Fix F&B last-7-days fill to span month boundary
"Fill F&B from last 7 days" only drew from the current month's elapsed days, so early in a month (e.g. the 3rd) it only had 1-2 actual days to repeat instead of a true trailing 7-day window. Add a dedicated last7-fnb endpoint that fetches a real 7-day window ending yesterday, reaching back into the prior month when needed.
This commit is contained in:
parent
d1c50c77d0
commit
73d2c713d4
3 changed files with 51 additions and 5 deletions
|
|
@ -57,9 +57,38 @@ async function fetchMonthFromApi(year, month, lastDayNum, dowAlign = true) {
|
|||
return { revMap, roomsMap }
|
||||
}
|
||||
|
||||
async function fetchLast7ActualsFnB() {
|
||||
const today = new Date()
|
||||
const end = new Date(today)
|
||||
end.setDate(end.getDate() - 1)
|
||||
const start = new Date(end)
|
||||
start.setDate(start.getDate() - 6)
|
||||
const startDate = start.toISOString().split('T')[0]
|
||||
|
||||
const revData = await fcFetch(`/forecast/revenue?start_date=${startDate}&days=7&type=all`)
|
||||
return revData.data
|
||||
.slice()
|
||||
.sort((a, b) => a.date.localeCompare(b.date))
|
||||
.map(d => ({
|
||||
date: d.date,
|
||||
actual_dry: d.dry?.otb ?? null,
|
||||
actual_wet: d.wet?.otb ?? null,
|
||||
forecast_dry: d.dry?.forecast ?? null,
|
||||
forecast_wet: d.wet?.forecast ?? null,
|
||||
}))
|
||||
}
|
||||
|
||||
export async function directorsForecastRoutes(fastify) {
|
||||
fastify.addHook('preHandler', requireAuth)
|
||||
|
||||
// GET /api/directors-forecast/last7-fnb — trailing 7 actual F&B days ending
|
||||
// yesterday, spanning a month boundary. Used by "fill F&B from last 7 days",
|
||||
// which otherwise only has the current month's elapsed days to draw from.
|
||||
fastify.get('/api/directors-forecast/last7-fnb', async (request, reply) => {
|
||||
const days = await fetchLast7ActualsFnB()
|
||||
return { days }
|
||||
})
|
||||
|
||||
// GET /api/directors-forecast/worksheet/:year/:month
|
||||
fastify.get('/api/directors-forecast/worksheet/:year/:month', async (request, reply) => {
|
||||
const year = parseInt(request.params.year)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,18 @@ export function dfGetReport(year: number, month: number, dowAlign = true): Promi
|
|||
return request<ForecastReportData>(`/directors-forecast/report/${year}/${month}?dow_align=${dowAlign}`)
|
||||
}
|
||||
|
||||
export type Last7FnBDay = {
|
||||
date: string
|
||||
actual_dry: number | null
|
||||
actual_wet: number | null
|
||||
forecast_dry: number | null
|
||||
forecast_wet: number | null
|
||||
}
|
||||
|
||||
export function dfGetLast7Fnb(): Promise<{ days: Last7FnBDay[] }> {
|
||||
return request<{ days: Last7FnBDay[] }>('/directors-forecast/last7-fnb')
|
||||
}
|
||||
|
||||
export function dfSaveSnapshot(year: number, month: number, data: object) {
|
||||
return request(`/directors-forecast/report/${year}/${month}/snapshot`, {
|
||||
method: 'POST', body: JSON.stringify(data),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react'
|
|||
import { useFrameViewport } from '../hooks/useFrameViewport'
|
||||
import { Save, RefreshCw, Camera, Trash2, Printer, Repeat2 } from 'lucide-react'
|
||||
import { useAuth } from '../components/AuthGate'
|
||||
import { dfGetWorksheet, dfSaveWorksheet, dfGetReport, dfSaveSnapshot, dfDeleteSnapshot } from '../api'
|
||||
import { dfGetWorksheet, dfSaveWorksheet, dfGetReport, dfSaveSnapshot, dfDeleteSnapshot, dfGetLast7Fnb } from '../api'
|
||||
import type { WorksheetDay, WorksheetData, ForecastReportData, ForecastSnapshot } from '../types'
|
||||
import { can, DOW_NAMES, MONTH_NAMES } from '../types'
|
||||
|
||||
|
|
@ -82,11 +82,16 @@ function WorksheetTab({ year, month, dowAlign }: { year: number; month: number;
|
|||
setDirty(true)
|
||||
}
|
||||
|
||||
function fillFnBFromLast7() {
|
||||
async function fillFnBFromLast7() {
|
||||
if (!data) return
|
||||
const last7 = data.days
|
||||
.filter(d => d.is_past && (d.actual_dry != null || d.actual_wet != null))
|
||||
.slice(-7)
|
||||
let last7
|
||||
try {
|
||||
const res = await dfGetLast7Fnb()
|
||||
last7 = res.days.filter(d => d.actual_dry != null || d.actual_wet != null)
|
||||
} catch {
|
||||
setError('Failed to load last 7 days of actuals.')
|
||||
return
|
||||
}
|
||||
if (!last7.length) return
|
||||
setOverrides(prev => {
|
||||
const next = { ...prev }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue