Add booking window management and locomotive scheduling features

- Implemented migration to release stuck assigned locomotives.
- Added schedule window phases to train schedules.
- Created booking batch offers table for partial capacity bookings.
- Developed BookingSplitService to handle partial booking offers and splits.
- Introduced BookingWindowService to manage booking window lifecycle and transitions.
- Added BookingBatchOffer entity to represent offers made during booking splits.
- Enhanced locomotive options with warnings for scheduling.
- Created UpcomingWindowsSection component to display upcoming booking windows.
This commit is contained in:
Marshal
2026-07-03 03:36:06 +00:00
parent 18c158fb61
commit 56de90892d
41 changed files with 2480 additions and 124 deletions

View File

@@ -360,6 +360,14 @@ export const api = {
() => TRAIN_SCHEDULING_INVALIDATIONS,
),
completeDocReview: endpoint<string, BatchBoardScheduleDetail>(
"train-scheduling",
"doc-review-complete",
(id) => trainSchedulingService.completeDocReview(id),
undefined,
() => TRAIN_SCHEDULING_INVALIDATIONS,
),
setBookingWindow: endpoint<
{ id: string; status: "OPEN" | "CLOSED" },
TrainScheduleDetail

View File

@@ -158,6 +158,20 @@ export const trainSchedulingService = {
return unwrap(response.data);
},
/**
* Staff finished reviewing documents early — runs the batch immediately
* for the schedule's whole route-day group.
*/
completeDocReview: async (
scheduleId: string,
): Promise<BatchBoardScheduleDetail> => {
const response = await client.post<BatchBoardScheduleDetail>(
URL_CONSTANTS.TRAIN_SCHEDULING.DOC_REVIEW_COMPLETE(scheduleId),
{},
);
return unwrap(response.data);
},
runAllocation: async (
scheduleId: string,
): Promise<WagonAllocationAttemptResult> => {
@@ -494,16 +508,7 @@ export const trainSchedulingService = {
},
updateGlobalRules: async (
payload: Partial<
Pick<
TrainSchedulingGlobalRules,
| "maxTrainLengthMeters"
| "maxTrainWeightTons"
| "maxWagonsPerTrain"
| "max20ftContainerWeightTons"
| "max20ftPairWeightDiffTons"
>
>,
payload: Partial<Omit<TrainSchedulingGlobalRules, "id">>,
): Promise<TrainSchedulingGlobalRules> => {
const response = await client.patch<TrainSchedulingGlobalRules>(
URL_CONSTANTS.TRAIN_SCHEDULING.GLOBAL_RULES,