diff --git a/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx b/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx
index 5502886d3..67e84a09f 100644
--- a/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx
+++ b/apps/edr-freight-web/backoffice/src/components/contracts/GlCreateBookingForm.tsx
@@ -348,6 +348,9 @@ export default function GlCreateBookingForm() {
// Intercity shipments ride a passing import/export train staff pick at
// finalize time — no shipment day is chosen and no window gate applies.
const isIntercity = contract?.tradeDirection === "DOMESTIC";
+ // USD billing is offered on import traffic only — export and domestic
+ // shipments are always invoiced in ETB.
+ const isImport = contract?.tradeDirection === "IMPORT";
// ONE_TIME split-remainder mode: a previous booking on this contract was
// split on train capacity, so the capacity endpoint reports the outstanding
@@ -1757,12 +1760,15 @@ export default function GlCreateBookingForm() {
Billing currency
- Shipments are invoiced in ETB.
+ {isImport
+ ? "Import shipments may be invoiced in ETB or USD. USD is paid by bank transfer, not online."
+ : "Shipments are invoiced in ETB."}
diff --git a/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx
index 85709f1d4..26a59b405 100644
--- a/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx
+++ b/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx
@@ -683,7 +683,11 @@ export default function EditBookingPage() {
/>
-
+ {/* USD billing is import-only; export/intercity stay ETB. */}
+
{(selectedService?.includesFirstMile ||
selectedService?.includesLastMile ||
diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/payment-currency-field.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/payment-currency-field.tsx
index d874fb783..fb91b515b 100644
--- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/payment-currency-field.tsx
+++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/payment-currency-field.tsx
@@ -19,14 +19,25 @@ const CURRENCY_ICONS: Record<
export function PaymentCurrencyField({
control,
+ allowUsd = false,
}: {
control: Control;
+ /**
+ * Offer USD alongside ETB. Import shipments only — export and domestic
+ * traffic is always invoiced in ETB.
+ */
+ allowUsd?: boolean;
}) {
+ const options = allowUsd
+ ? PAYMENT_CURRENCY_OPTIONS
+ : PAYMENT_CURRENCY_OPTIONS.filter((o) => o.value !== "USD");
return (
Payment currency
- Choose the currency for your freight quote and invoices.
+ {allowUsd
+ ? "Choose the currency for your freight quote and invoices. USD is paid by bank transfer, not online."
+ : "Choose the currency for your freight quote and invoices."}
- {PAYMENT_CURRENCY_OPTIONS.map((option) => {
+ {options.map((option) => {
const Icon = CURRENCY_ICONS[option.value].icon;
const selected = field.value === option.value;
return (
@@ -97,10 +108,7 @@ export function PaymentCurrencyField({
{/* Description for the active currency, kept subtle. */}
- {
- PAYMENT_CURRENCY_OPTIONS.find((o) => o.value === field.value)
- ?.description
- }
+ {options.find((o) => o.value === field.value)?.description}
diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts
index 08bb5236d..27b669d72 100644
--- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts
+++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts
@@ -81,11 +81,16 @@ export const PAYMENT_CURRENCY_OPTIONS: Array<{
label: string;
description: string;
}> = [
- // ponytail: ETB-only for now — re-add the USD option when multi-currency billing returns.
{
value: "ETB",
label: "ETB",
- description: "Ethiopian Birr — local pricing and invoicing.",
+ description: "Ethiopian Birr — pay online through the payment gateway.",
+ },
+ // Import shipments only; the field is hidden on export/domestic traffic.
+ {
+ value: "USD",
+ label: "USD",
+ description: "US Dollar — paid by bank transfer, slip sent to Finance.",
},
];
diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx
index 47e80e7e2..2c51cbb62 100644
--- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx
+++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx
@@ -133,7 +133,11 @@ export function Step2ServiceType({
)}
/>
-
+ {/* USD billing is import-only; export/intercity stay ETB. */}
+
{showServiceSections && (
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 c65ccea2a..a5b29a299 100644
--- a/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx
+++ b/apps/edr-freight-web/portal/src/pages/contracts/NewShipmentPage.tsx
@@ -1215,6 +1215,9 @@ function ScheduleStep({
})();
const isIntercity = contract.tradeDirection === "DOMESTIC";
+ // USD billing is offered on import traffic only — export and domestic
+ // shipments are always invoiced in ETB.
+ const isImport = contract.tradeDirection === "IMPORT";
const { data: availableDays, isLoading } = useQuery({
...api.bookings.getAvailableDaysForCargo.queryOptions({
input:
@@ -1310,12 +1313,15 @@ function ScheduleStep({
Billing currency *
- Shipments are invoiced in ETB.
+ {isImport
+ ? "Import shipments may be invoiced in ETB or USD. USD is paid by bank transfer, not online."
+ : "Shipments are invoiced in ETB."}
field.onChange(v)}
error={fieldState.error?.message}
+ allowUsd={isImport}
/>
)}
diff --git a/packages/ui-common/src/components/CurrencySelector/CurrencySelector.tsx b/packages/ui-common/src/components/CurrencySelector/CurrencySelector.tsx
index 5ce3d1272..f25a7b015 100644
--- a/packages/ui-common/src/components/CurrencySelector/CurrencySelector.tsx
+++ b/packages/ui-common/src/components/CurrencySelector/CurrencySelector.tsx
@@ -8,17 +8,27 @@ export interface CurrencySelectorProps {
disabled?: boolean;
/** Validation error shown under the cards. */
error?: string;
+ /**
+ * Offer USD alongside ETB. Import shipments only — export and domestic
+ * traffic is invoiced in ETB, so the option stays hidden everywhere else.
+ * USD is settled by bank transfer, never through the online gateway.
+ */
+ allowUsd?: boolean;
}
-// ponytail: ETB-only for now — restore the USD entry when multi-currency billing returns.
-const OPTIONS = [
- {
- code: "ETB",
- symbol: "Br",
- name: "Ethiopian Birr",
- hint: "All shipments are invoiced in ETB",
- },
-] as const;
+const ETB_OPTION = {
+ code: "ETB",
+ symbol: "Br",
+ name: "Ethiopian Birr",
+ hint: "Pay online through the payment gateway",
+} as const;
+
+const USD_OPTION = {
+ code: "USD",
+ symbol: "$",
+ name: "US Dollar",
+ hint: "Paid by bank transfer — send the slip to Finance",
+} as const;
/**
* Card-style USD/ETB billing-currency picker. Renders unselected when `value`
@@ -29,7 +39,9 @@ export function CurrencySelector({
onChange,
disabled = false,
error,
+ allowUsd = false,
}: CurrencySelectorProps) {
+ const options = allowUsd ? [ETB_OPTION, USD_OPTION] : [ETB_OPTION];
return (
- {OPTIONS.map((o) => {
+ {options.map((o) => {
const selected = value === o.code;
return (