Files
COMERCIAL-GTI/gti-maquina-comercial/scripts/recalcular-scores.mjs
T
GustavoandClaude Sonnet 5 f5af038e19 chore: import gti-maquina-comercial history via subtree
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

git-subtree-dir: gti-maquina-comercial
git-subtree-mainline: 93ca82979e
git-subtree-split: b77484946f
2026-09-28 15:50:08 -03:00

86 lines
3.0 KiB
JavaScript

import { loadDotEnv } from '../src/env.mjs';
import { openDb, transaction } from '../src/db.mjs';
import { scoreQualidade, scoreComercial, scoreGeral, classificarScoreGeral } from '../src/scoring.mjs';
// Recalcula score_qualidade/score_comercial/score/classificacao/prioridade/
// produto_principal de TODOS os leads a partir dos dados ja gravados + da
// afinidade/produtos configurados por nicho (tabela segments). Nao e um
// script de uso unico: roda de novo (`npm run recalc-scores`) sempre que o
// catalogo de afinidade/produtos em prospeccao/config.json mudar.
//
// Roda com o servidor parado (evita concorrencia de escrita no WAL).
await loadDotEnv();
const BATCH_SIZE = 2000;
function produtoPrincipalDe(produtos) {
return produtos.length ? [...produtos].sort((a, b) => b.estrelas - a.estrelas)[0].nome : '';
}
async function main() {
const db = openDb();
const segmentos = new Map(
db.prepare('SELECT name, affinity, products_json FROM segments').all()
.map((row) => [row.name, { affinity: row.affinity, products: JSON.parse(row.products_json) }])
);
const update = db.prepare(`
UPDATE leads SET
score = ?, classificacao = ?, motivo_classificacao = ?,
score_qualidade = ?, score_comercial = ?, prioridade = ?,
produto_principal = ?, produtos_json = ?, updated_at = datetime('now')
WHERE id = ?
`);
const total = db.prepare('SELECT COUNT(*) AS t FROM leads').get().t;
const porPrioridade = { 1: 0, 2: 0, 3: 0, 4: 0 };
let processed = 0;
let lastId = 0;
const page = db.prepare('SELECT * FROM leads WHERE id > ? ORDER BY id LIMIT ?');
while (true) {
const rows = page.all(lastId, BATCH_SIZE);
if (!rows.length) break;
transaction(db, () => {
for (const lead of rows) {
const info = segmentos.get(lead.segmento) || { affinity: 'media', products: [] };
const qualidade = scoreQualidade({
whatsapp: lead.whatsapp, cnpj: lead.cnpj, empresa: lead.empresa,
cidade: lead.cidade, segmento: lead.segmento, cnae: lead.cnae, website: lead.website
});
const comercial = scoreComercial({
whatsapp: lead.whatsapp, cnpj: lead.cnpj, website: lead.website,
email: lead.email, affinity: info.affinity
});
const geral = scoreGeral(qualidade.score, comercial);
const tier = classificarScoreGeral(geral);
const produtoPrincipal = produtoPrincipalDe(info.products);
update.run(
geral, tier.id, `score geral ${geral} (qualidade ${qualidade.score}, comercial ${comercial})`,
qualidade.score, comercial, tier.prioridade,
produtoPrincipal, JSON.stringify(info.products),
lead.id
);
porPrioridade[tier.prioridade] += 1;
}
});
processed += rows.length;
lastId = rows[rows.length - 1].id;
console.log(`${processed}/${total} leads recalculados...`);
}
console.log('Concluido. Distribuicao por prioridade:', porPrioridade);
db.close();
}
main().catch((error) => {
console.error('Erro no recalculo de scores:', error);
process.exit(1);
});