Add/fix refunds/cancellation reasons
This commit is contained in:
@@ -1290,10 +1290,10 @@ export class EventsService {
|
|||||||
|
|
||||||
// Transform and flatten the events into a single array
|
// Transform and flatten the events into a single array
|
||||||
const allEvents = [];
|
const allEvents = [];
|
||||||
results.forEach((result, index) => {
|
results.forEach((result) => {
|
||||||
const metricId = metrics[index];
|
if (result && Array.isArray(result.data)) {
|
||||||
const events = result.data || [];
|
allEvents.push(...result.data);
|
||||||
allEvents.push(...events);
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sort all events by datetime in descending order
|
// Sort all events by datetime in descending order
|
||||||
@@ -1303,12 +1303,22 @@ export class EventsService {
|
|||||||
return dateB - dateA;
|
return dateB - dateA;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
const result = {
|
||||||
data: allEvents,
|
data: allEvents,
|
||||||
meta: {
|
meta: {
|
||||||
total_count: allEvents.length
|
total_count: allEvents.length
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Cache the result
|
||||||
|
try {
|
||||||
|
const ttl = this.redisService._getTTL(timeRange);
|
||||||
|
await this.redisService.set(`${cacheKey}:feed`, result, ttl);
|
||||||
|
} catch (cacheError) {
|
||||||
|
console.warn('[EventsService] Cache set error:', cacheError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[EventsService] Error in batch metrics:', error);
|
console.error('[EventsService] Error in batch metrics:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -1540,6 +1550,7 @@ export class EventsService {
|
|||||||
|
|
||||||
// Transform events
|
// Transform events
|
||||||
const transformedEvents = this._transformEvents(currentEvents.data || []);
|
const transformedEvents = this._transformEvents(currentEvents.data || []);
|
||||||
|
console.log(`[EventsService] Processing ${transformedEvents.length} ${metric}`);
|
||||||
|
|
||||||
// Initialize daily stats map with all dates in range using TimeManager's day start
|
// Initialize daily stats map with all dates in range using TimeManager's day start
|
||||||
const dailyStats = new Map();
|
const dailyStats = new Map();
|
||||||
@@ -1557,35 +1568,59 @@ export class EventsService {
|
|||||||
currentDate = this.timeManager.getDayStart(currentDate.plus({ days: 1 }));
|
currentDate = this.timeManager.getDayStart(currentDate.plus({ days: 1 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process events
|
// Aggregate all reasons and items for the entire period
|
||||||
|
const periodStats = {
|
||||||
|
total: 0,
|
||||||
|
count: 0,
|
||||||
|
reasons: {},
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// Process current period events
|
||||||
for (const event of transformedEvents) {
|
for (const event of transformedEvents) {
|
||||||
const datetime = this.timeManager.toDateTime(event.attributes?.datetime);
|
const datetime = this.timeManager.toDateTime(event.attributes?.datetime);
|
||||||
if (!datetime) continue;
|
if (!datetime) continue;
|
||||||
|
|
||||||
// Get the day start for this event's time
|
|
||||||
const dayStart = this.timeManager.getDayStart(datetime);
|
|
||||||
const dateKey = dayStart.toFormat('yyyy-MM-dd');
|
|
||||||
if (!dailyStats.has(dateKey)) continue;
|
|
||||||
|
|
||||||
const dayStats = dailyStats.get(dateKey);
|
|
||||||
const props = event.event_properties || {};
|
const props = event.event_properties || {};
|
||||||
const amount = Number(metric === 'refunds' ? props.PaymentAmount : props.TotalAmount || 0);
|
const amount = Number(metric === 'refunds' ? props.PaymentAmount : props.TotalAmount || 0);
|
||||||
const reason = props.CancelReason || props.OrderMessage || 'No reason provided';
|
const reason = props.CancelReason || props.OrderMessage || 'No reason provided';
|
||||||
const orderId = props.OrderId || props.FromOrder;
|
const orderId = props.OrderId || props.FromOrder;
|
||||||
|
|
||||||
dayStats.total += amount;
|
const item = {
|
||||||
dayStats.count++;
|
|
||||||
dayStats.reasons[reason] = (dayStats.reasons[reason] || 0) + 1;
|
|
||||||
dayStats.items.push({
|
|
||||||
orderId,
|
orderId,
|
||||||
amount,
|
amount,
|
||||||
reason,
|
reason,
|
||||||
datetime: datetime.toISO()
|
datetime: datetime.toISO()
|
||||||
});
|
};
|
||||||
|
|
||||||
dailyStats.set(dateKey, dayStats);
|
// Always update period totals for events within the period
|
||||||
|
periodStats.total += amount;
|
||||||
|
periodStats.count++;
|
||||||
|
periodStats.reasons[reason] = (periodStats.reasons[reason] || 0) + 1;
|
||||||
|
periodStats.items.push(item);
|
||||||
|
|
||||||
|
// Get the day start for this event's time
|
||||||
|
const dayStart = this.timeManager.getDayStart(datetime);
|
||||||
|
const dateKey = dayStart.toFormat('yyyy-MM-dd');
|
||||||
|
|
||||||
|
// Update daily stats if we have this day in our map
|
||||||
|
if (dailyStats.has(dateKey)) {
|
||||||
|
const dayStats = dailyStats.get(dateKey);
|
||||||
|
dayStats.total += amount;
|
||||||
|
dayStats.count++;
|
||||||
|
dayStats.reasons[reason] = (dayStats.reasons[reason] || 0) + 1;
|
||||||
|
dayStats.items.push(item);
|
||||||
|
dailyStats.set(dateKey, dayStats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(`[EventsService] Period stats for ${metric}:`, {
|
||||||
|
total: periodStats.total,
|
||||||
|
count: periodStats.count,
|
||||||
|
reasonCount: Object.keys(periodStats.reasons).length,
|
||||||
|
itemCount: periodStats.items.length
|
||||||
|
});
|
||||||
|
|
||||||
// Convert to array and sort by date
|
// Convert to array and sort by date
|
||||||
const stats = Array.from(dailyStats.values())
|
const stats = Array.from(dailyStats.values())
|
||||||
.sort((a, b) => a.date.localeCompare(b.date))
|
.sort((a, b) => a.date.localeCompare(b.date))
|
||||||
@@ -1594,8 +1629,12 @@ export class EventsService {
|
|||||||
[metric === 'refunds' ? 'refunds' : 'canceledOrders']: {
|
[metric === 'refunds' ? 'refunds' : 'canceledOrders']: {
|
||||||
total: day.total,
|
total: day.total,
|
||||||
count: day.count,
|
count: day.count,
|
||||||
reasons: day.reasons,
|
reasons: periodStats.reasons, // Use period-wide reasons for each day
|
||||||
items: day.items
|
items: day.items,
|
||||||
|
periodTotal: periodStats.total,
|
||||||
|
periodCount: periodStats.count,
|
||||||
|
periodReasons: periodStats.reasons,
|
||||||
|
periodItems: periodStats.items
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -290,8 +290,7 @@ const CancellationsDetails = ({ data }) => {
|
|||||||
const reasonData = Object.entries(cancelData.reasons || {})
|
const reasonData = Object.entries(cancelData.reasons || {})
|
||||||
.map(([reason, count]) => ({
|
.map(([reason, count]) => ({
|
||||||
reason,
|
reason,
|
||||||
count,
|
count
|
||||||
percentage: (count / cancelData.count) * 100
|
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => b.count - a.count);
|
.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
@@ -328,7 +327,6 @@ const CancellationsDetails = ({ data }) => {
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Reason</TableHead>
|
<TableHead>Reason</TableHead>
|
||||||
<TableHead className="text-right">Count</TableHead>
|
<TableHead className="text-right">Count</TableHead>
|
||||||
<TableHead className="text-right">% of Total</TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -336,7 +334,6 @@ const CancellationsDetails = ({ data }) => {
|
|||||||
<TableRow key={index}>
|
<TableRow key={index}>
|
||||||
<TableCell className="font-medium">{item.reason}</TableCell>
|
<TableCell className="font-medium">{item.reason}</TableCell>
|
||||||
<TableCell className="text-right">{item.count.toLocaleString()}</TableCell>
|
<TableCell className="text-right">{item.count.toLocaleString()}</TableCell>
|
||||||
<TableCell className="text-right">{item.percentage.toFixed(1)}%</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@@ -629,8 +626,7 @@ const RefundDetails = ({ data }) => {
|
|||||||
const reasonData = Object.entries(refundData.reasons || {})
|
const reasonData = Object.entries(refundData.reasons || {})
|
||||||
.map(([reason, count]) => ({
|
.map(([reason, count]) => ({
|
||||||
reason,
|
reason,
|
||||||
count,
|
count
|
||||||
percentage: (count / refundData.count) * 100
|
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => b.count - a.count);
|
.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
@@ -667,7 +663,6 @@ const RefundDetails = ({ data }) => {
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Reason</TableHead>
|
<TableHead>Reason</TableHead>
|
||||||
<TableHead className="text-right">Count</TableHead>
|
<TableHead className="text-right">Count</TableHead>
|
||||||
<TableHead className="text-right">% of Total</TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -675,7 +670,6 @@ const RefundDetails = ({ data }) => {
|
|||||||
<TableRow key={index}>
|
<TableRow key={index}>
|
||||||
<TableCell className="font-medium">{item.reason}</TableCell>
|
<TableCell className="font-medium">{item.reason}</TableCell>
|
||||||
<TableCell className="text-right">{item.count.toLocaleString()}</TableCell>
|
<TableCell className="text-right">{item.count.toLocaleString()}</TableCell>
|
||||||
<TableCell className="text-right">{item.percentage.toFixed(1)}%</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user