Merge pull request #57194 from aerele/fix-operation-batch-size-flag-n-plus-one

fix: batch operation batch-size flag lookups to avoid n+1 query in wo…
This commit is contained in:
Mihir Kandoi
2026-07-17 07:47:59 +05:30
committed by GitHub

View File

@@ -194,29 +194,49 @@ class OperationsService:
op.wip_warehouse = self.doc.wip_warehouse
def _collect_bom_operations(self):
operations = []
groups = []
if self.doc.use_multi_level_bom:
bom_tree = frappe.get_doc("BOM", self.doc.bom_no).get_tree_representation()
for node in reversed(bom_tree.level_order_traversal()):
if node.is_bom:
qty = node.exploded_qty / node.bom_qty
operations.extend(self._bom_operations(node.name, qty=qty, exploded=True))
groups.append((self._bom_operations(node.name), qty, True))
bom_qty = frappe.get_cached_value("BOM", self.doc.bom_no, "quantity")
operations.extend(self._bom_operations(self.doc.bom_no, qty=bom_qty))
groups.append((self._bom_operations(self.doc.bom_no), bom_qty, False))
all_rows = [d for rows, qty, exploded in groups for d in rows]
batch_size_flags = self._get_batch_size_flags(d.operation for d in all_rows)
operations = []
for rows, qty, exploded in groups:
for d in rows:
self._adjust_operation_row(d, qty, exploded, batch_size_flags)
operations.append(d)
return operations
def _bom_operations(self, bom_no, qty=1, exploded=False):
data = frappe.get_all(
def _bom_operations(self, bom_no):
return frappe.get_all(
"BOM Operation", filters={"parent": bom_no}, fields=_BOM_OPERATION_FIELDS, order_by="idx"
)
for d in data:
self._adjust_operation_row(d, qty, exploded)
return data
def _adjust_operation_row(self, d, qty, exploded):
def _get_batch_size_flags(self, operation_names):
names = {name for name in operation_names if name}
if not names:
return {}
return dict(
frappe.get_all(
"Operation",
filters={"name": ["in", list(names)]},
fields=["name", "create_job_card_based_on_batch_size"],
as_list=True,
limit_page_length=0,
)
)
def _adjust_operation_row(self, d, qty, exploded, batch_size_flags):
if not d.fixed_time:
if frappe.get_value("Operation", d.operation, "create_job_card_based_on_batch_size"):
if batch_size_flags.get(d.operation):
qty = d.batch_size
d.time_in_mins = d.time_in_mins * flt(qty) if exploded else d.time_in_mins / flt(qty)