diff --git a/backend/src/routes/weekly-actual.js b/backend/src/routes/weekly-actual.js index 97701205..bb2d1f58 100644 --- a/backend/src/routes/weekly-actual.js +++ b/backend/src/routes/weekly-actual.js @@ -92,9 +92,10 @@ export async function weeklyActualRoutes(fastify) { const monthStart = new Date(year, month - 1, 1) const monthDays = Math.round((weekEndDate - monthStart) / 86400000) + 1 - // 12-month trend months (most recent last) + // 36 months of raw totals needed to compute rolling 12-month averages for + // 12 display points (indices 23–35) plus their LY equivalents (indices 0–23) const trendMonths = [] - for (let i = 11; i >= 0; i--) { + for (let i = 35; i >= 0; i--) { const d = new Date(year, month - 1 - i, 1) trendMonths.push({ year: d.getFullYear(), month: d.getMonth() + 1 }) } @@ -223,22 +224,35 @@ export async function weeklyActualRoutes(fastify) { }, } - // ── Monthly trend ───────────────────────────────────────────────────────── - const monthly_trend = trendMonths.map((tm, i) => { + // ── Monthly trend (rolling 12-month average) ────────────────────────────── + // Build raw monthly totals for all 36 months + const allMonthTotals = trendMonths.map((_, i) => { const data = trendRevRaw[i]?.data ?? [] - let rooms = 0, dry = 0, wet = 0 + let total = 0 for (const d of data) { - rooms += parseFloat(d.accom?.otb ?? 0) - dry += parseFloat(d.dry?.otb ?? 0) - wet += parseFloat(d.wet?.otb ?? 0) - } - return { - label: `${MONTH_LABELS[tm.month - 1]}-${String(tm.year).slice(2)}`, - rooms, dry, wet, - total: rooms + dry + wet, + total += parseFloat(d.accom?.otb ?? 0) + + parseFloat(d.dry?.otb ?? 0) + + parseFloat(d.wet?.otb ?? 0) } + return total }) + const rollingAvg = (arr, from, to) => + arr.slice(from, to + 1).reduce((s, v) => s + v, 0) / (to - from + 1) + + // Display points: indices 23–35 (the last 12 months) + // TY rolling avg at index i = average of allMonthTotals[i-11 .. i] + // LY rolling avg at index i = average of allMonthTotals[i-23 .. i-12] + const monthly_trend = [] + for (let i = 23; i < 36; i++) { + const tm = trendMonths[i] + monthly_trend.push({ + label: `${MONTH_LABELS[tm.month - 1]}-${String(tm.year).slice(2)}`, + this_year_avg: rollingAvg(allMonthTotals, i - 11, i), + last_year_avg: rollingAvg(allMonthTotals, i - 23, i - 12), + }) + } + return { week_ending: toDateStr(weekEndDate), week_start: toDateStr(weekStartDate), diff --git a/frontend/src/pages/WeeklyActual.tsx b/frontend/src/pages/WeeklyActual.tsx index 018de0c1..89b3d216 100644 --- a/frontend/src/pages/WeeklyActual.tsx +++ b/frontend/src/pages/WeeklyActual.tsx @@ -349,7 +349,7 @@ function MonthProgressSection({
-

Monthly Average Turnover — Last 12 Months

+

Rolling 12-Month Avg Turnover — Trend

@@ -357,9 +357,8 @@ function MonthProgressSection({ `£${(v/1000).toFixed(0)}k`} tick={{ fontSize: 10 }} width={52} /> - - - + +
diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 4e263b2a..5dd696d1 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -101,11 +101,9 @@ export interface MonthProgress { } export interface MonthTrend { - label: string - rooms: number - dry: number - wet: number - total: number + label: string + this_year_avg: number + last_year_avg: number } export interface WeeklyActualData {