feat(bookings): pending export requests hold wagons

This commit is contained in:
Marshal
2026-08-07 12:22:43 +00:00
parent 70215a9f37
commit 84c3f7a584
2 changed files with 35 additions and 7 deletions

View File

@@ -859,7 +859,9 @@ export class BookingBatchService implements OnModuleInit {
const locomotive = trainSetLocomotiveLimits(schedule?.trainSet); const locomotive = trainSetLocomotiveLimits(schedule?.trainSet);
if (!schedule || !locomotive) continue; if (!schedule || !locomotive) continue;
const limits = await this.capacityLimits(locomotive); const limits = await this.capacityLimits(locomotive);
const budget = await this.remainingBudget(schedule, limits, wagonDims); const budget = await this.remainingBudget(schedule, limits, wagonDims, [
booking.id,
]);
const leg = budget.legOf(booking.originYardId, booking.destinationYardId); const leg = budget.legOf(booking.originYardId, booking.destinationYardId);
if (!leg) continue; // this train's route doesn't carry the booking's leg if (!leg) continue; // this train's route doesn't carry the booking's leg
report.corridorMatched = true; report.corridorMatched = true;
@@ -1012,7 +1014,9 @@ export class BookingBatchService implements OnModuleInit {
const locomotive = trainSetLocomotiveLimits(schedule?.trainSet); const locomotive = trainSetLocomotiveLimits(schedule?.trainSet);
if (!schedule || !locomotive) continue; if (!schedule || !locomotive) continue;
const limits = await this.capacityLimits(locomotive); const limits = await this.capacityLimits(locomotive);
const budget = await this.remainingBudget(schedule, limits, wagonDims); const budget = await this.remainingBudget(schedule, limits, wagonDims, [
booking.id,
]);
const leg = budget.legOf(booking.originYardId, booking.destinationYardId); const leg = budget.legOf(booking.originYardId, booking.destinationYardId);
if (!leg) continue; // this train's route doesn't carry the booking's leg if (!leg) continue; // this train's route doesn't carry the booking's leg
const room = budget.remainingFor(leg); const room = budget.remainingFor(leg);
@@ -1128,7 +1132,9 @@ export class BookingBatchService implements OnModuleInit {
const locomotive = trainSetLocomotiveLimits(schedule?.trainSet); const locomotive = trainSetLocomotiveLimits(schedule?.trainSet);
if (!schedule || !locomotive) continue; if (!schedule || !locomotive) continue;
const limits = await this.capacityLimits(locomotive); const limits = await this.capacityLimits(locomotive);
const budget = await this.remainingBudget(schedule, limits, wagonDims); const budget = await this.remainingBudget(schedule, limits, wagonDims, [
booking.id,
]);
const leg = budget.legOf(booking.originYardId, booking.destinationYardId); const leg = budget.legOf(booking.originYardId, booking.destinationYardId);
if (!leg) continue; // this train's route doesn't carry the booking's leg if (!leg) continue; // this train's route doesn't carry the booking's leg
const room = budget.remainingFor(leg); const room = budget.remainingFor(leg);
@@ -1281,7 +1287,9 @@ export class BookingBatchService implements OnModuleInit {
if (!schedule || !locomotive) return false; if (!schedule || !locomotive) return false;
const wagonDims = await this.loadWagonDims(); const wagonDims = await this.loadWagonDims();
const limits = await this.capacityLimits(locomotive); const limits = await this.capacityLimits(locomotive);
const budget = await this.remainingBudget(schedule, limits, wagonDims); const budget = await this.remainingBudget(schedule, limits, wagonDims, [
booking.id,
]);
const leg = budget.legOf(booking.originYardId, booking.destinationYardId); const leg = budget.legOf(booking.originYardId, booking.destinationYardId);
if (!leg) return false; if (!leg) return false;
@@ -1382,7 +1390,12 @@ export class BookingBatchService implements OnModuleInit {
} }
const wagonDims = await this.loadWagonDims(); const wagonDims = await this.loadWagonDims();
const limits = await this.capacityLimits(locomotive); const limits = await this.capacityLimits(locomotive);
const budget = await this.remainingBudget(schedule, limits, wagonDims); const budget = await this.remainingBudget(
schedule,
limits,
wagonDims,
bookings.map((b) => b.id),
);
const leg = budget.legOf( const leg = budget.legOf(
bookings[0].originYardId, bookings[0].originYardId,
bookings[0].destinationYardId, bookings[0].destinationYardId,
@@ -4745,6 +4758,7 @@ export class BookingBatchService implements OnModuleInit {
schedule: TrainSchedule, schedule: TrainSchedule,
limits: TrainLimits, limits: TrainLimits,
wagonDims: WagonDims, wagonDims: WagonDims,
excludeBookingIds?: string[],
): Promise<CorridorBudget> { ): Promise<CorridorBudget> {
const physicalWagons = await this.builtTrainWagonCount(schedule); const physicalWagons = await this.builtTrainWagonCount(schedule);
if (physicalWagons != null) { if (physicalWagons != null) {
@@ -4780,7 +4794,21 @@ export class BookingBatchService implements OnModuleInit {
b.status === "PAID" || b.status === "PAID" ||
!payWindowLapsed(b.paymentDeadline, deadlineCutoff), !payWindowLapsed(b.paymentDeadline, deadlineCutoff),
); );
for (const b of [...allocated, ...reserved]) { // Export FCFS: a customer's pending operation request HOLDS its wagons from
// the moment it is submitted — the request named this exact train
// (requestedTrainScheduleId), so its capacity must not be shown to or
// booked by anyone else while staff review it. The booking(s) being
// evaluated are excluded so a request never blocks its own accept.
const pendingHolds = (
await this.dataSource.getRepository(Booking).find({
where: {
requestedTrainScheduleId: schedule.id,
status: 'OPERATION_REQUEST_PENDING',
} as never,
relations: ['bookingContainers'],
})
).filter((b) => !excludeBookingIds?.includes(b.id));
for (const b of [...allocated, ...reserved, ...pendingHolds]) {
budget.subtract( budget.subtract(
this.needFor(b, wagonDims), this.needFor(b, wagonDims),
budget.legForYards(b.originYardId, b.destinationYardId), budget.legForYards(b.originYardId, b.destinationYardId),

View File

@@ -17,7 +17,7 @@ import { WagonTransferRequestsService } from './wagon-transfer-requests.service'
TypeOrmModule.forFeature([ TypeOrmModule.forFeature([
Wagon, Wagon,
WagonMovement, WagonMovement,
WagonStatusLog, WagonStatusLog,
WagonTransferRequest, WagonTransferRequest,
Train, Train,
Yard, Yard,