Commit Graph

320 Commits

Author SHA1 Message Date
Hagernesh
fd6f0d03b6 feat(loading): notify loaded and left-behind containers, surface the CAS
A booking is routinely loaded in parts, and nothing told the customer which
containers boarded and which stayed behind. The carriage acceptance sheet was
the only record, and it both totalled up cargo still sitting in the yard and
lived inside a Warehouse documents bundle that direct truck-to-train cargo
has no business in.

The sheet now marks each wagon Loaded or Not loaded and totals only the loaded
ones. On load, the customer gets an in-app, SMS and email notice carrying the
train number, route, departure time and both container lists — capped to a
summary on SMS and email, complete in the inbox. Anything left behind also
raises a warehouse-desk notice so somebody owns finding it space.

That desk is addressed by a new warehouse_inventory:get_notification
permission: a recipient selector, not a route guard, so ops can assign who
gets pinged without granting access to anything.

The GRN notice went out over SMS alone, to whatever phone number the gate
clerk typed. Where the receive carries a booking it now resolves the company
and delivers in-app, SMS and email, skipping the typed phone so the customer
is not texted twice; manual and backlog receives keep the old path.
2026-08-29 08:47:39 +00:00
marshal
abf856547a Merge pull request #1453 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-08-29 10:40:53 +03:00
Hagernesh
312c1f1da3 feat(warehouses): backoffice UI for container stack positions
Surfaces the physical stack/slot model in the staff app.

- ZoneLayoutModal: stacks drawn level by level with occupancy colours,
  configured-vs-built-vs-occupied counts, and stack create/delete plus
  block/reserve/free on empty levels
- SlotPicker in the store and move modals, offering only the next
  fillable level of each stack so the form cannot suggest a position
  the API will refuse
- move modal warns when a container is buried, lists the blockers, and
  disables the action instead of firing a 409
- fix: move() now asserts accessibility server-side, matching release —
  both are exits from a stack
2026-08-29 06:39:29 +00:00
Marshal
7e163088d9 fix issue, add transit flow, fix cancellation 2026-08-28 22:13:49 +00:00
Hagernesh
3f4fd8648a feat(import-operations): bulk Excel upload for yard-resident empty containers
Empties already sitting in an EDR yard but never entered in the system had
to be typed one at a time. Adds a bulk path: parse the sheet in the browser
(all-or-nothing, row-numbered errors), preview it, then POST one batch.

The server rejects the batch if any container already has a non-COMPLETED
return, so re-uploading the same sheet cannot duplicate boxes. No interchange
notification fires — these are historical rows, not a live handover.

Company is an Autocomplete over registered customers that also accepts a
typed name, since a backfilled box may belong to a company that is not a
customer yet. Exact name match sets customer_id; the name always lands in the
new empty_container_returns.company_name.

Also fixes the single Record Return modal, which collected Yard and Zone and
then dropped them before the API call, and did not invalidate the returns
list after a standalone return.
2026-08-28 11:38:19 +00:00
Hagernesh
9cd29a21ed feat(train-scheduling): log leg-slot board/alight events at checkpoints
Leg slots (stampSlotLegs — bookings boarding/alighting mid-corridor)
reaching their board/alight yard produced no ScheduleWagonAdjustmentLog
row, unlike planned couples/cuts. Without it the marshalling document
has no way to show a wagon coupling in already loaded, or uncoupling
with cargo, at a mid-corridor stop.

recordCheckpoint now logs ADD at the board yard and REMOVE at the
alight yard for these slots, deduped against existing rows since
passedYardIds re-includes earlier stops on every checkpoint call.
Purely observational — the physical wagon was already pinned to the
slot at schedule-build time, so no wagon/consist state changes.

Stage 3 of the multi-stop marshalling plan (per-event numbered docs);
stages 4-6 (generalized doc builder, endpoints, UI) still open.
2026-08-28 11:16:46 +00:00
Nathnael Wondisha
cfd182cfea Merge pull request #1438 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-28 14:09:18 +03:00
Nathnael
aa3100d161 Merge branch 'dev' into freight/nati-2 2026-08-28 11:08:35 +00:00
marshal
b33e70d85b Merge pull request #1437 from Tria-plc/freight_feature/usermanagement
fix issues
2026-08-28 13:35:20 +03:00
Marshal
3015de7508 fix issues 2026-08-28 10:34:02 +00:00
Nathnael
0e9cfbce66 fix(reports): count container tonnage in exports and reports
Every SQL tonnage in the export datasets and report definitions used
`COALESCE(b.bulk_total_weight_tons, b.cargo_total_weight_vgm)`. COALESCE
falls through on NULL, never on 0 — and the portal booking wizard stores
`cargo_total_weight_vgm = 0` for container freight on purpose, because VGM
is captured per container line, not as a booking-level figure. So every
portal-created container booking reported as weighing nothing. The
backoffice wizard does store a booking-level total, so the same table holds
both shapes and the numbers looked erratic rather than uniformly zero.

