Files
helix-engage-server/src/supervisor/supervisor.service.ts
2026-03-27 16:57:22 +05:30

99 lines
2.9 KiB
TypeScript

import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PlatformGraphqlService } from '../platform/platform-graphql.service';
import { OzonetelAgentService } from '../ozonetel/ozonetel-agent.service';
type ActiveCall = {
ucid: string;
agentId: string;
callerNumber: string;
callType: string;
startTime: string;
status: 'active' | 'on-hold';
};
@Injectable()
export class SupervisorService implements OnModuleInit {
private readonly logger = new Logger(SupervisorService.name);
private readonly activeCalls = new Map<string, ActiveCall>();
constructor(
private platform: PlatformGraphqlService,
private ozonetel: OzonetelAgentService,
private config: ConfigService,
) {}
async onModuleInit() {
this.logger.log('Supervisor service initialized');
}
handleCallEvent(event: any) {
const action = event.action;
const ucid = event.ucid ?? event.monitorUCID;
const agentId = event.agent_id ?? event.agentID;
const callerNumber = event.caller_id ?? event.callerID;
const callType = event.call_type ?? event.Type;
const eventTime =
event.event_time ?? event.eventTime ?? new Date().toISOString();
if (!ucid) return;
if (action === 'Answered' || action === 'Calling') {
this.activeCalls.set(ucid, {
ucid,
agentId,
callerNumber,
callType,
startTime: eventTime,
status: 'active',
});
this.logger.log(`Active call: ${agentId}${callerNumber} (${ucid})`);
} else if (action === 'Disconnect') {
this.activeCalls.delete(ucid);
this.logger.log(`Call ended: ${ucid}`);
}
}
handleAgentEvent(event: any) {
this.logger.log(
`Agent event: ${event.agentId ?? event.agent_id}${event.action}`,
);
}
getActiveCalls(): ActiveCall[] {
return Array.from(this.activeCalls.values());
}
async getTeamPerformance(date: string): Promise<any> {
// Get all agents from platform
const agentData = await this.platform.query<any>(
`{ agents(first: 20) { edges { node {
id name ozonetelagentid npsscore
maxidleminutes minnpsthreshold minconversionpercent
} } } }`,
);
const agents = agentData?.agents?.edges?.map((e: any) => e.node) ?? [];
// Fetch Ozonetel time summary per agent
const summaries = await Promise.all(
agents.map(async (agent: any) => {
if (!agent.ozonetelagentid) return { ...agent, timeBreakdown: null };
try {
const summary = await this.ozonetel.getAgentSummary(
agent.ozonetelagentid,
date,
);
return { ...agent, timeBreakdown: summary };
} catch (err) {
this.logger.warn(
`Failed to get summary for ${agent.ozonetelagentid}: ${err}`,
);
return { ...agent, timeBreakdown: null };
}
}),
);
return { date, agents: summaries };
}
}