Adds the brainstormed roadmap design that turns fusion_accounting from an AI-only extension into a full replacement for Odoo 19 Enterprise accounting (account_accountant, account_reports, accountant, account_followup, plus selected satellites) for Nexa client deployments. Covers: - Sub-module topology (9 modules + meta-module): _core, _bank_rec, _reports, _dashboard, _followup, _assets, _budget, _ai, _migration - Data preservation strategy: bank reconciliations verified preserved automatically (live in Community account.partial.reconcile); shared-field-ownership pattern for Enterprise extension fields on account.move; pre-uninstall migration wizard for Enterprise-only tables - Phased roadmap: Phase 0 foundation through Phase 7+ optional satellites, with Bank Rec as Phase 1 priority and Reports as the largest phase - Architecture rules: hybrid mirror/abstract zones, fusion.* naming, runtime coexistence detection, zero hard Enterprise deps - Cross-version upgrade workflow: pinned Odoo source snapshots per version, annual diff ritual, UPGRADE_NOTES.md per sub-module - AI integration via adapter pattern (current AI tools route through adapters that prefer fusion native, fall back to Enterprise, then to pure Community) - Testing strategy, security, performance, multi-company/currency, localization, hosting Implementation of each phase happens in subsequent sessions, each with its own writing-plans pass starting with Phase 0 Foundation. Made-with: Cursor
58 KiB
Fusion Accounting — Enterprise Takeover Roadmap
Status: Design (approved 2026-04-18)
Owner: Nexa Systems Inc.
Target: Odoo 19 Community + fusion_accounting becomes a feature-complete drop-in replacement for Odoo 19 Enterprise accounting (account_accountant, account_reports, accountant, account_followup, plus selected satellite modules) for clients deployed by Nexa Systems.
1. Context and Goals
1.1 Current State
fusion_accounting today is a thin AI co-pilot that depends on three Enterprise modules:
'depends': ['account', 'account_accountant', 'account_reports', 'account_followup', 'mail']
It adds Claude/GPT-driven tool calling, a chat panel, a dashboard, an approval workflow, and rule-based automation on top of Odoo's accounting features. It does not own any core accounting capability — it orchestrates Enterprise's APIs.
1.2 Business Driver
Nexa Systems deploys Odoo to clients. The Enterprise subscription cost is a friction point. The goal is to deliver Enterprise-equivalent accounting capability on Odoo 19 Community via fusion_accounting, so clients can run on Community without losing core accounting features. fusion_accounting is not distributed publicly (no Odoo App Store listing); it ships only as part of a Nexa client engagement.
1.3 Scope of "Takeover"
The Enterprise modules being targeted, with verified file counts:
| Enterprise Module | Files | Role | Targeted Phase |
|---|---|---|---|
account_accountant |
232 | bank-rec widget, journal dashboard, fiscal year, auto-reconcile, deferred revenue/expense, signing | Phases 1, 3 |
account_reports |
618 | financial reports engine + 18 standard reports | Phase 2 |
accountant |
26 | menu root + glue | Phase 0 |
account_followup |
58 | customer payment reminders | Phase 5 |
account_asset |
n/a | asset register, depreciation | Phase 6 |
account_budget |
n/a | budgets vs actuals | Phase 6 |
account_loans, account_3way_match, account_check_printing, account_batch_payment, account_iso20022, account_intrastat, account_saft, account_sepa_direct_debit, account_online_synchronization, account_edi_* |
n/a | various | Phase 7+ (per client need) |
1.4 Existing Reference Material
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting/— current AI module (will be reorganized in Phase 0)/Users/gurpreet/Github/Odoo-Modules/Work in Progress/fusion_accounting/— abandoned earlier attempt; contains 461 files of code that a Feb 2026 audit (in that folder'sAUDIT_REPORT.md) determined to be near-verbatim copies of Odoo Enterprise. The WIP code is not continued. Its__manifest__.pyis harvested as a feature checklist; its file structure as a target-architecture sanity check/Users/gurpreet/Github/RePackaged-Odoo/accounting/— pinned snapshot of Odoo 19 Enterprise accounting source; used as reference-only for clean-room rewrites and as the diff baseline for V19→V20 upgrades
1.5 Non-Goals
- Not building a public commercial product (no App Store distribution, no commercial licensing pricing model)
- Not replicating every Enterprise feature (Phase 7+ items are deferred until a real client needs them)
- Not maintaining backward compatibility with Odoo versions before 19
- Not rewriting Community
account— fusion_accounting builds on top of, never replaces, Community accounting
2. Sub-Module Topology
fusion_accounting is split into independently installable sub-modules. Each has a single, well-bounded responsibility and a clear Enterprise counterpart it replaces.
2.1 The Sub-Modules
graph TD
community["account<br/>Odoo Community base"]
core["fusion_accounting_core<br/>shared fields, lock dates, fiscal year base,<br/>company config, security groups, analytic_mixin"]
bankrec["fusion_accounting_bank_rec<br/>reconcile widget + auto-reconcile engine"]
reports["fusion_accounting_reports<br/>financial reports engine + standard reports"]
dashboard["fusion_accounting_dashboard<br/>journal kanban, digest"]
followup["fusion_accounting_followup<br/>payment reminders"]
assets["fusion_accounting_assets<br/>asset register, depreciation"]
budget["fusion_accounting_budget<br/>budgets vs actuals"]
ai["fusion_accounting_ai<br/>Claude/GPT copilot + chat + dashboard tiles<br/>(current fusion_accounting code lives here)"]
migration["fusion_accounting_migration<br/>transitional Enterprise to fusion data wizard"]
meta["fusion_accounting<br/>meta-module: depends on all sub-modules"]
core --> community
bankrec --> core
reports --> core
dashboard --> core
followup --> reports
assets --> core
budget --> core
ai --> core
migration --> core
ai -.optional adapter calls.-> bankrec
ai -.optional adapter calls.-> reports
ai -.optional adapter calls.-> followup
ai -.optional adapter calls.-> assets
meta --> core
meta --> bankrec
meta --> reports
meta --> dashboard
meta --> followup
meta --> assets
meta --> budget
meta --> ai
meta -.transitional only.-> migration
2.2 Sub-Module Responsibilities
| Sub-module | Replaces | Owns | Phase |
|---|---|---|---|
fusion_accounting_core |
accountant (menu glue), shared bits of account_accountant |
Shared field declarations on account.move/account.bank.statement.line (deferred fields, signing user), fusion.fiscal.year, lock-date wizard, security groups, settings page, analytic_mixin shared ownership |
Phase 0 |
fusion_accounting_bank_rec |
account_accountant bank rec widget + account_accountant/wizard/account_auto_reconcile_wizard.py |
OWL bank-rec widget, fusion.reconcile.engine, auto-reconcile wizard, reconcile model extensions |
Phase 1 |
fusion_accounting_reports |
account_reports (entire 618-file engine + reports) |
fusion.account.report, fusion.account.report.line, PDF templates, OWL report viewer, P&L/BS/TB/GL/Aged/Partner/CashFlow/Executive Summary |
Phase 2 |
fusion_accounting_dashboard |
account_accountant journal dashboard, accountant/data/account_accountant_data.xml, digest |
Journal kanban, digest tiles, "Needs Attention" data shape | Phase 3 |
fusion_accounting_followup |
account_followup |
fusion.followup.line, follow-up workflow, multi-level reminders |
Phase 5 |
fusion_accounting_assets |
account_asset |
fusion.asset, fusion.asset.group, depreciation engine, asset-register report |
Phase 6 |
fusion_accounting_budget |
account_budget |
fusion.budget, budget-vs-actual report |
Phase 6 |
fusion_accounting_ai |
(none — original) | Existing AI orchestrator, tools, chat panel, approval workflow, scoring, rules — moved verbatim from current fusion_accounting |
Phase 0 |
fusion_accounting_migration |
(none — transitional) | Wizard that copies Enterprise-only data into fusion tables before Enterprise uninstall; safety guard that blocks Enterprise uninstall until wizard runs | Phase 0 |
fusion_accounting (meta) |
(none — packaging) | Empty shell; depends on every sub-module so a single install gets everything |
Phase 0 |
2.3 Why Split (vs. monolith)
- Sub-modules can be enabled per client need (a small client without payroll-style assets installs core + bank_rec + reports + ai only)
- Each sub-module has independent test runs and CI (faster feedback loop)
- Each sub-module's cross-version upgrade is independent —
fusion_accounting_reportscan absorb V20 changes without touchingfusion_accounting_bank_rec - The AI sub-module stays cleanly separate, which makes it easy to keep using fusion's AI on top of Odoo Enterprise (when a client retains Enterprise) by installing
_aionly
2.4 Open Sub-Module Naming Decisions
The meta-module retains the name fusion_accounting so existing client installs don't see a name change. Sub-modules use the fusion_accounting_* prefix consistently.
3. Data Preservation and Client Switchover Strategy
The single most important guarantee in this entire design: client switchover from Odoo Enterprise to Odoo Community + fusion_accounting must lose zero accounting data, especially bank reconciliations.
This section is the contract that backs that guarantee.
3.1 What Survives an Enterprise Uninstall Automatically
Verified by direct read of RePackaged-Odoo/accounting/account/ source. These models and fields live in the Community account module and are unaffected by any Enterprise uninstall:
| Data | Storage | Verified Location |
|---|---|---|
| Bank reconciliation links | account.partial.reconcile |
account/models/account_partial_reconcile.py |
| Full reconciliation markers | account.full.reconcile |
account/models/account_partial_reconcile.py |
Bank statement lines + is_reconciled flag |
account.bank.statement.line |
account/models/account_bank_statement_line.py |
| Invoices, bills, payments | account.move, account.payment |
account/models/account_move.py, account_payment.py |
| Journal entries + lines | account.move, account.move.line |
account/models/account_move_line.py |
| Chart of accounts | account.account |
account/models/account_account.py |
| Taxes | account.tax |
account/models/account_tax.py |
| Journals | account.journal |
account/models/account_journal.py |
| Partners | res.partner |
base |
| Reconciliation rule base | account.reconcile.model |
account/models/account_reconcile_model.py |
checked (Reviewed) flag on moves |
account.move.checked |
account/models/account_move.py line 315 |
Critical observation about bank reconciliation in Odoo 19: The Enterprise account_accountant module does not define a bank.rec.widget Python model in V19. The bank-rec widget is implemented entirely as frontend OWL components in account_accountant/static/src/components/bank_reconciliation/, with a thin BankReconciliationService (bank_reconciliation_service.js) that calls Community ORM methods directly. There is no Enterprise-side persistent storage for the widget. When the widget is removed (Enterprise uninstall), the underlying account.partial.reconcile rows are untouched; fusion's replacement widget reads the same rows and shows every historical reconciliation as already-matched.
(The Work-in-Progress code at Work in Progress/fusion_accounting/models/bank_rec_widget.py uses the V17/V18 architecture where bank.rec.widget was a _auto = False Python model. That architecture was removed in V19. Our Phase 1 implementation must match V19 architecture.)
Verified Enterprise uninstall hook safety: account_accountant/__init__.py line 32-42 only revokes security group assignments. There are zero destructive DB operations in the uninstall hook.
Verified absence of cascade hazards: grep for ondelete='cascade' in account_accountant/models/ returns zero matches. No Enterprise model deletion can cascade-delete a reconciliation.
3.2 What Is Lost on Enterprise Uninstall (Without Mitigation)
| Enterprise-owned data | Importance | Mitigation Strategy |
|---|---|---|
account.fiscal.year records (fiscal year closing definitions) |
Medium | Migration wizard → fusion.fiscal.year |
account.asset records + asset-line links on moves |
High if assets used | Migration wizard → fusion.asset |
account.loan records |
Low (rare) | Migration wizard → fusion.loan (Phase 7+) |
| Budget records | Medium if used | Migration wizard → fusion.budget |
| Follow-up rule definitions + history | Medium | Migration wizard → fusion.followup.* |
account.move.deferred_move_ids, deferred_original_move_ids, deferred_entry_type |
High if deferred revenue/expense used — breaks the link between original and deferred postings | Shared-field ownership in fusion_accounting_core |
account.move.signing_user (audit signer) |
Medium | Shared-field ownership |
account.move.payment_state_before_switch |
Throwaway (technical) | Ignore |
account.reconcile.model.created_automatically |
Throwaway (single boolean) | Shared-field ownership in _bank_rec |
account.bank.statement.line.cron_last_check |
Throwaway (technical) | Ignore |
| Report XML records (P&L, BS structure) | None — reference data, not client data | fusion ships its own equivalents in _reports |
| Enterprise-only menus, actions | None — UI only | fusion installs its own |
3.3 Mitigation Pattern A: Shared-Field Ownership
For Enterprise-added fields on Community models (the deferred_*, signing_user, created_automatically fields), fusion_accounting_core declares identical field definitions with the same relation table names:
class AccountMove(models.Model):
_inherit = "account.move"
deferred_move_ids = fields.Many2many(
comodel_name='account.move',
relation='account_move_deferred_rel', # identical relation table to Enterprise
column1='original_move_id',
column2='deferred_move_id',
copy=False,
)
deferred_original_move_ids = fields.Many2many(
comodel_name='account.move',
relation='account_move_deferred_rel',
column1='deferred_move_id',
column2='original_move_id',
copy=False,
)
deferred_entry_type = fields.Selection(
selection=[('expense', 'Deferred Expense'), ('revenue', 'Deferred Revenue')],
copy=False,
)
signing_user = fields.Many2one(comodel_name='res.users', copy=False)
payment_state_before_switch = fields.Char(copy=False)
Mechanism: Odoo's module registry tracks every module that declares a given field on a given model. When account_accountant uninstalls, Odoo only drops the column (or relation table) if no other installed module also declares it. Because fusion_accounting_core declares these identically, Odoo retains the column/table. Existing data values are preserved row-by-row.
Caveat: this pattern creates a schema dependency on Enterprise's choices. If Odoo ever renames account_move_deferred_rel in V20, both the Enterprise and fusion versions of that field break together — the migration is just ALTER TABLE ... RENAME in our migration script. We accept this risk because the alternative (renaming to fusion-namespaced fields) requires a much heavier migration of every existing row.
3.4 Mitigation Pattern B: Pre-Uninstall Migration Wizard
For Enterprise-only models (account.asset, account.fiscal.year, account.loan, budgets, followups), fusion_accounting_migration provides a wizard accessible from Settings → Fusion Accounting → Migrate from Enterprise.
The wizard:
- Detects which Enterprise modules are installed
- For each detected module, checks the corresponding fusion module is also installed (and prompts to install if missing)
- Shows a preview: row counts per Enterprise table that will be migrated, listing target fusion table for each
- On confirm, runs
INSERT INTO fusion_<table> SELECT ... FROM <enterprise_table>for each migration step, preserving primary keys andir.model.dataxml_ids - Generates a migration report (record counts, any rows that failed validation, warnings)
- Marks each Enterprise table as "migrated" via an
ir.config_parameterflag (fusion_accounting.migration.<module>.completed) - Re-running the wizard is idempotent: already-migrated tables are skipped unless explicitly re-migrated
A separate safety guard in fusion_accounting_migration overrides ir.module.module.button_immediate_uninstall for Enterprise accounting modules; if the migration flag for that module is False and it has data, the uninstall is blocked with a UserError linking to the wizard.
3.5 Switchover Protocol (the operator workflow)
graph TD
start[Client on Odoo 19 Enterprise] --> step1["Install fusion_accounting meta-module<br/>while Enterprise still running"]
step1 --> step2["fusion_accounting_core declares shared fields<br/>Odoo registers dual ownership for deferred_*, signing_user, etc."]
step2 --> step3["Open Settings → Fusion Accounting → Migrate from Enterprise"]
step3 --> step4["Wizard shows preview: row counts per table"]
step4 --> step5["Operator confirms"]
step5 --> step6["Wizard copies asset, fiscal year, loan, budget, followup rows<br/>into fusion tables"]
step6 --> step7["Wizard generates migration report"]
step7 --> step8["Operator reviews report"]
step8 --> step9["Operator triggers Enterprise uninstall in dep-safe order:<br/>account_reports → account_followup → account_asset →<br/>account_budget → account_loans → account_accountant → accountant"]
step9 --> step10["Safety guard verifies migration flags before each uninstall"]
step10 --> done["Done: Client on Community + fusion_accounting<br/>Bank recs intact, deferred links preserved,<br/>migrated data accessible via fusion menus"]
3.6 Empirical Verification Test (Phase 0 deliverable)
The shared-field-ownership analysis and the inventory of "what survives" is based on reading source. Strong, but not conclusive. Phase 0 includes a one-time empirical test:
- Provision a throwaway Odoo 19 Enterprise instance
- Install full Enterprise accounting stack
- Create representative test data:
- 50 invoices, 30 vendor bills, mix of paid/unpaid
- 15 bank reconciliations (full and partial)
- 5 deferred revenue entries with
deferred_move_idspopulated - 3 fiscal year closings
- 10 asset records with depreciation history
- 2 budgets with actuals
- Multi-currency journal entries
- 1 cash-basis tax move
- Take
pg_dumpsnapshot - Uninstall Enterprise modules in dep-safe order without running the migration wizard (this is the worst-case test)
- Diff schema and row counts before and after
- Document findings in
docs/superpowers/specs/2026-04-18-empirical-uninstall-test-results.md - If gaps are found vs. Section 3.2, expand the wizard scope or shared-field declarations accordingly
This test is a Phase 0 acceptance gate. The roadmap does not advance to Phase 1 until empirical verification confirms or expands the analysis.
3.7 Reverse-Migration Note
The reverse direction (client on Community + fusion adds an Enterprise subscription later) is not a hard requirement. fusion's runtime feature-gating (Section 4.4) handles the coexistence case: when Enterprise is detected, fusion's conflicting menus hide and the AI module continues running on top of Enterprise. A reverse-migration wizard can be added in Phase 7+ if a real client needs it.
3.8 Backup and Rollback
Every client deployment must include, before any switchover step:
pg_dumpof the live database- Snapshot of all installed module versions (
SELECT name, latest_version FROM ir_module_module WHERE state='installed') - Snapshot of
/mnt/extra-addons/contents
Rollback procedure: restore DB from pg_dump, restore extra-addons from snapshot, restart Odoo. The migration wizard's "Generate Backup First" checkbox is checked by default and must be explicitly unchecked to skip.
4. Phased Roadmap
Each phase produces shippable value. Phase order is locked. Time estimates are rough single-engineer figures and are not binding deadlines — the user has explicitly stated "no rush, product-first".
4.1 Phase Overview
| Phase | Focus | Estimate | Depends On |
|---|---|---|---|
| 0 | Foundation, sub-module split, migration scaffold, empirical test | 1-2 wks | (none) |
| 1 | Bank reconciliation (priority) | 3-5 wks | 0 |
| 2 | Financial reports engine | 6-10 wks | 0 |
| 3 | Dashboard + fiscal year + lock dates | 2-3 wks | 1, 2 |
| 4 | Tax reports + returns | 3-5 wks | 2 |
| 5 | Payment follow-ups | 2-3 wks | 3, 4 |
| 6 | Assets + budgets | 3-5 wks | 5 |
| 7+ | Optional satellites (loans, check printing, batch payment, 3-way match, EDI, SEPA, SAFT, intrastat, online sync) | per item | 6 |
Phases 1 and 2 can run in parallel after Phase 0 (no shared scope).
4.2 Phase 0 — Foundation
No user-facing features. Pure plumbing so every later phase is cheaper.
Scope:
- Create sub-module scaffolding for
fusion_accounting_core,fusion_accounting_migration,fusion_accounting_ai - Move existing AI copilot code from current
fusion_accounting/intofusion_accounting_ai/. Files moved:models/,services/,controllers/,wizards/,data/,static/src/,views/,security/,report/,tests/. Update internal imports - Convert current
fusion_accounting/into the meta-module: empty__init__.py, manifest withdepends = ['fusion_accounting_core', 'fusion_accounting_ai', ...](sub-modules added as later phases ship), no Python/JS/XML code of its own - Strip hard Enterprise deps from
fusion_accounting_ai/__manifest__.py. Replaceaccount_accountant,account_reports,account_followupwithaccount(Community). Add runtime detection (Section 4.4) - Refactor every AI tool in
fusion_accounting_ai/services/tools/that calls Enterprise APIs to go through an adapter layer (services/adapters/bank_rec_adapter.py,reports_adapter.py,followup_adapter.py). Adapters pick between Enterprise APIs (when present) and fusion native (when present) and a "feature-unavailable" stub (when neither) - Create
fusion_accounting_core/models/account_move.pywith shared-field declarations (Section 3.3) - Create
fusion_accounting_migration/shell: empty wizard, safety guard scaffold (no migrations yet) - Create
tools/check_odoo_diff.shscript that diffs two pinned Odoo source snapshots and outputs a categorized change list - Move security groups:
group_fusion_accounting_user/manager/adminmove from current tofusion_accounting_core/security/. Multi-company record rule onfusion.accounting.sessionadded (currently missing per existing CLAUDE.md "Known Issues") - Create per-sub-module
CLAUDE.md(factor common rules from existingfusion_accounting/CLAUDE.md) andUPGRADE_NOTES.mdtemplate - Run the empirical verification test (Section 3.6) on a throwaway V19 Enterprise instance
- CI: GitHub Actions or gitea workflow that runs
pytestper sub-module on every push
Exit criteria:
- Current AI copilot installs and runs on pure Community (no Enterprise modules present)
- Current AI copilot still installs and runs alongside Enterprise (coexistence mode)
- Empirical test report committed
- All adapter calls wired (no direct Enterprise API access from AI tools)
- CI green
Risks and mitigations:
- Risk: moving code between modules breaks existing client deployments. Mitigation: meta-module install upgrade hook handles model-record reassignment via
ir_model_dataupdates; pre-migration script runs on first install of Phase 0 - Risk: empirical test reveals gaps. Mitigation: scope-expand the migration wizard before declaring Phase 0 complete
4.3 Phase 1 — Bank Reconciliation
The user's stated priority. Replaces account_accountant's bank-rec widget end-to-end.
Scope:
- Create
fusion_accounting_bank_rec/sub-module - Frontend (mirror zone): build
static/src/components/bank_reconciliation/mirroring the file layout ofaccount_accountant/static/src/components/bank_reconciliation/(kanban_controller,kanban_renderer,bank_reconciliation_service,apply_amount,bankrec_form_dialog,button,button_list,chatter,file_uploader,line_info_pop_over,line_to_reconcile,list_view,quick_create,reconciled_line_name,search_dialog,statement_line,statement_summary). Mirror is structural — class names, file names, OWL component boundaries — not copy-paste. Implementation written fresh against documented Odoo behavior - Backend (abstract zone):
models/fusion_reconcile_engine.pycontaining the matching algorithm (FIFO, partial reconcile, write-off lines, exchange-rate diff posting, tax splits). Original implementation against documented requirements. Operates on Communityaccount.partial.reconcile models/fusion_reconcile_model.pyextending Communityaccount.reconcile.modelwith auto-rules, partner mapping, journal mapping. Shared-field ownership forcreated_automaticallywizards/auto_reconcile_wizard.pyclean-room rewrite ofaccount_accountant/wizard/account_auto_reconcile_wizard.pywizards/reconcile_wizard.pyclean-room rewrite ofaccount_accountant/wizard/account_reconcile_wizard.pyviews/bank_rec_widget_views.xmldefines the action that opens the OWL widget;views/account_reconcile_model_views.xmlfor rule editing- Menu: "Bank Reconciliation" under fusion accounting menu, with feature-gate (hidden if
account_accountantinstalled) - AI integration: existing AI tools
get_unreconciled_bank_lines,find_similar_bank_lines,get_bank_line_details,find_missing_itc_bills,find_duplicate_bills,get_overdue_invoicesget refactored to call fusion's bank rec engine viafusion_accounting_ai/services/adapters/bank_rec_adapter.py. The Tier 3 toolscreate_vendor_bill,register_bill_payment,create_expense_entrykeep their existing logic (they write to Communityaccount.move) - Migration: wizard validates
account.partial.reconcilerow count is preserved across switchover (read-only check, no migration needed) - Tests:
- Unit (engine): matching correctness with fixtures (single partner, multi-partner, multi-currency, partial, exchange diff, write-off, tax split)
- Integration: install + create statement + reconcile via UI + assert
account.partial.reconcilerows - Tour (JS): smoke through the full bank rec workflow
- Migration: install Enterprise, create 10 reconciliations, install fusion, uninstall Enterprise, assert reconciliations visible in fusion widget
Exit criteria:
- Community + fusion_accounting user can reconcile bank statements with feature parity to Enterprise
- All Phase 1 tests passing
- Migration round-trip (Enterprise → fusion) preserves every reconciliation
- AI tools work against fusion bank rec engine
4.4 Phase 2 — Financial Reports Engine
The largest phase. Replaces account_reports (618 files).
Scope:
- Create
fusion_accounting_reports/sub-module - Backend (abstract zone):
models/fusion_account_report.pydefiningfusion.account.reportandfusion.account.report.line. Generic engine that takes a report definition (sections, filters, computation rules) and produces report rows fromaccount.move.linedata. Original computation kernel — does not copyaccount_reports'saccount_report.py - Backend (mirror zone): report definition records mirror Odoo's data files. Files:
data/balance_sheet.xml,data/profit_and_loss.xml,data/cash_flow_report.xml,data/general_ledger.xml,data/trial_balance.xml,data/aged_partner_balance.xml,data/partner_ledger.xml,data/executive_summary.xml,data/sales_report.xml,data/multicurrency_revaluation_report.xml,data/bank_reconciliation_report.xml,data/deferred_reports.xml,data/journal_report.xml,data/customer_statement.xml. XML structure follows Odoo's so V20 ports are diff-and-apply - Frontend (mirror zone):
static/src/components/mirrorsaccount_reports/static/src/components/— filters bar, comparison toggle, drill-down, foldable sections, footnotes - PDF export: QWeb templates in
report/mirror Odoo'sdata/pdf_export_templates.xmlanddata/customer_reports_pdf_export_templates.xml. Asset bundlefusion_accounting_reports.assets_pdf_exportdefined in manifest - Performance: denormalized read paths for trial balance and general ledger (materialized aggregations refreshed on
account.movepost). Drill-down lazy-loads line detail. Per-(company, period, filter_hash) cache invalidated onaccount.move.linewrite - Multi-company, multi-currency, cash-basis toggle — all handled by the engine
- AI integration: tools
get_profit_loss,get_balance_sheet,get_trial_balance,get_aged_receivables,get_aged_payables,get_partner_ledger,answer_financial_questionrefactored viareports_adapter.py - Migration: report XML records are reference data, not client data. fusion ships its own equivalent records; no migration of report definitions needed. Existing journal entry data (which the reports compute from) is in Community
accountand untouched - Tests:
- Unit (engine): SQL-fixture comparisons (compute report → compare against hand-rolled SQL) for every standard report, every filter combination
- Integration: install + post entries + open report + assert numbers
- Multi-currency: single + multi + revaluation period
- Performance: 1k / 10k / 100k journal lines, assert P95 latency under 5s
- PDF: render every report to PDF, assert no QWeb errors
- Tour: smoke through report viewer with filters
Exit criteria:
- All 14 standard reports rendering correctly (numerical match against SQL fixtures)
- PDF export working for every report
- Performance targets met
- AI tools backed by fusion reports
4.5 Phase 3 — Dashboard + Fiscal Year + Lock Dates
Scope:
- Create
fusion_accounting_dashboard/sub-module - Journal kanban dashboard: mirror layout of
account_accountant/views/account_journal_dashboard_views.xml. Computed metrics inmodels/account_journal.pyextending Communityaccount.journalwith kanban-state fields (counts, totals, action buttons). Original computation; mirror UI models/fusion_fiscal_year.pydefiningfusion.fiscal.year(replacesaccount.fiscal.year)- Fiscal year wizard: closing workflow, period locks, initial-balance carry-forward
- Lock date wizard: clean-room rewrite of
account_accountant/wizard/account_change_lock_date.py. Operates on Communityaccount.lock_exceptionmodel (verified ataccount/models/account_lock_exception.py) - Digest tile contributions: extend
mail.digestwith fusion accounting metrics (revenue, expense, AR, AP) - "Needs Attention" panel — connect data already returned by current AI dashboard endpoint to a frontend rendering. Dashboard endpoint (currently in
fusion_accounting_ai/controllers/) moves tofusion_accounting_dashboard/controllers/; AI module's dashboard tiles call dashboard's endpoint via adapter - Tests:
- Journal dashboard kanban metrics match expected values for fixtures
- Fiscal year close locks subsequent edits
- Lock date wizard prevents posting before lock date
- Digest renders without errors
Exit criteria:
- Journal dashboard at parity with Enterprise
- Fiscal year management functional
- Lock dates enforced
- Digest emails delivering
4.6 Phase 4 — Tax Reports + Returns
Scope:
- Build on Phase 2 reports engine; tax reports are specialized
fusion.account.reportrecords - Generic tax report (
data/generic_tax_report.xml) with country-specific overrides - Canadian HST: unify the existing HST workflow in
fusion_accounting_ai(currently inservices/prompts/domain_prompts.pyand tool functions) with the new tax report engine. The existingfind_missing_itc_bills,get_overdue_invoices, etc. tools call into the tax report fusion.account.returnmodel (replacesaccount.returnfromaccount_reports) tracking tax return drafts, submitted state, payment status- Return creation wizard, return submission wizard, return generic payment wizard — clean-room rewrites of the corresponding
account_reportswizards - Tax closing entries (move generation on tax period close)
- Tests:
- Tax report numbers match SQL fixtures
- Return workflow: draft → review → submitted → paid
- HST 4-phase workflow (per existing CLAUDE.md) end-to-end
Exit criteria:
- Generic tax report functional
- Canadian HST workflow runs through fusion (no Enterprise dependency)
- Return tracking working
4.7 Phase 5 — Payment Follow-ups
Scope:
- Create
fusion_accounting_followup/sub-module models/fusion_followup_line.py(replacesaccount_followup.followup.line)models/res_partner.pyextendsres.partnerwith follow-up level, last reminder date, dunning historymodels/account_move.pyextendsaccount.movewith follow-up state (overdue days, last reminder)- Multi-level reminder workflow: each level has email template, days delay, optional SMS, optional
mail.activity wizards/followup_send_wizard.pyfor manual sends; cron for automatic- Follow-up report (PDF): clean-room template
- AI integration:
fusion_accounting_aiadds toolsdraft_followup_message_for_partner,send_followup_to_overdue_partnerscalling the followup engine via adapter - Migration: wizard copies
account_followup.followup.lineand partner-level follow-up state intofusion.followup.lineand shared-field-owned partner fields - Tests:
- Multi-level escalation
- Email template rendering
- SMS delivery (mock)
- AI-drafted message quality (snapshot tests)
Exit criteria:
- Multi-level dunning working
- Migration from
account_followuppreserves history
4.8 Phase 6 — Assets + Budgets
Scope:
- Create
fusion_accounting_assets/sub-modulemodels/fusion_asset.py(replacesaccount.asset)models/fusion_asset_group.py(replacesaccount.asset.group)- Depreciation engine: linear, declining, custom schedules. Original implementation
wizards/asset_modify.pyfor revaluation, sale, disposal — clean-room rewrite- Asset register report integrates with Phase 2 reports engine
- Migration wizard copies
account.assetrows + line links on moves
- Create
fusion_accounting_budget/sub-modulemodels/fusion_budget.py(replacesbudget.analytic)- Budget vs actual report integrates with Phase 2 reports engine
- Migration wizard copies budget records
- Tests for both
Exit criteria:
- Asset depreciation schedules computed correctly
- Disposal generates correct GL entries
- Budget variance report functional
4.9 Phase 7+ — Optional Satellites
Not scheduled. Each is its own brainstorming → spec → plan → implementation cycle when a real client needs it. Candidate satellite modules:
fusion_accounting_loans— loan amortizationfusion_accounting_check_printing— check printingfusion_accounting_batch_payment— batch paymentsfusion_accounting_3way_match— purchase 3-way matchfusion_accounting_edi— UBL/CII e-invoicingfusion_accounting_sepa— SEPA direct debit + credit transferfusion_accounting_saft— SAFT exportfusion_accounting_intrastat— intrastat reportfusion_accounting_iso20022— ISO 20022 payment filesfusion_accounting_online_sync— online bank sync (Yodlee/Plaid integration)
4.10 Per-Phase Deliverables (uniform)
Each phase produces:
- A separate design document in
docs/superpowers/specs/YYYY-MM-DD-fusion-accounting-phase-N-*-design.md(brainstormed in its own session) - A separate implementation plan via the
writing-plansskill - Working code with passing tests
- Entry in the sub-module's
UPGRADE_NOTES.mdlisting Odoo source files referenced and intentional deltas - Coverage in
fusion_accounting_migrationif the phase replaces an Enterprise data-bearing model - Manual QA checklist (install, migrate, smoke, uninstall) committed to the sub-module
- Update to the meta-module
__manifest__.pyadding the new sub-module to itsdepends
5. Architecture Rules
These rules apply to every sub-module and every phase. They are the discipline that keeps V19→V20 upgrades mechanical and prevents the WIP-style descent into copied code with stale architecture.
5.1 The Hybrid Split
Every sub-module has two zones with different rules:
Mirror zone (follows Odoo structure 1:1):
- XML view definitions and xpath targets
- Frontend OWL component file layout, service registration, widget props
- PDF/QWeb templates: structure, CSS class names
- Wizard flows: step order, field names where they appear in views
- Asset bundle declarations in manifests
Locations: views/, static/src/components/, report/ QWeb templates, wizards/*_views.xml, __manifest__.py asset bundles
Abstract zone (our own design, insulated from Odoo internals):
- Core algorithms: matching, aggregation, computation, depreciation
- Data access helpers
- Business validation, approval flows
- AI integration adapters
- Engine classes (e.g.
fusion_reconcile_engine.py)
Locations: models/fusion_*_engine.py, services/, controllers/ (business logic only — request routing is mirror-zone)
Rule of thumb: if Odoo refactors it every release, mirror it. If it's been stable for a decade (FIFO matching, accrual rules, depreciation math), abstract it.
5.2 Naming Conventions
| Thing | Convention | Example |
|---|---|---|
Model _name |
fusion.* prefix always |
fusion.bank.rec.widget, fusion.account.report, fusion.fiscal.year |
Model _inherit on Community |
Keep account.* (no rename) |
class AccountMove(models.Model): _inherit = 'account.move' |
Model _inherit on Enterprise |
Forbidden — duplicate fields via shared-field-ownership instead | n/a |
| Python class names | Fusion prefix for new models |
FusionBankRecWidget, FusionAccountReport |
| Table names (auto-derived) | Follows model prefix | fusion_bank_rec_widget, fusion_account_report |
| XML record IDs | fusion_* prefix |
<record id="fusion_view_bank_rec_form"> |
| Menu IDs | fusion_menu_* prefix |
Avoids collision with account_menu_* |
| Action IDs | fusion_action_* |
Same |
| Controller routes | /fusion_accounting/* |
Already in use; carries forward |
| Security groups | group_fusion_* |
Already in use |
| Field names on inherited Community models | Identical to Enterprise if shared-field-owned; otherwise x_fusion_* prefix |
deferred_move_ids (shared), x_fusion_ai_confidence (our own) |
| CSS/SCSS classes | .fusion_* or .o_fusion_* |
Avoids Bootstrap/Odoo collision |
ir.config_parameter keys |
fusion_accounting.* |
Already in use |
5.3 Coexistence Detection
Every sub-module that replaces an Enterprise feature must detect Enterprise at install time and at runtime, and feature-gate accordingly.
Helper function (lives in fusion_accounting_core/models/ir_module_module.py):
class IrModuleModule(models.Model):
_inherit = "ir.module.module"
@api.model
def _fusion_is_enterprise_accounting_installed(self):
return bool(self.sudo().search_count([
('name', 'in', ['account_accountant', 'account_reports', 'accountant']),
('state', '=', 'installed'),
]))
Three coexistence modes per sub-module, configurable in Settings → Fusion Accounting → Integration Mode:
- Replace (default when Enterprise absent): fusion menus visible, fusion views primary, fusion workflows active
- Augment (default when Enterprise present): fusion menus hidden, fusion widgets disabled, fusion AI module continues to call Enterprise APIs via adapters
- Force-replace (manual): fusion menus visible alongside Enterprise (operator's choice — risk of confusion, used during migration)
Menu visibility achieved via groups attribute referencing a dynamically-computed group (group_fusion_show_menus_when_enterprise_absent), implemented as a @api.depends computed field on res.users that recomputes membership when modules change state.
5.4 Zero Hard Enterprise Dependencies
After Phase 0:
fusion_accounting_core/__manifest__.py:depends = ['account', 'mail', 'web_tour']fusion_accounting_ai/__manifest__.py:depends = ['fusion_accounting_core']plusexternal_dependenciesforanthropic,openai- Every other
fusion_accounting_*/__manifest__.py:depends = ['fusion_accounting_core']plus fusion siblings as needed (e.g.,_followupdepends on_reports)
No fusion_accounting_* module may have account_accountant, account_reports, accountant, account_followup, account_asset, account_budget, account_loans, account_3way_match, account_check_printing, account_batch_payment, account_iso20022, account_intrastat, account_saft, account_sepa_direct_debit, account_online_synchronization, or any account_edi_* in its depends.
Runtime detection (Section 5.3) replaces compile-time dependency.
5.5 Canonical Sub-Module Directory Layout
fusion_accounting_<feature>/
├── __manifest__.py
├── __init__.py
├── CLAUDE.md # module-specific context for Cursor agent
├── UPGRADE_NOTES.md # Odoo version deltas absorbed
├── README.md # operator-facing install/configure/troubleshoot
├── docs/
│ └── odoo_diff/ # snapshots of relevant Odoo source for diffing
│ └── v19/
│ └── account_accountant__bank_reconciliation_service.js
├── controllers/
│ └── __init__.py
├── data/
├── demo/
├── i18n/
├── models/
│ ├── __init__.py
│ ├── fusion_<feature>_engine.py # abstract zone: core algorithm
│ ├── account_<x>.py # mirror zone: inherits Community model
│ └── fusion_<y>.py # mirror zone: our own models
├── report/
├── security/
│ ├── ir.model.access.csv
│ └── <feature>_security.xml
├── services/ # AI / heavy business logic
├── static/
│ ├── description/
│ │ ├── icon.png
│ │ └── index.html
│ └── src/
│ ├── components/ # mirror zone: OWL components
│ ├── scss/
│ ├── services/ # frontend services
│ └── views/
├── tests/
│ ├── __init__.py
│ ├── test_<feature>_engine.py # abstract zone unit tests
│ ├── test_<feature>_integration.py # full-stack integration tests
│ ├── test_migration.py # Enterprise → fusion round-trip
│ └── tours/
├── views/
├── wizards/
└── migrations/ # Odoo version migration scripts (XX.0.x.y.z)
└── 19.0.1.0.0/
├── pre-migration.py
└── post-migration.py
5.6 Odoo 19 Gotchas (carried forward, factored across CLAUDE.md files)
The current fusion_accounting/CLAUDE.md documents Odoo 19-specific traps that have already cost time. All carry forward:
- Search views: no
stringattribute on<search>or<group>; group-by filters needdomain="[]";<separator/>before<group> - OWL client actions:
static props = ["*"](accept any), notstatic props = [](accept none) - OWL rich HTML:
markup()andt-outunreliable in Odoo 19; useonMounted+onPatched+ directinnerHTML - Cron
safe_eval: noimportstatements; usedatetime.datetime.now()notfrom datetime import datetime read_group()deprecated → use_read_group()ir_config_parameterSelection field migrations: stored DB value must match new options or Settings page crashesimplied_idson groups only applies to newly-added users — existing users need SQL backfillTransientModelin controllers: use.new({...})not.create({...})- HTTP routes:
type="jsonrpc", nottype="json"(deprecated) res.config.settings: only boolean/integer/float/char/selection/many2one/datetime; no Date fieldsres.groups: nousersfield, nocategory_idfield- Search views: no
group expand="0"syntax - SCSS imports:
@import "./partial"is forbidden in Odoo 19 custom SCSS; register every SCSS file as a separate entry inweb.assets_backend - Card styling: don't rely on
var(--bs-border-color)orvar(--bs-body-bg); use Odoo's kanban explicit-hex pattern with custom-property tokens - Dark mode: branch on
$o-webclient-color-schemeat SCSS compile time, not runtime DOM class - Asset bundle cache busting: bump manifest version +
DELETE FROM ir_attachment WHERE url LIKE '/web/assets/%'if needed
These rules belong in each sub-module's CLAUDE.md (the relevant subset) plus the workspace-root CLAUDE.md (common rules).
5.7 Manifest Versioning and Branch Strategy
- Per-sub-module manifest:
'version': 'XX.0.x.y.z'where XX is the Odoo version (e.g.,19.0.1.0.0for V19, first release) - Bump
XXon Odoo version change (V19 → V20 → V21) - Bump
xon major feature additions within an Odoo version - Bump
yon minor features and bug fixes - Bump
zon hotfixes - Git branches:
main-v19,main-v20, etc. Each client deployment is pinned to one branch - Release tags:
<sub-module>/v19.0.1.0.0per sub-module per release
6. Cross-Version Upgrade Workflow
This section is the user's stated top concern: how to keep porting Enterprise changes forward each year without it becoming a rewrite project.
6.1 Snapshot Discipline
Maintain one pinned snapshot of the relevant Odoo source per Odoo version:
/Users/gurpreet/Github/RePackaged-Odoo/
├── accounting-v19/ # current snapshot (already in place at accounting/)
├── accounting-v20/ # added when V20 ships
├── accounting-v21/ # added when V21 ships
Older snapshots are never deleted — they are the diff source for upgrade work.
6.2 Annual Upgrade Ritual
When Odoo V<N+1> ships:
- Add the snapshot folder
- For each fusion sub-module:
- Run
tools/check_odoo_diff.sh <enterprise_module> v<N> v<N+1> > reports/v<N+1>_<module>_diff.md - Manually classify each change in the diff:
[MIRROR]— apply the same hunk to fusion's mirror-zone files (mechanical)[ABSTRACT]— verify the Odoo public API surface our adapter uses still works; update the adapter if signatures changed[NEW FEATURE]— decide port or defer[BUG FIX]— port (usually cheap)[REMOVED]— clean up our equivalent
- Apply mirror-zone hunks (these are usually direct
patch -p1operations) - Write Odoo version migration scripts in
migrations/<N+1>.0.0.0.0/for any data-shape changes - Update
UPGRADE_NOTES.md - Run all tests
- Run
- Tag releases on
main-v<N+1>branch - Pilot upgrade on one client first; ratchet outward
6.3 UPGRADE_NOTES.md Template
# UPGRADE_NOTES — fusion_accounting_bank_rec
## V19.0.1.0.0 (initial)
- Ported from: account_accountant V19 (snapshot date 2026-04-18)
- Mirror sources:
- account_accountant/static/src/components/bank_reconciliation/* → fusion_accounting_bank_rec/static/src/components/bank_reconciliation/*
- account_accountant/wizard/account_auto_reconcile_wizard.py → fusion_accounting_bank_rec/wizards/auto_reconcile_wizard.py (clean-room)
- Abstract zone:
- models/fusion_reconcile_engine.py — original implementation
- Intentional deltas from Odoo:
- AI hook in reconcile step (calls fusion_accounting_ai.suggest_match adapter)
- Different default colour palette (SCSS var overrides)
## V20.0.x.y.z (planned, not yet shipped)
- Odoo changes account_accountant V19 → V20 absorbed:
- [MIRROR] kanban_renderer.js: column layout changed, applied identical hunk
- [ABSTRACT] account.reconcile.model._apply_lines_for_bank_widget signature changed — updated adapter
- [NEW FEATURE] batch-reconcile-across-journals — deferred to V20.1
- Migration scripts:
- migrations/20.0.0.0.0/pre-migration.py: rename column foo → bar
6.4 tools/check_odoo_diff.sh Specification
The script lives at fusion_accounting/tools/check_odoo_diff.sh (workspace root, shared across sub-modules). Usage:
tools/check_odoo_diff.sh <enterprise_module> <from_version> <to_version> [<output_file>]
Behavior:
- Runs
diff -ruN /Users/gurpreet/Github/RePackaged-Odoo/accounting-<from>/<module> /Users/gurpreet/Github/RePackaged-Odoo/accounting-<to>/<module> - Splits output into per-file sections
- For each file, classifies based on file path:
views/andstatic/src/components/andreport/→[MIRROR]candidate;models/*_engine.py-like →[ABSTRACT]review; new files →[NEW FEATURE]review - Outputs a markdown report with per-file sections and classification suggestions
- Exit code: 0 if no changes, non-zero if changes (CI can use to flag annual upgrades)
6.5 Pinning and Rollback
- Git:
main-v19,main-v20, etc. branches in fusion repo. Each client stays on their pinned Odoo version - Manifest version pinned per sub-module per Odoo version
- Client deployment: never auto-upgrade. Upgrade is a deliberate, tested, per-client migration
- Rollback: restore DB from
pg_dumptaken before upgrade, restorefusion_accounting_*checkout from git tag, restart Odoo
6.6 Cross-Version Migration Scripts
Odoo's standard migration mechanism applies. Each sub-module has a migrations/ folder with subfolders named after manifest versions. Scripts run automatically when the manifest version bumps in the database vs. on disk.
# fusion_accounting_assets/migrations/20.0.0.0.0/pre-migration.py
def migrate(cr, version):
# V20 renamed fusion_asset.original_value to fusion_asset.acquisition_cost
cr.execute("ALTER TABLE fusion_asset RENAME COLUMN original_value TO acquisition_cost")
7. AI Integration, Testing, Documentation
7.1 AI Integration
The AI copilot (existing fusion_accounting/services/, fusion_accounting/static/src/, fusion_accounting/controllers/ etc.) moves to fusion_accounting_ai/ in Phase 0 and stays original code. What changes:
Adapter pattern: every AI tool that today calls Enterprise APIs gets routed through an adapter:
fusion_accounting_ai/services/adapters/
├── bank_rec_adapter.py
├── reports_adapter.py
├── followup_adapter.py
├── assets_adapter.py
└── _registry.py
Adapter behavior (uniform pattern across all adapters):
class BankRecAdapter:
def __init__(self, env):
self.env = env
def list_unreconciled_lines(self, journal_id, limit=100):
# Prefer fusion native if installed
if 'fusion.bank.rec.widget' in self.env.registry:
return self.env['fusion.bank.rec.widget'].sudo().get_unreconciled(journal_id, limit)
# Fall back to Enterprise if installed
elif self.env['ir.module.module']._fusion_is_module_installed('account_accountant'):
return self._enterprise_unreconciled_lines(journal_id, limit)
# Last resort: pure Community search
else:
return self.env['account.bank.statement.line'].sudo().search([
('journal_id', '=', journal_id),
('is_reconciled', '=', False),
], limit=limit)
This pattern means fusion_accounting_ai always works, regardless of which other modules are installed. The AI tool functions in fusion_accounting_ai/services/tools/ get refactored once in Phase 0 to call adapters; subsequent phases just enrich the adapters.
New AI capabilities unlocked by native implementations: each native phase exposes engine internals to AI tools that Enterprise didn't expose cleanly. Examples:
- Phase 1: AI gets access to fusion's match-confidence scores
- Phase 2: AI can request a report computation with custom comparison periods on the fly
- Phase 4: AI has direct access to tax-grid-by-account decomposition
- Phase 5: AI drafts follow-up messages with full payment history context
Existing AI patterns carry forward unchanged:
- Tool tiering (Tier 1 / 2 / 3 with auto-promotion)
- Provider pinning per session (Claude vs OpenAI consistency within a session)
- Tier 3 approval flow with
pending_approvalplaceholder swap on approve/reject - Rich-text chat output via
mdToHtml()andinnerHTMLinjection - Interactive
fusion-tableblocks for actionable results - Session ownership / multi-company record rules (the
fusion.accounting.sessionrule that's currently missing gets added in Phase 0)
7.2 Testing Strategy
Every phase must pass these test categories before exit:
| Category | Scope | Where it lives |
|---|---|---|
| Unit (engine) | Pure-Python; no Odoo DB. Algorithm correctness with fixtures | tests/test_<feature>_engine.py |
| Integration (Odoo TestCase) | Full Odoo DB; install + create data + exercise workflow + assert state | tests/test_<feature>_integration.py |
| Migration round-trip | Install Enterprise, create Enterprise-only data, install fusion, run wizard, uninstall Enterprise, assert data integrity | tests/test_migration.py |
| Tour (JS) | End-to-end widget UI smoke | tests/tours/<feature>_tour.js |
| Performance | Phase 2 reports especially; assert P95 latency at 1k/10k/100k rows | tests/test_<feature>_performance.py |
| Multi-matrix | Single-company, multi-company, multi-currency, cash-basis on/off | parameterized within other tests |
CI runs all tests on every push. A nightly job runs migration tests against a fixture Enterprise DB.
7.3 Documentation Deliverables
Per sub-module:
CLAUDE.md— module-specific context for Cursor/AI assistanceUPGRADE_NOTES.md— Odoo version porting logREADME.md— operator-facing: install, configure, troubleshoot, common gotchas- One screencast or animated GIF per major user workflow, in
static/description/ - Per-feature feature flag documentation in
CLAUDE.mdif applicable
Workspace-root documentation:
/Users/gurpreet/Github/Odoo-Modules/CLAUDE.md— common Odoo 19 conventions (already substantial; carries forward)/Users/gurpreet/Github/Odoo-Modules/fusion_accounting/CLAUDE.md— meta-module overview pointing at sub-modules/Users/gurpreet/Github/Odoo-Modules/fusion_accounting/docs/superpowers/specs/— design and plan docs (this doc and future ones)
7.4 Security
- Three groups carry forward from existing module:
group_fusion_accounting_user/manager/admin. Move from current location tofusion_accounting_core/security/security.xmlin Phase 0 - Auto-assignments from Community accounting groups:
account.group_account_user→ fusion User;account.group_account_manager→ fusion Admin (already in place) - Multi-company record rules on every fusion model with
company_id. Add the missing rule onfusion.accounting.sessionin Phase 0 - ACLs in
security/ir.model.access.csvper sub-module, scoped to that sub-module's models only - Approve/reject endpoints continue to use
auth='user'with imperativehas_group()check inside the handler (Odoo has no built-inauth='manager')
7.5 Performance Considerations (Phase 2 in particular)
Odoo Enterprise reports have known performance issues on large databases. The Phase 2 design doc must lock in:
- Denormalized read paths for trial balance and general ledger (materialized aggregations refreshed on
account.movepost) - Lazy-load line detail (drill-down fetches separately, not all at once)
- Cache report runs per
(company_id, period, filter_hash)with invalidation onaccount.move.linewrite/post/cancel - Parallel computation across companies in multi-company reports
- SQL query review (no Python aggregation of large result sets)
7.6 Multi-Company, Multi-Currency, Analytic
Not a separate phase. Woven into every phase's exit criteria:
- Every fusion model with company-scoped data has
company_idfield and a multi-company record rule - Every monetary field pairs with
currency_id analytic_mixin(currently inaccount_accountant/models/analytic_mixin.py): declared infusion_accounting_corevia shared-field-ownership pattern so analytic tags survive Enterprise uninstall
7.7 Localization
Canadian HST is built into the existing AI module (fusion_accounting_ai/services/prompts/domain_prompts.py) and carries forward. Other localizations are deferred:
- Each country-specific tax report becomes a
fusion.account.reportrecord infusion_accounting_reports/data/<country>_<report>.xml - Country-specific chart of accounts: continue to use Odoo's
account.chart.templatemechanism (Community) - New countries are added on demand, per client engagement
7.8 Hosting and Deployment
Out of scope for this design doc; covered in workspace-root operational docs. fusion_accounting deploys to the existing Nexa Odoo infrastructure (per existing fusion_accounting/CLAUDE.md: odoo-westin for Westin Healthcare, equivalents for other clients). Deploy commands in CLAUDE.md carry forward.
8. Acceptance Criteria for This Roadmap
This roadmap is considered "done" (and ready for the first writing-plans session for Phase 0) when:
- The user has reviewed this document and signed off
- No unresolved ambiguity remains in any of the locked decisions (sub-module topology, data preservation, phase order, architecture rules, upgrade workflow)
- The empirical verification test (Section 3.6) is scheduled as part of Phase 0 and not deferred
The next session's deliverable will be the Phase 0 implementation plan (via the writing-plans skill), which will turn Section 4.2 into actionable, testable tasks.
9. Open Questions Deferred to Future Sessions
Items consciously left open here, to be resolved in their respective phase brainstorming sessions:
- Phase 1: exact UI deltas from Odoo's bank rec widget (colour palette, AI confidence badge placement, keyboard shortcuts)
- Phase 2: report definition data format (XML mirroring Odoo vs. our own simpler format)
- Phase 2: caching layer implementation (in-memory vs. Redis vs. PostgreSQL materialized views)
- Phase 4: which non-Canadian tax jurisdictions to seed
- Phase 5: SMS provider integration (Twilio?
mail.smsOdoo built-in?) - Phase 6: depreciation methods to support beyond linear/declining (sum-of-years-digits, units-of-production)
- Phase 7+: which satellites have actual client demand right now
10. References
- Workspace root:
/Users/gurpreet/Github/Odoo-Modules/ - Current AI module:
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting/ - Current AI module conventions:
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting/CLAUDE.md - Workspace conventions:
/Users/gurpreet/Github/Odoo-Modules/CLAUDE.md - WIP code (not continued):
/Users/gurpreet/Github/Odoo-Modules/Work in Progress/fusion_accounting/ - WIP audit report:
/Users/gurpreet/Github/Odoo-Modules/Work in Progress/fusion_accounting/AUDIT_REPORT.md - Pinned Odoo source:
/Users/gurpreet/Github/RePackaged-Odoo/accounting/ - Plan file (this session):
/Users/gurpreet/.cursor/plans/fusion_accounting_takeover_roadmap_c851fdb4.plan.md