Files
Odoo-Modules/nexa_coa_setup/README.md
gsinghpal 2737bc481c docs(nexa_coa_setup): comprehensive operating runbook
Expands README into a full ops guide covering:
- Chart of accounts at a glance (4-digit ranges + examples)
- Standard products catalog with SKUs and income routing
- Fiscal positions with auto-detect rules
- Three analytic plans + their tag conventions
- Install / update / deploy / restore commands
- Yearly close calendar (HST Mar 31, T2 Jun 30, SR&ED prep timeline)
- Common tasks (add account, add product, add analytic, lock FY,
  reclassify invoice, pull SR&ED data)
- Compliance flags (associated-corp SBD sharing, s.15(2) loans,
  transfer pricing, HST cadence triggers, specified-employee SR&ED cap)
- Implementation scripts table (audit reference)
- Open items checklist for future manual follow-ups

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:52:18 -04:00

13 KiB

Nexa Systems — Chart of Accounts Setup

Odoo 19 module that installs and maintains Nexa Systems Inc's chart of accounts, taxes, fiscal positions, analytic plans, partner records, and seeded standard products.

  • Design reference: docs/superpowers/specs/2026-05-12-nexa-coa-design.md
  • Implementation plan: docs/superpowers/plans/2026-05-12-nexa-coa-setup.md
  • Target: odoo-nexa (192.168.1.111), database nexamain

Chart of accounts at a glance

Range Purpose Examples
1010-1090 Cash & bank 1010 Scotia 9309, 1030 BMO, 1040 RBC, 1070 Scotia CC, 1090 Suspense
1100-1130 Accounts receivable 1100 Customers, 1120 Due From Shareholder, 1130 Due From Associated Corps
1210-1230 Tax assets 1210 HST/GST ITC Receivable, 1220 Instalments, 1230 QST Refund
1510-1750 Capital assets + accumulated depreciation 1510 Computers (CCA 50), 1550 Software (CCA 14.1)
2010-2130 Trade AP + sales tax 2010 Vendors, 2110 HST Collected, 2120 QST Collected, 2130 Net Payable
2210-2330 Payroll + corporate tax payable 2210 Fed Tax W/H, 2220 CPP, 2230 EI
2510-2590 Shareholder + intercompany 2510 Due To Shareholder, 2520 Long-term Loan, 2590 Due To Associated
3010-3590 Equity + retained earnings 3010 Common Shares, 3510 RE Current Year, 3590 Dividends Declared
4010-4050 Recurring revenue 4010 SaaS, 4020 Hosting, 4030 Support, 4040 Domain Pass-through, 4050 Setup
4110-4160 Project revenue 4110 Custom Software, 4120 Web App, 4130 Website, 4140 ERP, 4150 Mobile
4210-4230 Services revenue (hourly) 4210 Consulting, 4220 Training, 4230 Tech Support
4310-4320 Reseller revenue 4310 Software resale, 4320 Hardware resale
4910-4930 Revenue adjustments 4910 Discounts, 4920 Returns, 4930 Bad Debt Recovery
5010-5910 Direct costs (COGS) 5010 Cloud Infrastructure, 5210 Sub Labour CA (SR&ED-eligible)
6010-6092 Personnel — T4 employees 6010 Dev salaries (SR&ED proxy base), 6040 Owner salary
6110-6120 Contract labour (non-project) 6110 Canadian, 6120 Foreign
6210-6270 Office & facilities 6210 Rent, 6220 Home Office, 6240 Internet & Phone
6310-6350 Software subs (internal) 6310 Productivity, 6320 Dev Tools, 6340 Security
6410-6450 Marketing & sales 6410 Digital Ads, 6450 Own Website
6510-6540 Professional fees 6510 Legal, 6520 Accounting, 6530 Tax Prep
6610-6650 Insurance 6620 Professional Liability / E&O, 6630 Cyber
6710-6740 Travel & entertainment 6710 Travel, 6720 M&E (50% deductible)
6810-6840 Training & development
6910-6960 Banking & finance 6910 Bank fees, 6920 Stripe/merchant, 6960 Late penalties (non-deductible)
7010-7050 Other 7010 Bad Debt, 7020 Donations, 7030 Fines (non-deductible), 7050 Depreciation

Standard products (seeded)

All 14 starter products auto-route to the right income account via their category. Use as-is, duplicate to create variants, or override prices per customer/quote.

SKU Description Default Income →
SAAS-BASIC SaaS Subscription — Basic per-customer 4010
HOST-S/M/L Hosting Small/Medium/Large $49/$149/$299 mo 4020
SUPPORT-RET Support Retainer (4 hrs/mo) $640 mo 4030
SETUP-FEE Setup / Onboarding Fee $500 4050
DEV-SOFTWARE Custom Software Dev $160 / hr 4110
DEV-WEBAPP Custom Web App Dev $160 / hr 4120
DEV-WEBSITE Custom Website Dev $160 / hr 4130
ERP-IMPL ERP Implementation $175 / hr 4140
CONSULT Consulting & Advisory $200 / hr 4210
TRAINING Training & Workshop $120 / hr 4220
TECH-SUPPORT Technical Support — Hourly $160 / hr 4230
RESALE-SW Software License (template) per-quote 4310

