feat(fusion_accounting_assets): Phase 3 skeleton + plan

50-task plan to replace Enterprise account_asset module:
- CORE scope: 3 depreciation methods (straight-line, declining-balance, units-of-production)
- HYBRID engine: shared primitives + persisted asset/category/disposal/anomaly models
- AI augmentation: utilization anomaly detection + LLM-suggested useful life
- Full lifecycle: draft -> running -> paused -> disposed
- Coexists with Enterprise (group_fusion_show_when_enterprise_absent)
- Same V19 conventions + test pyramid + perf-budget discipline as Phases 1-2

Skeleton: empty manifest + dirs + icon. Tasks 3-50 add the substance.
Made-with: Cursor
This commit is contained in:
gsinghpal
2026-04-19 16:43:06 -04:00
parent fdfaf7e779
commit 99b6990dd6
11 changed files with 210 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
# Phase 3 — Fusion Accounting Assets Implementation Plan
**Module:** `fusion_accounting_assets`
**Branch:** `fusion_accounting/phase-3-assets`
**Pre-phase tag:** `fusion_accounting/pre-phase-3`
**Estimated tasks:** ~50
**Reference:** `/Users/gurpreet/Github/RePackaged-Odoo/accounting/account_asset/` (~2258 LOC Python)
## Goal
Replace Odoo Enterprise's `account_asset` module — asset management with depreciation schedules, disposal, partial sale, and reporting. CORE scope: 3 depreciation methods (straight-line, declining balance, units of production), full asset lifecycle, depreciation board, disposal/sale wizards. AI augmentation: utilization anomaly detection + AI-suggested useful life from invoice context. Coexists with Enterprise.
## Architecture (HYBRID engine, Phase 1+2 pattern)
```
fusion.asset.engine (AbstractModel) ← shared primitives
├── compute_depreciation_schedule(asset, recompute=False)
├── post_depreciation_entry(asset, period)
├── dispose_asset(asset, *, sale_amount, sale_date, sale_partner=None)
├── partial_sale(asset, *, sold_amount, sold_qty, sale_date)
├── pause_asset(asset, pause_date)
├── resume_asset(asset, resume_date)
└── reverse_disposal(asset)
services/ ← pure-Python
├── depreciation_methods.py → straight_line, declining_balance, units_of_production
├── prorate.py → first/last period prorating (calendar/365/etc.)
├── salvage_value.py → end-of-life value math
├── anomaly_detection.py → utilization variance vs expected
├── useful_life_predictor.py → LLM-suggested useful life from invoice description
└── useful_life_prompt.py → provider-agnostic LLM prompt
models/
├── fusion_asset.py → main fusion.asset model
├── fusion_asset_depreciation_line.py → depreciation board lines
├── fusion_asset_category.py → categories with default settings
├── fusion_asset_disposal.py → disposal records
├── fusion_asset_anomaly.py → flagged utilization issues
├── fusion_asset_engine.py → AbstractModel orchestrator
└── account_move.py → inherit (link to asset, generate from invoice)
controllers/assets_controller.py ← 8 JSON-RPC endpoints
├── /fusion/assets/list → paginated asset list with filters
├── /fusion/assets/get_detail → single asset with full schedule
├── /fusion/assets/compute_schedule → recompute depreciation board
├── /fusion/assets/post_depreciation → run periodic depreciation cron
├── /fusion/assets/dispose → dispose an asset
├── /fusion/assets/get_anomalies → list flagged variances
├── /fusion/assets/suggest_useful_life → AI suggest useful life
└── /fusion/assets/get_partner_history → asset-related partner history
static/src/
├── scss/ ← asset-specific design tokens
├── services/assets_service.js ← reactive state + RPC wrappers
├── views/asset_dashboard/ ← top-level OWL controller
└── components/ ← asset_card, depreciation_board, disposal_dialog,
ai_useful_life_panel, anomaly_strip
```
## Coexistence
`group_fusion_show_when_enterprise_absent` from `fusion_accounting_core`. Asset menu only visible when `account_asset` NOT installed. Engine + AI tools always available.
## Tasks (50 total)
### Group 1: Foundation (1-2)
1. Safety net (DONE)
2. Plan doc + module skeleton
### Group 2: Pure-Python services TDD (3-7)
3. `services/depreciation_methods.py` — straight_line + declining_balance + units_of_production (TDD)
4. `services/prorate.py` — first/last period prorating
5. `services/salvage_value.py` — end-of-life math
6. `services/anomaly_detection.py` — utilization variance
7. `services/useful_life_predictor.py` + `useful_life_prompt.py` — LLM integration
### Group 3: Persisted models (8-13)
8. `models/fusion_asset.py` — main asset model with state machine
9. `models/fusion_asset_depreciation_line.py` — depreciation board lines
10. `models/fusion_asset_category.py` — categories with defaults
11. `models/fusion_asset_disposal.py` — disposal records
12. `models/fusion_asset_anomaly.py` — flagged anomalies
13. `models/account_move.py` (inherit) — link asset to invoice
### Group 4: Engine (14-15)
14. `models/fusion_asset_engine.py` — 7-method API
15. Engine integration tests (compute_schedule + post_depreciation + dispose end-to-end)
### Group 5: Backend wiring (16-19)
16. JSON-RPC controller (8 endpoints)
17. AssetsAdapter wiring `_via_fusion` paths
18. 5 new AI tools
19. Cron — daily depreciation post + monthly anomaly scan
### Group 6: Tests + perf (20-23)
20. Property-based tests (Hypothesis: schedule sums == cost - salvage)
21. Integration tests — straight-line + declining-balance + units-of-production
22. Materialized view for asset book values (perf)
23. Performance benchmarks
### Group 7: Frontend OWL (24-31)
24. SCSS tokens + main asset stylesheet (light + dark)
25. `assets_service.js` (reactive state + RPC wrappers)
26. `asset_dashboard` (top-level kanban + summary)
27. `asset_card` (one asset summary card)
28. `asset_detail_panel` (right-side: schedule, history, AI suggestions)
29. `depreciation_board` (table view of schedule with edit chevrons)
30. `disposal_dialog` (sale/scrap wizard)
31. Fusion-only: `ai_useful_life_panel` + `anomaly_strip`
### Group 8: Wizards (32-35)
32. Asset creation wizard (from invoice line)
33. Disposal wizard (sale, scrap, donation)
34. Partial sale wizard
35. Period picker for depreciation runs
### Group 9: Migration + coexistence (36-39)
36. Migration wizard inheritance — backfill from account.asset rows
37. Audit report PDF (per-company asset count, total NBV, etc.)
38. Menu + window action with coexistence group filter
39. Coexistence test
### Group 10: Final tests + polish (40-50)
40. 5 OWL tour tests
41. Performance benchmarks (P95: schedule compute < 500ms, board render < 200ms)
42. Optimize if benchmarks fail (conditional)
43. Local LLM compat test for useful_life_predictor
44. Update meta-module manifest
45. CLAUDE.md, UPGRADE_NOTES.md, README.md
46. End-to-end smoke + tag phase-3-complete + push
47-50. Reserved for inherited features: account_move integration, draft journal entries, post-on-confirm flow, fiscal-year-aware proration
## Performance Targets (P95)
- `compute_schedule` (10-year asset): <500ms
- `post_depreciation_entry`: <200ms
- `dispose_asset`: <300ms
- Controller `list`: <300ms
- Controller `get_detail`: <500ms
## V19 Conventions (carried from Phase 1+2)
- `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`
- `models.Constraint` for unique-keys
- `env.flush_all()` before MV REFRESH
- REFRESH MATERIALIZED VIEW CONCURRENTLY needs autocommit cursor
## Test Targets
Match Phase 1+2 test pyramid:
- Unit (pure-Python services)
- Integration (engine end-to-end)
- Property-based (Hypothesis: schedule total invariants)
- Controller (HttpCase JSON-RPC)
- MV correctness
- Performance benchmarks (tagged 'benchmark')
- OWL tours (tagged 'tour')
- Local LLM smoke (tagged 'local_llm')
Phase 1+2 final: 287 tests. Phase 3 target: ~140-180 additional → ~430-470 total.