Fix previous period data
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import fetch from 'node-fetch';
|
||||
import { TimeManager } from '../utils/time.utils.js';
|
||||
import { RedisService } from './redis.service.js';
|
||||
import _ from 'lodash';
|
||||
|
||||
const METRIC_IDS = {
|
||||
PLACED_ORDER: 'Y8cqcF',
|
||||
@@ -225,12 +226,24 @@ export class EventsService {
|
||||
metricId: METRIC_IDS.CANCELED_ORDER
|
||||
}),
|
||||
this.getEvents({
|
||||
// Only pass through non-date related params for previous period
|
||||
..._.omit(params, ['timeRange', 'startDate', 'endDate']),
|
||||
metricId: METRIC_IDS.PLACED_ORDER,
|
||||
startDate: prevPeriodStart.toISO(),
|
||||
endDate: prevPeriodEnd.toISO()
|
||||
})
|
||||
]);
|
||||
|
||||
// Add debug logging
|
||||
console.log('[EventsService] Previous period request:', {
|
||||
params: _.omit(params, ['timeRange', 'startDate', 'endDate']),
|
||||
dates: {
|
||||
start: prevPeriodStart.toISO(),
|
||||
end: prevPeriodEnd.toISO()
|
||||
},
|
||||
responseLength: prevPeriodData?.data?.length
|
||||
});
|
||||
|
||||
// Transform all data
|
||||
const transformedOrders = this._transformEvents(orderData.data);
|
||||
const transformedShipped = this._transformEvents(shippedData.data);
|
||||
@@ -1489,15 +1502,51 @@ export class EventsService {
|
||||
...params,
|
||||
startDate: periodStart.toISO(),
|
||||
endDate: periodEnd.toISO(),
|
||||
metricId: METRIC_IDS.PLACED_ORDER
|
||||
metricId: METRIC_IDS.PLACED_ORDER,
|
||||
customFilters: params.metric === 'pre_orders' ? ['equals(event_properties.HasPreorder,true)'] :
|
||||
params.metric === 'local_pickup' ? ['equals(event_properties.LocalPickup,true)'] :
|
||||
params.metric === 'on_hold' ? ['equals(event_properties.IsOnHold,true)'] : undefined
|
||||
}),
|
||||
this.getEvents({
|
||||
metricId: METRIC_IDS.PLACED_ORDER,
|
||||
..._.omit(params, ['timeRange', 'startDate', 'endDate']),
|
||||
startDate: prevPeriodStart.toISO(),
|
||||
endDate: prevPeriodEnd.toISO()
|
||||
endDate: prevPeriodEnd.toISO(),
|
||||
metricId: METRIC_IDS.PLACED_ORDER,
|
||||
timeRange: undefined,
|
||||
isPreviousPeriod: true,
|
||||
cacheKey: `prev_${prevPeriodStart.toISO()}_${prevPeriodEnd.toISO()}`,
|
||||
customFilters: params.metric === 'pre_orders' ? ['equals(event_properties.HasPreorder,true)'] :
|
||||
params.metric === 'local_pickup' ? ['equals(event_properties.LocalPickup,true)'] :
|
||||
params.metric === 'on_hold' ? ['equals(event_properties.IsOnHold,true)'] : undefined
|
||||
})
|
||||
]);
|
||||
|
||||
// Add debug logging for request params and filters
|
||||
console.log('[EventsService] Request details with filters:', {
|
||||
current: {
|
||||
params: {
|
||||
...params,
|
||||
startDate: periodStart.toISO(),
|
||||
endDate: periodEnd.toISO(),
|
||||
customFilters: params.metric === 'pre_orders' ? ['equals(event_properties.HasPreorder,true)'] :
|
||||
params.metric === 'local_pickup' ? ['equals(event_properties.LocalPickup,true)'] :
|
||||
params.metric === 'on_hold' ? ['equals(event_properties.IsOnHold,true)'] : undefined
|
||||
},
|
||||
responseLength: currentResponse?.data?.length
|
||||
},
|
||||
previous: {
|
||||
params: {
|
||||
..._.omit(params, ['timeRange', 'startDate', 'endDate']),
|
||||
startDate: prevPeriodStart.toISO(),
|
||||
endDate: prevPeriodEnd.toISO(),
|
||||
customFilters: params.metric === 'pre_orders' ? ['equals(event_properties.HasPreorder,true)'] :
|
||||
params.metric === 'local_pickup' ? ['equals(event_properties.LocalPickup,true)'] :
|
||||
params.metric === 'on_hold' ? ['equals(event_properties.IsOnHold,true)'] : undefined
|
||||
},
|
||||
responseLength: prevResponse?.data?.length
|
||||
}
|
||||
});
|
||||
|
||||
// Transform events
|
||||
const currentEvents = this._transformEvents(currentResponse.data || []);
|
||||
const prevEvents = this._transformEvents(prevResponse.data || []);
|
||||
@@ -1561,6 +1610,7 @@ export class EventsService {
|
||||
const dateKey = prevDate.toFormat('yyyy-MM-dd');
|
||||
prevDailyStats.set(dateKey, {
|
||||
date: prevDate.toISO(),
|
||||
timestamp: dateKey,
|
||||
revenue: 0,
|
||||
orders: 0,
|
||||
itemCount: 0
|
||||
@@ -1584,31 +1634,43 @@ export class EventsService {
|
||||
dayStats.revenue += totalAmount;
|
||||
dayStats.orders++;
|
||||
dayStats.itemCount += items.length;
|
||||
prevDailyStats.set(dateKey, dayStats);
|
||||
}
|
||||
|
||||
// Map previous period data to current period days based on relative position
|
||||
const prevPeriodDays = Array.from(prevDailyStats.values());
|
||||
const currentPeriodDays = Array.from(dailyStats.values());
|
||||
const daysInPeriod = currentPeriodDays.length;
|
||||
// Map previous period data to current period days
|
||||
const prevPeriodDays = Array.from(prevDailyStats.values()).sort((a, b) => a.date.localeCompare(b.date));
|
||||
const currentPeriodDays = Array.from(dailyStats.values()).sort((a, b) => a.date.localeCompare(b.date));
|
||||
|
||||
for (let i = 0; i < daysInPeriod; i++) {
|
||||
// Add debug logging for data before mapping
|
||||
console.log('[EventsService] Data before mapping:', {
|
||||
currentPeriod: currentPeriodDays.slice(0, 3),
|
||||
previousPeriod: prevPeriodDays.slice(0, 3),
|
||||
currentLength: currentPeriodDays.length,
|
||||
prevLength: prevPeriodDays.length
|
||||
});
|
||||
|
||||
// Map the data using array indices
|
||||
for (let i = 0; i < currentPeriodDays.length && i < prevPeriodDays.length; i++) {
|
||||
const currentDayStats = currentPeriodDays[i];
|
||||
const prevDayStats = prevPeriodDays[i];
|
||||
|
||||
if (prevDayStats) {
|
||||
if (prevDayStats && currentDayStats) {
|
||||
const dayStats = dailyStats.get(currentDayStats.timestamp);
|
||||
dayStats.prevRevenue = prevDayStats.revenue;
|
||||
dayStats.prevOrders = prevDayStats.orders;
|
||||
dayStats.prevItemCount = prevDayStats.itemCount;
|
||||
dayStats.prevAvgOrderValue = prevDayStats.orders > 0 ? prevDayStats.revenue / prevDayStats.orders : 0;
|
||||
if (dayStats) {
|
||||
dayStats.prevRevenue = prevDayStats.revenue;
|
||||
dayStats.prevOrders = prevDayStats.orders;
|
||||
dayStats.prevItemCount = prevDayStats.itemCount;
|
||||
dayStats.prevAvgOrderValue = prevDayStats.orders > 0 ? prevDayStats.revenue / prevDayStats.orders : 0;
|
||||
dailyStats.set(currentDayStats.timestamp, dayStats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log the final daily stats before returning
|
||||
console.log('[EventsService] Final daily stats sample:', {
|
||||
totalDays: dailyStats.size,
|
||||
firstDay: Array.from(dailyStats.values())[0],
|
||||
lastDay: Array.from(dailyStats.values())[dailyStats.size - 1]
|
||||
// Add debug logging for mapped data
|
||||
console.log('[EventsService] Sample of mapped data:', {
|
||||
firstDay: dailyStats.get(currentPeriodDays[0]?.timestamp),
|
||||
lastDay: dailyStats.get(currentPeriodDays[currentPeriodDays.length - 1]?.timestamp),
|
||||
totalDays: dailyStats.size
|
||||
});
|
||||
|
||||
// Convert to array and sort by date
|
||||
|
||||
@@ -131,24 +131,47 @@ export class RedisService {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to generate cache keys
|
||||
_getCacheKey(type, params = {}) {
|
||||
const { timeRange, startDate, endDate, metricId, metric, daily } = params;
|
||||
let key = `klaviyo:${type}`;
|
||||
// Helper to generate cache keys
|
||||
_getCacheKey(type, params = {}) {
|
||||
const {
|
||||
timeRange,
|
||||
startDate,
|
||||
endDate,
|
||||
metricId,
|
||||
metric,
|
||||
daily,
|
||||
cacheKey,
|
||||
isPreviousPeriod
|
||||
} = params;
|
||||
|
||||
if (type === 'stats:details') {
|
||||
key += `:${metric}${daily ? ':daily' : ''}`;
|
||||
}
|
||||
let key = `klaviyo:${type}`;
|
||||
|
||||
if (timeRange) {
|
||||
key += `:${timeRange}${metricId ? `:${metricId}` : ''}`;
|
||||
} else if (startDate && endDate) {
|
||||
key += `:custom:${startDate}:${endDate}${metricId ? `:${metricId}` : ''}`;
|
||||
}
|
||||
|
||||
return key;
|
||||
// Handle "stats:details" for daily or metric-based keys
|
||||
if (type === 'stats:details') {
|
||||
key += `:${metric}${daily ? ':daily' : ''}`;
|
||||
}
|
||||
|
||||
// If a specific cache key is provided, use it (highest priority)
|
||||
if (cacheKey) {
|
||||
key += `:${cacheKey}`;
|
||||
}
|
||||
// Otherwise, build a default cache key
|
||||
else if (timeRange) {
|
||||
key += `:${timeRange}${metricId ? `:${metricId}` : ''}`;
|
||||
if (isPreviousPeriod) {
|
||||
key += ':prev';
|
||||
}
|
||||
} else if (startDate && endDate) {
|
||||
key += `:custom:${startDate}:${endDate}${metricId ? `:${metricId}` : ''}`;
|
||||
if (isPreviousPeriod) {
|
||||
key += ':prev';
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
// Get TTL based on time range
|
||||
_getTTL(timeRange) {
|
||||
const TTL_MAP = {
|
||||
|
||||
@@ -523,53 +523,24 @@ const SalesChart = ({
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Get previous period params
|
||||
const prevPeriodParams = calculatePreviousPeriodDates(
|
||||
params.timeRange,
|
||||
params.startDate,
|
||||
params.endDate
|
||||
);
|
||||
// Fetch data
|
||||
const response = await axios.get('/api/klaviyo/events/stats/details', {
|
||||
params: {
|
||||
...params,
|
||||
metric: 'revenue',
|
||||
daily: true
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch both current and previous period data
|
||||
const [currentResponse, prevResponse] = await Promise.all([
|
||||
axios.get('/api/klaviyo/events/stats/details', {
|
||||
params: {
|
||||
...params,
|
||||
metric: 'revenue',
|
||||
daily: true
|
||||
}
|
||||
}),
|
||||
axios.get('/api/klaviyo/events/stats/details', {
|
||||
params: {
|
||||
metric: 'revenue',
|
||||
daily: true,
|
||||
...(prevPeriodParams || {})
|
||||
}
|
||||
})
|
||||
]);
|
||||
|
||||
if (!currentResponse.data) {
|
||||
if (!response.data) {
|
||||
throw new Error('Invalid response format');
|
||||
}
|
||||
|
||||
// Process the data
|
||||
const currentStats = Array.isArray(currentResponse.data) ? currentResponse.data : currentResponse.data.stats || [];
|
||||
const prevStats = Array.isArray(prevResponse.data) ? prevResponse.data : (prevResponse.data?.stats || []);
|
||||
const currentStats = Array.isArray(response.data) ? response.data : response.data.stats || [];
|
||||
|
||||
// Map previous period data to current period dates
|
||||
const processedStats = currentStats.map((day, index) => {
|
||||
// Find the corresponding previous period day
|
||||
const prevDay = prevStats[index] || {};
|
||||
|
||||
return {
|
||||
...day,
|
||||
prevRevenue: Number(prevDay.revenue || 0),
|
||||
prevOrders: Number(prevDay.orders || 0),
|
||||
prevAvgOrderValue: Number(prevDay.averageOrderValue || (prevDay.orders > 0 ? prevDay.revenue / prevDay.orders : 0))
|
||||
};
|
||||
});
|
||||
|
||||
const processedData = processData(processedStats);
|
||||
// Process the data directly without remapping
|
||||
const processedData = processData(currentStats);
|
||||
const stats = calculateSummaryStats(processedData);
|
||||
|
||||
setData(processedData);
|
||||
|
||||
Reference in New Issue
Block a user