From 9139994686bbdb34f03a70c7bbf0d5d101db36ac Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 11 Aug 2026 18:16:38 +0530 Subject: [PATCH] fix: skip PO items with invoice-created receipts in billing repair patch A Purchase Receipt row created from a Purchase Invoice carries both purchase_order_item and purchase_invoice_item, and its billed_amt is pinned to the row amount by update_billing_status. Redistributing the PO-invoiced pool over such rows zeroes the invoice-created receipt and flips it from Completed to To Bill, so the repair leaves those PO Items untouched. (cherry picked from commit ace4230f973d13fbd9d67a2d11c18e4661ed13b5) --- ...lculate_purchase_receipt_billing_status.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/erpnext/patches/v16_0/recalculate_purchase_receipt_billing_status.py b/erpnext/patches/v16_0/recalculate_purchase_receipt_billing_status.py index 4acbe0375f8..9f0afb79c2e 100644 --- a/erpnext/patches/v16_0/recalculate_purchase_receipt_billing_status.py +++ b/erpnext/patches/v16_0/recalculate_purchase_receipt_billing_status.py @@ -25,6 +25,11 @@ def execute(): def get_affected_purchase_order_items() -> list[str]: purchase_order_items = get_candidate_purchase_order_items() + if purchase_order_items: + purchase_order_items = exclude_purchase_order_items_with_invoice_created_receipts( + purchase_order_items + ) + if not purchase_order_items: return [] @@ -55,6 +60,21 @@ def get_affected_purchase_order_items() -> list[str]: ] +def exclude_purchase_order_items_with_invoice_created_receipts(purchase_order_items: list[str]) -> list[str]: + invoice_created_receipt_items = set( + frappe.get_all( + "Purchase Receipt Item", + filters={ + "purchase_order_item": ("in", purchase_order_items), + "purchase_invoice_item": ("is", "set"), + "docstatus": 1, + }, + pluck="purchase_order_item", + ) + ) + return [item for item in purchase_order_items if item not in invoice_created_receipt_items] + + def get_candidate_purchase_order_items() -> list[str]: purchase_receipt = frappe.qb.DocType("Purchase Receipt") purchase_receipt_item = frappe.qb.DocType("Purchase Receipt Item")