mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
103 lines
4.0 KiB
TypeScript
103 lines
4.0 KiB
TypeScript
/**
|
|
* Tunables for the demand-batching booking → allocation flow.
|
|
* Times run in EAT so window boundaries match the local operating clock.
|
|
*
|
|
* Cadence and pay-window durations moved to the train_scheduling_global_rules
|
|
* table (TrainSchedulingService.getWindowConfig) — the window engine
|
|
* (BookingWindowService) drives all timing off that config.
|
|
*/
|
|
|
|
export const BATCH_TIMEZONE = "Africa/Addis_Ababa";
|
|
|
|
/** How long before the pay deadline the one reminder notification goes out. */
|
|
export const PAYMENT_REMINDER_LEAD_MS = 10 * 60_000;
|
|
|
|
/** Drain tail applied to every pay window when FREIGHT_PAYMENT_DRAIN_MINUTES is unset. */
|
|
export const DEFAULT_PAYMENT_DRAIN_MINUTES = 7;
|
|
|
|
/**
|
|
* Drain tail on every pay window, in ms. Read per call so the env var can be
|
|
* changed without a rebuild (and so tests can set it).
|
|
*/
|
|
export function paymentDrainMs(): number {
|
|
// An empty/blank value is UNSET, not zero — a bare `FREIGHT_PAYMENT_DRAIN_MINUTES=`
|
|
// left in a .env must not silently disable the drain (Number('') is 0).
|
|
const raw = process.env.FREIGHT_PAYMENT_DRAIN_MINUTES?.trim();
|
|
const minutes = raw ? Number(raw) : NaN;
|
|
return (
|
|
(Number.isFinite(minutes) && minutes >= 0
|
|
? minutes
|
|
: DEFAULT_PAYMENT_DRAIN_MINUTES) * 60_000
|
|
);
|
|
}
|
|
|
|
/**
|
|
* ISO timestamp of the end of a pay window's drain tail, for client display
|
|
* (the "payment processing" countdown). Null in ⇒ null out.
|
|
*/
|
|
export function paymentDrainEndsAtIso(
|
|
deadline: Date | string | null | undefined,
|
|
): string | null {
|
|
if (deadline == null) return null;
|
|
const ms = new Date(deadline).getTime();
|
|
if (!Number.isFinite(ms)) return null;
|
|
return new Date(ms + paymentDrainMs()).toISOString();
|
|
}
|
|
|
|
/**
|
|
* A pay window AND its drain tail have closed.
|
|
*
|
|
* Settlement is asynchronous (provider confirm → payment-api → outbox relay), so
|
|
* a payment made in the last seconds of the window lands after `paymentDeadline`.
|
|
* The drain defers the WHOLE expiry pipeline — wagons stay held, the waiting list
|
|
* is not promoted, the window cycle does not conclude — so that settlement still
|
|
* has a live booking to land on. A payment that arrives even later is not lost
|
|
* either: it settles the expired invoice and revives the booking (see
|
|
* BillingService.settleByPaymentId + BookingInvoiceService.advanceBookingOnPayment).
|
|
*
|
|
* No deadline ⇒ never lapsed; callers decide what an unknown deadline means.
|
|
*/
|
|
export function payWindowLapsed(
|
|
deadline: Date | null | undefined,
|
|
now: number,
|
|
drainMs: number = paymentDrainMs(),
|
|
): boolean {
|
|
return deadline != null && deadline.getTime() + drainMs <= now;
|
|
}
|
|
|
|
/** Fallback wagons-per-booking when a booking has no computed `wagonsRequired`. */
|
|
export const DEFAULT_WAGONS_PER_BOOKING = 1;
|
|
|
|
/**
|
|
* Fallback per-wagon length (m) for the batch length budget when global rules don't yet
|
|
* define maxTrainLength / maxWagons to derive it from. Used only to estimate train length
|
|
* against the locomotive's max train length.
|
|
*/
|
|
export const DEFAULT_WAGON_LENGTH_METERS = 14;
|
|
|
|
/** Default NW5 flat wagon length for container bookings (m). */
|
|
export const DEFAULT_CONTAINER_WAGON_LENGTH_METERS = 14;
|
|
|
|
/** Default CW3 covered wagon length for bulk bookings (m). */
|
|
export const DEFAULT_BULK_WAGON_LENGTH_METERS = 14;
|
|
|
|
/**
|
|
* Fallback tare weights (T) matching the length fallbacks above. The locomotive
|
|
* pull limit is a GROSS limit, so a booking's weight budget must include the
|
|
* empty weight of every wagon it occupies — not just its cargo.
|
|
*/
|
|
export const DEFAULT_CONTAINER_WAGON_TARE_TONS = 22.4;
|
|
|
|
/** Default CW3 gondola tare for bulk bookings (T). */
|
|
export const DEFAULT_BULK_WAGON_TARE_TONS = 23.4;
|
|
|
|
/**
|
|
* Fallback rated payloads (T) matching the tare fallbacks above. A bulk booking's
|
|
* wagon count is its cargo divided by this, so a zero here would make the count
|
|
* infinite — callers must floor it at a positive number.
|
|
*/
|
|
export const DEFAULT_CONTAINER_WAGON_CAPACITY_TONS = 70;
|
|
|
|
/** Default CW3 gondola rated payload for bulk bookings (T). */
|
|
export const DEFAULT_BULK_WAGON_CAPACITY_TONS = 60;
|