Deterministic and heuristic financial reconciliation engine matching bank statement transactions against open receivables (invoices).
Designed to automate accounting close cycles, accounts receivable (AR) settlement, and ERP invoice-clearing workflows.
In enterprise finance operations, matching bank deposits (EFT, Havale, wire transfers) against issued e-invoices is labor-intensive and error-prone:
- Customers often omit invoice numbers or make typos in transfer descriptions.
- Partial payments and combined payments create discrepancies.
- Double-allocations lead to accounting ledger corruption.
recon-engine implements a tiered, confidence-scored matching pipeline that guarantees zero double-allocation and surfaces exact reconciliation decisions.
flowchart TD
TX[Bank Credit Transaction] --> T1{Tier 1: Invoice Number & Exact Amount}
T1 -- Yes --> C1[CONFIRMED 1.0<br/>Auto-reconcile]
T1 -- No --> T2{Tier 2: Tax ID VKN/TCKN & Exact Amount}
T2 -- Yes --> C2[CONFIRMED 0.95<br/>Auto-reconcile]
T2 -- No --> T3{Tier 3: Invoice Number Found<br/>Different Amount}
T3 -- Less --> P1[PARTIAL 0.95<br/>Allocate partial]
T3 -- More --> O1[OVERPAID 0.90<br/>Flag surplus]
T3 -- No --> T4{Tier 4: Customer Name Tokens & Exact Amount}
T4 -- Yes --> M1[PROPOSED 0.85<br/>Manual sign-off]
T4 -- No --> T5{Tier 5: Unique Amount Match}
T5 -- Yes --> M2[PROPOSED 0.70<br/>Manual sign-off]
T5 -- No --> U[UNMATCHED 0.0<br/>Investigation queue]
| Tier | Rule | Status | Confidence | Action |
|---|---|---|---|---|
| 1 | Invoice Number found + Exact Amount | CONFIRMED |
1.00 | Immediate auto-clear in ERP |
| 2 | Customer Tax ID (VKN/TCKN) + Exact Amount | CONFIRMED |
0.95 | Auto-clear in ERP |
| 3a | Invoice Number found + Amount < Invoice | PARTIAL |
0.95 | Allocate partial, keep invoice open |
| 3b | Invoice Number found + Amount > Invoice | OVERPAID |
0.90 | Clear invoice, credit balance forward |
| 4 | Customer Name Tokens + Exact Amount | PROPOSED |
0.85 | Suggested match for accountant |
| 5 | Single Unique Invoice with Matching Amount | PROPOSED |
0.70 | Suggested match for accountant |
| 6 | No rule satisfied | UNMATCHED |
0.00 | Queue for manual review |
- Double-Allocation Guard: Once an invoice is matched or allocated, it is isolated from candidate pools for subsequent transactions in the run.
- Turkish Character Normalization: Robust normalization of Turkish characters (
İ,ı,Ğ,ğ,Ü,ü,Ş,ş,Ö,ö,Ç,ç) and punctuation in bank transaction descriptions. - Exact Decimal Math: Eliminates float rounding bugs by enforcing
decimal.Decimalthroughout. - Zero Runtime Dependencies: Built purely with Python standard library.
pip install recon-enginefrom decimal import Decimal
from recon_engine import InvoiceRecord, TransactionRecord, ReconciliationEngine, MatchStatus
# 1. Define open invoices
invoices = [
InvoiceRecord(
invoice_id="INV-001",
number="EDM2026000000042",
customer_tax_id="1234567890",
customer_name="Acme Teknoloji A.Ş.",
amount=Decimal("15000.00"),
),
InvoiceRecord(
invoice_id="INV-002",
number="EDM2026000000043",
customer_tax_id="9876543210",
customer_name="Beta Lojistik Ltd.",
amount=Decimal("4500.50"),
),
]
# 2. Define bank transactions (from mt940-camt-parser)
transactions = [
TransactionRecord(
transaction_id="TX-101",
amount=Decimal("15000.00"),
description="HAVALE EDM2026000000042 FATURA BEDELI",
),
TransactionRecord(
transaction_id="TX-102",
amount=Decimal("4500.50"),
description="GELEN HAVALE VKN 9876543210",
),
]
# 3. Run reconciliation
engine = ReconciliationEngine(invoices)
summary = engine.reconcile(transactions)
print(f"Total Transactions: {summary.total_transactions}")
print(f"Confirmed Matches: {summary.confirmed_matches}")
print(f"Unmatched: {summary.unmatched_transactions}")
for r in summary.results:
print(f"TX {r.transaction_id} -> INV {r.invoice_id} [{r.status.value}] ({r.confidence * 100:.0f}%) via {r.rule_applied}")python -m unittest discover testsMIT © Yasin BALÇIK