How-to

Three-way match a bill against PO and GRN

Automatic check that supplier bill quantity, price, and goods received all line up before you pay.

2 min readLast updated 26 May 2026
Jump to section

What it does

When a supplier bill is linked to a Purchase Order (the bill has a po_id), the matcher runs three checks on save and writes the result into fin_three_way_matches:

  1. Quantity vs PO — each bill line's quantity must be ≤ (PO line quantity − already invoiced). Otherwise the bill is flagged qty_variance or over_billed.
  2. Unit price vs PO — each bill line's unit price must be within tolerance vs the PO line. Default is 2%. Otherwise price_variance.
  3. GRN coverage — the sum of received quantities across all GRNs for that line must be ≥ the bill quantity. Otherwise no_grn.

The result shows on the bill detail page as a status pill: matched, qty_variance, price_variance, no_grn, or over_billed. The variance amount and notes are surfaced below the pill. A non-matched status doesn't block the bill — the operator can override after review, but the audit trail records the variance.

How to use it

  1. Open the bill. If it's linked to a PO, the Three-way match panel appears on the right.
  2. Read the status pill. If matched, no action needed.
  3. If qty_variance or over_billed, click the PO link to check the original quantities. Either correct the bill or accept the over-billing with a comment in the bill notes.
  4. If price_variance, compare the bill's unit price against the PO. Common causes: supplier raised prices mid-term, FX move, line item miscoded.
  5. If no_grn, raise the missing GRN against the PO first — see Record a Goods Received Note. Save the bill again to re-run the match.
  6. Once you've reviewed the variance, approve and post the bill as normal. The match status stays on the record.

Tips

  • Tolerances are currently constants — 2% for price, 5% for quantity. Per-tenant tolerance configuration is a V2 follow-up.
  • The "already invoiced" figure is summed across all prior bills against the same PO line. Partial-billing a PO over several months works without manual tracking.
  • over_billed is the strict case where bill quantity exceeds remaining PO quantity outright. qty_variance is the within-line case. Both surface, but over_billed is the harder block.
  • A bill without a po_id skips the matcher entirely — there's no PO to compare against. The pill is hidden in that case.

Still stuck? Email support or open the support widget in the bottom-right.