Files
PowderCoatingLogix/docs/ACCOUNTING_DEPLOY_VERIFICATION.md
T
spouliot 8b9a3dff41 Add accounting deploy & verification checklist
Repeatable post-deploy (and periodic) check that proves the books are consistent
against real data: per company, Trial Balance debits==credits, Balance Reconciliation
shows no drift, then Recalculate Balances and re-check. Includes the read-only
pre-deploy migration preview, the two pending migrations in order, account spot-checks
for the audit-touched accounts, and the inventory/sales-tax policy reminders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 21:42:32 -04:00

4.9 KiB
Raw Blame History

Accounting Deploy & Verification Checklist

Repeatable steps to run whenever accounting changes ship (and a good periodic health check). Goal: prove the books are internally consistent with real data, not just code review. Companions: docs/ACCOUNTING_AUDIT.md (findings/decisions), docs/ACCOUNTING_LEDGER_REFACTOR.md (future).

The decisive invariant: a Trial Balance whose total debits == total credits, with no drift on the Balance Reconciliation report, for every company. If that holds, the ledger is sound by construction.


1. Pre-deploy (against the production DB, read-only)

Migrations are applied manually at deploy (the app does not auto-migrate). Two are pending from the 2026-06 audit; apply in this order:

  1. RenameDepositsAccountAddPayroll (O1 — renames 2300 → "Customer Deposits", adds 2400 Payroll)
  2. FixGiftCertificateLiabilityAccount (O5 — relabels mislabeled 2500 → GC Liability, adds 2900)

Both are non-destructive (no account Id / number / balance is changed; only relabels + additive inserts). Preview exactly what they'll touch (read-only — swap account numbers as needed):

-- O1: 2300 rows that will be renamed (only those still named the default), and who gets a new 2400
SELECT CompanyId, AccountNumber, Name, CurrentBalance,
       CASE WHEN Name = 'Payroll Liabilities' THEN 'WILL RENAME -> Customer Deposits' ELSE 'kept as-is' END AS Action
FROM Accounts WHERE AccountNumber = '2300' AND IsDeleted = 0 ORDER BY CompanyId;

-- O5: 2500 rows that will be relabeled (only those still named "Long-Term Loan")
SELECT CompanyId, AccountNumber, Name, CurrentBalance,
       CASE WHEN Name = 'Long-Term Loan' THEN 'WILL RELABEL -> Gift Certificate Liability' ELSE 'kept as-is' END AS Action
FROM Accounts WHERE AccountNumber = '2500' AND IsDeleted = 0 ORDER BY CompanyId;

2. Deploy

  1. Merge devmaster, trigger the Jenkins production job.
  2. Apply the two migrations above (in order) to the production DB.

3. Post-deploy verification (per company — all of them)

Run for every company (there are ~7). Most is doable from the app UI under Reports / Finance.

  • Trial Balance — open it. Total Debits must equal Total Credits. Any difference is a one-sided posting and must be investigated before trusting other reports.
  • Balance Reconciliation report (/Reports/Reconciliation) — every account's stored balance should match the recomputed balance (no drift highlighted). Also confirm: - AR control account == sum of customer balances (AR subledger). - AP control account == sum of vendor balances (AP subledger).
  • Recalculate Balances, then re-open the Trial Balance and Balance Reconciliation. This exercises the recompute paths the audit fixed (LedgerService). After a recalc: - Trial Balance still balances. - Reconciliation shows no drift (stored now == recomputed by definition; the point is TB stays balanced and the values look sane).

4. Spot-check the accounts the audit touched

For each company, glance at these on the Trial Balance / chart of accounts:

  • 2300 Customer Deposits — named correctly; balance == outstanding (un-applied) customer deposits.
  • 2400 Payroll Liabilities — exists (likely 0 unless payroll is tracked).
  • 2500 Gift Certificate Liability — named correctly; balance == outstanding GC value (issued redeemed voided).
  • 2900 Long-Term Loan — present where the old 2500 was relabeled.
  • 4950 Sales Discounts / 4960 Sales Returns — contra-revenue, show as debit-balance.
  • AR — for any company that uses gift certificates or has written off an invoice, confirm AR is not overstated (these were O7 / O8). Cross-check AR total against the AR Aging report.

5. If something is off

  • A Trial Balance that doesn't balance → a posting hit only one side. Note the company + amount and check it against the findings in docs/ACCOUNTING_AUDIT.md (the resolved O2/O6/O7/O8 patterns) before assuming a new bug.
  • Drift on the Reconciliation report → run Recalculate Balances; if it persists, the recompute is missing a posting type (same class as the audit findings).
  • Do not treat a recalc as a fix for a real imbalance — it makes stored == recomputed, which can hide a one-sided posting if only one engine is wrong. The Trial Balance balancing is the real test.

6. Policy reminders (from the audit)

  • Inventory = expensed at purchase (periodic). Do not map an item's CogsAccountId + InventoryAccountId (set only via CSV import) while also expensing powder at purchase — that double-counts COGS. Keep those empty.
  • Sales-tax remittance is capped at the outstanding 2200 balance (O4) — you cannot over-remit.

When to repeat

  • After any accounting feature change or import.
  • As a periodic health check (e.g. monthly), run Section 3 — it's cheap and catches drift early.