From d6513ff7abbe053c0b21634dfc5f4e847edad08c Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 12 May 2026 18:39:24 -0400 Subject: [PATCH] feat(nexa_coa_setup): module skeleton with hooks stub Co-Authored-By: Claude Sonnet 4.6 --- nexa_coa_setup/README.md | 26 ++++++++++ nexa_coa_setup/__init__.py | 2 + nexa_coa_setup/__manifest__.py | 38 ++++++++++++++ nexa_coa_setup/data/01_account_account.xml | 5 ++ nexa_coa_setup/data/02_account_journal.xml | 5 ++ nexa_coa_setup/data/03_account_tax.xml | 5 ++ .../data/04_account_fiscal_position.xml | 5 ++ .../data/05_account_analytic_plan.xml | 5 ++ .../data/06_account_analytic_account.xml | 5 ++ nexa_coa_setup/data/07_product_category.xml | 5 ++ .../data/08_res_partner_category.xml | 5 ++ nexa_coa_setup/data/09_res_partner.xml | 5 ++ .../data/10_account_reconcile_model.xml | 5 ++ nexa_coa_setup/hooks.py | 50 +++++++++++++++++++ nexa_coa_setup/models/__init__.py | 1 + nexa_coa_setup/security/ir.model.access.csv | 1 + 16 files changed, 168 insertions(+) create mode 100644 nexa_coa_setup/README.md create mode 100644 nexa_coa_setup/__init__.py create mode 100644 nexa_coa_setup/__manifest__.py create mode 100644 nexa_coa_setup/data/01_account_account.xml create mode 100644 nexa_coa_setup/data/02_account_journal.xml create mode 100644 nexa_coa_setup/data/03_account_tax.xml create mode 100644 nexa_coa_setup/data/04_account_fiscal_position.xml create mode 100644 nexa_coa_setup/data/05_account_analytic_plan.xml create mode 100644 nexa_coa_setup/data/06_account_analytic_account.xml create mode 100644 nexa_coa_setup/data/07_product_category.xml create mode 100644 nexa_coa_setup/data/08_res_partner_category.xml create mode 100644 nexa_coa_setup/data/09_res_partner.xml create mode 100644 nexa_coa_setup/data/10_account_reconcile_model.xml create mode 100644 nexa_coa_setup/hooks.py create mode 100644 nexa_coa_setup/models/__init__.py create mode 100644 nexa_coa_setup/security/ir.model.access.csv diff --git a/nexa_coa_setup/README.md b/nexa_coa_setup/README.md new file mode 100644 index 00000000..09a233ee --- /dev/null +++ b/nexa_coa_setup/README.md @@ -0,0 +1,26 @@ +# Nexa Systems — Chart of Accounts Setup + +Custom Odoo 19 module that configures the chart of accounts, taxes, +fiscal positions, analytic plans, and partner records for Nexa Systems Inc. + +## Install + +``` +docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf -d nexamain \ + -i nexa_coa_setup --no-http --stop-after-init +``` + +## Update + +``` +docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf -d nexamain \ + -u nexa_coa_setup --no-http --stop-after-init +``` + +## Design reference + +See `docs/superpowers/specs/2026-05-12-nexa-coa-design.md`. + +## Safety + +Always take a pg_dump BEFORE running `-i` or `-u`. See `docs/superpowers/plans/2026-05-12-nexa-coa-setup.md` Phase 0. diff --git a/nexa_coa_setup/__init__.py b/nexa_coa_setup/__init__.py new file mode 100644 index 00000000..cc6b6354 --- /dev/null +++ b/nexa_coa_setup/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook diff --git a/nexa_coa_setup/__manifest__.py b/nexa_coa_setup/__manifest__.py new file mode 100644 index 00000000..52b4e87a --- /dev/null +++ b/nexa_coa_setup/__manifest__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 +{ + "name": "Nexa Systems — Chart of Accounts Setup", + "version": "19.0.1.0.0", + "category": "Accounting/Localizations/Chart of Accounts", + "summary": "Custom CoA, taxes, fiscal positions, analytic plans, and intercompany partner setup for Nexa Systems Inc.", + "author": "Nexa Systems Inc.", + "website": "https://nexasystems.ca", + "license": "OPL-1", + "depends": [ + "account", + "account_accountant", + "l10n_ca", + "analytic", + "sale_management", + "purchase", + "sale_subscription", + ], + "data": [ + "security/ir.model.access.csv", + "data/01_account_account.xml", + "data/02_account_journal.xml", + "data/03_account_tax.xml", + "data/04_account_fiscal_position.xml", + "data/05_account_analytic_plan.xml", + "data/06_account_analytic_account.xml", + "data/07_product_category.xml", + "data/08_res_partner_category.xml", + "data/09_res_partner.xml", + "data/10_account_reconcile_model.xml", + ], + "post_init_hook": "post_init_hook", + "installable": True, + "application": False, + "auto_install": False, +} diff --git a/nexa_coa_setup/data/01_account_account.xml b/nexa_coa_setup/data/01_account_account.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/01_account_account.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/02_account_journal.xml b/nexa_coa_setup/data/02_account_journal.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/02_account_journal.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/03_account_tax.xml b/nexa_coa_setup/data/03_account_tax.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/03_account_tax.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/04_account_fiscal_position.xml b/nexa_coa_setup/data/04_account_fiscal_position.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/04_account_fiscal_position.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/05_account_analytic_plan.xml b/nexa_coa_setup/data/05_account_analytic_plan.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/05_account_analytic_plan.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/06_account_analytic_account.xml b/nexa_coa_setup/data/06_account_analytic_account.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/06_account_analytic_account.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/07_product_category.xml b/nexa_coa_setup/data/07_product_category.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/07_product_category.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/08_res_partner_category.xml b/nexa_coa_setup/data/08_res_partner_category.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/08_res_partner_category.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/09_res_partner.xml b/nexa_coa_setup/data/09_res_partner.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/09_res_partner.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/data/10_account_reconcile_model.xml b/nexa_coa_setup/data/10_account_reconcile_model.xml new file mode 100644 index 00000000..7faba267 --- /dev/null +++ b/nexa_coa_setup/data/10_account_reconcile_model.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nexa_coa_setup/hooks.py b/nexa_coa_setup/hooks.py new file mode 100644 index 00000000..28a12ed6 --- /dev/null +++ b/nexa_coa_setup/hooks.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +import logging + +_logger = logging.getLogger(__name__) + + +def post_init_hook(env): + """Imperative one-shot operations after module data is loaded. + + Each helper is idempotent — safe to re-run on -u. + """ + _logger.info("nexa_coa_setup: post_init_hook starting") + _normalize_company_hst_number(env) + _archive_unused_l10n_ca_accounts(env) + _rename_legacy_accounts(env) + _lock_fiscal_year_2025(env) + _logger.info("nexa_coa_setup: post_init_hook complete") + + +def _normalize_company_hst_number(env): + """Convert '741224877' to '741224877 RT0001' if not already in full form.""" + company = env.ref("base.main_company", raise_if_not_found=False) + if not company: + return + vat = (company.partner_id.vat or "").strip() + if vat == "741224877": + company.partner_id.vat = "741224877 RT0001" + _logger.info("nexa_coa_setup: normalized HST# to '741224877 RT0001'") + + +def _archive_unused_l10n_ca_accounts(env): + """Stub — filled in Phase 4. Archives ~370 unused accounts.""" + pass + + +def _rename_legacy_accounts(env): + """Stub — filled in Phase 4. Renames the 14xx/15xx legacy accounts.""" + pass + + +def _lock_fiscal_year_2025(env): + """Set fiscalyear_lock_date = 2025-12-31 on main company.""" + from datetime import date + company = env.ref("base.main_company", raise_if_not_found=False) + if not company: + return + target = date(2025, 12, 31) + if not company.fiscalyear_lock_date or company.fiscalyear_lock_date < target: + company.fiscalyear_lock_date = target + _logger.info("nexa_coa_setup: fiscalyear_lock_date set to 2025-12-31") diff --git a/nexa_coa_setup/models/__init__.py b/nexa_coa_setup/models/__init__.py new file mode 100644 index 00000000..b8899ea4 --- /dev/null +++ b/nexa_coa_setup/models/__init__.py @@ -0,0 +1 @@ +# no custom models — placeholder for future extensions diff --git a/nexa_coa_setup/security/ir.model.access.csv b/nexa_coa_setup/security/ir.model.access.csv new file mode 100644 index 00000000..97dd8b91 --- /dev/null +++ b/nexa_coa_setup/security/ir.model.access.csv @@ -0,0 +1 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink