feat: add Ozonetel Set Disposition API for proper ACW release

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 18:35:59 +05:30
parent 72e6373acf
commit 8c6cd2c156
2 changed files with 170 additions and 47 deletions

View File

@@ -53,24 +53,76 @@ export class OzonetelAgentController {
}
}
@Post('dispose')
async dispose(
@Body() body: {
ucid: string;
disposition: string;
callerPhone?: string;
direction?: string;
durationSec?: number;
leadId?: string;
notes?: string;
},
) {
if (!body.ucid || !body.disposition) {
throw new HttpException('ucid and disposition required', 400);
}
this.logger.log(`Dispose: ucid=${body.ucid} disposition=${body.disposition}`);
const ozonetelDisposition = this.mapToOzonetelDisposition(body.disposition);
try {
const result = await this.ozonetelAgent.setDisposition({
agentId: this.defaultAgentId,
ucid: body.ucid,
disposition: ozonetelDisposition,
});
return result;
} catch (error: any) {
const message = error.response?.data?.message ?? error.message ?? 'Disposition failed';
this.logger.error(`Dispose failed: ${message}`);
// Don't throw — disposition failure shouldn't block the UI
return { status: 'error', message };
}
}
@Post('dial')
async dial(
@Body() body: { phoneNumber: string; leadId?: string },
@Body() body: { phoneNumber: string; campaignName?: string; leadId?: string },
) {
if (!body.phoneNumber) {
throw new HttpException('phoneNumber required', 400);
}
this.logger.log(`Dial request: ${body.phoneNumber} (lead: ${body.leadId ?? 'none'})`);
const campaignName = body.campaignName ?? process.env.OZONETEL_CAMPAIGN_NAME ?? 'Inbound_918041763265';
this.logger.log(`Manual dial: ${body.phoneNumber} campaign=${campaignName} (lead: ${body.leadId ?? 'none'})`);
try {
const result = await this.ozonetelAgent.dialCustomer({
const result = await this.ozonetelAgent.manualDial({
agentId: this.defaultAgentId,
campaignName,
customerNumber: body.phoneNumber,
});
return result;
} catch (error: any) {
const message = error.response?.data?.message ?? error.message ?? 'Dial failed';
throw new HttpException(message, 502);
throw new HttpException(message, error.response?.status ?? 502);
}
}
private mapToOzonetelDisposition(disposition: string): string {
// Campaign only has 'General Enquiry' configured currently
const map: Record<string, string> = {
'APPOINTMENT_BOOKED': 'General Enquiry',
'FOLLOW_UP_SCHEDULED': 'General Enquiry',
'INFO_PROVIDED': 'General Enquiry',
'NO_ANSWER': 'General Enquiry',
'WRONG_NUMBER': 'General Enquiry',
'CALLBACK_REQUESTED': 'General Enquiry',
};
return map[disposition] ?? 'General Enquiry';
}
}