implement intercity booking management and booking window websocket integration

This commit is contained in:
Marshal
2026-07-06 13:28:21 +00:00
parent 907f4edc0a
commit fed5f2f43f
46 changed files with 1772 additions and 101 deletions

View File

@@ -0,0 +1,41 @@
/**
* Shared contracts for live booking-window pushes.
*
* The freight API emits one event whenever a schedule's booking-window state
* changes (phase transition, open/close, cycle reopen). Portal home and the
* backoffice GL windows section subscribe and refresh instantly instead of
* waiting for their poll interval.
*/
/** Booking-window lifecycle phase persisted on a train schedule. */
export type BookingWindowPhase =
| "PRE_WINDOW"
| "OPEN"
| "DOC_REVIEW"
| "PAYMENT"
| "CLOSED_FOR_DAY"
| "DONE";
/** Payload pushed on every booking-window state change. */
export interface BookingWindowPhaseEvent {
scheduleId: string;
originYardId: string;
destinationYardId: string;
direction: string | null;
phase: BookingWindowPhase;
bookingWindowStatus: string | null;
bookingCycleNo: number;
windowOpensAt: string | null;
windowClosesAt: string | null;
docReviewEndsAt: string | null;
paymentPhaseEndsAt: string | null;
scheduledDepartureDate: string | null;
}
/** Socket.io event names pushed server → client on the booking-windows namespace. */
export const BOOKING_WINDOW_WS_EVENTS = {
PHASE: "booking-window:phase",
} as const;
/** Socket.io namespace the booking-window gateway listens on. */
export const BOOKING_WINDOW_WS_NAMESPACE = "booking-windows";

View File

@@ -695,8 +695,8 @@ export interface CreateBulkLineDto {
export interface CreateBookingUnderContractDto {
/** Required for GENERAL multi-route contracts; ONE_TIME auto-selected. */
contractRouteId?: string;
/** Binding shipment day. */
scheduledDate: string;
/** Binding shipment day. Omitted for intercity (DOMESTIC) bookings — staff assign a passing train later. */
scheduledDate?: string;
containers?: CreateBookingContainerLineDto[];
bulkLines?: CreateBulkLineDto[];
notes?: string;

View File

@@ -8,6 +8,7 @@ export * from "./etrade";
export * from "./contracts";
export * from "./clearance-files.catalog";
export * from "./notifications";
export * from "./booking-window-ws";
export enum TradeDirection {
IMPORT = "IMPORT",
@@ -220,6 +221,24 @@ export enum WagonReadiness {
export type ScheduleTradeDirection = "IMPORT" | "EXPORT" | "DOMESTIC";
/**
* The only two countries on the EDR line. Yard `country` is constrained to
* these values; route trade direction is derived from the origin/destination
* yard countries (ET→DJ = EXPORT, DJ→ET = IMPORT, same-country = DOMESTIC,
* shown as "Intercity" in UIs and currently disabled for scheduling/contracts).
*/
export enum YardCountry {
ETHIOPIA = "Ethiopia",
DJIBOUTI = "Djibouti",
}
/** UI label for a schedule/route trade direction (DOMESTIC displays as Intercity). */
export const TRADE_DIRECTION_LABELS: Record<ScheduleTradeDirection, string> = {
IMPORT: "Import",
EXPORT: "Export",
DOMESTIC: "Intercity",
};
export enum TrainCheckpointKind {
Departed = "DEPARTED",
Passed = "PASSED",