Commit Graph

124 Commits

Author SHA1 Message Date
marshalyordanos
8437a6d5f1 feat(train-crew): implement train crew management module
- Added DTOs for creating, querying, and updating train crew members.
- Created entity for train crew members with relevant fields and enums for role, nationality, and status.
- Developed service for handling CRUD operations and ensuring no duplicate crew members.
- Implemented controller to manage API endpoints for train crew operations.
- Integrated permissions for viewing, creating, updating, and deleting train crew members.
- Added frontend components for displaying, adding, editing, and deleting train crew members.
- Established API service for interacting with the train crew backend.
- Updated routing and sidebar to include train crew management section.
2026-09-04 20:45:41 +03:00
marshal
13ac3144e2 merge conflict resolved 2026-09-02 22:35:18 +00:00
marshal
6efa9dab93 feat(freight): GL rebook of cancelled wagons, seal+train required on completion, train/voyage in SMS 2026-09-02 21:23:24 +00:00
hager
3f7b744987 feat(empty-return-requests): customer-requested empty return, priced and paid
A booking sold WITHOUT the return service had no way to send its empties
back: the containers were the customer's problem and nothing in the
system priced, billed or planned the movement.

Adds the request flow end to end. The customer opens the booking, says
how many containers are coming back and types each number; the request
lands in a new backoffice queue (Empty Return Requests). Approval prices
it off the same live WITH_RETURN route rate the rule engine bills when
the service IS bought up front — per container, converted to birr, and
overridable by the reviewer — and issues the invoice there and then.
Payment settles through the normal invoice path, whose
`empty_return_request.invoice.paid` event moves the request to PAID; the
customer then books the return date and the truck.

Scheduled requests surface on Container Returns as Planned Empty
Returns, where confirming the arrival records the containers through the
existing empty-container-return flow — which in turn closes the request
once its last container is in.

Container freight only, never a booking that already ships WITH_RETURN,
and only from IN_TRANSIT onward: the empty comes back after delivery, so
the option has to outlive ARRIVED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 11:05:03 +00:00
marshal
522a65f0e7 Merge pull request #1461 from Tria-plc/freight_feature/usermanagement
feat(contracts): implement staff cancellation of contracts with reaso…
2026-08-29 14:36:08 +03:00
Marshal
6ac41cf078 feat(contracts): implement staff cancellation of contracts with reason and notification 2026-08-29 11:31:13 +00:00
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
Marshal
978f1889c6 feat(transit-agents): give transit agents a portal login
Optional IAM account per agent — nullable, nothing backfilled, so
roster-only rows keep working. Staff invite existing ones; new ones get
an account when an email is supplied. Activation reuses the shipping-line
link path. SMS reachability widens to Djibouti.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-29 07:40:07 +00:00
Hagernesh
d4373dfbe4 feat(warehouses): delete yards/zones and inspect zone contents
Yard and zone soft-delete, refused with 409 while a yard still has
zones or a zone still holds inventory. warehouse_zones:delete was
missing from the catalog — the role presets spread every zone key, so
its absence crashes FreightPositionsSeeder at boot; a migration seeds
it everywhere.

Clicking a zone opens its contents as a datatable. Container identity
comes from booking_container_units for booked cargo and from
containers for backlog registrations; bulk cargo keeps its row with no
container number rather than disappearing from the zone.
2026-08-28 14:54:17 +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
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
Nathnael
2286135228 feat(reports): add port warehouse operations summary
Reproduces the monthly count sheet a port warehouse publishes: trains,
containers by size and laden state, wagons, TEU and bulk wagons per cargo
type, each split into export and import beside an overall total.

Two departures from the spreadsheet it replaces:

- Wagons are counted distinctly from the marshalling record rather than
  derived as 20ft/2 + 40ft + bulk wagons, which overstates whenever a wagon
  ran part-loaded.
- Total is counted over everything rather than summed across the direction
  columns — a train carrying both an import and an export booking belongs to
  both and would otherwise count twice.

Demurrage is billed on invoice lines and is left to Revenue by Category.

Adds a station filter matching either end of the corridor, so one warehouse
can report the trains it worked in both directions.
2026-08-24 08:58:58 +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
Nathnael Wondisha
4a295a73a4 Merge pull request #1379 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-21 16:09:24 +03:00
ghost2023
b60e361483 feat(iam): add per-layout overview permissions
Adds edr_freight_app:overview:<layout>:view for each of the 6 overview
dashboard layouts (clearance, occ, operation, marketer, finance,
executive), seeded via OVERVIEW_LAYOUT_PERMISSIONS alongside the
existing report permissions.

