diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 295a65ef8e6..acf7dfdaa11 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -87,20 +87,29 @@ def get_batch_naming_series(): class Batch(Document): def autoname(self): """Generate random ID for batch if not specified""" - if not self.batch_id: - create_new_batch, batch_number_series = frappe.db.get_value( - "Item", self.item, ["create_new_batch", "batch_number_series"] - ) - if create_new_batch: - if batch_number_series: - self.batch_id = make_autoname(batch_number_series, doc=self) - elif batch_uses_naming_series(): - self.batch_id = self.get_name_from_naming_series() - else: - self.batch_id = get_name_from_hash() + if self.batch_id: + self.name = self.batch_id + return + + create_new_batch, batch_number_series = frappe.db.get_value( + "Item", self.item, ["create_new_batch", "batch_number_series"] + ) + + if not create_new_batch: + frappe.throw(_("Batch ID is mandatory"), frappe.MandatoryError) + + while not self.batch_id: + if batch_number_series: + self.batch_id = make_autoname(batch_number_series, doc=self) + elif batch_uses_naming_series(): + self.batch_id = self.get_name_from_naming_series() else: - frappe.throw(_("Batch ID is mandatory"), frappe.MandatoryError) + self.batch_id = get_name_from_hash() + + # User might have manually created a batch with next number + if frappe.db.exists("Batch", self.batch_id): + self.batch_id = None self.name = self.batch_id diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index c1190c8fc57..e67504a5f5a 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -8,6 +8,8 @@ from frappe.utils import cint, flt from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.stock.doctype.batch.batch import UnableToSelectBatchError, get_batch_no, get_batch_qty +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt from erpnext.stock.get_item_details import get_item_details @@ -19,11 +21,13 @@ class TestBatch(FrappeTestCase): ) @classmethod - def make_batch_item(cls, item_name): + def make_batch_item(cls, item_name=None): from erpnext.stock.doctype.item.test_item import make_item - if not frappe.db.exists(item_name): + if not frappe.db.exists("Item", item_name): return make_item(item_name, dict(has_batch_no=1, create_new_batch=1, is_stock_item=1)) + else: + return frappe.get_doc("Item", item_name) def test_purchase_receipt(self, batch_qty=100): """Test automated batch creation from Purchase Receipt""" @@ -237,7 +241,7 @@ class TestBatch(FrappeTestCase): if not use_naming_series: frappe.set_value("Stock Settings", "Stock Settings", "use_naming_series", 0) - def make_new_batch(self, item_name, batch_id=None, do_not_insert=0): + def make_new_batch(self, item_name=None, batch_id=None, do_not_insert=0): batch = frappe.new_doc("Batch") item = self.make_batch_item(item_name) batch.item = item.name @@ -300,6 +304,26 @@ class TestBatch(FrappeTestCase): details = get_item_details(args) self.assertEqual(details.get("price_list_rate"), 400) + def test_autocreation_of_batches(self): + """ + Test if auto created batch no excludes existing batch numbers + """ + item_code = make_item( + properties={ + "has_batch_no": 1, + "batch_number_series": "BATCHEXISTING.###", + "create_new_batch": 1, + } + ).name + + manually_created_batch = self.make_new_batch(item_code, batch_id="BATCHEXISTING001").name + + pr_1 = make_purchase_receipt(item_code=item_code, qty=1, batch_no=manually_created_batch) + pr_2 = make_purchase_receipt(item_code=item_code, qty=1) + + self.assertNotEqual(pr_1.items[0].batch_no, pr_2.items[0].batch_no) + self.assertEqual("BATCHEXISTING002", pr_2.items[0].batch_no) + def create_batch(item_code, rate, create_item_price_for_batch): pi = make_purchase_invoice( diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 65c30de0978..2d9402e5325 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -1507,6 +1507,7 @@ def make_purchase_receipt(**args): "conversion_factor": args.conversion_factor or 1.0, "stock_qty": flt(qty) * (flt(args.conversion_factor) or 1.0), "serial_no": args.serial_no, + "batch_no": args.batch_no, "stock_uom": args.stock_uom or "_Test UOM", "uom": uom, "cost_center": args.cost_center