Files
Odoo-Modules/fusion_accounting/docs/superpowers/specs/2026-04-18-fusion-accounting-enterprise-takeover-roadmap-design.md
gsinghpal 956678dd27 docs(fusion_accounting): roadmap design for Enterprise takeover
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
2026-04-18 20:55:22 -04:00

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's AUDIT_REPORT.md) determined to be near-verbatim copies of Odoo Enterprise. The WIP code is not continued. Its __manifest__.py is 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_reports can absorb V20 changes without touching fusion_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 _ai only

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:

  1. Detects which Enterprise modules are installed
  2. For each detected module, checks the corresponding fusion module is also installed (and prompts to install if missing)
  3. Shows a preview: row counts per Enterprise table that will be migrated, listing target fusion table for each
  4. On confirm, runs INSERT INTO fusion_<table> SELECT ... FROM <enterprise_table> for each migration step, preserving primary keys and ir.model.data xml_ids
  5. Generates a migration report (record counts, any rows that failed validation, warnings)
  6. Marks each Enterprise table as "migrated" via an ir.config_parameter flag (fusion_accounting.migration.<module>.completed)
  7. 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:

  1. Provision a throwaway Odoo 19 Enterprise instance
  2. Install full Enterprise accounting stack
  3. 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_ids populated
    • 3 fiscal year closings
    • 10 asset records with depreciation history
    • 2 budgets with actuals
    • Multi-currency journal entries
    • 1 cash-basis tax move
  4. Take pg_dump snapshot
  5. Uninstall Enterprise modules in dep-safe order without running the migration wizard (this is the worst-case test)
  6. Diff schema and row counts before and after
  7. Document findings in docs/superpowers/specs/2026-04-18-empirical-uninstall-test-results.md
  8. 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_dump of 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/ into fusion_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 with depends = ['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. Replace account_accountant, account_reports, account_followup with account (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.py with shared-field declarations (Section 3.3)
  • Create fusion_accounting_migration/ shell: empty wizard, safety guard scaffold (no migrations yet)
  • Create tools/check_odoo_diff.sh script that diffs two pinned Odoo source snapshots and outputs a categorized change list
  • Move security groups: group_fusion_accounting_user/manager/admin move from current to fusion_accounting_core/security/. Multi-company record rule on fusion.accounting.session added (currently missing per existing CLAUDE.md "Known Issues")
  • Create per-sub-module CLAUDE.md (factor common rules from existing fusion_accounting/CLAUDE.md) and UPGRADE_NOTES.md template
  • Run the empirical verification test (Section 3.6) on a throwaway V19 Enterprise instance
  • CI: GitHub Actions or gitea workflow that runs pytest per 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_data updates; 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 of account_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.py containing the matching algorithm (FIFO, partial reconcile, write-off lines, exchange-rate diff posting, tax splits). Original implementation against documented requirements. Operates on Community account.partial.reconcile
  • models/fusion_reconcile_model.py extending Community account.reconcile.model with auto-rules, partner mapping, journal mapping. Shared-field ownership for created_automatically
  • wizards/auto_reconcile_wizard.py clean-room rewrite of account_accountant/wizard/account_auto_reconcile_wizard.py
  • wizards/reconcile_wizard.py clean-room rewrite of account_accountant/wizard/account_reconcile_wizard.py
  • views/bank_rec_widget_views.xml defines the action that opens the OWL widget; views/account_reconcile_model_views.xml for rule editing
  • Menu: "Bank Reconciliation" under fusion accounting menu, with feature-gate (hidden if account_accountant installed)
  • 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_invoices get refactored to call fusion's bank rec engine via fusion_accounting_ai/services/adapters/bank_rec_adapter.py. The Tier 3 tools create_vendor_bill, register_bill_payment, create_expense_entry keep their existing logic (they write to Community account.move)
  • Migration: wizard validates account.partial.reconcile row 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.reconcile rows
    • 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.py defining fusion.account.report and fusion.account.report.line. Generic engine that takes a report definition (sections, filters, computation rules) and produces report rows from account.move.line data. Original computation kernel — does not copy account_reports's account_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/ mirrors account_reports/static/src/components/ — filters bar, comparison toggle, drill-down, foldable sections, footnotes
  • PDF export: QWeb templates in report/ mirror Odoo's data/pdf_export_templates.xml and data/customer_reports_pdf_export_templates.xml. Asset bundle fusion_accounting_reports.assets_pdf_export defined in manifest
  • Performance: denormalized read paths for trial balance and general ledger (materialized aggregations refreshed on account.move post). Drill-down lazy-loads line detail. Per-(company, period, filter_hash) cache invalidated on account.move.line write
  • 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_question refactored via reports_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 account and 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 in models/account_journal.py extending Community account.journal with kanban-state fields (counts, totals, action buttons). Original computation; mirror UI
  • models/fusion_fiscal_year.py defining fusion.fiscal.year (replaces account.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 Community account.lock_exception model (verified at account/models/account_lock_exception.py)
  • Digest tile contributions: extend mail.digest with 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 to fusion_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.report records
  • Generic tax report (data/generic_tax_report.xml) with country-specific overrides
  • Canadian HST: unify the existing HST workflow in fusion_accounting_ai (currently in services/prompts/domain_prompts.py and tool functions) with the new tax report engine. The existing find_missing_itc_bills, get_overdue_invoices, etc. tools call into the tax report
  • fusion.account.return model (replaces account.return from account_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_reports wizards
  • 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 (replaces account_followup.followup.line)
  • models/res_partner.py extends res.partner with follow-up level, last reminder date, dunning history
  • models/account_move.py extends account.move with 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.py for manual sends; cron for automatic
  • Follow-up report (PDF): clean-room template
  • AI integration: fusion_accounting_ai adds tools draft_followup_message_for_partner, send_followup_to_overdue_partners calling the followup engine via adapter
  • Migration: wizard copies account_followup.followup.line and partner-level follow-up state into fusion.followup.line and 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_followup preserves history

4.8 Phase 6 — Assets + Budgets

Scope:

  • Create fusion_accounting_assets/ sub-module
    • models/fusion_asset.py (replaces account.asset)
    • models/fusion_asset_group.py (replaces account.asset.group)
    • Depreciation engine: linear, declining, custom schedules. Original implementation
    • wizards/asset_modify.py for revaluation, sale, disposal — clean-room rewrite
    • Asset register report integrates with Phase 2 reports engine
    • Migration wizard copies account.asset rows + line links on moves
  • Create fusion_accounting_budget/ sub-module
    • models/fusion_budget.py (replaces budget.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 amortization
  • fusion_accounting_check_printing — check printing
  • fusion_accounting_batch_payment — batch payments
  • fusion_accounting_3way_match — purchase 3-way match
  • fusion_accounting_edi — UBL/CII e-invoicing
  • fusion_accounting_sepa — SEPA direct debit + credit transfer
  • fusion_accounting_saft — SAFT export
  • fusion_accounting_intrastat — intrastat report
  • fusion_accounting_iso20022 — ISO 20022 payment files
  • fusion_accounting_online_sync — online bank sync (Yodlee/Plaid integration)

4.10 Per-Phase Deliverables (uniform)

Each phase produces:

  1. A separate design document in docs/superpowers/specs/YYYY-MM-DD-fusion-accounting-phase-N-*-design.md (brainstormed in its own session)
  2. A separate implementation plan via the writing-plans skill
  3. Working code with passing tests
  4. Entry in the sub-module's UPGRADE_NOTES.md listing Odoo source files referenced and intentional deltas
  5. Coverage in fusion_accounting_migration if the phase replaces an Enterprise data-bearing model
  6. Manual QA checklist (install, migrate, smoke, uninstall) committed to the sub-module
  7. Update to the meta-module __manifest__.py adding the new sub-module to its depends

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:

  1. Replace (default when Enterprise absent): fusion menus visible, fusion views primary, fusion workflows active
  2. Augment (default when Enterprise present): fusion menus hidden, fusion widgets disabled, fusion AI module continues to call Enterprise APIs via adapters
  3. 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'] plus external_dependencies for anthropic, openai
  • Every other fusion_accounting_*/__manifest__.py: depends = ['fusion_accounting_core'] plus fusion siblings as needed (e.g., _followup depends 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 string attribute on <search> or <group>; group-by filters need domain="[]"; <separator/> before <group>
  • OWL client actions: static props = ["*"] (accept any), not static props = [] (accept none)
  • OWL rich HTML: markup() and t-out unreliable in Odoo 19; use onMounted + onPatched + direct innerHTML
  • Cron safe_eval: no import statements; use datetime.datetime.now() not from datetime import datetime
  • read_group() deprecated → use _read_group()
  • ir_config_parameter Selection field migrations: stored DB value must match new options or Settings page crashes
  • implied_ids on groups only applies to newly-added users — existing users need SQL backfill
  • TransientModel in controllers: use .new({...}) not .create({...})
  • HTTP routes: type="jsonrpc", not type="json" (deprecated)
  • res.config.settings: only boolean/integer/float/char/selection/many2one/datetime; no Date fields
  • res.groups: no users field, no category_id field
  • 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 in web.assets_backend
  • Card styling: don't rely on var(--bs-border-color) or var(--bs-body-bg); use Odoo's kanban explicit-hex pattern with custom-property tokens
  • Dark mode: branch on $o-webclient-color-scheme at 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.0 for V19, first release)
  • Bump XX on Odoo version change (V19 → V20 → V21)
  • Bump x on major feature additions within an Odoo version
  • Bump y on minor features and bug fixes
  • Bump z on hotfixes
  • Git branches: main-v19, main-v20, etc. Each client deployment is pinned to one branch
  • Release tags: <sub-module>/v19.0.1.0.0 per 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:

  1. Add the snapshot folder
  2. 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 -p1 operations)
    • 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
  3. Tag releases on main-v<N+1> branch
  4. 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/ and static/src/components/ and report/[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_dump taken before upgrade, restore fusion_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_approval placeholder swap on approve/reject
  • Rich-text chat output via mdToHtml() and innerHTML injection
  • Interactive fusion-table blocks for actionable results
  • Session ownership / multi-company record rules (the fusion.accounting.session rule 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 assistance
  • UPGRADE_NOTES.md — Odoo version porting log
  • README.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.md if 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 to fusion_accounting_core/security/security.xml in 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 on fusion.accounting.session in Phase 0
  • ACLs in security/ir.model.access.csv per sub-module, scoped to that sub-module's models only
  • Approve/reject endpoints continue to use auth='user' with imperative has_group() check inside the handler (Odoo has no built-in auth='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.move post)
  • Lazy-load line detail (drill-down fetches separately, not all at once)
  • Cache report runs per (company_id, period, filter_hash) with invalidation on account.move.line write/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_id field and a multi-company record rule
  • Every monetary field pairs with currency_id
  • analytic_mixin (currently in account_accountant/models/analytic_mixin.py): declared in fusion_accounting_core via 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.report record in fusion_accounting_reports/data/<country>_<report>.xml
  • Country-specific chart of accounts: continue to use Odoo's account.chart.template mechanism (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.sms Odoo 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