Per-product message templates, official/não-oficial channel selection, manual per-number sending, and a 20-minute internal scheduler for the existing automatic outreach batch — all pre-existing local work being committed as-is.
129 lines
4.5 KiB
JavaScript
129 lines
4.5 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { openDb, createLeadInserter, transaction, getSetting, setSetting, seedSegments, seedMunicipios, seedGeoCache, seedSettings, seedMessageTemplates, updateMessageTemplate } from '../src/db.mjs';
|
|
|
|
function sampleLead(overrides = {}) {
|
|
return {
|
|
lead_uid: 'GTI-TEST-1',
|
|
dedup_key: 'cnpj:57557263000113',
|
|
empresa: 'PREMIUM EXPRESS',
|
|
legal_name: 'PREMIUM EXPRESS LTDA',
|
|
whatsapp: '557193335451',
|
|
ddd: '71',
|
|
email: '',
|
|
cidade: 'Salvador',
|
|
uf: 'BA',
|
|
segmento: 'restaurantes',
|
|
segmento_label: 'Restaurantes',
|
|
interesse: 'Autoatendimento para WhatsApp',
|
|
cnpj: '57557263000113',
|
|
cnae: '5611203',
|
|
endereco: 'RUA X, 1',
|
|
website: '',
|
|
pains_json: '["atendimento"]',
|
|
origem: 'cnpj-base',
|
|
telefone_valido: 1,
|
|
cnpj_valido: 1,
|
|
empresa_valida: 1,
|
|
score: 100,
|
|
classificacao: 'bom',
|
|
motivo_classificacao: 'ok',
|
|
capture_run_id: null,
|
|
captured_at: '2026-07-09T14:26:18.560Z',
|
|
exported_at: null,
|
|
...overrides
|
|
};
|
|
}
|
|
|
|
test('openDb cria esquema e aplica migrations uma unica vez', () => {
|
|
const db = openDb(':memory:');
|
|
const version = db.prepare('SELECT MAX(version) AS v FROM schema_migrations').get().v;
|
|
assert.ok(version >= 1);
|
|
const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map((r) => r.name);
|
|
for (const table of ['leads', 'capture_runs', 'extractions', 'exports', 'export_leads', 'segments', 'municipios', 'geo_cache', 'settings']) {
|
|
assert.ok(tables.includes(table), `tabela ${table} ausente`);
|
|
}
|
|
db.close();
|
|
});
|
|
|
|
test('createLeadInserter insere e ignora duplicata pela dedup_key', () => {
|
|
const db = openDb(':memory:');
|
|
const insert = createLeadInserter(db);
|
|
|
|
assert.equal(insert(sampleLead()), 'inserted');
|
|
assert.equal(insert(sampleLead({ empresa: 'OUTRO NOME' })), 'duplicate');
|
|
|
|
const total = db.prepare('SELECT COUNT(*) AS t FROM leads').get().t;
|
|
assert.equal(total, 1);
|
|
db.close();
|
|
});
|
|
|
|
test('transaction faz rollback em erro', () => {
|
|
const db = openDb(':memory:');
|
|
const insert = createLeadInserter(db);
|
|
|
|
assert.throws(() =>
|
|
transaction(db, () => {
|
|
insert(sampleLead());
|
|
throw new Error('boom');
|
|
})
|
|
);
|
|
|
|
assert.equal(db.prepare('SELECT COUNT(*) AS t FROM leads').get().t, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('settings: get/set e seed com defaults Z-PRO', () => {
|
|
const db = openDb(':memory:');
|
|
seedSettings(db);
|
|
|
|
assert.equal(getSetting(db, 'zpro.pipelineId'), '1');
|
|
assert.equal(getSetting(db, 'zpro.stageId'), '1');
|
|
assert.equal(getSetting(db, 'zpro.responsibleId'), '15');
|
|
|
|
setSetting(db, 'zpro.pipelineId', '9');
|
|
assert.equal(getSetting(db, 'zpro.pipelineId'), '9');
|
|
|
|
// seed nao sobrescreve valor ja definido pelo usuario
|
|
seedSettings(db);
|
|
assert.equal(getSetting(db, 'zpro.pipelineId'), '9');
|
|
db.close();
|
|
});
|
|
|
|
test('message_templates salva variaveis WABA automaticas por produto', () => {
|
|
const db = openDb(':memory:');
|
|
seedMessageTemplates(db, ['ERP']);
|
|
|
|
const updated = updateMessageTemplate(db, 'ERP', {
|
|
canal: 'oficial',
|
|
templateWabaNome: 'gti_inicio_atendimento_solicitado',
|
|
templateWabaIdioma: 'pt_BR',
|
|
templateWabaVariaveis: ['{empresa}', 'Assunto: {produto}', '']
|
|
});
|
|
|
|
assert.equal(updated.template_waba_nome, 'gti_inicio_atendimento_solicitado');
|
|
assert.deepEqual(JSON.parse(updated.template_waba_variaveis_json), ['{empresa}', 'Assunto: {produto}']);
|
|
db.close();
|
|
});
|
|
|
|
test('seeds de segments, municipios e geo_cache', () => {
|
|
const db = openDb(':memory:');
|
|
|
|
seedSegments(db, [
|
|
{ name: 'clinicas_medicas', queries: ['clinica'], cnaeCodes: ['8630501'], overpassTags: [{ key: 'amenity', value: 'clinic' }], interest: 'gestao de TI', pains: ['agenda'] }
|
|
]);
|
|
const segment = db.prepare('SELECT * FROM segments WHERE name = ?').get('clinicas_medicas');
|
|
assert.equal(segment.label, 'Clinicas Medicas');
|
|
assert.deepEqual(JSON.parse(segment.cnae_codes_json), ['8630501']);
|
|
|
|
seedMunicipios(db, [{ codigo_ibge: '2928703', nome: 'Santo Antônio de Jesus', uf: 'BA' }]);
|
|
const municipio = db.prepare('SELECT * FROM municipios WHERE uf = ?').get('BA');
|
|
assert.equal(municipio.nome_clean, 'santo antonio de jesus');
|
|
|
|
seedGeoCache(db, [{ name: 'Santo Antonio de Jesus', state: 'BA', bbox: [-12.995, -39.325, -12.925, -39.225] }]);
|
|
const bbox = db.prepare('SELECT * FROM geo_cache WHERE key = ?').get('bbox:BA:santo antonio de jesus');
|
|
assert.equal(bbox.south, -12.995);
|
|
assert.equal(bbox.provider, 'config-legacy');
|
|
db.close();
|
|
});
|