Commit Graph

3054 Commits

Author SHA1 Message Date
Nathnael
93163ac575 Merge branch 'dev' into freight/chore/payment-test 2026-07-31 10:57:07 +00:00
marshal
7f87e2d8ca Merge pull request #1040 from Tria-plc/freight_feature/usermanagement
intercity fix
2026-07-31 13:50:50 +03:00
Marshal
a64af98205 intercity fix 2026-07-31 10:50:16 +00:00
Nathnael
a975aa7547 fix(payment-providers): stop halving every non-DJF CAC Bank amount
Both callers already hand the provider a major-currency amount before this
call — freight sends invoice.balanceAmount (e.g. 700 for $700), passenger
sends CurrencyService's converted charge amount — with the target currency's
own decimal precision already applied (0dp DJF, 2dp USD/ETB). CAC's
toMajorAmount then divided anything that wasn't DJF by 100 on top of that,
so a USD 700 charge reached the bank as 7.00. This never surfaced because
CAC has only ever been wired for DJF (passenger) until now.

Also scoped the bank's documented 10-100,000 bound to DJF — it's the only
currency the spec states bounds for, so a USD amount outside that DJF-shaped
range is no longer rejected locally; an amount genuinely out of range still
comes back as a bank rejection.

Passenger is unaffected: its CAC currency has always been DJF, and the DJF
branch's behavior (amount unchanged, bounds enforced) is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 10:33:46 +00:00
marshal
b65a1d8146 Merge pull request #1039 from Tria-plc/freight_feature/usermanagement
intercity fix
2026-07-31 13:27:25 +03:00
Marshal
74b7ee81fc intercity fix 2026-07-31 10:26:17 +00:00
Nathnael
c176b9e7d6 fix(payment): give the payment-service client a 60s budget
CAC Bank's initiate SMSes an OTP before it answers and routinely takes more
than the 10s this client allowed, so every CAC charge came back as a 502
while the bank was still working — and if the bank had answered, the payer
would have been texted a code for an intent the freight side never recorded.
Matches the passenger API, which already budgets 60s and reads the same
PAYMENT_API_HTTP_TIMEOUT_MS override.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 09:02:27 +00:00
Nathnael
6f5f6d7b0a test(payment): cover the CAC Bank OTP confirm path
The confirm flow settles money on a provider with no webhook, so the two
places it can go wrong are worth pinning: that the OTP is forwarded against
the GATEWAY intent id (not the local projection id), and that a rejected
code leaves the intent open instead of failing the payment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 08:20:35 +00:00
Nathnael
97bfe95ec3 feat(payment): integrate CAC Bank OTP payments into freight flows
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>
2026-07-31 08:11:23 +00:00
Nathnael
5a02da91d2 refactor(api): extract self-service attributes for immediate application and poa verification improvement 2026-07-31 07:38:49 +00:00
Hagernesh
9afc3d4059 Empty container enhancement 2026-07-31 07:34:02 +00:00
Hagernesh
341c2b3742 add carriage acceptance sheet PDF per booking
Lists every wagon allocated to a booking with tare, equated length,
capacity, container and seal numbers, plus footer totals and signature
lines. Issued on cargo acceptance (export) and on allocation before
marshalling (import), so the endpoint rejects bookings with no wagon
allocations. Price per wagon splits the booking amount by allocated
weight, with the last row absorbing rounding so the column sums to the
total. Reuses the existing marshalling document renderer and its
Chromium-less tabular fallback.
2026-07-31 07:02:11 +00:00
Hagernesh
08e0fe2db2 feat: auto-populate yard and zone from selected warehouse
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>
2026-07-31 06:57:15 +00:00
Hagernesh
1bae13aec4 feat: add yard/zone fields and returned containers table 2026-07-31 06:46:03 +00:00
Hagernesh
74cf80106e feat: add yard/zone fields and returned containers table
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>
2026-07-31 06:45:03 +00:00
marshal
378b9b6b21 Merge pull request #1035 from Tria-plc/freight_feature/usermanagement
add goverment booking
2026-07-31 04:26:31 +03:00
Marshal
d07a2e239e add goverment booking 2026-07-31 01:25:47 +00:00
marshal
a7f44c1d16 Merge pull request #1034 from Tria-plc/freight_feature/usermanagement
add goverment booking
2026-07-31 04:08:39 +03:00
Marshal
7a72245229 add goverment booking 2026-07-31 01:07:48 +00:00
marshal
5564819b28 Merge pull request #1033 from Tria-plc/freight_feature/usermanagement
add goverment booking
2026-07-31 03:43:36 +03:00
Marshal
65f18b4796 add goverment booking 2026-07-31 00:41:51 +00:00
marshal
e6b16feb25 Merge pull request #1032 from Tria-plc/freight_feature/usermanagement
leg-aware capacity and wagon sharing
2026-07-31 01:07:55 +03:00
Marshal
34e4a7d13f leg-aware capacity and wagon sharing 2026-07-30 22:07:23 +00:00
marshal
143cbebb18 Merge pull request #1031 from Tria-plc/freight_feature/usermanagement
leg-aware capacity and wagon sharing
2026-07-30 22:08:50 +03:00
Marshal
f891f6abe2 leg-aware capacity and wagon sharing 2026-07-30 19:08:06 +00:00
marshal
52eda90642 Merge pull request #1030 from Tria-plc/freight_feature/usermanagement
leg-aware capacity and wagon sharing
2026-07-30 20:22:44 +03:00
Marshal
acef6870e9 leg-aware capacity and wagon sharing 2026-07-30 17:21:44 +00:00
Hagernesh
c74b9320a2 feat: add standalone container return modal
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>
2026-07-30 14:35:59 +00:00
Hagernesh
63aa2c7920 docs: clarify container returns are last-mile only (not first-mile)
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>
2026-07-30 14:35:59 +00:00
Hagernesh
c0d6b1a1c5 feat: add Container Returns page with EDR/Customer filter
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>
2026-07-30 14:07:09 +00:00
Hagernesh
154b7d11d5 feat: add warehouse selection to empty container returns form
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>
2026-07-30 14:07:09 +00:00
Hagernesh
c9300ab4cd feat: add EDR Last Mile Returns page with bulk/single form
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>
2026-07-30 14:07:09 +00:00
marshal
4937bcec53 Merge pull request #1027 from Tria-plc/freight_feature/usermanagement
fix issue
2026-07-30 16:33:38 +03:00
Marshal
8f25fb3e8b fix issue 2026-07-30 13:33:07 +00:00
Nathnael Wondisha
7d3002ca4c Merge pull request #1026 from Tria-plc/freight/nati-1
chore: update the iamapi package to 0.7.15
2026-07-30 16:24:32 +03:00
Nathnael
eefbc7b111 chore: update the iamapi package to 0.7.15 2026-07-30 13:22:20 +00:00
marshal
ceaf0ba7eb Merge pull request #1025 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-30 16:16:52 +03:00
Marshal
2cdf8bd161 export flow and fix intercity issue 2026-07-30 13:15:56 +00:00
Marshal
e80aac877f export flow and fix intercity issue 2026-07-30 13:11:35 +00:00
Nathnael Wondisha
349ff436d8 Merge pull request #1024 from Tria-plc/freight/chore/payment-test
fix: support widget peak and onboarding wizard responsivness
2026-07-30 16:10:05 +03:00
Nathnael
bfb4991234 fix: support widget peak and onboarding wizard responsivness 2026-07-30 13:08:51 +00:00
marshal
9973f57571 Merge pull request #1023 from Tria-plc/freight_feature/usermanagement
fix rate issue
2026-07-30 15:23:27 +03:00
Marshal
9208050cb5 fix rate issue 2026-07-30 12:18:50 +00:00
Hagernesh
fd1646e4d5 feat: repeat truck column labels inside each expanded booking
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.
2026-07-30 12:15:56 +00:00
Marshal
acb6f286d4 fix(payments): reconcile with gateway before expiring unpaid holds
Replace the fixed 5-minute grace with a settlement check at expiry:
expire() calls the payment API's reconcile endpoint — paid intents are
kept and allocated via payment.succeeded, unverifiable results defer
expiry to the next tick, only verifiably unpaid holds expire.
2026-07-30 12:01:59 +00:00
Marshal
22de05fe8e Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight_feature/usermanagement 2026-07-30 11:31:02 +00:00
Marshal
2ca04b8f98 changes export flow 2026-07-30 11:30:34 +00:00
Hagernesh
fe04d2edd6 feat: add warehouse gate times editor modal for import trucks
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>
2026-07-30 10:04:32 +00:00
Marshal
b671f07ce6 fix(rule-engine): merge duplicate Sebeta yards, block dupes
Two active Sebeta yards (LEGACY_DEST/'Sebeta' and SEBETA/'sebeta')
split rates and routes across different yard ids, so route-scoped rate
lookups missed. Migration repoints every yard reference to the survivor,
retires the duplicate, and adds partial unique indexes on active label
and code. Service now rejects case-insensitive duplicate labels on
create/update - the old guard only compared generated codes, which
missed labels whose existing code differs (LEGACY_DEST).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 09:25:02 +00:00
Marshal
9241ce01d2 fix(contracts): price base freight from contract lane only
Contract pricing matched base container/bulk rates by type+currency
with no origin/destination filter, so a lane with no configured rate
silently froze another lane's price into the contract snapshot
(CTR-2026-00065: DCT-Sebeta contract froze DCT-GMP rates) and bookings
then billed off it. Now scoped to the contract's first route and a
missing lane rate hard-blocks pricing with a 422, matching the
customs-clearance and booking-side behaviour.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 09:24:37 +00:00