← DArnTech services

darnbooks · QuickBooks Desktop → ERPNext · migration proof · 2026-08-21

The Penny-Exact Proof

A complete company — 1,191 transactions over two fiscal years — was placed into real QuickBooks Desktop, extracted through QuickBooks' own API, and loaded into ERPNext. At every step, an independent checker compared the books. They match to the penny, everywhere.

TRIAL BALANCE337,670.12Dr = Cr, all four systems
1,191 transactions 1,828 line items 386 payments w/ applications 44 ledger accounts 0 differences at the gate
Scope, stated plainly: the company is synthetic — generated data built to exercise real migration hazards (partial payments, credit memos, owner draws, sales tax, near-duplicate vendor names). No client data was used, and this page claims exactly what it shows: one company, moved once, verified three ways. Payroll is out of scope by design — it routes to a payroll service, and the books receive the journal entry.

How the proof is built

One rule makes the whole thing checkable: every system must describe the books in the same neutral format — a normalized JSON schema where money is a decimal string, never a float. The generator writes it, the QuickBooks extractor writes it, the ERPNext reader writes it. The parity checker only ever compares two of those files; it doesn't know or care where they came from.

Generator QuickBooks Normalized ERPNext v15 seed 42, deterministic Desktop Enterprise 24 JSON snapshot fresh company canonical JSON real install, real books money = decimal string chart from extraction IIF lists+txns qbXML payments qbXML 17.0 extract raw XML archived REST import provenance-tagged reader: books back out as the same JSON CHECK 1 — parity: canonical vs. what QuickBooks holds . CHECK 2 — rebuild TB recomputed from raw txns CHECK 3 — parity: ERPNext read-back vs. the extract
The three checks are independent: check 1 proves QuickBooks holds the intended books, check 2 proves the extracted transactions alone are sufficient to rebuild the trial balance, and check 3 proves ERPNext ends up holding the same books it was given. Any single-cent error anywhere fails a gate — that failure mode is itself tested.

The three checks, with their actual output

CHECK 1 · PASS

QuickBooks holds the intended books

The generator's canonical file says what the books should be. After importing into a fresh QuickBooks company and extracting back out over qbXML, the two snapshots are compared: trial balance per account, AR and AP agings per customer and vendor, and every entity count.

$ python3 tools/parity_check.py --named-deltas artifacts/seed42/expected-deltas-qbd.json \
    artifacts/extract-20260821T183504Z.json artifacts/seed42/synthetic-company.json
  ~ named delta (accepted): counts.accounts: A=44 vs B=37   # QBD pre-creates 7 accounts
  ~ named delta (accepted): counts.terms: A=7 vs B=3        # QBD pre-creates standard terms
RESULT: PASS - snapshots match on all compared fields (2 named delta(s) accepted).

The two "named deltas" are QuickBooks' own furniture — accounts and payment terms it creates in every new company. They are declared in a file, matched exactly, and the check fails if they don't appear. Nothing is waved through silently.

CHECK 2 · PENNY-EXACT

The extraction is complete enough to rebuild the books

This is the strongest evidence that nothing was lost in extraction: taking only the extracted transactions and re-deriving every posting from first principles (debits, credits, tax lines, payment applications, fiscal-year close), the rebuilt trial balance equals QuickBooks' own report on every account.

$ python3 tools/recompute_tb.py artifacts/extract-20260821T183504Z.json
  QBD TB total       : 337670.12 Dr / 337670.12 Cr
  recomputed TB total: 337670.12 Dr / 337670.12 Cr
  accounts compared 36: matched 36, mismatched 0 (0 unexplained by declared gaps)
RESULT: PENNY-EXACT — recomputed TB matches QuickBooks on every account.
CHECK 3 · PASS, ZERO DELTAS

ERPNext ends up with the same books

The extract is loaded into a fresh ERPNext company over REST — chart of accounts from the extraction (never a template), every document tagged back to its QuickBooks transaction ID. A separate reader pulls the books out of ERPNext as the same normalized JSON, and the checker compares it against the extract. The reader also fails loudly if any untagged ledger entry exists — nothing may post outside the migration.

$ python3 tools/parity_check.py erpnext-snapshot-extract.json artifacts/extract-20260821T183504Z.json
  Compared: trialBalance, arAging, apAging, counts
RESULT: PASS - snapshots match on all compared fields.

Same books, two systems

The trial balance as each system reports it, captured live from the running installs.

QUICKBOOKS DESKTOP ENTERPRISE 24 · Trial Balance, all dates
QuickBooks Desktop Trial Balance report for Acme Sign & Service as of July 31, 2026, listing all 37 accounts with a double-underlined total of 337,670.12 in both the debit and credit columns.
ERPNEXT v15 · Trial Balance, fiscal 2026 view of the migrated company
ERPNext Trial Balance report for the migrated company Acme Sign & Service, fiscal year 2026, showing closing balances identical to the QuickBooks report: Checking 38,562.92, Accounts Receivable 42,084.52, Accounts Payable 24,352.27, Sales Tax Payable 729.68.

The two systems present the report differently — ERPNext shows opening/period/closing per fiscal year, QuickBooks a point-in-time balance — but the closing figures are the same numbers, cent for cent. The row-by-row, full-window comparison is what the checker does mechanically in Check 3.

Why you can trust the checker

Chain of evidence

WhatWhere
Canonical books (generator output)artifacts/seed42/synthetic-company.json · .iif
Live QuickBooks extract (gate artifact)artifacts/extract-20260821T183504Z.json
Raw qbXML payloads (every request/response)artifacts/raw/
Check 1 — accepted-deltas declarationartifacts/seed42/expected-deltas-qbd.json
Check 2 — recompute comparisonartifacts/tb-recompute-20260821T164415Z.json
Check 3 — ERPNext read-back + parity reportartifacts/seed42/erpnext-snapshot-from-extract.json · parity-erpnext-vs-extract.txt
Gate commits (private repo)7258263 Phase 1.4 green · 135e073 v1 green
Live ERPNext targeta dedicated, disposable test container, company "Acme Sign & Service"

Explaining it in sixty seconds

The problem. QuickBooks Desktop is being sunset — payroll and bank feeds die May 2026 — and businesses need their books moved somewhere, exactly, with proof.

What we built. A migration pipeline that pulls the books out of QuickBooks through its own API and loads them into ERPNext — plus an independent checker that compares the two systems' books line by line, to the penny.

How we know it works. We built a full fake company — two years, 1,191 transactions, the messy stuff included — put it into real QuickBooks, migrated it, and ran the checker at every step. Trial balance, receivables aging, payables aging: identical to the cent, zero differences. And the checker itself is tested — change one cent anywhere and it catches it.

The honest caveat. This is a proof on synthetic books, not a delivered client migration — it demonstrates the machinery, and every claim on this page is backed by a committed artifact you can re-run.

What the proof surfaced along the way

The value of doing this against real QuickBooks rather than on paper: the live install pushed back, and each finding is now encoded in the tools.

Other systems we move

The pipeline and the checker aren't QuickBooks-specific — any system that can export its books can be held to the same penny. The next lane is underway:

Have books to move?

This proof is the method we bring to your company file. Scope depends on your books, so it starts with a conversation, not a quote form.

Book a 30-min call All services →