add booking request functionality for GENERAL customs contracts

- Create migration for booking_requests table with necessary fields and indexes.
- Implement BookingRequestRepository for database operations related to booking requests.
- Develop BookingRequestService to handle business logic for submitting, accepting, rejecting, and canceling booking requests.
- Create DTOs for creating booking requests and reviewing them.
- Define BookingRequest entity to map to the booking_requests table.
- Add UI components for managing shipment requests, including detail and list pages.
- Implement OperationDatePicker component for selecting available shipment days.
This commit is contained in:
Marshal
2026-06-29 09:30:44 +00:00
parent aeb5e0046e
commit 0f7cac2b68
46 changed files with 2665 additions and 992 deletions

View File

@@ -43,6 +43,7 @@ import { ContractClearanceService } from './contract-clearance.service';
import { ContractBookingService } from './contract-booking.service';
import { ClearanceMilestoneService } from './clearance-milestone.service';
import { GlOperationsService } from './gl-operations.service';
import { BookingRequestService } from './booking-request.service';
import { SignaturesService } from '../signatures/signatures.service';
import { CreateContractDto } from './dto/create-contract.dto';
import { UpdateContractDto } from './dto/update-contract.dto';
@@ -58,6 +59,10 @@ import { SignContractDto } from './dto/sign-contract.dto';
import { ReviewClearanceDocumentDto } from './dto/review-clearance-document.dto';
import { RenewContractDto } from './dto/renew-contract.dto';
import { CreateBookingUnderContractDto } from './dto/create-booking-under-contract.dto';
import {
CreateBookingRequestDto,
ReviewBookingRequestDto,
} from './dto/create-booking-request.dto';
import {
AdviseDutyDto,
AssignRiskDto,
@@ -78,9 +83,78 @@ export class ContractsController {
private readonly contractBookingService: ContractBookingService,
private readonly milestoneService: ClearanceMilestoneService,
private readonly glOperationsService: GlOperationsService,
private readonly bookingRequestService: BookingRequestService,
private readonly signaturesService: SignaturesService,
) {}
// ── Shipment / booking requests (GENERAL + customs, Path B) ───────────────
// STATIC routes declared before any `:id`-param route so Nest matches them
// (mirrors the clearance/queue ordering below).
@Get('booking-requests/queue')
@BookingStaff(FREIGHT_PERMS.contracts.createBooking)
@ApiOperation({ summary: 'GL queue: pending shipment requests across contracts' })
bookingRequestQueue() {
return this.bookingRequestService.queue();
}
@Get('booking-requests/:reqId')
@ApiOperation({ summary: 'A single shipment request' })
getBookingRequest(@Param('reqId', ParseUUIDPipe) reqId: string) {
return this.bookingRequestService.findOne(reqId);
}
@Post('booking-requests/:reqId/accept')
@BookingStaff(FREIGHT_PERMS.contracts.createBooking)
@ApiOperation({ summary: 'GL marks a shipment request accepted + links the created booking' })
acceptBookingRequest(
@Param('reqId', ParseUUIDPipe) reqId: string,
@Body() body: { bookingId: string },
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingRequestService.accept(
reqId,
body.bookingId,
resolveAuthUserId(user),
);
}
@Post('booking-requests/:reqId/reject')
@BookingStaff(FREIGHT_PERMS.contracts.createBooking)
@ApiOperation({ summary: 'GL rejects a shipment request' })
rejectBookingRequest(
@Param('reqId', ParseUUIDPipe) reqId: string,
@Body() dto: ReviewBookingRequestDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingRequestService.reject(reqId, dto.note, resolveAuthUserId(user));
}
@Post('booking-requests/:reqId/cancel')
@ApiOperation({ summary: 'Customer cancels their own pending shipment request' })
cancelBookingRequest(
@Param('reqId', ParseUUIDPipe) reqId: string,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingRequestService.cancel(reqId, resolveAuthUserId(user));
}
@Post(':id/booking-requests')
@ApiOperation({ summary: 'Customer submits a shipment request on a GENERAL customs contract' })
submitBookingRequest(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: CreateBookingRequestDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingRequestService.submit(id, dto, resolveAuthUserId(user));
}
@Get(':id/booking-requests')
@ApiOperation({ summary: 'List the shipment requests on a contract' })
listBookingRequests(@Param('id', ParseUUIDPipe) id: string) {
return this.bookingRequestService.listForContract(id);
}
@Post()
@UseInterceptors(AnyFilesInterceptor())
@ApiConsumes('multipart/form-data')