From a638dece6b79ef26fe8486dfa1e3baf0afcd13b7 Mon Sep 17 00:00:00 2001 From: kavin-114 Date: Thu, 29 Jan 2026 02:17:20 +0530 Subject: [PATCH 1/2] fix(stock): remove is_return condition on pos batch qty calculation (cherry picked from commit 2c19c1fd061bb3d60cf870976985d63790fdad67) --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 46be3cbbf8f..8ab75360c08 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -2477,11 +2477,11 @@ def get_reserved_batches_for_pos(kwargs) -> dict: key = (row.batch_no, row.warehouse) if key in pos_batches: - pos_batches[key]["qty"] -= row.qty * -1 if row.is_return else row.qty + pos_batches[key]["qty"] += row.qty * -1 else: pos_batches[key] = frappe._dict( { - "qty": (row.qty * -1 if not row.is_return else row.qty), + "qty": row.qty * -1, "warehouse": row.warehouse, } ) From 5b5d0f56de54c734eae080d9754bcec89ec3920a Mon Sep 17 00:00:00 2001 From: kavin-114 Date: Tue, 3 Feb 2026 12:43:09 +0530 Subject: [PATCH 2/2] test: add unit test case for pos reserved with return qty (cherry picked from commit 12ec997027591ea57ccf3b779d0dcd4d7474f464) --- .../doctype/pos_invoice/test_pos_invoice.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index 97b3e87770f..c1be1d2eae0 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -838,6 +838,53 @@ class TestPOSInvoice(unittest.TestCase): if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC": self.assertEqual(batch.qty, 5) + def test_pos_batch_reservation_with_return_qty(self): + """ + Test POS Invoice reserved qty for batch without bundle with return invoices. + """ + from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( + get_auto_batch_nos, + ) + from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_batch_item_with_batch, + ) + + create_batch_item_with_batch("_Batch Item Reserve Return", "TestBatch-RR 01") + se = make_stock_entry( + target="_Test Warehouse - _TC", + item_code="_Batch Item Reserve Return", + qty=30, + basic_rate=100, + ) + + se.reload() + + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + # POS Invoice for the batch without bundle + pos_inv = create_pos_invoice(item="_Batch Item Reserve Return", rate=300, qty=15, do_not_save=1) + pos_inv.append( + "payments", + {"mode_of_payment": "Cash", "amount": 4500}, + ) + pos_inv.items[0].batch_no = batch_no + pos_inv.save() + pos_inv.submit() + + # POS Invoice return + pos_return = make_sales_return(pos_inv.name) + + pos_return.insert() + pos_return.submit() + + batches = get_auto_batch_nos( + frappe._dict({"item_code": "_Batch Item Reserve Return", "warehouse": "_Test Warehouse - _TC"}) + ) + + for batch in batches: + if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC": + self.assertEqual(batch.qty, 30) + def test_pos_batch_item_qty_validation(self): from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( BatchNegativeStockError,