generateCampaignQueue computed candidatosEncontrados after slicing to quantidade, so it could never differ from adicionadosNaFila. An operator generating a queue with quantidade smaller than the eligible pool saw no signal that more eligible leads existed. Now candidatosEncontrados is read before the slice, while adicionadosNaFila still reflects rows actually inserted.
153 lines
6.2 KiB
JavaScript
153 lines
6.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { openDb, createLeadInserter } from '../src/db.mjs';
|
|
import { createCampaign } from '../src/outreach/campaign-store.mjs';
|
|
import { generateCampaignQueue, listQueue, approveQueueRows, cancelQueueRows } from '../src/outreach/campaign-queue.mjs';
|
|
|
|
function inserirLead(db, overrides = {}) {
|
|
const inserir = createLeadInserter(db);
|
|
const dedup = overrides.dedup_key || `lead-${Math.random()}`;
|
|
inserir({
|
|
dedup_key: dedup, empresa: 'Oficina Teste', legal_name: '', whatsapp: '5511999990001',
|
|
ddd: '11', email: '', cidade: 'SP', uf: 'SP', segmento: 'oficinas_mecanicas', segmento_label: '',
|
|
interesse: '', cnpj: '', cnae: '', endereco: '', website: '', pains_json: '[]', origem: 'teste',
|
|
telefone_valido: 1, cnpj_valido: 0, empresa_valida: 1, score: 80, classificacao: 'bom',
|
|
motivo_classificacao: '', score_qualidade: 80, score_comercial: 80, prioridade: 1,
|
|
produto_principal: 'ERP', produtos_json: '[]', capture_run_id: null, captured_at: null, exported_at: null,
|
|
...overrides
|
|
});
|
|
return db.prepare('SELECT * FROM leads WHERE dedup_key = ?').get(dedup);
|
|
}
|
|
|
|
function campanhaComVariantes(db, overrides = {}) {
|
|
return createCampaign(db, {
|
|
nome: 'ERP oficinas', produto: 'ERP', segmentos: ['oficinas_mecanicas'],
|
|
variantes: [{ code: 'A', mensagem: 'Ola {empresa}' }],
|
|
...overrides
|
|
});
|
|
}
|
|
|
|
test('generateCampaignQueue cria linhas preview so para leads do produto/segmento certos', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { dedup_key: 'l1', whatsapp: '5511999990001' });
|
|
inserirLead(db, { dedup_key: 'l2', segmento: 'outro_segmento', whatsapp: '5511999990002' });
|
|
const campanha = campanhaComVariantes(db);
|
|
|
|
const resultado = generateCampaignQueue(db, campanha.id);
|
|
assert.equal(resultado.candidatosEncontrados, 1);
|
|
assert.equal(resultado.adicionadosNaFila, 1);
|
|
|
|
const fila = listQueue(db, campanha.id);
|
|
assert.equal(fila.length, 1);
|
|
assert.equal(fila[0].status, 'preview');
|
|
assert.equal(fila[0].rendered_message, 'Ola Oficina Teste');
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue exclui lead com envio ja enviado para o mesmo produto (por lead_id)', () => {
|
|
const db = openDb(':memory:');
|
|
const lead = inserirLead(db);
|
|
db.prepare(
|
|
`INSERT INTO outreach_sends (lead_id, produto, numero, mensagem_enviada, status) VALUES (?, 'ERP', ?, 'oi', 'enviado')`
|
|
).run(lead.id, lead.whatsapp);
|
|
const campanha = campanhaComVariantes(db);
|
|
|
|
const resultado = generateCampaignQueue(db, campanha.id);
|
|
assert.equal(resultado.candidatosEncontrados, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue exclui numero com envio manual ja enviado (sem lead_id) para o mesmo produto', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { whatsapp: '5511999990009' });
|
|
db.prepare(
|
|
`INSERT INTO outreach_sends (lead_id, produto, numero, mensagem_enviada, status, origem)
|
|
VALUES (NULL, 'ERP', '5511999990009', 'oi', 'enviado', 'manual')`
|
|
).run();
|
|
const campanha = campanhaComVariantes(db);
|
|
|
|
const resultado = generateCampaignQueue(db, campanha.id);
|
|
assert.equal(resultado.candidatosEncontrados, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue exclui numero em opt-out', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { whatsapp: '5511999990001' });
|
|
db.prepare(`INSERT INTO outreach_opt_out (numero) VALUES ('5511999990001')`).run();
|
|
const campanha = campanhaComVariantes(db);
|
|
|
|
const resultado = generateCampaignQueue(db, campanha.id);
|
|
assert.equal(resultado.candidatosEncontrados, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue nao duplica lead ja na fila (preview/approved/sent) de outra campanha do mesmo produto', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { dedup_key: 'unico', whatsapp: '5511999990001' });
|
|
const campanha1 = campanhaComVariantes(db, { nome: 'Campanha 1' });
|
|
generateCampaignQueue(db, campanha1.id);
|
|
|
|
const campanha2 = campanhaComVariantes(db, { nome: 'Campanha 2' });
|
|
const resultado = generateCampaignQueue(db, campanha2.id);
|
|
assert.equal(resultado.candidatosEncontrados, 0);
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue respeita o parametro quantidade', () => {
|
|
const db = openDb(':memory:');
|
|
for (let i = 0; i < 5; i += 1) {
|
|
inserirLead(db, { dedup_key: `lead-${i}`, whatsapp: `551199999000${i}` });
|
|
}
|
|
const campanha = campanhaComVariantes(db);
|
|
const resultado = generateCampaignQueue(db, campanha.id, { quantidade: 3 });
|
|
assert.equal(resultado.adicionadosNaFila, 3);
|
|
db.close();
|
|
});
|
|
|
|
test('generateCampaignQueue reporta candidatosEncontrados como o pool elegivel completo, mesmo com quantidade menor', () => {
|
|
const db = openDb(':memory:');
|
|
for (let i = 0; i < 5; i += 1) {
|
|
inserirLead(db, { dedup_key: `pool-${i}`, whatsapp: `551199998000${i}` });
|
|
}
|
|
const campanha = campanhaComVariantes(db);
|
|
const resultado = generateCampaignQueue(db, campanha.id, { quantidade: 2 });
|
|
assert.equal(resultado.candidatosEncontrados, 5);
|
|
assert.equal(resultado.adicionadosNaFila, 2);
|
|
assert.equal(listQueue(db, campanha.id).length, 2);
|
|
db.close();
|
|
});
|
|
|
|
test('approveQueueRows so aprova linhas em preview da campanha certa', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { whatsapp: '5511999990001' });
|
|
const campanha = campanhaComVariantes(db);
|
|
generateCampaignQueue(db, campanha.id);
|
|
const [linha] = listQueue(db, campanha.id);
|
|
|
|
const total = approveQueueRows(db, campanha.id, [linha.id]);
|
|
assert.equal(total, 1);
|
|
assert.equal(listQueue(db, campanha.id, 'approved').length, 1);
|
|
});
|
|
|
|
test('cancelQueueRows cancela e registra motivo', () => {
|
|
const db = openDb(':memory:');
|
|
inserirLead(db, { whatsapp: '5511999990001' });
|
|
const campanha = campanhaComVariantes(db);
|
|
generateCampaignQueue(db, campanha.id);
|
|
const [linha] = listQueue(db, campanha.id);
|
|
|
|
const total = cancelQueueRows(db, campanha.id, [linha.id], 'nao interessa');
|
|
assert.equal(total, 1);
|
|
const cancelada = listQueue(db, campanha.id, 'cancelled')[0];
|
|
assert.equal(cancelada.cancel_reason, 'nao interessa');
|
|
});
|
|
|
|
test('approveQueueRows/cancelQueueRows com lista vazia nao lanca erro', () => {
|
|
const db = openDb(':memory:');
|
|
const campanha = campanhaComVariantes(db);
|
|
assert.equal(approveQueueRows(db, campanha.id, []), 0);
|
|
assert.equal(cancelQueueRows(db, campanha.id, []), 0);
|
|
db.close();
|
|
});
|