Files
edr-platform/apps/edr-freight-api/src/modules/last-mile-requests/last-mile-requests.controller.ts

87 lines
3.4 KiB
TypeScript

import { Body, Controller, Get, Param, ParseUUIDPipe, Post, Query } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '@edr/api-common';
import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type';
import { LastMileRequestStatus } from '@edr/types';
import { BookingStaff } from '../../common/booking-guards';
import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry';
import { ApproveLastMileRequestDto } from './dto/approve-last-mile-request.dto';
import { RejectLastMileRequestDto } from './dto/reject-last-mile-request.dto';
import { SubmitLastMileRequestDto } from './dto/submit-last-mile-request.dto';
import { LastMileRequestsService } from './last-mile-requests.service';
@ApiTags('last-mile-requests')
@ApiBearerAuth()
@Controller('last-mile-requests')
export class LastMileRequestsController {
constructor(private readonly requestsService: LastMileRequestsService) {}
@Get()
@BookingStaff(FREIGHT_PERMS.lastMile.requestView)
@ApiOperation({ summary: 'List last-mile confirmation requests' })
findAll(
@Query('status') status?: string,
@Query('bookingId') bookingId?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.requestsService.findAll({
status: status as LastMileRequestStatus | undefined,
bookingId,
page: page ? parseInt(page, 10) : undefined,
pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
});
}
@Get('free-truck-count')
@BookingStaff(FREIGHT_PERMS.lastMile.requestView)
@ApiOperation({ summary: 'Free (ACTIVE + unassigned) trucks — informational context for approval' })
freeTruckCount() {
return this.requestsService.freeTruckCount().then((count) => ({ count }));
}
@Get(':id')
@BookingStaff(FREIGHT_PERMS.lastMile.requestView)
@ApiOperation({ summary: 'Get a last-mile confirmation request by ID' })
findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.requestsService.findById(id);
}
// No @BookingStaff — the customer (portal) fills this, not backoffice staff.
// TODO: integrate @edr/auth — @CurrentUser is a stub until then; the service
// still cross-checks the request's booking against the resolved company.
@Post(':id/submit')
@ApiOperation({ summary: "Customer confirms which containers go via EDR last-mile" })
submit(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: SubmitLastMileRequestDto,
@CurrentUser() user: TCurrentUser,
) {
return this.requestsService.submit(id, user?.id ?? null, dto.containerNumbers);
}
@Post(':id/approve')
@BookingStaff(FREIGHT_PERMS.lastMile.requestApprove)
@ApiOperation({ summary: 'Truck & Machinery chief approves the request — generates the advance invoice' })
approve(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: ApproveLastMileRequestDto,
@CurrentUser() user: TCurrentUser,
) {
return this.requestsService.approve(id, user?.id ?? null, dto.advanceAmount);
}
@Post(':id/reject')
@BookingStaff(FREIGHT_PERMS.lastMile.requestApprove)
@ApiOperation({ summary: 'Truck & Machinery chief rejects the request with a reason' })
reject(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: RejectLastMileRequestDto,
@CurrentUser() user: TCurrentUser,
) {
return this.requestsService.reject(id, user?.id ?? null, dto.reason);
}
}