Add client purchase pattern charts
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m9s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m9s
This commit is contained in:
@@ -414,6 +414,35 @@ const getDateOnly = (value) => {
|
||||
return match ? match[1] : null;
|
||||
};
|
||||
|
||||
const WEEKDAY_LABELS = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'];
|
||||
|
||||
const getWeekdayIndex = (value) => {
|
||||
const dateKey = getDateOnly(value);
|
||||
if (!dateKey) return null;
|
||||
|
||||
const date = new Date(`${dateKey}T00:00:00`);
|
||||
if (Number.isNaN(date.getTime())) return null;
|
||||
|
||||
return date.getDay();
|
||||
};
|
||||
|
||||
const getHourFromTimestamp = (value) => {
|
||||
if (!value) return null;
|
||||
|
||||
const rawValue = String(value);
|
||||
const hasTime = /\b\d{1,2}:\d{2}/.test(rawValue);
|
||||
if (!hasTime) return null;
|
||||
|
||||
const date = value instanceof Date ? value : new Date(rawValue);
|
||||
if (!Number.isNaN(date.getTime())) return date.getHours();
|
||||
|
||||
const timeMatch = rawValue.match(/\b(\d{1,2}):\d{2}/);
|
||||
if (!timeMatch) return null;
|
||||
|
||||
const hour = Number(timeMatch[1]);
|
||||
return hour >= 0 && hour <= 23 ? hour : null;
|
||||
};
|
||||
|
||||
const buildRfmSegments = (clients) => {
|
||||
return Object.values(RFM_SEGMENTS).map(segment => {
|
||||
const segmentClients = clients.filter(client => client.segmentKey === segment.key);
|
||||
@@ -910,7 +939,8 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||
nome_vendedor,
|
||||
marketplace,
|
||||
canal_venda,
|
||||
numero_ecommerce
|
||||
numero_ecommerce,
|
||||
created_at
|
||||
FROM identity_orders
|
||||
WHERE ${periodFilters.join(' AND ')}
|
||||
ORDER BY data_pedido_date DESC, COALESCE(NULLIF(pedido_id, ''), data_pedido || '_' || valor_pedido::text) DESC;
|
||||
@@ -923,6 +953,12 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||
|
||||
const groupedOrdersByKey = new Map();
|
||||
const spentByDate = new Map();
|
||||
const weekdayCounts = WEEKDAY_LABELS.map(label => ({ label, value: 0 }));
|
||||
const hourCounts = Array.from({ length: 24 }, (_, hour) => ({
|
||||
label: `${String(hour).padStart(2, '0')}h`,
|
||||
value: 0
|
||||
}));
|
||||
const patternOrderKeys = new Set();
|
||||
let periodSpent = 0;
|
||||
let periodItems = 0;
|
||||
|
||||
@@ -932,6 +968,19 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||
const dateLabel = row.data_pedido || dateKey;
|
||||
const groupKey = getOrderGroupKey(row);
|
||||
|
||||
if (!patternOrderKeys.has(groupKey)) {
|
||||
patternOrderKeys.add(groupKey);
|
||||
const weekdayIndex = getWeekdayIndex(row.data_pedido_date) ?? getWeekdayIndex(row.data_pedido);
|
||||
if (weekdayIndex !== null) {
|
||||
weekdayCounts[weekdayIndex].value += 1;
|
||||
}
|
||||
|
||||
const orderHour = getHourFromTimestamp(row.created_at) ?? getHourFromTimestamp(row.data_pedido);
|
||||
if (orderHour !== null) {
|
||||
hourCounts[orderHour].value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
periodSpent += itemRevenue;
|
||||
periodItems += toNumber(row.quantidade);
|
||||
|
||||
@@ -968,7 +1017,8 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||
nome_vendedor: row.nome_vendedor || '',
|
||||
marketplace: row.marketplace || '',
|
||||
canal_venda: row.canal_venda || '',
|
||||
numero_ecommerce: row.numero_ecommerce || ''
|
||||
numero_ecommerce: row.numero_ecommerce || '',
|
||||
Recebido_Em: row.created_at || ''
|
||||
});
|
||||
});
|
||||
|
||||
@@ -995,6 +1045,8 @@ const getClientDetailsAnalytics = async (clientToken, range = {}) => {
|
||||
periodOrderCount,
|
||||
periodItems,
|
||||
chartData,
|
||||
purchaseWeekdays: weekdayCounts,
|
||||
purchaseHours: hourCounts,
|
||||
groupedOrders
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user