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 {
|
try {
|
||||||
const [callsData, apptsData, leadsData, followUpsData, teamData] = await Promise.all([
|
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>(`{ 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>(`{ leads(first: 200) { edges { node { id assignedAgent status } } } }`, undefined, { silent: true }),
|
||||||
apiClient.graphql<any>(`{ followUps(first: 200) { edges { node { id assignedAgent } } } }`, 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[];
|
let agentPerfs: AgentPerf[];
|
||||||
|
|
||||||
if (teamAgents.length > 0) {
|
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) => {
|
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 agentLeads = leads.filter((l: any) => l.assignedAgent === agent.name);
|
||||||
const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === agent.name);
|
const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === agent.name);
|
||||||
const agentAppts = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
|
const agentAppts = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
|
||||||
@@ -148,10 +154,23 @@ export const TeamPerformancePage = () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Fallback: build agent list from call records
|
// Fallback: build agent list from call records. Prefer
|
||||||
const agentNames = [...new Set(calls.map((c: any) => c.agentName).filter(Boolean))] as string[];
|
// the authoritative agent relation; fall back to the raw
|
||||||
agentPerfs = agentNames.map((name) => {
|
// agentName string (Ozonetel transfer chain) only when
|
||||||
const agentCalls = calls.filter((c: any) => c.agentName === name);
|
// 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 agentLeads = leads.filter((l: any) => l.assignedAgent === name);
|
||||||
const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === name);
|
const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === name);
|
||||||
const completed = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
|
const completed = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
|
||||||
|
|||||||
Reference in New Issue
Block a user