Work

Synthetic data

Bank reconciliation that explains itself

Know which invoices are paid, with a reason for every match.

A synthetic bank statement and invoice list are loaded; the matches appear with a confidence and a reason; the review list shows the unclear cases and why each was not matched.

Who it is for

  • Small firms that send invoices and chase payments.
  • Bookkeeping assistants who reconcile bank statements every month.

The challenge

Matching a month of bank transfers against open invoices is slow by hand. Payers leave out the invoice number, pay two invoices in one transfer, pay in instalments or lose a bank fee on the way. A simple lookup by invoice number and amount finds only the easy cases; a tool that guesses the rest can mark an invoice as paid when it is not.

What we built

  1. Reads a bank-statement CSV and a list of invoices: a CSV of your sales invoices, and/or the supplier-invoice file that our doc2data demo extracts from PDFs. English and Italian column names are recognised (for example Data contabile, Dare/Avere, Descrizione operazioni), and amounts in 1.234,56 or 1,234.56.
  2. Matches each bank line to its invoice or invoices: exact invoice number and amount, one transfer paying several invoices, instalments, a reference one character off or a deducted bank fee, and equal amount within the invoice's date window.
  3. Explains every match with a confidence score and a plain-language reason. The score is a fixed value for each matching rule (for example 0.80 for amount and date only), not a percentage of certainty that the invoice is paid.
  4. Does not guess. Nothing below a confidence of 0.80 is matched automatically. Two invoices that fit equally well, partial payments, weak guesses, bank lines with no invoice, invoices with no payment and unreadable rows all go to a review list, each with its reason.

Local processing runs on your own computer, with owner access.

Table of matches between synthetic bank lines and invoices, each with a confidence and a reason.
Matches with confidence and reasons · synthetic data, 5 October 2026.
Review list of synthetic bank lines and invoices that were not matched automatically, each with its reason.
Measured accuracy · synthetic data, 5 October 2026.

Results

All bank lines and invoices are invented by our own generator, with an answer key. Measured 5 October 2026; figures from the project's evaluation summary.

The baseline is the same engine restricted to exact matches (invoice number in the bank text and amount equal), roughly what a simple spreadsheet lookup does. Per the developer's record, consistent with the commit history, the "final" sets were generated once, after the last rule change, and never used to change anything.

SetRoleBank linesMatched automaticallyWrong automatic matchesMatch recallBaseline recall
maindevelopment906601.00.4545
italiandevelopment906701.00.4478
holdouthold-out906701.00.4478
holdout_italianhold-out906701.00.4478
final_holdoutfinal hold-out906801.00.4412
stressstress401800.54550.1212
stress_holdoutstress401800.54550.1212
final_stressfinal stress401600.48480.1212
  • Match recall is the share of payments that should have been matched and were.
  • On the normal sets every bank line got the right outcome; on the final hold-out set, 90 of 90.
  • 0 wrong automatic matches is a measured count on synthetic sets, not a guarantee.
  • On the stress sets, built from harder cases to find the limits, the tool made no wrong automatic match but sent about half of the payments that should have matched to the review list. On the final stress set, 23 of 40 bank lines got the right outcome.
  • The generator and the rules were written by the same developer. These results show the rules do what they are meant to do; they do not show how the tool performs on your bank's exports.

Technical background

Python, pandas, openpyxl, Streamlit; tests with pytest and Playwright; packaged with Docker.

Limits

  • Left for a person, by design: payments with no reference that are also early, late or short by a fee; payers written as an acronym; truncated bank text.
  • Not handled: discounts, currency conversion, and netting credit notes against invoices. Credit notes (negative amounts) are reported as unreadable rows.
  • Dates must be ISO or day-first; US month-first dates are rejected. One currency per match.
  • Supplier invoices from doc2data carry no due date, so a 60-day term is assumed for the date window.
  • Not tested on real bank exports. Bank CSV layouts differ from bank to bank.
  • Not accounting advice.

Source: snello-reconcile README and reports/summary.json, measured 5 October 2026 (final-set line counts from reports/final_holdout and reports/final_stress). Code is private, so it is not linked.

Related work

Synthetic data

FatturaPA reader and SdI receipt explainer

Italian e-invoices (XML and signed .p7m) to one checked spreadsheet, where the implemented checks flag defined problems, with the SdI rejection code where one applies; SdI notices explained in plain words.

Test results and limits

On 3 synthetic sets of 94 invoices: 28 of 28 planted faults detected in each, 0 of 66 clean invoices flagged by mistake (measured 5 October 2026).

Read the project: FatturaPA reader and SdI receipt explainer

Bring your workflow into focus.

Send up to 3 samples or describe one process. We reply by email with what is feasible and how we would measure it.

Start a project

Optional AI assistance

The project now includes optional Groq assistance, disabled by default. The original local checks, calculations and source passages remain the basis for results. AI output needs human review.

After administrator setup, explicit consent is required before text is sent to Groq. Explanation tools show a context preview; invoice extraction can send OCR or document text after its consent step. API credentials stay on the server. Owner access, upload limits and a shared request budget protect the local demos.

This static website does not run the assistant or accept document uploads. Earlier demo recordings and measurements cover the original local workflows; the Groq integration has not yet been evaluated with live requests.

SNELLO / TOOLS

This explains the tool; it is not a live AI session. No document is uploaded.

Our working method
Full diagram

Read the project

Discuss your project

Send up to 3 samples or describe one process, the tools you use and the result you need.

snello.contact@gmail.com

Go to the Contact page

Navigation