FEAT: Roteamento para atendentes melhorado
All checks were successful
Deploy Dev / deploy (push) Successful in 3s
All checks were successful
Deploy Dev / deploy (push) Successful in 3s
This commit is contained in:
parent
d495698c02
commit
2fd19e9bae
@ -31,7 +31,7 @@ export class KnowledgeBaseService implements OnModuleInit {
|
||||
ALTER TABLE bot_triage_intents
|
||||
ADD COLUMN IF NOT EXISTS response_message TEXT,
|
||||
ADD COLUMN IF NOT EXISTS resolution_question TEXT,
|
||||
ADD COLUMN IF NOT EXISTS escalation_message TEXT NOT NULL DEFAULT 'Certo, vou encaminhar seu atendimento para um especialista no assunto.';
|
||||
ADD COLUMN IF NOT EXISTS escalation_message TEXT NOT NULL DEFAULT 'Certo, vou encaminhar seu atendimento para o time responsável.';
|
||||
`).catch(() => undefined);
|
||||
|
||||
await this.database.query(`
|
||||
@ -529,7 +529,7 @@ export class KnowledgeBaseService implements OnModuleInit {
|
||||
audience_id, label, area_id, keywords, response_message, resolution_question,
|
||||
escalation_message, sort_order, active, updated_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 'Certo, vou encaminhar seu atendimento para um especialista no assunto.'), $8, TRUE, CURRENT_TIMESTAMP)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 'Certo, vou encaminhar seu atendimento para o time responsável.'), $8, TRUE, CURRENT_TIMESTAMP)
|
||||
RETURNING *
|
||||
`,
|
||||
[
|
||||
|
||||
@ -421,7 +421,7 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
return builderFlowResult;
|
||||
}
|
||||
|
||||
const configuredFlowResult = await this.routeConfiguredFlow(chatId, cleanMessage, current, messageId);
|
||||
const configuredFlowResult = await this.routeConfiguredFlow(chatId, cleanMessage, current, messageId, variables);
|
||||
if (configuredFlowResult) {
|
||||
return configuredFlowResult;
|
||||
}
|
||||
@ -429,7 +429,14 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
const detectedArea = await this.detectKnownArea(cleanMessage);
|
||||
|
||||
if (detectedArea) {
|
||||
const assignment = await this.queueChat(chatId, detectedArea.id, `Roteado automaticamente pelo ${VIRTUAL_AGENT_NAME}`);
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
detectedArea.id,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
intentLabel: detectedArea.name,
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
const hasPreviousTriage = current?.status === 'bot_triage';
|
||||
const botMessage = hasPreviousTriage
|
||||
@ -453,7 +460,14 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
|
||||
if (attempts >= 2) {
|
||||
const supportArea = await this.getAreaByName('Suporte');
|
||||
const assignment = await this.queueChat(chatId, supportArea.id, 'Roteado para suporte por falta de classificacao');
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
supportArea.id,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
fallbackReason: 'não teve a solicitação classificada pelo Agente Virtual',
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
|
||||
return {
|
||||
@ -590,7 +604,11 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
areaId,
|
||||
`Roteado pelo fluxo do ${VIRTUAL_AGENT_NAME}: ${matchedChild.title}`,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
audienceLabel: currentNode.title,
|
||||
intentLabel: matchedChild.title,
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
|
||||
@ -601,7 +619,7 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
'Atendente virtual',
|
||||
VIRTUAL_AGENT_NAME,
|
||||
this.applyBotVariables(
|
||||
matchedChild.message_text || `Certo, vou encaminhar seu atendimento para ${matchedChild.area_nome || 'a especialidade correta'}.`,
|
||||
matchedChild.message_text || 'Certo, vou encaminhar seu atendimento para o time responsável.',
|
||||
variables,
|
||||
),
|
||||
),
|
||||
@ -628,7 +646,11 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
fallbackAreaId,
|
||||
`Fallback do fluxo do ${VIRTUAL_AGENT_NAME}: ${currentNode.title}`,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
audienceLabel: currentNode.title,
|
||||
fallbackReason: 'não teve a solicitação classificada pelo Agente Virtual',
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
|
||||
@ -659,7 +681,13 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
};
|
||||
}
|
||||
|
||||
private async routeConfiguredFlow(chatId: string, message: string, current: any, messageId?: string) {
|
||||
private async routeConfiguredFlow(
|
||||
chatId: string,
|
||||
message: string,
|
||||
current: any,
|
||||
messageId?: string,
|
||||
variables: BotMessageVariables = {},
|
||||
) {
|
||||
const flow = await this.getActiveTriageFlow();
|
||||
if (!flow || !flow.audiences.length) return null;
|
||||
|
||||
@ -694,7 +722,7 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
}
|
||||
|
||||
if (current.triage_step === 'resolution' && current.triage_intent_id) {
|
||||
return this.routeConfiguredResolution(chatId, message, flow, current, messageId);
|
||||
return this.routeConfiguredResolution(chatId, message, flow, current, messageId, variables);
|
||||
}
|
||||
|
||||
return this.routeConfiguredAudience(chatId, message, flow, current, messageId);
|
||||
@ -778,14 +806,29 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
};
|
||||
}
|
||||
|
||||
private async routeConfiguredResolution(chatId: string, message: string, flow: TriageFlow, current: any, messageId?: string) {
|
||||
const intent = flow.audiences
|
||||
.flatMap((audience) => audience.intents)
|
||||
.find((item) => Number(item.id) === Number(current.triage_intent_id));
|
||||
private async routeConfiguredResolution(
|
||||
chatId: string,
|
||||
message: string,
|
||||
flow: TriageFlow,
|
||||
current: any,
|
||||
messageId?: string,
|
||||
variables: BotMessageVariables = {},
|
||||
) {
|
||||
const audience = flow.audiences.find((item) =>
|
||||
item.intents.some((intentItem) => Number(intentItem.id) === Number(current.triage_intent_id)),
|
||||
);
|
||||
const intent = audience?.intents.find((item) => Number(item.id) === Number(current.triage_intent_id));
|
||||
|
||||
if (!intent) {
|
||||
const fallbackAreaId = flow.fallback_area_id || (await this.getAreaByName('Suporte')).id;
|
||||
const assignment = await this.queueChat(chatId, fallbackAreaId, `Fallback configurado pelo ${VIRTUAL_AGENT_NAME}`);
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
fallbackAreaId,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
fallbackReason: 'não teve a solicitação classificada pelo Agente Virtual',
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
return {
|
||||
assignment,
|
||||
@ -846,7 +889,11 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
const assignment = await this.queueChat(
|
||||
chatId,
|
||||
intent.area_id,
|
||||
`Cliente solicitou especialista apos orientacao do ${VIRTUAL_AGENT_NAME}: ${intent.label}`,
|
||||
this.buildVirtualAgentTransferNote({
|
||||
name: variables.nome,
|
||||
audienceLabel: audience?.label,
|
||||
intentLabel: intent.label,
|
||||
}),
|
||||
);
|
||||
await this.markBotRoute(chatId, messageId);
|
||||
|
||||
@ -856,7 +903,7 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
botMessage: this.formatSenderMessage(
|
||||
'Atendente virtual',
|
||||
VIRTUAL_AGENT_NAME,
|
||||
intent.escalation_message || `Certo, vou encaminhar seu atendimento para ${intent.area_nome}.`,
|
||||
intent.escalation_message || 'Certo, vou encaminhar seu atendimento para o time responsável.',
|
||||
),
|
||||
};
|
||||
}
|
||||
@ -1249,6 +1296,58 @@ export class WhatsappAssignmentService implements OnModuleInit {
|
||||
return ['ferias'].includes(normalized) ? 'as' : 'o';
|
||||
}
|
||||
|
||||
private buildVirtualAgentTransferNote(input: {
|
||||
name?: string | null;
|
||||
audienceLabel?: string | null;
|
||||
intentLabel?: string | null;
|
||||
fallbackReason?: string;
|
||||
}) {
|
||||
const subject = this.getFirstName(input.name) || 'Cliente';
|
||||
const audienceDescription = this.getAudienceDescription(input.audienceLabel);
|
||||
const topic = this.getTopicLabel(input.intentLabel);
|
||||
|
||||
if (audienceDescription && topic) {
|
||||
return `${subject} ${audienceDescription} e quer saber sobre ${topic}`;
|
||||
}
|
||||
|
||||
if (topic) {
|
||||
return `${subject} quer saber sobre ${topic}`;
|
||||
}
|
||||
|
||||
if (audienceDescription && input.fallbackReason) {
|
||||
return `${subject} ${audienceDescription} e ${input.fallbackReason}`;
|
||||
}
|
||||
|
||||
if (input.fallbackReason) {
|
||||
return `${subject} ${input.fallbackReason}`;
|
||||
}
|
||||
|
||||
return `Roteado pelo ${VIRTUAL_AGENT_NAME}`;
|
||||
}
|
||||
|
||||
private getAudienceDescription(value?: string | null) {
|
||||
const normalized = this.normalize(value || '');
|
||||
|
||||
if (!normalized) return '';
|
||||
if (normalized.includes('ex-colaborador') || normalized.includes('ex colaborador')) return 'é um ex-colaborador';
|
||||
if (normalized.includes('candidato') || normalized.includes('vaga')) return 'é um candidato';
|
||||
if (normalized.includes('colaborador') || normalized.includes('funcionario')) return 'é um colaborador';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private getTopicLabel(value?: string | null) {
|
||||
const text = this.cleanVariable(value);
|
||||
const normalized = this.normalize(text);
|
||||
const knownTopics: Record<string, string> = {
|
||||
beneficios: 'Benefícios',
|
||||
ferias: 'Férias',
|
||||
rescisao: 'Rescisão',
|
||||
};
|
||||
|
||||
return knownTopics[normalized] || text;
|
||||
}
|
||||
|
||||
private applyBotVariables(message: string, variables: BotMessageVariables) {
|
||||
const firstName = this.getFirstName(variables.nome);
|
||||
const fullName = this.cleanVariable(variables.nome);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user