B2B Supplier Portals & Automated Procurement: Three-Way Invoice Matching (PO, GRN, Invoice) and Tender Management

How CFOs and procurement directors eliminate supplier overbilling, ghost deliveries, and manual RFQ email chaos with automated 3-Way Matching (PO + GRN + Invoice) in Python.

Why Email-Based Procurement and Manual Invoice Checks Leak Millions

In hospitality groups, hospital networks, construction firms, supermarket chains, and manufacturing enterprises, procurement accounts for 55% to 75% of total company expenditure. When vendor RFQs (Requests for Quotation), Purchase Orders (POs), warehouse Goods Received Notes (GRNs), and supplier invoices are managed across WhatsApp messages, email attachments, and paper delivery slips, three costly leaks occur every month:

  • Price Creep on Invoices: A supplier quotes KES 1,200 per unit on the approved Purchase Order, but bills KES 1,280 on the invoice three weeks later—hoping busy accounts-payable clerks won't notice.
  • Short-Delivery Overbilling: You order 500 bags of cement; the truck delivers 460 bags to the site (recorded on a paper gate pass), but the supplier submits an invoice for all 500 bags.
  • Collusive RFQ Manipulation: Without a sealed digital tender portal, procurement officers can selectively leak competitor bids to favored suppliers.

At devManue Procurement & ERP Engineering, we build self-service B2B Supplier Portals with automated Three-Way Matching (PO vs. GRN vs. Supplier Invoice) that mathematically blocks any invoice from entering the CFO payment queue unless every quantity and unit price reconciles to the cent.

1. Manual Accounts Payable vs. Automated B2B Supplier & 3-Way Match Portal

Here is how an automated procurement and vendor portal transforms accounts payable accuracy and supplier turnaround time:

Procurement Workflow Manual Email & Paper Process devManue B2B Supplier & 3-Way Match Portal
RFQ & Tender Bidding Scattered PDF email quotes; manual Excel comparison table; high collusion risk. Sealed digital vendor bidding (locked until deadline) + instant automated price/lead-time ranking.
Three-Way Invoice Matching Clerks manually staple paper PO, gate pass, and invoice; 3.5% overbilling leakage. 100% automated line-by-line check (PO Price × GRN Received Qty == Invoice Line Total).
Supplier Status Calls Finance team interrupted 30 times a day by vendors asking "When will my invoice be paid?" Self-serve Vendor Portal shows live status: Submitted → 3-Way Matched → Scheduled for Friday Run.
Turnkey Build Budget Pays for itself in 60 days from stopped overbilling alone $3,500 – $7,000 fixed-price build (4 – 6 weeks).

2. Production Code: Deterministic Line-Level Three-Way Matching Engine

When a supplier uploads their PDF/eTIMS invoice into the vendor portal, our OCR engine extracts the line items and immediately executes a line-level three-way match against the approved Purchase Order and the warehouse clerk's Goods Received Note (GRN):

# Automated Line-Level Three-Way Procurement Matcher (PO vs. GRN vs. Supplier Invoice)
from decimal import Decimal
from typing import List, Dict
from .models import PurchaseOrder, GoodsReceivedNote, SupplierInvoice

def execute_three_way_invoice_match(invoice: SupplierInvoice) -> Dict:
    """Verifies that billed quantities do not exceed received GRN goods and prices match the approved PO."""
    po: PurchaseOrder = invoice.purchase_order
    discrepancies: List[str] = []

    po_lines_by_sku = {line.sku_code: line for line in po.lines.all()}
    grn_qty_by_sku = po.get_cumulative_accepted_grn_quantities()
    already_invoiced_by_sku = po.get_previously_invoiced_quantities(exclude_invoice_id=invoice.id)

    for inv_line in invoice.lines.all():
        sku = inv_line.sku_code
        if sku not in po_lines_by_sku:
            discrepancies.append(f"SKU {sku}: Item was never ordered on Purchase Order #{po.po_number}.")
            continue

        po_line = po_lines_by_sku[sku]
        accepted_qty = grn_qty_by_sku.get(sku, Decimal("0.00"))
        prev_billed_qty = already_invoiced_by_sku.get(sku, Decimal("0.00"))
        max_billable_qty = max(Decimal("0.00"), accepted_qty - prev_billed_qty)

        # Check 1: Quantity billed vs. actual warehouse GRN accepted quantity
        if inv_line.quantity_billed > max_billable_qty:
            discrepancies.append(
                f"SKU {sku} Quantity Overbill: Billed {inv_line.quantity_billed}, "
                f"but only {max_billable_qty} accepted units remain unbilled on warehouse GRNs."
            )

        # Check 2: Unit price billed vs. contracted PO unit price
        if inv_line.unit_price > po_line.agreed_unit_price:
            discrepancies.append(
                f"SKU {sku} Price Overbill: Billed at {inv_line.unit_price} vs. PO agreed price {po_line.agreed_unit_price}."
            )

    if discrepancies:
        invoice.match_status = "BLOCKED_DISCREPANCY"
        invoice.discrepancy_log = discrepancies
        invoice.save(update_fields=["match_status", "discrepancy_log", "updated_at"])
        return {"matched": False, "errors": discrepancies}

    invoice.match_status = "THREE_WAY_VERIFIED_READY_FOR_PAYMENT"
    invoice.save(update_fields=["match_status", "updated_at"])
    return {"matched": True, "errors": []}

Want to stop supplier overbilling and modernize your procurement workflow? Explore our Automated Document & OCR Engineering Services or schedule a B2B Procurement Portal Discovery Call.

3. Frequently Asked Questions (FAQ)

What happens when a supplier delivers an order across three partial truckloads over two weeks?

Our engine tracks cumulative Goods Received Notes (GRNs) against each Purchase Order line item. Whether the supplier submits three separate partial invoices or one consolidated invoice at the end of the month, the matcher ensures total billed units never exceed total physically received units.

Can we enforce multi-level internal requisition approvals before a Purchase Order is issued?

Yes. You can configure dynamic approval matrices by department and spend threshold (e.g., POs under $1,000 require Department Head approval; POs over $5,000 require Operations Director + CFO sign-off via WhatsApp/email one-click approval links).

Architectural Continuity & Deep Dives

For related production architectures and system implementations, explore these companion guides:

// High-Throughput Engineering • Systems Architecture Consulting

Scaling Python & Django APIs or Resolving Concurrency Bottlenecks?

We partner with engineering founders and tech leads to architect resilient distributed systems, optimize async worker pools, design scalable databases, and eliminate production latency spikes.

All Insights
Chat on WhatsApp