Fix RFV period buyers with historical scoring
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m34s

This commit is contained in:
Cauê Faleiros
2026-06-17 15:07:59 -03:00
parent 10c69457ba
commit 3a907b0743
6 changed files with 89 additions and 48 deletions

View File

@@ -191,28 +191,30 @@ test('buildRfmClients scores segments from RFM history when period totals are sm
assert.equal(yesterdayBuyer.monetaryScore, 3);
});
test('getRfmAnalytics groups period buyers by their RFM tag before the selected period', async () => {
test('getRfmAnalytics classifies period buyers by history through the selected range end', async () => {
const originalQuery = pool.query;
const calls = [];
pool.query = async (sql, params) => {
calls.push({ sql, params });
const isHistoryQuery = sql.includes('recency_days');
const endDate = params[0];
const referenceDate = params[0];
if (isHistoryQuery) {
return {
rows: [
{
customer_key: '1',
name: 'Cliente Ontem',
phone: '1',
monetary: 5000,
frequency: 20,
quantity_purchased: 20,
last_purchase_date: '2026-06-14',
recency_days: endDate === '2026-06-13' ? 0 : 1
recency_days: referenceDate === '2026-06-14' ? 0 : 1
},
{
customer_key: '2',
name: 'Cliente Antigo',
phone: '2',
monetary: 50,
@@ -222,6 +224,7 @@ test('getRfmAnalytics groups period buyers by their RFM tag before the selected
recency_days: 164
},
{
customer_key: '3',
name: 'Cliente Medio',
phone: '3',
monetary: 100,
@@ -229,6 +232,16 @@ test('getRfmAnalytics groups period buyers by their RFM tag before the selected
quantity_purchased: 2,
last_purchase_date: '2026-03-01',
recency_days: 105
},
{
customer_key: 'name:Cliente Sem Fone',
name: 'Cliente Sem Fone',
phone: null,
monetary: 1000,
frequency: 10,
quantity_purchased: 10,
last_purchase_date: '2026-06-14',
recency_days: 1
}
]
};
@@ -237,6 +250,7 @@ test('getRfmAnalytics groups period buyers by their RFM tag before the selected
return {
rows: [
{
customer_key: '1',
name: 'Cliente Ontem',
phone: '1',
monetary: 100,
@@ -245,12 +259,22 @@ test('getRfmAnalytics groups period buyers by their RFM tag before the selected
last_purchase_date: '2026-06-14'
},
{
customer_key: '4',
name: 'Cliente Novo no Periodo',
phone: '4',
monetary: 25,
frequency: 1,
quantity_purchased: 1,
last_purchase_date: '2026-06-14'
},
{
customer_key: 'name:Cliente Sem Fone',
name: 'Cliente Sem Fone',
phone: null,
monetary: 30,
frequency: 1,
quantity_purchased: 1,
last_purchase_date: '2026-06-14'
}
]
};
@@ -261,18 +285,26 @@ test('getRfmAnalytics groups period buyers by their RFM tag before the selected
const yesterday = await getRfmAnalytics({ start: '2026-06-14', end: '2026-06-14' });
assert.deepEqual(calls[0].params, ['2026-06-09', '2026-06-15']);
assert.doesNotMatch(calls[0].sql, /cliente_fone IS NOT NULL/);
assert.match(calls[1].sql, /\(\$1::date - MAX\(data_pedido_date\)\)::int/);
assert.match(calls[1].sql, /data_pedido_date <= \$1::date/);
assert.deepEqual(calls[1].params, ['2026-06-08']);
assert.doesNotMatch(calls[1].sql, /cliente_fone IS NOT NULL/);
assert.deepEqual(calls[1].params, ['2026-06-15']);
assert.deepEqual(calls[2].params, ['2026-06-14', '2026-06-14']);
assert.deepEqual(calls[3].params, ['2026-06-13']);
assert.deepEqual(calls[3].params, ['2026-06-14']);
assert.equal(sevenDays.clients[0].segmentKey, 'champions');
assert.equal(yesterday.clients[0].segmentKey, 'champions');
assert.equal(yesterday.clients[0].frequency, 1);
assert.equal(yesterday.clients[0].monetary, 100);
assert.equal(yesterday.clients.length, 2);
assert.equal(yesterday.clients.length, 3);
assert.ok(!yesterday.clients.some(client => client.phone === '2'));
assert.ok(yesterday.clients.some(client => client.phone === '4' && client.segmentKey === 'new_customers'));
assert.ok(yesterday.clients.some(client => (
client.customerKey === 'name:Cliente Sem Fone' &&
client.phone === '' &&
client.segmentKey === 'champions' &&
client.monetary === 30
)));
} finally {
pool.query = originalQuery;
}