PayMatch
Reconciles internal payments with a bank statement: matches, amount differences, missing rows and duplicates. An ambiguous pair stays ambiguous instead of going to whichever row came first.
A two-deck sorter
Our payments and the bank statement ride as two decks. The comb clips a pair only when the cards chose each other; ambiguous and unmatched ones go to their own trays.
How it matches
Rows are normalised and duplicate references are quarantined. Candidates are generated by currency, time window and normalised reference, then scored on configurable evidence. A pair is accepted only when each side is the other’s unique best candidate.
Why this way
A greedy pass hands a disputed payment to whichever row came first, and the mistake goes unnoticed. Here anything that can’t be decided uniquely is marked ambiguous, with the evidence listed.
Under the hood
- Statuses: matched, amount mismatch, missing internal, missing external, duplicate, ambiguous.
- Decimal amounts, timestamps only with an explicit offset.
- Mutual best pairs instead of a greedy pass.
- A JSON report and an optional PostgreSQL audit record.