Fix client identity when phone is added
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 58s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 58s
This commit is contained in:
@@ -14,7 +14,37 @@ const PRODUCT_NAME_SQL = `
|
|||||||
ELSE NULLIF(TRIM(regexp_replace(split_part(COALESCE(produto_descricao, 'Unknown'), ' TAMANHO', 1), '${SIZE_SUFFIX_SQL_PATTERN}', '', 'i')), '')
|
ELSE NULLIF(TRIM(regexp_replace(split_part(COALESCE(produto_descricao, 'Unknown'), ' TAMANHO', 1), '${SIZE_SUFFIX_SQL_PATTERN}', '', 'i')), '')
|
||||||
END
|
END
|
||||||
`;
|
`;
|
||||||
const CUSTOMER_KEY_SQL = "COALESCE(NULLIF(cliente_fone, ''), 'name:' || COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido'))";
|
const NORMALIZED_CUSTOMER_NAME_SQL = "NULLIF(LOWER(TRIM(regexp_replace(COALESCE(cliente_nome, ''), '\\s+', ' ', 'g'))), '')";
|
||||||
|
// Phone-less historical rows must follow the later known phone for the same client name.
|
||||||
|
const CUSTOMER_IDENTITY_CTE = `
|
||||||
|
WITH order_identity AS (
|
||||||
|
SELECT
|
||||||
|
orders.*,
|
||||||
|
${NORMALIZED_CUSTOMER_NAME_SQL} as normalized_customer_name
|
||||||
|
FROM orders
|
||||||
|
),
|
||||||
|
customer_phone_by_name AS (
|
||||||
|
SELECT
|
||||||
|
normalized_customer_name,
|
||||||
|
(ARRAY_AGG(NULLIF(cliente_fone, '') ORDER BY data_pedido_date DESC NULLS LAST, id DESC)
|
||||||
|
FILTER (WHERE NULLIF(cliente_fone, '') IS NOT NULL))[1] as canonical_phone
|
||||||
|
FROM order_identity
|
||||||
|
WHERE normalized_customer_name IS NOT NULL
|
||||||
|
GROUP BY normalized_customer_name
|
||||||
|
),
|
||||||
|
identity_orders AS (
|
||||||
|
SELECT
|
||||||
|
order_identity.*,
|
||||||
|
COALESCE(
|
||||||
|
NULLIF(order_identity.cliente_fone, ''),
|
||||||
|
customer_phone_by_name.canonical_phone,
|
||||||
|
'name:' || COALESCE(NULLIF(order_identity.cliente_nome, ''), 'Cliente Desconhecido')
|
||||||
|
) as customer_key
|
||||||
|
FROM order_identity
|
||||||
|
LEFT JOIN customer_phone_by_name USING (normalized_customer_name)
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
const CUSTOMER_KEY_SQL = 'customer_key';
|
||||||
|
|
||||||
const getClientTokenSecret = () => (
|
const getClientTokenSecret = () => (
|
||||||
process.env.CLIENT_TOKEN_SECRET ||
|
process.env.CLIENT_TOKEN_SECRET ||
|
||||||
@@ -102,6 +132,28 @@ const resolveClientToken = async (clientToken) => {
|
|||||||
return result.rows[0]?.customer_key || null;
|
return result.rows[0]?.customer_key || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveCanonicalCustomerKey = async (customerKey) => {
|
||||||
|
const normalizedCustomerKey = String(customerKey || '');
|
||||||
|
if (!normalizedCustomerKey.startsWith('name:')) return customerKey;
|
||||||
|
|
||||||
|
const legacyName = normalizedCustomerKey.slice(5).trim();
|
||||||
|
if (!legacyName) return customerKey;
|
||||||
|
|
||||||
|
const result = await pool.query(`
|
||||||
|
${CUSTOMER_IDENTITY_CTE}
|
||||||
|
SELECT customer_key
|
||||||
|
FROM identity_orders
|
||||||
|
WHERE normalized_customer_name = NULLIF(LOWER(TRIM(regexp_replace($1, '\\s+', ' ', 'g'))), '')
|
||||||
|
ORDER BY
|
||||||
|
NULLIF(cliente_fone, '') IS NOT NULL DESC,
|
||||||
|
data_pedido_date DESC NULLS LAST,
|
||||||
|
id DESC
|
||||||
|
LIMIT 1;
|
||||||
|
`, [legacyName]);
|
||||||
|
|
||||||
|
return result.rows[0]?.customer_key || customerKey;
|
||||||
|
};
|
||||||
|
|
||||||
const normalizeDateParam = (value) => {
|
const normalizeDateParam = (value) => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
|
|
||||||
@@ -605,6 +657,7 @@ const getProductDetailsAnalytics = async (productId, range = {}) => {
|
|||||||
const getClientAnalytics = async (range = {}) => {
|
const getClientAnalytics = async (range = {}) => {
|
||||||
const { params, whereClause } = buildDateFilter(range);
|
const { params, whereClause } = buildDateFilter(range);
|
||||||
const result = await pool.query(`
|
const result = await pool.query(`
|
||||||
|
${CUSTOMER_IDENTITY_CTE}
|
||||||
SELECT
|
SELECT
|
||||||
${CUSTOMER_KEY_SQL} as customer_key,
|
${CUSTOMER_KEY_SQL} as customer_key,
|
||||||
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
||||||
@@ -613,7 +666,7 @@ const getClientAnalytics = async (range = {}) => {
|
|||||||
COALESCE(SUM(quantidade * valor_unitario), 0) as total_spent,
|
COALESCE(SUM(quantidade * valor_unitario), 0) as total_spent,
|
||||||
COUNT(DISTINCT COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text))::int as order_count,
|
COUNT(DISTINCT COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text))::int as order_count,
|
||||||
MAX(data_pedido_date) as last_purchase_date
|
MAX(data_pedido_date) as last_purchase_date
|
||||||
FROM orders
|
FROM identity_orders
|
||||||
${whereClause}
|
${whereClause}
|
||||||
GROUP BY customer_key
|
GROUP BY customer_key
|
||||||
ORDER BY total_spent DESC;
|
ORDER BY total_spent DESC;
|
||||||
@@ -699,10 +752,11 @@ const getOrderGroupKey = (row) => (
|
|||||||
const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||||
const customerKey = await resolveClientToken(clientToken);
|
const customerKey = await resolveClientToken(clientToken);
|
||||||
if (!customerKey) return null;
|
if (!customerKey) return null;
|
||||||
|
const resolvedCustomerKey = await resolveCanonicalCustomerKey(customerKey);
|
||||||
|
|
||||||
const normalizedStart = normalizeDateParam(range.start);
|
const normalizedStart = normalizeDateParam(range.start);
|
||||||
const normalizedEnd = normalizeDateParam(range.end);
|
const normalizedEnd = normalizeDateParam(range.end);
|
||||||
const periodParams = [customerKey];
|
const periodParams = [resolvedCustomerKey];
|
||||||
const periodFilters = [
|
const periodFilters = [
|
||||||
`${CUSTOMER_KEY_SQL} = $1`,
|
`${CUSTOMER_KEY_SQL} = $1`,
|
||||||
'data_pedido_date IS NOT NULL'
|
'data_pedido_date IS NOT NULL'
|
||||||
@@ -720,15 +774,17 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
|||||||
|
|
||||||
const [summaryResult, periodResult] = await Promise.all([
|
const [summaryResult, periodResult] = await Promise.all([
|
||||||
pool.query(`
|
pool.query(`
|
||||||
|
${CUSTOMER_IDENTITY_CTE}
|
||||||
SELECT
|
SELECT
|
||||||
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
||||||
MAX(NULLIF(cliente_fone, '')) as phone,
|
MAX(NULLIF(cliente_fone, '')) as phone,
|
||||||
COUNT(DISTINCT COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text))::int as all_time_order_count
|
COUNT(DISTINCT COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text))::int as all_time_order_count
|
||||||
FROM orders
|
FROM identity_orders
|
||||||
WHERE ${CUSTOMER_KEY_SQL} = $1
|
WHERE ${CUSTOMER_KEY_SQL} = $1
|
||||||
AND data_pedido_date IS NOT NULL;
|
AND data_pedido_date IS NOT NULL;
|
||||||
`, [customerKey]),
|
`, [resolvedCustomerKey]),
|
||||||
pool.query(`
|
pool.query(`
|
||||||
|
${CUSTOMER_IDENTITY_CTE}
|
||||||
SELECT
|
SELECT
|
||||||
cliente_nome,
|
cliente_nome,
|
||||||
cliente_fone,
|
cliente_fone,
|
||||||
@@ -746,7 +802,7 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
|||||||
marketplace,
|
marketplace,
|
||||||
canal_venda,
|
canal_venda,
|
||||||
numero_ecommerce
|
numero_ecommerce
|
||||||
FROM orders
|
FROM identity_orders
|
||||||
WHERE ${periodFilters.join(' AND ')}
|
WHERE ${periodFilters.join(' AND ')}
|
||||||
ORDER BY data_pedido_date DESC, COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text) DESC;
|
ORDER BY data_pedido_date DESC, COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text) DESC;
|
||||||
`, periodParams)
|
`, periodParams)
|
||||||
@@ -877,6 +933,7 @@ const getRfmAnalytics = async (range = {}) => {
|
|||||||
await client.query(`SET LOCAL statement_timeout = '${RFM_QUERY_TIMEOUT_MS}ms'`);
|
await client.query(`SET LOCAL statement_timeout = '${RFM_QUERY_TIMEOUT_MS}ms'`);
|
||||||
|
|
||||||
const periodResult = await client.query(`
|
const periodResult = await client.query(`
|
||||||
|
${CUSTOMER_IDENTITY_CTE}
|
||||||
SELECT
|
SELECT
|
||||||
${CUSTOMER_KEY_SQL} as customer_key,
|
${CUSTOMER_KEY_SQL} as customer_key,
|
||||||
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
||||||
@@ -886,7 +943,7 @@ const getRfmAnalytics = async (range = {}) => {
|
|||||||
COALESCE(SUM(quantidade), 0) as quantity_purchased,
|
COALESCE(SUM(quantidade), 0) as quantity_purchased,
|
||||||
MAX(data_pedido_date) as last_purchase_date,
|
MAX(data_pedido_date) as last_purchase_date,
|
||||||
GREATEST((${periodRecencyReferenceDate} - MAX(data_pedido_date))::int, 0) as recency_days
|
GREATEST((${periodRecencyReferenceDate} - MAX(data_pedido_date))::int, 0) as recency_days
|
||||||
FROM orders
|
FROM identity_orders
|
||||||
${whereClause}
|
${whereClause}
|
||||||
GROUP BY customer_key
|
GROUP BY customer_key
|
||||||
ORDER BY monetary DESC;
|
ORDER BY monetary DESC;
|
||||||
@@ -926,7 +983,8 @@ const getRfmAnalytics = async (range = {}) => {
|
|||||||
const customerKeysParam = `$${historyParams.push(periodCustomerKeys)}::text[]`;
|
const customerKeysParam = `$${historyParams.push(periodCustomerKeys)}::text[]`;
|
||||||
|
|
||||||
const historyResult = await client.query(`
|
const historyResult = await client.query(`
|
||||||
WITH customer_history AS (
|
${CUSTOMER_IDENTITY_CTE},
|
||||||
|
customer_history AS (
|
||||||
SELECT
|
SELECT
|
||||||
${CUSTOMER_KEY_SQL} as customer_key,
|
${CUSTOMER_KEY_SQL} as customer_key,
|
||||||
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
MAX(COALESCE(NULLIF(cliente_nome, ''), 'Cliente Desconhecido')) as name,
|
||||||
@@ -936,7 +994,7 @@ const getRfmAnalytics = async (range = {}) => {
|
|||||||
COALESCE(SUM(quantidade), 0) as quantity_purchased,
|
COALESCE(SUM(quantidade), 0) as quantity_purchased,
|
||||||
MAX(data_pedido_date) as last_purchase_date,
|
MAX(data_pedido_date) as last_purchase_date,
|
||||||
GREATEST((${recencyReferenceDate} - MAX(data_pedido_date))::int, 0) as recency_days
|
GREATEST((${recencyReferenceDate} - MAX(data_pedido_date))::int, 0) as recency_days
|
||||||
FROM orders
|
FROM identity_orders
|
||||||
WHERE ${historyFilters.join(' AND ')}
|
WHERE ${historyFilters.join(' AND ')}
|
||||||
GROUP BY customer_key
|
GROUP BY customer_key
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -568,6 +568,50 @@ test('getClientAnalytics returns opaque client tokens', async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getClientAnalytics groups phone-less history through the customer identity CTE', async () => {
|
||||||
|
const originalQuery = pool.query;
|
||||||
|
const calls = [];
|
||||||
|
|
||||||
|
pool.query = async (sql, params = []) => {
|
||||||
|
calls.push({ sql, params });
|
||||||
|
|
||||||
|
if (sql.includes('INSERT INTO client_identity_tokens')) {
|
||||||
|
return { rows: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
customer_key: '(16) 99999-9999',
|
||||||
|
name: 'Cliente Com Historico',
|
||||||
|
phone: '(16) 99999-9999',
|
||||||
|
quantity_purchased: 1002,
|
||||||
|
total_spent: 50000,
|
||||||
|
order_count: 250,
|
||||||
|
last_purchase_date: '2026-06-15'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const clients = await getClientAnalytics({ start: '2026-05-01', end: '2026-06-15' });
|
||||||
|
|
||||||
|
assert.equal(calls.length, 2);
|
||||||
|
assert.equal(clients.length, 1);
|
||||||
|
assert.equal(clients[0].customerKey, '(16) 99999-9999');
|
||||||
|
assert.equal(clients[0].phone, '(16) 99999-9999');
|
||||||
|
assert.match(calls[0].sql, /WITH order_identity AS/);
|
||||||
|
assert.match(calls[0].sql, /customer_phone_by_name AS/);
|
||||||
|
assert.match(calls[0].sql, /ARRAY_AGG\(NULLIF\(cliente_fone, ''\) ORDER BY data_pedido_date DESC NULLS LAST, id DESC\)/);
|
||||||
|
assert.match(calls[0].sql, /NULLIF\(order_identity\.cliente_fone, ''\),\s+customer_phone_by_name\.canonical_phone/s);
|
||||||
|
assert.match(calls[0].sql, /FROM identity_orders/);
|
||||||
|
assert.match(calls[0].sql, /GROUP BY customer_key/);
|
||||||
|
} finally {
|
||||||
|
pool.query = originalQuery;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('getClientFilterOptions returns distinct date-scoped order metadata options', async () => {
|
test('getClientFilterOptions returns distinct date-scoped order metadata options', async () => {
|
||||||
const originalQuery = pool.query;
|
const originalQuery = pool.query;
|
||||||
const calls = [];
|
const calls = [];
|
||||||
@@ -612,7 +656,7 @@ test('getClientFilterOptions returns distinct date-scoped order metadata options
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getClientDetailsAnalytics fetches only the tokenized client and period rows', async () => {
|
test('getClientDetailsAnalytics resolves legacy name tokens to the canonical phone client', async () => {
|
||||||
const originalQuery = pool.query;
|
const originalQuery = pool.query;
|
||||||
const calls = [];
|
const calls = [];
|
||||||
const clientToken = createClientToken('name:Cliente Sem Fone');
|
const clientToken = createClientToken('name:Cliente Sem Fone');
|
||||||
@@ -624,11 +668,15 @@ test('getClientDetailsAnalytics fetches only the tokenized client and period row
|
|||||||
return { rows: [{ customer_key: 'name:Cliente Sem Fone' }] };
|
return { rows: [{ customer_key: 'name:Cliente Sem Fone' }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sql.includes('SELECT customer_key') && sql.includes('FROM identity_orders')) {
|
||||||
|
return { rows: [{ customer_key: '(16) 99999-9999' }] };
|
||||||
|
}
|
||||||
|
|
||||||
if (sql.includes('all_time_order_count')) {
|
if (sql.includes('all_time_order_count')) {
|
||||||
return {
|
return {
|
||||||
rows: [{
|
rows: [{
|
||||||
name: 'Cliente Sem Fone',
|
name: 'Cliente Sem Fone',
|
||||||
phone: null,
|
phone: '(16) 99999-9999',
|
||||||
all_time_order_count: 3
|
all_time_order_count: 3
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
@@ -638,7 +686,7 @@ test('getClientDetailsAnalytics fetches only the tokenized client and period row
|
|||||||
rows: [
|
rows: [
|
||||||
{
|
{
|
||||||
cliente_nome: 'Cliente Sem Fone',
|
cliente_nome: 'Cliente Sem Fone',
|
||||||
cliente_fone: null,
|
cliente_fone: '',
|
||||||
data_pedido: '10-06-2026',
|
data_pedido: '10-06-2026',
|
||||||
data_pedido_date: '2026-06-10',
|
data_pedido_date: '2026-06-10',
|
||||||
valor_pedido: 25,
|
valor_pedido: 25,
|
||||||
@@ -650,7 +698,7 @@ test('getClientDetailsAnalytics fetches only the tokenized client and period row
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cliente_nome: 'Cliente Sem Fone',
|
cliente_nome: 'Cliente Sem Fone',
|
||||||
cliente_fone: null,
|
cliente_fone: '(16) 99999-9999',
|
||||||
data_pedido: '10-06-2026',
|
data_pedido: '10-06-2026',
|
||||||
data_pedido_date: '2026-06-10',
|
data_pedido_date: '2026-06-10',
|
||||||
valor_pedido: 25,
|
valor_pedido: 25,
|
||||||
@@ -667,16 +715,19 @@ test('getClientDetailsAnalytics fetches only the tokenized client and period row
|
|||||||
try {
|
try {
|
||||||
const details = await getClientDetailsAnalytics(clientToken, { start: '2026-06-01', end: '2026-06-15' });
|
const details = await getClientDetailsAnalytics(clientToken, { start: '2026-06-01', end: '2026-06-15' });
|
||||||
|
|
||||||
assert.equal(calls.length, 3);
|
assert.equal(calls.length, 4);
|
||||||
assert.match(calls[0].sql, /FROM client_identity_tokens/);
|
assert.match(calls[0].sql, /FROM client_identity_tokens/);
|
||||||
assert.deepEqual(calls[0].params, [clientToken]);
|
assert.deepEqual(calls[0].params, [clientToken]);
|
||||||
assert.match(calls[1].sql, /WHERE COALESCE\(NULLIF\(cliente_fone, ''\), 'name:' \|\| COALESCE\(NULLIF\(cliente_nome, ''\), 'Cliente Desconhecido'\)\) = \$1/);
|
assert.match(calls[1].sql, /SELECT customer_key/);
|
||||||
assert.deepEqual(calls[1].params, ['name:Cliente Sem Fone']);
|
assert.deepEqual(calls[1].params, ['Cliente Sem Fone']);
|
||||||
assert.match(calls[2].sql, /data_pedido_date >= \$2::date/);
|
assert.match(calls[2].sql, /FROM identity_orders/);
|
||||||
assert.match(calls[2].sql, /data_pedido_date <= \$3::date/);
|
assert.match(calls[2].sql, /WHERE customer_key = \$1/);
|
||||||
assert.deepEqual(calls[2].params, ['name:Cliente Sem Fone', '2026-06-01', '2026-06-15']);
|
assert.deepEqual(calls[2].params, ['(16) 99999-9999']);
|
||||||
|
assert.match(calls[3].sql, /data_pedido_date >= \$2::date/);
|
||||||
|
assert.match(calls[3].sql, /data_pedido_date <= \$3::date/);
|
||||||
|
assert.deepEqual(calls[3].params, ['(16) 99999-9999', '2026-06-01', '2026-06-15']);
|
||||||
assert.equal(details.clientName, 'Cliente Sem Fone');
|
assert.equal(details.clientName, 'Cliente Sem Fone');
|
||||||
assert.equal(details.clientPhone, '');
|
assert.equal(details.clientPhone, '(16) 99999-9999');
|
||||||
assert.equal(details.allTimeOrderCount, 3);
|
assert.equal(details.allTimeOrderCount, 3);
|
||||||
assert.equal(details.periodSpent, 25);
|
assert.equal(details.periodSpent, 25);
|
||||||
assert.equal(details.periodItems, 3);
|
assert.equal(details.periodItems, 3);
|
||||||
@@ -807,7 +858,8 @@ test('getRfmAnalytics classifies period buyers by history through the selected r
|
|||||||
|
|
||||||
assert.match(calls[1].sql, /SET LOCAL statement_timeout/);
|
assert.match(calls[1].sql, /SET LOCAL statement_timeout/);
|
||||||
assert.deepEqual(selectCalls[0].params, ['2026-06-09', '2026-06-15']);
|
assert.deepEqual(selectCalls[0].params, ['2026-06-09', '2026-06-15']);
|
||||||
assert.doesNotMatch(selectCalls[0].sql, /cliente_fone IS NOT NULL/);
|
assert.doesNotMatch(selectCalls[0].sql, /WHERE\s+cliente_fone IS NOT NULL/);
|
||||||
|
assert.match(selectCalls[0].sql, /FROM identity_orders/);
|
||||||
assert.match(selectCalls[1].sql, /\(\$1::date - MAX\(data_pedido_date\)\)::int/);
|
assert.match(selectCalls[1].sql, /\(\$1::date - MAX\(data_pedido_date\)\)::int/);
|
||||||
assert.match(selectCalls[1].sql, /data_pedido_date <= \$1::date/);
|
assert.match(selectCalls[1].sql, /data_pedido_date <= \$1::date/);
|
||||||
assert.match(selectCalls[1].sql, /WHEN frequency <= 1 THEN 1/);
|
assert.match(selectCalls[1].sql, /WHEN frequency <= 1 THEN 1/);
|
||||||
@@ -815,7 +867,8 @@ test('getRfmAnalytics classifies period buyers by history through the selected r
|
|||||||
assert.doesNotMatch(selectCalls[1].sql, /PERCENT_RANK\(\) OVER \(ORDER BY frequency\)/);
|
assert.doesNotMatch(selectCalls[1].sql, /PERCENT_RANK\(\) OVER \(ORDER BY frequency\)/);
|
||||||
assert.match(selectCalls[1].sql, /PERCENT_RANK\(\) OVER \(ORDER BY monetary\)/);
|
assert.match(selectCalls[1].sql, /PERCENT_RANK\(\) OVER \(ORDER BY monetary\)/);
|
||||||
assert.match(selectCalls[1].sql, /customer_key = ANY\(\$2::text\[\]\)/);
|
assert.match(selectCalls[1].sql, /customer_key = ANY\(\$2::text\[\]\)/);
|
||||||
assert.doesNotMatch(selectCalls[1].sql, /cliente_fone IS NOT NULL/);
|
assert.doesNotMatch(selectCalls[1].sql, /WHERE\s+cliente_fone IS NOT NULL/);
|
||||||
|
assert.match(selectCalls[1].sql, /FROM identity_orders/);
|
||||||
assert.deepEqual(selectCalls[1].params, ['2026-06-15', ['1', '4', 'name:Cliente Sem Fone']]);
|
assert.deepEqual(selectCalls[1].params, ['2026-06-15', ['1', '4', 'name:Cliente Sem Fone']]);
|
||||||
assert.deepEqual(selectCalls[2].params, ['2026-06-14', '2026-06-14']);
|
assert.deepEqual(selectCalls[2].params, ['2026-06-14', '2026-06-14']);
|
||||||
assert.deepEqual(selectCalls[3].params, ['2026-06-14', ['1', '4', 'name:Cliente Sem Fone']]);
|
assert.deepEqual(selectCalls[3].params, ['2026-06-14', ['1', '4', 'name:Cliente Sem Fone']]);
|
||||||
|
|||||||
Reference in New Issue
Block a user