fix: correct revenue metric mapping in Weekly Sales grid (pivot revenue vs ads cost)

This commit is contained in:
Christian Vidal Wolf
2026-02-19 16:22:19 +01:00
parent 079e4130f7
commit 2b9399e7e0
3 changed files with 256360 additions and 27 deletions
+256326
View File
File diff suppressed because it is too large Load Diff
+30 -26
View File
@@ -207,6 +207,8 @@ const WeeklyRow: React.FC<{
const prevVal = row.unitsByWeek[weeks[idx + 1]] || 0; const prevVal = row.unitsByWeek[weeks[idx + 1]] || 0;
const spend = row.spendByWeek[week] || 0; const spend = row.spendByWeek[week] || 0;
const prevSpend = row.spendByWeek[weeks[idx + 1]] || 0; const prevSpend = row.spendByWeek[weeks[idx + 1]] || 0;
const revenue = row.revenueByWeek[week] || 0;
const prevRevenue = row.revenueByWeek[weeks[idx + 1]] || 0;
const gv = row.gvByWeek?.[week] || 0; const gv = row.gvByWeek?.[week] || 0;
const prevGv = row.gvByWeek?.[weeks[idx + 1]] || 0; const prevGv = row.gvByWeek?.[weeks[idx + 1]] || 0;
@@ -218,6 +220,7 @@ const WeeklyRow: React.FC<{
const lastYearWeek = `${parseInt(year) - 1}-${weekNum}`; const lastYearWeek = `${parseInt(year) - 1}-${weekNum}`;
const yoyUnits = row.unitsByWeek[lastYearWeek] || 0; const yoyUnits = row.unitsByWeek[lastYearWeek] || 0;
const yoySpend = row.spendByWeek[lastYearWeek] || 0; const yoySpend = row.spendByWeek[lastYearWeek] || 0;
const yoyRevenue = row.revenueByWeek[lastYearWeek] || 0;
const yoyGv = row.gvByWeek?.[lastYearWeek] || 0; const yoyGv = row.gvByWeek?.[lastYearWeek] || 0;
@@ -244,9 +247,9 @@ const WeeklyRow: React.FC<{
</MetricDetailTooltip> </MetricDetailTooltip>
) : ( ) : (
<MetricDetailTooltip <MetricDetailTooltip
currentValue={spend} currentValue={revenue}
previousValue={prevSpend} previousValue={prevRevenue}
yoyValue={yoySpend} yoyValue={yoyRevenue}
currentWeekLabel={`Week ${weekNum} (${year})`} currentWeekLabel={`Week ${weekNum} (${year})`}
previousWeekLabel={`Week ${prevWeekNum} (${year})`} previousWeekLabel={`Week ${prevWeekNum} (${year})`}
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`} yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
@@ -255,10 +258,10 @@ const WeeklyRow: React.FC<{
formatValue={(v) => `${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`} formatValue={(v) => `${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className={`text-sm font-bold ${spend > 0 ? (sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-400' : 'text-white') : 'text-slate-700'}`}> <span className={`text-sm font-bold ${revenue > 0 ? (sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-400' : 'text-white') : 'text-slate-700'}`}>
{spend > 0 ? `${spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}` : '-'} {revenue > 0 ? `${revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}` : '-'}
</span> </span>
{spend > 0 && renderGrowth(spend, prevSpend)} {revenue > 0 && renderGrowth(revenue, prevRevenue)}
</div> </div>
</MetricDetailTooltip> </MetricDetailTooltip>
)} )}
@@ -266,23 +269,23 @@ const WeeklyRow: React.FC<{
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
{/* Secondary Metric (the one not selected) */} {/* Secondary Metric (the one not selected) */}
{primaryMetric === 'units' ? ( {primaryMetric === 'units' ? (
spend > 0 && ( revenue > 0 && (
<MetricDetailTooltip <MetricDetailTooltip
currentValue={spend} currentValue={revenue}
previousValue={prevSpend} previousValue={prevRevenue}
yoyValue={yoySpend} yoyValue={yoyRevenue}
currentWeekLabel={`Week ${weekNum} (${year})`} currentWeekLabel={`Week ${weekNum} (${year})`}
previousWeekLabel={`Week ${prevWeekNum} (${year})`} previousWeekLabel={`Week ${prevWeekNum} (${year})`}
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`} yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
metricName="Spend" metricName="Revenue"
metricColor="text-indigo-400" metricColor="text-indigo-400/80"
formatValue={(v) => `${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`} formatValue={(v) => `${v.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`}
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1 text-[10px]">
<span className={`text-[11px] font-medium ${sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-300' : 'text-indigo-400/80'}`}> <span className={`font-medium ${sortConfig?.key === week && sortConfig.metric === 'spend' ? 'text-amber-300' : 'text-indigo-400/80'}`}>
{spend.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })} {revenue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
</span> </span>
{renderGrowth(spend, prevSpend)} {renderGrowth(revenue, prevRevenue)}
</div> </div>
</MetricDetailTooltip> </MetricDetailTooltip>
) )
@@ -296,11 +299,11 @@ const WeeklyRow: React.FC<{
previousWeekLabel={`Week ${prevWeekNum} (${year})`} previousWeekLabel={`Week ${prevWeekNum} (${year})`}
yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`} yoyWeekLabel={`Week ${weekNum} (${parseInt(year) - 1})`}
metricName="Units" metricName="Units"
metricColor="text-indigo-400" metricColor="text-indigo-400/80"
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1 text-[10px]">
<span className={`text-[11px] font-medium ${sortConfig?.key === week && sortConfig.metric === 'units' ? 'text-amber-300' : 'text-indigo-400/80'}`}> <span className={`font-medium ${sortConfig?.key === week && sortConfig.metric === 'units' ? 'text-indigo-300' : 'text-indigo-400/80'}`}>
{val.toLocaleString('de-DE')} Units {val.toLocaleString('de-DE')}
</span> </span>
{renderGrowth(val, prevVal)} {renderGrowth(val, prevVal)}
</div> </div>
@@ -427,12 +430,12 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
// Calculate totals in a SINGLE PASS // Calculate totals in a SINGLE PASS
const weekTotals = useMemo(() => { const weekTotals = useMemo(() => {
const totals: { [weekKey: string]: { units: number, spend: number, gv: number } } = {}; const totals: { [weekKey: string]: { units: number, spend: number, revenue: number, gv: number } } = {};
const visibleWeeks = weeks; const visibleWeeks = weeks;
// Initialize visible weeks // Initialize visible weeks
for (let i = 0; i < visibleWeeks.length; i++) { for (let i = 0; i < visibleWeeks.length; i++) {
totals[visibleWeeks[i]] = { units: 0, spend: 0, gv: 0 }; totals[visibleWeeks[i]] = { units: 0, spend: 0, revenue: 0, gv: 0 };
} }
// Single pass through rows // Single pass through rows
@@ -442,6 +445,7 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
const w = visibleWeeks[j]; const w = visibleWeeks[j];
totals[w].units += (row.unitsByWeek[w] || 0); totals[w].units += (row.unitsByWeek[w] || 0);
totals[w].spend += (row.spendByWeek[w] || 0); totals[w].spend += (row.spendByWeek[w] || 0);
totals[w].revenue += (row.revenueByWeek[w] || 0);
totals[w].gv += (row.gvByWeek?.[w] || 0); totals[w].gv += (row.gvByWeek?.[w] || 0);
} }
} }
@@ -981,15 +985,15 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
{renderGrowth(weekTotals[week]?.units || 0, weekTotals[weeks[idx + 1]]?.units || 0)} {renderGrowth(weekTotals[week]?.units || 0, weekTotals[weeks[idx + 1]]?.units || 0)}
</div> </div>
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold"> <div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
<span>{(weekTotals[week]?.spend || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span> <span>{(weekTotals[week]?.revenue || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
{renderGrowth(weekTotals[week]?.spend || 0, weekTotals[weeks[idx + 1]]?.spend || 0)} {renderGrowth(weekTotals[week]?.revenue || 0, weekTotals[weeks[idx + 1]]?.revenue || 0)}
</div> </div>
</> </>
) : ( ) : (
<> <>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span>{(weekTotals[week]?.spend || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span> <span>{(weekTotals[week]?.revenue || 0).toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</span>
{renderGrowth(weekTotals[week]?.spend || 0, weekTotals[weeks[idx + 1]]?.spend || 0)} {renderGrowth(weekTotals[week]?.revenue || 0, weekTotals[weeks[idx + 1]]?.revenue || 0)}
</div> </div>
<div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold"> <div className="flex items-center justify-center gap-1 text-[10px] text-indigo-400 font-bold">
<span>{(weekTotals[week]?.units || 0).toLocaleString('de-DE')} Units</span> <span>{(weekTotals[week]?.units || 0).toLocaleString('de-DE')} Units</span>
+4 -1
View File
@@ -1642,7 +1642,8 @@ export interface WeeklyPivotRow {
line: string; line: string;
customer: string; customer: string;
unitsByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" unitsByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
spendByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" spendByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" (Ads Cost)
revenueByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" (Sell-out)
gvByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW" gvByWeek: { [weekKey: string]: number }; // Key: "YYYY-WW"
} }
@@ -1691,6 +1692,7 @@ export const pivotWeeklySalesData = (data: CombinedKPIs[]): {
customer: record.customer || record.marketplace || '', customer: record.customer || record.marketplace || '',
unitsByWeek: {}, unitsByWeek: {},
spendByWeek: {}, spendByWeek: {},
revenueByWeek: {},
gvByWeek: {} gvByWeek: {}
}; };
map.set(key, row); map.set(key, row);
@@ -1698,6 +1700,7 @@ export const pivotWeeklySalesData = (data: CombinedKPIs[]): {
row.unitsByWeek[weekKey] = (row.unitsByWeek[weekKey] || 0) + (record.unitsTotal || 0); row.unitsByWeek[weekKey] = (row.unitsByWeek[weekKey] || 0) + (record.unitsTotal || 0);
row.spendByWeek[weekKey] = (row.spendByWeek[weekKey] || 0) + (record.cost || 0); row.spendByWeek[weekKey] = (row.spendByWeek[weekKey] || 0) + (record.cost || 0);
row.revenueByWeek[weekKey] = (row.revenueByWeek[weekKey] || 0) + (record.salesTotal || 0);
row.gvByWeek[weekKey] = (row.gvByWeek[weekKey] || 0) + (record.glanceViews || 0); row.gvByWeek[weekKey] = (row.gvByWeek[weekKey] || 0) + (record.glanceViews || 0);
} }