Wide service fee columns in Reports Hub (All Service Fee Breakdown)

Objective

  • Ship wide service fee columns in Reports Hub so finance can see one column per active catalog service on each inspection row — charge amount or $0 — without pivoting charges in Excel.
  • Users opt in via a single “All Service Fee Breakdown” control when charges are linked on an Inspections-base report, then save and re-run that report like any other custom export.

Background

  • Andy and Erin need job-level revenue visibility: which services were charged on each job and for how much. Today, Line items (charges base + linked inspections) exports one row per charge — not one row per job with service-named columns.
  • Wide service columns do not exist today. Reports Hub has aggregation pivot / addOnServiceName groupBy for upsell-by-ancillary reports, but not dynamic flat-export columns keyed by catalog service.
  • Related fields already available (not part of this ticket): finance can add baseFee, addOnTotal, address, datetime, etc. from the existing inspections column picker (exportFieldDefinitions.ts, documentResolution.ts). Value aggregations on baseFee / addOnTotal already work via the standard aggregation UI when configured.
  • Epic context: Child of Reports Hub update for Finance (ATT-1862). Identifying columns from siblings remain optional add-ons in the builder.
  • No prebuilt report for v1. Users assemble the finance view manually and save it.

Locked product decisions (v1)

Wide service fee columns

  • Column set: All active services in the company catalog, ordered like the Services List settings page — business segments sorted by order, then services within each segment sorted by order (ServiceSettingsList.tsx; order on serviceSchema.ts and business segments). Exclude inactive/deactivated services (active: false).
  • Scope: Include all active catalog services in that order (primary and add-on). No separate add-on-only subset.
  • Stability: Column headers do not change when filters or date range change. They only change when services are added, removed, reordered, renamed, or activated/deactivated on the Services List page.
  • Multiple charges for same service on one job: Sum all charge amounts for that service into the single column for that service.
  • Duplicate display names: Services with the same name remain distinct columns (keyed by service id internally). Column order follows Services List so category context disambiguates. Optional enhancement (not required for v1): append category abbreviation in brackets when names collide, e.g. Termite (CI).
  • Max columns: No maximum in preview or export — full active-catalog width is acceptable.

Charge amount source

  • Use charge amount summed per _serviceId on the job. Wide columns reflect what was charged; they do not recalculate base vs add-on logic (originalBasePrice ?? amount on primary remains on existing baseFee field).

Builder UX

  • Opt-in via a single “All Service Fee Breakdown” option in the charges collection (linked from inspections). Selecting it adds the full set of wide service fee columns for the company’s active catalog — users do not pick individual service columns one by one.

Done when

  • On an Inspections-base report with charges linked, a user can enable All Service Fee Breakdown and:
  • See one column per active catalog service on each job row, Services List order, with $0 where the job has no charge for that service.
  • See wide columns in preview (horizontal scroll; no column cap).
  • Export matches preview for wide columns.
  • Save and re-run the report with wide columns persisted in the report config.

Scope

Backend

  • Wide service fee columns (new behavior): extend flat export in joinedReport.ts and/or runDataExportJob.ts to emit dynamic columns keyed by catalog service id (header = service display name), ordered per company Services List. Load column set from active company services only — not from distinct service names in the filtered result set.
  • Sum charge amount per _serviceId when multiple charges match the same service on one job; resolve display name via _serviceId / catalogName (chargeFields.catalogName in exportFieldDefinitions.ts).
  • Expose All Service Fee Breakdown in export/report config so saved reports persist the opt-in (exact config shape: decision left to implementer).

Frontend

  • Report builder — All Service Fee Breakdown opt-in under linked charges on inspections-base reports (CreateReportForm.tsx, column-picker components).
  • ReportPreviewSection.tsx — render dynamic wide columns; horizontal scroll; no column cap.
  • Export run path — wide columns included when config has breakdown enabled.
  • Services List order reference: attik-frontend/src/app/tools/settings/services/ServiceSettingsList.tsx.

Out of scope

  • Job-level add-on names computed field (delimited list) — wide columns supersede for finance; open a follow-up only if a compact text column is still wanted.
  • baseFee / addOnTotal / addOnCount — already exportable; not modified by this ticket.
  • Value aggregations on baseFee / addOnTotal or per-wide-column totals — existing aggregation UI; not part of this ticket.
  • New prebuilt in prebuiltReports.ts
  • Global category columns: ATT-1857
  • Convenience / PAC fees: ATT-1859
  • Client name, county, full address: ATT-1858
  • Business segments / linking: ATT-1861
  • Split date/time columns: ATT-1863

References

  • Parent epic: Reports Hub update for Finance
  • Charge rollup (existing base/add-on fields): attik-backend/src/util/functions/dataExports/documentResolution.ts
  • Field defs: attik-backend/src/config/exportFieldDefinitions.ts
  • Report builder: attik-frontend/src/app/tools/data-exports/CreateReportForm.tsx
  • Services List ordering: attik-frontend/src/app/tools/settings/services/ServiceSettingsList.tsx

Diagram

flowchart LR
  subgraph catalog [Active company catalog]
    BL[Services List order\nsegment.order → service.order]
    S1[Service A]
    S2[Service B]
    S3[Service C]
    BL --> S1
    BL --> S2
    BL --> S3
  end

  subgraph job [Inspection job charges]
    AC1[Charge Service A]
    AC2[Charge Service A duplicate]
    AC3[Charge Service B]
  end

  subgraph export [Wide export row same job]
    WA[Service A column\nsum amounts]
    WB[Service B column]
    WC[Service C column\n$0 if none]
  end

  AC1 --> WA
  AC2 --> WA
  AC3 --> WB
  S1 -. column header .-> WA
  S2 -. column header .-> WB
  S3 -. column header .-> WC

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

3 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.