mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-05-18 20:08:19 +00:00
fix: await Ozonetel logout + per-agent sipPassword + campaign name on missed calls
Three changes: 1. Await Ozonetel logout in /auth/logout — prevents race condition when agent re-logs in quickly via "Remember me". The fire-and-forget logoutAgent() left a window where the next loginAgent() arrived while Ozonetel was still processing the previous logout, leaving the agent stuck in "Telephony Unavailable". (#559) 2. Use agentConfig.sipPassword (from Agent entity) instead of OZONETEL_AGENT_PASSWORD env var for login/logout/force-ready. The env var was a single shared credential that ignored per-agent passwords. Removed hardcoded "Test123$" fallback. Force-ready now looks up the Agent entity by ozonetelAgentId to get the correct sipPassword + sipExtension. 3. Missed-calls worklist query now fetches campaign { id campaignName } so the frontend Branch column can show the campaign name instead of the raw DID phone number. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,10 +138,9 @@ export class AuthController {
|
||||
this.logger.warn(`Ozonetel token refresh on login failed: ${err.message}`);
|
||||
});
|
||||
|
||||
const ozAgentPassword = this.telephony.getConfig().ozonetel.agentPassword || 'Test123$';
|
||||
this.ozonetelAgent.loginAgent({
|
||||
agentId: agentConfig.ozonetelAgentId,
|
||||
password: ozAgentPassword,
|
||||
password: agentConfig.sipPassword,
|
||||
phoneNumber: agentConfig.sipExtension,
|
||||
mode: 'blended',
|
||||
}).catch(err => {
|
||||
@@ -250,9 +249,14 @@ export class AuthController {
|
||||
await this.sessionService.unlockSession(agentConfig.ozonetelAgentId);
|
||||
this.logger.log(`Session unlocked for ${agentConfig.ozonetelAgentId}`);
|
||||
|
||||
this.ozonetelAgent.logoutAgent({
|
||||
// Await the Ozonetel logout so it completes before the
|
||||
// HTTP response returns. Without this, a fast re-login
|
||||
// (e.g. "remember me" auto-fill) races the logout and
|
||||
// the agent lands in "Telephony Unavailable" because
|
||||
// Ozonetel receives login while still processing logout.
|
||||
await this.ozonetelAgent.logoutAgent({
|
||||
agentId: agentConfig.ozonetelAgentId,
|
||||
password: this.telephony.getConfig().ozonetel.agentPassword || 'Test123$',
|
||||
password: agentConfig.sipPassword,
|
||||
}).catch(err => this.logger.warn(`Ozonetel logout failed: ${err.message}`));
|
||||
|
||||
this.agentConfigService.clearCache(memberId);
|
||||
|
||||
@@ -31,13 +31,26 @@ export class MaintController {
|
||||
async forceReady(@Body() body: { agentId: string }) {
|
||||
if (!body?.agentId) throw new HttpException('agentId required', 400);
|
||||
const agentId = body.agentId;
|
||||
const oz = this.telephony.getConfig().ozonetel;
|
||||
const password = oz.agentPassword;
|
||||
if (!password) throw new HttpException('agent password not configured', 400);
|
||||
const sipId = oz.sipId;
|
||||
if (!sipId) throw new HttpException('SIP ID not configured', 400);
|
||||
|
||||
this.logger.log(`[MAINT] Force ready: agent=${agentId}`);
|
||||
// Look up the Agent entity to get sipPassword + sipExtension.
|
||||
// Password comes from the Agent record, not an env var — each
|
||||
// agent owns their own Ozonetel credential.
|
||||
const agentData = await this.platform.query<any>(
|
||||
`{ agents(first: 1, filter: { ozonetelAgentId: { eq: "${agentId}" } }) { edges { node {
|
||||
id sipExtension sipPassword
|
||||
} } } }`,
|
||||
).catch(() => null);
|
||||
|
||||
const agent = agentData?.agents?.edges?.[0]?.node;
|
||||
if (!agent) throw new HttpException(`Agent ${agentId} not found in platform`, 404);
|
||||
|
||||
const password = agent.sipPassword ?? agent.sipExtension;
|
||||
if (!password) throw new HttpException(`Agent ${agentId} has no sipPassword configured`, 400);
|
||||
|
||||
const sipId = agent.sipExtension;
|
||||
if (!sipId) throw new HttpException(`Agent ${agentId} has no sipExtension configured`, 400);
|
||||
|
||||
this.logger.log(`[MAINT] Force ready: agent=${agentId} ext=${sipId}`);
|
||||
|
||||
try {
|
||||
await this.ozonetel.logoutAgent({ agentId, password });
|
||||
|
||||
@@ -177,6 +177,7 @@ export class WorklistService {
|
||||
startedAt endedAt durationSec
|
||||
disposition leadId leadName
|
||||
callbackStatus callSourceNumber missedCallCount callbackAttemptedAt
|
||||
campaign { id campaignName }
|
||||
} } pageInfo { hasNextPage endCursor } } }`,
|
||||
'calls',
|
||||
authHeader,
|
||||
|
||||
Reference in New Issue
Block a user