Extract the resolver the TypeScript side already has three copies of
(bookingCargoTons, cargoTonsAndItems, totalVgmTons) into one SQL helper:
NULLIF both booking-level columns, then fall back to
SUM(booking_container.total_vgm_tons). Applied to the bookings and
train-schedules export datasets, the cargo-summary, contract-utilization and
booking-status-breakdown reports, and the intercity booking list.

On dev data this recovers 116 of 154 zero-weight container bookings and
raises live booking tonnage from 42,973 t to 61,424 t.
2026-08-28 09:20:46 +00:00
marshal
081f66fb82 Merge pull request #1434 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-08-28 10:34:31 +03:00
Marshal
ba56974e32 feat(train): enhance train history and scheduling features
- Added a reason field to train history entries for detach/maintenance actions.
- Updated TrainHistoryPanel to display the reason for wagon detachments.
- Introduced per-wagon load/unload functionality in ScheduleWorkspacePanel with a modal for managing individual wagons.
- Implemented API endpoints for loading and unloading specific wagons, including the ability to cancel remaining wagons with a reason.
- Refactored detach request handling in TrainBuilderDetailPage to streamline the process and remove the approval flow, requiring a reason for detachments.
- Updated types and services to support new wagon loading/unloading features and booking wagon retrieval.
2026-08-28 07:33:28 +00:00
Nathnael Wondisha
a3b29b2792 Merge pull request #1422 from Tria-plc/freight_feature/usermanagement
feat: refine loading window validation and improve error messaging fo…
2026-08-27 08:26:44 +03:00
Marshal
d9017df730 feat: refine loading window validation and improve error messaging for dispatching 2026-08-27 03:26:44 +00:00
marshal
3f353e52b8 Merge pull request #1420 from Tria-plc/freight_feature/usermanagement
feat: enhance station work logging with user display names and improv…
2026-08-27 05:30:58 +03:00
Marshal
6ec3c8c5e0 feat: enhance station work logging with user display names and improve loading/unloading logic 2026-08-27 02:29:50 +00:00
Hagernesh
42ae6b9752 feat(train-scheduling): show coupled/uncoupled wagons on intercity marshalling doc
Marshalling 2 rendered only the final consist after a mid-corridor
adjustScheduleConsist call, with no signal that anything changed.
Reuses the existing ScheduleWagonAdjustmentLog (already recording
every ADD/REMOVE/SWITCH) filtered to the printed stop's yard and to
ADD/SWITCH, and prints a Consist changed at this stop box. Origin
import/export docs are untouched — the option is only passed from
intercityMarshallingDocument.
2026-08-26 19:00:43 +00:00
Hagernesh
69062389c7 fix(train-scheduling): marshalling docs respect mid-corridor wagon coupling
Origin marshalling (import + export) now prints leg slots as
TO BE LOADED AT <board yard> with board/alight stations and keeps
their containers out of the loaded tallies. Intercity Marshalling 2 no
longer hides whole-route cargo whose allocation never left PLANNED
(import flow confirms loading at schedule level), so the on-board view
matches the physical consist before and after mid-corridor coupling.
2026-08-26 08:30:38 +00:00
marshal
bcc5daa137 Merge pull request #1415 from Tria-plc/freight_feature/usermanagement
feat: implement MANUAL_ONLY status for bookings and update related logic
2026-08-26 01:02:18 +03:00
Marshal
29371b0b39 feat: implement MANUAL_ONLY status for bookings and update related logic 2026-08-25 22:01:03 +00:00
marshal
1459e646f6 Merge pull request #1414 from Tria-plc/freight_feature/usermanagement
feat: enhance train scheduling and contract management features
2026-08-26 00:46:17 +03:00
Marshal
b926a3116e feat: enhance train scheduling and contract management features
- Added StationWorkControls to manage loading/unloading phases in TrainScheduleV2DetailPage.
- Implemented API endpoints for recording station work and managing wagon detach requests.
- Updated contract templates to include Ethiopian customs handling options.
- Enhanced shipment forms to collect customs clearing agent details for without-customs bookings.
- Introduced NUMBER_OF_WAGONS as a unit of measure for bulk cargo, allowing customers to specify wagon counts.
- Improved validation for customs clearing agent information in shipment forms.
- Updated various components and services to accommodate new features and ensure data integrity.
2026-08-25 21:44:21 +00:00
marshal
a4e9466915 Merge pull request #1412 from Tria-plc/freight_feature/usermanagement
feat: enhance booking and audit log functionalities
2026-08-25 02:50:34 +03:00
Marshal
d5a5085d6d feat: enhance booking and audit log functionalities
- Implemented read-only locking for customer-requested container sizes and billing currency in the GlCreateBookingForm component.
- Added functionality to lock partner quantities based on shipment requests in the ConsolidationPartnerPanel.
- Introduced a new Leave action in the LogPassYardWorkModal to unassign bookings from trains.
- Enhanced the AuditLogsPage to support filtering by action and added a Go button for direct navigation to entity detail pages.
- Updated WagonCancellationsPage to handle odd-20ft credits requiring partner selection during rebooking.
- Improved TrainScheduleV2DetailPage to allow manual loading of cargo and display warnings for unassigned bookings.
- Added a new reference field to the audit logs for better searchability and tracking of actions.
- Created a migration to add the reference column to the audit logs table and established an index for efficient querying.
- Defined a registry for audit reference sources to streamline the retrieval of human identifiers for various entities.
2026-08-24 23:49:20 +00:00
Nathnael
0a85dbe60d Merge branch 'dev' into freight/nati-2 2026-08-24 14:02:03 +00:00
Marshal
2a107e8ba3 fix issue -> consolidation 2026-08-24 12:24:23 +00:00
Nathnael
17c2dca3cc feat(reports): record loading and unloading time per stop
The OCC report publishes total loading and unloading time and the other
activity left over from a station stay, but nothing recorded when handling
started or ended — the July 2026 seed had to write the figure into a
checkpoint note. Four nullable stamps now ride the stop's arrival row, which
is the row the staying-time report builds a stay from (a turnaround's
departure belongs to a different schedule).