Granted 1:1 to match today's role-dashboards.config.ts ROLE_LAYOUTS
key table, appended only at the terminal EDR_FREIGHT_ROLES /
EDR_FREIGHT_POSITIONS assembly points (never inside the reusable
ROLE_PERMISSION_PRESETS/POSITION_PERMISSION_PRESETS builders) so
composite positions like chief don't leak multiple layout grants from
the role arrays they spread.

The ~20 ad-hoc edr_freight_app/xxx department sub-positions are not
backfilled here and will fall back to the executive layout until
granted manually via the IAM positions admin screen.

Part of switching overview layout resolution from role/position-key
matching to permission checks, mirroring how reports already work.
2026-08-21 15:42:58 +03:00
Nathnael
25d13baa6f chore: reporting and filtering 2026-08-21 09:25:21 +00:00
Hagernesh
d4c19d7e40 finance only permission for Additional charges 2026-08-20 12:59:33 +00:00
Hagernesh
0ceb595714 feat(bookings): add ad-hoc additional-charge module
New freight.additional_charge table, independent of BookingClearanceCharge
(unbounded per booking, free-text reason). Draft -> send issues an invoice
and notifies the customer in-app/SMS/email; settles via the standard
.invoice.paid event. Adds the Additional charges row-menu entry
next to Cancel booking, permission-gated.

Not included: the Additional Payments tab UI, add-charge modal, portal pay
flow.
2026-08-20 12:59:33 +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
fb21ad1541 feat(WIP): filtering, exporting and more reports 2026-08-19 13:51:18 +00:00
Nathnael Wondisha
8e11b3a168 Merge pull request #1349 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-19 13:17:07 +03:00
Nathnael
e964a9b8f4 chore: more reporting 2026-08-19 10:14:46 +00:00
Marshal
13f66dfb66 changes 2026-08-19 08:41:51 +00:00
marshal
c1150f8af2 Merge pull request #1337 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-08-18 16:19:34 +03:00
Marshal
40904049cf feat: implement consolidation approval process for shared-wagon bookings
- Add migration for consolidation approvals table and status enum
- Create ConsolidationApprovalService to handle approval logic
- Implement repository for managing consolidation approvals
- Add entity for consolidation approval with necessary fields
- Develop frontend components for displaying and managing consolidation approvals
- Create tests for consolidation approval service to ensure correct behavior
2026-08-18 13:17:55 +00:00
Nathnael Wondisha
065f34aa67 Merge pull request #1335 from Tria-plc/freight/feat/yard-loc-ac
feat: yard scoping to position
2026-08-18 15:57:03 +03:00
Nathnael
6823a32fee feat: yard scoping to position 2026-08-18 12:55:11 +00:00
marshal
1e67034968 Merge pull request #1329 from Tria-plc/freight_feature/usermanagement
feat(freight): offer built-train wagons per boarding yard on multi-ya…
2026-08-18 11:28:32 +03:00
Marshal
c723b660e2 feat(freight): offer built-train wagons per boarding yard on multi-yard consists 2026-08-18 08:27:18 +00:00
Nathnael
7c6c894c78 Merge branch 'freight/nati-2' into freight/feat/element-chat 2026-08-17 12:53:39 +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
Nathnael
7143ba1040 feat(customers): notify marketing on returned changes, name actors in history
Three gaps on the backoffice customer detail page:

- Rejecting a change request or sending it back for correction notified
  nobody. Adds CompanyNotifierService.changeRequestReturned, which pings
  the customer desk with the reviewer, the outcome and the note. Marketing
  joins that desk via customers:view + customers:get_notification in the
  role preset — grants still come from the IAM UI, the preset only sets
  the default for new environments.
- submitted_by / reviewed_by / actor_id were stored but never resolved, so
  the History tab could say what changed but never who asked or who sent
  it back. Resolves them through a shared iam-user-name util (deduped from
  the private copy in contract-document-history.service) and renders
  "Requested by" / "Sent back to marketing by" lines. The
  changes_requested badge is relabelled to match the workflow.
- "View" opened an in-page modal one document at a time. Adds
  openFileInNewTab, which opens the tab inside the click gesture and fills
  it once the authenticated fetch resolves, and an "Open all" button that
  loops over the documents table so every file lands in its own tab.
