Fix duplicate top campaign clients by phone
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m22s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m22s
This commit is contained in:
@@ -25,24 +25,6 @@ const WHATSAPP_CUSTOMER_PHONE_SQL = `
|
|||||||
ELSE ${NORMALIZED_CUSTOMER_PHONE_SQL}
|
ELSE ${NORMALIZED_CUSTOMER_PHONE_SQL}
|
||||||
END
|
END
|
||||||
`;
|
`;
|
||||||
const CANONICAL_CAMPAIGN_CUSTOMER_NAME_SQL = `
|
|
||||||
NULLIF(TRIM(regexp_replace(
|
|
||||||
regexp_replace(
|
|
||||||
regexp_replace(
|
|
||||||
regexp_replace(LOWER(COALESCE(cliente_nome, '')), '[^[:alnum:][:space:]]+', ' ', 'g'),
|
|
||||||
'(^|[[:space:]])[0-9]{2,14}([[:space:]]|$)',
|
|
||||||
' ',
|
|
||||||
'g'
|
|
||||||
),
|
|
||||||
'(^|[[:space:]])(ltda|me|eireli|epp)([[:space:]]|$)',
|
|
||||||
' ',
|
|
||||||
'g'
|
|
||||||
),
|
|
||||||
'[[:space:]]+',
|
|
||||||
' ',
|
|
||||||
'g'
|
|
||||||
)), '')
|
|
||||||
`;
|
|
||||||
const CUSTOMER_IDENTITY_CTE = `
|
const CUSTOMER_IDENTITY_CTE = `
|
||||||
WITH customer_phone_by_name AS (
|
WITH customer_phone_by_name AS (
|
||||||
SELECT
|
SELECT
|
||||||
@@ -177,7 +159,6 @@ const getTopClientsForCampaign = async ({ days, limit, start, end } = {}) => {
|
|||||||
WITH campaign_orders AS (
|
WITH campaign_orders AS (
|
||||||
SELECT
|
SELECT
|
||||||
orders.*,
|
orders.*,
|
||||||
${CANONICAL_CAMPAIGN_CUSTOMER_NAME_SQL} as canonical_customer_name,
|
|
||||||
${WHATSAPP_CUSTOMER_PHONE_SQL} as whatsapp_phone
|
${WHATSAPP_CUSTOMER_PHONE_SQL} as whatsapp_phone
|
||||||
FROM orders
|
FROM orders
|
||||||
)
|
)
|
||||||
@@ -199,7 +180,9 @@ const getTopClientsForCampaign = async ({ days, limit, start, end } = {}) => {
|
|||||||
WHERE data_pedido_date >= $1::date
|
WHERE data_pedido_date >= $1::date
|
||||||
AND data_pedido_date <= $2::date
|
AND data_pedido_date <= $2::date
|
||||||
AND whatsapp_phone IS NOT NULL
|
AND whatsapp_phone IS NOT NULL
|
||||||
GROUP BY COALESCE(canonical_customer_name, whatsapp_phone)
|
-- A campaign recipient is a WhatsApp destination, so each normalized
|
||||||
|
-- phone number must produce exactly one exported customer.
|
||||||
|
GROUP BY whatsapp_phone
|
||||||
ORDER BY total_gasto DESC
|
ORDER BY total_gasto DESC
|
||||||
LIMIT $3;
|
LIMIT $3;
|
||||||
`, [range.start, range.end, normalizedLimit]);
|
`, [range.start, range.end, normalizedLimit]);
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ test('getTopClientsForCampaign returns top clients for an explicit date range',
|
|||||||
|
|
||||||
assert.equal(queries.length, 1);
|
assert.equal(queries.length, 1);
|
||||||
assert.deepEqual(queries[0].params, ['2026-06-28', '2026-07-27', 1000]);
|
assert.deepEqual(queries[0].params, ['2026-06-28', '2026-07-27', 1000]);
|
||||||
assert.match(queries[0].sql, /GROUP BY COALESCE\(canonical_customer_name, whatsapp_phone\)/);
|
assert.match(queries[0].sql, /GROUP BY whatsapp_phone/);
|
||||||
|
assert.doesNotMatch(queries[0].sql, /GROUP BY COALESCE\(canonical_customer_name, whatsapp_phone\)/);
|
||||||
assert.match(queries[0].sql, /ARRAY_AGG\(DISTINCT whatsapp_phone\)/);
|
assert.match(queries[0].sql, /ARRAY_AGG\(DISTINCT whatsapp_phone\)/);
|
||||||
assert.match(queries[0].sql, /ORDER BY total_gasto DESC/);
|
assert.match(queries[0].sql, /ORDER BY total_gasto DESC/);
|
||||||
});
|
});
|
||||||
@@ -95,7 +96,7 @@ test('getTopClientsForCampaign derives an inclusive 30 day range from the end da
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getTopClientsForCampaign normalizes phones and ranks one row per canonical client name', async () => {
|
test('getTopClientsForCampaign normalizes phones and groups one row per WhatsApp number', async () => {
|
||||||
await withCampaignService(async () => ({ rows: [] }), async ({ getTopClientsForCampaign }, queries) => {
|
await withCampaignService(async () => ({ rows: [] }), async ({ getTopClientsForCampaign }, queries) => {
|
||||||
await getTopClientsForCampaign({
|
await getTopClientsForCampaign({
|
||||||
days: '30',
|
days: '30',
|
||||||
@@ -105,6 +106,6 @@ test('getTopClientsForCampaign normalizes phones and ranks one row per canonical
|
|||||||
assert.match(queries[0].sql, /regexp_replace\(COALESCE\(cliente_fone, ''\), '\\D', '', 'g'\)/);
|
assert.match(queries[0].sql, /regexp_replace\(COALESCE\(cliente_fone, ''\), '\\D', '', 'g'\)/);
|
||||||
assert.match(queries[0].sql, /WHEN length\(/);
|
assert.match(queries[0].sql, /WHEN length\(/);
|
||||||
assert.match(queries[0].sql, /'55' \|\|/);
|
assert.match(queries[0].sql, /'55' \|\|/);
|
||||||
assert.match(queries[0].sql, /canonical_customer_name/);
|
assert.match(queries[0].sql, /GROUP BY whatsapp_phone/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user