-
Notifications
You must be signed in to change notification settings - Fork 1
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
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:
- Manager's
getReportsfilters server-side by the caller's account features and role, so the portal only lists what the caller may run. - 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.
| Code | Report | Feature |
|---|---|---|
live-report |
Live Report | — |
position-record |
Position Record | — |
transporters-in-geofence |
Transporters In Geofence | geofencing |
geofence-events |
Geofence Events | geofencing |
| Code | Report | Feature | 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 |
| Code | Report | |
|---|---|---|
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.
| Code | Report | |
|---|---|---|
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.
| Code | Report | |
|---|---|---|
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.
| Code | Report | |
|---|---|---|
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.
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.
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).
| Format | Implementation |
|---|---|
| Preview | JSON from the shared ReportDataset
|
| Excel | The default for every catalog row |
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.
| 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.
- Implement the
IReport(withGetDatasetAsync) in Reporting. - Add the seeded Manager catalog row with its governance metadata — Category, RequiredFeatureKey, ManagerOnly, SupportsPdf, SortOrder — to the DBInitializer upsert list.
- Add the portal
reportListandreportDescriptionsi18n keys, in bothen.jsonandes.json. - Add a filter strategy in the portal for the report's parameters.
- Add resx keys for every VM property name that becomes a column header.
Platform
- Architecture
- Technology
- Inter-Service Communication
- Database
- Security and Identity
- User Permissions Overview
Services
- Manager
- Telemetry
- Router
- Adding a Provider
- Geofencing
- Trip Management
- Reporting
- Common Library
- Frontend
Engineering
User docs
- User Guide (ships in the app)