From a3e9d13da30089467441cf48586e5a6f3e211feb Mon Sep 17 00:00:00 2001 From: R-Jayaraman Date: Thu, 30 Jul 2026 12:11:11 +0530 Subject: [PATCH] fix(sales): reject sales returns where every item has zero quantity validate_returned_items() set items_returned=True whenever a row matched a valid item from the original document, even if its qty was 0. This let a Sales Invoice, Delivery Note, or POS Invoice return be submitted with every line at qty=0 - a no-op document with no stock or financial effect that still consumed a document number and linked back to the original transaction. Scoped to the Sales side only: items_returned now flips to True for Sales Invoice/Delivery Note/POS Invoice only when qty (or received_qty) is actually negative, so an all-zero sales return correctly hits the existing "At least one item should be entered with negative quantity" check. Purchase Invoice, Purchase Receipt, and Subcontracting Receipt are unchanged. --- erpnext/controllers/sales_and_purchase_return.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 3148834ebec..f03541412e1 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -160,7 +160,14 @@ def validate_returned_items(doc): ): frappe.throw(_("Warehouse is mandatory")) - if doc.doctype in ("Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"): + if doc.doctype in ( + "Purchase Invoice", + "Purchase Receipt", + "Subcontracting Receipt", + "Sales Invoice", + "Delivery Note", + "POS Invoice", + ): if flt(d.qty) < 0 or flt(d.get("received_qty")) < 0: items_returned = True else: