fix: % Amount Billed exceeds 100% on fully rejected Purchase Receipts (#58897)

* fix: include rejected qty in Purchase Receipt billing base

* test: per billed stays 100% for fully rejected receipt
This commit is contained in:
Shllokkk
2026-09-09 15:03:59 +05:30
committed by GitHub
parent 3856638d01
commit 79c8e4db7f
2 changed files with 44 additions and 6 deletions

View File

@@ -1314,10 +1314,14 @@ def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate
returned_qty = flt(item_wise_returned_qty.get(item.name))
returned_amount = flt(returned_qty) * flt(item.rate)
pending_amount = flt(item.amount) - returned_amount
if buying_settings.bill_for_rejected_quantity_in_purchase_invoice:
pending_amount = flt(item.amount)
total_billable_amount = abs(flt(item.amount))
# When rejected qty is billable, its value is part of the billable base too
rejected_amount = 0.0
if buying_settings.bill_for_rejected_quantity_in_purchase_invoice:
rejected_amount = flt(item.rejected_qty * item.rate, item.precision("amount"))
pending_amount = flt(item.amount) + rejected_amount
total_billable_amount = abs(flt(item.amount) + rejected_amount)
if pending_amount > 0:
total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt
@@ -1327,9 +1331,7 @@ def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate
if pr_doc.get("is_return") and not total_amount and total_billed_amount:
total_amount = total_billed_amount
amount = item.amount
if frappe.db.get_single_value("Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"):
amount += flt(item.rejected_qty * item.rate, item.precision("amount"))
amount = flt(item.amount) + rejected_amount
if adjust_incoming_rate:
adjusted_amt = 0.0

View File

@@ -600,6 +600,42 @@ class TestPurchaseReceipt(ERPNextTestSuite):
return_pr.cancel()
pr.cancel()
def test_per_billed_for_fully_rejected_receipt(self):
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage
bill_rejected = frappe.db.get_single_value(
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"
)
frappe.db.set_single_value("Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice", 1)
try:
# Fully rejected receipt: accepted qty 0, whole qty in rejected warehouse
pr = make_purchase_receipt(
received_qty=10,
qty=0,
rejected_qty=10,
rate=9.5,
rejected_warehouse="_Test Warehouse 1 - _TC",
do_not_save=True,
)
pr.items[0].warehouse = ""
pr.submit()
# Bill the rejected qty (10 x 9.5) directly against the receipt item
pr.items[0].db_set("billed_amt", 95)
update_billing_percentage(pr)
pr.load_from_db()
# Billing the rejected qty must not push per_billed above 100
self.assertEqual(pr.per_billed, 100)
self.assertEqual(pr.status, "Completed")
pr.cancel()
finally:
frappe.db.set_single_value(
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice", bill_rejected
)
def test_purchase_receipt_for_rejected_gle_without_accepted_warehouse(self):
from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse