import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseUUIDPipe, Patch, Post, Query, } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { TrainSchedulingManage, TrainSchedulingView } from '../../common/booking-guards'; import { CreateFirstMileDto } from './dto/create-first-mile.dto'; import { UpdateFirstMileDto } from './dto/update-first-mile.dto'; import { AllocateFirstMileContainersDto } from './dto/allocate-containers.dto'; import { FirstMileStatus } from './entities/first-mile.entity'; import { FirstMileService } from './first-mile.service'; import { FirstMileInvoiceService } from './first-mile-invoice.service'; @ApiTags('first-mile') @ApiBearerAuth() @Controller('first-mile') @TrainSchedulingView() export class FirstMileController { constructor( private readonly firstMileService: FirstMileService, private readonly firstMileInvoiceService: FirstMileInvoiceService, ) {} @Get() @ApiOperation({ summary: 'List first-mile legs' }) findAll( @Query('status') status?: string, @Query('bookingId') bookingId?: string, @Query('vehicleId') vehicleId?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, @Query('sortBy') sortBy?: string, @Query('sortOrder') sortOrder?: 'ASC' | 'DESC', ) { return this.firstMileService.findAll({ status: status as FirstMileStatus | undefined, bookingId, vehicleId, page: page ? parseInt(page, 10) : undefined, pageSize: pageSize ? parseInt(pageSize, 10) : undefined, sortBy, sortOrder, }); } @Get(':id') @ApiOperation({ summary: 'Get a first-mile leg by ID' }) findOne(@Param('id', ParseUUIDPipe) id: string) { return this.firstMileService.findById(id); } @Post('accept/:reference') @TrainSchedulingManage() @ApiOperation({ summary: 'Accept a paid booking and create a first-mile leg' }) acceptBooking(@Param('reference') reference: string) { return this.firstMileService.acceptBookingByReference(reference); } @Post() @TrainSchedulingManage() @ApiOperation({ summary: 'Create a first-mile leg' }) create(@Body() dto: CreateFirstMileDto) { return this.firstMileService.create(dto); } @Patch(':id') @TrainSchedulingManage() @ApiOperation({ summary: 'Update a first-mile leg' }) async update(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateFirstMileDto) { const record = await this.firstMileService.update(id, dto); // Auto-generate invoice if distance or payment was updated if (dto.exactKm !== undefined || dto.remainingPayment !== undefined) { await this.firstMileInvoiceService.ensureInvoiceFor(record); } return record; } @Delete(':id') @TrainSchedulingManage() @HttpCode(HttpStatus.NO_CONTENT) @ApiOperation({ summary: 'Soft-delete a first-mile leg' }) remove(@Param('id', ParseUUIDPipe) id: string) { return this.firstMileService.remove(id); } @Post(':firstMileId/allocate-containers') @TrainSchedulingManage() @ApiOperation({ summary: 'Allocate containers to vehicles for a first-mile leg' }) allocateContainers( @Param('firstMileId', ParseUUIDPipe) firstMileId: string, @Body() dto: AllocateFirstMileContainersDto, ) { return this.firstMileService.allocateContainers(firstMileId, dto.allocations); } }