diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.controller.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.controller.ts index 8bf4f571f..f8e9208af 100644 --- a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.controller.ts +++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.controller.ts @@ -1,6 +1,8 @@ import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Query, Request, Res } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import type { Response } from 'express'; +import { CurrentUser } from '@edr/api-common'; +import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type'; import { BookingStaff } from '../../common/booking-guards'; import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry'; @@ -127,7 +129,8 @@ export class WarehouseInventoryController { @Post('receive-bulk') @BookingStaff(FREIGHT_PERMS.warehouseInventory.receive) @ApiOperation({ summary: 'Bulk-receive selected eligible PAID bookings into a location' }) - receiveBulk(@Body() dto: BulkReceiveDto) { + receiveBulk(@Body() dto: BulkReceiveDto, @CurrentUser() user: TCurrentUser) { + dto.performedBy = user?.id ?? dto.performedBy; return this.inventoryService.bulkReceive(dto); } @@ -173,15 +176,16 @@ export class WarehouseInventoryController { loadItemsOntoTrain( @Param('scheduleId', ParseUUIDPipe) scheduleId: string, @Body() dto: { inventoryIds: string[]; performedBy?: string }, + @CurrentUser() user: TCurrentUser, ) { - return this.inventoryService.loadItemsOntoTrain(scheduleId, dto.inventoryIds ?? [], dto.performedBy); + return this.inventoryService.loadItemsOntoTrain(scheduleId, dto.inventoryIds ?? [], user?.id ?? dto.performedBy); } @Post('bulk-dispatch-export') @BookingStaff(FREIGHT_PERMS.warehouseInventory.dispatch) @ApiOperation({ summary: 'Bulk-dispatch loaded EXPORT inventory (LOADED → DISPATCHED)' }) - bulkDispatchExport(@Body() dto: { inventoryIds: string[]; performedBy?: string }) { - return this.inventoryService.bulkDispatchExport(dto.inventoryIds ?? [], dto.performedBy); + bulkDispatchExport(@Body() dto: { inventoryIds: string[]; performedBy?: string }, @CurrentUser() user: TCurrentUser) { + return this.inventoryService.bulkDispatchExport(dto.inventoryIds ?? [], user?.id ?? dto.performedBy); } @Post('bulk-mark-inspected') @@ -204,8 +208,12 @@ export class WarehouseInventoryController { @Post(':id/gate-clearance') @BookingStaff(FREIGHT_PERMS.warehouseInventory.gatePass) @ApiOperation({ summary: 'Final terminal release / gate clearance (blocked while fees unpaid)' }) - gateClearance(@Param('id', ParseUUIDPipe) id: string, @Body('performedBy') performedBy?: string) { - return this.inventoryService.gateClearance(id, performedBy); + gateClearance( + @Param('id', ParseUUIDPipe) id: string, + @Body('performedBy') performedBy: string | undefined, + @CurrentUser() user: TCurrentUser, + ) { + return this.inventoryService.gateClearance(id, user?.id ?? performedBy); } @Get('import/arrive-queue') @@ -230,10 +238,10 @@ export class WarehouseInventoryController { warehouseId?: string; performedBy?: string; assignments?: { bookingId: string; warehouseId: string; yardId: string; zoneId: string }[]; - }) { + }, @CurrentUser() user: TCurrentUser) { return this.inventoryService.autoUnloadArrivedBookings( dto.scheduleId, - dto.performedBy, + user?.id ?? dto.performedBy, dto.warehouseId, dto.assignments, ); @@ -275,8 +283,8 @@ export class WarehouseInventoryController { @Post('export/auto-unload-at-djibouti') @BookingStaff(FREIGHT_PERMS.warehouseInventory.unload) @ApiOperation({ summary: 'Unload all eligible export items assigned to an arrived Djibouti-side train' }) - autoUnloadExportAtDjibouti(@Body() dto: { scheduleId: string; performedBy?: string }) { - return this.inventoryService.autoUnloadExportAtDjibouti(dto.scheduleId, dto.performedBy); + autoUnloadExportAtDjibouti(@Body() dto: { scheduleId: string; performedBy?: string }, @CurrentUser() user: TCurrentUser) { + return this.inventoryService.autoUnloadExportAtDjibouti(dto.scheduleId, user?.id ?? dto.performedBy); } @Get('import/pickup-ready-queue') @@ -303,14 +311,16 @@ export class WarehouseInventoryController { @Post('receive') @BookingStaff(FREIGHT_PERMS.warehouseInventory.receive) @ApiOperation({ summary: 'Receive inventory at a warehouse location' }) - receive(@Body() dto: ReceiveWarehouseInventoryDto) { + receive(@Body() dto: ReceiveWarehouseInventoryDto, @CurrentUser() user: TCurrentUser) { + dto.performedBy = user?.id ?? dto.performedBy; return this.inventoryService.receive(dto); } @Post('reserve') @BookingStaff(FREIGHT_PERMS.warehouseInventory.move) @ApiOperation({ summary: 'Reserve stored inventory for a PAID booking' }) - reserve(@Body() dto: ReserveInventoryDto) { + reserve(@Body() dto: ReserveInventoryDto, @CurrentUser() user: TCurrentUser) { + dto.performedBy = user?.id ?? dto.performedBy; return this.inventoryService.reserve(dto); } @@ -345,15 +355,19 @@ export class WarehouseInventoryController { @Post(':id/store') @BookingStaff(FREIGHT_PERMS.warehouseInventory.move) @ApiOperation({ summary: 'Mark received inventory as STORED (optional explicit warehouse/yard/zone)' }) - store(@Param('id', ParseUUIDPipe) id: string, @Body() dto: StoreInventoryDto) { - return this.inventoryService.store(id, dto.performedBy, dto); + store(@Param('id', ParseUUIDPipe) id: string, @Body() dto: StoreInventoryDto, @CurrentUser() user: TCurrentUser) { + return this.inventoryService.store(id, user?.id ?? dto.performedBy, dto); } @Post(':id/ready-for-loading') @BookingStaff(FREIGHT_PERMS.warehouseInventory.move) @ApiOperation({ summary: 'Mark reserved inventory READY_FOR_LOADING' }) - readyForLoading(@Param('id', ParseUUIDPipe) id: string, @Body('performedBy') performedBy?: string) { - return this.inventoryService.readyForLoading(id, performedBy); + readyForLoading( + @Param('id', ParseUUIDPipe) id: string, + @Body('performedBy') performedBy: string | undefined, + @CurrentUser() user: TCurrentUser, + ) { + return this.inventoryService.readyForLoading(id, user?.id ?? performedBy); } @Post(':id/load') @@ -366,8 +380,12 @@ export class WarehouseInventoryController { @Post(':id/ready-for-pickup') @BookingStaff(FREIGHT_PERMS.warehouseInventory.move) @ApiOperation({ summary: 'Mark inspected IMPORT inventory READY_FOR_PICKUP' }) - readyForPickup(@Param('id', ParseUUIDPipe) id: string, @Body('performedBy') performedBy?: string) { - return this.inventoryService.readyForPickup(id, performedBy); + readyForPickup( + @Param('id', ParseUUIDPipe) id: string, + @Body('performedBy') performedBy: string | undefined, + @CurrentUser() user: TCurrentUser, + ) { + return this.inventoryService.readyForPickup(id, user?.id ?? performedBy); } @Post(':id/release') @@ -429,10 +447,11 @@ export class WarehouseInventoryController { @Param('bookingId', ParseUUIDPipe) bookingId: string, @Body() dto: ApproveDeliveryDto, @Request() req: { user?: { id?: string; sub?: string } }, + @CurrentUser() user: TCurrentUser, ) { return this.inventoryService.approveDeliveryForBooking( bookingId, - req.user?.id ?? req.user?.sub, + user?.id ?? req.user?.id ?? req.user?.sub, dto.signerName, ); } @@ -494,14 +513,19 @@ export class WarehouseInventoryController { @Post(':id/deliver') @BookingStaff(FREIGHT_PERMS.warehouseInventory.deliver) @ApiOperation({ summary: 'Deliver import goods to the customer + capture proof of delivery' }) - deliver(@Param('id', ParseUUIDPipe) id: string, @Body() dto: DeliverInventoryDto) { + deliver(@Param('id', ParseUUIDPipe) id: string, @Body() dto: DeliverInventoryDto, @CurrentUser() user: TCurrentUser) { + dto.performedBy = user?.id ?? dto.performedBy; return this.inventoryService.deliver(id, dto); } @Patch(':id/dispatch') @BookingStaff(FREIGHT_PERMS.warehouseInventory.dispatch) @ApiOperation({ summary: 'Mark loaded inventory DISPATCHED (left the terminal)' }) - dispatch(@Param('id', ParseUUIDPipe) id: string, @Body('performedBy') performedBy?: string) { - return this.inventoryService.dispatch(id, performedBy); + dispatch( + @Param('id', ParseUUIDPipe) id: string, + @Body('performedBy') performedBy: string | undefined, + @CurrentUser() user: TCurrentUser, + ) { + return this.inventoryService.dispatch(id, user?.id ?? performedBy); } } diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.controller.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.controller.ts index 635ca1a10..6ea50db1b 100644 --- a/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.controller.ts +++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.controller.ts @@ -1,6 +1,8 @@ import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Query, Res } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import type { Response } from 'express'; +import { CurrentUser } from '@edr/api-common'; +import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type'; import { BookingStaff } from '../../common/booking-guards'; import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry'; @@ -17,7 +19,8 @@ export class WarehouseInvoiceController { @Post('warehouse-inventory/:id/generate-fee-invoice') @BookingStaff(FREIGHT_PERMS.warehouseFeeInvoices.generate) @ApiOperation({ summary: 'Generate a warehouse fee invoice from Batch 5 fee calculation' }) - generate(@Param('id', ParseUUIDPipe) id: string, @Body() dto: GenerateInvoiceDto) { + generate(@Param('id', ParseUUIDPipe) id: string, @Body() dto: GenerateInvoiceDto, @CurrentUser() user: TCurrentUser) { + dto.performedBy = user?.id ?? dto.performedBy; return this.invoiceService.generateForInventory(id, dto); }