Enhance bulk booking handling and wagon capacity calculations across services

This commit is contained in:
Marshal
2026-07-09 15:30:00 +00:00
parent 3259bd7667
commit 1690f9e498
11 changed files with 278 additions and 32 deletions

View File

@@ -55,12 +55,17 @@ export class BookingSplitService {
* Size the largest part of the booking that fits `freeWagons`, priced via an
* in-memory clone. Returns null when nothing meaningful fits (no whole
* container unit / no bulk tonnage, or pricing failed).
*
* `maxOfferedWeightTons` caps the offered CARGO tonnage (bulk only) — on a
* weight-limited train the wagons' own tare eats into the locomotive's
* remaining pull weight, so the caller passes the room left after tare.
*/
async sizeOffer(
booking: Booking,
freeWagons: number,
totalWagons: number,
bulkWagonCapacityTons: number,
maxOfferedWeightTons?: number,
): Promise<SizedOffer | null> {
if (freeWagons < 1 || freeWagons >= totalWagons) return null;
@@ -110,10 +115,15 @@ export class BookingSplitService {
if (!offeredLines.length || offeredWagons <= 0) return null;
clone.bookingContainers = clonedContainers;
} else {
// Bulk: split by weight — the offered part is what freeWagons can carry.
// Bulk: split by weight — the offered part is what freeWagons can carry,
// further capped by the caller's weight room when the pull limit binds.
const totalWeight = Number(booking.cargoTotalWeightVgm ?? 0);
if (totalWeight <= 0 || bulkWagonCapacityTons <= 0) return null;
offeredWeightTons = Math.min(totalWeight, freeWagons * bulkWagonCapacityTons);
offeredWeightTons = Math.min(
totalWeight,
freeWagons * bulkWagonCapacityTons,
maxOfferedWeightTons ?? Number.POSITIVE_INFINITY,
);
if (offeredWeightTons <= 0) return null;
offeredWagons = Math.min(
freeWagons,