mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(intercity): only load/unload where the yard has a facility
Intercity cargo rides a passing train and is handled at the booking's own yards, so those yards need the equipment to do it — a train stopping somewhere is not the same as somewhere being able to load it. Loading at an origin or unloading at a destination without has_facility is now refused, naming the yard. The check sits inside loadBooking/unloadBooking rather than the intercity controller wrapper, because recording a checkpoint auto-unloads every booking destined at that yard (autoUnloadAtYard) and would otherwise route around it. Import/export are untouched: their cargo is handled at the route's terminal ports, not at an arbitrary mid-corridor yard, so the gate returns early for anything that isn't DOMESTIC. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { InjectDataSource } from '@nestjs/typeorm';
|
||||
import { DataSource, EntityManager, In } from 'typeorm';
|
||||
import { Freight } from '@edr/types';
|
||||
|
||||
import { YardFacilitiesService } from '../rule-engine/services/yard-facilities.service';
|
||||
import { Booking } from '../bookings/entities/booking.entity';
|
||||
import { ClearanceMilestoneService } from '../contracts/clearance-milestone.service';
|
||||
import { Yard } from '../rule-engine/entities/yard.entity';
|
||||
@@ -43,6 +44,7 @@ export class BookingJourneyService {
|
||||
|
||||
constructor(
|
||||
@InjectDataSource() private readonly dataSource: DataSource,
|
||||
private readonly yardFacilities: YardFacilitiesService,
|
||||
@Optional() private readonly milestoneService?: ClearanceMilestoneService,
|
||||
) {}
|
||||
|
||||
@@ -63,6 +65,7 @@ export class BookingJourneyService {
|
||||
);
|
||||
}
|
||||
await this.assertTrainAtYard(schedule, booking.originYardId, 'origin');
|
||||
await this.assertYardCanHandleCargo(booking, booking.originYardId, 'origin');
|
||||
|
||||
const now = new Date();
|
||||
await this.dataSource.transaction(async (manager) => {
|
||||
@@ -99,6 +102,7 @@ export class BookingJourneyService {
|
||||
);
|
||||
}
|
||||
await this.assertTrainAtYard(schedule, booking.destinationYardId, 'destination');
|
||||
await this.assertYardCanHandleCargo(booking, booking.destinationYardId, 'destination');
|
||||
|
||||
// Intercity has no clearance/delivery tail — unloading completes it. Import/
|
||||
// export continue into clearance, keyed on the booking's own arrival.
|
||||
@@ -306,6 +310,33 @@ export class BookingJourneyService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERCITY ONLY. Intercity cargo rides a passing train and is handled at the
|
||||
* booking's own yards, so those yards need the equipment to do it — a train
|
||||
* stopping somewhere is not the same as somewhere being able to load it.
|
||||
*
|
||||
* Import/export are untouched: their cargo is handled at the route's terminal
|
||||
* ports, not at an arbitrary mid-corridor yard, and gating them here would
|
||||
* block existing traffic.
|
||||
*
|
||||
* Lives here rather than in the controller so the checkpoint-driven
|
||||
* autoUnloadAtYard path cannot route around it.
|
||||
*/
|
||||
private async assertYardCanHandleCargo(
|
||||
booking: Booking,
|
||||
yardId: string,
|
||||
side: 'origin' | 'destination',
|
||||
): Promise<void> {
|
||||
if (booking.tradeDirection !== 'DOMESTIC') return;
|
||||
const facility = await this.yardFacilities.facilityForYard(yardId);
|
||||
if (!facility?.hasFacility) {
|
||||
throw new BadRequestException(
|
||||
`${facility?.yardLabel ?? 'This yard'} has no load/unload facility — an intercity booking cannot be ` +
|
||||
`${side === 'origin' ? 'loaded at its origin' : 'unloaded at its destination'} here.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The train is "at" a yard when the latest recorded checkpoint is that yard,
|
||||
* or — for a booking boarding at the train's own origin — when the train has
|
||||
|
||||
Reference in New Issue
Block a user