diff --git a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts index 46175c7ef..0b239990b 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.service.ts @@ -310,7 +310,10 @@ export class BookingBatchService implements OnModuleInit { private async openRouteDayGroups(): Promise { const open = ( await this.trainSchedulesRepository.findAll({ - where: { bookingWindowStatus: "OPEN" }, + where: [ + { bookingWindowStatus: "OPEN", status: TrainScheduleStatusEnum.Draft }, + { bookingWindowStatus: "OPEN", status: TrainScheduleStatusEnum.Scheduled }, + ], }) ).filter((s) => s.windowPhase == null); const groups = new Map(); 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 32a046356..3b36fdc9a 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 @@ -2049,7 +2049,9 @@ export class TrainSchedulingService { await this.trainSchedulesRepository.updateStatus( id, TrainScheduleStatusEnum.Cancelled, - {}, + // Retire the booking window so a canceled schedule never lingers as an + // "open window" in booking-window lists or the legacy batch fill. + { bookingWindowStatus: 'CLOSED', windowPhase: 'DONE' }, manager, ); if (schedule.trainSetId) { diff --git a/apps/edr-freight-web/backoffice/src/components/contracts/GlUpcomingWindowsSection.tsx b/apps/edr-freight-web/backoffice/src/components/contracts/GlUpcomingWindowsSection.tsx index e5e998721..dc95729c1 100644 --- a/apps/edr-freight-web/backoffice/src/components/contracts/GlUpcomingWindowsSection.tsx +++ b/apps/edr-freight-web/backoffice/src/components/contracts/GlUpcomingWindowsSection.tsx @@ -235,6 +235,8 @@ export function GlUpcomingWindowsSection() { const rows = (data ?? []).filter( (w) => w.windowPhase != null && w.windowPhase !== "DONE" && !isPast(w), ); + // Canceled schedules are retired to windowPhase='DONE' server-side, so the + // guard above already excludes them; they never reach the upcoming list. // Open lanes first, then by opening time. return rows.sort((a, b) => { const openDiff = Number(b.isOpenNow) - Number(a.isOpenNow);