Product file uses noupdate=1 so your price/description edits persist across module updates.


Fiscal positions (automatic tax handling)

Tax routing is determined by customer billing address — you don't pick the tax manually on invoices.

Position Auto-applies to Sales tax
CA — Ontario (Default) ON customers 13% HST
CA — Atlantic NB, NS, PE, NL 15% HST
CA — Quebec QC 5% GST + 9.975% QST
CA — BC BC 5% GST (PST handled per-product if applicable)
CA — Prairies / Territories AB, MB, SK, YT, NT, NU 5% GST
Export — US All US customers 0% (Zero-rated)
Export — International Manual 0% (Zero-rated)
Tax Exempt Manual (cert-holders) 0%

Analytic plans

Three orthogonal tagging plans on every transaction:

Plan Tags Used for
Customer Project One per engagement (e.g. PRJ-2026-WESTIN-ERP) Project P&L, billable-hour realization, WIP
Department DEPT-DEV, DEPT-SALES, DEPT-ADMIN, DEPT-HOSTING Cost allocation, departmental P&L
SR&ED Tag SRED-T4-DEV-SALARY, SRED-SPECIFIED-EMPLOYEE, SRED-CONTRACTOR-CA-ARM-LENGTH, SRED-CONTRACTOR-CA-NON-ARM-LENGTH, SRED-MATERIALS-CONSUMED, SRED-OVERHEAD-PROXY-BASIS, NOT-ELIGIBLE T661 SR&ED filing

Install / update

Always pg_dump first.

ssh odoo-nexa "STAMP=\$(date +%Y%m%d_%H%M%S) && \
  docker exec odoo-nexa-db pg_dump -U odoo -d nexamain -F c -Z 9 \
    > /tmp/nexamain_\${STAMP}.dump"
scp odoo-nexa:/tmp/nexamain_*.dump ~/Backups/odoo-nexa/

