Commit Graph

4712 Commits

Author SHA1 Message Date
Hagernesh
58cb71a9cf feat(train-scheduling): add direct truck-to-train load action beside Load
Export bookings whose cargo goes straight from customer truck to wagon
never get a warehouse GRN, so the load gate (assertExportReceivedWithGrn)
rejects them forever unless staff first flip exportHandoverMode on the
booking detail page, then come back and retry Load.

Add a Truck to Train button next to Load in the schedule workspace's
on-train list, shown for EXPORT bookings at the boarding yard. One click
sets exportHandoverMode=DIRECT_TO_TRAIN then loads the booking.
2026-08-13 08:55:17 +00:00
Nathnael
6a102bf938 feat(reports): header actions, single export dialog, date-range presets
- ReportPage drops its own PageHeader (and the back arrow); ReportView
  now optionally renders the header itself (pageHeader prop) with
  export/refresh as its actions. Embedded ReportSection usage is
  unaffected (keeps the inline toolbar next to filters).
- Replace the two xlsx/pdf icon buttons with one Export button opening
  a dialog: format as large icon radio cards, fields as checkboxes
  (select-all toggle), record count (default all, capped per format).
  Export applies the report's current filters and sort.
- Backend: export route accepts fields (whitelisted against the
  report's own columns) and limit; ReportExportService takes an
  optional column subset instead of always dumping every column.
- Fixed a real bug found while wiring this up: runAll() ignored the
  caller's sortBy/sortOrder and always used the report's default sort,
  so exports silently didn't match whatever order was on screen.
- Report daterange filters now use DatePickerInput + the shared
  getDateRangePresets() (Today/Last 7 days/This month/...) instead of
  two bare DateInputs, matching every other date-range filter in the
  app.
- Removed the reports hub grid page. /dashboard/reports now redirects
  to the first report the caller has access to, or /dashboard if they
  have none.
2026-08-13 08:53:03 +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
Nathnael
efc5a24380 feat(reports): add optional chart view to the report engine
ReportDefinition gets an optional chart {type: line|bar, x, y[]} field —
plots the same rows the table gets, no separate query. Frontend adds a
table/chart toggle (defaults to table) using the existing recharts
dependency, no new package.

Chart view fetches up to 100 rows (the API's page-size ceiling) instead
of the table's current page, so it doesn't silently plot a fraction of
the filtered set; shows a truncation note past that cap.

Wired onto 5 reports as proof: wagon-fleet-status, locomotive-fleet-
status, booking-status-breakdown, revenue-summary (bar), and
global-logistics-wagons (line). Everything else stays table-only —
charting is opt-in per report, not a default.
2026-08-13 08:34:08 +00:00
Nathnael
6f14cf8bbf feat(freight-backoffice): add DateRangePicker, replace ad-hoc from/to date filters
Adds a shadcn Popover+Calendar range picker with presets (Today, Last 7/30
days, this/last month, YTD) and Apply/Cancel. Swaps it into every shadcn-family
from-to date filter: activity log, sector reports, incoming records (EN
branch), CombinedFilterBar (13 consumers), user records, audit log — also
fixes an uncontrolled-input bug on the audit log date fields.

Mantine-based ListControls/ReportFilters left untouched (different UI kit).
2026-08-13 08:33:59 +00:00
Hagernesh
833e62990e feat(train-scheduling): add wagon type, tare, equated length, station, seal no and note columns to import marshalling doc
Import Load List / Marshalling Document only rendered Seq, Wagon,
Booking, Company, Load, Container numbers, Weight T — missing fields
present on the physical marshaling sheet (wagon type, tare, equated
length, departure/arrival station, seal no) and a blank note column
for yard staff. Export marshalling doc already had most of these;
import doc now matches. Existing columns kept in place, unchanged.
2026-08-13 08:25:20 +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
9930bef8aa fix(freight-api): quote fallback sort aliases
Sorting by a column with no explicit sortExpr fell back to the bare
select alias unquoted. Postgres folds unquoted identifiers to lowercase,
so any camelCase alias (utilizationPct, bookedTons) 42703'd. Quote the
fallback to match the case TypeORM's addSelect actually emitted.
2026-08-13 07:54:44 +00:00
Nathnael
081b9945cb feat(freight-backoffice): render reports from the server-driven catalog
Drop reportConfigs.ts (per-report FE config duplicating the backend) and
the chart-drawing ReportPage. Replace with ReportView: one engine that
renders any report the GET /reports catalog describes — filters, KPI
strip, sortable/paginated DataTable, xlsx/pdf export via blob download.
ReportSection embeds a report inline on any page, scoped by idKey, and
renders nothing if the caller lacks that report's permission.

Sidebar Reports submenu is now built from the live catalog
(sidebar-sections.tsx + App.tsx) instead of a hand-listed key — no FE
edit needed to add or hide a report.
2026-08-13 07:52:29 +00:00
Nathnael
b7583df426 feat(freight-api): replace canned reports with a generic report engine
Nuke the 17 hand-written raw-SQL reports (no pagination, hard LIMITs) and
the reports module built around them. Replace with a resolver contract:
a report declares columns/filters/permission and a TypeORM QueryBuilder;
ReportRunnerService applies filtering, a whitelisted sort, offset/limit
paging, and a COUNT(*) FROM (query) wrapper for the total (getCount() is
wrong for GROUP BY). ReportExportService re-runs the same resolver
unpaginated for xlsx (exceljs) and pdf (existing PdfRenderService, now
landscape-capable) exports.

Ships with 4 reports: bookings-list, revenue-by-customer,
aging-receivables, contract-utilization. Catalog + per-report permission
checks live in the controller; adding a report is one new definitions/
file plus a REPORT_KEYS entry, no frontend change.
2026-08-13 07:52:20 +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
Nathnael
d261d6ea7c style: inter module integration 2026-08-13 06:54:54 +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
marshal
58ca7338f4 Merge pull request #1267 from Tria-plc/staging
Staging
2026-08-12 20:42:25 +03:00
marshal
216b358bdd Merge pull request #1266 from Tria-plc/dev
freight
2026-08-12 20:27:13 +03:00
marshal
f5e98ae67c Merge pull request #1265 from Tria-plc/freight_feature/usermanagement
fix issue
2026-08-12 20:21:26 +03:00
Marshal
e37f1e0807 fix issue 2026-08-12 17:19:06 +00:00
Hagernesh Tadesse
e0f18f17b3 Merge pull request #1264 from Tria-plc/eims-integration
Eims integration

feat(eims): register receipts, cancellations, and QR-verified invoices with MoR EIMS

Extends EIMS integration from invoice registration to the full document
set: sales/withholding receipt registration, registration cancellation,
and a signed verification QR embedded on the printed invoice/receipt
(new eims_signed_qr column, widened IRN/previous-IRN columns for the
longer cancelled-doc format). Invoice document renderer and its
Chromium-less fallback both carry the QR now; seal rendering goes
through the shared seal-markup util instead of duplicating it inline.

Also closes a wagon-loading gap unrelated to EIMS: re-check the
1×40ft/2×20ft-per-wagon TEU packing rule at loading-confirmation time,
not just at allocation time, so a later wagon swap or edited allocation
can't sneak a wagon over capacity undetected.
2026-08-12 17:18:28 +03:00
Hagernesh
2d4da8110b eims integration master test complete 2026-08-12 14:12:23 +00:00
Hagernesh
8d53dc17ce docs(eims): confirm signing algorithm and cert format against MoR's guide
Cross-checked our RSA-SHA512 signing and raw-bytes certificate encoding
against MoR's own "Guide to Generating and Using Certificate for E-Invoicing"
(supplied today). Both were previously documented as our best inference from
the Postman collection; the guide names SHA512withRSA explicitly (PKCS#1v1.5,
matching Node's createSign default) and its own worked example certificate is
byte-for-byte the same Subject:/Issuer: + 3-cert PEM chain text-file format
ours is. No behavior change -- the comment now says confirmed, not assumed.

Field order, section names, date format and the {request, signature,
certificate} envelope in the guide's worked example all match our mapper
exactly (order doesn't matter per the guide, but it's a further concordance
check). The one guide/live disagreement -- its example shows "NatureOfSupplies":
"Goods" where our actual 400 SCHEMA ERROR demanded lowercase "goods"/"service"
-- is left as-is: the live, machine-generated schema error outranks a static
doc example that may predate a schema change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:08:51 +00:00
Hagernesh
5c2afe3454 fix(notifications): guard emitNew/emitUnreadCount against no WS server
@WebSocketServer() only wires `server` once the WS adapter attaches to a
running HTTP listener. It never does under NestFactory.createApplicationContext
(scripts, one-off jobs) -- confirmed live tonight, when the EIMS self-test
registration's failure alert crashed with "Cannot read properties of null
(reading 'to')" instead of just logging that no socket was available.

The registration result itself was unaffected (postSigned already resolved,
the EimsApiException was correctly re-thrown), but the crash happened inside
an await'd call in the same chain -- in a context where it wasn't caught, it
would have masked whatever result the caller actually cared about.

Both push methods now skip and log at debug level when no server is attached,
since the notification row is already persisted by the time they're called --
a missing socket just means "no live push this time", not a reason to lose
the caller's own outcome. `server` drops its `!` non-null assertion to match.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:08:51 +00:00
marshal
bf67016588 Merge pull request #1263 from Tria-plc/dev
Dev Freight
2026-08-12 16:50:24 +03:00
marshal
50e7ecc9eb Merge pull request #1262 from Tria-plc/freight_feature/usermanagement
feat: fuel surcharge per lane and cargo type
2026-08-12 16:49:27 +03:00
Marshal
ff3cee12e3 feat: fuel surcharge per lane and cargo type 2026-08-12 13:47:53 +00:00
marshal
c93a6f8332 Merge pull request #1261 from Tria-plc/freight_feature/usermanagement
baseLiters
2026-08-12 16:30:33 +03:00
Marshal
dd39c2be7c baseLiters 2026-08-12 13:29:31 +00:00
Nathnael Wondisha
494b7aeca6 Merge pull request #1260 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-12 16:19:23 +03:00
Nathnael
5a856027af feat: add email and password 2026-08-12 12:28:37 +00:00
Nathnael
0f1bac8080 feat(freight-api): add non-PII auth context to request log line 2026-08-12 12:28:37 +00:00
marshal
135c8e2b50 Merge pull request #1259 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-08-12 14:28:04 +03:00
Marshal
ddcdcab518 merge conflict 2026-08-12 11:24:22 +00:00
Marshal
08c8b52f85 feat(portal): show payer account note and train number on booking windows 2026-08-12 11:23:19 +00:00
Marshal
f882104ed3 fix(train-scheduling): move loose wagons and locomotives on train merge 2026-08-12 11:23:10 +00:00
Marshal
3dbda745dd feat(contracts): lazily expire lapsed contracts and price fuel surcharge 2026-08-12 11:23:04 +00:00
Marshal
a02d24806b feat(rule-engine): add fuel surcharge rate trigger and cargo flag 2026-08-12 11:22:51 +00:00
Abubeker Yasin
f9167f84f7 Merge pull request #1258 from Tria-plc/dev
Merge dev to staging
2026-08-12 14:14:30 +03:00
Stephanos A.
56da01dc4c Merge pull request #1257 from Tria-plc/alpha
Backoffice build issue resolution
2026-08-12 13:50:44 +03:00
Stephanos A
057d68709b Backoffice build issue resolution 2026-08-12 13:44:52 +03:00
Nathnael Wondisha
f6be3f4e32 Merge pull request #1255 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-12 13:23:29 +03:00
Stephanos A.
ec2b381870 Merge pull request #1256 from Tria-plc/alpha
Overall report and segment tariff override updates
2026-08-12 13:23:00 +03:00
ghost2023
2a816912fc fix(freight-permissions): split company stamp from per-officer teeter permission 2026-08-12 13:18:29 +03:00
Stephanos A
9d19801535 Overall report and segment tariff override updates 2026-08-12 13:11:24 +03:00
ghost2023
02a264930b fix: consolidate stamp settings into single company stamp page 2026-08-12 13:04:18 +03:00
Nathnael
068ee49a9f style: invoice 2026-08-12 09:33:21 +00:00
Nathnael
bd9f7f354a feat(freight-api): enrich canonical request log line
Emit the request line as raw JSON on stdout (level/time/logger as fields)
instead of through Nest's console logger, whose prefix made it unparsable.

Collect data points via logCtx at the flow chokepoints: BaseRepository
writes (status changes, creates, deletes), invoice transitions, payment
intent lifecycle + outbound payment-service calls, booking/contract entry
state, review-note reasons, signatures and OTP verify outcomes.
2026-08-12 09:31:31 +00:00
Marshal
4efd65c105 feat: key bulk templates by trade direction
Bulk contract templates are now unique per (cargo type, trade direction,
customs option) instead of (cargo type, customs option). Intercity is
domestic and crosses no border, so it carries no customs variant:
with_customs stays null there, enforced by a check constraint.

Contract resolution already passed the trade direction through but the
bulk lookup dropped it, so one template served all three directions.

Container templates are unchanged — cargo_type_id is null on those rows,
which keeps them out of both the new index and the constraint.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 09:20:28 +00:00
marshal
b485e56a3e Merge pull request #1254 from Tria-plc/freight_feature/usermanagement
fix issue
2026-08-12 12:08:41 +03:00
Marshal
357aae7d82 fix issue 2026-08-12 09:08:08 +00:00