From d00b0668064b57714a138ccb6c033ea60140860c Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Wed, 15 Apr 2026 07:43:49 +0530 Subject: [PATCH] feat(team-performance): group calls by authoritative agent relation Prefer call.agent.id (set by CDR enrichment) over call.agentName string matching. Falls back to the raw agentName only when the row hasn't been enriched yet. Eliminates the "RamaiahAdmin -> GlobalHealthX" transfer-chain rows and the display-name collisions (two distinct AgentIDs with the same Full Name). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/pages/team-performance.tsx | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/pages/team-performance.tsx b/src/pages/team-performance.tsx index c27b57d..f7ac380 100644 --- a/src/pages/team-performance.tsx +++ b/src/pages/team-performance.tsx @@ -90,7 +90,7 @@ export const TeamPerformancePage = () => { try { const [callsData, apptsData, leadsData, followUpsData, teamData] = await Promise.all([ - apiClient.graphql(`{ calls(first: 500, filter: { startedAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id direction callStatus agentName startedAt } } } }`, undefined, { silent: true }), + apiClient.graphql(`{ calls(first: 500, filter: { startedAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id direction callStatus agentName startedAt agentId agent { id name ozonetelAgentId } } } } }`, undefined, { silent: true }), apiClient.graphql(`{ appointments(first: 200, filter: { scheduledAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id status } } } }`, undefined, { silent: true }), apiClient.graphql(`{ leads(first: 200) { edges { node { id assignedAgent status } } } }`, undefined, { silent: true }), apiClient.graphql(`{ followUps(first: 200) { edges { node { id assignedAgent } } } }`, undefined, { silent: true }), @@ -110,9 +110,15 @@ export const TeamPerformancePage = () => { let agentPerfs: AgentPerf[]; if (teamAgents.length > 0) { - // Real Ozonetel data available + // Real Ozonetel data available — prefer authoritative agent + // relation (set by CDR enrichment), fall back to agentName + // string for rows not yet enriched. agentPerfs = teamAgents.map((agent: any) => { - const agentCalls = calls.filter((c: any) => c.agentName === agent.name || c.agentName === agent.ozonetelAgentId); + const agentCalls = calls.filter((c: any) => { + if (c.agentId && c.agentId === agent.id) return true; + if (!c.agentId && (c.agentName === agent.name || c.agentName === agent.ozonetelAgentId)) return true; + return false; + }); const agentLeads = leads.filter((l: any) => l.assignedAgent === agent.name); const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === agent.name); const agentAppts = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length; @@ -148,10 +154,23 @@ export const TeamPerformancePage = () => { }; }); } else { - // Fallback: build agent list from call records - const agentNames = [...new Set(calls.map((c: any) => c.agentName).filter(Boolean))] as string[]; - agentPerfs = agentNames.map((name) => { - const agentCalls = calls.filter((c: any) => c.agentName === name); + // Fallback: build agent list from call records. Prefer + // the authoritative agent relation; fall back to the raw + // agentName string (Ozonetel transfer chain) only when + // we have nothing better. + const byKey = new Map(); + for (const c of calls) { + if (c.agent?.id) { + byKey.set(c.agent.id, { key: c.agent.id, name: c.agent.name ?? c.agent.ozonetelAgentId, ozonetelAgentId: c.agent.ozonetelAgentId }); + } else if (c.agentName) { + byKey.set(`legacy:${c.agentName}`, { key: `legacy:${c.agentName}`, name: c.agentName, ozonetelAgentId: c.agentName }); + } + } + agentPerfs = Array.from(byKey.values()).map(({ key, name, ozonetelAgentId: _ozonetelAgentId }) => { + const agentCalls = calls.filter((c: any) => { + if (key.startsWith('legacy:')) return c.agentName === name && !c.agent?.id; + return c.agent?.id === key; + }); const agentLeads = leads.filter((l: any) => l.assignedAgent === name); const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === name); const completed = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;