From aa46c3da07619cf1326fa534d5da8c011cbf9c5c Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 3 Aug 2026 13:06:43 -0300 Subject: [PATCH] Fix dead manual-send exclusion in campaign candidate query The real manual-send route (routes/outreach.mjs) always inserts with produto='' and lead_id=NULL, so the old single NOT EXISTS predicate (produto = ? AND (lead_id = leads.id OR numero = leads.whatsapp)) could never match a real manual send's row -- the numero branch was unreachable in production even though a prior test fabricated a produto value manual sends never write. Split into two NOT EXISTS clauses: one scoped to produto+lead_id (automatic/campaign sends), one scoped to numero+ origem='manual' with no produto requirement (manual sends). Updated the existing regression test to insert the row exactly like the real route does (produto: '', lead_id: NULL, origem: 'manual'). --- src/outreach/campaign-queue.mjs | 8 +++++++- tests/campaign-queue.test.mjs | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/outreach/campaign-queue.mjs b/src/outreach/campaign-queue.mjs index fbe70de..e648d14 100644 --- a/src/outreach/campaign-queue.mjs +++ b/src/outreach/campaign-queue.mjs @@ -15,7 +15,13 @@ function candidateQuery() { AND NOT EXISTS ( SELECT 1 FROM outreach_sends WHERE outreach_sends.produto = ? AND outreach_sends.status = 'enviado' - AND (outreach_sends.lead_id = leads.id OR outreach_sends.numero = leads.whatsapp) + AND outreach_sends.lead_id = leads.id + ) + AND NOT EXISTS ( + SELECT 1 FROM outreach_sends + WHERE outreach_sends.status = 'enviado' + AND outreach_sends.numero = leads.whatsapp + AND outreach_sends.origem = 'manual' ) AND NOT EXISTS ( SELECT 1 FROM outreach_campaign_queue q diff --git a/tests/campaign-queue.test.mjs b/tests/campaign-queue.test.mjs index d4d2040..e2789b9 100644 --- a/tests/campaign-queue.test.mjs +++ b/tests/campaign-queue.test.mjs @@ -57,12 +57,15 @@ test('generateCampaignQueue exclui lead com envio ja enviado para o mesmo produt db.close(); }); -test('generateCampaignQueue exclui numero com envio manual ja enviado (sem lead_id) para o mesmo produto', () => { +test('generateCampaignQueue exclui numero com envio manual ja enviado (sem lead_id, produto vazio, como o envio manual real grava)', () => { const db = openDb(':memory:'); inserirLead(db, { whatsapp: '5511999990009' }); + // Reproduz exatamente como src/server/routes/outreach.mjs grava um envio + // manual: lead_id NULL, produto '' (nunca o produto da campanha) e + // origem='manual'. A exclusao precisa valer mesmo assim, por numero. db.prepare( `INSERT INTO outreach_sends (lead_id, produto, numero, mensagem_enviada, status, origem) - VALUES (NULL, 'ERP', '5511999990009', 'oi', 'enviado', 'manual')` + VALUES (NULL, '', '5511999990009', 'oi', 'enviado', 'manual')` ).run(); const campanha = campanhaComVariantes(db);