To Be Invoiced jobs with no agreements still look report-gated on the work order

Objective

  • Stop CSRs from thinking invoice-terms jobs need a manual report “unlock” when clients should already have access.
  • Make the work order Reports panel reflect computed client access (invoice terms, agreements, payment)—not only whether gating is enabled on the inspection.
  • Reduce unnecessary lockReport: false overrides and confusion when activity shows no one manually locked reports.

Background

  • Product feedback from invoice-terms builder jobs (e.g. DW Homes NHF): work order shows To Be Invoiced, Agreements section is empty (no active or archived agreements), but the Reports panel still looks gated and CSRs manually disable gating to “unlock.”
  • Example job referenced in investigation: CHI730.
  • Activity feed shows no user who locked reports—expected for default gating, but misleading for staff who expect an audit trail when access looks blocked.
  • Backend behavior today: when toBeInvoiced === true and there are no active agreements in the Agreement collection, checkReportAccess returns unlocked even if lockReport is still true (see integration tests in lockReport.test.ts).
  • Work order UI today: the Reports switch reflects inspection.lockReport !== false and label copy “Requires Payment & Agreement” (reportGateCopy.ts)—which does not change for invoice-terms jobs and can read as “locked” while clients may already be allowed.
  • toBeInvoiced is set at Attik job creation when a contact has invoiceApproved and a role with portal pay permission (createInspection.ts), or toggled later via Allow Invoice Terms on Services & Payments (ServicesPayments.tsx).

Scope

Backend

  • attik-backend/src/util/functions/inspection/checkReportAccess.ts — source of truth for client report access: lockReport === false bypasses all rules; otherwise unlock when toBeInvoiced and no active agreements (or agreements signed); payment ignored when toBeInvoiced.
  • attik-backend/src/models/inspectionSchema.tslockReport (default true), toBeInvoiced, synced agreement.present / agreement.signed.
  • attik-backend/src/routes/reports.ts — client portal report fetch uses checkReportAccess (403 when locked).
  • attik-backend/src/routes/inspection.ts — PATCH supports lockReport and toBeInvoiced.
  • attik-backend/src/util/functions/agreements/agreementLockSync.ts — agreement present/signed math (stale rows, archived excluded).
  • attik-backend/tests/integration/lockReport.test.tstoBeInvoiced + no agreements → unlocked.

Frontend

  • attik-frontend/src/app/tools/inspections/[id]/components/reports/Reports.tsx — Reports switch PATCHes lockReport; reportGatingEnabled = inspection?.lockReport !== false (does not use computed access).
  • attik-frontend/src/util/functions/report/reportGateCopy.ts — switch labels/toasts always payment + agreement wording.
  • attik-frontend/src/app/tools/inspections/[id]/components/ServicesPayments.tsxTo Be Invoiced chip and Allow Invoice Terms / Disable Invoice Terms toggle.
  • attik-frontend/src/app/client/job/[slug]/components/AttikReportList.tsx and ReportList.tsx — client portal lock UI from toBeInvoiced, payment, and agreements; falls back to inspection.agreement when agreement list is empty (align with backend DB query behavior).
  • attik-frontend/src/util/functions/report/computeAgreementSignedForReportLock.ts — portal agreement lock math (keep aligned with backend).
  • attik-frontend/src/app/tools/inspections/[id]/components/Agreements.tsx — empty state when no agreements on inspection.

Product / decisions for implementer

  • Decision needed: Should the work order switch show computed client access state, a separate “clients can access” indicator, or auto-relax display when toBeInvoiced && no agreements?
  • Decision needed: Should copy distinguish invoice-terms gating (agreement-only) from standard gating (payment + agreement)?
  • Decision needed: Whether to log or surface why gating would block clients (unsigned agreement, unpaid, invoice terms) without implying a user manually locked reports.
  • Out of scope unless repro confirms portal block: Agreement templates on other services on the same job (CHI730 was confirmed empty in Agreements UI).

Investigation outcomes (acceptance)

  • [ ] Work order clearly communicates client report access for To Be Invoiced + zero agreements without requiring CSR to set lockReport: false.
  • [ ] Labels/copy on Reports panel reflect invoice-terms vs standard payment gating where applicable.
  • [ ] Client portal and backend checkReportAccess stay aligned for invoice-terms jobs with empty agreements.
  • [ ] Repro case CHI730 (or equivalent) documented: before/after behavior for CSR workflow.
  • [ ] No regression for jobs that should remain gated (unsigned agreements, unpaid non-invoice jobs).

References

  • attik-backend/src/util/functions/inspection/checkReportAccess.ts
  • attik-backend/tests/integration/lockReport.test.ts
  • attik-frontend/src/app/tools/inspections/[id]/components/reports/Reports.tsx
  • attik-frontend/src/util/functions/report/reportGateCopy.ts
  • attik-frontend/src/app/tools/inspections/[id]/components/ServicesPayments.tsx
  • attik-frontend/src/app/client/job/[slug]/components/AttikReportList.tsx

Please authenticate to join the conversation.

Upvoters
Status

Canceled

Board
🏠

Main App

Date

1 day ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.