Commit Graph

166 Commits

Author SHA1 Message Date
hager
eeac88f3be fix(freight-backoffice): identify yards by name rather than code
Operators know the yards by name, not by the internal code: the yard coded
KALITY is universally called GMP / Gelan Multipurpose Port (Indode), so
rendering the code alongside the name read as two different places.

Show the name alone in route creation, the yard desks modal and the
booking route card, falling back to the code only when a yard has no
name. The code is unchanged in the data and remains searchable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 19:37:02 +00:00
ghost2023
214f96dbae feat(freight-backoffice): support DJF in booking, contract and warehouse screens
Currency dropdowns/pickers (AdditionalPaymentsTab, ClearanceChargesTab,
PhasedClearanceActionPanel, AdviseDutyCard, ContractRequestsPage,
ruleEngine/resources, WarehouseRulesPage, VehicleDetailPage,
FeePreviewModal) offer DJF alongside ETB/USD; GlCreateBookingForm's
currency selector gets allowDjf next to allowUsd. Narrow 'ETB'|'USD'
type unions widened to include 'DJF' across the warehouse
billingCurrency plumbing (useWarehouses, warehouse.service, api.ts)
and the customer/invoice types.

Ad-hoc money() formatters (BookingTrucksPanel, AccrualDashboard,
ImportTrucksPage, EmptyReturnRequestsPage) and formatMoney call sites
that hardcoded 2 decimals (wagon-cancellation cards, BookingRequestDetailPage,
WagonCancellationsPage, PaymentsPage, WarehouseInvoicesPage) now use
currencyDecimals() from @edr/ui-common so DJF renders with 0 decimals
instead of forced cents. The 3 duplicate overview formatCurrency/
formatAmount helpers (typed 'ETB'|'USD') widen to accept any currency.

Two correctness fixes: OverviewRecentBookingsTable's currency==='USD'
? 'USD' : 'ETB' was mislabeling every non-USD currency as ETB; and
WarehouseInvoicesPage's gateway-method default now routes any
non-ETB currency (not just USD) to WAAFI, so DJF invoices get a
working default instead of TELEBIRR (ETB-only).

Claude-Session: https://claude.ai/code/session_01CZy77vCWhka3pnmVF9NDkL
2026-09-04 11:53:56 +03:00
ghost2023
2317684db9 feat(fleet): add last-maintenance date filter to wagons list
Adds maintenanceFrom/maintenanceTo to WagonListFilters and wires a
wagons-only "Last maintenance" date-range filter into FleetResourcePage,
alongside the existing Registered filter. Server-paged, so the range is
resolved by the API (see wagons.service.ts).
2026-08-21 15:55:02 +03:00
Nathnael
1f11c3a4ca feat(export-ui): mount the export button on the eight remaining list pages
customers, contracts, invoices, payments, train schedules, and locomotives /
trains / wagons via the fleet page's config.

FilterBar pages pass controls.params into the children slot. The four pages
still on ad-hoc filtering pass their own hand-built filter object instead,
which is why ExportButton takes plain params rather than a UseFilters — it
would otherwise have been blocked behind migrating those pages. FleetResource
serves seven slugs from config, so it gets an optional exportKey there and
renders nothing for the four slugs with no dataset yet.

Auditing each page's real filter keys against the dataset declarations turned
up three gaps where an on-screen filter would have silently not applied to the
export: invoices sends a singular "status" (the dataset only had the
multiselect "statuses"), contracts sends paymentCurrency, serviceTypeId and
route origin/destination, and train schedules sends freightType. Added all of
them — contract routes filter through EXISTS on contract_routes since they are
one-to-many, and train-schedule freightType through EXISTS on the bookings
aboard, matching the list service.

Verified in the browser: the button renders on each page, and the invoices
dialog follows that page's own filter object — selecting Paid moves the count
from 126 to 100, which matches the database. Filter pass-through checked
against the database for invoices, payments, wagons, contracts and train
schedules.
2026-08-20 07:17:25 +00:00
Nathnael
7aa4405423 Merge branch 'dev' into freight/nati-2
Conflict in ClearanceDocumentsPage: this branch migrated the page to the
pill FilterBar, dev added filters to the Select stack it replaced. Kept
the FilterBar and carried dev's additions across as a "Booked by"
(customerKind) FilterDef plus the shipping-line search placeholder; dev's
startOfDayIso/endOfDayIso went away because dateRangeParams already does
that. The Ship icon import is needed by dev's shipping-line customer cell,
which merged cleanly on its own.
2026-08-17 12:43:35 +00:00
Marshal
ca9f631f6f Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight_feature/usermanagement 2026-08-15 10:12:59 +00:00
Marshal
dc38e843a6 feat: full wagon cancel, leg board, wagon dates
feat(freight): editable train leg times, SL invoice payer
2026-08-15 10:12:37 +00:00
Nathnael
8ba8376f45 feat(filters): migrate FleetResourcePage to the pill filter bar
The real live fleet page — FleetCrudPages.tsx (previous commit) turned
out to be dead code; every fleet route (locomotives/trains/wagons/
containers/cargoes/vehicles/drivers) actually renders this one,
config-driven off resources.ts. Highest-leverage single file in the
remaining inventory: 7 routes at once.

- filterDefs are built per slug from `config.listFilters` (status/yard/
  wagon type/train…, wired to real server params via each def's
  default `{key: value}` toParams) plus a "Registered" date range. The
  3 slugs with no server list filters (trains/containers/cargoes) fall
  back to a plain client-only Status filter off a fixed enum, not
  "whatever status exists in the currently-loaded rows" — the latter
  would be circular (filterDefs feeds useFilters, which feeds the
  query that produces those rows).
- serverListFilters/pagedFilters derive straight from `controls.params`
  instead of hand-picking each field off local state — the def keys
  already match the API's param names, so this is mostly free.
- filteredRows keeps the original's exact "usesServerListFilters ⇒
  trust the server, don't re-check client-side" short-circuit — some
  server list filters (a wagon's `trainNumber` matches either of two
  different columns) aren't expressible as a plain client-side field
  equality, and re-applying them would silently break.
- Pagination moved from a local `usePagination()` (component state) to
  useFilters' URL-backed page/pageSize — the whole point of this pass.
  DataTable takes `controls.tableProps(total)` directly; FleetCardGrid
  (not a DataTable) is fed the same pieces by hand.
- The two manual "reset on slug/filter change" effects are dropped —
  a same-app nav Link to a bare path already clears the query string,
  and useFilters already deletes `page` on every filter/search change.
- FleetToolbar's view-mode SegmentedControl moves into FilterBar's
  `children` slot; its search/filters props are no longer used here.
2026-08-15 08:39:59 +00:00
Nathnael
6c4969f3fd feat(filters): migrate FleetCrudPages to the pill filter bar
Covers 6 pages at once: the shared FleetCrudPage<T> factory
(TrainMasterDataPage, WagonsCrudPage, ContainersCrudPage,
CargoesCrudPage, LocomotivesCrudPage) plus the standalone
WagonTypesCrudPage.

- FleetCrudPage gains an optional `statusOptions` prop; when passed it
  builds a Status enum FilterDef and swaps the old plain search Input
  for FilterBar + useFilters + applyClientFilters (client-bridge —
  these endpoints return bare arrays). Status option lists sourced
  from the actual entity/enum definitions, not guessed, and reused in
  each page's create/edit form Select instead of duplicating them.
  Column-header click-to-sort is untouched (separate mechanism).
- WagonTypesCrudPage (hand-rolled, not on the factory) gets a boolean
  Active/Inactive filter the same way, replacing its search-text hack
  that string-matched "active"/"inactive" against the query.
2026-08-15 07:51:31 +00:00
Nathnael
e5e75b4166 feat(filter-bar): migrate 3 more fleet pages, extract footer adapter
- ruleEngineFooterProps.ts: toRuleEngineFooterProps() — the
  useFilters-to-RuleEngineListFooter pagination adapter had already been
  hand-written twice (TrucksOnSitePage, CompliancePage) with the same
  pageSize-drop risk useFilters itself just had fixed; extracted before a
  third copy could drift.
- CompliancePage, FuelPurchasePage, IncidentsPage: ListControls ->
  FilterBar + applyClientFilters, same mechanical pattern as the
  warehouse pages (search + one date range, endpoints take no params at
  all per the inventory sweep — confirmed correct bucket, not assumed).
2026-08-14 14:13:11 +00:00
Nathnael
89cdc0ad06 style: ui fixes 2026-08-13 13:46:46 +00:00
Nathnael
58b47318e9 feat(freight-backoffice): consolidate Mantine from/to date filters into range pickers
Replaces every remaining split from/to Mantine DateInput/DatePickerInput pair
with a single DatePickerInput type="range", sharing one preset list (Today,
Last 7/30 days, this/last month, YTD) via getDateRangePresets(). Covers
ListControls (18 consumers), FleetResourcePage, ContractRequestsPage,
BookingRequestsPage (created + scheduled ranges), WagonCancellationsPage,
BatchBoardPage, ClearanceDocumentsPage, ShipmentRequestsPage.

Native Mantine range picker, not the shadcn DateRangePicker, to match each
page's existing design system instead of clashing with it.

Reports date-range filter (ReportFilters.tsx) intentionally left untouched.
2026-08-13 08:45:29 +00:00
Marshal
e29e3ff837 fix(freight-backoffice): render wagon transfer reason as sanitized HTML in a modal 2026-08-10 14:02:13 +00:00
Hagernesh
204bfd2421 fix: let trains dispatch with cargo still in the warehouse
The export-only assertAllocatedCargoLoaded guard threw a
BadRequestException whenever a booking on the schedule had warehouse
inventory in RECEIVED, STORED or READY_FOR_LOADING, making it
impossible to dispatch a train whose cargo had not been inspected and
loaded onto a wagon.

Leaving cargo behind is an operational decision, not an error state.
The dispatch confirm dialog already lists unassigned and unloaded
bookings and offers Dispatch anyway, so the readiness signal is
preserved — only the hard block is gone.

Wagon/locomotive conflicts and the Djibouti gatepass check still block
dispatch: those are physical and legal conflicts, not cargo readiness.
2026-08-08 13:17:43 +00:00
Hagernesh
375cf55e5f LM map missing map api fall back fix 2026-08-08 07:51:41 +00:00
Marshal
70215a9f37 feat(wagons): audited maintenance/availability toggle 2026-08-07 12:10:43 +00:00
Marshal
5d68a3f7b7 add permanent purge functionality for wagons and routes
- Implemented a  method in  to permanently delete wagons without history.
- Added corresponding permissions for hard delete actions in .
- Updated the UI components to include purge actions, ensuring they are only available to users with the appropriate permissions.
- Created modals for confirming permanent deletions in  and .
- Enhanced API services to handle purge requests for locomotives, wagons, and routes.
- Added tests for the purge functionality in both  and  services to ensure proper behavior and error handling.
2026-08-04 14:07:16 +00:00
Hagernesh
90fef6856b Container return and Price per KM for Vehcles 2026-07-31 10:52:52 +00:00
Marshal
2ca04b8f98 changes export flow 2026-07-30 11:30:34 +00:00
Marshal
481878e553 paginate wagons, locomotives and routes lists server-side 2026-07-27 21:27:36 +00:00
Marshal
496c66017f update locaomotive and fix wagon transfer issue 2026-07-27 20:34:14 +00:00
Marshal
9b13fa2ac6 feat: implement wagon transfer management modals and page
- Add TransferFulfillModal for fulfilling wagon transfer requests.
- Create TransferRequestFormModal for filing new wagon transfer requests.
- Introduce TransferCloseShortModal for closing requests that cannot be fully fulfilled.
- Develop WagonTransfersPage to manage and display wagon transfer requests.
- Implement utility functions for handling wagon transfer request data and UI components.
- Enhance UI with Mantine components for better user experience.
2026-07-26 15:11:50 +00:00
Marshal
fde5e6de4b add company stamp upload functionality for contract signing
- Introduced StampUpload component for uploading company stamp images.
- Integrated stamp upload in contract signing modal, supporting PNG and JPG formats.
- Implemented validation for file type and size (max 5 MB).
- Added visual feedback for drag-and-drop functionality.
- Updated contract-related pages to handle duplicate contract alerts and pricing notices.
- Enhanced contract expiry management with a nightly sweep service.
- Added unit tests for new features and updated existing tests for contract handling.
2026-07-25 17:14:58 +00:00
Marshal
54b5882355 changes 2026-07-25 06:05:20 +00:00
Hagernesh
2f124bc666 Intercity load unload with grn ,Warehouse , fleet , and allocation endpoints permission 2026-07-24 11:55:05 +00:00
Hagernesh
cf8a2e928d fix(warehouses): detention groups by canonical truck type
Join truck_types via vehicles.truck_type_id (normalized legacy
vehicle_type only as fallback) so type renames can't unmatch detention
rules and FK-less vehicles keep billing.
2026-07-24 11:55:05 +00:00
Marshal
668b5e1c9d add permissions and fix issues 2026-07-23 20:24:20 +00:00
Hagernesh
73f36fe46e Export interchange document — a generation error after Djibouti unloading failed the whole request and left the document missing until a manual rerun. Generation is now best-effort (unload never fails on paperwork) and reruns backfill the document. 2026-07-23 11:31:44 +00:00
marshal
f5f41e0a5a Merge pull request #926 from Tria-plc/freight_feature/usermanagement
implement freight permissions for trains, wagons, and routes
2026-07-23 08:57:59 +03:00
Marshal
129a4d1d0a implement freight permissions for trains, wagons, and routes 2026-07-23 05:57:14 +00:00
Hagernesh
15540f78e2 fix(portal): Table has no size prop in BulkTruckUploadModal 2026-07-22 14:11:58 +00:00
Hagernesh
8dc4dd585e feat(procurement): validate acquisition lease fields and enforce bulk-receive capacity
Reject lease start/end and monthly payment on PURCHASE acquisitions (create and
update, validated against the resulting record). Add asset_acquisitions.item_name
column + migration. Enforce warehouse/yard/zone capacity on bulk receive and apply
capacity-counter deltas on save. Adds acquisition-guard spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 12:15:47 +00:00
Hagernesh
b616f520ae feat(fleet): validate vehicle plate numbers against a letters-and-digits format
Plate, power-plate and trailer accepted any free text — a vehicle could be
saved with a plate of "assadasd". They must be letters, a hyphen, then digits,
like ET-9875 or AA-8642.

