diff --git a/fusion_accounting/PHASE_2_PLAN.md b/fusion_accounting/PHASE_2_PLAN.md new file mode 100644 index 00000000..41529d9f --- /dev/null +++ b/fusion_accounting/PHASE_2_PLAN.md @@ -0,0 +1,167 @@ +# 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) +3. `services/date_periods.py` (fiscal periods, comparison derivation) +4. `services/currency_conversion.py` + `services/account_hierarchy.py` + `services/totaling.py` +5. `models/fusion_report.py` (report definition model) +6. `services/line_resolver.py` (compute report rows from definition) +7. `services/drill_down_resolver.py` +8. `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) +9. P&L (income statement) +10. Balance sheet +11. Trial balance +12. General ledger + +### Group 4: AI features (tasks 13-17) +13. Anomaly detection service (variance vs prior period) +14. AI commentary service +15. Commentary prompt + LLMProvider integration +16. `fusion.report.commentary` persisted model +17. `fusion.report.anomaly` persisted model + +### Group 5: Backend wiring (tasks 18-20) +18. JSON-RPC controller (8 endpoints) +19. ReportsAdapter `_via_fusion` paths +20. 5 new AI tools + +### Group 6: Tests + perf (tasks 21-25) +21. Property-based tests (totals balance invariant) +22. Integration tests — P&L correctness vs known fixtures +23. Integration tests — balance sheet + trial balance +24. Materialized view for GL +25. Cron jobs (anomaly scan + commentary refresh) + +### Group 7: Frontend (tasks 26-33) +26. SCSS tokens + main report stylesheet +27. `reports_service.js` +28. `report_viewer` component (top-level) +29. `report_table` component (rows, totals, drill chevrons) +30. `drill_down_dialog` +31. `period_filter` (date range + comparison toggle) +32. `ai_commentary_panel` (Fusion-only) +33. `anomaly_strip` (Fusion-only) + +### Group 8: Export + wizards (tasks 34-36) +34. PDF export (QWeb template per report) +35. XLSX export wizard +36. Period selection + comparison wizard + +### Group 9: Migration + coexistence (tasks 37-39) +37. Migration wizard inheritance (cache existing definitions) +38. Menu + window actions with coexistence group filter +39. Coexistence test + +### Group 10: Final tests + polish (tasks 40-46) +40. 5 OWL tour tests +41. Performance benchmarks +42. Optimize if benchmarks fail (conditional) +43. Local LLM compat test for commentary +44. Update meta-module manifest +45. CLAUDE.md, UPGRADE_NOTES.md, README.md +46. 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. diff --git a/fusion_accounting_reports/__init__.py b/fusion_accounting_reports/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/__manifest__.py b/fusion_accounting_reports/__manifest__.py new file mode 100644 index 00000000..64ef0424 --- /dev/null +++ b/fusion_accounting_reports/__manifest__.py @@ -0,0 +1,43 @@ +{ + 'name': 'Fusion Accounting Reports', + 'version': '19.0.1.0.0', + 'category': 'Accounting/Accounting', + 'summary': 'AI-augmented financial reports (P&L, balance sheet, trial balance, GL).', + 'description': """ +Fusion Accounting Reports +========================= + +A Fusion-native replacement for Odoo Enterprise's account_reports module. + +CORE scope (Phase 2): +- Income Statement (P&L) +- Balance Sheet +- Trial Balance +- General Ledger (with drill-down) + +AI augmentation: +- Anomaly detection (variance vs prior period) +- AI commentary (LLM-generated narrative) + +Coexists with Enterprise: when account_reports is installed, the Fusion +menu hides; the engine and AI tools remain available for the chat. +""", + 'author': 'Fusion Accounting', + 'license': 'LGPL-3', + 'depends': [ + 'fusion_accounting_core', + 'fusion_accounting_ai', + 'account', + ], + 'data': [ + 'security/ir.model.access.csv', + ], + 'assets': { + 'web.assets_backend': [ + ], + }, + 'installable': True, + 'auto_install': False, + 'application': False, + 'icon': '/fusion_accounting_reports/static/description/icon.png', +} diff --git a/fusion_accounting_reports/controllers/__init__.py b/fusion_accounting_reports/controllers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/models/__init__.py b/fusion_accounting_reports/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/reports/__init__.py b/fusion_accounting_reports/reports/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/security/ir.model.access.csv b/fusion_accounting_reports/security/ir.model.access.csv new file mode 100644 index 00000000..97dd8b91 --- /dev/null +++ b/fusion_accounting_reports/security/ir.model.access.csv @@ -0,0 +1 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink diff --git a/fusion_accounting_reports/services/__init__.py b/fusion_accounting_reports/services/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/static/description/icon.png b/fusion_accounting_reports/static/description/icon.png new file mode 100644 index 00000000..6773c627 Binary files /dev/null and b/fusion_accounting_reports/static/description/icon.png differ diff --git a/fusion_accounting_reports/tests/__init__.py b/fusion_accounting_reports/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fusion_accounting_reports/wizards/__init__.py b/fusion_accounting_reports/wizards/__init__.py new file mode 100644 index 00000000..e69de29b