Commit Graph

943 Commits

Author SHA1 Message Date
Hagernesh
2798fed6d8 fix(train-scheduling): block dispatch when allocated cargo is not loaded
dispatchSchedule guarded status, Djibouti departure rules, locomotives and
wagons — but never checked the cargo. A train could be dispatched while the
bookings allocated to it sat received in the warehouse, silently leaving them
behind. Dispatch now refuses when an allocated booking has warehouse inventory
in RECEIVED/STORED/READY_FOR_LOADING, naming the bookings and pointing at the
two ways out: load them, or drop the wagon allocation so they ride a later
train. Bookings with no inventory at all are not blocked — allocating a wagon
before the goods arrive is normal planning.

Also drops RESERVED from the Load-to-Train filters: reserved stock is not
awaiting loading.

The sched_bookings CTE moves to common/schedule-bookings.sql so the warehouse
loading queue and this dispatch guard resolve a train's bookings identically —
if they drift, a train departs leaving cargo the warehouse still expects to load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:01:57 +00:00
Hagernesh
e115b9b753 fix(warehouse): resolve Load-to-Train bookings from wagon allocation
The Load-to-Train queue was permanently empty for real traffic. loadableTrains()
and trainLoadableItems() gated on freight.train_schedule_bookings, but nothing in
the application writes that table — only the demo seeders do. Real wagon
allocation writes wagon_booking_allocations, reached via
train_schedules -> train_sets -> train_set_wagons, so an allocated export booking
never satisfied the EXISTS gate and no train ever appeared.

Both queries now resolve a schedule's bookings through a shared sched_bookings
CTE that unions the wagon-allocation chain with train_schedule_bookings, so real
allocations show up and the seeded demo scenarios keep working. The panel already
groups the returned rows by booking with their containers, so the queue now lists
the train, its bookings and their containers for selection.

Export flow this serves: booked -> paid -> received at the warehouse (first-mile
or self-haul) -> GRN -> loaded onto the wagons allocated to the booking.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:01:57 +00:00
marshal
2def8f9b0e Merge pull request #753 from Tria-plc/freight_feature/usermanagement
Comment out payment event handling for local demos in BillingService
2026-07-17 10:49:46 +03:00
Marshal
5a1e0dba4d Comment out payment event handling for local demos in BillingService 2026-07-17 07:43:17 +00:00
Nathnael Wondisha
f769d97135 Merge pull request #752 from Tria-plc/freight/feat/fixes-v1
Freight/feat/fixes v1
2026-07-17 10:01:44 +03:00
Marshal
71507b27fd changes 2026-07-16 20:09:59 +00:00
Marshal
35c53e3f36 changes 2026-07-16 20:03:35 +00:00
Nathnael
e626e1db63 Merge branch 'dev' into freight/feat/fixes-v1 2026-07-16 13:23:40 +00:00
marshal
1a3fa4bc5a Merge pull request #738 from Tria-plc/freight_feature/usermanagement
fix issue
2026-07-16 16:00:07 +03:00
Marshal
b50adc4666 fix issue 2026-07-16 12:59:28 +00:00
Nathnael Wondisha
8ee3f13bdb Merge pull request #735 from Tria-plc/freight/feat/payment-revert
fix: revert the testing
2026-07-16 15:13:30 +03:00
Nathnael
f71bbbf782 feat: setup account page for customer and centeralize the otps and phone usages to use the iam user 2026-07-16 12:08:45 +00:00
Nathnael
c19e4260c1 fix: revert the testing 2026-07-16 12:04:58 +00:00
marshal
35a9d25aaa Merge pull request #734 from Tria-plc/freight_feature/usermanagement
fix u=issue
2026-07-16 15:02:40 +03:00
Marshal
e8e12c1363 fix u=issue 2026-07-16 12:02:11 +00:00
Hagernesh
d5182c5d85 feat(last-mile): wire multi-container assignment, bulk drawdown + EDR exit papers
Frontend for the per-truck EDR backend:

- Assign modal takes a container LOAD per truck (MultiSelect, max 2) instead of a
  single container, so a truck can carry one 40ft or two 20ft. Sends
  containerNumbers[]; the API enforces the size rule.
- requiredVehicles is now size-aware: a 40ft fills a truck (1 each), two 20ft
  share one. It previously assumed ceil(containers / 2) regardless of size, so a
  2x40ft booking under-counted the trucks needed.
- Bulk bookings show the drawdown in the assign modal — remaining vs total
  tonnage, what's been hauled, and a "fully hauled" state when it reaches 0.
- New "Truck exit papers" row action opens a per-truck list (plate, containers,
  arrival, exit, net weight) with a per-truck exit-paper download.
- last-mile findAll/findById now load each assignment's containers so the UI can
  hydrate a truck's load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 09:24:22 +00:00
Hagernesh
ff49554cc2 feat(last-mile): per-truck EDR arrival/exit, exit paper, bulk drawdown, departure notify
EDR last-mile is multi-truck but was modelled as one: setVehicles accepted any
number of trucks with no validation, arrival/delivery were stamped once per
last_mile record (N trucks shared one timestamp), EDR trucks got no exit paper,
and the per-truck EDR handover never happened because deliver() resolved the
plate via last_mile_container_allocations — a table nothing writes.

- Migration 2260000000000: per-truck arrived_at/departed_at/gross_weight_tons/
  net_weight_tons on last_mile_vehicle_assignments, plus a
  last_mile_vehicle_containers child table (a truck holds 1x40ft OR 2x20ft, so
  the single container_number scalar could not express a load). Weights are
  TONNES and named accordingly — the older gross_weight_kg lies about its unit.
- setVehicles: enforce the size rule (one 40ft, or two 20ft), container
  membership, one-container-one-truck, and never more trucks than containers.
  Bulk carries no containers and is instead gated on tonnage remaining.
- Bulk drawdown: remainingTonsForBooking = booking VGM minus the net weighed off
  every departed truck (both tonnes, no conversion), exposed as
  GET /last-mile/booking/:bookingId/remaining-tons.
- release() now stamps the EDR truck's own arrival and exit (matched by plate, so
  it works for bulk too) alongside the existing customer-truck stamp. The exit
  weighing itself is untouched.
- New GET /warehouse-inventory/edr-truck-exit-paper/:assignmentId — per-truck
  exit paper for EDR trucks. Deliberately not signature-gated: EDR handovers are
  generated at delivery, after the truck has left.
- deliver(): resolve the handover plate from the truck's own containers instead
  of the dead allocations table, so EDR handovers are genuinely per-truck.
- Notify the customer (portal inbox + SMS/email) when a truck leaves — one hook
  in release() covers both self-haul and EDR, since it is the single exit path.

Self-haul is intentionally unchanged (one booking-level handover signed once).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 09:24:22 +00:00
Nathnael Wondisha
68f6a393a9 Merge pull request #730 from Tria-plc/freight/feat/fixes-v1
Freight/feat/fixes v1
2026-07-16 11:59:01 +03:00
Nathnael
6dde17fa4d fix: premature payable invoice 2026-07-16 08:38:49 +00:00
natib21
af57ffdda4 Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight/feature/user_management_UI 2026-07-16 08:13:57 +00:00
natib21
4a04aa7e97 fic 2026-07-16 08:13:22 +00:00
Nathnael Wondisha
2db321b37a Merge pull request #724 from Tria-plc/freight/feat/fixes-v1
Freight/feat/fixes v1
2026-07-16 10:59:36 +03:00
yaschalew10
b6d71ccc57 Merge pull request #723 from Tria-plc/freight/feature/user_management_UI
Freight/feature/user management UI
2026-07-16 10:50:34 +03:00
natib21
9d53552f95 Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight/feature/user_management_UI 2026-07-16 07:48:27 +00:00
natib21
a4b3309412 add seed 2026-07-16 07:43:54 +00:00
Nathnael
08faf56c4f fix: payment autopay on the payment init added for testing 2026-07-16 06:43:30 +00:00
marshal
50d5ce5ad9 Merge pull request #721 from Tria-plc/freight_feature/usermanagement
fix issue
2026-07-16 04:06:52 +03:00
Marshal
fe29b38377 fix issue 2026-07-16 01:05:57 +00:00
marshal
ea22f38adf Merge pull request #720 from Tria-plc/freight_feature/usermanagement
fix issue
2026-07-16 03:34:14 +03:00
Marshal
41fe04652f fix issue 2026-07-16 00:33:31 +00:00
marshal
67bc835458 Merge pull request #719 from Tria-plc/freight_feature/usermanagement
implement empty-container return service: add return quantity handlin…
2026-07-16 02:06:08 +03:00
Marshal
234a74e812 implement empty-container return service: add return quantity handling, update related DTOs, services, and UI components 2026-07-15 22:48:04 +00:00
marshal
e3fccbd24d Merge pull request #717 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-15 23:18:55 +03:00
Marshal
fc44eee25e implement update train details feature: add DTO, service method, and UI modal for editing train name and run numbers 2026-07-15 20:14:39 +00:00
Hagernesh
2647776d19 feat(warehouse): stamp actor as display name instead of UUID
Add actorLabel(user) — resolves the authenticated user to a readable name
(name → username → email → id) — and use it for the performed_by audit stamp on
every warehouse action, so the activity log shows a person, not a UUID. The
freight DB has no users table to join, so the name is stamped at write time.
approve-delivery keeps the raw user id (it is an id argument, not the audit
label). Existing rows keep their prior value; this applies going forward.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:24:05 +00:00
Hagernesh
2044312d93 feat(warehouse): stamp authenticated user as action actor (performedBy)
Warehouse mutation endpoints now record the JWT-authenticated user as the actor
(user.id) instead of trusting a client-supplied performedBy string, unlocking
per-operator productivity metrics and a trustworthy audit trail. Covers receive,
receive-bulk, reserve, store, ready-for-loading, ready-for-pickup, load-onto-
train, bulk-dispatch, dispatch, deliver, gate-clearance, approve-delivery, the
Djibouti/import auto-unload actions, and fee-invoice generation. The prior
client value is kept only as a fallback for unauthenticated/internal calls.

move/load do not yet carry an actor (their DTOs have no performedBy) — separate
follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 14:51:21 +00:00
Marshal
d7d9db9c3a changes 2026-07-15 14:27:00 +00:00
Hagernesh
ac90b04be0 feat(warehouse): P2 dashboard — gate/dock throughput + live auto-refresh
- gateStats(): items cleared through the gate today, average arrival→gate
  turnaround (hours, 30d), and clearances per hour over the last 24h → new
  GateThroughputCard in the dashboard Performance section.
- Live board: every dashboard query (dashboard, ops, throughput, dwell, cycle,
  on-time, zone occupancy, accrual, gate) now auto-refreshes on a 60s interval,
  with a "Live" indicator in the header.

New endpoint GET /warehouse-inventory/gate-stats (guarded). Deferred (need
upstream data): capacity forecast, labour productivity, WebSocket push, yard map.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 14:26:02 +00:00
Hagernesh
fc4aadbc57 feat(warehouse): P1 dashboard analytics — dwell/aging, cycle-time + on-time, live deltas
Adds the operational-performance layer to the warehouse cockpit:

- Dwell time & aging: dwellStats() (avg + 0-3/4-7/8-14/15+ buckets over
  in-warehouse items) → DwellAgingCard histogram.
- Cycle time & on-time: cycleStats() (arrived→ready→loaded→dispatched stage
  averages + dock-to-dispatch) and onTimeDispatchStats() (share of items that
  left before their storage free-days expired, resolved via the fee engine's
  own rule matching) → CycleTimeCard.
- Live tiles: opsStats() now returns receivedYesterday; KpiStrip renders an
  optional ▲/▼ delta, and the ops strip shows received-today vs yesterday.

New endpoints: GET /warehouse-inventory/{dwell-stats,cycle-stats} and
/warehouse-fees/on-time-dispatch (all guarded). New "Performance" section on
WarehouseDashboardPage. On-time reads N/A when there is no sample / no active
storage rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 13:55:39 +00:00
marshal
6391ba837a Merge pull request #707 from Tria-plc/freight_feature/usermanagement
changes
2026-07-15 16:30:28 +03:00
Marshal
19c9da28ae changes 2026-07-15 13:29:01 +00:00
Hagernesh
2e22b72e27 feat(warehouse): assemble dashboard cockpit + server-side throughput series
- WarehouseDashboardPage now composes the ops KPI strip, lifecycle cards, flow
  charts, zone-occupancy heatmap and demurrage/accrual exceptions into one
  control-tower view; drop the redundant lifecycle donut.
- New GET /warehouse-inventory/throughput (date_trunc time series) replaces the
  client-side buildTrend that downloaded the entire inventory list to bucket it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 12:27:53 +00:00
SennayT
f9706c9fb0 refactor: separate base image configuration into Dockerfile.base for improved build management 2026-07-15 10:51:35 +00:00
SennayT
3416585a01 add puppeteer support 2026-07-15 13:42:42 +03:00
marshal
7700aa6358 Merge pull request #701 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-15 13:32:37 +03:00
Marshal
c71a0043d6 implement wagon maintenance feature: add functionality to detach wagons and move them to maintenance status 2026-07-15 10:32:09 +00:00
Marshal
11771e5f92 remove reopen delay minutes from global rules and update related types
- Removed the  field from  and related components.
- Updated  to reflect the removal of the reopen delay input field.
- Modified  to include new train number fields:  and .
- Added  interface to manage active schedules with trade direction.
- Introduced  interface to track wagon shortages in bookings.
- Updated  logic to ensure consistent UI state representation.
- Created migrations to drop the  column and add  and  columns to the  table.
- Added tests for the new booking window display logic and wagon planning functionality.
2026-07-15 09:13:02 +00:00
Marshal
9be7f356f0 enhance train scheduling logic to exclude cancelled trains and refine window filtering 2026-07-15 07:07:10 +00:00
Hagernesh
7e934b3433 feat(warehouse,last-mile): truck load size rule, dedup last-mile, driver-required + arrival prefill
Truck loading:
- loadTruck enforces max 2 containers / one 40ft (two 20ft) and auto-marks an
  assigned truck arrived on load; container-items payload + modal expose
  container size with a client-side selection cap.
- Show "#x containers pending assignment" in the portal truck card and the
  backoffice container modal.

Last-mile:
- create() is idempotent — return the existing record for a booking instead of
  inserting a duplicate delivery row (fixed the same booking showing twice in
  Assign-Mile).
- setVehicles/update reject a truck with no assigned driver; the Assign toast
  now surfaces the reason.
- New GET /last-mile/booking/:id/arrival-trucks returns assigned EDR trucks with
  driver details; ReleaseOrderModal fetches and auto-fills them so an assigned
  EDR truck no longer reads as "not assigned yet".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 14:16:45 +00:00
Marshal
5cffe2860c fix train builder and consolidation 2026-07-14 13:49:39 +00:00