fix(accounts): stop counting received qty on non-stock invoice returns (backport #58924) (#58928)

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
This commit is contained in:
mergify[bot]
2026-09-09 09:20:26 +00:00
committed by GitHub
parent 75a5d2b766
commit 228108ad4c
3 changed files with 37 additions and 17 deletions

View File

@@ -78,7 +78,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
const me = this;
super.refresh();
hide_fields(this.frm.doc);
hide_fields(this.frm);
// Show / Hide button
this.show_general_ledger();
erpnext.accounts.ledger_preview.show_accounting_ledger_preview(this.frm);
@@ -435,7 +435,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
}
is_paid() {
hide_fields(this.frm.doc);
hide_fields(this.frm);
if (cint(this.frm.doc.is_paid)) {
this.frm.set_value("allocate_advances_automatically", 0);
this.frm.set_value("payment_terms_template", "");
@@ -499,28 +499,26 @@ cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
// Hide Fields
// ------------
function hide_fields(doc) {
var parent_fields = ["due_date", "is_opening", "advances_section", "from_date", "to_date"];
function hide_fields(frm) {
const doc = frm.doc;
const parent_fields = ["due_date", "is_opening", "advances_section", "from_date", "to_date"];
if (cint(doc.is_paid) == 1) {
hide_field(parent_fields);
frm.toggle_display(parent_fields, false);
} else {
for (var i in parent_fields) {
var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
if (!docfield.hidden) unhide_field(parent_fields[i]);
for (const fieldname of parent_fields) {
const docfield = frappe.meta.docfield_map[doc.doctype][fieldname];
if (!docfield.hidden) frm.toggle_display(fieldname, true);
}
}
var item_fields_stock = ["warehouse_section", "received_qty", "rejected_qty"];
const item_fields_stock = ["warehouse_section", "received_qty", "rejected_qty"];
if (cur_frm.fields_dict["items"]) {
cur_frm.fields_dict["items"].grid.set_column_disp(
item_fields_stock,
cint(doc.update_stock) == 1 || cint(doc.is_return) == 1 ? true : false
);
if (frm.fields_dict["items"]) {
frm.fields_dict["items"].grid.set_column_disp(item_fields_stock, cint(doc.update_stock) == 1);
}
cur_frm.refresh_fields();
frm.refresh_fields();
}
cur_frm.fields_dict.cash_bank_account.get_query = function (doc) {
@@ -736,7 +734,7 @@ frappe.ui.form.on("Purchase Invoice", {
},
update_stock: function (frm) {
hide_fields(frm.doc);
hide_fields(frm);
frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock ? true : false);
},

View File

@@ -3081,6 +3081,23 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin):
self.assertRaises(StockOverReturnError, return_doc.save)
def test_partial_returns_ignore_received_qty_without_update_stock(self):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
invoice = make_purchase_invoice(qty=10, received_qty=10)
first_return = make_return_doc(invoice.doctype, invoice.name)
first_return.items[0].qty = -4
first_return.save().submit()
self.assertEqual(first_return.items[0].received_qty, -10)
second_return = make_return_doc(invoice.doctype, invoice.name)
second_return.items[0].qty = -6
second_return.save().submit()
self.assertEqual(second_return.docstatus, 1)
def test_apply_discount_on_grand_total(self):
"""
To test if after applying discount on grand total,

View File

@@ -190,7 +190,12 @@ def validate_quantity(doc, key, args, ref, valid_items, already_returned_items):
if (doc.doctype == "Purchase Invoice" or doc.doctype == "Sales Invoice") and not doc.update_stock:
fields = ["qty"]
if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"]:
tracks_accepted_rejected_split = doc.doctype in (
"Purchase Receipt",
"Subcontracting Receipt",
) or (doc.doctype == "Purchase Invoice" and doc.update_stock)
if tracks_accepted_rejected_split:
if not args.get("return_qty_from_rejected_warehouse"):
fields.extend(["received_qty", "rejected_qty"])
else: