Преглед изворни кода

ajustes avaliação de atendimentos

leonardo пре 2 месеци
родитељ
комит
5f66a0f768

+ 66 - 0
scripts/corrigirPisoScoreAvaliacoes.js

@@ -0,0 +1,66 @@
+// Corrige retroativamente avaliações que violam a regra de piso do juiz:
+// Resolvido="sim" + Sentimento="positivo" nunca deveriam ter ScoreAtendente < 6
+// (mesma regra agora imposta em código por aplicarPisoScore, em atendimentoAvaliacaoService.js).
+// Idempotente: rodar de novo depois de aplicado não encontra mais linhas.
+//
+// Uso:
+//   node scripts/corrigirPisoScoreAvaliacoes.js                       # dry-run
+//   node scripts/corrigirPisoScoreAvaliacoes.js --apply                # aplica
+//   node scripts/corrigirPisoScoreAvaliacoes.js --apply --expect-count 50   # trava de segurança
+
+import fs from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+import { AtendimentoAvaliacao } from "../src/models/AtendimentoAvaliacao.model.js";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const APLICAR = process.argv.includes("--apply");
+const expectIdx = process.argv.indexOf("--expect-count");
+const EXPECT_COUNT = expectIdx > -1 ? Number(process.argv[expectIdx + 1]) : null;
+const SCORE_MINIMO = 6;
+
+async function main() {
+  const linhas = await AtendimentoAvaliacao.query()
+    .where("Resolvido", "sim")
+    .where("Sentimento", "positivo")
+    .whereNotNull("ScoreAtendente")
+    .where("ScoreAtendente", "<", SCORE_MINIMO)
+    .select("AtendimentoId", "ScoreAtendente", "JustificativaScore", "UpdatedAt");
+
+  console.log(`[backfill-piso-score] ${linhas.length} avaliações violam a regra de piso.`);
+  linhas.forEach((l) =>
+    console.log(`  #${l.AtendimentoId}  score ${l.ScoreAtendente} -> ${SCORE_MINIMO}  | ${(l.JustificativaScore ?? "").slice(0, 80)}`)
+  );
+
+  if (EXPECT_COUNT !== null && linhas.length !== EXPECT_COUNT) {
+    console.error(`[backfill-piso-score] abortando: esperava ${EXPECT_COUNT} linhas, achei ${linhas.length}.`);
+    process.exit(1);
+  }
+  if (!APLICAR) {
+    console.log("[backfill-piso-score] dry-run (nenhuma alteração feita). Use --apply para aplicar.");
+    process.exit(0);
+  }
+  if (linhas.length === 0) {
+    console.log("[backfill-piso-score] nada para corrigir.");
+    process.exit(0);
+  }
+
+  const backupDir = path.resolve(__dirname, "logs");
+  fs.mkdirSync(backupDir, { recursive: true });
+  const backupPath = path.join(backupDir, `backfill-piso-score-${new Date().toISOString().replace(/[:.]/g, "-")}.json`);
+  fs.writeFileSync(backupPath, JSON.stringify(linhas, null, 2));
+  console.log(`[backfill-piso-score] backup salvo em ${backupPath}`);
+
+  const ids = linhas.map((l) => l.AtendimentoId);
+  const afetados = await AtendimentoAvaliacao.query()
+    .whereIn("AtendimentoId", ids)
+    .patch({ ScoreAtendente: SCORE_MINIMO }); // UpdatedAt propositalmente não é tocado
+
+  console.log(`[backfill-piso-score] ${afetados} linhas atualizadas para score ${SCORE_MINIMO}.`);
+  process.exit(0);
+}
+
+main().catch((e) => {
+  console.error("[backfill-piso-score] falha:", e.message);
+  process.exit(1);
+});

+ 296 - 0
scripts/logs/backfill-piso-score-2026-07-10T12-54-29-980Z.json

@@ -0,0 +1,296 @@
+[
+  {
+    "AtendimentoId": 143351,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e o cliente teve que aguardar mais de 20 minutos sem resposta. O atendente Nicholas não forneceu uma solução imediata para a solicitação do cliente.",
+    "UpdatedAt": "2026-07-09T15:00:31.000Z"
+  },
+  {
+    "AtendimentoId": 144062,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e o cliente teve que aguardar mais de 20 minutos várias vezes. O atendente Lucas não conseguiu resolver o problema imediatamente e precisou encaminhar o cliente para uma solução alternativa.",
+    "UpdatedAt": "2026-07-09T17:46:10.000Z"
+  },
+  {
+    "AtendimentoId": 144814,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorou muito tempo para ser atendido e o cliente foi deixado sem resposta por mais de 20 minutos.",
+    "UpdatedAt": "2026-07-09T17:49:01.000Z"
+  },
+  {
+    "AtendimentoId": 148720,
+    "ScoreAtendente": 1,
+    "JustificativaScore": "Atendente inicial foi eficaz em entender o problema do cliente e passou o atendimento para outro atendente que não se manifestou de forma alguma.",
+    "UpdatedAt": "2026-07-09T17:53:32.000Z"
+  },
+  {
+    "AtendimentoId": 148880,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve várias transferências de atendentes, o que pode ter causado confusão para o cliente.",
+    "UpdatedAt": "2026-07-09T17:54:48.000Z"
+  },
+  {
+    "AtendimentoId": 149420,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve longos períodos de silêncio do atendente. A cliente precisou repetir sua solicitação várias vezes.",
+    "UpdatedAt": "2026-07-09T17:58:14.000Z"
+  },
+  {
+    "AtendimentoId": 149618,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento com falhas na comunicação e transferência de responsabilidade entre atendentes. O cliente teve que esperar mais de 20 minutos por resposta em duas ocasiões.",
+    "UpdatedAt": "2026-07-09T18:00:16.000Z"
+  },
+  {
+    "AtendimentoId": 149760,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou cerca de 4 horas para ser resolvido e o cliente aguardava resposta há mais de 20 minutos.",
+    "UpdatedAt": "2026-07-09T18:03:28.000Z"
+  },
+  {
+    "AtendimentoId": 149817,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou mais de 24 horas para ser resolvido, com a atendente Bruna não oferecendo uma solução eficaz inicialmente e apenas encaminhando o cliente após um tempo.",
+    "UpdatedAt": "2026-07-09T18:06:07.000Z"
+  },
+  {
+    "AtendimentoId": 149839,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento com falhas de comunicação e demora em responder ao cliente.",
+    "UpdatedAt": "2026-07-09T18:06:58.000Z"
+  },
+  {
+    "AtendimentoId": 150092,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo e teve várias transferências entre atendentes. O cliente precisou repetir informações diversas vezes.",
+    "UpdatedAt": "2026-07-09T15:04:36.000Z"
+  },
+  {
+    "AtendimentoId": 150124,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorado e com várias interrupções, atendentes não conseguiram resolver o problema de liberação do sinal de forma eficiente.",
+    "UpdatedAt": "2026-07-09T18:32:48.000Z"
+  },
+  {
+    "AtendimentoId": 150126,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento transferido várias vezes e atendente final não ofereceu solução personalizada.",
+    "UpdatedAt": "2026-07-09T18:33:01.000Z"
+  },
+  {
+    "AtendimentoId": 150141,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve transferências desnecessárias entre os atendentes. O cliente precisou repetir informações e esperar por respostas.",
+    "UpdatedAt": "2026-07-09T15:05:14.000Z"
+  },
+  {
+    "AtendimentoId": 150303,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "O atendimento foi demorado e teve várias interrupções, com o cliente aguardando respostas por mais de 20 minutos. O atendente Gabriel não conseguiu resolver a situação de forma eficaz.",
+    "UpdatedAt": "2026-07-09T18:48:19.000Z"
+  },
+  {
+    "AtendimentoId": 150337,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve várias interrupções. O cliente precisou repetir o problema diversas vezes e não recebeu uma solução clara até o final.",
+    "UpdatedAt": "2026-07-09T15:06:11.000Z"
+  },
+  {
+    "AtendimentoId": 150466,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "O atendimento foi demorado e o cliente teve que insistir várias vezes para agendar a visita técnica. O atendente não ofereceu solução imediata, apenas aguardou até que o cliente aceitasse uma data futura.",
+    "UpdatedAt": "2026-07-09T18:52:51.000Z"
+  },
+  {
+    "AtendimentoId": 150699,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "O atendimento foi demorado e teve várias transferências de atendentes. O cliente aguardou por períodos prolongados sem resposta.",
+    "UpdatedAt": "2026-07-09T18:56:09.000Z"
+  },
+  {
+    "AtendimentoId": 150756,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorado e com poucas respostas claras do atendente. O cliente teve que enviar imagens para tentar explicar o problema.",
+    "UpdatedAt": "2026-07-09T15:14:44.000Z"
+  },
+  {
+    "AtendimentoId": 150919,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve várias interrupções, com o cliente aguardando resposta por mais de 20 minutos em alguns momentos. Além disso, a atendente Helen não conseguiu realizar o cancelamento da conta do cliente no momento correto.",
+    "UpdatedAt": "2026-07-09T15:17:41.000Z"
+  },
+  {
+    "AtendimentoId": 150935,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo para resolver o problema do cliente e não houve uma abordagem eficaz para entender as necessidades específicas da família.",
+    "UpdatedAt": "2026-07-09T20:24:26.000Z"
+  },
+  {
+    "AtendimentoId": 150960,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo para ser resolvido e o atendente Fernanda não foi eficaz em manter a comunicação com o cliente.",
+    "UpdatedAt": "2026-07-09T20:03:42.000Z"
+  },
+  {
+    "AtendimentoId": 150975,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendente Carla transferiu o atendimento sem resolver a dúvida do cliente e Bruna não explicou por que as faturas foram duplicadas.",
+    "UpdatedAt": "2026-07-09T19:11:23.000Z"
+  },
+  {
+    "AtendimentoId": 151009,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento confuso e com demora em resolver o problema do cliente, que foi finalmente resolvido após várias tentativas.",
+    "UpdatedAt": "2026-07-10T11:46:13.000Z"
+  },
+  {
+    "AtendimentoId": 151032,
+    "ScoreAtendente": 1,
+    "JustificativaScore": "Atendimento demorou cerca de 14 horas para ser finalizado e o cliente teve que aguardar mais de 20 minutos por resposta. O atendente não se manifestou durante esse período.",
+    "UpdatedAt": "2026-07-09T19:13:20.000Z"
+  },
+  {
+    "AtendimentoId": 151063,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendente Bruna foi paciente e tentou ajudar o cliente a encontrar uma solução para pagar sua fatura vencida, mas não conseguiu fornecer informações claras sobre como proceder. O cliente teve que enviar várias mensagens com fotos do boleto pago.",
+    "UpdatedAt": "2026-07-09T19:27:00.000Z"
+  },
+  {
+    "AtendimentoId": 151075,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendente Gabriel inicialmente respondeu rapidamente e tentou ajudar o cliente. No entanto, a conversa foi interrompida por um desconhecido e, posteriormente, o atendente Leonardo não conseguiu fornecer informações precisas sobre o horário da visita técnica.",
+    "UpdatedAt": "2026-07-09T15:24:28.000Z"
+  },
+  {
+    "AtendimentoId": 151090,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendente Gabriel inicialmente demonstrou interesse e tentou entender o problema do cliente. No entanto, após alguns minutos de conversa, ele parece ter se distanciado e não respondeu às mensagens do cliente por mais de 20 minutos, deixando-o aguardando resposta.",
+    "UpdatedAt": "2026-07-09T15:24:48.000Z"
+  },
+  {
+    "AtendimentoId": 151111,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorou muito tempo e não houve comunicação eficaz entre atendente e cliente.",
+    "UpdatedAt": "2026-07-09T17:19:48.000Z"
+  },
+  {
+    "AtendimentoId": 151155,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve várias interrupções. O cliente precisou esperar por respostas durante mais de 20 minutos em diferentes momentos.",
+    "UpdatedAt": "2026-07-09T19:30:49.000Z"
+  },
+  {
+    "AtendimentoId": 151160,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorado e com falhas na comunicação entre atendentes. O cliente aguardou mais de 20 minutos por duas vezes sem resposta.",
+    "UpdatedAt": "2026-07-09T19:31:30.000Z"
+  },
+  {
+    "AtendimentoId": 151219,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo para resolver o problema do cliente e a atendente não foi eficaz em explicar as opções de vencimento do boleto.",
+    "UpdatedAt": "2026-07-09T19:35:22.000Z"
+  },
+  {
+    "AtendimentoId": 151242,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo para resolver a solicitação do cliente, com transferência de atendente e aguardos de resposta.",
+    "UpdatedAt": "2026-07-09T19:51:25.000Z"
+  },
+  {
+    "AtendimentoId": 151260,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendimento foi demorado e teve várias interrupções, com mudanças de atendentes. O cliente aguardou mais de 20 minutos em duas ocasiões.",
+    "UpdatedAt": "2026-07-09T15:28:13.000Z"
+  },
+  {
+    "AtendimentoId": 151283,
+    "ScoreAtendente": 3,
+    "JustificativaScore": "Atendente demorou muito tempo para responder e não ofereceu solução eficaz para os problemas do cliente.",
+    "UpdatedAt": "2026-07-09T15:31:34.000Z"
+  },
+  {
+    "AtendimentoId": 151361,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorado e com várias transferências de atendentes. O cliente teve que esperar mais de 20 minutos por resposta em várias ocasiões.",
+    "UpdatedAt": "2026-07-09T19:43:43.000Z"
+  },
+  {
+    "AtendimentoId": 151380,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou mais de 20 minutos para responder ao cliente e não houve comunicação eficaz durante esse período.",
+    "UpdatedAt": "2026-07-09T16:56:18.000Z"
+  },
+  {
+    "AtendimentoId": 151383,
+    "ScoreAtendente": 1,
+    "JustificativaScore": "Atendimento demorou cerca de 27 minutos para ser resolvido e o atendente não se manifestou após a mensagem do cliente.",
+    "UpdatedAt": "2026-07-09T20:05:18.000Z"
+  },
+  {
+    "AtendimentoId": 151405,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorado e com pouca interação efetiva entre atendente e cliente.",
+    "UpdatedAt": "2026-07-09T19:51:46.000Z"
+  },
+  {
+    "AtendimentoId": 151408,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorado e com poucas respostas claras do atendente. O cliente teve que enviar várias mensagens para obter informações.",
+    "UpdatedAt": "2026-07-09T19:48:22.000Z"
+  },
+  {
+    "AtendimentoId": 151424,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "O atendimento foi demorado e o cliente teve que repetir informações diversas vezes. O atendente não pareceu muito engajado em resolver o problema.",
+    "UpdatedAt": "2026-07-09T16:57:21.000Z"
+  },
+  {
+    "AtendimentoId": 151450,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento demorou muito tempo para responder às perguntas do cliente.",
+    "UpdatedAt": "2026-07-09T17:03:32.000Z"
+  },
+  {
+    "AtendimentoId": 151453,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorou muito tempo para ser resolvido e o atendente não se comunicou com o cliente durante esse período.",
+    "UpdatedAt": "2026-07-09T17:17:19.000Z"
+  },
+  {
+    "AtendimentoId": 151456,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "O atendente Gabriel respondeu após mais de 12 horas da última mensagem do cliente e não ofereceu uma solução imediata.",
+    "UpdatedAt": "2026-07-09T17:37:44.000Z"
+  },
+  {
+    "AtendimentoId": 151480,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendente Carla demorou a responder e não ofereceu uma solução imediata para o problema do cliente.",
+    "UpdatedAt": "2026-07-09T13:40:59.000Z"
+  },
+  {
+    "AtendimentoId": 151536,
+    "ScoreAtendente": 5,
+    "JustificativaScore": "Atendimento transferido várias vezes e demora excessiva para resolver o problema do cliente.",
+    "UpdatedAt": "2026-07-09T16:40:24.000Z"
+  },
+  {
+    "AtendimentoId": 151539,
+    "ScoreAtendente": 1,
+    "JustificativaScore": "Atendente Fernanda não conseguiu identificar a necessidade do cliente e foi direta ao assunto de planos sem entender o problema apresentado.",
+    "UpdatedAt": "2026-07-09T17:24:39.000Z"
+  },
+  {
+    "AtendimentoId": 151551,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendimento demorou muito tempo para resolver o problema do cliente e não houve uma abordagem eficaz para atender às suas necessidades.",
+    "UpdatedAt": "2026-07-10T12:21:14.000Z"
+  },
+  {
+    "AtendimentoId": 151598,
+    "ScoreAtendente": 4,
+    "JustificativaScore": "Atendente demorou a responder e não foi eficaz em resolver o problema do cliente.",
+    "UpdatedAt": "2026-07-09T19:55:34.000Z"
+  }
+]

