Skip to content

Reporting

Sergio Hernandez edited this page Jul 24, 2026 · 1 revision

Reporting

The Reporting service turns platform data into files. It is REST-only (Minimal APIs) and has no database of its own — every dataset is composed from the services that own the data.

Related pages: Manager · Trip Management · Inter-Service Communication


The governed catalog

A report is not just code. Each one has a catalog row in Manager (app.reports) carrying its governance metadata:

Column Meaning
Code The stable identifier used to invoke it
Category Operations, Gps, Documents, Workforce, Trips, Administration
RequiredFeatureKey The account feature that must be enabled; null means global
ManagerOnly Whether the report is restricted to the Manager role
SupportsPdf Whether PDF rendering is offered
SortOrder Display order within its category
Active Whether the report is offered at all

Governance is enforced twice:

  1. Manager's getReports filters server-side by the caller's account features and role, so the portal only lists what the caller may run.
  2. Reporting re-enforces the same metadata at execution time via Manager reportByCode (cached 60 s). A hidden report invoked directly by code gets 403 or 404 — the portal filter is convenience, not the control.

The catalog is re-seeded idempotently on every Manager start, per-code upsert. Code is the source of truth for seeded metadata; only Active survives a restart. See Manager.


Catalog contents (30 reports)

Operations (4)

Code Report Feature
live-report Live Report
position-record Position Record
transporters-in-geofence Transporters In Geofence geofencing
geofence-events Geofence Events geofencing

GPS integration (10)

Code Report Feature PDF Manager only
gps.provider-health-summary GPS Provider Health Summary gps.integration
gps.provider-sync-history GPS Provider Sync History gps.integration
gps.sync-statistics GPS Sync Statistics gps.integration
gps.synchronized-device-inventory GPS Synchronized Device Inventory gps.integration
gps.recently-added-devices GPS Recently Added Devices gps.integration
gps.unassigned-devices GPS Unassigned Devices gps.integration
gps.ignored-devices GPS Ignored Devices gps.integration
gps.assignment-history GPS Assignment History gps.integration
gps.latest-position-freshness GPS Latest Position Freshness gps.integration
gps.position-history GPS Position History gps.positionHistory

Documents (4)

Code Report PDF
documents-expiring Documents expiring within a window
documents-missing-required Transporters missing required documents
documents-share-activity Document share activity
documents-upload-volume Document upload volume

All gated by documents.

Workforce (3)

Code Report PDF
workforce-driver-registry Driver registry export
workforce-qualification-expirations Driver qualifications expiring within a window
workforce-assignment-history Driver to transporter assignment history

All gated by workforce and ManagerOnly — their feeds require Drivers/Read, which only the Manager role holds. Widening the dispatcher role to read driver records would be the wrong trade for a report.

Trips (6)

Code Report PDF
trip-summary Trip summary by period
trip-detail Trip stop-level detail
trip-on-time-performance Trip on-time performance
trip-stop-dwell Trip stop dwell distribution
trip-toll-cost Estimated toll cost by trip
trip-pod-export Proof-of-delivery register

All gated by trip-management, and not ManagerOnly — these are dispatcher-facing and their feeds require Trips/Export, which the User role holds. trip-pod-export carries receiver names, identity documents and signature coordinates, but the dispatcher owns the trip that produced them; the control on bulk PII export is the export audit.

Administration (3)

Code Report PDF
accounts-by-status Accounts by lifecycle status
feature-enablement-matrix Feature enablement matrix across accounts
group-membership-export Group membership export

Global (no feature key) and ManagerOnly.


Dataset model

Every report supplies GetDatasetAsync and returns a shared ReportDataset. Preview, Excel and PDF all render from that one dataset — there is no per-format data path to drift.

Column headers are resolved by VM property name through the Reporting Resources ResourceManager.

Renaming a VM property requires renaming the matching resx keys, or the header falls back to the raw property name.


Limits

Configured under AppSettings:Reporting:

Setting Default Behaviour
MaxExportRows 100 000 Excel export ceiling
MaxPdfRows 500 PDF refuses a larger dataset — it never truncates
PreviewRows 100 In-portal preview

Paged upstream feeds are drained at 500 rows per page with a 100 000-row defensive cap (GeofenceReader, TripReportReader and the GPS readers).


Rendering

Format Implementation
Preview JSON from the shared ReportDataset
Excel The default for every catalog row
PDF PdfReportBuilder, PDFsharp-MigraDoc 6.2.4 — only for rows flagged SupportsPdf

PDF exports fetch account branding from Manager's accountBranding (cached 60 s, failure-tolerant — a branding error never fails the export). The account name is rendered; logo bytes are not embedded yet.


Upstream reads

Source Provides
Manager Master data, GPS integration inventory, document compliance, account and feature data, the catalog metadata itself
Telemetry Position history, operator health summaries, sync runs, latest positions
Router Device positions, provider position records
Geofencing Transporters in geofence, geofence events
TripManagement Trip, stop, toll and proof-of-delivery datasets

Reporting's Router, Geofence and Telemetry clients are among the few registered WithRetry — they are query-only, so a retry is safe. See Inter-Service Communication.

Because Reporting is REST-only, it does not host a GraphQL server and the platform's GraphQL hardening (max depth, dev-only error detail) does not apply to it.


Adding a report

  1. Implement the IReport (with GetDatasetAsync) in Reporting.
  2. Add the seeded Manager catalog row with its governance metadata — Category, RequiredFeatureKey, ManagerOnly, SupportsPdf, SortOrder — to the DBInitializer upsert list.
  3. Add the portal reportList and reportDescriptions i18n keys, in both en.json and es.json.
  4. Add a filter strategy in the portal for the report's parameters.
  5. Add resx keys for every VM property name that becomes a column header.

Clone this wiki locally