Baseline commit of the existing Maquina Comercial Pessoal project
Tracks the app that was already in place (capture, treatment, outreach, WhatsApp integration, server, frontend, tests, docs) so future feature work can branch and use isolated worktrees.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { openDb, createLeadInserter, setSetting } from '../src/db.mjs';
|
||||
import { dashboardSummary, dashboardDailyEvolution, dashboardMaiorOportunidade } from '../src/treatment/dashboard.mjs';
|
||||
|
||||
function seedLeads(db) {
|
||||
const insert = createLeadInserter(db);
|
||||
const base = {
|
||||
legal_name: '', whatsapp: '', ddd: '', email: '', segmento: '', segmento_label: '',
|
||||
interesse: '', cnpj: '', cnae: '', endereco: '', website: '', pains_json: '[]',
|
||||
origem: 'cnpj-base', telefone_valido: 0, cnpj_valido: 0, empresa_valida: 1,
|
||||
score: 50, classificacao: 'medio', motivo_classificacao: '', capture_run_id: null,
|
||||
captured_at: null
|
||||
};
|
||||
const hoje = new Date().toISOString();
|
||||
|
||||
insert({ ...base, lead_uid: 'A', dedup_key: 'k1', empresa: 'A', cidade: 'Salvador', uf: 'BA', prioridade: 1, exported_at: hoje });
|
||||
insert({ ...base, lead_uid: 'B', dedup_key: 'k2', empresa: 'B', cidade: 'Salvador', uf: 'BA', prioridade: 1, exported_at: null });
|
||||
insert({ ...base, lead_uid: 'C', dedup_key: 'k3', empresa: 'C', cidade: 'Ilheus', uf: 'BA', prioridade: 2, exported_at: null });
|
||||
insert({ ...base, lead_uid: 'D', dedup_key: 'k4', empresa: 'D', cidade: 'Ilheus', uf: 'BA', prioridade: 4, exported_at: null });
|
||||
}
|
||||
|
||||
test('dashboardSummary calcula totais, percentuais e meta diaria sobre a base toda', () => {
|
||||
const db = openDb(':memory:');
|
||||
seedLeads(db);
|
||||
setSetting(db, 'meta_diaria', '2');
|
||||
|
||||
const s = dashboardSummary(db, {});
|
||||
|
||||
assert.equal(s.total, 4);
|
||||
assert.equal(s.p1, 2);
|
||||
assert.equal(s.p2, 1);
|
||||
assert.equal(s.p3, 0);
|
||||
assert.equal(s.p4, 1);
|
||||
assert.equal(s.potencial_pct, 50);
|
||||
assert.equal(s.p1_pct, 50);
|
||||
assert.equal(s.p4_pct, 25);
|
||||
assert.equal(s.exportados, 1);
|
||||
assert.equal(s.disponiveis, 3);
|
||||
assert.equal(s.cobertura_pct, 25);
|
||||
assert.equal(s.hoje_exportados, 1);
|
||||
assert.equal(s.meta_diaria, 2);
|
||||
assert.equal(s.meta_pct, 50);
|
||||
assert.equal(s.dias_estimados, 2);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
test('dashboardSummary respeita o filtro (cidade) ao calcular percentuais', () => {
|
||||
const db = openDb(':memory:');
|
||||
seedLeads(db);
|
||||
|
||||
const s = dashboardSummary(db, { cidade: 'Ilheus' });
|
||||
|
||||
assert.equal(s.total, 2);
|
||||
assert.equal(s.p1, 0);
|
||||
assert.equal(s.p2, 1);
|
||||
assert.equal(s.p4, 1);
|
||||
assert.equal(s.p2_pct, 50);
|
||||
assert.equal(s.p4_pct, 50);
|
||||
assert.equal(s.exportados, 0);
|
||||
assert.equal(s.cobertura_pct, 0);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
test('dashboardSummary com base vazia nao divide por zero', () => {
|
||||
const db = openDb(':memory:');
|
||||
|
||||
const s = dashboardSummary(db, {});
|
||||
|
||||
assert.equal(s.total, 0);
|
||||
assert.equal(s.potencial_pct, 0);
|
||||
assert.equal(s.cobertura_pct, 0);
|
||||
assert.equal(s.meta_pct, 0);
|
||||
assert.equal(s.dias_estimados, 0);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
function seedLeadsComProdutos(db) {
|
||||
const insert = createLeadInserter(db);
|
||||
const base = {
|
||||
legal_name: '', whatsapp: '', ddd: '', email: '', segmento: '', segmento_label: '',
|
||||
interesse: '', cnpj: '', cnae: '', endereco: '', website: '', pains_json: '[]',
|
||||
origem: 'cnpj-base', telefone_valido: 0, cnpj_valido: 0, empresa_valida: 1,
|
||||
score: 50, classificacao: 'medio', motivo_classificacao: '', capture_run_id: null,
|
||||
captured_at: null, prioridade: 1, produtos_json: '[]'
|
||||
};
|
||||
|
||||
insert({ ...base, lead_uid: 'A', dedup_key: 'k1', empresa: 'A', cidade: 'Salvador', uf: 'BA', produto_principal: 'ERP', exported_at: '2026-07-10T10:00:00.000Z' });
|
||||
insert({ ...base, lead_uid: 'B', dedup_key: 'k2', empresa: 'B', cidade: 'Salvador', uf: 'BA', produto_principal: 'ERP', exported_at: '2026-07-10T11:00:00.000Z' });
|
||||
insert({ ...base, lead_uid: 'C', dedup_key: 'k3', empresa: 'C', cidade: 'Salvador', uf: 'BA', produto_principal: 'G-Chat', exported_at: '2026-07-11T09:00:00.000Z' });
|
||||
insert({ ...base, lead_uid: 'D', dedup_key: 'k4', empresa: 'D', cidade: 'Ilheus', uf: 'BA', produto_principal: 'ERP', exported_at: null });
|
||||
}
|
||||
|
||||
test('dashboardDailyEvolution agrupa exportacoes por dia em ordem cronologica', () => {
|
||||
const db = openDb(':memory:');
|
||||
seedLeadsComProdutos(db);
|
||||
|
||||
const evolution = dashboardDailyEvolution(db, {}, 14).map((r) => ({ ...r }));
|
||||
|
||||
assert.deepEqual(evolution, [
|
||||
{ dia: '2026-07-10', total: 2 },
|
||||
{ dia: '2026-07-11', total: 1 }
|
||||
]);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
test('dashboardDailyEvolution respeita o filtro', () => {
|
||||
const db = openDb(':memory:');
|
||||
seedLeadsComProdutos(db);
|
||||
|
||||
const evolution = dashboardDailyEvolution(db, { cidade: 'Ilheus' }, 14);
|
||||
|
||||
assert.deepEqual(evolution, []);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
test('dashboardMaiorOportunidade retorna a combinacao cidade+produto com mais empresas', () => {
|
||||
const db = openDb(':memory:');
|
||||
seedLeadsComProdutos(db);
|
||||
|
||||
const oportunidade = dashboardMaiorOportunidade(db, {});
|
||||
|
||||
assert.deepEqual({ ...oportunidade }, { cidade: 'Salvador', produto: 'ERP', total: 2 });
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
test('dashboardMaiorOportunidade retorna null quando nao ha dados', () => {
|
||||
const db = openDb(':memory:');
|
||||
|
||||
assert.equal(dashboardMaiorOportunidade(db, {}), null);
|
||||
|
||||
db.close();
|
||||
});
|
||||
Reference in New Issue
Block a user