+ 53 - 2
src/services/atendimentoAvaliacaoService.js

@@ -19,6 +19,40 @@ const AVALIACAO_SYSTEM_PROMPT = [
   "Um atendimento resolvido com cliente satisfeito NUNCA recebe score abaixo de 6.",
   "Se nenhum atendente humano participou, use score_atendente = null.",
   "",
+  "Exemplos de calibração (conversas fictícias e resumidas — sirvam de referência para o score, não copie o texto):",
+  "",
+  "Exemplo 1 — resolvido e cliente satisfeito, mas processo com falha (score = piso 6):",
+  'Cliente: "Minha internet caiu de novo, terceira vez essa semana."',
+  "Sistema: atendimento transferido para o setor técnico.",
+  "(Atendente Marcos não responde por mais de 20 minutos.)",
+  'Cliente: "alguém aí? já fazem 20 minutos"',
+  'Atendente Marcos: "Desculpe a demora! Vou reiniciar sua conexão remotamente."',
+  'Cliente: "Voltou, obrigado!"',
+  '→ justificativa_score: "Problema resolvido e cliente satisfeito ao final, mas o atendente demorou mais',
+  '  de 20 minutos para responder, prejudicando a experiência."',
+  "→ score_atendente: 6 — mesmo com falha grave de processo, resolvido=sim e sentimento=positivo nunca",
+  "  ficam abaixo de 6; a falha já está registrada na justificativa e nas sugestões de melhoria.",
+  "",
+  "Exemplo 2 — atendimento exemplar (score 9-10):",
+  'Cliente: "Minha internet está lenta há dois dias."',
+  'Atendente Ana: "Pode me mandar um print do teste de velocidade em oiii.com.br/velocimetro?"',
+  'Cliente: (envia print) "aqui está"',
+  'Atendente Ana: "Identifiquei um problema no roteador. Reinicie e afaste de outros aparelhos eletrônicos."',
+  'Cliente: "Funcionou perfeitamente, muito obrigado pela agilidade!"',
+  '→ justificativa_score: "Atendente identificou a causa rapidamente, orientou com clareza em poucas',
+  '  mensagens e o cliente confirmou a solução, satisfeito."',
+  "→ score_atendente: 9",
+  "",
+  "Exemplo 3 — não resolvido, cliente insatisfeito (score 2-3):",
+  'Cliente: "Preciso da segunda via do meu boleto."',
+  'Atendente Rafael: "Segue o valor: R$ 350,00" (valor está incorreto, cliente paga R$ 120,00)',
+  'Cliente: "Esse valor está errado, sempre pago R$ 120."',
+  'Atendente Rafael: "Vou te transferir para o financeiro."',
+  "(conversa termina sem retorno do financeiro)",
+  '→ justificativa_score: "Atendente informou valor incorreto e não corrigiu o erro; cliente ficou sem',
+  '  solução e insatisfeito, saindo da conversa sem retorno."',
+  "→ score_atendente: 2",
+  "",
   "Campos:",
   '- resolvido: "sim" se o problema do cliente foi claramente resolvido na conversa; "parcial" se houve',
   '  encaminhamento/paliativo; "nao" se terminou sem solução; "indefinido" se não dá para concluir.',
@@ -106,6 +140,23 @@ function normalizeScore(value) {
   return Math.min(10, Math.max(1, Math.round(n)));
 }
 
+// impõe no código a regra de piso do prompt: o modelo juiz (llama3.1 8B) às vezes calcula a
+// severidade certa na justificativa mas esquece de aplicar a regra condicional ao decidir o
+// score final — observado em ~6% das avaliações reais.
+const SCORE_MINIMO_RESOLVIDO_POSITIVO = 6;
+
+export function aplicarPisoScore(dados) {
+  if (
+    dados.Resolvido === "sim" &&
+    dados.Sentimento === "positivo" &&
+    dados.ScoreAtendente !== null &&
+    dados.ScoreAtendente < SCORE_MINIMO_RESOLVIDO_POSITIVO
+  ) {
+    return { ...dados, ScoreAtendente: SCORE_MINIMO_RESOLVIDO_POSITIVO };
+  }
+  return dados;
+}
+
 function normalizeStringArray(value, { maxItems = 10, maxLength = 300 } = {}) {
   if (!Array.isArray(value)) return [];
   return value
@@ -129,7 +180,7 @@ function parseAvaliacao(content) {
     ? parsed.horario_visita.trim().slice(0, 150)
     : null;
 
-  return {
+  return aplicarPisoScore({
     ScoreAtendente: normalizeScore(parsed.score_atendente),
     JustificativaScore: typeof parsed.justificativa_score === "string" && parsed.justificativa_score.trim()
       ? parsed.justificativa_score.trim()
@@ -142,7 +193,7 @@ function parseAvaliacao(content) {
     VisitaAgendada: Boolean(parsed.visita_agendada),
     HorarioVisitaInformado: horarioInformado,
     HorarioVisita: horarioInformado === "sim" ? horarioVisita : null
-  };
+  });
 }
 
 function contarInteracoes(mensagens) {