mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-05-18 20:08:19 +00:00
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) <noreply@anthropic.com>
This commit is contained in:
@@ -90,7 +90,7 @@ export const TeamPerformancePage = () => {
|
||||
|
||||
try {
|
||||
const [callsData, apptsData, leadsData, followUpsData, teamData] = await Promise.all([
|
||||
apiClient.graphql<any>(`{ calls(first: 500, filter: { startedAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id direction callStatus agentName startedAt } } } }`, undefined, { silent: true }),
|
||||
apiClient.graphql<any>(`{ 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<any>(`{ appointments(first: 200, filter: { scheduledAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id status } } } }`, undefined, { silent: true }),
|
||||
apiClient.graphql<any>(`{ leads(first: 200) { edges { node { id assignedAgent status } } } }`, undefined, { silent: true }),
|
||||
apiClient.graphql<any>(`{ 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<string, { key: string; name: string; ozonetelAgentId: string }>();
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user