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++; }); }); });