AI Summary - 20-sec read - Reviewed by experts
- Three-way matching means a vendor bill is only paid when it agrees with the purchase order (what you ordered) and the goods receipt (what actually arrived). Odoo can enforce this so a mismatched bill never reaches payment.
- The single most important setting is the bill control policy on each product: set it to 'Received quantities' so Odoo bills you for what was received, not what was ordered. This is what stops paying for short deliveries.
- Odoo flags price and quantity differences on the vendor bill against the PO, so an over-billed line or a duplicate invoice surfaces before approval instead of after the money leaves.
- For India and UAE teams this also protects GST and VAT input credit: you reclaim tax only on bills that tie to a real receipt, which is exactly what an audit wants to see.
- Short on time? Book a free call.
Short on time? Book a free call.
Most accounts payable teams approve vendor bills the same risky way: open the supplier's invoice, glance at the amount, check it looks roughly like what was ordered, and post it. Nobody is checking that the goods actually arrived, that the price matches the agreed PO, or that this exact invoice was not already paid last month. That gap is where money leaks out, a few percent at a time, and nobody notices until a year-end review.
Three-way matching closes the gap. It is a control where a vendor bill can only be paid when three documents agree: the purchase order, the goods receipt, and the supplier invoice. Odoo has the pieces to enforce this natively. This guide shows you how to configure it so a wrong bill physically cannot be paid by mistake.
What three-way matching actually checks
The name describes three documents that must line up before payment is released:
- The purchase order - what you agreed to buy, at what price, in what quantity. This is your commitment.
- The goods receipt - what your warehouse or store actually received and counted in. This is reality.
- The vendor bill - what the supplier is charging you for. This is the claim.
A bill is only safe to pay when all three agree on quantity and price. If the PO says 100 units at 50 each, the receipt confirms 100 arrived, and the bill charges 100 at 50, you pay with confidence. If the bill charges for 100 but the receipt shows 90 arrived, you have a 10-unit gap that should be queried, not paid. Without the receipt in the loop, your team would pay the full 100 and never know.
Why most Odoo setups skip the receipt
Here is the trap. Out of the box, many Odoo configurations bill on ordered quantities, not received quantities. That means Odoo cheerfully drafts a vendor bill for the full PO amount the moment you create the bill, regardless of whether the stock turned up. Your team sees a draft that matches the supplier invoice and posts it. You have just done two-way matching - PO against invoice - and called it control.
The fix is one field, set correctly, on every purchased product.
Not sure where your AP control is leaking?
Get a free audit. Send us how your team approves vendor bills today and we will show you exactly where a mismatched or duplicate bill could slip through, and what to change in Odoo to stop it. No pitch, reply in 2 hrs, no card needed, NDA on request.
Get a free auditStep 1: set the bill control policy to received quantities
This is the setting that turns two-way matching into three-way matching.
- Open a product you buy, go to the Purchase tab, and find Control Policy (sometimes shown as 'Bill Control').
- Set it to On received quantities, not 'On ordered quantities'.
- To apply it to everything by default, set the same value in Accounting or Inventory settings as the default bill control policy, so new products inherit it.
With this in place, when you click 'Create Bill' on a purchase order, Odoo proposes a bill for the quantity actually received so far, not the quantity ordered. If only 90 of 100 units have been received, the draft bill is for 90. The 10 outstanding units stay un-billed until they arrive. A short delivery can no longer be quietly paid in full.
Step 2: make goods receipts non-optional
Three-way matching only works if someone actually records what arrived. That means the warehouse or store must validate the receipt in Inventory before AP creates the bill. Two habits make this stick:
- Receive against the PO, not blind. Staff open the incoming transfer linked to the purchase order and confirm the counted quantity. Odoo records the received quantity per line, which is the number the bill control policy reads.
- Count, do not rubber-stamp. If the box says 100 and only 90 are inside, the receipt should record 90. The whole control depends on the receipt being honest about reality, because that is the number AP will pay against.
This is the same discipline that keeps your stock valuation honest. If you have ever chased a phantom stock difference after go-live, the causes overlap, and the fix in why your Odoo stock valuation does not match after go-live starts with the same receiving rigour.
Step 3: read the differences Odoo shows you on the bill
When you create the vendor bill from the PO, Odoo pulls the lines and shows the matched quantity and price. Your AP reviewer is now checking three specific things before posting:
- Quantity. Does the billed quantity match the received quantity? With the received-quantities policy, it will, unless someone edited the line. Any manual override is a red flag to investigate.
- Price. Does the unit price on the bill match the PO price? Odoo carries the PO price onto the draft. If the supplier invoice charges more, the difference is visible on the line, not buried in a total.
- Duplicate. Enter the supplier's invoice number in the Bill Reference field. Odoo warns you if a bill with the same reference from the same vendor already exists, which is your defence against paying the same invoice twice.
Takeaways
- Set every purchased product's bill control policy to 'On received quantities'. This one field is what makes matching three-way instead of two-way.
- Goods receipts must be validated honestly in Inventory. The control is only as good as the received quantity the warehouse records.
- Always fill the Bill Reference with the supplier invoice number so Odoo catches duplicate invoices before payment.
- Tie tax input credit to matched bills. In India and UAE, GST and VAT reclaim should only sit on bills that agree with a real receipt.
Why this matters for GST and VAT compliance
For an India or UAE finance team, three-way matching is not only about catching overpayments. It is about a clean tax position. You claim input GST or recoverable VAT on purchases, and a tax audit will test whether each claim sits on a genuine, received supply. A bill that matches its PO and its goods receipt is exactly the evidence trail an auditor expects. A bill that was posted on ordered quantities, for stock that may or may not have arrived, is a weak link. Getting matching right means your GST and tax compliance automation rests on transactions that are already verified, not on a reconciliation you scramble to rebuild at filing time.
It also keeps your books trustworthy. The same control that stops overpayment is what makes your purchase ledger reconcile cleanly. If you are still tying out opening figures, the groundwork in why your first Odoo reports do not reconcile and the ongoing workflow in Odoo bank reconciliation with statement import and reconciliation models sit directly downstream of matched vendor bills.
Want your Odoo AP locked down so a wrong bill cannot be paid?
Talk to a team that configures three-way matching, approval rules, and GST or VAT-ready vendor bills for India and UAE businesses every week. We will review your purchase-to-pay flow and fix the leaks. No pitch, reply in 2 hrs.
Book a free callStep 4: add approval rules so control is not just a habit
Configuration sets the trap; approval rules make sure someone is watching it. Two additions turn matching from a guideline into a gate:
- Purchase approval thresholds. Require manager approval on purchase orders above a value, so the PO that anchors the match was itself authorised. Without an approved PO, there is nothing legitimate to match against.
- Separation of duties. The person who receives stock should not be the same person who approves the bill and releases payment. Odoo's user roles and access rights let you split receiving, AP posting, and payment so no single person can wave a bill through end to end.
This is the difference between a control that survives a busy month-end and one that quietly gets bypassed when the team is under pressure. Once it is configured in Odoo, the discipline holds even when nobody is thinking about it. Teams that automate the next step often layer this onto automating PO payments and vendor management in Odoo and predictive purchasing as covered in automating Odoo purchase orders with AI predictions, but the matching gate has to come first.
FAQ
What is the difference between two-way and three-way matching?
Two-way matching compares the supplier invoice to the purchase order only. It confirms the price and quantity were agreed, but not that the goods arrived. Three-way matching adds the goods receipt, so you also confirm what was actually delivered before paying. The receipt is the document that catches short deliveries and goods that were ordered but never came.
Does three-way matching work in Odoo Community or only Enterprise?
The core mechanism - the bill control policy set to received quantities, goods receipts in Inventory, and the duplicate-reference warning - works in both. Enterprise adds smoother approval workflows and more reporting, but a Community setup can still enforce the match. The control is a configuration choice, not a paid feature.
What happens to the unbilled balance when a delivery is short?
With the received-quantities policy, Odoo only bills what was received, so a short delivery leaves the remaining quantity un-billed on the purchase order. When the rest arrives and is received, you create a second bill for the balance. The PO tracks the billed and un-billed quantities for you, so nothing is lost and nothing is paid early.
How do I handle a legitimate price difference, like a freight charge?
Genuine extras such as freight or landed costs should be added as their own lines or through Odoo's landed-costs feature, not by overriding the matched product price. Keep the product line matched to the PO and receipt, and record the extra separately so the audit trail stays clean and the match still holds.
The takeaway: three-way matching is not a finance luxury, it is the cheapest insurance your purchase ledger will ever buy. One field set correctly, honest receiving, and a duplicate check turn vendor bills from a trust exercise into a verified one. Configure it once in Odoo and the leak closes for good.
Founder and CEO of Braincuber. Has scoped and shipped 500+ Odoo, AI, and cloud projects for US mid-market and global brands. Takes every founder call personally — no SDR layer between buyers and the people building the system.