The server now enforces it on CreateVehicleDto (and UpdateVehicleDto via
PartialType): each plate is trimmed and upper-cased, then matched against
^[A-Z]{2,3}-\d{2,6}$, so "et-9875" is accepted and stored as ET-9875 while an
empty optional trailer/power plate still passes.

The fleet form gains the same check inline: FleetFormFieldDef takes an optional
pattern, the dialog tests it on submit against the upper-cased value, and the
vehicle config points plate and trailer at a regex that mirrors the server's.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 11:03:40 +00:00
Marshal
6f8456631c Implement intercity document handling and rejection notes for contracts 2026-07-21 10:20:36 +00:00
Hagernesh
92a0cc197b feat(fleet): make the dashboard stat cards link to their detail
The four headline cards — total vehicles, drivers, fuel spend, maintenance —
were static numbers with no way through to the list behind them. Each now takes
an optional href and, when set, wraps in a link to its detail page (vehicles,
drivers, fuel purchases, maintenance). A card without an href stays exactly as
before. The Card is wrapped rather than turned into a link so Mantine's Card
typing stays clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 09:22:47 +00:00
Marshal
603537a20b add yard distances management to rule engine
- Introduced new yard distances resource with CRUD operations.
- Created migration for yard distances table with necessary constraints.
- Implemented service and repository for yard distances handling.
- Added controller for API endpoints to manage yard distances.
- Updated rule engine configuration to include yard distances.
- Enhanced rule engine resource page to support yard distance selection.
- Updated contracts and train builder pages to handle new yard distance logic.
- Added error handling utility for better error message extraction.
2026-07-21 08:50:50 +00:00
Marshal
26f73cbe5f chnages 2026-07-20 13:55:26 +00:00
natib21
6ee771c953 fix search 2026-07-17 15:01:30 +00:00
natib21
0d98ccb04b fix 2026-07-17 13:10:27 +00:00
marshal
f690b635eb Merge pull request #767 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-17 14:40:59 +03:00
Marshal
221c49fcda fix issue 2026-07-17 11:38:54 +00:00
natib21
3bb4c8fb42 fix build num 2026-07-17 10:29:27 +00:00
natib21
8671b982c5 fix null value 2026-07-17 10:18:41 +00:00
natib21
84d5add58e fix four digit 2026-07-17 09:47:37 +00:00
natib21
1abf71306e add export/inport number 2026-07-17 09:15:21 +00:00
natib21
b4118e1bd4 add export/inport number 2026-07-17 08:47:52 +00:00
Marshal
41fe04652f fix issue 2026-07-16 00:33:31 +00:00
Marshal
19c9da28ae changes 2026-07-15 13:29:01 +00:00
Marshal
6d0cf50b4d train 2026-07-14 11:06:49 +00:00
Marshal
dd87c2a722 wagon work space, container validation 2026-07-10 23:29:28 +00:00