mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-12 02:18:18 +00:00
feat: SSE agent state, maint module, timestamp fix, missed call lead lookup
- SSE agent state stream: supervisor maintains state map from Ozonetel webhooks, streams via /api/supervisor/agent-state/stream - Force-logout via SSE: distinct force-logout event type avoids conflict with normal login cycle - Maint module (/api/maint): OTP-guarded endpoints for force-ready, unlock-agent, backfill-missed-calls, fix-timestamps - Fix Ozonetel IST→UTC timestamp conversion: istToUtc() in webhook controller and missed-queue service - Missed call lead lookup: ingestion queries leads by phone, stores leadId + leadName on Call entity - Timestamp backfill endpoint: throttled at 700ms/mutation, idempotent (skips already-fixed records) - Structured logging: full JSON payloads for agent/call webhooks, [DISPOSE] trace with agentId - Fix dead code: agent-state endpoint auto-assign was after return statement - Export SupervisorService for cross-module injection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,16 @@ import { Controller, Post, Body, Headers, Logger } from '@nestjs/common';
|
||||
import { PlatformGraphqlService } from '../platform/platform-graphql.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
// Ozonetel sends all timestamps in IST — convert to UTC for storage
|
||||
function istToUtc(istDateStr: string | null): string | null {
|
||||
if (!istDateStr) return null;
|
||||
// Parse as-is, then subtract 5:30 to get UTC
|
||||
const d = new Date(istDateStr);
|
||||
if (isNaN(d.getTime())) return null;
|
||||
d.setMinutes(d.getMinutes() - 330); // IST is UTC+5:30
|
||||
return d.toISOString();
|
||||
}
|
||||
|
||||
@Controller('webhooks/ozonetel')
|
||||
export class MissedCallWebhookController {
|
||||
private readonly logger = new Logger(MissedCallWebhookController.name);
|
||||
@@ -130,8 +140,8 @@ export class MissedCallWebhookController {
|
||||
callStatus: data.callStatus,
|
||||
callerNumber: { primaryPhoneNumber: `+91${data.callerPhone}` },
|
||||
agentName: data.agentName,
|
||||
startedAt: data.startTime ? new Date(data.startTime).toISOString() : null,
|
||||
endedAt: data.endTime ? new Date(data.endTime).toISOString() : null,
|
||||
startedAt: istToUtc(data.startTime),
|
||||
endedAt: istToUtc(data.endTime),
|
||||
durationSec: data.duration,
|
||||
disposition: this.mapDisposition(data.disposition),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user