Engine Signature
Everything runs through a single entry point. Inputs are already-parsed, already-validated rows. Output is a full per-entry breakdown plus aggregate counters.
reconcile(books, gstr2b, config) → ReconciliationReport
books
→
Purchase register rows (parsed by excel_parser) after validation by invoice_validator.
gstr2b
→
GSTR-2B invoices (parsed by gstr2b_parser) with IRN, GSTIN, normalized invoice #, dedup hashes.
config
→
Tolerances: value_tolerance=1.0, date_tolerance_days=7, fuzzy_threshold=0.85.
Report
←
Summary counts + entries[] with match_category, match_confidence, match_pass, mismatch_types[], auto_resolved, and the full books_record + gstr2b_record for audit.
The 5-Pass Ladder
Click any pass to see exactly how it matches, what confidence it emits, and why it sits where it does.
IRN_EXACT
Match by Invoice Reference Number (cryptographic e-invoice hash)
Used only for e-invoiced B2B supplies · passes/irn_match.py
EXACT_MATCH
GSTIN + normalized invoice # + value (± Rs 1)
The happy path · passes/exact_match.py
FUZZY_INVOICE
GSTIN exact + fuzzy invoice # (similarity ≥ 0.85 via rapidfuzz)
Handles OCR errors and ERP export drift · passes/fuzzy_match.py
AMOUNT_DATE
GSTIN + amount (±2%) + date (±7 days). Invoice # unreconcilable.
Always flags requires_review · passes/amount_date_match.py
LOOSE_MATCH
GSTIN + amount (±1%) only. Last resort before declaring missing.
Always requires_review · passes/loose_match.py
Click any pass row above for the matching recipe, algorithm, and typical use cases.
Full Engine Pipeline
The 5 passes are sandwiched between preparation and resolution steps, ordering matters.
engine.reconcile(), step by step
Step 1 · Dedup
→
duplicate_detector.py, exact duplicates are removed, near-duplicates flagged for review.
Step 2 · Pass 1-5
→
Sequential matching. Each pass consumes a slice of the unmatched pool.
Step 3 · Mismatch detect
→
For matched pairs, diff each field. Populate mismatch_types[].
Step 4 · Auto-resolve
→
auto_resolver.py, promote trivial mismatches back to MATCHED.
Step 5 · Cross-period
→
cross_period.py, residue searches adjacent 2B periods (late filers) with month penalty.
Step 6 · Classify
→
Unmatched books → MISSING_IN_GSTR2B · Unmatched 2B → MISSING_IN_BOOKS.
Step 7 · Confidence
→
confidence.py, adjust per-entry score with vendor grade & cross-period penalties.
Mismatch Types
Even inside MATCHED pairs, individual fields can disagree. Each type carries a downstream ITC risk weight.
TAXABLE_VALUE
Net (pre-tax) invoice value differs between books and 2B.
Risk weight: +50
TAX_AMOUNT
CGST/SGST/IGST/cess don't match, direct ITC mismatch.
Risk weight: +60
TAX_RATE
Effective GST rate implied by the numbers differs.
Risk weight: +40
DATE
Invoice dates differ by more than tolerance.
Risk weight: +10
INVOICE_NUMBER_FORMAT
Matched fuzzy but invoice # strings differ, format drift.
Risk weight: +5 (warn)
REVERSE_CHARGE
Books claims reverse charge but 2B does not (or vice versa).
Risk weight: +30
Auto-Resolver Rules
Small, deterministic fixes that take a mismatched pair back to MATCHED without human review.
Rule 1 · Rounding
- Value difference ≤ Rs 1 (absolute)
- Each tax component delta within proportional tolerance
- Dates and GSTINs already exact
- Marks entry as auto_resolved=true, MATCHED
Rule 2 · Date-only drift
- All numeric fields exact
- Date difference ≤ 3 days
- Invoice # exact (post-normalization)
- Common cause: book-date vs invoice-date convention
Rule 3 · Invoice # format-only
- Normalized invoice # identical (prefix strip, zero strip, case fold)
- All other fields already exact
- Original strings differ (e.g.
INV-001/24 vs inv1/24)
Never auto-resolves
- Tax amount mismatches beyond rounding
- Different GSTINs (even if visually similar)
- Pass 4 / Pass 5 matches (always require review)
- Reverse-charge flag disagreements
Confidence Adjustment
The pass baseline is just the start, confidence moves up or down based on secondary signals.
Vendor grade A (high compliance)
+0.03
Vendor grade C (low compliance)
-0.05
Cross-period (per month offset)
-0.05
IRN available but not used
-0.02
ITC Risk Scoring
Once reconciliation completes, every non-MATCHED (or mismatched) entry is scored 0-100 and bucketed. This drives the finance-team action queue.
Critical
71-100
3-day SLA · immediate vendor follow-up
High
51-70
7-day SLA · confirm with vendor this week
Medium
31-50
15-day SLA · batch follow-up
Low
0-30
30-day SLA · monitor at month-end
TAXABLE_VALUE_MISMATCH
+50
Sample Report Output
Shape of the final ReconciliationReport for a typical month with 200 vendor invoices.
ReconciliationReport (illustrative)
{
"total_books_entries": 200,
"total_gstr2b_entries": 195,
"matched": 142,
"auto_resolved": 18,
"mismatched": 14,
"probable_matches": 9,
"missing_in_gstr2b": 12,
"missing_in_books": 5,
"duplicates_detected": 3,
"entries": [
{
"supplier_gstin": "29ABCDE1234F1Z5",
"invoice_number": "INV-2024/0412",
"match_category": "MATCHED",
"match_pass": "EXACT_MATCH",
"match_confidence": 0.98,
"books_value": 125000.00,
"gstr2b_value": 125000.00,
"mismatch_types": [],
"auto_resolved": false
},
// ... one entry per reconciled pair or unmatched record
]
}