[Fix] Timeout issue while saving multilevel BOM (#13118)
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 8cafb91..5e1e52a 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -47,7 +47,6 @@
self.validate_currency()
self.set_conversion_rate()
self.validate_uom_is_interger()
- self.update_stock_qty()
self.set_bom_material_details()
self.validate_materials()
self.validate_operations()
@@ -247,14 +246,12 @@
set_default(self, "item")
item = frappe.get_doc("Item", self.item)
if item.default_bom != self.name:
- item.default_bom = self.name
- item.save(ignore_permissions = True)
+ frappe.db.set_value('Item', self.item, 'default_bom', self.name)
else:
frappe.db.set(self, "is_default", 0)
item = frappe.get_doc("Item", self.item)
if item.default_bom == self.name:
- item.default_bom = None
- item.save(ignore_permissions = True)
+ frappe.db.set_value('Item', self.item, 'default_bom', None)
def clear_operations(self):
if not self.with_operations:
@@ -291,6 +288,8 @@
m.uom = m.stock_uom
m.qty = m.stock_qty
+ m.db_update()
+
def validate_uom_is_interger(self):
from erpnext.utilities.transaction_base import validate_uom_is_integer
validate_uom_is_integer(self, "uom", "qty", "BOM Item")
@@ -333,19 +332,23 @@
def check_recursion(self):
""" Check whether recursion occurs in any bom"""
+ bom_list = self.traverse_tree()
+ bom_nos = frappe.get_all('BOM Item', fields=["bom_no"],
+ filters={'parent': ('in', bom_list), 'parenttype': 'BOM'})
- check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
- for d in check_list:
- bom_list, count = [self.name], 0
- while (len(bom_list) > count ):
- boms = frappe.db.sql(" select %s from `tabBOM Item` where %s = %s and parenttype='BOM'" %
- (d[0], d[1], '%s'), cstr(bom_list[count]))
- count = count + 1
- for b in boms:
- if b[0] == self.name:
- frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(b[0], self.name))
- if b[0]:
- bom_list.append(b[0])
+ raise_exception = False
+ if bom_nos and self.name in [d.bom_no for d in bom_nos]:
+ raise_exception = True
+
+ if not raise_exception:
+ bom_nos = frappe.get_all('BOM Item', fields=["parent"],
+ filters={'bom_no': self.name, 'parenttype': 'BOM'})
+
+ if self.name in [d.parent for d in bom_nos]:
+ raise_exception = True
+
+ if raise_exception:
+ frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(self.name, self.name))
def update_cost_and_exploded_items(self, bom_list=[]):
bom_list = self.traverse_tree(bom_list)