Restructure weekly actuals charts — Sales History section + month cumulative
Backend:
- Always fetch full calendar month (not truncated at week ending)
- Add month_daily[] to response (per-day TY/LY by dept, is_actual flag)
Frontend:
- New 'Sales History' section with:
- Monthly dept line chart: 12-month x-axis, TY vs prior year per dept
(Rooms/Dry/Wet solid, LY dashed — same colour per dept)
- Rolling 12-month average trend (moved from Month Progress)
- Month Progress section gains cumulative line chart:
- X-axis = day of month, 6 lines (3 TY solid + 3 LY dashed)
- TY lines stop at week ending; LY spans full month
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7f0d1057c1
commit
ffa13d6e57
3 changed files with 165 additions and 65 deletions
|
|
@ -88,9 +88,9 @@ export async function weeklyActualRoutes(fastify) {
|
|||
// 5-week window: start 4 weeks before this week's Sunday
|
||||
const fiveWeekStart = addDays(weekStartDate, -28)
|
||||
|
||||
// Month to date: 1st of month → week ending date
|
||||
const monthStart = new Date(year, month - 1, 1)
|
||||
const monthDays = Math.round((weekEndDate - monthStart) / 86400000) + 1
|
||||
// Full calendar month (needed for daily chart — month progress filters by date)
|
||||
const monthStart = new Date(year, month - 1, 1)
|
||||
const daysInMonth = new Date(year, month, 0).getDate()
|
||||
|
||||
// 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)
|
||||
|
|
@ -106,10 +106,8 @@ export async function weeklyActualRoutes(fastify) {
|
|||
fcFetch(`/forecast/revenue?start_date=${toDateStr(fiveWeekStart)}&days=35&type=all`),
|
||||
// This week rooms (for occupancy table)
|
||||
fcFetch(`/forecast/rooms?start_date=${toDateStr(weekStartDate)}&days=7`),
|
||||
// Month to date revenue
|
||||
monthDays > 0
|
||||
? fcFetch(`/forecast/revenue?start_date=${toDateStr(monthStart)}&days=${monthDays}&type=all`)
|
||||
: Promise.resolve({ data: [] }),
|
||||
// Full month revenue (used for month progress totals + daily chart)
|
||||
fcFetch(`/forecast/revenue?start_date=${toDateStr(monthStart)}&days=${daysInMonth}&type=all`),
|
||||
// 12 monthly trend revenue calls
|
||||
...trendMonths.map(({ year: y, month: m }) => {
|
||||
const firstDay = new Date(y, m - 1, 1)
|
||||
|
|
@ -118,11 +116,11 @@ export async function weeklyActualRoutes(fastify) {
|
|||
}),
|
||||
])
|
||||
|
||||
const [fiveWeekRevRaw, thisWeekRoomsRaw, monthRevRaw, ...trendRevRaw] = results
|
||||
const [fiveWeekRevRaw, thisWeekRoomsRaw, fullMonthRevRaw, ...trendRevRaw] = results
|
||||
|
||||
const fiveWeekRevMap = buildDayMap(fiveWeekRevRaw)
|
||||
const fiveWeekRevMap = buildDayMap(fiveWeekRevRaw)
|
||||
const thisWeekRoomsMap = buildDayMap(thisWeekRoomsRaw)
|
||||
const monthRevMap = buildDayMap(monthRevRaw)
|
||||
const fullMonthRevMap = buildDayMap(fullMonthRevRaw)
|
||||
|
||||
// ── Five week summaries ────────────────────────────────────────────────────
|
||||
const fiveWeeks = [0, 1, 2, 3, 4].map(w => {
|
||||
|
|
@ -181,11 +179,11 @@ export async function weeklyActualRoutes(fastify) {
|
|||
let mBud = { rooms: 0, dry: 0, wet: 0 }
|
||||
let mLy = { rooms: 0, dry: 0, wet: 0 }
|
||||
|
||||
for (let i = 0; i < monthDays; i++) {
|
||||
for (let i = 0; i < daysInMonth; i++) {
|
||||
const d = addDays(monthStart, i)
|
||||
if (d > weekEndDate) break
|
||||
const dateStr = toDateStr(d)
|
||||
const rev = monthRevMap[dateStr] || {}
|
||||
const rev = fullMonthRevMap[dateStr] || {}
|
||||
|
||||
mNet.rooms += parseFloat(rev.accom?.otb ?? 0)
|
||||
mNet.dry += parseFloat(rev.dry?.otb ?? 0)
|
||||
|
|
@ -224,6 +222,26 @@ export async function weeklyActualRoutes(fastify) {
|
|||
},
|
||||
}
|
||||
|
||||
// ── Month daily (for cumulative progress line chart) ──────────────────────
|
||||
const weekEndStr = toDateStr(weekEndDate)
|
||||
const month_daily = []
|
||||
for (let i = 0; i < daysInMonth; i++) {
|
||||
const d = addDays(monthStart, i)
|
||||
const dateStr = toDateStr(d)
|
||||
const rev = fullMonthRevMap[dateStr] || {}
|
||||
month_daily.push({
|
||||
day: i + 1,
|
||||
date: dateStr,
|
||||
ty_rooms: parseFloat(rev.accom?.otb ?? 0),
|
||||
ty_dry: parseFloat(rev.dry?.otb ?? 0),
|
||||
ty_wet: parseFloat(rev.wet?.otb ?? 0),
|
||||
ly_rooms: parseFloat(rev.accom?.prior_final ?? 0),
|
||||
ly_dry: parseFloat(rev.dry?.prior_final ?? 0),
|
||||
ly_wet: parseFloat(rev.wet?.prior_final ?? 0),
|
||||
is_actual: dateStr <= weekEndStr,
|
||||
})
|
||||
}
|
||||
|
||||
// ── Monthly trend (rolling 12-month average) ──────────────────────────────
|
||||
// Build raw monthly totals for all 36 months
|
||||
const allMonthTotals = trendMonths.map((_, i) => {
|
||||
|
|
@ -279,6 +297,7 @@ export async function weeklyActualRoutes(fastify) {
|
|||
five_weeks: fiveWeeks,
|
||||
occupancy,
|
||||
month_progress,
|
||||
month_daily,
|
||||
monthly_trend,
|
||||
monthly_split,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue