mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-11 18:08:16 +00:00
feat: call control, recording, CDR, missed calls, live call assist
- Call Control API (CONFERENCE/HOLD/MUTE/KICK_CALL) - Recording pause/unpause - Fetch CDR Detailed (call history with recordings) - Abandon Calls (missed calls from Ozonetel) - Call Assist WebSocket gateway (Deepgram STT + OpenAI suggestions) - Call Assist service (lead context loading) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Controller, Post, Body, Logger, HttpException } from '@nestjs/common';
|
||||
import { Controller, Post, Get, Body, Query, Logger, HttpException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { OzonetelAgentService } from './ozonetel-agent.service';
|
||||
|
||||
@@ -136,6 +136,72 @@ export class OzonetelAgentController {
|
||||
}
|
||||
}
|
||||
|
||||
@Post('call-control')
|
||||
async callControl(
|
||||
@Body() body: {
|
||||
action: 'CONFERENCE' | 'HOLD' | 'UNHOLD' | 'MUTE' | 'UNMUTE' | 'KICK_CALL';
|
||||
ucid: string;
|
||||
conferenceNumber?: string;
|
||||
},
|
||||
) {
|
||||
if (!body.action || !body.ucid) {
|
||||
throw new HttpException('action and ucid required', 400);
|
||||
}
|
||||
if (body.action === 'CONFERENCE' && !body.conferenceNumber) {
|
||||
throw new HttpException('conferenceNumber required for CONFERENCE action', 400);
|
||||
}
|
||||
|
||||
this.logger.log(`Call control: ${body.action} ucid=${body.ucid}`);
|
||||
|
||||
try {
|
||||
const result = await this.ozonetelAgent.callControl(body);
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
const message = error.response?.data?.message ?? error.message ?? 'Call control failed';
|
||||
throw new HttpException(message, error.response?.status ?? 502);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('recording')
|
||||
async recording(
|
||||
@Body() body: { ucid: string; action: 'pause' | 'unPause' },
|
||||
) {
|
||||
if (!body.ucid || !body.action) {
|
||||
throw new HttpException('ucid and action required', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.ozonetelAgent.pauseRecording(body);
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
const message = error.response?.data?.message ?? error.message ?? 'Recording control failed';
|
||||
throw new HttpException(message, error.response?.status ?? 502);
|
||||
}
|
||||
}
|
||||
|
||||
@Get('missed-calls')
|
||||
async missedCalls() {
|
||||
const result = await this.ozonetelAgent.getAbandonCalls();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Get('call-history')
|
||||
async callHistory(
|
||||
@Query('date') date?: string,
|
||||
@Query('status') status?: string,
|
||||
@Query('callType') callType?: string,
|
||||
) {
|
||||
const targetDate = date ?? new Date().toISOString().split('T')[0];
|
||||
this.logger.log(`Call history: date=${targetDate} status=${status ?? 'all'} type=${callType ?? 'all'}`);
|
||||
|
||||
const result = await this.ozonetelAgent.fetchCDR({
|
||||
date: targetDate,
|
||||
status,
|
||||
callType,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private mapToOzonetelDisposition(disposition: string): string {
|
||||
// Campaign only has 'General Enquiry' configured currently
|
||||
const map: Record<string, string> = {
|
||||
|
||||
Reference in New Issue
Block a user