Add snapshot of booking-window rules to train schedules and update related logic

This commit is contained in:
Marshal
2026-07-03 18:45:45 +00:00
parent 0ac5adcee9
commit 8db19dfacf
5 changed files with 142 additions and 8 deletions

View File

@@ -307,14 +307,22 @@ function boardWindowFromInterval(start: Date, end: Date): BoardWindow {
* `computeImportWindowTimes` + `concludeCycle`'s reopen math so the board shows the
* exact windows the engine runs.
* EXPORT: a single FCFS window from `departure exportBookingLeadHours` to departure.
*
* `anchorOpensAt` pins the FIRST window's open time to the schedule's stored
* `windowOpensAt` instead of recomputing it from config. Pass it so the board
* shows the real frozen window (and reopen cycles projected from it) even after
* the global rule changed — the recomputed open time would otherwise drift.
*/
export function listConfigBookingWindows(
direction: string | null | undefined,
departure: Date,
cfg: BoardWindowConfig,
anchorOpensAt?: Date | null,
): BoardWindow[] {
if (direction === 'EXPORT') {
const start = new Date(departure.getTime() - cfg.exportBookingLeadHours * 3_600_000);
const start =
anchorOpensAt ??
new Date(departure.getTime() - cfg.exportBookingLeadHours * 3_600_000);
return [boardWindowFromInterval(start, departure)];
}
@@ -323,7 +331,7 @@ export function listConfigBookingWindows(
const reopenMs = cfg.reopenDelayMinutes * 60_000;
const windowDay = shiftEatDay(eatDay(departure), -cfg.importWindowLeadDays);
let opensAt = eatDayToUtc(windowDay, cfg.windowOpenHour);
let opensAt = anchorOpensAt ?? eatDayToUtc(windowDay, cfg.windowOpenHour);
// Reopen stays on the same EAT booking day and before departure; cap at 12 cycles.
for (let cycle = 0; cycle < 12; cycle += 1) {
if (opensAt.getTime() >= departure.getTime()) break;
@@ -375,8 +383,9 @@ export function groupBookingsIntoBoardWindows<T>(
departure: Date,
cfg: BoardWindowConfig,
pendingKey = 'pending-contract',
anchorOpensAt?: Date | null,
): Map<string, { window: BoardWindow | null; items: T[] }> {
const windows = listConfigBookingWindows(direction, departure, cfg);
const windows = listConfigBookingWindows(direction, departure, cfg, anchorOpensAt);
const map = new Map<string, { window: BoardWindow | null; items: T[] }>();
for (const w of windows) {
map.set(w.key, { window: w, items: [] });