fix issue

This commit is contained in:
Marshal
2026-08-22 00:49:53 +00:00
parent bad418d79e
commit b6c1efa043
22 changed files with 1448 additions and 88 deletions

View File

@@ -35,11 +35,34 @@ export type DeferredBookingRow = {
shortage?: BookingWagonShortage | null;
};
/** A booking the customer has already paid for. */
const isPaid = (booking: Booking): boolean =>
booking.paymentStatus === 'PAID' || booking.status === 'PAID';
/**
* Seating order for the wagon planner.
*
* Government first, then PAID bookings, then priority score, then date.
*
* Payment ranks above priority score on purpose: money has changed hands and
* the customer was promised space on THIS train. Without it the planner
* seated an unpaid booking that merely arrived earlier and left a paid one
* with no wagon — the reported S-2026-00045 case, where a paid 695T bulk
* booking lost every wagon to unpaid container bookings and vanished from
* the train with free PW2 still standing in the consist.
*
* This only decides who is seated FIRST when the train is oversubscribed. It
* never invents capacity: an oversubscribed train still defers someone, and
* that someone is now the party who has not paid.
*/
export function sortBookingsForScheduling(bookings: Booking[]): Booking[] {
return [...bookings].sort((a, b) => {
const govDiff = Number(Boolean(b.isGovernment)) - Number(Boolean(a.isGovernment));
if (govDiff !== 0) return govDiff;
const paidDiff = Number(isPaid(b)) - Number(isPaid(a));
if (paidDiff !== 0) return paidDiff;
const priorityDiff = (b.priorityScore ?? 0) - (a.priorityScore ?? 0);
if (priorityDiff !== 0) return priorityDiff;