Blog

Reports and exports: what the server builds when you download or print

Starting from filters you choose

When you generate a report in the app, you usually pick a location (or all locations), a start date, and an end date. Those choices become parameters on the server. The backend then asks the database for violations that belong to your organization and fall inside that window — and, if you selected a site, only rows linked to that location.

The printable “PDF” report (HTML first)

For many teams, the workflow is: open a printable HTML report in the browser, then use Print → Save as PDF. The server assembles an HTML document with headings, tables, and the violation details it already stores (codes, descriptions, statuses, image links where available). The PDF is created by your browser’s print engine, which keeps the stack simpler and avoids running a separate PDF server for every deployment.

CSV: rows your spreadsheet can chew on

CSV export returns one row per violation (or a full-org export, depending on the endpoint) with columns that match what you need for analysis: identifiers, text fields, dates, and pipe-separated image URLs so multiple photos do not break the comma structure. That format is deliberate: spreadsheets and BI tools can import a single file without custom parsers for nested images.

Location summary tables

The reports area can also show a per-location summary: how many inspections, how many open violations, how many cleared. Those numbers come from aggregating the same underlying tables — counts grouped by location ID — so what you see on the dashboard and what you export stay aligned.

API routes vs. form actions

Some exports are triggered by GET requests to API routes (for example generating a file download). Other workflows in this codebase use form actions for uploads because that pattern behaves reliably on Cloudflare Workers. The important part for readers: whether the response is HTML or a file, the server is still reading only your organization’s data using the same session and membership checks as the rest of the app.

What this means for you

Reporting is not a black box: it is the same structured data you enter through inspections and violations, filtered and rendered. If a number looks wrong, the place to verify is usually the underlying rows (dates, location link, status) rather than “the report math” inventing new facts.