From 61c31f0cd053c993101d3287e91993ed93faa6cd Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 21 Dec 2025 21:37:13 +0530 Subject: [PATCH] fix: same serial number was picked in multiple sales invoices --- .../serial_and_batch_bundle.py | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 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 5c15245c5f6..1cd325d7b9e 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 @@ -2042,13 +2042,7 @@ def get_available_serial_nos(kwargs): kwargs, reserved_entries, reserved_voucher_details ): filters["name"] = ("in", reserved_serial_nos) - return frappe.get_all( - "Serial No", - fields=fields, - filters=filters, - limit=cint(kwargs.qty) or 10000000, - order_by=order_by, - ) + return get_serial_nos_based_on_filters(filters, fields, order_by, kwargs) # Check if serial nos are reserved for other vouchers then ignore those serial nos elif ignore_reserved_serial_nos := get_other_doc_reserved_serials( @@ -2087,13 +2081,47 @@ def get_available_serial_nos(kwargs): filters["batch_no"] = ("in", batches) - return frappe.get_all( - "Serial No", - fields=fields, - filters=filters, - limit=cint(kwargs.qty) or 10000000, - order_by=order_by, - ) + return get_serial_nos_based_on_filters(filters, fields, order_by, kwargs) + + +def get_serial_nos_based_on_filters(filters, fields, order_by, kwargs): + doctype = frappe.qb.DocType("Serial No") + + order_by_column = getattr(doctype, order_by) + query = frappe.qb.from_(doctype).orderby(order_by_column).limit(cint(kwargs.qty) or 10000000).for_update() + + for key, value in filters.items(): + column = getattr(doctype, key) + + if isinstance(value, tuple): + operator = value[0] + + if operator == "between": + query = query.where(column.between(value[1], value[2])) + + elif operator == "in": + query = query.where(column.isin(value[1])) + + elif operator == "not in": + query = query.where(column.notin(value[1])) + + elif operator == "is": + if value[1] == "set": + query = query.where(column.isnotnull()) + elif value[1] == "not set": + query = query.where(column.isnull()) + else: + query = query.where(column == value) + + for field in fields: + if " as " in field.lower(): + # Split field and alias + field_name, alias = field.split(" as ", 1) + query = query.select(getattr(doctype, field_name).as_(alias)) + else: + query = query.select(getattr(doctype, field)) + + return query.run(as_dict=True) def get_serial_nos_from_sre(kwargs):