corrigirPisoScoreAvaliacoes.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Corrige retroativamente avaliações que violam a regra de piso do juiz:
  2. // Resolvido="sim" + Sentimento="positivo" nunca deveriam ter ScoreAtendente < 6
  3. // (mesma regra agora imposta em código por aplicarPisoScore, em atendimentoAvaliacaoService.js).
  4. // Idempotente: rodar de novo depois de aplicado não encontra mais linhas.
  5. //
  6. // Uso:
  7. // node scripts/corrigirPisoScoreAvaliacoes.js # dry-run
  8. // node scripts/corrigirPisoScoreAvaliacoes.js --apply # aplica
  9. // node scripts/corrigirPisoScoreAvaliacoes.js --apply --expect-count 50 # trava de segurança
  10. import fs from "node:fs";
  11. import path from "node:path";
  12. import { fileURLToPath } from "node:url";
  13. import { AtendimentoAvaliacao } from "../src/models/AtendimentoAvaliacao.model.js";
  14. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  15. const APLICAR = process.argv.includes("--apply");
  16. const expectIdx = process.argv.indexOf("--expect-count");
  17. const EXPECT_COUNT = expectIdx > -1 ? Number(process.argv[expectIdx + 1]) : null;
  18. const SCORE_MINIMO = 6;
  19. async function main() {
  20. const linhas = await AtendimentoAvaliacao.query()
  21. .where("Resolvido", "sim")
  22. .where("Sentimento", "positivo")
  23. .whereNotNull("ScoreAtendente")
  24. .where("ScoreAtendente", "<", SCORE_MINIMO)
  25. .select("AtendimentoId", "ScoreAtendente", "JustificativaScore", "UpdatedAt");
  26. console.log(`[backfill-piso-score] ${linhas.length} avaliações violam a regra de piso.`);
  27. linhas.forEach((l) =>
  28. console.log(` #${l.AtendimentoId} score ${l.ScoreAtendente} -> ${SCORE_MINIMO} | ${(l.JustificativaScore ?? "").slice(0, 80)}`)
  29. );
  30. if (EXPECT_COUNT !== null && linhas.length !== EXPECT_COUNT) {
  31. console.error(`[backfill-piso-score] abortando: esperava ${EXPECT_COUNT} linhas, achei ${linhas.length}.`);
  32. process.exit(1);
  33. }
  34. if (!APLICAR) {
  35. console.log("[backfill-piso-score] dry-run (nenhuma alteração feita). Use --apply para aplicar.");
  36. process.exit(0);
  37. }
  38. if (linhas.length === 0) {
  39. console.log("[backfill-piso-score] nada para corrigir.");
  40. process.exit(0);
  41. }
  42. const backupDir = path.resolve(__dirname, "logs");
  43. fs.mkdirSync(backupDir, { recursive: true });
  44. const backupPath = path.join(backupDir, `backfill-piso-score-${new Date().toISOString().replace(/[:.]/g, "-")}.json`);
  45. fs.writeFileSync(backupPath, JSON.stringify(linhas, null, 2));
  46. console.log(`[backfill-piso-score] backup salvo em ${backupPath}`);
  47. const ids = linhas.map((l) => l.AtendimentoId);
  48. const afetados = await AtendimentoAvaliacao.query()
  49. .whereIn("AtendimentoId", ids)
  50. .patch({ ScoreAtendente: SCORE_MINIMO }); // UpdatedAt propositalmente não é tocado
  51. console.log(`[backfill-piso-score] ${afetados} linhas atualizadas para score ${SCORE_MINIMO}.`);
  52. process.exit(0);
  53. }
  54. main().catch((e) => {
  55. console.error("[backfill-piso-score] falha:", e.message);
  56. process.exit(1);
  57. });