Expose shared-number state on lead list and detail queries
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
// exportacoes: o MESMO objeto de filtro que a tela usa para navegar e o que
|
// exportacoes: o MESMO objeto de filtro que a tela usa para navegar e o que
|
||||||
// define quais leads entram num relatorio/exportacao.
|
// define quais leads entram num relatorio/exportacao.
|
||||||
|
|
||||||
import { getWhatsAppVerification } from '../db.mjs';
|
import { getWhatsAppVerification, listSharedNumberGroups } from '../db.mjs';
|
||||||
|
|
||||||
const SORTS = {
|
const SORTS = {
|
||||||
'prioridade:asc': 'prioridade ASC, score DESC, cidade ASC, empresa ASC',
|
'prioridade:asc': 'prioridade ASC, score DESC, cidade ASC, empresa ASC',
|
||||||
@@ -75,6 +75,7 @@ export function listLeads(db, filtro = {}) {
|
|||||||
const orderBy = SORTS[filtro.sort] || SORTS['prioridade:asc'];
|
const orderBy = SORTS[filtro.sort] || SORTS['prioridade:asc'];
|
||||||
|
|
||||||
const total = db.prepare(`SELECT COUNT(*) AS t FROM leads ${whereSql}`).get(...params).t;
|
const total = db.prepare(`SELECT COUNT(*) AS t FROM leads ${whereSql}`).get(...params).t;
|
||||||
|
const sharedIndex = sharedNumberIndex(db);
|
||||||
const rows = db.prepare(
|
const rows = db.prepare(
|
||||||
`SELECT leads.id AS id, empresa, legal_name, whatsapp, ddd, cidade, uf, segmento, segmento_label,
|
`SELECT leads.id AS id, empresa, legal_name, whatsapp, ddd, cidade, uf, segmento, segmento_label,
|
||||||
interesse, cnpj, cnae, score, score_qualidade, score_comercial, classificacao,
|
interesse, cnpj, cnae, score, score_qualidade, score_comercial, classificacao,
|
||||||
@@ -84,14 +85,15 @@ export function listLeads(db, filtro = {}) {
|
|||||||
${whereSql}
|
${whereSql}
|
||||||
ORDER BY ${orderBy}
|
ORDER BY ${orderBy}
|
||||||
LIMIT ? OFFSET ?`
|
LIMIT ? OFFSET ?`
|
||||||
).all(...params, pageSize, (page - 1) * pageSize).map((lead) => withWhatsAppState(db, lead));
|
).all(...params, pageSize, (page - 1) * pageSize)
|
||||||
|
.map((lead) => withSharedNumberState(withWhatsAppState(db, lead), sharedIndex));
|
||||||
|
|
||||||
return { total, page, pageSize, rows };
|
return { total, page, pageSize, rows };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLead(db, id) {
|
export function getLead(db, id) {
|
||||||
const storedLead = db.prepare('SELECT * FROM leads WHERE id = ?').get(id);
|
const storedLead = db.prepare('SELECT * FROM leads WHERE id = ?').get(id);
|
||||||
const lead = storedLead ? withWhatsAppState(db, storedLead) : null;
|
const lead = storedLead ? withSharedNumberState(withWhatsAppState(db, storedLead), sharedNumberIndex(db)) : null;
|
||||||
if (!lead) return null;
|
if (!lead) return null;
|
||||||
|
|
||||||
const exportHistory = db.prepare(
|
const exportHistory = db.prepare(
|
||||||
@@ -142,6 +144,26 @@ function withWhatsAppState(db, lead) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sharedNumberIndex(db) {
|
||||||
|
const index = new Map();
|
||||||
|
for (const group of listSharedNumberGroups(db)) {
|
||||||
|
for (const lead of group.leads) {
|
||||||
|
index.set(lead.id, { total: group.leads.length, liberado: group.liberado });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
function withSharedNumberState(lead, index) {
|
||||||
|
const shared = index.get(lead.id);
|
||||||
|
return {
|
||||||
|
...lead,
|
||||||
|
numero_compartilhado: Boolean(shared),
|
||||||
|
numero_compartilhado_total: shared?.total || 0,
|
||||||
|
numero_compartilhado_liberado: shared?.liberado || false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function countLeads(db, filtro = {}) {
|
export function countLeads(db, filtro = {}) {
|
||||||
const { whereSql, params } = buildLeadFilter(filtro);
|
const { whereSql, params } = buildLeadFilter(filtro);
|
||||||
return db.prepare(`SELECT COUNT(*) AS t FROM leads ${whereSql}`).get(...params).t;
|
return db.prepare(`SELECT COUNT(*) AS t FROM leads ${whereSql}`).get(...params).t;
|
||||||
|
|||||||
@@ -140,3 +140,38 @@ test('lead sem verificacao equivalente permanece nao consultado', async () => {
|
|||||||
}
|
}
|
||||||
db.close();
|
db.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('listagem e detalhe marcam numero compartilhado por mais de um lead', async () => {
|
||||||
|
const { openDb, addSharedNumberOverride } = await import('../src/db.mjs');
|
||||||
|
const { getLead, listLeads } = await import('../src/treatment/queries.mjs');
|
||||||
|
const db = openDb(':memory:');
|
||||||
|
const sharedA = db.prepare(
|
||||||
|
`INSERT INTO leads (dedup_key, empresa, whatsapp, telefone_valido)
|
||||||
|
VALUES ('shared-a', 'Contabilidade Cliente A', '5575999091780', 1)`
|
||||||
|
).run();
|
||||||
|
db.prepare(
|
||||||
|
`INSERT INTO leads (dedup_key, empresa, whatsapp, telefone_valido)
|
||||||
|
VALUES ('shared-b', 'Contabilidade Cliente B', '557599091780', 1)`
|
||||||
|
).run();
|
||||||
|
const solo = db.prepare(
|
||||||
|
`INSERT INTO leads (dedup_key, empresa, whatsapp, telefone_valido)
|
||||||
|
VALUES ('solo', 'Empresa Unica', '5511999990001', 1)`
|
||||||
|
).run();
|
||||||
|
|
||||||
|
const rows = listLeads(db).rows;
|
||||||
|
const shared = rows.find((row) => row.id === Number(sharedA.lastInsertRowid));
|
||||||
|
const unique = rows.find((row) => row.id === Number(solo.lastInsertRowid));
|
||||||
|
assert.equal(shared.numero_compartilhado, true);
|
||||||
|
assert.equal(shared.numero_compartilhado_total, 2);
|
||||||
|
assert.equal(shared.numero_compartilhado_liberado, false);
|
||||||
|
assert.equal(unique.numero_compartilhado, false);
|
||||||
|
assert.equal(unique.numero_compartilhado_total, 0);
|
||||||
|
|
||||||
|
const detail = getLead(db, Number(sharedA.lastInsertRowid));
|
||||||
|
assert.equal(detail.numero_compartilhado, true);
|
||||||
|
|
||||||
|
addSharedNumberOverride(db, '5575999091780', 'revisado');
|
||||||
|
const refreshed = getLead(db, Number(sharedA.lastInsertRowid));
|
||||||
|
assert.equal(refreshed.numero_compartilhado_liberado, true);
|
||||||
|
db.close();
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user