DEV Community

Cover image for A proof of cash validator in 40 lines of Python: every row and every column has to tie
Damin Mutti
Damin Mutti

Posted on Originally published at zerabooks.com

A proof of cash validator in 40 lines of Python: every row and every column has to tie

A proof of cash is valid only when two rules hold. Across: every row satisfies beginning + receipts - disbursements - ending = 0. Down: in each column, bank plus reconciling items equals books. Rule one catches mis-entered rows. Rule two finds real differences, and the failing columns show whether a receipt or a payment is missing.

Accountants build these in spreadsheets, and spreadsheets break quietly. A sign typed wrong in one cell, an item in the wrong column, and the totals still look plausible. A validator catches both.

What are the two rules of a proof of cash?

Rule 1, across: for every row, beginning + receipts - disbursements - ending == 0. This applies to reconciling items too. A deposit in transit at period end adds to receipts and to ending, so its row nets to zero.

Rule 2, down: for each column, bank + sum(reconciling items) == books.

If rule 1 fails, a row is mis-entered. If rule 2 fails in some columns and not others, the failing columns point at the finding.

What does a proof of cash CSV look like?

One row per line. This is the shape of the free template on the page linked below, March 2026 for a fictional client:

Line,Beginning balance,Receipts,Disbursements,Ending balance
Balance per bank,48210.00,61385.40,57902.15,51693.25
"Deposit in transit, prior period end",3150.00,-3150.00,,
"Deposit in transit, current period end",,4820.00,,4820.00
"Outstanding checks, prior period end",-2640.00,,-2640.00,
"Outstanding checks, current period end",,,5115.60,-5115.60
"NSF customer check, not yet in books",,,-750.00,750.00
"Bank service fee, not yet in books",,,-45.00,45.00
"Interest credited, not yet in books",,-18.37,,-18.37
Balance per books,48720.00,63037.03,59582.75,52174.28
Enter fullscreen mode Exit fullscreen mode

Blank means zero. Negative means the item reduces that column.

Line Beginning Receipts Disbursements Ending
Balance per bank 48,210.00 61,385.40 57,902.15 51,693.25
Reconciling items, net 510.00 1,651.63 1,680.60 481.03
Balance per books 48,720.00 63,037.03 59,582.75 52,174.28

How do you validate a proof of cash in Python?

import csv
from decimal import Decimal

COLS = ["Beginning balance", "Receipts", "Disbursements", "Ending balance"]

def amount(cell: str) -> Decimal:
    return Decimal(cell) if cell and cell.strip() else Decimal("0")

def check(path: str) -> bool:
    with open(path, newline="", encoding="utf-8") as f:
        rows = list(csv.DictReader(f))

    ok = True
    for r in rows:                                   # rule 1: across
        b, rc, d, e = (amount(r[c]) for c in COLS)
        off = b + rc - d - e
        if off:
            ok = False
            print(f"Row does not read across: {r['Line']} (off by {off})")

    bank = next(r for r in rows if r["Line"] == "Balance per bank")
    books = next(r for r in rows if r["Line"] == "Balance per books")
    items = [r for r in rows if r not in (bank, books)]
    for c in COLS:                                   # rule 2: down
        adjusted = amount(bank[c]) + sum((amount(r[c]) for r in items), Decimal("0"))
        if adjusted - amount(books[c]):
            ok = False
            print(f"{c}: adjusted bank {adjusted} vs books {amount(books[c])}")
    print("Ties on every row and column." if ok else "Does not tie.")
    return ok
Enter fullscreen mode Exit fullscreen mode

On the template it prints Ties on every row and column.

A statement that ties in ZeraBooks: deposits, withdrawals and net each compared between statement and ledger, with a $0.00 difference
ZeraBooks runs the receipts, disbursements and net comparison for every month of every account in its general ledger.

What does a failing proof of cash look like?

A fictional June where the books are missing a 900.00 counter deposit:

Line,Beginning balance,Receipts,Disbursements,Ending balance
Balance per bank,15000.00,42300.00,39850.00,17450.00
"Deposit in transit, prior period end",1200.00,-1200.00,,
"Deposit in transit, current period end",,2500.00,,2500.00
"Outstanding checks, prior period end",-3100.00,,-3100.00,
"Outstanding checks, current period end",,,1750.00,-1750.00
Balance per books,13100.00,42700.00,38500.00,17300.00
Enter fullscreen mode Exit fullscreen mode
Receipts: adjusted bank 43600.00 vs books 42700.00
Ending balance: adjusted bank 18200.00 vs books 17300.00
Does not tie.
Enter fullscreen mode Exit fullscreen mode

Every row reads across, so nothing is mis-entered. Receipts and ending are each 900.00 apart, and disbursements agree. That pattern says the bank received 900.00 the books never recorded. No timing item explains it.

Columns that fail Columns that agree Likely finding
Receipts and Ending Disbursements Unrecorded receipt
Disbursements and Ending Receipts Unrecorded payment
Receipts and Disbursements, by the same amount Ending Equal and opposite omissions

Where do the bank-side figures come from?

Beginning and ending per bank are the statement's printed opening and closing balances. Receipts and disbursements per bank are the sums of money in and money out. If you extract those from PDFs, prove the extraction first: opening plus money in minus money out must equal the printed closing balance. The full worked example, an explanation of every reconciling item and the CSV template are on the proof of cash page.

Key takeaways

  • Rule 1 (across) catches typing and sign errors in a single row.
  • Rule 2 (down) finds real differences; the failing columns name the type.
  • Use Decimal; the check is to the cent.
  • Prove the bank-side extraction against printed balances before trusting it.

FAQ

How is a proof of cash different from a bank reconciliation?

A bank reconciliation ties the ending balance only. A proof of cash also ties receipts and disbursements, which catches equal and opposite omissions.

Do NSF checks and bank fees belong in the proof?

Yes, until the books record them. Each sits in the column where bank and books disagree and in the ending balance, then drops out once journaled.

Does ZeraBooks build the proof of cash?

No. It supplies the proven bank side and, in the general ledger, a monthly deposits, withdrawals and net comparison. It doesn't keep a list of outstanding items or perform audits.

Disclosure: I'm the founder of ZeraBooks. ZeraBooks general ledger software compares each month's deposits, withdrawals and net with the statement, and its converter's Money in and out download gives receipts and disbursements per bank as two columns. $79 a month billed annually or $149 monthly, after a 7-day trial.

Top comments (0)