From 69d7a640ee7da732d7983ecdd2574acfbc711fa1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 12 Dec 2023 16:18:32 +0530 Subject: [PATCH] fix: negative batch issue (#38688) --- .../serial_and_batch_bundle.py | 7 +++- .../doctype/stock_entry/test_stock_entry.py | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) 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 67858815bb..ecb9314fbb 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 @@ -709,6 +709,7 @@ class SerialandBatchBundle(Document): "item_code": self.item_code, "warehouse": self.warehouse, "batch_no": batches, + "consider_negative_batches": True, } ) ) @@ -719,6 +720,9 @@ class SerialandBatchBundle(Document): available_batches = get_available_batches_qty(available_batches) for batch_no in batches: if batch_no not in available_batches or available_batches[batch_no] < 0: + if flt(available_batches.get(batch_no)) < 0: + self.validate_negative_batch(batch_no, available_batches[batch_no]) + self.throw_error_message( f"Batch {bold(batch_no)} is not available in the selected warehouse {self.warehouse}" ) @@ -1491,7 +1495,8 @@ def get_auto_batch_nos(kwargs): available_batches, stock_ledgers_batches, pos_invoice_batches, sre_reserved_batches ) - available_batches = list(filter(lambda x: x.qty > 0, available_batches)) + if not kwargs.consider_negative_batches: + available_batches = list(filter(lambda x: x.qty > 0, available_batches)) if not qty: return available_batches diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index eb1c7a85eb..e0e364f397 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -1733,6 +1733,45 @@ class TestStockEntry(FrappeTestCase): self.assertFalse(doc.is_enqueue_action()) frappe.flags.in_test = True + def test_negative_batch(self): + item_code = "Test Negative Batch Item - 001" + make_item( + item_code, + {"has_batch_no": 1, "create_new_batch": 1, "batch_naming_series": "Test-BCH-NNS.#####"}, + ) + + se1 = make_stock_entry( + item_code=item_code, + purpose="Material Receipt", + qty=100, + target="_Test Warehouse - _TC", + ) + + se1.reload() + + batch_no = get_batch_from_bundle(se1.items[0].serial_and_batch_bundle) + + se2 = make_stock_entry( + item_code=item_code, + purpose="Material Issue", + batch_no=batch_no, + qty=10, + source="_Test Warehouse - _TC", + ) + + se2.reload() + + se3 = make_stock_entry( + item_code=item_code, + purpose="Material Receipt", + qty=100, + target="_Test Warehouse - _TC", + ) + + se3.reload() + + self.assertRaises(frappe.ValidationError, se1.cancel) + def make_serialized_item(**args): args = frappe._dict(args)