Handling is unloading start to loading end, so a container stop reads as one
window and a bulk station that only loads or only unloads still reports its
half; other activity is the rest of the stay. Both stay NULL where nothing
was logged rather than collapsing to zero.

- station-staying-time: + loading/unloading and other activity per stop
- turnaround-cycle: + the same, summed over the cycle's stops
- loading-unloading (new): per train per station per period, so a week or
  month view is that train's average over its stops
- the stop/stay query moves to operations-classification, shared by both
2026-08-24 12:09:04 +00:00
Marshal
979f024869 feat: enhance booking cancellation logic for consolidated pairs with one paid side 2026-08-24 07:13:50 +00:00
Marshal
716444e60a feat: add pagination to schedule history and consolidation approvals
- Implemented pagination in ScheduleHistoryPanel to manage large history entries.
- Updated API to support pagination parameters for schedule history.
- Enhanced ConsolidationApprovalsPage with tabbed navigation and pagination for approval rows.
- Introduced new types for paginated responses in bookings and train scheduling services.
- Added a database migration to create an index on wagon_booking_allocations for performance improvements.
2026-08-23 04:51:34 +00:00
Marshal
e2189040fa feat: add pagination to schedule history and consolidation approvals
- Implemented pagination in ScheduleHistoryPanel to manage large history entries.
- Updated API to support pagination parameters for schedule history.
- Enhanced ConsolidationApprovalsPage with tabbed navigation and pagination for approval rows.
- Introduced new types for paginated responses in bookings and train scheduling services.
- Added a database migration to create an index on wagon_booking_allocations for performance improvements.
2026-08-23 04:49:58 +00:00
marshal
105879b531 Merge pull request #1399 from Tria-plc/freight_feature/usermanagement
feat(train-scheduling): mid-route consist changes, audit history, saf…
2026-08-23 06:59:27 +03:00
Marshal
8e6fc09aac feat(train-scheduling): mid-route consist changes, audit history, safer workspace
- planned couples: loose wagons join the train at a route stop, added
  from the schedule yards tab; capacity credits them per corridor edge
  and coupling validates locomotive weight/length caps per leg
