Reports & Publishing
This article covers two related concerns:- Publishing an inspection report — the workflow that takes a finalized inspection from internal review to client delivery
- The Reports module — the business-intelligence reporting surface at
/reports(Monthly Reconciliation, Outstanding A/R, Service Mix, Agent Referral, Inspector Productivity, Activity Log, Tax Summary)
Publishing an inspection report
What “publish” actually does
Clicking Publish in the Inspection Reviewer is one click that triggers a sequence:- Server-side PDF rendering — your template, branding, narratives, photos, ratings, SPOs, summary, and cover photo are composed into a single PDF by the backend’s PDF pipeline (using
pdf-poppler,pdfkit, Handlebars) - Upload to Google Cloud Storage — the PDF lands in your tenant’s GCS bucket at a deterministic path
reportStatus = 'published'is written to the inspection in Firestorereport.publishedworkflow trigger fires — every workflow step you’ve wired to that trigger in Comms Cockpit executes- Versioning — the report version increments. Previous versions remain in GCS for audit. The Reports tab on Inspection Details shows the version history.
Pre-flight checks before publish
The Reviewer surfaces warnings if the inspection isn’t ready:
Each warning is a soft block — you can publish anyway, but the report quality suffers.
What clients see after publish
Thereport.published trigger fires whatever workflow steps you’ve configured. The canonical setup is two steps:
See Communications → Report Delivery for the rationale for splitting these.
The Client Portal view
Client recipients click$ReportLink and land on the Client Portal (/client-portal/:portalSlug). From there they can:
- Download the PDF
- View the inspection summary
- Access the Repair Request Builder to mark deficiencies they want resolved before closing
- See payment options (if balance is outstanding)
- Sign any post-inspection documents
The Realtor Portal view
Agents land at/portal/:tenantSlug after clicking $AgentReportLink. The view:
- Summary-only — does not include pricing, repair request, or full inspector contact
- Magic-link authenticated — no account creation required
- 90-day expiration on the link
- Branded with your company logo
Re-publishing after edits
You can edit a published inspection and re-publish — every Publish action increments the version. Behaviors:- The new version becomes canonical for
$ReportLinkand$AgentReportLink - Previous versions remain in GCS and accessible from the Reports tab on Inspection Details
- A
report.publishedtrigger fires again — your workflow re-sends the delivery emails (set conditional rules in Comms Cockpit if you only want the first publish to email) - The History tab logs each republish event
Operationally, most teams set the report-delivery workflow steps to conditional on first publish only (e.g. previousReportStatus != 'published') so re-publishes don’t re-spam the client.
The Reports module — business intelligence
The Reports module lives at/reports (the Reports item in the sidebar). It’s a separate workspace from the per-inspection report workflow above — it produces business analytics reports about your inspection business.
[SCREENSHOT: reports-module.png — desktop, the Reports module showing a card grid of available reports: Monthly Reconciliation, Outstanding A/R, Service Mix, Agent Referral, Inspector Productivity, Activity Log, Tax Summary.]
The 7 standard reports
Common controls
Every report shares the same control row:Monthly Reconciliation — the most-used report
The Monthly Reconciliation report shows, for each order in the selected period:
A footer row totals all columns. Below the table, four summary stat cards:
By Order vs By Payout
A toggle (By order / By payout) changes the view:- By Order — one row per order (default). Match individual orders to fees.
- By Payout — one row per Stripe payout (= one bank deposit). Each row expandable to the constituent orders. This view matches your bank statement line items directly.
Outstanding A/R — collections workflow
Lists every order withpaymentStatus IN ['pending', 'partial'] AND a completed inspection. Bucketed by aging:
Click an order to drill into Inspection Details. From there, manually record a payment or trigger a payment-request email.
Service Mix — pricing optimization
A pivot overorders.services[]:
Sort by revenue or count. Useful for identifying which ancillaries pull in the most revenue per attach.
Agent Referral — relationship management
Pivot overorders.referringAgentId:
Sort by revenue to see your top agents. Sort by Last referred ascending to find dormant agents who might be cultivated.
Inspector Productivity — team management
For multi-inspector firms only. Pivot overorders.assignedInspectorId:
Activity Log — audit trail
Chronological list of everyworkflowEvents entry for the period. Useful for dispute resolution (“when did we send the contract?”) and audit (“who modified this order?”).
Tax Summary — year-end
Aggregates annual revenue byservice.taxCategory. The categories are configurable per service in Pricing Manager. Useful inputs for 1099 generation and end-of-year tax prep.
Recurring email subscription
Click Email monthly on any report. A small dialog asks for:- Recipient(s) — default to the signed-in user, multi-select your team
- Frequency — Monthly (1st of month) / Quarterly / Annual
Errors and recovery
Publish errors
Reports module errors
What this page does NOT do
- It does not edit individual reports. That’s Inspection Reviewer.
- It does not generate the BI dashboard. That’s the Dashboard (
/). - It does not handle agent communications. That’s Comms Cockpit for templates, Inspection Details → Communications for per-order messaging.
- It does not compute payroll or other internal HR metrics.
Related articles
- Generate Your First Report — onboarding walkthrough for publishing
- Inspection Reviewer — where Publish lives
- Communications — what fires on
report.published - Web Admin Overview — sidebar context for the Reports tab
- BI Dashboard Architecture — the data model behind the Reports module (designed in a parallel project)