From 29f7d05800a0c991c6e60423c1bef52f8c79cf87 Mon Sep 17 00:00:00 2001 From: Marshal Date: Thu, 6 Aug 2026 23:18:48 +0000 Subject: [PATCH] allow create inside lead window --- .../train-scheduling.service.ts | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts index df5c44fde..e8ed6ff4b 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts @@ -1546,23 +1546,10 @@ export class TrainSchedulingService { } : globalCfg; - // Staff cannot schedule inside the lead window — there must be room for a - // booking window before departure. IMPORT/DOMESTIC lead is in whole EAT - // days (lead 3, today 11th → first allowed departure is the 14th); EXPORT - // lead is in hours (24h = 1 day ahead). Checked against the schedule's OWN - // lead, so a custom lead is honoured rather than rejected by the global one. - const earliest = earliestSchedulableDeparture(direction, windowCfg, new Date()); - if (departure.getTime() < earliest.getTime()) { - const detail = - direction === 'EXPORT' - ? `at least ${windowCfg.exportBookingLeadHours} hour(s) ahead` - : `at least ${windowCfg.importWindowLeadDays} day(s) ahead`; - throw new BadRequestException( - `Departure ${departure.toISOString()} is inside the booking lead window; ` + - `${direction === 'EXPORT' ? 'export' : 'import'} trains must be scheduled ${detail} ` + - `(earliest ${earliest.toISOString()})`, - ); - } + // Short-notice trains are allowed: a departure inside the booking lead + // window is NOT rejected — the window just opens immediately (opensAt is + // clamped to `now` below) instead of waiting out a lead that has already + // passed. Only `updateScheduleDate` still enforces the lead floor. // Freeze the rule this schedule is born with. A later global-rules edit // only re-derives NOT-YET-OPEN schedules (see restampPendingWindows); an @@ -1577,6 +1564,11 @@ export class TrainSchedulingService { ...ruleSnapshot, ...computeImportWindowTimes(departure, windowCfg, new Date()), }; + // Inside-lead departure (e.g. a huge configured lead): the raw open lands + // in the past — clamp it to `now` so the window tick opens it immediately. + if (computedTimes.windowOpensAt.getTime() < Date.now()) { + computedTimes.windowOpensAt = new Date(); + } if ( computedTimes.windowOpensAt.getTime() >= computedTimes.windowClosesAt.getTime() ) {