← 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.
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
ERPNEXT v15 · Trial Balance, fiscal 2026 view of the migrated company
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
- It can fail, and that's tested. The checker's self-test perturbs a single cent in one account and must catch it — a checker that can't fail proves nothing.
- Money is never floating-point. Amounts travel as decimal strings end to end; the checker rejects any JSON number with a fractional part as a contract violation.
- Known differences are declared, not ignored. Accepted deltas live in a committed file, must match character-for-character, and must actually occur — a stale allowlist fails the run.
- The raw material is archived. Every qbXML request and response — the actual XML QuickBooks produced — is committed to the repository. The extraction can be audited or replayed without QuickBooks installed.
- The input is reproducible. The synthetic company generates byte-identically from seed 42; anyone with the repository can regenerate it and re-run every gate.
Chain of evidence
| What | Where |
| 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 declaration | artifacts/seed42/expected-deltas-qbd.json |
| Check 2 — recompute comparison | artifacts/tb-recompute-20260821T164415Z.json |
| Check 3 — ERPNext read-back + parity report | artifacts/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 target | a 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.
- QuickBooks' bulk import format (IIF) silently cannot carry bill payments at all — payments travel over the API with explicit invoice/bill applications, which is also what preserves aging reports.
- Fresh QuickBooks companies pre-create accounts and terms that collide with imported charts; the collision surface was mapped by extraction and is now declared, not discovered.
- QuickBooks ages credit memos by due date derived from customer terms — three tools had to agree on that truth before agings matched.
- Items imported via IIF come out one-sided; two-sided income/expense items require a UI conversion QuickBooks refuses over the API.
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:
- Sage 50 → ERPNext — the same 1,191-transaction proof company, written into Sage 50's documented export format and rebuilt from those files to the penny. Export side proven; the ERPNext leg and its published gate are in progress.
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 →