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.
|
||||
`
|
||||
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');
|
||||
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