/** * Booking-window timings sourced from the train_scheduling_global_rules singleton, * with hardcoded fallbacks when the row is missing (see TrainSchedulingService.getWindowConfig). */ export interface BookingWindowConfig { /** Days before departure the single import booking-window day falls on. */ importWindowLeadDays: number; /** Hours before departure an export booking becomes acceptable (FCFS). */ exportBookingLeadHours: number; /** Local (Africa/Addis_Ababa) hour at which the import window opens each day. */ windowOpenHour: number; /** * Local (Africa/Addis_Ababa) hour the booking desk shuts for the day: once a * cycle's reopen would fall at/after this hour, the window pauses and resumes * next morning at windowOpenHour. Equal to windowOpenHour ⇒ 24-hour desk. */ windowCloseHour: number; windowDurationHours: number; /** Max staff document-review time after the window closes. */ docReviewMinutes: number; /** Pay window for IMPORT/DOMESTIC bookings (also part of the reopen gap). */ paymentWindowMinutes: number; /** Pay window for EXPORT bookings — independent of the import value. */ exportPaymentWindowMinutes: number; /** * Minutes before departure the IMPORT/DOMESTIC booking window shuts. When set * (> 0), the effective booking cutoff is `departure − this`, capping the first * window close and every reopen cycle. NULL/0 ⇒ no offset (close at departure). */ importCloseOffsetMinutes?: number | null; /** * Minutes before departure the EXPORT FCFS booking window shuts. When set (> 0), * export closes at `departure − this` instead of at departure. NULL/0 ⇒ none. */ exportCloseOffsetMinutes?: number | null; } /** Window phase lifecycle for the one-booking-day import cycle. NULL on legacy/DOMESTIC schedules. */ export const WINDOW_PHASES = [ 'PRE_WINDOW', 'OPEN', 'DOC_REVIEW', 'PAYMENT', 'CLOSED_FOR_DAY', 'DONE', ] as const; export type WindowPhase = (typeof WINDOW_PHASES)[number];