From 6c96b7ad94847c64d496e362d4d5d53c08fe3abb Mon Sep 17 00:00:00 2001 From: Hagernesh Date: Thu, 13 Aug 2026 11:27:15 +0000 Subject: [PATCH] fix(warehouses): free warehouse/yard/zone capacity on export dispatch dispatch() (LOADED -> DISPATCHED) routed through the shared transition() helper, which only flipped status/timestamp and never called applyCapacityDelta. deliver() (import pickup) already decrements correctly, so export cargo leaving by train inflated currentWeight/ currentVolume/currentContainers forever instead of freeing capacity. Add optional freeCapacity hook to transition(), wire dispatch() to it, mirroring the negative-delta pattern already used in deliver(). --- .../warehouses/warehouse-inventory.service.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts index 58b5e9493..7412f0269 100644 --- a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts +++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts @@ -5161,6 +5161,7 @@ export class WarehouseInventoryService { activityType: 'INVENTORY_DISPATCHED', description: 'Inventory dispatched', performedBy, + freeCapacity: true, }); } @@ -5445,6 +5446,8 @@ export class WarehouseInventoryService { description: string; performedBy?: string; preloaded?: WarehouseInventory; + /** Cargo physically leaves the warehouse on this transition — free up capacity (mirrors deliver()). */ + freeCapacity?: boolean; }, ): Promise { const item = opts.preloaded ?? (await this.findById(id)); @@ -5455,6 +5458,20 @@ export class WarehouseInventoryService { status: to, [opts.timestampField]: new Date(), }); + + if (opts.freeCapacity) { + const weight = Number(item.weight) || 0; + const volume = Number(item.volume) || 0; + const containerCount = item.containerId ? Math.round(Number(item.quantity) || 0) : 0; + await this.applyCapacityDelta( + manager, + { warehouseId: item.warehouseId, yardId: item.yardId, zoneId: item.zoneId }, + -weight, + -volume, + -containerCount, + ); + } + await this.activityLog.record( { activityType: opts.activityType,