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:
- Quantity vs PO — each bill line's quantity must be ≤ (PO line
quantity − already invoiced). Otherwise the bill is flagged
qty_varianceorover_billed. - Unit price vs PO — each bill line's unit price must be within
tolerance vs the PO line. Default is 2%. Otherwise
price_variance. - 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
- Open the bill. If it's linked to a PO, the Three-way match panel appears on the right.
- Read the status pill. If
matched, no action needed. - If
qty_varianceorover_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. - If
price_variance, compare the bill's unit price against the PO. Common causes: supplier raised prices mid-term, FX move, line item miscoded. - 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. - 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_billedis the strict case where bill quantity exceeds remaining PO quantity outright.qty_varianceis the within-line case. Both surface, butover_billedis the harder block.- A bill without a
po_idskips the matcher entirely — there's no PO to compare against. The pill is hidden in that case.