Ticket #181 — eTrade auto-fetch already existed; adds a client-side
download of the fetched record (eTrade returns data, not a document)
on the portal onboarding step and the backoffice customer detail page.
Ticket #238 — pre-approval edits and document uploads write straight
to the live company row with no approval gate and, until now, no
trace. Adds an append-only company_revisions log (diffed field
changes, document uploads) recorded from updateProfile and
uploadCompanyDocuments, exposed via GET /companies/:id/revisions and
shown as "Version history" on the backoffice customer detail page.
Ticket #420 — add approved_at to companies (migration), stamped at
both promotion sites (first-profile auto-approve and manual staff
status change). Surfaced as Submitted on/Approved on in the backoffice
customer list and detail views.
Ticket #422 — surface Pending/Suspended/Approved company status as a
banner, branching AccountReviewBanner on companyStatus instead of only
per-profile review state.
CAC Bank is an OTP debit with no redirect and no webhook: initiate SMSes a
code to the payer's mobile, and the charge only settles when that code is
confirmed. The payment service already spoke it (passenger uses it); the
freight side had the enum values but none of the flow.
API:
- PaymentClientService.confirmOtp forwards the code to
POST /payments/intents/:id/confirm, mapping 400/404 to BadRequest so a
mistyped code stays retryable instead of surfacing as a gateway failure.
- PaymentService.confirmOtp is keyed by the LOCAL intent id (the invoice's
paymentId) rather than the domain reference, so the right invoice settles
when several share a booking. On success billing settles the invoice.
- payInvoice rejects CAC_BANK without payerAccount before calling the
gateway, and no longer runs the demo auto-settle for a COLLECT_OTP intent
(it is not paid until the payer confirms).
- POST /billing/my-invoices/:id/confirm — ownership-checked, and since
warehouse fee invoices are central invoices it covers those too.
Portal:
- useInvoicePayment owns the whole flow (initiate, redirect-or-OTP, confirm)
and replaces the five near-identical pay mutations at the call sites.
- PaymentMethodModal gains the CAC Bank option, the payer mobile field, and
the OTP step. Click-outside is disabled there so a stray click cannot drop
the payer out of a live OTP window.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
When warehouse is selected in standalone return modal, yard and zone
fields are automatically populated from warehouse data (yard from
warehouse.yard or warehouse.code, zone from warehouse.zone). Fields are
read-only/disabled to prevent manual editing.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add Yard and Zone input fields to standalone return modal. Add table
showing all returned containers with: container number, booking ref,
returned date, facility, yard, condition, status. Table appears at top
of Container Returns page when returns exist.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add "Record Return" button at top of Container Returns page for
standalone/unboooked returns. Modal accepts container number, return
date, warehouse, condition, handover notes. No booking association
required — supports returns that arrive without clear booking context.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Update labels and comments to reflect that container returns are for
last-mile trucks only: either EDR last-mile or customer self-haul. Same
truck that delivered will return with empty containers. Changed labels
from "EDR Returns" → "EDR Last Mile" and "Customer Returns" →
"Customer Self-Haul".
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Separate page for tracking empty container returns by type: EDR returns
(empty containers from EDR first-mile) or Customer returns (customer
self-haul). Segmented control filter, expandable booking rows showing
containers, modal to record return with warehouse selection. Accessible
via sidebar menu under Import Operations.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Replace manual facility/yard input with warehouse dropdown. Form fetches
available warehouses and auto-populates facility (warehouse name) and yard
(warehouse code) from selection, eliminating manual entry.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
New page for empty container returns: tables show EDR trucks with company
names and return containers. Modal form for processing single or bulk
returns, with fields for facility, yard, condition, return date, and
handover notes. Accessible via sidebar menu under Import Operations.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Extract the truck column list to TRUCK_COLUMNS and drive both the table
head and a per-booking label row from it, so an expanded booking's rows
are labelled without scrolling back to the head.
Enable per-truck editing of warehouse gate arrival/departure times
(arrivedAt/departedAt) via modal on Import Trucks page. Accessible via
row action menu for EDR-haulage trucks. Includes backend endpoint
POST /last-mile/:id/warehouse-gate-times and frontend modal with
DateTimePicker inputs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Show per-truck warehouse gate arrival (arrivedAt) and departure
(departedAt) timestamps on the Import Trucks page, enabling staff to see
when each truck entered and exited the warehouse. Times displayed in local
format; EDR and customer trucks both supported.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Introduced ContractCourtBadge to display the responsible party for contract actions.
- Updated ContractStatusBadge to include new court badge.
- Enhanced ClearanceDocumentsPage with additional filters for trade direction, freight type, and ownership.
- Modified ContractRequestDetailPage and ContractRequestsPage to utilize ContractCourtBadge.
Booking detail now has a Trucks tab displaying every EDR or customer truck
assigned to a booking's last mile. Each row shows warehouse-gate times
(arrival/departure) and destination-detention times (arrival/return), with
detention costs and inspection status. Detention rows only for EDR trucks;
customer self-haul shows —. Reuses existing TruckDetentionModal and
FeePreviewModal for edit/view actions.
Backend: arrivalTrucksForBooking() adds lastMileId per truck (direct chain to
detention preview), containerItems() adds inspection_status column to responses.
No new SQL, no migrations, no new endpoints.
Frontend: BookingTrucksPanel.tsx self-fetches all data via existing warehouse +
last-mile services, renders adaptive table with cargo-cost strip above.
Wired into BookingRequestDetailPage.tsx tab bar.