mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 23:28:11 +00:00
add lashing surcharge for cargo types with hasLashing flag
add lashing surcharge for cargo types with hasLashing flag
This commit is contained in:
@@ -731,6 +731,64 @@ export class BookingBatchService implements OnModuleInit {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Advisory free-wagon count for an IMPORT/DOMESTIC booking on a given day,
|
||||
* summed across every train on the booking's corridor that day. Unlike the
|
||||
* export gate this does NOT block and does NOT first-fit a single train:
|
||||
* import is batched and splittable, so the honest number a customer can plan
|
||||
* against is the TOTAL room across the day's trains for the booking's wagon
|
||||
* type, in that type's own wagon units.
|
||||
*
|
||||
* It deliberately skips the `isFillable` window-phase gate. A customer picks a
|
||||
* shipment day while its window is still OPEN (or pre-window) — the batch fill
|
||||
* only makes those trains fillable after the window closes — so gating on the
|
||||
* fill phase here would report 0 for exactly the days customers are choosing.
|
||||
* We therefore count any non-FULL train that carries the leg, netting out the
|
||||
* capacity already consumed by allocated + live-reserved bookings
|
||||
* (`remainingBudget`). The count is an upper bound: the batch engine may still
|
||||
* split the booking across trains or defer a remainder to a later window.
|
||||
*/
|
||||
async dayImportAvailability(
|
||||
booking: Booking,
|
||||
day: string,
|
||||
): Promise<{ freeWagons: number; need: number; trainsForDay: boolean }> {
|
||||
const corridor = await this.trainSchedulesRepository.findAll({
|
||||
where: [
|
||||
{ status: TrainScheduleStatusEnum.Draft },
|
||||
{ status: TrainScheduleStatusEnum.Scheduled },
|
||||
],
|
||||
});
|
||||
const candidates = corridor.filter(
|
||||
(s) =>
|
||||
s.scheduledDepartureDate != null &&
|
||||
eatDay(s.scheduledDepartureDate) === day &&
|
||||
s.bookingWindowStatus !== 'FULL' &&
|
||||
s.direction !== 'EXPORT',
|
||||
);
|
||||
|
||||
const wagonDims = await this.loadWagonDims();
|
||||
const dims = this.dimsFor(booking, wagonDims);
|
||||
const need = this.wagonsFor(booking, wagonDims);
|
||||
let freeWagons = 0;
|
||||
let trainsForDay = false;
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const schedule = await this.trainSchedulesRepository.findByIdWithFullGraph(
|
||||
candidate.id,
|
||||
);
|
||||
const locomotive = schedule?.trainSet?.locomotive;
|
||||
if (!schedule || !locomotive) continue;
|
||||
const limits = await this.capacityLimits(locomotive);
|
||||
const budget = await this.remainingBudget(schedule, limits, wagonDims);
|
||||
const leg = budget.legOf(booking.originYardId, booking.destinationYardId);
|
||||
if (!leg) continue; // this train's route doesn't carry the booking's leg
|
||||
trainsForDay = true;
|
||||
freeWagons += this.bookableWithin(budget.remainingFor(leg), dims).wagons;
|
||||
}
|
||||
|
||||
return { freeWagons, need, trainsForDay };
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an export booking into the FCFS flow. Solo bookings reserve immediately.
|
||||
* A consolidated booking reserves as a pair only once BOTH partners are ready
|
||||
@@ -1118,6 +1176,17 @@ export class BookingBatchService implements OnModuleInit {
|
||||
s.ruleExportBookingLeadHours,
|
||||
liveCfg.exportBookingLeadHours,
|
||||
),
|
||||
// Frozen close offsets: a snapshot null means "no offset for this train"
|
||||
// and stays null (not the live offset); only legacy rows lacking the
|
||||
// column (undefined) fall back to live config.
|
||||
importCloseOffsetMinutes:
|
||||
s.ruleImportCloseOffsetMinutes !== undefined
|
||||
? s.ruleImportCloseOffsetMinutes
|
||||
: liveCfg.importCloseOffsetMinutes,
|
||||
exportCloseOffsetMinutes:
|
||||
s.ruleExportCloseOffsetMinutes !== undefined
|
||||
? s.ruleExportCloseOffsetMinutes
|
||||
: liveCfg.exportCloseOffsetMinutes,
|
||||
};
|
||||
const departureDate = s.scheduledDepartureDate ?? new Date();
|
||||
const windowBuckets = groupBookingsIntoBoardWindows(
|
||||
|
||||
Reference in New Issue
Block a user