mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 23:28:11 +00:00
feat(clearance): preview charge documents before and after upload
This commit is contained in:
@@ -1218,12 +1218,7 @@ export class BookingBatchService implements OnModuleInit {
|
||||
schedule.originStationId,
|
||||
budget.stops,
|
||||
);
|
||||
const ledger = new WagonStockLedger(
|
||||
stock.remainingByTypeId,
|
||||
Math.max(1, budget.stops.length - 1),
|
||||
stock.byYardId,
|
||||
budget.stops,
|
||||
);
|
||||
const ledger = await this.stockLedgerFor(schedule, budget, [booking.id]);
|
||||
// On a multi-yard consist the pool that matters is the one standing at
|
||||
// the booking's own boarding yard — a type carried only in Mojo must not
|
||||
// be advertised to a customer boarding at Dire.
|
||||
@@ -4782,18 +4777,36 @@ export class BookingBatchService implements OnModuleInit {
|
||||
private async stockLedgerFor(
|
||||
schedule: TrainSchedule,
|
||||
budget: CorridorBudget,
|
||||
excludeBookingIds?: string[],
|
||||
): Promise<WagonStockLedger> {
|
||||
const stock = await this.trainSchedulingService.wagonStockForSchedule(
|
||||
schedule.id,
|
||||
schedule.originStationId,
|
||||
budget.stops,
|
||||
);
|
||||
return new WagonStockLedger(
|
||||
const ledger = new WagonStockLedger(
|
||||
stock.remainingByTypeId,
|
||||
Math.max(1, budget.stops.length - 1),
|
||||
stock.byYardId,
|
||||
budget.stops,
|
||||
);
|
||||
// Debit what is already committed, per boarding yard and wagon type — the
|
||||
// same bookings the corridor budget subtracted. A booking with no resolvable
|
||||
// wagon type still occupies steel, so it drains any type at its yard.
|
||||
const [wagonDims, allowed] = await Promise.all([
|
||||
this.loadWagonDims(),
|
||||
this.loadAllowedWagonTypeIds(),
|
||||
]);
|
||||
const anyType = [...stock.remainingByTypeId.keys()];
|
||||
for (const b of await this.committedBookings(schedule, excludeBookingIds)) {
|
||||
const typeIds = this.allowedWagonTypeIdsFor(b, allowed);
|
||||
ledger.consume(
|
||||
typeIds.length ? typeIds : anyType,
|
||||
this.wagonsFor(b, wagonDims),
|
||||
budget.legForYards(b.originYardId, b.destinationYardId),
|
||||
);
|
||||
}
|
||||
return ledger;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4956,6 +4969,29 @@ export class BookingBatchService implements OnModuleInit {
|
||||
// wagon serves disjoint legs — capacity freed past an alight yard is real.
|
||||
const stops = await this.stopsForSchedule(schedule);
|
||||
const budget = new CorridorBudget(stops, limits.base, limits.tolerance);
|
||||
for (const b of await this.committedBookings(schedule, excludeBookingIds)) {
|
||||
budget.subtract(
|
||||
this.needFor(b, wagonDims),
|
||||
budget.legForYards(b.originYardId, b.destinationYardId),
|
||||
);
|
||||
}
|
||||
return budget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every booking already holding capacity on the schedule: allocated (linked),
|
||||
* live-reserved (unexpired pay window or paid), and pending export requests
|
||||
* that named this train. The ONE list both the abstract corridor budget and
|
||||
* the per-yard wagon-type ledger must debit — when only the budget saw them,
|
||||
* a train with 15 wagons planned at Mojo and 15 already booked from Mojo
|
||||
* still advertised "15 free" there, because the whole-train budget had room
|
||||
* left on that edge (from the other yard's wagons) and the ledger was born
|
||||
* full.
|
||||
*/
|
||||
private async committedBookings(
|
||||
schedule: TrainSchedule,
|
||||
excludeBookingIds?: string[],
|
||||
): Promise<Booking[]> {
|
||||
const allocated = (schedule.scheduleBookings ?? [])
|
||||
.map((sb) => sb.booking)
|
||||
.filter((b): b is Booking => Boolean(b));
|
||||
@@ -4988,13 +5024,14 @@ export class BookingBatchService implements OnModuleInit {
|
||||
relations: ['bookingContainers'],
|
||||
})
|
||||
).filter((b) => !excludeBookingIds?.includes(b.id));
|
||||
for (const b of [...allocated, ...reserved, ...pendingHolds]) {
|
||||
budget.subtract(
|
||||
this.needFor(b, wagonDims),
|
||||
budget.legForYards(b.originYardId, b.destinationYardId),
|
||||
);
|
||||
}
|
||||
return budget;
|
||||
// A booking can sit in more than one set (allocated AND still reserved);
|
||||
// it holds its wagons once.
|
||||
const seen = new Set<string>();
|
||||
return [...allocated, ...reserved, ...pendingHolds].filter((b) => {
|
||||
if (seen.has(b.id) || excludeBookingIds?.includes(b.id)) return false;
|
||||
seen.add(b.id);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user