Fix mini sales chart and sales charts previous period calculations
This commit is contained in:
@@ -328,44 +328,74 @@ router.get('/stats/details', async (req, res) => {
|
|||||||
|
|
||||||
const [dailyResults] = await connection.execute(dailyQuery, params);
|
const [dailyResults] = await connection.execute(dailyQuery, params);
|
||||||
|
|
||||||
// Get all previous year data in a single query
|
// Get previous period data using the same logic as main stats endpoint
|
||||||
const prevYearQuery = `
|
let prevWhereClause, prevParams;
|
||||||
|
|
||||||
|
if (timeRange && timeRange !== 'custom') {
|
||||||
|
const prevTimeRange = getPreviousTimeRange(timeRange);
|
||||||
|
const result = getTimeRangeConditions(prevTimeRange);
|
||||||
|
prevWhereClause = result.whereClause;
|
||||||
|
prevParams = result.params;
|
||||||
|
} else {
|
||||||
|
// Custom date range - go back by the same duration
|
||||||
|
const start = new Date(startDate);
|
||||||
|
const end = new Date(endDate);
|
||||||
|
const duration = end.getTime() - start.getTime();
|
||||||
|
|
||||||
|
const prevEnd = new Date(start.getTime() - 1);
|
||||||
|
const prevStart = new Date(prevEnd.getTime() - duration);
|
||||||
|
|
||||||
|
prevWhereClause = 'date_placed >= ? AND date_placed <= ?';
|
||||||
|
prevParams = [prevStart.toISOString(), prevEnd.toISOString()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get previous period daily data
|
||||||
|
const prevQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
DATE(date_placed) as date,
|
DATE(date_placed) as date,
|
||||||
COUNT(*) as prevOrders,
|
COUNT(*) as prevOrders,
|
||||||
SUM(summary_total) as prevRevenue,
|
SUM(summary_total) as prevRevenue,
|
||||||
AVG(summary_total) as prevAvgOrderValue
|
AVG(summary_total) as prevAvgOrderValue
|
||||||
FROM _order
|
FROM _order
|
||||||
WHERE order_status > 15 AND ${whereClause.replace(/date_placed/g, 'DATE_SUB(date_placed, INTERVAL 1 YEAR)')}
|
WHERE order_status > 15 AND ${prevWhereClause}
|
||||||
GROUP BY DATE(date_placed)
|
GROUP BY DATE(date_placed)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const [prevYearResults] = await connection.execute(prevYearQuery, params);
|
const [prevResults] = await connection.execute(prevQuery, prevParams);
|
||||||
|
|
||||||
// Create a map for quick lookup of previous year data
|
// Create a map for quick lookup of previous period data
|
||||||
const prevYearMap = new Map();
|
const prevMap = new Map();
|
||||||
prevYearResults.forEach(prev => {
|
prevResults.forEach(prev => {
|
||||||
const currentYearDate = new Date(prev.date);
|
const key = new Date(prev.date).toISOString().split('T')[0];
|
||||||
currentYearDate.setFullYear(currentYearDate.getFullYear() + 1);
|
prevMap.set(key, prev);
|
||||||
const key = currentYearDate.toISOString().split('T')[0];
|
|
||||||
prevYearMap.set(key, prev);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Combine current and previous year data
|
// For period-to-period comparison, we need to map days by relative position
|
||||||
const statsWithComparison = dailyResults.map(day => {
|
// since dates won't match exactly (e.g., current week vs previous week)
|
||||||
const dayKey = new Date(day.date).toISOString().split('T')[0];
|
const dailyArray = dailyResults.map(day => ({
|
||||||
const prev = prevYearMap.get(dayKey) || { prevOrders: 0, prevRevenue: 0, prevAvgOrderValue: 0 };
|
timestamp: day.date,
|
||||||
|
date: day.date,
|
||||||
|
orders: parseInt(day.orders),
|
||||||
|
revenue: parseFloat(day.revenue),
|
||||||
|
averageOrderValue: parseFloat(day.averageOrderValue || 0),
|
||||||
|
itemCount: parseInt(day.itemCount)
|
||||||
|
}));
|
||||||
|
|
||||||
|
const prevArray = prevResults.map(day => ({
|
||||||
|
orders: parseInt(day.prevOrders),
|
||||||
|
revenue: parseFloat(day.prevRevenue),
|
||||||
|
averageOrderValue: parseFloat(day.prevAvgOrderValue || 0)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Combine current and previous period data by matching relative positions
|
||||||
|
const statsWithComparison = dailyArray.map((day, index) => {
|
||||||
|
const prev = prevArray[index] || { orders: 0, revenue: 0, averageOrderValue: 0 };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timestamp: day.date,
|
...day,
|
||||||
date: day.date,
|
prevOrders: prev.orders,
|
||||||
orders: parseInt(day.orders),
|
prevRevenue: prev.revenue,
|
||||||
revenue: parseFloat(day.revenue),
|
prevAvgOrderValue: prev.averageOrderValue
|
||||||
averageOrderValue: parseFloat(day.averageOrderValue || 0),
|
|
||||||
itemCount: parseInt(day.itemCount),
|
|
||||||
prevOrders: parseInt(prev.prevOrders || 0),
|
|
||||||
prevRevenue: parseFloat(prev.prevRevenue || 0),
|
|
||||||
prevAvgOrderValue: parseFloat(prev.prevAvgOrderValue || 0)
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
6
dashboard/package-lock.json
generated
6
dashboard/package-lock.json
generated
@@ -4058,9 +4058,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001686",
|
"version": "1.0.30001720",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz",
|
||||||
"integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==",
|
"integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -196,13 +196,13 @@ const MiniSalesChart = ({ className = "" }) => {
|
|||||||
daily: true,
|
daily: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.data) {
|
if (!response.stats) {
|
||||||
throw new Error("Invalid response format");
|
throw new Error("Invalid response format");
|
||||||
}
|
}
|
||||||
|
|
||||||
const stats = Array.isArray(response)
|
const stats = Array.isArray(response.stats)
|
||||||
? response
|
? response.stats
|
||||||
: response.stats || [];
|
: [];
|
||||||
|
|
||||||
const processedData = processData(stats);
|
const processedData = processData(stats);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user