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

* fix: include rejected qty in Purchase Receipt billing base

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: per billed stays 100% for fully rejected receipt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Shllokkk
2026-09-09 14:58:18 +05:30
committed by GitHub
parent fd492100b0
commit 3761eb8cbe
2 changed files with 46 additions and 6 deletions

View File

@@ -200,10 +200,14 @@ def update_billing_percentage(
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
@@ -213,9 +217,7 @@ def update_billing_percentage(
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

@@ -617,6 +617,44 @@ class TestPurchaseReceipt(ERPNextTestSuite):
return_pr.cancel()
pr.cancel()
def test_per_billed_for_fully_rejected_receipt(self):
from erpnext.stock.doctype.purchase_receipt.services.billing_status 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