From e2ad024da10f04ada5a03c513ceea2134e5b491b Mon Sep 17 00:00:00 2001 From: Hagernesh Date: Wed, 29 Jul 2026 14:11:22 +0000 Subject: [PATCH] fix(train-scheduling): marshalling doc 40ft/20ft counts were always 0 findByIdWithFullGraph loaded containerItems but not containerItems.bookingContainer, so item.bookingContainer was always undefined and the 40ft/20ft/total tallies on the Import/Export Marshalling Document silently read as 0. Load containerType on both the item and its bookingContainer, and resolve size from whichever is set. --- .../train-schedules.repository.ts | 6 ++- .../train-scheduling.service.ts | 38 ++++++++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/apps/edr-freight-api/src/modules/train-schedules/train-schedules.repository.ts b/apps/edr-freight-api/src/modules/train-schedules/train-schedules.repository.ts index 294fb93f1..b0cbeb886 100644 --- a/apps/edr-freight-api/src/modules/train-schedules/train-schedules.repository.ts +++ b/apps/edr-freight-api/src/modules/train-schedules/train-schedules.repository.ts @@ -39,7 +39,11 @@ export class TrainSchedulesRepository extends BaseRepository { physicalWagon: true, allocations: { booking: { company: true, bookingContainers: { containerType: true } }, - containerItems: true, + // Both size sources loaded: the item's own container_type_id FK + // (always set for a manually-entered item) and the booking-line + // fallback via bookingContainer.containerType — the marshalling + // document's 40ft/20ft tally reads whichever is present. + containerItems: { containerType: true, bookingContainer: { containerType: true } }, }, }, }, 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 599e1ed72..d75eadc4a 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 @@ -2801,6 +2801,32 @@ export class TrainSchedulingService { }; } + /** + * A container item's size in feet, for the marshalling document's 40ft/20ft + * tally. Two independent sources, since only one is populated depending on + * how the item was created: + * - `item.containerType` — the item's own container_type_id FK, set for + * manually-entered items (no booking-container line behind them). + * - `item.bookingContainer.containerType.sizeFt` / `.containerSize` — the + * booking-line fallback for items generated from an allocation. + * (`findByIdWithFullGraph` must load both relations or every item here + * silently resolves to null and the tally stays zero.) + */ + private resolveContainerItemSize(item: { + containerType?: { sizeFt?: number | null } | null; + bookingContainer?: { + containerSize?: string | null; + containerType?: { sizeFt?: number | null } | null; + } | null; + }): number | null { + const fromSizeFt = item.containerType?.sizeFt ?? item.bookingContainer?.containerType?.sizeFt; + if (fromSizeFt === 20 || fromSizeFt === 40) return fromSizeFt; + const label = item.bookingContainer?.containerSize; + if (label?.includes('40')) return 40; + if (label?.includes('20')) return 20; + return null; + } + private buildExportLoadListHtml(schedule: TrainSchedule): string { const esc = (value: unknown) => String(value ?? '-') @@ -2870,9 +2896,9 @@ export class TrainSchedulingService { 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 size = this.resolveContainerItemSize(item); + if (size === 40) count40ft++; + else if (size === 20) count20ft++; }); }); }); @@ -3036,9 +3062,9 @@ export class TrainSchedulingService { 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 size = this.resolveContainerItemSize(item); + if (size === 40) count40ft++; + else if (size === 20) count20ft++; }); }); });