Add campaign outreach schema (migration v8)
This commit is contained in:
+79
@@ -238,6 +238,85 @@ const MIGRATIONS = [
|
|||||||
// usar placeholders resolvidos por lead: {empresa}, {produto}, {cidade}, etc.
|
// usar placeholders resolvidos por lead: {empresa}, {produto}, {cidade}, etc.
|
||||||
`
|
`
|
||||||
ALTER TABLE message_templates ADD COLUMN template_waba_variaveis_json TEXT NOT NULL DEFAULT '[]';
|
ALTER TABLE message_templates ADD COLUMN template_waba_variaveis_json TEXT NOT NULL DEFAULT '[]';
|
||||||
|
`,
|
||||||
|
// v8 — campanhas de outreach com catalogo dinamico (a Comercial tem 57
|
||||||
|
// segmentos e 4 produtos, catalogo fixo em codigo nao cabe nessa escala:
|
||||||
|
// o operador cria a campanha pela tela). Roda ao lado do runOutreachBatch
|
||||||
|
// existente (run.mjs) sem substitui-lo. outreach_opt_out e novo aqui (nao
|
||||||
|
// existia antes): uma fila que recontata o mesmo lead ao longo de semanas
|
||||||
|
// precisa checar quem ja pediu pra parar.
|
||||||
|
`
|
||||||
|
CREATE TABLE outreach_campaigns (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
nome TEXT NOT NULL,
|
||||||
|
produto TEXT NOT NULL,
|
||||||
|
segmentos_json TEXT NOT NULL DEFAULT '[]',
|
||||||
|
status TEXT NOT NULL DEFAULT 'rascunho',
|
||||||
|
pause_reason TEXT,
|
||||||
|
limite_diario_atual INTEGER NOT NULL DEFAULT 10,
|
||||||
|
limite_diario_teto INTEGER NOT NULL DEFAULT 80,
|
||||||
|
semana_iniciada_em TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_campaign_variants (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
campaign_id INTEGER NOT NULL REFERENCES outreach_campaigns(id),
|
||||||
|
code TEXT NOT NULL,
|
||||||
|
mensagem TEXT NOT NULL,
|
||||||
|
ativo INTEGER NOT NULL DEFAULT 1
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_campaign_variants_campaign ON outreach_campaign_variants(campaign_id);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_campaign_queue (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
campaign_id INTEGER NOT NULL REFERENCES outreach_campaigns(id),
|
||||||
|
lead_id INTEGER NOT NULL REFERENCES leads(id),
|
||||||
|
variant_id INTEGER NOT NULL REFERENCES outreach_campaign_variants(id),
|
||||||
|
segmento TEXT NOT NULL DEFAULT '',
|
||||||
|
numero TEXT NOT NULL,
|
||||||
|
rendered_message TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'preview',
|
||||||
|
cancel_reason TEXT,
|
||||||
|
outreach_send_id INTEGER REFERENCES outreach_sends(id),
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_campaign_queue_campaign_status ON outreach_campaign_queue(campaign_id, status);
|
||||||
|
CREATE INDEX idx_campaign_queue_lead ON outreach_campaign_queue(lead_id);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_lead_states (
|
||||||
|
lead_id INTEGER PRIMARY KEY REFERENCES leads(id),
|
||||||
|
stage TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_stage_events (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
lead_id INTEGER NOT NULL REFERENCES leads(id),
|
||||||
|
campaign_id INTEGER REFERENCES outreach_campaigns(id),
|
||||||
|
stage TEXT NOT NULL,
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_stage_events_lead ON outreach_stage_events(lead_id);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_appointments (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
lead_id INTEGER NOT NULL REFERENCES leads(id),
|
||||||
|
kind TEXT NOT NULL,
|
||||||
|
scheduled_at TEXT,
|
||||||
|
note TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_appointments_lead ON outreach_appointments(lead_id);
|
||||||
|
|
||||||
|
CREATE TABLE outreach_opt_out (
|
||||||
|
numero TEXT PRIMARY KEY,
|
||||||
|
motivo TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
`
|
`
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -126,3 +126,21 @@ test('seeds de segments, municipios e geo_cache', () => {
|
|||||||
assert.equal(bbox.provider, 'config-legacy');
|
assert.equal(bbox.provider, 'config-legacy');
|
||||||
db.close();
|
db.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('migracao v8 cria as tabelas de campanha de outreach', () => {
|
||||||
|
const db = openDb(':memory:');
|
||||||
|
const tabelas = db.prepare(
|
||||||
|
`SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'outreach_%'`
|
||||||
|
).all().map((r) => r.name);
|
||||||
|
for (const nome of [
|
||||||
|
'outreach_campaigns', 'outreach_campaign_variants', 'outreach_campaign_queue',
|
||||||
|
'outreach_lead_states', 'outreach_stage_events', 'outreach_appointments', 'outreach_opt_out'
|
||||||
|
]) {
|
||||||
|
assert.ok(tabelas.includes(nome), `tabela ${nome} deveria existir`);
|
||||||
|
}
|
||||||
|
db.prepare(`INSERT INTO outreach_campaigns (nome, produto, segmentos_json) VALUES ('Teste', 'ERP', '["oficinas"]')`).run();
|
||||||
|
const campanha = db.prepare('SELECT * FROM outreach_campaigns').get();
|
||||||
|
assert.equal(campanha.status, 'rascunho');
|
||||||
|
assert.equal(campanha.limite_diario_atual, 10);
|
||||||
|
db.close();
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user