3 Way PO Matching SQL Query in Oracle Fusion: Purchase Order, Receipt, and Invoice Reconciliation
3 Way Matching SQL Query in Oracle Fusion: Purchase Order, Receipt, and Invoice Reconciliation
In any procurement system, ensuring the accuracy of supplier payments is critical. One of the most robust methods for validating supplier invoices is the 3-way matching process. This blog breaks down the 3-way matching concept in Oracle E-Business Suite (EBS) or Oracle Fusion, explains its benefits, and presents a detailed SQL query that helps extract and reconcile PO, Receipt, and Invoice data.
What is 3-Way Matching ?
3-Way Matching is a process that compares the following three documents before payment is released:
-
Purchase Order (PO) – What you ordered
-
Receipt – What you received
-
Invoice – What the supplier billed
This comparison ensures that you only pay for goods that were ordered and received, avoiding overpayments, duplicates, and fraud.
Matching Criteria
| Element | PO | Receipt | Invoice |
|---|---|---|---|
| Quantity | Ordered quantity | Quantity received | Quantity invoiced |
| Amount | Unit price × Ordered Qty | Amount received | Amount billed |
| Item/Service | Line items on PO | Goods received | Billed line items |
| Distribution | Charge accounts, taxes | Matched distributions | Invoiced distributions |
Extract 3-Way Matching Data
Below is a comprehensive SQL query to pull data across PO, Receiving, and Invoices. It is helpful for audit, reconciliation, or payment troubleshooting in Oracle EBS or Fusion.
Query Breakdown:
-
PO details:
po_headers_all,po_lines_all,po_line_locations_all,po_distributions_all -
Receipts:
rcv_transactions,rcv_shipment_headers,rcv_shipment_lines -
Invoices:
ap_invoices_all,ap_invoice_lines_all,ap_payment_schedules_all
SELECTpo.po_number,po.po_order_date,po.po_currency_code,po.po_line_number,po.po_status,po.quantity_p,po.amount_p,po.amount_received_p,po.po_line_qty,po.polineamount,po.quantity_received,po.po_promised_date,po.po_charge_account,po.promise_delivery_date,po.po_distribution_num,rcv.*,inv.invoice_num,inv.line_number,inv.invoice_line_amount_lc,inv.payment_status,inv.invoice_currency_codeFROM(SELECTpha.segment1 po_number,TO_CHAR(pha.creation_date, 'DD-Mon-YYYY', 'nls_date_language=english') po_order_date,pha.currency_code po_currency_code,pla.line_num po_line_number,pha.document_status po_status,pla.line_status po_line_status,pla.quantity quantity_p,plla.amount amount_p,plla.amount_received amount_received_p,CASEWHEN plla.quantity IS NULL THEN plla.amountELSE pla.unit_priceEND polineamount,CASEWHEN pla.quantity IS NULL THEN plla.amountELSE pla.quantityEND po_line_qty,CASEWHEN pla.quantity IS NULL THEN plla.amount - plla.amount_receivedELSE pla.quantity - plla.quantity_receivedEND qty_open,CASEWHEN plla.quantity_received IS NULL THEN plla.amount_receivedELSE plla.quantity_receivedEND quantity_received,TO_CHAR(plla.promised_date, 'DD-Mon-YYYY', 'nls_date_language=english') po_promised_date,pda.distribution_num po_distribution_num,gcc1.segment1 || '-' || gcc1.segment2 || '-' || gcc1.segment3 || '-' || gcc1.segment4 || '-' ||gcc1.segment5 || '-' || gcc1.segment6 || '-' || gcc1.segment6 || '-' || gcc1.segment7 || '-' ||gcc1.segment8 || '-' || gcc1.segment9 po_charge_account,pda.req_distribution_id,plla.line_location_id,plla.promised_date promise_delivery_date,pha.po_header_id ppo_header_id,pla.po_line_id ppo_line_idFROMpo_distributions_all pda,po_line_locations_all plla,po_lines_all pla,po_headers_all pha,gl_code_combinations gcc1WHEREpda.line_location_id = plla.line_location_id (+)AND plla.po_line_id = pla.po_line_id (+)AND pla.po_header_id = pha.po_header_id (+)AND pda.code_combination_id = gcc1.code_combination_id (+)) po,(SELECTrt.po_header_id,rt.po_line_id,rt.po_line_location_id,rt.po_distribution_id,rt.transaction_id,rsh.receipt_num po_receipt_no,TO_CHAR(rsh.creation_date, 'DD-Mon-YYYY', 'nls_date_language=english') receipt_date,rsh.approval_status receipt_status,CASEWHEN rsl.quantity_received IS NULL THEN rsl.amount_receivedELSE rsl.quantity_receivedEND re_qty,rsh.SHIPMENT_NUMFROMpo_headers_all pha1,rcv_shipment_headers rsh,rcv_shipment_lines rsl,rcv_transactions rtWHEREpha1.po_header_id = rt.po_header_idAND rt.shipment_header_id = rsh.shipment_header_idAND rsh.shipment_header_id = rsl.shipment_header_idAND rt.shipment_line_id = rsl.shipment_line_idAND pha1.po_header_id = rsl.po_header_idAND rt.transaction_type = 'RECEIVE') rcv,(SELECTaila.rcv_transaction_id,aila.po_line_id,aia.invoice_currency_code,aila.po_line_location_id,aila.po_distribution_id,aila.po_header_id,aia.invoice_id,aia.invoice_num,aila.line_number,aia.approval_status inv_status,DECODE(apsa.payment_status_flag, 'Y', 'Paid', 'P', 'Partially Paid', 'Unpaid') payment_status,(aila.amount) * (NVL(aia.exchange_rate, 1)) invoice_line_amount_lcFROMap_invoices_all aia,ap_invoice_lines_all aila,ap_payment_schedules_all apsaWHEREaia.invoice_id = aila.invoice_idAND aia.cancelled_date IS NULLAND aia.invoice_id = apsa.invoice_id (+)AND aia.org_id = apsa.org_id (+)) invWHEREpo.line_location_id = rcv.po_line_location_id (+)AND rcv.transaction_id = inv.rcv_transaction_id (+)AND rcv.po_line_id = inv.po_line_id (+)AND rcv.po_line_location_id = inv.po_line_location_id (+)AND rcv.po_distribution_id = inv.po_distribution_id (+)AND rcv.po_header_id = inv.po_header_id (+)AND po.ppo_header_id = inv.po_header_id (+)
Comments
Post a Comment