diff --git a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx
index 477ec2bbb..783554b85 100644
--- a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx
+++ b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx
@@ -412,10 +412,9 @@ function NewShipmentBookingForm({
mode: "onChange",
});
- // 20ft containers ride two per wagon. An odd total no longer blocks the
- // booking — the server auto-pairs it with another customer's odd booking, or
- // parks it as PENDING_CONSOLIDATION until one shows up (same consolidation
- // gate the direct-booking flow already uses).
+ // 20ft containers ride two per wagon. On the COMPLETION page an odd total
+ // hard-blocks submit — odd (consolidated) bookings are GL's job in the
+ // backoffice. The direct-booking route keeps the consolidation notice.
const watchedContainers = form.watch("containers");
const ft20Total =
contract.freightType === "CONTAINER"
@@ -424,6 +423,7 @@ function NewShipmentBookingForm({
.reduce((sum, l) => sum + Number(l.quantity || 0), 0)
: 0;
const hasOdd20ft = ft20Total % 2 === 1;
+ const blockOdd20ft = hasOdd20ft && Boolean(completeBookingId);
// COMPLETION mode: fetch the booking — a changes-requested resubmit prefills
// the form from it and shows the operations note + uploaded documents.
@@ -580,6 +580,9 @@ function NewShipmentBookingForm({
// run it for every freight type; container contracts additionally get
// overweight warnings + 20ft pairing hard-blocks surfaced in the modal.
const handleReview = form.handleSubmit((values) => {
+ // Completion: odd 20ft counts never reach review — the red alert next to
+ // the button explains; odd (consolidated) bookings are GL's backoffice job.
+ if (blockOdd20ft) return;
setPendingValues(values);
validateMutation.reset();
validateMutation.mutate(buildDto(values));
@@ -744,7 +747,17 @@ function NewShipmentBookingForm({
Fix the highlighted fields before reviewing the price.
) : null}
- {hasOdd20ft ? (
+ {blockOdd20ft ? (
+ }
+ mb="sm"
+ >
+ {`${ft20Total} is an odd number of 20ft containers. 20ft containers travel two per wagon, so they must be booked in even numbers — add one more or remove one (e.g. ${ft20Total + 1} or ${ft20Total - 1}).`}
+
+ ) : hasOdd20ft ? (