2026-08-17 12:38:06 +00:00
Marshal
1ca7776143 Enhance manual payment processing for USD and ETB invoices
- Updated API documentation and summaries to reflect support for both USD and ETB invoices.
- Modified data structures to include trade direction for invoices.
- Adjusted UI components to accommodate manual payment confirmations and display relevant information.
- Implemented filtering options for currency in the manual payments worklist.
2026-08-17 09:13:09 +00:00
Nathnael
00bd1250ee feat: WIP element Chat intergration 2026-08-17 08:02:00 +00:00
Hagernesh
d66cfe2328 feat(billing): issue credit/debit memos against registered invoices
POST billing/invoices/:id/memo files a MoR DEB/CRE memo by reusing
createInvoice unchanged. sourceId is the original invoice's own id, not its
source's — this structurally keeps memos out of findPayable/expirePayable/
billQuery's sourceId-keyed lookups regardless of status. Credit notes are
created settled; debit notes are created open/unpaid as a genuine new
receivable, not force-settled. memoIssue is granted to the chief position,
not the general finance role.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 08:38:35 +00:00
Marshal
b9ba830a09 shipping line 2026-08-13 18:56:52 +00:00
Marshal
5837ac7b6e Merge branch 'dev' 2026-08-13 14:14:31 +00:00
marshalyordanos
9fff469ffa feat: implement shipping line bookings management
- Add ShippingLineBookingsPage for listing and managing shipping line bookings.
- Create ShippingLineDocumentsModal for document uploads related to bookings.
- Introduce ShippingLineInitiateModal for initiating new shipping line bookings.
- Implement booking document state management with booking-doc-state utility.
- Add shipping line bookings service for API interactions.
- Update index to export new components and services.
- Enhance types for freight to include shipping line credits.
2026-08-13 15:54:40 +03:00
Nathnael
3190b9bd38 Merge branch 'dev' into freight/nati-2 2026-08-13 11:34:57 +00:00
Hagernesh
c4bf3c9479 feat(freight): add company logo setting applied to every generated document
New logo-settings module (mirrors stamp-settings): single uploaded logo,
stored via FilesService/MinIO, injected as a data URL into invoice/receipt,
contract, warehouse, train-scheduling, and payment-receipt PDFs. Adds a
matching backoffice settings page and settings:logo:view/manage permissions.

>
2026-08-13 10:54:23 +00:00
Nathnael
29913259f6 feat(freight-api): add 9 commercial/finance reports
customer-status (company-profile roles, not Company — importer/
exporter/forwarder lives there), contract-lifecycle, customs-documents
(clearance milestones), invoicing-pipeline, first-last-mile-bookings
(one resolver, UNION ALL over first_mile/last_mile — verified the
raw-string .from() subquery against the live query builder, not just
hand-written SQL, after the join-alias bug earlier this branch),
invoices-by-status, payments-by-status, revenue-summary, cargo-summary.

payments carries no deleted_at column despite extending BaseEntity —
caught by column-checking against the live DB before shipping, dropped
the soft-delete filter for that one query.

Completes the ITLMS dashboard spec's 20-resolver dedup list (19 built,
freight-weight-variance dropped — no charged-vs-actual weight
distinction in the schema).
2026-08-13 08:23:19 +00:00
Nathnael
a53a9c7152 feat(freight-api): add 6 booking/train-lifecycle reports
booking-status-breakdown (dedupes the same 'status per port/train/
cargo/contract' ask across 4 dashboards), train-schedule-status,
train-turnaround, wagon-teu-utilization, loaded-capacity,
global-logistics-wagons.

Dropped freight-weight-variance from this batch: the schema has no
'charged weight' distinct from VGM/actual, so a charged-vs-actual
variance report isn't buildable without a product decision on what
'charged' means here.
2026-08-13 08:14:17 +00:00
Nathnael
c0cdf80560 feat(freight-api): add 4 fleet-ops reports
wagon-fleet-status, wagon-status-duration, wagon-requests,
locomotive-fleet-status. First batch off the ITLMS dashboard spec —
fleet data (wagons/locomotives/transfer-requests) needed no schema
work, just resolvers. No frontend changes: catalog is server-driven.
2026-08-13 08:08:13 +00:00
Nathnael
08804c84e9 feat(freight-api): seed a permission per report
Each report key (REPORT_KEYS) mints its own edr_freight_app:reports:<key>:view
permission, derived the same way rule-engine resource permissions are.
reports:view stays the section master key; STAFF_DASHBOARD_KEYS grants every
report key alongside it so existing presets don't regress on reseed.
2026-08-13 07:52:10 +00:00
marshalyordanos
9aae132dd4 feat: add shipping line companies management
- Implement ShippingLineCompaniesService for registering and managing shipping line companies.
- Create ResendActivationAction component for resending activation links to shipping lines.
- Develop ShippingLineCompaniesPage for listing and registering shipping lines with validation.
- Introduce shippingLineCompanies.service for API interactions related to shipping lines.
- Define types for shipping line companies, including registration and pagination.
- Add placeholder pages for shipping line portal, including home, bookings, help, invoices, and settings.
2026-08-13 08:54:20 +03:00
Hagernesh
2d4da8110b eims integration master test complete 2026-08-12 14:12:23 +00:00
ghost2023
2a816912fc fix(freight-permissions): split company stamp from per-officer teeter permission 2026-08-12 13:18:29 +03:00
Marshal
6434bb266c Merge branch 'dev' 2026-08-12 06:44:30 +00:00