46-task plan to replace Enterprise account_reports module: - CORE scope: P&L, balance sheet, trial balance, GL with drill-down - HYBRID engine: shared primitives + per-report models - AI augmentation: anomaly detection + LLM-generated commentary - Coexists with Enterprise (group_fusion_show_when_enterprise_absent) - Same V19 conventions + test pyramid + perf-budget discipline as Phase 1 Skeleton: empty manifest + dirs + icon. Tasks 3-46 add the substance. Made-with: Cursor
7.0 KiB
Phase 2 — Fusion Accounting Reports Implementation Plan
Module: fusion_accounting_reports
Branch: fusion_accounting/phase-2-reports
Pre-phase tag: fusion_accounting/pre-phase-2
Estimated tasks: 46
Reference: /Users/gurpreet/Github/RePackaged-Odoo/accounting/account_reports/
Goal
Replace Odoo Enterprise's account_reports module with a Fusion-native financial reports engine. CORE scope: P&L (income statement), balance sheet, trial balance, general ledger with drill-down. AI augmentation: anomaly detection (variance vs prior period) + AI-generated commentary. Coexists with Enterprise (Enterprise wins by default; Fusion menu shows when Enterprise absent).
Architecture (HYBRID engine)
fusion.report.engine (AbstractModel) ← shared primitives
├── compute_pnl(period, comparison=None)
├── compute_balance_sheet(date_to, comparison=None)
├── compute_trial_balance(period)
├── compute_gl(period, account_ids=None)
├── drill_down(report_type, line_id, period)
└── _walk_account_hierarchy(root_account_ids)
services/ ← pure-Python
├── date_periods.py → fiscal-period math, comparison-period derivation
├── account_hierarchy.py → recursive account tree walk + roll-ups
├── totaling.py → balance/credit/debit aggregation rules
├── currency_conversion.py → multi-currency revaluation at report date
├── anomaly_detection.py → variance vs prior-period statistical flags
└── commentary_generator.py → LLM prompt + parse for narrative
models/
├── fusion_report.py → report definition (metadata, line specs)
├── fusion_report_engine.py → AbstractModel orchestrator
├── fusion_report_pnl.py → P&L definition + execute
├── fusion_report_balance_sheet.py
├── fusion_report_trial_balance.py
├── fusion_report_general_ledger.py
├── fusion_report_anomaly.py → persisted flagged variances
├── fusion_report_commentary.py → cached AI narratives
└── fusion_unreconciled_gl_mv.py → MV for fast GL listing on large DBs
controllers/bank_rec_controller.py ← 8 JSON-RPC endpoints
├── /fusion/reports/run → execute one report
├── /fusion/reports/drill_down → drill into a report line
├── /fusion/reports/get_anomalies → list flagged variances
├── /fusion/reports/get_commentary → fetch / regenerate narrative
├── /fusion/reports/compare_periods → side-by-side comparison
├── /fusion/reports/export_pdf → PDF export
├── /fusion/reports/export_xlsx → XLSX export
└── /fusion/reports/list_available → list all report types
static/src/
├── scss/ ← report-specific design tokens
├── services/reports_service.js ← reactive state + RPC wrappers
├── views/reports_viewer/ ← top-level OWL controller
└── components/ ← report_table, drill_down_dialog,
period_filter, ai_commentary_panel,
anomaly_strip
Coexistence
Same pattern as Phase 1: group_fusion_show_when_enterprise_absent from fusion_accounting_core. Reports menu only visible when account_reports is NOT installed. Engine + AI tools always available.
Tasks (46 total)
Group 1: Foundation (tasks 1-2)
- Safety net (tag pre-phase-2, branch phase-2-reports) — DONE
- Plan doc + module skeleton
Group 2: Engine primitives — TDD layered (tasks 3-8)
services/date_periods.py(fiscal periods, comparison derivation)services/currency_conversion.py+services/account_hierarchy.py+services/totaling.pymodels/fusion_report.py(report definition model)services/line_resolver.py(compute report rows from definition)services/drill_down_resolver.pymodels/fusion_report_engine.py(5-method API: compute_pnl, compute_balance_sheet, compute_trial_balance, compute_gl, drill_down)
Group 3: Per-report models (tasks 9-12)
- P&L (income statement)
- Balance sheet
- Trial balance
- General ledger
Group 4: AI features (tasks 13-17)
- Anomaly detection service (variance vs prior period)
- AI commentary service
- Commentary prompt + LLMProvider integration
fusion.report.commentarypersisted modelfusion.report.anomalypersisted model
Group 5: Backend wiring (tasks 18-20)
- JSON-RPC controller (8 endpoints)
- ReportsAdapter
_via_fusionpaths - 5 new AI tools
Group 6: Tests + perf (tasks 21-25)
- Property-based tests (totals balance invariant)
- Integration tests — P&L correctness vs known fixtures
- Integration tests — balance sheet + trial balance
- Materialized view for GL
- Cron jobs (anomaly scan + commentary refresh)
Group 7: Frontend (tasks 26-33)
- SCSS tokens + main report stylesheet
reports_service.jsreport_viewercomponent (top-level)report_tablecomponent (rows, totals, drill chevrons)drill_down_dialogperiod_filter(date range + comparison toggle)ai_commentary_panel(Fusion-only)anomaly_strip(Fusion-only)
Group 8: Export + wizards (tasks 34-36)
- PDF export (QWeb template per report)
- XLSX export wizard
- Period selection + comparison wizard
Group 9: Migration + coexistence (tasks 37-39)
- Migration wizard inheritance (cache existing definitions)
- Menu + window actions with coexistence group filter
- Coexistence test
Group 10: Final tests + polish (tasks 40-46)
- 5 OWL tour tests
- Performance benchmarks
- Optimize if benchmarks fail (conditional)
- Local LLM compat test for commentary
- Update meta-module manifest
- CLAUDE.md, UPGRADE_NOTES.md, README.md
- End-to-end smoke + tag phase-2-complete + push
Performance Targets (P95)
engine.compute_pnl(1 year, 500 accounts): <2sengine.compute_balance_sheet: <2sengine.compute_trial_balance: <1sengine.compute_gl(1 month, all accounts): <3sengine.drill_down(1 line): <500ms- Controller
runendpoint: <2.5s
V19 Conventions (from Phase 1 lessons)
models.Constraintnot_sql_constraints- No
@api.depends('id')on stored compute fields @route(type='jsonrpc')nottype='json'ir.cronhas nonumbercallfieldres.groups.user_idsnotusersir.ui.menu.group_idsnotgroups_idres.users.all_group_idsfor searchesmodels.Constraintfor unique-keys- Prefer
env.flush_all()before MV REFRESH
Test Targets
Match Phase 1's test pyramid:
- Unit (services pure-Python)
- Integration (engine end-to-end with factories)
- Property-based (Hypothesis, totals balance invariant)
- Controller (HttpCase JSON-RPC)
- MV correctness
- Performance benchmarks (tagged 'benchmark')
- OWL tours (tagged 'tour')
- Local LLM smoke (tagged 'local_llm', skips when no LLM)
Phase 1 final: 157 tests passing. Phase 2 target: ~120-150 additional.