Deploy module changes (Mac → server; rsync isn't available, use tar):

cd /Users/gurpreet/Github/Odoo-Modules && \
  tar czf - nexa_coa_setup | \
  ssh odoo-nexa "cd /opt/odoo/custom-addons && \
    sudo rm -rf nexa_coa_setup && sudo tar xzf - && \
    sudo chown -R 1000:1000 nexa_coa_setup"

Install (first time on a database):

ssh odoo-nexa "docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf \
  -d nexamain -i nexa_coa_setup --no-http --stop-after-init"

Update (after editing XML or hooks):

ssh odoo-nexa "docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf \
  -d nexamain -u nexa_coa_setup --no-http --stop-after-init"

Restore from backup (only if catastrophic):

DUMP=~/Backups/odoo-nexa/nexamain_<timestamp>.dump
scp "$DUMP" odoo-nexa:/tmp/
ssh odoo-nexa "docker exec odoo-nexa-db psql -U odoo -d postgres -c \
  'DROP DATABASE nexamain;' && \
  docker exec odoo-nexa-db psql -U odoo -d postgres -c \
  'CREATE DATABASE nexamain OWNER odoo;' && \
  cat $DUMP | docker exec -i odoo-nexa-db pg_restore -U odoo -d nexamain && \
  docker restart odoo-nexa-app"

Yearly close calendar

Nexa is an annual HST filer and an annual T2 filer (fiscal year-end Dec 31).

When What Notes
Jan Confirm asset purchases for the year, assign correct CCA class accounts (1510-1560) Class 50 hardware @ 55% DB (AccII = 82.5% Y1 through 2027). Class 14.1 software @ 100% Y1.
Jan-Feb Pull SR&ED analytic report. Filter on SR&ED Tag analytic plan. Export. Hand off to accountant for T661 prep.
Mar 31 HST/GST annual return due. Line 105 = sum of 2110, Line 108 = sum of 1210 ITC. Pay any net tax + first quarterly instalment if prior year > $3k.
Mar 31 T2 balance due (CCPC). T2 return itself is due June 30.
Mar-Apr Set fiscalyear_lock_date to prior Dec 31 via Accounting > Configuration > Settings > Lock Dates. Prevents accidental back-dating into closed period.
Jun 30 T2 corporate income tax return due. Schedule 23 allocates SBD + SR&ED expenditure limits across Nexa / Westin / Divine. Associated-group calculation.
Quarterly Pay HST instalments (if prior net tax ≥ $3k). Track via 1220 Instalments Paid.
Sep-Dec Yearly review of intercompany pricing (Nexa ↔ Westin / Divine). Transfer-pricing compliance — must be fair market value.

Common tasks

Add a new GL account

  1. Append a <record id="acct_NNNN" model="account.account"> to data/01_account_account.xml using the next free 4-digit code in the relevant range.
  2. Deploy + -u (see Install/Update above).
  3. Verify: psql -d nexamain -c "SELECT code, name FROM ... WHERE code = 'NNNN';"

Add a new product

For ad-hoc / per-customer items, just create via UI:

  • Sales > Products > New → set name, price, Product Category (this drives the income account).
  • The fiscal position auto-applies tax when invoicing.

For new standard catalog items, append to data/11_products.xml (uses noupdate=1 so a re-install won't overwrite UI edits).

Add a new analytic account (project, department, SR&ED tag)

Projects are dynamic — create via UI:

  • Accounting > Configuration > Analytic Accounting > Analytic Accounts > New
  • Code: PRJ-{YYYY}-{CUST}-{SHORTNAME} (e.g. PRJ-2026-WESTIN-ERP-PHASE2)
  • Plan: Customer Project

For departments or new SR&ED tags, edit data/06_account_analytic_account.xml + deploy + -u.

Set the fiscal year lock

Accounting > Configuration > Settings > Lock Dates > set Lock Date to Dec 31 of the prior fiscal year. Requires:

  • All bank statement lines for the period reconciled / cleared / deleted
  • Final accountant adjustments posted

The post_init_hook attempts this automatically at install but tolerates failure (logs a warning instead) — set it manually once the books are clean.

Reclassify a wrongly-categorized historical invoice line

Two ways:

  • In place (no PDF change): SQL UPDATE account_move_line SET account_id = <new_id> WHERE id = <line_id>;. Used in scripts/fix_invoice_1127.py and scripts/reclass_historical_411000.py as references.
  • Proper way (audit-trail clean): Reset invoice to draft, edit, re-post. Requires admin permissions + un-reconciling any payment first.

Pull SR&ED data at year-end

-- Eligible salaries summary
SELECT aa.code, aa.name, ROUND(SUM(aml.debit - aml.credit)::numeric, 2) AS amount
FROM account_move_line aml
JOIN account_analytic_line aal ON aal.move_line_id = aml.id
JOIN account_analytic_account aa ON aa.id = aal.account_id
JOIN account_analytic_plan ap ON ap.id = aa.plan_id
WHERE ap.name = 'SR&ED Tag'
  AND aml.date BETWEEN '2026-01-01' AND '2026-12-31'
  AND aa.code <> 'NOT-ELIGIBLE'
GROUP BY aa.code, aa.name
ORDER BY aa.code;

Plus pull eligible contractor invoices: customer = Nexa, vendor in Canada (arm's length), tagged SRED-CONTRACTOR-CA-ARM-LENGTH.


Compliance flags (do not forget)

  • Associated corporations: Westin Healthcare Inc + Divine Mobility Inc share Nexa's $500k SBD limit and $3M SR&ED expenditure limit. Annual Schedule 23 filing allocates these across the group.
  • Subsection 15(2): Shareholder loans outstanding > 1 year past fiscal year-end become taxable to Gurpreet personally. Track 2510 (short-term) vs 2520 (long-term commercial loan).
  • Transfer pricing (s.247): Nexa invoicing Westin / Divine must be at fair market value. Document the methodology; penalty is 10% of any adjustment.
  • GST/HST cadence: currently annual. Once Nexa-only revenue clears $1.5M, CRA auto-moves you to quarterly filing.
  • QC QST registration: required if Nexa has any QC customers and revenue > $30k. Separate from federal CRA registration.
  • Quick Method GST/HST: likely unavailable — the $400k threshold is checked against the associated-group total (Nexa + Westin + Divine combined).
  • Specified employee SR&ED cap: Gurpreet's SR&ED-eligible salary is capped at 75% of basic salary (no bonuses), and only counts if paid via T4 payroll.

Implementation scripts (one-shot, idempotent)

All under scripts/ — preserved for audit reference; not run by the module itself. Already executed against prod.

Script What it did
fix_gl_codes.py Renumbered 119100/119900 → 115200/115900 and 511105 → 511100
convert_to_4digit.py Renumbered 128 Nexa accounts from 6-digit l10n_ca style to clean 4-digit
convert_l10nca_to_4digit.py Renumbered 12 retained l10n_ca legacy accounts (Bank/AR/AP/HST) to 4-digit
fix_invoice_1127.py Reclassified Entech invoice 1127's 17 lines + reassigned 14 product templates to proper categories
reclass_historical_411000.py Batch-reclassified 200 historical invoice lines from legacy 411000 by keyword rules
test_invoices.py End-to-end invoice tests (ON HST, US zero-rated, QC GST+QST, intercompany)

Open items (manual follow-ups)

  • Set fiscal year lock at 2025-12-31 once unreconciled bank statement lines are cleared
  • Verify HST# format display on customer invoice PDFs (stored as 741224877RT0001; some Canadian accountants prefer 741224877 RT0001 with space — change via UI if needed)
  • When first T4 employee is hired: configure payroll (Wagepoint / ADP / Odoo Payroll), set up source deduction journal automation, decide on payroll cadence
  • When first USD invoice arrives: add USD bank account (1020 reserved), enable currency_rate_live cron, configure multi-currency on company
  • When asset count grows: install custom CCA module OR keep maintaining CCA schedule via accountant's spreadsheet