J-17 — Run Monthly Tax Report
One-liner: Finance generates a monthly tax report tied to immutable settlements; downloads PDF/CSV; submits to tax authority.
1. Purpose
Finance generates a monthly tax report (per tenant + per property) tied to immutable settlements; downloads PDF / CSV; submits to the tax authority where applicable. Outcome: a sealed report that reconciles to the ledger and is submission-ready.
2. Persona Context
- Persona: Finance.
- Surface: Electron Desktop.
- Primary BFF:
bff-backoffice-service. - Backing services:
reporting-service,payments-service,audit-service. - Preconditions: Month is closed (no open folios for the period).
- Trigger: Finance opens Reports -> Tax and selects month.
3. Entry Points
| # | Entry | Notes |
|---|---|---|
| 1 | Reports tab -> Tax | Default |
| 2 | Scheduled monthly notification | P2 |
4. Screen-by-Screen Flow
4.1 TaxReportPickerScreen
- Layout: Month / property selector; "Generate" CTA; existing reports list (sealed / draft).
- Components:
MonthSelect,PropertySelect,Button,ReportListTable. - Offline: Reads from SQLite; generation queued.
- AI: None.
- Errors: Open folios warning.
- Loading: Sub-200 ms.
- A11y: Field labels.
- RTL: Mirror.
- Perf: <= 200 ms.
- Telemetry:
frontend.tax.picker_viewed.
4.2 TaxReportPreviewScreen
- Layout: Per-tax-category breakdown, taxable revenue, exemptions, totals; PDF preview; "Download PDF" / "Download CSV" / "Submit (where applicable)" CTAs; "Seal" CTA.
- Components:
TaxBreakdownTable,PdfPreview,Button(variants). - Offline: Generation local; submission queued.
- AI: None.
- Errors: Reconciliation drift -> warning + drilldown.
- Loading: Generation <= 5 s.
- A11y: Table semantics; PDF preview accessible (alt text).
- RTL: Mirror.
- Perf: Generation <= 5 s; download instant.
- Telemetry:
frontend.tax.report_generated { month, property };frontend.tax.sealed.
5. State Machine
6. Data Requirements
6.1 Server state
POST /api/v1/reports/tax(idempotent; returns reportId)GET /api/v1/reports/tax/:idPOST /api/v1/reports/tax/:id/seal(idempotent)POST /api/v1/reports/tax/:id/submit(idempotent; where authority integration exists)
6.2 Local persistence
- SQLite
tax_reports_local,outbox.
6.3 Idempotency
- All mutations carry
X-Idempotency-Key.
7. AI Behavior
n/a.
8. Offline Behavior
- Generation from SQLite ledger snapshot.
- Submission queued.
9. Error States
| Error | Trigger | UX shown | Recovery | Telemetry |
|---|---|---|---|---|
OPEN_FOLIOS_FOR_PERIOD | Open folios | Warning with link to resolve | User resolves | frontend.tax.open_folios |
RECONCILIATION_DRIFT | Drift detected | Warning + drilldown | User reviews | frontend.tax.recon_drift |
AUTHORITY_SUBMISSION_FAILED | Submission 5xx | Banner with retry | Retry | error.surfaced { code } |
10. E2E Test Gates
- Composite gate
G-FIN-1: pick month -> generate -> preview -> download PDF/CSV -> seal -> (submit). - Reconciliation drift detection.
11. Performance Requirements
| Metric | Target |
|---|---|
| Picker mount | <= 200 ms |
| Generation | <= 5 s p95 |
| Seal | <= 1 s p95 |
12. Accessibility Requirements
- All keyboard-completable.
- PDF preview has accessible fallback.
13. Telemetry
Frontend events
frontend.tax.picker_viewedfrontend.tax.report_generated { month, property }frontend.tax.sealed
Domain events emitted
melmastoon.reporting.tax.generated.v1melmastoon.reporting.tax.sealed.v1melmastoon.audit.recorded.v1
14. Success Criteria
- Report reconciles to ledger (zero drift).
- Sealed report has cryptographic hash; downloadable.
- Submission path proven where authority integration exists.