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

@@ -570,6 +570,74 @@ export interface CreateBookingUnderContractDto {
notes?: string;
}
// ── Shipment / booking requests (GENERAL + customs, Path B) ─────────────────
// On a GENERAL customs contract the customer cannot book directly. They submit a
// shipment request (date + quantities); Global Logistics reviews it, then creates
// the booking on their behalf and per-booking clearance begins.
export const BOOKING_REQUEST_STATUSES = [
"PENDING",
"ACCEPTED",
"REJECTED",
"CANCELLED",
] as const;
export type BookingRequestStatus = (typeof BOOKING_REQUEST_STATUSES)[number];
/** Requested quantities — container lines OR a single bulk line (no per-unit data). */
export interface RequestedShipmentLines {
containers?: Array<{
containerSize: string;
quantity: number;
hazardousQuantity?: number;
reeferQuantity?: number;
}>;
bulk?: {
cargoTypeId?: string | null;
cargoWeightTons?: number;
itemCount?: number;
hazardousQuantity?: number;
};
}
export interface IBookingRequest extends BaseEntity {
reference: string;
contractId: string;
requestedByUserId?: string | null;
contractRouteId?: string | null;
/** Customer's preferred shipment day — informational; GL sets the binding date. */
scheduledDate?: string | null;
status: BookingRequestStatus;
requestedLines: RequestedShipmentLines;
notes?: string | null;
/** Set when GL accepts and creates the booking. */
createdBookingId?: string | null;
reviewedByStaffId?: string | null;
reviewedAt?: string | null;
reviewNote?: string | null;
}
export interface CreateBookingRequestDto {
contractRouteId?: string;
scheduledDate?: string;
containers?: Array<{
containerSize: string;
quantity: number;
hazardousQuantity?: number;
reeferQuantity?: number;
}>;
bulk?: {
cargoTypeId?: string | null;
cargoWeightTons?: number;
itemCount?: number;
hazardousQuantity?: number;
};
notes?: string;
}
export interface ReviewBookingRequestDto {
note?: string;
}
// ── Clearance review / finalize DTOs (Path B) ───────────────────────────────
export interface ReviewContractClearanceDocumentDto {

View File

@@ -592,6 +592,23 @@ export interface AvailableDaysQuery {
destinationYardId?: string;
}
/**
* Cargo-aware availability query: beyond the route yards it carries the cargo
* sizing so the server only returns days where a train has remaining capacity
* AND enough matching-type wagons. Response reuses {@link AvailableDaysResponse}.
*/
export interface AvailableDaysForCargoQuery {
originYardId?: string;
destinationYardId?: string;
freightType: "CONTAINER" | "BULK";
/** Bulk cargo type code (e.g. "COFFEE"); ignored for container freight. */
cargoTypeCode?: string;
/** Total bulk weight in tons. */
totalWeightTons?: number;
/** Container lines (size + quantity) for container freight. */
containers?: { containerSize: string; quantity: number }[];
}
/**
* Day-level booking pool: the EAT calendar days that have at least one OPEN
* departure on a route. `days` are `yyyy-MM-dd` strings, e.g. `["2026-06-20"]`.