- real-cut toggle: a cut wagon permanently leaves the train build at
  its cut yard (soft cut still sits out one trip only)
- fix heaviest-leg display counting a shared slot's full cargo on
  every spanned edge (phantom pull-weight overload on S-2026-00045)
- confirmation dialogs for workspace add/load/unload/remove actions
- train-builder History and Detached-wagons tabs, backed by paginated
  endpoints; builder detaches now always write adjustment-log rows

Migrations 3660 (planned_wagon_couples, planned_wagon_real_cuts) and
3670 (adjustment log train_schedule_id nullable) — both applied to the
dev DB by hand; watch mode does not run migrations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 03:55:54 +00:00
Hagernesh
e426e0c16e feat(train-scheduling): dedicated load/unload permissions
Carves cargo load/unload confirmation out of the coarse
trainScheduling.update permission into its own guard
(TrainSchedulingLoad/TrainSchedulingUnload), covering import, export,
and intercity — the generic per-booking route already serves all
directions, and the intercity-specific route gets the same two keys.
Adds the catalog entries and grants them to operationsOfficer/director
alongside the existing .update grant so current access is unchanged.
2026-08-22 09:17:28 +00:00
Marshal
ba89b670c8 fix issue 2026-08-22 06:26:43 +00:00
Marshal
3455c1b3b4 fix issue 2026-08-22 01:29:44 +00:00
Marshal
1ab2cfdb3b fix issue 2026-08-22 01:23:50 +00:00
Marshal
b6c1efa043 fix issue 2026-08-22 00:49:53 +00:00
Marshal
bad418d79e changes 2026-08-22 00:09:00 +00:00
Marshal
c48e9b8905 fix issue and add consolidation 2026-08-21 23:28:59 +00:00
Marshal
09deecd04c fix issue and add consolidation 2026-08-21 23:16:06 +00:00
Marshal
4c549029fe feat(clearance): preview charge documents before and after upload 2026-08-21 07:04:22 +00:00
Marshal
d99b294c21 fix issue 2026-08-20 18:10:29 +00:00
Marshal
9e1d5ee9f2 [200~feat: add CustomsPaymentsCard and PaymentsTab components for handling customs payments and payment summaries 2026-08-20 15:45:42 +00:00
Nathnael
2ec818e590 Merge branch 'dev' into freight/nati-2
# Conflicts:
#	apps/edr-freight-api/src/app.module.ts
#	apps/edr-freight-api/src/seed/freight-permissions.registry.ts
#	apps/edr-freight-web/backoffice/src/components/layout/sidebar-sections.tsx
#	apps/edr-freight-web/backoffice/src/constants/URLS.ts
#	apps/edr-freight-web/backoffice/src/lib/permissions.ts
2026-08-20 11:33:19 +00:00
Nathnael
7446adaa88 feat(api): accept several yards on each end of a route filter
Bookings, contracts and train schedules all validated originYardId /
destinationYardId (originStationId / destinationStationId) as a single
@IsUUID and matched with `=`, so a list could be narrowed to exactly one
lane. The filter bar can now ask for several stations per end, and each
end independently, which needs the same on the server.

@IdListParam() is the shared transform: one id, a comma-separated list,
or a repeated query param, always landing as a string[]. It yields
undefined rather than [] when nothing usable is left — a repository that
branches on `?.length` can then never hand TypeORM an empty array, which
compiles to the syntax error IN (). It stays backwards compatible with
the single-value form, so existing deep links and saved views are
unaffected.

Matching moves to IN (:...ids) — for contracts inside the two existing
EXISTS subqueries, which keeps meaning "has a route from one of these
origins" AND "has a route to one of these destinations", not necessarily
the same route. All three statements were EXPLAIN-validated against
edr_dev.
2026-08-20 11:24:46 +00:00
Marshal
c723b660e2 feat(freight): offer built-train wagons per boarding yard on multi-yard consists 2026-08-18 08:27:18 +00:00
Marshal
0e228bfd8d changes 2026-08-17 06:14:25 +00:00
Marshal
5ce5cbe29d feat: enhance booking and scheduling features with shipping line support and improved search functionality 2026-08-16 08:18:40 +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