From ff039bd4407fe70331fa436fb4c21c1ea73988c2 Mon Sep 17 00:00:00 2001 From: Marshal Date: Mon, 22 Jun 2026 11:40:35 +0000 Subject: [PATCH] feat(bookings): update payment eligibility logic for general contracts and one-time bookings --- .../modules/train-scheduling/booking-batch.constants.ts | 3 ++- .../bookings/BookingDetailPage/ReadonlyBookingView.tsx | 9 ++++++++- .../portal/src/pages/bookings/MyBookings.tsx | 8 +++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.constants.ts b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.constants.ts index eda168e03..5c9cb6119 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.constants.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/booking-batch.constants.ts @@ -3,10 +3,11 @@ * Times run in EAT so the 07:00/10:00/… boundaries match the local operating clock. */ -/** Batch boundaries — every 3h from 07:00 (the 07:00–10:00 intake settles at 10:00, etc.). */ +/** Batch boundaries — every 3h from 00:00 (00–03, 03–06, … 21–24), matching the board windows. */ // export const BATCH_CRON = '0 7,10,13,16,19,22 * * *'; // export const BATCH_CRON = '*/3 * * * *'; export const BATCH_CRON = '*/5 * * * *'; +// export const BATCH_CRON = '0 */3 * * *';// export const BATCH_TIMEZONE = 'Africa/Addis_Ababa'; diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx index 4120dec7f..ca7346a83 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx @@ -50,8 +50,15 @@ export function ReadonlyBookingView({ booking }: { booking: Freight.IBooking }) }); const pricing = booking.pricingBreakdown; + // A general contract is paid once it's FULLY_EXECUTED (signed) — it never + // enters batch selection. A one-time booking can only pay once it's been + // SELECTED_FOR_BATCH (assigned a slot with a pay window). + const isGeneralContract = booking.bookingType === "GENERAL_CONTRACT"; const canPay = - status === "SELECTED_FOR_BATCH" && booking.paymentStatus !== "PAID"; + booking.paymentStatus !== "PAID" && + (isGeneralContract + ? status === "FULLY_EXECUTED" + : status === "SELECTED_FOR_BATCH"); const showCountdown = canPay && !!booking.paymentDeadline; const isExpired = status === "EXPIRED"; const isPendingConsolidation = status === "PENDING_CONSOLIDATION"; diff --git a/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx b/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx index d4d8a75ec..5d7200008 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx @@ -180,6 +180,9 @@ function PrimaryAction({ }) { const { status, id } = booking; const go = () => onNavigate(`/bookings/${id}`); + // A general contract is payable as soon as it's FULLY_EXECUTED (signed); a + // one-time booking only after it's SELECTED_FOR_BATCH. + const isGeneralContract = booking.bookingType === "GENERAL_CONTRACT"; if (status === "DRAFT") { return (