mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 19:58:11 +00:00
changes
This commit is contained in:
@@ -130,6 +130,7 @@ import {
|
||||
maxEdgeConsistUsage,
|
||||
perEdgeConsistUsage,
|
||||
validateContainerPlacements,
|
||||
validateWagonCargoExclusivity,
|
||||
validateMixedTrainLimitsPerEdge,
|
||||
MAX_TEU_SLOTS_PER_WAGON,
|
||||
type ContainerPlacementInput,
|
||||
@@ -2200,12 +2201,23 @@ export class TrainSchedulingService {
|
||||
].map((bookingId) => ({ trainScheduleId: scheduleId, bookingId }));
|
||||
await this.trainScheduleBookingsRepository.createMany(scheduleBookingRecords, manager);
|
||||
|
||||
// Leg spans for the per-edge exclusivity guard — a wagon may carry
|
||||
// containers to Dire Dawa and bulk onward, never both at once.
|
||||
const persistLegs = new Map(
|
||||
bookings.flatMap((b) => {
|
||||
const from = scheduleStops.indexOf(b.originYardId);
|
||||
const to = scheduleStops.indexOf(b.destinationYardId);
|
||||
return from >= 0 && to > from ? [[b.id, { from, to }] as const] : [];
|
||||
}),
|
||||
);
|
||||
await this.persistAllocationsAndLoads(
|
||||
manager,
|
||||
savedWagons,
|
||||
wagonPlan,
|
||||
bookings,
|
||||
containerPlacements ?? [],
|
||||
persistLegs,
|
||||
Math.max(1, scheduleStops.length - 1),
|
||||
);
|
||||
|
||||
// The link above puts these bookings on the train: they are SCHEDULED, not
|
||||
@@ -5023,6 +5035,9 @@ export class TrainSchedulingService {
|
||||
trainLimits,
|
||||
stops,
|
||||
stopLabels,
|
||||
// Cargo exclusivity is a per-edge rule: a wagon may carry containers
|
||||
// to Dire Dawa and bulk onward from there, never both at once.
|
||||
legByBookingId,
|
||||
),
|
||||
);
|
||||
if (requireContainerPlacements && resolvedMode !== 'BULK') {
|
||||
@@ -6048,6 +6063,9 @@ export class TrainSchedulingService {
|
||||
wagonPlan: WagonPlanSlot[],
|
||||
bookings: Booking[],
|
||||
containerPlacements: ContainerPlacementInput[] = [],
|
||||
/** Booking id → stop-index span, for the per-edge exclusivity guard. */
|
||||
legs?: Map<string, { from: number; to: number }>,
|
||||
edgeCount = 1,
|
||||
) {
|
||||
const bookingById = new Map(bookings.map((b) => [b.id, b]));
|
||||
const lineById = new Map(
|
||||
@@ -6081,16 +6099,18 @@ export class TrainSchedulingService {
|
||||
const trainSetWagon = savedWagons[i];
|
||||
if (!slot || !trainSetWagon) continue;
|
||||
|
||||
// Last line of defense behind validateWagonCargoExclusivity: a wagon
|
||||
// with bulk on it carries that one load only — never a container and
|
||||
// never a second bulk booking.
|
||||
if (
|
||||
slot.allocations.length > 1 &&
|
||||
slot.allocations.some((a) => a.loadType === AllocationLoadType.Bulk)
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Wagon #${slot.sequenceNo} mixes bulk with other cargo — a wagon carrying bulk takes that one load only`,
|
||||
);
|
||||
// Last line of defense behind validateWagonCargoExclusivity: while a
|
||||
// bulk load rides, its wagon carries nothing else — no container and no
|
||||
// second bulk booking. Loads on DISJOINT legs (a container that alights
|
||||
// where the bulk boards) legitimately share the wagon, so the check is
|
||||
// per corridor edge, using the same leg spans the plan was built with.
|
||||
const exclusivityIssues = validateWagonCargoExclusivity(
|
||||
[slot],
|
||||
legs,
|
||||
edgeCount,
|
||||
);
|
||||
if (exclusivityIssues.length) {
|
||||
throw new BadRequestException(exclusivityIssues[0]);
|
||||
}
|
||||
|
||||
for (const alloc of slot.allocations) {
|
||||
|
||||
Reference in New Issue
Block a user