enhance contract clearance and train scheduling logic; add filters for clearance documents and improve booking validation

This commit is contained in:
Marshal
2026-07-13 21:40:10 +00:00
parent 3fe4ea72ac
commit 957a185a4d
5 changed files with 45 additions and 7 deletions

View File

@@ -1136,14 +1136,35 @@ export class TrainSchedulingService {
throw new BadRequestException('Schedule has no train set');
}
// Batch parity: a schedule may only allocate bookings that targeted it. This mirrors
// the automatic fill, which only pulls bookings whose train_schedule_id is this schedule.
// Batch parity: a schedule may only allocate bookings from its route-day POOL.
// Under day-level pooling (see fillRouteDayInternal) an unreserved booking has
// a NULL train_schedule_id and is only pinned by reserve(); a reserved one is
// pinned to whichever train in the day's group first held it. Every train
// sharing this origin + destination + EAT departure day draws from ONE shared
// pool (one shared booking window), so a booking is allocatable here when it is
// either unpinned (NULL) or pinned to THIS train or a GROUP SIBLING. A booking
// pinned to a train on a DIFFERENT route/day is a real stray. Genuine route/
// day/capacity fit is enforced downstream by validateBookingsForScheduling.
// EXPORT never groups, so its pool is this schedule alone (plus NULL pool).
if (dto.bookingIds.length) {
const groupScheduleIds = new Set<string>([scheduleId]);
if (schedule.direction !== 'EXPORT') {
const siblings = await this.findGroupSiblings(
this.dataSource.manager,
schedule.originStationId,
schedule.destinationStationId,
schedule.scheduledDepartureDate,
scheduleId,
);
for (const sib of siblings) groupScheduleIds.add(sib.id);
}
const targeted = await this.bookingsRepository.findByIdsForScheduling(dto.bookingIds);
const stray = targeted.filter((b) => b.trainScheduleId !== scheduleId);
const stray = targeted.filter(
(b) => b.trainScheduleId != null && !groupScheduleIds.has(b.trainScheduleId),
);
if (stray.length) {
throw new BadRequestException(
`These bookings are not assigned to this schedule: ${stray
`These bookings are pinned to a train on a different route or day: ${stray
.map((b) => b.reference ?? b.id)
.join(', ')}`,
);