top of page

import { fetch } from 'wix-fetch'; import { webMethod, Permissions } from 'wix-web-module'; import { currentMember } from 'wix-members-backend'; import { getSecret } from 'wix-secrets-backend'; const MONDAY_URL = 'https://api.monday.com/v2'; const MONDAY_API_VERSION = '2026-07'; const AGENTS_BOARD_ID = 359616654; const ASSIGNMENTS_BOARD_ID = 9713635727; const TRANSACTIONS_BOARD_ID = '3417790829'; const CLOSED_GROUP_ID = 'new_group_mkkcffk9'; const AGENT_WORK_EMAIL = 'work_email'; const AGENT_HOME_EMAIL = 'home_email'; const ASSIGNMENT_AGENT = 'board_relation_mktcafs'; const ASSIGNMENT_TRANSACTION = 'board_relation_mktc7bc9'; const ASSIGNMENT_SHARES = 'numeric_mktcber3'; const TRANSACTION_STATUS = 'status_124'; const TRANSACTION_TYPE = 'status_155'; const TRANSACTION_CLOSED_DATE = 'date49'; const TRANSACTION_STATUS_DATE = 'date__1'; const TRANSACTION_SALE_PRICE = 'numeric_mktcp458'; const TRANSACTION_FEE = 'numeric_mktk5jbj'; const TRANSACTION_COMMISSION = 'numeric_mkttmjzq'; const TRANSACTION_ASSIGNMENTS = 'board_relation_mktcjqrd'; const TRANSACTION_API_EMAIL = 'text_mm17c7s1'; // Explicitly approved Wix login aliases. Keep this fail-closed: an alias may // resolve only to one canonical Kale roster email. const LOGIN_EMAIL_ALIASES = Object.freeze({ 'kalezoomgpt@gmail.com': 'nick@kalerealty.com' }); function normalizeEmail(value) { return String(value || '').trim().toLowerCase(); } function canonicalAgentEmail(value) { const email = normalizeEmail(value); return LOGIN_EMAIL_ALIASES[email] || email; } function asNumber(value) { const number = Number(value); return Number.isFinite(number) ? number : 0; } function asMoney(value) { return Math.round((asNumber(value) + Number.EPSILON) * 100) / 100; } function column(item, id) { return (item.column_values || []).find((value) => value.id === id); } function columnText(item, id) { return column(item, id)?.text || ''; } async function mondayQuery(apiKey, query) { const response = await fetch(MONDAY_URL, { method: 'POST', headers: { Authorization: apiKey, 'Content-Type': 'application/json', 'API-Version': MONDAY_API_VERSION }, body: JSON.stringify({ query }) }); if (!response.ok) { throw new Error('Unable to load deal data.'); } const payload = await response.json(); if (payload.errors?.length) { console.error('Monday Deals query failed', payload.errors); throw new Error('Unable to load deal data.'); } return payload.data; } async function findAgentId(apiKey, email) { const safeEmail = JSON.stringify(email); const data = await mondayQuery(apiKey, `query { boards(ids: [${AGENTS_BOARD_ID}]) { items_page( limit: 50 query_params: { operator: or rules: [ { column_id: "${AGENT_WORK_EMAIL}", compare_value: [${safeEmail}], operator: contains_text } { column_id: "${AGENT_HOME_EMAIL}", compare_value: [${safeEmail}], operator: contains_text } ] } ) { items { id column_values(ids: ["${AGENT_WORK_EMAIL}", "${AGENT_HOME_EMAIL}"]) { id text } } } } }`); const matches = (data.boards?.[0]?.items_page?.items || []).filter((item) => { const workEmail = normalizeEmail(columnText(item, AGENT_WORK_EMAIL)); const homeEmail = normalizeEmail(columnText(item, AGENT_HOME_EMAIL)); return workEmail === email || homeEmail === email; }); if (matches.length !== 1) { console.warn('Monday Deals agent identity was missing or ambiguous.'); return null; } return matches[0].id; } function assignmentSelection() { return `cursor items { id column_values(ids: ["${ASSIGNMENT_TRANSACTION}", "${ASSIGNMENT_SHARES}"]) { id text ... on BoardRelationValue { linked_item_ids } } }`; } async function loadAssignments(apiKey, agentId) { const assignments = []; let data = await mondayQuery(apiKey, `query { boards(ids: [${ASSIGNMENTS_BOARD_ID}]) { items_page( limit: 500 query_params: { rules: [ { column_id: "${ASSIGNMENT_AGENT}", compare_value: [${Number(agentId)}], operator: any_of } ] } ) { ${assignmentSelection()} } } }`); let page = data.boards?.[0]?.items_page; while (page) { assignments.push(...(page.items || [])); if (!page.cursor) break; const cursor = JSON.stringify(page.cursor); data = await mondayQuery(apiKey, `query { next_items_page(limit: 500, cursor: ${cursor}) { ${assignmentSelection()} } }`); page = data.next_items_page; } const sharesByTransaction = new Map(); for (const assignment of assignments) { const transactionIds = column(assignment, ASSIGNMENT_TRANSACTION)?.linked_item_ids || []; const shares = asNumber(columnText(assignment, ASSIGNMENT_SHARES)); if (shares <= 0) continue; for (const transactionId of transactionIds) { sharesByTransaction.set( String(transactionId), (sharesByTransaction.get(String(transactionId)) || 0) + shares ); } } return sharesByTransaction; } function transactionSelection() { return `id name board { id } group { id } column_values(ids: [ "${TRANSACTION_STATUS}", "${TRANSACTION_TYPE}", "${TRANSACTION_CLOSED_DATE}", "${TRANSACTION_STATUS_DATE}", "${TRANSACTION_SALE_PRICE}", "${TRANSACTION_FEE}", "${TRANSACTION_COMMISSION}", "${TRANSACTION_ASSIGNMENTS}", "${TRANSACTION_API_EMAIL}" ]) { id text ... on BoardRelationValue { linked_items { id column_values(ids: ["${ASSIGNMENT_SHARES}"]) { id text } } } }`; } async function loadTransactions(apiKey, transactionIds) { const transactions = []; for (let index = 0; index < transactionIds.length; index += 100) { const ids = transactionIds.slice(index, index + 100).map(Number).filter(Number.isFinite); if (!ids.length) continue; const data = await mondayQuery(apiKey, `query { items(ids: [${ids.join(',')}]) { ${transactionSelection()} } }`); transactions.push(...(data.items || [])); } return transactions; } async function loadLegacyTransactions(apiKey, email) { const transactions = []; const safeEmail = JSON.stringify(email); let data = await mondayQuery(apiKey, `query { boards(ids: [${TRANSACTIONS_BOARD_ID}]) { items_page( limit: 500 query_params: { rules: [ { column_id: "${TRANSACTION_API_EMAIL}", compare_value: [${safeEmail}], operator: contains_text } ] } ) { cursor items { ${transactionSelection()} } } } }`); let page = data.boards?.[0]?.items_page; while (page) { transactions.push(...(page.items || [])); if (!page.cursor) break; const cursor = JSON.stringify(page.cursor); data = await mondayQuery(apiKey, `query { next_items_page(limit: 500, cursor: ${cursor}) { cursor items { ${transactionSelection()} } } }`); page = data.next_items_page; } return transactions.filter((item) => { return normalizeEmail(columnText(item, TRANSACTION_API_EMAIL)) === email; }); } function totalTransactionShares(item) { const relation = column(item, TRANSACTION_ASSIGNMENTS); return (relation?.linked_items || []).reduce((total, assignment) => { return total + asNumber(columnText(assignment, ASSIGNMENT_SHARES)); }, 0); } export const getClosedDealsByAgent = webMethod( Permissions.SiteMember, async () => { const member = await currentMember.getMember(); const email = canonicalAgentEmail(member?.loginEmail); if (!email) return []; const apiKey = await getSecret('MONDAY_API_KEY'); const agentId = await findAgentId(apiKey, email); const sharesByTransaction = agentId ? await loadAssignments(apiKey, agentId) : new Map(); const assignedTransactions = await loadTransactions(apiKey, [...sharesByTransaction.keys()]); const legacyTransactions = await loadLegacyTransactions(apiKey, email); const transactionsById = new Map(); for (const item of legacyTransactions) transactionsById.set(String(item.id), item); for (const item of assignedTransactions) transactionsById.set(String(item.id), item); const transactions = [...transactionsById.values()]; return transactions .filter((item) => { return String(item.board?.id) === TRANSACTIONS_BOARD_ID && item.group?.id === CLOSED_GROUP_ID; }) .map((item) => { const agentShares = sharesByTransaction.get(String(item.id)) || 0; const totalShares = totalTransactionShares(item); const isLegacyMatch = normalizeEmail(columnText(item, TRANSACTION_API_EMAIL)) === email; if ((agentShares <= 0 || totalShares <= 0) && !isLegacyMatch) return null; const shareRatio = agentShares > 0 && totalShares > 0 ? agentShares / totalShares : 1; const commission = asMoney(asNumber(columnText(item, TRANSACTION_COMMISSION)) * shareRatio); const transFee = asMoney(asNumber(columnText(item, TRANSACTION_FEE)) * shareRatio); return { id: item.id, propertyAddress: item.name, address: item.name, listOrBuy: columnText(item, TRANSACTION_TYPE), closedDate: columnText(item, TRANSACTION_CLOSED_DATE) || columnText(item, TRANSACTION_STATUS_DATE), salePrice: columnText(item, TRANSACTION_SALE_PRICE), transFee: transFee.toFixed(2), commission: commission.toFixed(2) }; }) .filter(Boolean) .sort((a, b) => String(b.closedDate).localeCompare(String(a.closedDate))); } );

© 2024 Kale Realty | Website Designed and Developed by YCS Web Agency

bottom of page