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 eede928827..620b9606a7 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 @@ -1004,13 +1004,17 @@ def make_serial_nos(item_code, serial_nos): item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) serial_nos = [d.get("serial_no") for d in serial_nos if d.get("serial_no")] + existing_serial_nos = frappe.get_all("Serial No", filters={"name": ("in", serial_nos)}) + + existing_serial_nos = [d.get("name") for d in existing_serial_nos if d.get("name")] + serial_nos = list(set(serial_nos) - set(existing_serial_nos)) + + if not serial_nos: + return serial_nos_details = [] user = frappe.session.user for serial_no in serial_nos: - if frappe.db.exists("Serial No", serial_no): - continue - serial_nos_details.append( ( serial_no, @@ -1046,9 +1050,16 @@ def make_serial_nos(item_code, serial_nos): def make_batch_nos(item_code, batch_nos): item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) - batch_nos = [d.get("batch_no") for d in batch_nos if d.get("batch_no")] + existing_batches = frappe.get_all("Batch", filters={"name": ("in", batch_nos)}) + + existing_batches = [d.get("name") for d in existing_batches if d.get("name")] + + batch_nos = list(set(batch_nos) - set(existing_batches)) + if not batch_nos: + return + batch_nos_details = [] user = frappe.session.user for batch_no in batch_nos: diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 19757479a5..0d453fb841 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -10,6 +10,8 @@ from frappe.utils import add_days, add_to_date, flt, nowdate, nowtime, today from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( add_serial_batch_ledgers, + make_batch_nos, + make_serial_nos, ) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry @@ -481,6 +483,38 @@ class TestSerialandBatchBundle(FrappeTestCase): docstatus = frappe.db.get_value("Serial and Batch Bundle", bundle, "docstatus") self.assertEqual(docstatus, 2) + def test_batch_duplicate_entry(self): + item_code = make_item(properties={"has_batch_no": 1}).name + + batch_id = "TEST-BATTCCH-VAL-00001" + batch_nos = [{"batch_no": batch_id, "qty": 1}] + + make_batch_nos(item_code, batch_nos) + self.assertTrue(frappe.db.exists("Batch", batch_id)) + + batch_id = "TEST-BATTCCH-VAL-00001" + batch_nos = [{"batch_no": batch_id, "qty": 1}] + + # Shouldn't throw duplicate entry error + make_batch_nos(item_code, batch_nos) + self.assertTrue(frappe.db.exists("Batch", batch_id)) + + def test_serial_no_duplicate_entry(self): + item_code = make_item(properties={"has_serial_no": 1}).name + + serial_no_id = "TEST-SNID-VAL-00001" + serial_nos = [{"serial_no": serial_no_id, "qty": 1}] + + make_serial_nos(item_code, serial_nos) + self.assertTrue(frappe.db.exists("Serial No", serial_no_id)) + + serial_no_id = "TEST-SNID-VAL-00001" + serial_nos = [{"batch_no": serial_no_id, "qty": 1}] + + # Shouldn't throw duplicate entry error + make_serial_nos(item_code, serial_nos) + self.assertTrue(frappe.db.exists("Serial No", serial_no_id)) + def get_batch_from_bundle(bundle): from erpnext.stock.serial_batch_bundle import get_batch_nos