fix: validate duplicate SBB
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 8ffbaa1..dd27200 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -46,6 +46,9 @@
class StockController(AccountsController):
def validate(self):
super(StockController, self).validate()
+
+ if self.docstatus == 0:
+ self.validate_duplicate_serial_and_batch_bundle()
if not self.get("is_return"):
self.validate_inspection()
self.validate_serialized_batch()
@@ -55,6 +58,32 @@
self.validate_internal_transfer()
self.validate_putaway_capacity()
+ def validate_duplicate_serial_and_batch_bundle(self):
+ if sbb_list := [
+ item.get("serial_and_batch_bundle")
+ for item in self.items
+ if item.get("serial_and_batch_bundle")
+ ]:
+ SLE = frappe.qb.DocType("Stock Ledger Entry")
+ data = (
+ frappe.qb.from_(SLE)
+ .select(SLE.voucher_type, SLE.voucher_no, SLE.serial_and_batch_bundle)
+ .where(
+ (SLE.docstatus == 1)
+ & (SLE.serial_and_batch_bundle.notnull())
+ & (SLE.serial_and_batch_bundle.isin(sbb_list))
+ )
+ .limit(1)
+ ).run(as_dict=True)
+
+ if data:
+ data = data[0]
+ frappe.throw(
+ _("Serial and Batch Bundle {0} is already used in {1} {2}.").format(
+ frappe.bold(data.serial_and_batch_bundle), data.voucher_type, data.voucher_no
+ )
+ )
+
def make_gl_entries(self, gl_entries=None, from_repost=False):
if self.docstatus == 2:
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)