train loading for import

This commit is contained in:
Hagernesh
2026-07-04 09:33:07 +00:00
parent 5b4f624188
commit 00cd1fccf6
13 changed files with 534 additions and 34 deletions

View File

@@ -920,6 +920,23 @@ export class WarehouseInventoryService {
}),
);
// Receiving the booking flags every container unit as received into the
// port (self-haul export: the delivering truck's goods are now in) so
// staff can raise the per-container GRN over what's received.
await manager.query(
`UPDATE freight.booking_container_units bcu
SET received_to_port = true,
received_at = COALESCE(bcu.received_at, NOW()),
updated_at = NOW()
FROM freight.booking_containers bc
WHERE bc.id = bcu.booking_container_id
AND bc.booking_id = $1
AND bc.deleted_at IS NULL
AND bcu.deleted_at IS NULL
AND bcu.received_to_port = false`,
[bookingId],
);
await this.activityLog.record(
{
activityType: 'INVENTORY_RECEIVED',
@@ -1774,6 +1791,26 @@ export class WarehouseInventoryService {
await this.applyCapacityDelta(manager, dto, weight, volume, containerCount);
// Per-container receive: flag this container's unit as received into the
// port so staff can raise the GRN over what's received.
if (dto.bookingId && dto.containerId) {
await manager.query(
`UPDATE freight.booking_container_units bcu
SET received_to_port = true,
received_at = COALESCE(bcu.received_at, NOW()),
updated_at = NOW()
FROM freight.booking_containers bc, freight.containers cont
WHERE bc.id = bcu.booking_container_id
AND bc.booking_id = $1
AND bc.deleted_at IS NULL
AND cont.id = $2
AND cont.container_number = bcu.container_number
AND bcu.deleted_at IS NULL
AND bcu.received_to_port = false`,
[dto.bookingId, dto.containerId],
);
}
await this.activityLog.record(
{
activityType: 'INVENTORY_RECEIVED',
@@ -2084,6 +2121,9 @@ export class WarehouseInventoryService {
AND a.deleted_at IS NULL`,
[item.bookingId, item.containerId],
);
// NB: import arrival changes nothing on the goods — received_to_port is
// an EXPORT concept (set when a truck delivers into the port). Import
// load + weight are captured on truck departure, not arrival.
}
// Booking-level flag stamped on the FIRST truck arrival. The import
// handover is signed ONCE (before the first truck leaves), even though
@@ -2175,12 +2215,16 @@ export class WarehouseInventoryService {
truckType: string;
containerNumbers: string;
truckWeightTons: string | number | null;
grossWeightKg: string | number | null;
departedAt: string | null;
} | null = null;
if (row?.tradeDirection === 'IMPORT' && row?.containerNumber && row?.bookingId) {
const [truckRow] = await this.dataSource.query(
`SELECT a.plate_number AS "plateNumber",
a.driver_name AS "driverName",
a.truck_type AS "truckType",
a.gross_weight_kg AS "grossWeightKg",
a.departed_at AS "departedAt",
string_agg(DISTINCT c2.container_number, ', ' ORDER BY c2.container_number) AS "containerNumbers",
COALESCE((
SELECT SUM(bcu.vgm_tons)
@@ -2231,8 +2275,14 @@ export class WarehouseInventoryService {
truckPlateNumber: truck?.plateNumber ?? null,
truckDriverName: truck?.driverName ?? null,
truckType: truck?.truckType ?? null,
truckContainers: truck?.containerNumbers ?? null,
truckWeightKg: truck ? Number(truck.truckWeightTons ?? 0) * 1000 : null,
truckGateOut: truck?.departedAt ?? null,
// Prefer the weighed gross captured on departure; fall back to the summed
// container VGM when the truck hasn't been weighed yet.
truckWeightKg: truck
? Number(truck.grossWeightKg ?? 0) > 0
? Number(truck.grossWeightKg)
: Number(truck.truckWeightTons ?? 0) * 1000
: null,
});
return {
@@ -3165,7 +3215,7 @@ export class WarehouseInventoryService {
truckPlateNumber?: string | null;
truckDriverName?: string | null;
truckType?: string | null;
truckContainers?: string | null;
truckGateOut?: string | null;
truckWeightKg?: number | null;
}): string {
const esc = (value: unknown) =>
@@ -3208,7 +3258,18 @@ export class WarehouseInventoryService {
['Pickup Truck Plate', data.truckPlateNumber],
['Truck Driver', data.truckDriverName],
['Truck Type', data.truckType],
['Containers Loaded on Truck', data.truckContainers],
[
'Gate-Out Time',
data.truckGateOut
? new Date(data.truckGateOut).toLocaleString('en-GB', {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
})
: null,
],
] as [string, string | null][])
: []),
...(data.exitInspectionSummary ? [['Exit Inspection', data.exitInspectionSummary] as [string, string]] : []),