diff --git a/nexa_coa_setup/data/01_account_account.xml b/nexa_coa_setup/data/01_account_account.xml index 9325387a..0125aae2 100644 --- a/nexa_coa_setup/data/01_account_account.xml +++ b/nexa_coa_setup/data/01_account_account.xml @@ -14,99 +14,99 @@ these accounts were at codes 119100/119900 — codes updated in-place via scripts/fix_gl_codes.py without rewriting ir.model.data. --> - 115200 + 1120 Due From Shareholder — Gurpreet asset_current - 115900 + 1130 Due From Associated Corporations asset_current - 118100 + 1210 HST/GST Input Tax Credit (ITC) Receivable asset_current - 118200 + 1220 HST/GST Instalments Paid asset_current - 118300 + 1230 QST Input Tax Refund Receivable asset_current - 151100 + 1510 Computer Hardware & Equipment (CCA Class 50) asset_fixed - 151200 + 1520 Office Furniture & Equipment (CCA Class 8) asset_fixed - 151300 + 1530 Vehicles (CCA Class 10/10.1) asset_fixed - 151400 + 1540 Leasehold Improvements (CCA Class 13) asset_fixed - 151500 + 1550 Acquired Software & Intangibles (CCA Class 14.1) asset_fixed - 151600 + 1560 Tools & Small Equipment <$500 (CCA Class 12) asset_fixed - 154100 + 1710 Acc. Depreciation — Computer Hardware asset_fixed - 154200 + 1720 Acc. Depreciation — Office Furniture asset_fixed - 154300 + 1730 Acc. Depreciation — Vehicles asset_fixed - 154400 + 1740 Acc. Depreciation — Leasehold Improvements asset_fixed - 154500 + 1750 Acc. Depreciation — Acquired Software asset_fixed @@ -116,75 +116,75 @@ - 213100 + 2110 HST/GST Collected on Sales liability_current - 213500 + 2120 QST Collected on Sales liability_current - 214100 + 2130 Net HST/GST Payable liability_current - 215100 + 2210 Source Deductions Payable — Federal Tax liability_current - 215200 + 2220 Source Deductions Payable — CPP liability_current - 215300 + 2230 Source Deductions Payable — EI liability_current - 216100 + 2310 Corporate Income Tax — Federal Payable liability_current - 216200 + 2320 Corporate Income Tax — Provincial Payable liability_current - 216300 + 2330 Corporate Tax Instalments Paid asset_current - 221100 + 2510 Due To Shareholder — Gurpreet (short-term) liability_current - 221200 + 2520 Shareholder Loan — Gurpreet (long-term) liability_non_current - 222900 + 2590 Due To Associated Corporations liability_current @@ -195,37 +195,37 @@ - 311100 + 3010 Share Capital — Common Shares equity - 311200 + 3020 Share Capital — Preferred Shares equity - 311300 + 3030 Contributed Surplus equity - 321100 + 3510 Retained Earnings — Current Year equity - 321200 + 3520 Retained Earnings — Prior Years equity - 321900 + 3590 Dividends Declared equity @@ -235,115 +235,115 @@ - 411100 + 4010 SaaS Subscription Revenue income - 411200 + 4020 Hosting & Infrastructure Revenue income - 411300 + 4030 Support & Maintenance Contracts Revenue income - 411400 + 4040 Domain/SSL/Renewal Pass-through Revenue income - 411500 + 4050 Setup / Onboarding Fees Revenue income - 412100 + 4110 Custom Software Development Revenue income - 412200 + 4120 Custom Web Application Development Revenue income - 412300 + 4130 Custom Website Development Revenue income - 412400 + 4140 ERP Implementation & Customization Revenue income - 412500 + 4150 Mobile App Development Revenue income - 412600 + 4160 Business App / Integration Revenue income - 413100 + 4210 Consulting & Advisory Revenue income - 413200 + 4220 Training & Workshops Revenue income - 413300 + 4230 Technical Support — Per-incident / Hourly Revenue income - 414100 + 4310 Third-party Software Resale Revenue income - 414200 + 4320 Hardware Resale Revenue income - 419100 + 4910 Sales Discounts income - 419200 + 4920 Sales Returns & Refunds income - 419300 + 4930 Bad Debt Recovery income_other @@ -357,103 +357,103 @@ Cloud Infrastructure now claims the clean 511100 code. XMLID acct_511105 preserved from initial install. --> - 511100 + 5010 Cloud Infrastructure (AWS, Hetzner, OVH, DigitalOcean, Linode) expense_direct_cost - 511110 + 5020 CDN & Edge Services (Cloudflare, Fastly) expense_direct_cost - 511120 + 5030 Backup & Storage Services expense_direct_cost - 511130 + 5040 Database & Backend Services (Supabase, hosted Postgres, Redis) expense_direct_cost - 511140 + 5050 Monitoring & Observability (customer-facing only) expense_direct_cost - 511150 + 5060 SSL Certificates & Domains (wholesale for resale) expense_direct_cost - 511160 + 5070 DNS & Email Hosting (wholesale for resale) expense_direct_cost - 511200 + 5110 Third-party API Costs (Twilio, SendGrid, OpenAI) expense_direct_cost - 511210 + 5120 Per-customer Licensing & Royalties expense_direct_cost - 512100 + 5210 Subcontracted Labour — Canadian (T4A) — SR&ED-eligible expense_direct_cost - 512110 + 5220 Subcontracted Labour — Foreign — NOT SR&ED-eligible expense_direct_cost - 512200 + 5230 Project-specific Software & Licenses expense_direct_cost - 512300 + 5240 Project Travel & Onsite (rebilled) expense_direct_cost - 512400 + 5250 Project Hardware (passed through) expense_direct_cost - 513100 + 5310 Cost of Software Resold expense_direct_cost - 513200 + 5320 Cost of Hardware Resold expense_direct_cost - 519100 + 5910 COGS Adjustments / Write-offs expense_direct_cost @@ -463,349 +463,349 @@ - 611100 + 6010 Salaries & Wages — Development (SR&ED-eligible) expense - 611200 + 6020 Salaries & Wages — Sales & Marketing expense - 611300 + 6030 Salaries & Wages — Admin & Operations expense - 611400 + 6040 Salary — Shareholder/Officer (Gurpreet) expense - 611500 + 6050 Employer CPP / QPP Contributions expense - 611600 + 6060 Employer EI Premiums expense - 611700 + 6070 Employer Health Tax (EHT/QHST) expense - 611800 + 6080 WCB / WSIB Premiums expense - 611900 + 6090 Employee Benefits (health, dental, group) expense - 611950 + 6091 Bonuses & Incentives expense - 611960 + 6092 Vacation Pay Accrual expense - 612100 + 6110 Contract Labour — Canadian (admin/marketing/freelance) expense - 612200 + 6120 Contract Labour — Foreign expense - 621100 + 6210 Rent — Commercial Office expense - 621200 + 6220 Home Office — Business Portion expense - 621300 + 6230 Utilities — Commercial expense - 621400 + 6240 Internet & Phone — Business expense - 621500 + 6250 Office Supplies & Consumables expense - 621600 + 6260 Cleaning & Maintenance expense - 621700 + 6270 Office Snacks & Refreshments expense - 631100 + 6310 Software — Productivity (M365, Slack, Notion, Linear, GitHub) expense - 631200 + 6320 Software — Development Tools (Cursor, Figma, IDEs) expense - 631300 + 6330 Software — Internal Infrastructure expense - 631400 + 6340 Software — Security & IT expense - 631500 + 6350 Software — Sales & Marketing expense - 641100 + 6410 Advertising — Digital Ads expense - 641200 + 6420 Advertising — Content / SEO expense - 641300 + 6430 Trade Shows & Conferences expense - 641400 + 6440 Promotional Items / Branded Swag expense - 641500 + 6450 Website — Own (nexasystems.ca) expense - 651100 + 6510 Legal Fees — General expense - 651200 + 6520 Accounting & Bookkeeping expense - 651300 + 6530 Tax Preparation (T2, T1, GST/HST) expense - 651400 + 6540 Business Consulting expense - 661100 + 6610 Insurance — Commercial General Liability expense - 661200 + 6620 Insurance — Professional Liability / E&O expense - 661300 + 6630 Insurance — Cyber Liability expense - 661400 + 6640 Insurance — Property expense - 661500 + 6650 Insurance — Directors & Officers expense - 671100 + 6710 Travel — Flights, Hotels, Ground Transport expense - 671200 + 6720 Meals & Entertainment — 50% Deductible expense - 671300 + 6730 Vehicle — Operating (gas, insurance, repairs, parking) expense - 671400 + 6740 Mileage Reimbursement — Personal Vehicle expense - 681100 + 6810 Conferences & Seminars (registration) expense - 681200 + 6820 Courses & Certifications expense - 681300 + 6830 Books & Publications expense - 681400 + 6840 Professional Memberships & Dues expense - 691100 + 6910 Bank Service Charges expense - 691200 + 6920 Merchant Processing Fees (Stripe, PayPal, Square) expense - 691300 + 6930 Wire Transfer & FX Fees expense - 691400 + 6940 Interest Expense — Bank Loans / LOC expense - 691500 + 6950 Interest Expense — Credit Cards expense - 691600 + 6960 Late Payment Penalties — Non-deductible expense - 699100 + 7010 Bad Debt Expense expense - 699200 + 7020 Donations & Sponsorships (deductible) expense - 699300 + 7030 Penalties & Fines — Non-deductible expense - 699400 + 7040 Realized FX Losses expense - 699500 + 7050 Depreciation / CCA Expense expense diff --git a/nexa_coa_setup/hooks.py b/nexa_coa_setup/hooks.py index 7554c885..2a562911 100644 --- a/nexa_coa_setup/hooks.py +++ b/nexa_coa_setup/hooks.py @@ -232,18 +232,18 @@ def _delete_unused_accounts(env): # at the new accounts, so when an invoice creates tax journal items they hit # 118100 (ITC) and 213100 (HST collected) instead of the archived legacy ones. _TAX_REPARTITION_REMAP = { - # ITC / receivable side - "118100.OLD": "118100", - "118200.OLD": "118300", # PST/QST receivable → QST refund receivable - "118300.OLD": "118100", - "118400": "118100", # 14% HST receivable - "118500": "118100", # 15% HST receivable - # Payable / collected side - "231000": "213100", # GST to pay - "232000": "213500", # PST/QST to pay - "233000": "213100", # HST 13% to pay - "234000": "213100", # HST 14% to pay - "235000": "213100", # HST 15% to pay + # ITC / receivable side → Nexa 1210 HST/GST ITC Receivable (or 1230 QST refund) + "118100.OLD": "1210", + "118200.OLD": "1230", + "118300.OLD": "1210", + "118400": "1210", + "118500": "1210", + # Payable / collected side → Nexa 2110 HST/GST Collected (or 2120 QST collected) + "231000": "2110", + "232000": "2120", + "233000": "2110", + "234000": "2110", + "235000": "2110", } @@ -483,20 +483,20 @@ def _archive_unused_l10n_ca_accounts(env): # accountant-driven reconciliation. _LEGACY_RENAMES = [ # (code, new_name, archive_after) - ("1400", "(LEGACY) Transferred to Gurpreet — re-class to 221100", True), - ("1505", "(LEGACY) Sent to India — re-class to 612200", True), + ("1400", "(LEGACY) Transferred to Gurpreet — re-class to 2510", True), + ("1505", "(LEGACY) Sent to India — re-class to 6120", True), ("1580", "(LEGACY) Transferred to Westin — Westin is now a partner", True), ("1590", "(LEGACY) Transferred to Divine — Divine is now a partner", True), ("1600", "(LEGACY) Transferred to Manpreet — non-related; archive", True), - ("1500", "(LEGACY) Food & Entertainment — re-class to 671200", True), - ("1501", "(LEGACY) Office Expenses — re-class to 621500", True), - ("411000", "(LEGACY) Inside Sales — re-class to 412xxx specific lines", True), + ("1500", "(LEGACY) Food & Entertainment — re-class to 6720", True), + ("1501", "(LEGACY) Office Expenses — re-class to 6250", True), + ("411000", "(LEGACY) Inside Sales — re-class to 4xxx specific lines", True), ("412000", "(LEGACY) Harmonized Provinces Sales — handled by tax codes", True), ("413000", "(LEGACY) Non-Harmonized Provinces Sales — handled by tax", True), ("414000", "(LEGACY) International Sales — handled by Zero-rated Export", True), ("12000", "(LEGACY) Abdul & Future Mobility — use partner subledger", True), ("12001", "(LEGACY) MSI Account — use partner subledger", True), - ("110010", "(LEGACY) Bank Fee — re-class to 691100", True), + ("110010", "(LEGACY) Bank Fee — re-class to 6910", True), ] diff --git a/nexa_coa_setup/scripts/convert_to_4digit.py b/nexa_coa_setup/scripts/convert_to_4digit.py new file mode 100644 index 00000000..50de14bf --- /dev/null +++ b/nexa_coa_setup/scripts/convert_to_4digit.py @@ -0,0 +1,171 @@ +"""Map current Nexa CoA codes (6-digit) to a clean 4-digit scheme. +Run on prod via odoo-shell. Updates account_account.code in place.""" + +# (current_code, new_code, expected_name_substring_for_safety) +CODE_MAP = [ + # 1xxx ASSETS + ("115200", "1120", "Due From Shareholder"), + ("115900", "1130", "Due From Associated Corporations"), + ("118100", "1210", "Input Tax Credit"), + ("118200", "1220", "Instalments Paid"), + ("118300", "1230", "QST Input Tax Refund"), + ("151100", "1510", "Computer Hardware"), + ("151200", "1520", "Office Furniture"), + ("151300", "1530", "Vehicles"), + ("151400", "1540", "Leasehold Improvements"), + ("151500", "1550", "Acquired Software"), + ("151600", "1560", "Tools"), + ("154100", "1710", "Acc. Depreciation — Computer"), + ("154200", "1720", "Acc. Depreciation — Office"), + ("154300", "1730", "Acc. Depreciation — Vehicles"), + ("154400", "1740", "Acc. Depreciation — Leasehold"), + ("154500", "1750", "Acc. Depreciation — Acquired"), + + # 2xxx LIABILITIES + ("213100", "2110", "HST/GST Collected"), + ("213500", "2120", "QST Collected"), + ("214100", "2130", "Net HST/GST Payable"), + ("215100", "2210", "Source Deductions Payable — Federal"), + ("215200", "2220", "Source Deductions Payable — CPP"), + ("215300", "2230", "Source Deductions Payable — EI"), + ("216100", "2310", "Federal Payable"), + ("216200", "2320", "Provincial Payable"), + ("216300", "2330", "Tax Instalments Paid"), + ("221100", "2510", "Due To Shareholder"), + ("221200", "2520", "Shareholder Loan"), + ("222900", "2590", "Due To Associated Corporations"), + + # 3xxx EQUITY + ("311100", "3010", "Common Shares"), + ("311200", "3020", "Preferred Shares"), + ("311300", "3030", "Contributed Surplus"), + ("321100", "3510", "Retained Earnings — Current"), + ("321200", "3520", "Retained Earnings — Prior"), + ("321900", "3590", "Dividends Declared"), + + # 4xxx REVENUE + ("411100", "4010", "SaaS Subscription"), + ("411200", "4020", "Hosting"), + ("411300", "4030", "Support"), + ("411400", "4040", "Domain/SSL"), + ("411500", "4050", "Setup"), + ("412100", "4110", "Custom Software Development"), + ("412200", "4120", "Custom Web Application"), + ("412300", "4130", "Custom Website"), + ("412400", "4140", "ERP Implementation"), + ("412500", "4150", "Mobile App"), + ("412600", "4160", "Business App"), + ("413100", "4210", "Consulting"), + ("413200", "4220", "Training"), + ("413300", "4230", "Technical Support — Per-incident"), + ("414100", "4310", "Third-party Software Resale"), + ("414200", "4320", "Hardware Resale"), + ("419100", "4910", "Sales Discounts"), + ("419200", "4920", "Sales Returns"), + ("419300", "4930", "Bad Debt Recovery"), + + # 5xxx COGS + ("511100", "5010", "Cloud Infrastructure"), + ("511110", "5020", "CDN"), + ("511120", "5030", "Backup"), + ("511130", "5040", "Database"), + ("511140", "5050", "Monitoring"), + ("511150", "5060", "SSL"), + ("511160", "5070", "DNS"), + ("511200", "5110", "Third-party API"), + ("511210", "5120", "Per-customer Licensing"), + ("512100", "5210", "Subcontracted Labour — Canadian"), + ("512110", "5220", "Subcontracted Labour — Foreign"), + ("512200", "5230", "Project-specific Software"), + ("512300", "5240", "Project Travel"), + ("512400", "5250", "Project Hardware"), + ("513100", "5310", "Cost of Software Resold"), + ("513200", "5320", "Cost of Hardware Resold"), + ("519100", "5910", "COGS Adjustments"), + + # 6xxx OPERATING EXPENSES + ("611100", "6010", "Salaries & Wages — Development"), + ("611200", "6020", "Salaries & Wages — Sales"), + ("611300", "6030", "Salaries & Wages — Admin"), + ("611400", "6040", "Salary — Shareholder"), + ("611500", "6050", "Employer CPP"), + ("611600", "6060", "Employer EI"), + ("611700", "6070", "Employer Health Tax"), + ("611800", "6080", "WCB"), + ("611900", "6090", "Employee Benefits"), + ("611950", "6091", "Bonuses"), + ("611960", "6092", "Vacation Pay"), + ("612100", "6110", "Contract Labour — Canadian"), + ("612200", "6120", "Contract Labour — Foreign"), + ("621100", "6210", "Rent"), + ("621200", "6220", "Home Office"), + ("621300", "6230", "Utilities"), + ("621400", "6240", "Internet"), + ("621500", "6250", "Office Supplies"), + ("621600", "6260", "Cleaning"), + ("621700", "6270", "Office Snacks"), + ("631100", "6310", "Software — Productivity"), + ("631200", "6320", "Software — Development Tools"), + ("631300", "6330", "Software — Internal Infrastructure"), + ("631400", "6340", "Software — Security"), + ("631500", "6350", "Software — Sales"), + ("641100", "6410", "Advertising — Digital"), + ("641200", "6420", "Advertising — Content"), + ("641300", "6430", "Trade Shows"), + ("641400", "6440", "Promotional"), + ("641500", "6450", "Website — Own"), + ("651100", "6510", "Legal Fees"), + ("651200", "6520", "Accounting"), + ("651300", "6530", "Tax Preparation"), + ("651400", "6540", "Business Consulting"), + ("661100", "6610", "Insurance — Commercial General"), + ("661200", "6620", "Insurance — Professional Liability"), + ("661300", "6630", "Insurance — Cyber"), + ("661400", "6640", "Insurance — Property"), + ("661500", "6650", "Insurance — Directors"), + ("671100", "6710", "Travel"), + ("671200", "6720", "Meals"), + ("671300", "6730", "Vehicle — Operating"), + ("671400", "6740", "Mileage"), + ("681100", "6810", "Conferences"), + ("681200", "6820", "Courses"), + ("681300", "6830", "Books"), + ("681400", "6840", "Professional Memberships"), + ("691100", "6910", "Bank Service Charges"), + ("691200", "6920", "Merchant Processing"), + ("691300", "6930", "Wire Transfer"), + ("691400", "6940", "Interest Expense — Bank"), + ("691500", "6950", "Interest Expense — Credit Cards"), + ("691600", "6960", "Late Payment Penalties"), + + # 7xxx OTHER (was 699xxx) + ("699100", "7010", "Bad Debt Expense"), + ("699200", "7020", "Donations"), + ("699300", "7030", "Penalties & Fines"), + ("699400", "7040", "Realized FX Losses"), + ("699500", "7050", "Depreciation"), +] + +ok = 0 +skipped = 0 +missing = 0 +for old_code, new_code, expected_name_part in CODE_MAP: + acc = env['account.account'].search([('code', '=', old_code)], limit=1) + if not acc: + print(f"MISS {old_code} → {new_code}: not found") + missing += 1 + continue + if expected_name_part.lower() not in (acc.name or '').lower(): + print(f"SKIP {old_code} → {new_code}: name '{acc.name}' doesn't contain '{expected_name_part}'") + skipped += 1 + continue + # Check target code is free + conflict = env['account.account'].with_context(active_test=False).search([('code', '=', new_code)], limit=1) + if conflict: + print(f"SKIP {old_code} → {new_code}: target occupied by {conflict.name}") + skipped += 1 + continue + acc.code = new_code + ok += 1 +print(f">>> Renumbered {ok}, skipped {skipped}, missing {missing} of {len(CODE_MAP)}") +env.cr.commit()