backfillTranscricaoSentinel.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import fs from "node:fs";
  2. import path from "node:path";
  3. import { fileURLToPath } from "node:url";
  4. import { AtendimentoAvaliacao } from "../src/models/AtendimentoAvaliacao.model.js";
  5. import { AtendimentoMensagem } from "../src/models/AtendimentoMensagem.model.js";
  6. import { contarPendentes } from "../src/services/atendimentoAvaliacaoService.js";
  7. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  8. const APLICAR = process.argv.includes("--apply");
  9. const limiteIdx = process.argv.indexOf("--limite");
  10. const LIMITE = limiteIdx > -1 ? Number(process.argv[limiteIdx + 1]) : null;
  11. const SENTINELS = ["__processando__", "__erro__"];
  12. async function buscarCandidatos() {
  13. const rows = await AtendimentoAvaliacao.query()
  14. .where("atendimento_avaliacoes.Avaliavel", true)
  15. .join(AtendimentoMensagem.tableName + " as m", "m.AtendimentoId", "atendimento_avaliacoes.AtendimentoId")
  16. .whereIn("m.Transcricao", SENTINELS)
  17. .whereRaw("atendimento_avaliacoes.UltimaMensagemId >= m.Id")
  18. .select(
  19. "atendimento_avaliacoes.AtendimentoId",
  20. "atendimento_avaliacoes.ScoreAtendente",
  21. "atendimento_avaliacoes.UltimaMensagemId"
  22. )
  23. .distinct("atendimento_avaliacoes.AtendimentoId")
  24. .orderBy("atendimento_avaliacoes.AtendimentoId");
  25. return rows;
  26. }
  27. async function main() {
  28. const candidatos = await buscarCandidatos();
  29. const alvos = LIMITE ? candidatos.slice(0, LIMITE) : candidatos;
  30. console.log(`[backfill-transcricao-sentinel] ${candidatos.length} atendimentos avaliados com sentinel no texto.`);
  31. console.log(`[backfill-transcricao-sentinel] ${alvos.length} avaliações serão resetadas para pendente${LIMITE ? ` (--limite ${LIMITE})` : ""}.`);
  32. if (!APLICAR) {
  33. console.log("[backfill-transcricao-sentinel] dry-run (nenhuma alteração feita). Use --apply para executar.");
  34. process.exit(0);
  35. }
  36. if (alvos.length === 0) {
  37. console.log("[backfill-transcricao-sentinel] nada para reavaliar.");
  38. process.exit(0);
  39. }
  40. const backupDir = path.resolve(__dirname, "logs");
  41. fs.mkdirSync(backupDir, { recursive: true });
  42. const backupPath = path.join(backupDir, `backfill-transcricao-sentinel-${new Date().toISOString().replace(/[:.]/g, "-")}.json`);
  43. fs.writeFileSync(backupPath, JSON.stringify(alvos, null, 2));
  44. console.log(`[backfill-transcricao-sentinel] backup dos valores antigos salvo em ${backupPath}`);
  45. const ids = alvos.map((a) => a.AtendimentoId);
  46. const pendentesAntes = await contarPendentes();
  47. await AtendimentoAvaliacao.query().whereIn("AtendimentoId", ids).patch({ UltimaMensagemId: null });
  48. const pendentesDepois = await contarPendentes();
  49. console.log(`[backfill-transcricao-sentinel] resetados ${ids.length} — fila de pendentes ${pendentesAntes} -> ${pendentesDepois}.`);
  50. console.log("[backfill-transcricao-sentinel] pronto. Agora rode scripts/avaliarTudo.js para drenar a fila.");
  51. process.exit(0);
  52. }
  53. main().catch((e) => {
  54. console.error("[backfill-transcricao-sentinel] falha:", e.message);
  55. process.exit(1);
  56. });