mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 14:55:23 +02:00
fix: include ads-only ASINs in merge and use unfiltered rows for totals
1. Changed weekTotals to use 'rows' instead of 'filteredRows' so totals always show complete sums regardless of search/growth filters 2. Added second pass in mergeSalesAndAdsData to include ads records for ASINs that have ad spend but no corresponding sales data
This commit is contained in:
@@ -119,18 +119,18 @@ const WeeklyGrid: React.FC<WeeklyGridProps> = ({ data }) => {
|
|||||||
|
|
||||||
const totalPages = Math.ceil(sortedRows.length / ROWS_PER_PAGE);
|
const totalPages = Math.ceil(sortedRows.length / ROWS_PER_PAGE);
|
||||||
|
|
||||||
// Calculate totals per week
|
// Calculate totals per week - use unfiltered 'rows' to show complete totals
|
||||||
const weekTotals = useMemo(() => {
|
const weekTotals = useMemo(() => {
|
||||||
const totals: { [weekKey: string]: { units: number, spend: number } } = {};
|
const totals: { [weekKey: string]: { units: number, spend: number } } = {};
|
||||||
weeks.forEach(week => {
|
weeks.forEach(week => {
|
||||||
totals[week] = filteredRows.reduce((acc, row) => {
|
totals[week] = rows.reduce((acc, row) => {
|
||||||
acc.units += (row.unitsByWeek[week] || 0);
|
acc.units += (row.unitsByWeek[week] || 0);
|
||||||
acc.spend += (row.spendByWeek[week] || 0);
|
acc.spend += (row.spendByWeek[week] || 0);
|
||||||
return acc;
|
return acc;
|
||||||
}, { units: 0, spend: 0 });
|
}, { units: 0, spend: 0 });
|
||||||
});
|
});
|
||||||
return totals;
|
return totals;
|
||||||
}, [filteredRows, weeks]);
|
}, [rows, weeks]);
|
||||||
|
|
||||||
const renderGrowth = (current: number, previous: number) => {
|
const renderGrowth = (current: number, previous: number) => {
|
||||||
if (!previous || previous === 0) return null;
|
if (!previous || previous === 0) return null;
|
||||||
|
|||||||
@@ -541,6 +541,50 @@ export const mergeSalesAndAdsData = (salesData: SalesRecord[], adsData: AdsRecor
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3. Include ads-only records (ASINs with ads but no sales)
|
||||||
|
const usedAdsKeys = new Set<string>();
|
||||||
|
salesData.forEach(sale => {
|
||||||
|
const weekNum = sale.week || 0;
|
||||||
|
const key = `${sale.asin.trim().toUpperCase()}|${sale.customer.trim().toUpperCase()}|${sale.year}|${weekNum}`;
|
||||||
|
usedAdsKeys.add(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
adsData.forEach(ad => {
|
||||||
|
const key = `${ad.asin.trim().toUpperCase()}|${ad.country.trim().toUpperCase()}|${ad.year}|${ad.week}`;
|
||||||
|
if (!usedAdsKeys.has(key)) {
|
||||||
|
// Create a CombinedKPIs record for ads-only data
|
||||||
|
mergedData.push({
|
||||||
|
id: `ads-${key}`,
|
||||||
|
marketplace: ad.country,
|
||||||
|
customer: ad.country,
|
||||||
|
month: '',
|
||||||
|
week: ad.week,
|
||||||
|
year: ad.year,
|
||||||
|
asin: ad.asin,
|
||||||
|
title: '',
|
||||||
|
line: '',
|
||||||
|
sku: '',
|
||||||
|
salesTotal: 0,
|
||||||
|
unitsTotal: 0,
|
||||||
|
salesAds: ad.attributedSales30d,
|
||||||
|
unitsAds: ad.attributedUnits30d,
|
||||||
|
cost: ad.cost,
|
||||||
|
clicks: ad.clicks,
|
||||||
|
impressions: ad.impressions,
|
||||||
|
salesOrganic: 0,
|
||||||
|
unitsOrganic: 0,
|
||||||
|
paidSalesShare: 0,
|
||||||
|
organicSalesShare: 0,
|
||||||
|
acos: ad.attributedSales30d > 0 ? (ad.cost / ad.attributedSales30d) * 100 : 0,
|
||||||
|
tacos: 0,
|
||||||
|
roas: ad.cost > 0 ? ad.attributedSales30d / ad.cost : 0,
|
||||||
|
ctr: ad.impressions > 0 ? (ad.clicks / ad.impressions) * 100 : 0,
|
||||||
|
cpc: ad.clicks > 0 ? ad.cost / ad.clicks : 0,
|
||||||
|
cvrUnits: ad.clicks > 0 ? (ad.attributedUnits30d / ad.clicks) * 100 : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return mergedData;
|
return mergedData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user