mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-11 18:08:16 +00:00
fix: skip outbound calls in webhook + filter abandon polls by campaign
Webhook controller now skips outbound calls (type=Manual/OutBound). An unanswered outbound dial is NOT a missed inbound call — it was being incorrectly created as MISSED with PENDING_CALLBACK status. MissedQueueService now filters the Ozonetel abandonCalls API response by campaign name (read from TelephonyConfigService). Prevents cross-tenant ingestion when multiple sidecars share the same Ozonetel account. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ 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';
|
||||
import { TelephonyConfigService } from '../config/telephony-config.service';
|
||||
|
||||
// Ozonetel sends all timestamps in IST — convert to UTC for storage
|
||||
export function istToUtc(istDateStr: string | null): string | null {
|
||||
@@ -33,10 +34,16 @@ export class MissedQueueService implements OnModuleInit {
|
||||
private readonly config: ConfigService,
|
||||
private readonly platform: PlatformGraphqlService,
|
||||
private readonly ozonetel: OzonetelAgentService,
|
||||
private readonly telephony: TelephonyConfigService,
|
||||
) {
|
||||
this.pollIntervalMs = this.config.get<number>('missedQueue.pollIntervalMs', 30000);
|
||||
}
|
||||
|
||||
// Read-through so admin config changes take effect without restart
|
||||
private get ownCampaign(): string {
|
||||
return this.telephony.getConfig().ozonetel.campaignName ?? '';
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.logger.log(`Starting missed call ingestion polling every ${this.pollIntervalMs}ms`);
|
||||
setInterval(() => this.ingest().catch(err => this.logger.error('Ingestion failed', err)), this.pollIntervalMs);
|
||||
@@ -61,7 +68,17 @@ export class MissedQueueService implements OnModuleInit {
|
||||
|
||||
if (!abandonCalls?.length) return { created: 0, updated: 0 };
|
||||
|
||||
for (const call of abandonCalls) {
|
||||
// Filter to this sidecar's campaign only — the Ozonetel API
|
||||
// returns ALL abandoned calls across the account.
|
||||
const filtered = this.ownCampaign
|
||||
? abandonCalls.filter((c: any) => c.campaign === this.ownCampaign)
|
||||
: abandonCalls;
|
||||
|
||||
if (filtered.length < abandonCalls.length) {
|
||||
this.logger.log(`Filtered ${abandonCalls.length - filtered.length} calls from other campaigns (own=${this.ownCampaign})`);
|
||||
}
|
||||
|
||||
for (const call of filtered) {
|
||||
const ucid = call.monitorUCID;
|
||||
if (!ucid || this.processedUcids.has(ucid)) continue;
|
||||
this.processedUcids.add(ucid);
|
||||
|
||||
Reference in New Issue
Block a user