fix(freight): correct direct CAS lines and sync inventory on schedule load

End-to-end testing of the direct truck-to-train flow surfaced two defects
in the carriage acceptance sheet's no-wagon fallback. Container numbers
were read from freight.containers, which only gains rows at allocation,
so a direct booking's declared containers never appeared; they are read
from booking_container_units now, seal numbers included. The weight used
bulkTotalWeightTons alone, which is null for CONTAINER and PER_TON bulk
bookings, printing 0.00 — cargoTotalWeightVgm is the real weight there
and only holds an item count for PER_ITEM break-bulk.

Separately, warehouse cargo can be loaded from the Load-to-Train queue or
from the schedule, but loading from the schedule never advanced
warehouse_inventory. The booking went IN_TRANSIT while its cargo still
read as sitting in the warehouse — the same inconsistency that produced
the spurious dispatch block. loadBooking now moves the inventory to
LOADED in the same transaction, and no-ops for direct bookings.
This commit is contained in:
Hagernesh
2026-08-09 16:03:52 +00:00
parent 1797238d26
commit cde67e4c6a
5 changed files with 31 additions and 424 deletions

View File

@@ -95,6 +95,20 @@ export class BookingJourneyService {
await manager
.getRepository(TrainScheduleBooking)
.update({ trainScheduleId: scheduleId, bookingId }, { loadingStatus: 'LOADED' });
// Warehouse cargo may be loaded either from the warehouse Load-to-Train
// queue or from the schedule itself. Loading here must move its inventory
// too, otherwise the goods read as still sitting in the shed while the
// train leaves with them. No-ops for direct truck-to-train (no inventory).
// ponytail: no WarehouseLoading record on this path — those are only read
// back as per-inventory loading history, never billed. Create them here if
// that history ever has to be complete.
await manager.query(
`UPDATE freight.warehouse_inventory
SET status = 'LOADED', loaded_at = COALESCE(loaded_at, $2), updated_at = NOW()
WHERE booking_id = $1 AND deleted_at IS NULL
AND status NOT IN ('LOADED', 'DISPATCHED')`,
[bookingId, now],
);
// The facility handed the cargo over — raise its GRN. No-ops for yards
// without a facility (import/export terminals), which keep their own flow.
await this.facilityHandling.recordHandling(manager, {