From 48beb2ee23a1a95ae46b8782dfd3749b45e04d2f 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. (cherry picked from commit a3e9d13da30089467441cf48586e5a6f3e211feb) # Conflicts: # erpnext/controllers/sales_and_purchase_return.py --- erpnext/controllers/sales_and_purchase_return.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index c58580739e3..efca82b425b 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -158,7 +158,22 @@ def validate_returned_items(doc): ): frappe.throw(_("Warehouse is mandatory")) +<<<<<<< HEAD items_returned = True +======= + 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: + items_returned = True +>>>>>>> a3e9d13da3 (fix(sales): reject sales returns where every item has zero quantity) elif d.item_name: items_returned = True