diff --git a/erpnext/manufacturing/doctype/work_order/services/operations.py b/erpnext/manufacturing/doctype/work_order/services/operations.py index 1d1d061cb38..153c9be06d0 100644 --- a/erpnext/manufacturing/doctype/work_order/services/operations.py +++ b/erpnext/manufacturing/doctype/work_order/services/operations.py @@ -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)