diff --git a/apps/edr-freight-web/portal/src/pages/contracts/ContractDetailPage.tsx b/apps/edr-freight-web/portal/src/pages/contracts/ContractDetailPage.tsx index 6ceb1fb69..ded69afb1 100644 --- a/apps/edr-freight-web/portal/src/pages/contracts/ContractDetailPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/contracts/ContractDetailPage.tsx @@ -64,6 +64,7 @@ import { } from "@/pages/bookings/booking-display"; import { InitiateBookingButton } from "@/components/customer-actions/ContractCustomerAction"; import { formatRateUnit } from "./new-contract-form/unit-rates"; +import { formatAmount } from "./new-shipment-form/total"; import { bookingDocNoun } from "@/pages/bookings/clearance/bookingNextAction"; import { getContractBookingAction } from "./contract-booking-action"; import { closedWindowMessage, hasOpenWindow } from "./booking-window"; @@ -719,7 +720,7 @@ export default function ContractDetailPage() { )} - {(item.unitPrice ?? 0).toLocaleString()} {pricing.currency}{" "} + {formatAmount(item.unitPrice)} {pricing.currency}{" "} / {formatRateUnit(item.unit)} @@ -1336,9 +1337,7 @@ export default function ContractDetailPage() { whiteSpace: "nowrap", }} > - {amount > 0 - ? `ETB ${amount.toLocaleString()}` - : "—"} + {amount > 0 ? `ETB ${formatAmount(amount)}` : "—"} 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 a5b29a299..347cdd2bb 100644 --- a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx @@ -75,7 +75,7 @@ import { createShipmentFormSchema, initialShipmentFormValues, } from "./new-shipment-form/schema"; -import { computeShipmentTotal } from "./new-shipment-form/total"; +import { computeShipmentTotal, formatAmount } from "./new-shipment-form/total"; import { downloadContainerImportTemplate, parseContainerExcel, @@ -1014,7 +1014,7 @@ function PriceConfirmModal({ ))} {overweightSurchargeAmount > 0 - ? `An overweight surcharge of ${overweightSurchargeAmount.toLocaleString()} ${ + ? `An overweight surcharge of ${formatAmount(overweightSurchargeAmount)} ${ validation?.currency ?? total?.currency ?? "" } applies (included in the total below). You can still submit, or go back and adjust weights.` : "An overweight surcharge applies. You can still submit, or go back and adjust weights."} @@ -1038,7 +1038,7 @@ function PriceConfirmModal({ {line.quantity.toLocaleString()} ×{" "} - {line.unitPrice.toLocaleString()} {total.currency} ·{" "} + {formatAmount(line.unitPrice)} {total.currency} ·{" "} {formatRateUnit(line.unit)} @@ -1048,7 +1048,7 @@ function PriceConfirmModal({ c="#10202F" style={{ whiteSpace: "nowrap" }} > - {line.amount.toLocaleString()} {total.currency} + {formatAmount(line.amount)} {total.currency} ))} @@ -1070,7 +1070,7 @@ function PriceConfirmModal({ Total - {total.total.toLocaleString()}{" "} + {formatAmount(total.total)}{" "} {total.currency} diff --git a/apps/edr-freight-web/portal/src/pages/contracts/new-shipment-form/total.ts b/apps/edr-freight-web/portal/src/pages/contracts/new-shipment-form/total.ts index cbe9ae083..7c80ca1d6 100644 --- a/apps/edr-freight-web/portal/src/pages/contracts/new-shipment-form/total.ts +++ b/apps/edr-freight-web/portal/src/pages/contracts/new-shipment-form/total.ts @@ -15,6 +15,19 @@ export interface ShipmentTotal { total: number; } +/** + * Money always prints its cents. Bare toLocaleString() defaults to + * maximumFractionDigits: 0, which rounded the total away from the line items it + * sums (118,171.21 shown as 118,171) — and the customer is billed the exact + * amount, so the shown figure must match to the cent. + */ +export function formatAmount(amount: number | string | null | undefined) { + return Number(amount ?? 0).toLocaleString(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }); +} + /** * Quantity a bulk rate bills, in ITS OWN unit. PER_ITEM cargo carries both * figures — the item count prices the booking, the tonnage sizes the wagons —