mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
Empties had no way onto a departure: the return record could name a train but nothing seated it on a wagon. Export schedules now expose a loading action that packs selected returns onto free wagons at one 40ft or two 20ft each, enforced both in the picker and in the API (existing empties on the schedule count against their wagon). Adds container_size, train_schedule_id and wagon_sequence_no to freight.empty_container_returns.
125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
import { Body, Controller, Get, Param, ParseUUIDPipe, Post, Query } from '@nestjs/common';
|
||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||
|
||
import { BookingStaff } from '../../common/booking-guards';
|
||
import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry';
|
||
import {
|
||
AssignCustomsRiskDto,
|
||
CreateDjiboutiIncidentDto,
|
||
CreateEmptyContainerReturnDto,
|
||
ImportOperationActionDto,
|
||
LoadEmptyContainersOnTrainDto,
|
||
RecordDeclarationDto,
|
||
UpdateEmptyContainerReturnStatusDto,
|
||
UploadImportCustomsDocumentDto,
|
||
} from './dto/import-operations.dto';
|
||
import { ImportOperationsService } from './import-operations.service';
|
||
|
||
@ApiTags('import-operations')
|
||
@ApiBearerAuth()
|
||
@Controller('import-operations')
|
||
// Post-booking customs / import-operations actions are GL/Ops work, mirroring the
|
||
// contracts controller's GL operational endpoints (risk, duty, milestones).
|
||
@BookingStaff(FREIGHT_PERMS.bookings.operations)
|
||
export class ImportOperationsController {
|
||
constructor(private readonly service: ImportOperationsService) {}
|
||
|
||
@Get('djibouti-incidents')
|
||
@ApiOperation({ summary: 'Batch 8: list Djibouti import incidents' })
|
||
listIncidents(@Query('bookingId') bookingId?: string) {
|
||
return this.service.listIncidents(bookingId);
|
||
}
|
||
|
||
@Post('djibouti-incidents')
|
||
@ApiOperation({ summary: 'Batch 8: report a Djibouti import incident / exception' })
|
||
createIncident(@Body() dto: CreateDjiboutiIncidentDto) {
|
||
return this.service.createIncident(dto);
|
||
}
|
||
|
||
@Get('customs/:bookingId')
|
||
@ApiOperation({ summary: 'Batch 12: import customs finalization state' })
|
||
getCustoms(@Param('bookingId', ParseUUIDPipe) bookingId: string) {
|
||
return this.service.getCustoms(bookingId);
|
||
}
|
||
|
||
@Post('customs/:bookingId/documents')
|
||
@ApiOperation({ summary: 'Batch 12: upload IM4/IM5/T1/permit/payment-slip documents' })
|
||
uploadCustomsDocument(
|
||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||
@Body() dto: UploadImportCustomsDocumentDto,
|
||
) {
|
||
return this.service.uploadCustomsDocument(bookingId, dto);
|
||
}
|
||
|
||
@Post('customs/:bookingId/declaration')
|
||
@ApiOperation({ summary: 'Batch 12: record declaration serial number' })
|
||
recordDeclaration(
|
||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||
@Body() dto: RecordDeclarationDto,
|
||
) {
|
||
return this.service.recordDeclaration(bookingId, dto);
|
||
}
|
||
|
||
@Post('customs/:bookingId/notify-duties-taxes')
|
||
@ApiOperation({ summary: 'Batch 12: notify duties and taxes' })
|
||
notifyDutiesTaxes(
|
||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||
@Body() dto: ImportOperationActionDto,
|
||
) {
|
||
return this.service.notifyDutiesTaxes(bookingId, dto);
|
||
}
|
||
|
||
@Post('customs/:bookingId/duties-taxes-paid')
|
||
@ApiOperation({ summary: 'Batch 12: mark duties and taxes paid' })
|
||
markDutiesTaxesPaid(
|
||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||
@Body() dto: ImportOperationActionDto,
|
||
) {
|
||
return this.service.markDutiesTaxesPaid(bookingId, dto);
|
||
}
|
||
|
||
@Post('customs/:bookingId/risk')
|
||
@ApiOperation({ summary: 'Batch 12: assign customs risk' })
|
||
assignRisk(@Param('bookingId', ParseUUIDPipe) bookingId: string, @Body() dto: AssignCustomsRiskDto) {
|
||
return this.service.assignRisk(bookingId, dto);
|
||
}
|
||
|
||
@Post('customs/:bookingId/release-permitted')
|
||
@ApiOperation({ summary: 'Batch 12: mark import release permitted' })
|
||
markReleasePermitted(
|
||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||
@Body() dto: ImportOperationActionDto,
|
||
) {
|
||
return this.service.markReleasePermitted(bookingId, dto);
|
||
}
|
||
|
||
@Get('empty-container-returns')
|
||
@ApiOperation({ summary: 'Batch 16: list empty container returns' })
|
||
listEmptyReturns() {
|
||
return this.service.listEmptyReturns();
|
||
}
|
||
|
||
@Post('empty-container-returns')
|
||
@ApiOperation({ summary: 'Batch 16: create an empty container return record' })
|
||
createEmptyReturn(@Body() dto: CreateEmptyContainerReturnDto) {
|
||
return this.service.createEmptyReturn(dto);
|
||
}
|
||
|
||
@Post('empty-container-returns/load-on-train')
|
||
@ApiOperation({
|
||
summary: 'Load returned empties onto an export train (1×40ft or 2×20ft per wagon)',
|
||
})
|
||
loadEmptyReturnsOnTrain(@Body() dto: LoadEmptyContainersOnTrainDto) {
|
||
return this.service.loadEmptyReturnsOnTrain(dto);
|
||
}
|
||
|
||
@Post('empty-container-returns/:id/status')
|
||
@ApiOperation({ summary: 'Batch 16: advance empty container return workflow' })
|
||
updateEmptyReturnStatus(
|
||
@Param('id', ParseUUIDPipe) id: string,
|
||
@Body() dto: UpdateEmptyContainerReturnStatusDto,
|
||
) {
|
||
return this.service.updateEmptyReturnStatus(id, dto);
|
||
}
|
||
}
|