From 78b5665ea72476c5ba1b2cd93c86019f8f258a40 Mon Sep 17 00:00:00 2001 From: Hagernesh Date: Wed, 29 Jul 2026 13:40:14 +0000 Subject: [PATCH] feat(marshalling-documents): add company column and container summary Export and import marshalling documents now include: - Company name column per cargo allocation row - Executive summary with container counts (40ft, 20ft, total) - Total weight already shown, now grouped with container data Both export and import load list templates enhanced with same structure for consistency. Container size calculated from booking container data. --- .../train-scheduling.service.ts | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts index 418338257..599e1ed72 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts @@ -2754,11 +2754,13 @@ export class TrainSchedulingService { allocations: (wagon.allocations ?? []).map((allocation) => ({ bookingId: allocation.bookingId, bookingReference: allocation.booking?.reference ?? null, + booking: allocation.booking, loadType: allocation.loadType ?? null, allocatedWeightTons: Number(allocation.allocatedWeightTons) || 0, containerNumbers: (allocation.containerItems ?? []) .map((item) => item.containerNumber) .filter(Boolean), + containerItems: allocation.containerItems ?? [], })), })), operation: await this.getImportDjiboutiOperation(schedule.id), @@ -2839,6 +2841,7 @@ export class TrainSchedulingService { return allocations.map((allocation) => { const booking = allocation.booking ?? bookingById.get(allocation.bookingId); const cargoType = (booking as unknown as { cargoType?: { name?: string; code?: string } } | undefined)?.cargoType; + const companyName = (booking as unknown as { company?: { name?: string } } | undefined)?.company?.name ?? '-'; const containerItems = allocation.containerItems ?? []; const firstContainer = containerItems[0]; const containerNumbers = containerItems.map((item) => item.containerNumber).filter(Boolean).join(', '); @@ -2847,6 +2850,7 @@ export class TrainSchedulingService { return ` ${wagonCells} ${esc(cargoType?.name ?? cargoType?.code ?? allocation.loadType)} + ${esc(companyName)} ${esc(containerNumbers || firstContainer?.containerNumber)} ${esc(chassisNumbers)} ${esc(sealNumbers)} @@ -2861,6 +2865,18 @@ export class TrainSchedulingService { 0, ); + // Container count summary (40ft, 20ft) + let count40ft = 0, count20ft = 0; + wagons.forEach((wagon) => { + (wagon.allocations ?? []).forEach((allocation) => { + (allocation.containerItems ?? []).forEach((item) => { + const size = item.bookingContainer?.containerSize; + if (size?.includes('40')) count40ft++; + else if (size?.includes('20')) count20ft++; + }); + }); + }); + return ` @@ -2910,6 +2926,9 @@ export class TrainSchedulingService {
Departure station${esc(schedule.originStation?.label ?? schedule.originStation?.code)}
Arrival station${esc(schedule.destinationStation?.label ?? schedule.destinationStation?.code)}
Total loaded weight${esc(totalWeight.toFixed(3))} T
+
Containers 40ft${esc(count40ft)}
+
Containers 20ft${esc(count20ft)}
+
Total containers${esc(count40ft + count20ft)}
Prepared person${esc(schedule.preparedByUserId)}
Check person${esc(schedule.checkedByUserId)}
Wagons${esc(wagons.length)}${emptyWagons ? ` (${emptyWagons} empty)` : ''}
@@ -2928,6 +2947,7 @@ export class TrainSchedulingService { Tare Weight Load Capacity Cargo Type + Company Container No Chassis No Seal No @@ -3010,6 +3030,19 @@ export class TrainSchedulingService { 0, ); const emptyWagons = loadList.wagons.filter((wagon) => wagon.allocations.length === 0).length; + + // Container count summary (40ft, 20ft) + let count40ft = 0, count20ft = 0; + loadList.wagons.forEach((wagon) => { + wagon.allocations.forEach((allocation) => { + (allocation.containerItems ?? []).forEach((item) => { + const size = item.bookingContainer?.containerSize; + if (size?.includes('40')) count40ft++; + else if (size?.includes('20')) count20ft++; + }); + }); + }); + const allocationRows = loadList.wagons .flatMap((wagon) => { const wagonCells = `${esc(wagon.sequenceNo)} @@ -3025,13 +3058,17 @@ export class TrainSchedulingService { ]; } return wagon.allocations.map( - (allocation) => ` + (allocation) => { + const companyName = (allocation.booking as unknown as { company?: { name?: string } } | undefined)?.company?.name ?? '-'; + return ` ${wagonCells} ${esc(allocation.bookingReference ?? allocation.bookingId)} + ${esc(companyName)} ${esc(allocation.loadType)} ${esc(allocation.containerNumbers.length ? allocation.containerNumbers.join(', ') : '-')} ${esc(Number(allocation.allocatedWeightTons || 0).toFixed(3))} - `, + `; + }, ); }) .join(''); @@ -3096,6 +3133,9 @@ export class TrainSchedulingService {
Wagons${esc(loadList.wagons.length)}${emptyWagons ? ` (${emptyWagons} empty)` : ''}
Allocations${esc(totalAllocations)}
Total weight${esc(totalWeight.toFixed(3))} T
+
Containers 40ft${esc(count40ft)}
+
Containers 20ft${esc(count20ft)}
+
Total containers${esc(count40ft + count20ft)}
Gatepass granted${esc(date(loadList.operation.gatepassGrantedAt))}
@@ -3115,6 +3155,7 @@ export class TrainSchedulingService { Seq Wagon Booking + Company Load Container numbers Weight T