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>
This commit is contained in:
@@ -1,26 +1,261 @@
|
|||||||
# Nexa Systems — Chart of Accounts Setup
|
# Nexa Systems — Chart of Accounts Setup
|
||||||
|
|
||||||
Custom Odoo 19 module that configures the chart of accounts, taxes,
|
Odoo 19 module that installs and maintains Nexa Systems Inc's chart of
|
||||||
fiscal positions, analytic plans, and partner records for Nexa Systems Inc.
|
accounts, taxes, fiscal positions, analytic plans, partner records, and
|
||||||
|
seeded standard products.
|
||||||
|
|
||||||
## Install
|
- **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`
|
||||||
|
|
||||||
```
|
---
|
||||||
docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf -d nexamain \
|
|
||||||
-i nexa_coa_setup --no-http --stop-after-init
|
## 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.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update
|
**Deploy module changes** (Mac → server; rsync isn't available, use tar):
|
||||||
|
|
||||||
```
|
```bash
|
||||||
docker exec odoo-nexa-app odoo -c /etc/odoo/odoo.conf -d nexamain \
|
cd /Users/gurpreet/Github/Odoo-Modules && \
|
||||||
-u nexa_coa_setup --no-http --stop-after-init
|
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"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Design reference
|
**Install (first time on a database)**:
|
||||||
|
|
||||||
See `docs/superpowers/specs/2026-05-12-nexa-coa-design.md`.
|
```bash
|
||||||
|
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"
|
||||||
|
```
|
||||||
|
|
||||||
## Safety
|
**Update (after editing XML or hooks)**:
|
||||||
|
|
||||||
Always take a pg_dump BEFORE running `-i` or `-u`. See `docs/superpowers/plans/2026-05-12-nexa-coa-setup.md` Phase 0.
|
```bash
|
||||||
|
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):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 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
|
||||||
|
|||||||
Reference in New Issue
Block a user