Files
Odoo-Modules/fusion_accounting/PHASE_2_PLAN.md
gsinghpal a93162cb70 feat(fusion_accounting_reports): Phase 2 skeleton + plan
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
2026-04-19 15:03:03 -04:00

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)

  1. Safety net (tag pre-phase-2, branch phase-2-reports) — DONE
  2. Plan doc + module skeleton

Group 2: Engine primitives — TDD layered (tasks 3-8)

  1. services/date_periods.py (fiscal periods, comparison derivation)
  2. services/currency_conversion.py + services/account_hierarchy.py + services/totaling.py
  3. models/fusion_report.py (report definition model)
  4. services/line_resolver.py (compute report rows from definition)
  5. services/drill_down_resolver.py
  6. models/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)

  1. P&L (income statement)
  2. Balance sheet
  3. Trial balance
  4. General ledger

Group 4: AI features (tasks 13-17)

  1. Anomaly detection service (variance vs prior period)
  2. AI commentary service
  3. Commentary prompt + LLMProvider integration
  4. fusion.report.commentary persisted model
  5. fusion.report.anomaly persisted model

Group 5: Backend wiring (tasks 18-20)

  1. JSON-RPC controller (8 endpoints)
  2. ReportsAdapter _via_fusion paths
  3. 5 new AI tools

Group 6: Tests + perf (tasks 21-25)

  1. Property-based tests (totals balance invariant)
  2. Integration tests — P&L correctness vs known fixtures
  3. Integration tests — balance sheet + trial balance
  4. Materialized view for GL
  5. Cron jobs (anomaly scan + commentary refresh)

Group 7: Frontend (tasks 26-33)

  1. SCSS tokens + main report stylesheet
  2. reports_service.js
  3. report_viewer component (top-level)
  4. report_table component (rows, totals, drill chevrons)
  5. drill_down_dialog
  6. period_filter (date range + comparison toggle)
  7. ai_commentary_panel (Fusion-only)
  8. anomaly_strip (Fusion-only)

Group 8: Export + wizards (tasks 34-36)

  1. PDF export (QWeb template per report)
  2. XLSX export wizard
  3. Period selection + comparison wizard

Group 9: Migration + coexistence (tasks 37-39)

  1. Migration wizard inheritance (cache existing definitions)
  2. Menu + window actions with coexistence group filter
  3. Coexistence test

Group 10: Final tests + polish (tasks 40-46)

  1. 5 OWL tour tests
  2. Performance benchmarks
  3. Optimize if benchmarks fail (conditional)
  4. Local LLM compat test for commentary
  5. Update meta-module manifest
  6. CLAUDE.md, UPGRADE_NOTES.md, README.md
  7. End-to-end smoke + tag phase-2-complete + push

Performance Targets (P95)

  • engine.compute_pnl (1 year, 500 accounts): <2s
  • engine.compute_balance_sheet: <2s
  • engine.compute_trial_balance: <1s
  • engine.compute_gl (1 month, all accounts): <3s
  • engine.drill_down (1 line): <500ms
  • Controller run endpoint: <2.5s

V19 Conventions (from Phase 1 lessons)

  • models.Constraint not _sql_constraints
  • No @api.depends('id') on stored compute fields
  • @route(type='jsonrpc') not type='json'
  • ir.cron has no numbercall field
  • res.groups.user_ids not users
  • ir.ui.menu.group_ids not groups_id
  • res.users.all_group_ids for searches
  • models.Constraint for 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.