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
This commit is contained in:
167
fusion_accounting/PHASE_2_PLAN.md
Normal file
167
fusion_accounting/PHASE_2_PLAN.md
Normal file
@@ -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.
|
||||||
0
fusion_accounting_reports/__init__.py
Normal file
0
fusion_accounting_reports/__init__.py
Normal file
43
fusion_accounting_reports/__manifest__.py
Normal file
43
fusion_accounting_reports/__manifest__.py
Normal file
@@ -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',
|
||||||
|
}
|
||||||
0
fusion_accounting_reports/controllers/__init__.py
Normal file
0
fusion_accounting_reports/controllers/__init__.py
Normal file
0
fusion_accounting_reports/models/__init__.py
Normal file
0
fusion_accounting_reports/models/__init__.py
Normal file
0
fusion_accounting_reports/reports/__init__.py
Normal file
0
fusion_accounting_reports/reports/__init__.py
Normal file
1
fusion_accounting_reports/security/ir.model.access.csv
Normal file
1
fusion_accounting_reports/security/ir.model.access.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
0
fusion_accounting_reports/services/__init__.py
Normal file
0
fusion_accounting_reports/services/__init__.py
Normal file
BIN
fusion_accounting_reports/static/description/icon.png
Normal file
BIN
fusion_accounting_reports/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
0
fusion_accounting_reports/tests/__init__.py
Normal file
0
fusion_accounting_reports/tests/__init__.py
Normal file
0
fusion_accounting_reports/wizards/__init__.py
Normal file
0
fusion_accounting_reports/wizards/__init__.py
Normal file
Reference in New Issue
Block a user