Merge pull request #29736 from rohitwaghchaure/performance-issue-while-making-wo
fix: time out error while making work orders from production plan
This commit is contained in:
commit
ce79434a9b
@ -341,6 +341,7 @@ class ProductionPlan(Document):
|
||||
|
||||
def get_production_items(self):
|
||||
item_dict = {}
|
||||
|
||||
for d in self.po_items:
|
||||
item_details = {
|
||||
"production_item" : d.item_code,
|
||||
@ -357,12 +358,12 @@ class ProductionPlan(Document):
|
||||
"production_plan" : self.name,
|
||||
"production_plan_item" : d.name,
|
||||
"product_bundle_item" : d.product_bundle_item,
|
||||
"planned_start_date" : d.planned_start_date
|
||||
"planned_start_date" : d.planned_start_date,
|
||||
"project" : self.project
|
||||
}
|
||||
|
||||
item_details.update({
|
||||
"project": self.project or frappe.db.get_value("Sales Order", d.sales_order, "project")
|
||||
})
|
||||
if not item_details['project'] and d.sales_order:
|
||||
item_details['project'] = frappe.get_cached_value("Sales Order", d.sales_order, "project")
|
||||
|
||||
if self.get_items_from == "Material Request":
|
||||
item_details.update({
|
||||
@ -380,39 +381,59 @@ class ProductionPlan(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_work_order(self):
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import get_default_warehouse
|
||||
|
||||
wo_list, po_list = [], []
|
||||
subcontracted_po = {}
|
||||
default_warehouses = get_default_warehouse()
|
||||
|
||||
self.validate_data()
|
||||
self.make_work_order_for_finished_goods(wo_list)
|
||||
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po)
|
||||
self.make_work_order_for_finished_goods(wo_list, default_warehouses)
|
||||
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po, default_warehouses)
|
||||
self.make_subcontracted_purchase_order(subcontracted_po, po_list)
|
||||
self.show_list_created_message('Work Order', wo_list)
|
||||
self.show_list_created_message('Purchase Order', po_list)
|
||||
|
||||
def make_work_order_for_finished_goods(self, wo_list):
|
||||
def make_work_order_for_finished_goods(self, wo_list, default_warehouses):
|
||||
items_data = self.get_production_items()
|
||||
|
||||
for key, item in items_data.items():
|
||||
if self.sub_assembly_items:
|
||||
item['use_multi_level_bom'] = 0
|
||||
|
||||
set_default_warehouses(item, default_warehouses)
|
||||
work_order = self.create_work_order(item)
|
||||
if work_order:
|
||||
wo_list.append(work_order)
|
||||
|
||||
def make_work_order_for_subassembly_items(self, wo_list, subcontracted_po):
|
||||
def make_work_order_for_subassembly_items(self, wo_list, subcontracted_po, default_warehouses):
|
||||
for row in self.sub_assembly_items:
|
||||
if row.type_of_manufacturing == 'Subcontract':
|
||||
subcontracted_po.setdefault(row.supplier, []).append(row)
|
||||
continue
|
||||
|
||||
args = {}
|
||||
self.prepare_args_for_sub_assembly_items(row, args)
|
||||
work_order = self.create_work_order(args)
|
||||
work_order_data = {
|
||||
'wip_warehouse': default_warehouses.get('wip_warehouse'),
|
||||
'fg_warehouse': default_warehouses.get('fg_warehouse')
|
||||
}
|
||||
|
||||
self.prepare_data_for_sub_assembly_items(row, work_order_data)
|
||||
work_order = self.create_work_order(work_order_data)
|
||||
if work_order:
|
||||
wo_list.append(work_order)
|
||||
|
||||
def prepare_data_for_sub_assembly_items(self, row, wo_data):
|
||||
for field in ["production_item", "item_name", "qty", "fg_warehouse",
|
||||
"description", "bom_no", "stock_uom", "bom_level",
|
||||
"production_plan_item", "schedule_date"]:
|
||||
if row.get(field):
|
||||
wo_data[field] = row.get(field)
|
||||
|
||||
wo_data.update({
|
||||
"use_multi_level_bom": 0,
|
||||
"production_plan": self.name,
|
||||
"production_plan_sub_assembly_item": row.name
|
||||
})
|
||||
|
||||
def make_subcontracted_purchase_order(self, subcontracted_po, purchase_orders):
|
||||
if not subcontracted_po:
|
||||
return
|
||||
@ -423,7 +444,7 @@ class ProductionPlan(Document):
|
||||
po.schedule_date = getdate(po_list[0].schedule_date) if po_list[0].schedule_date else nowdate()
|
||||
po.is_subcontracted = 'Yes'
|
||||
for row in po_list:
|
||||
args = {
|
||||
po_data = {
|
||||
'item_code': row.production_item,
|
||||
'warehouse': row.fg_warehouse,
|
||||
'production_plan_sub_assembly_item': row.name,
|
||||
@ -433,9 +454,9 @@ class ProductionPlan(Document):
|
||||
|
||||
for field in ['schedule_date', 'qty', 'uom', 'stock_uom', 'item_name',
|
||||
'description', 'production_plan_item']:
|
||||
args[field] = row.get(field)
|
||||
po_data[field] = row.get(field)
|
||||
|
||||
po.append('items', args)
|
||||
po.append('items', po_data)
|
||||
|
||||
po.set_missing_values()
|
||||
po.flags.ignore_mandatory = True
|
||||
@ -452,24 +473,9 @@ class ProductionPlan(Document):
|
||||
doc_list = [get_link_to_form(doctype, p) for p in doc_list]
|
||||
msgprint(_("{0} created").format(comma_and(doc_list)))
|
||||
|
||||
def prepare_args_for_sub_assembly_items(self, row, args):
|
||||
for field in ["production_item", "item_name", "qty", "fg_warehouse",
|
||||
"description", "bom_no", "stock_uom", "bom_level",
|
||||
"production_plan_item", "schedule_date"]:
|
||||
args[field] = row.get(field)
|
||||
|
||||
args.update({
|
||||
"use_multi_level_bom": 0,
|
||||
"production_plan": self.name,
|
||||
"production_plan_sub_assembly_item": row.name
|
||||
})
|
||||
|
||||
def create_work_order(self, item):
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import (
|
||||
OverProductionError,
|
||||
get_default_warehouse,
|
||||
)
|
||||
warehouse = get_default_warehouse()
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError
|
||||
|
||||
wo = frappe.new_doc("Work Order")
|
||||
wo.update(item)
|
||||
wo.planned_start_date = item.get('planned_start_date') or item.get('schedule_date')
|
||||
@ -478,11 +484,11 @@ class ProductionPlan(Document):
|
||||
wo.fg_warehouse = item.get("warehouse")
|
||||
|
||||
wo.set_work_order_operations()
|
||||
wo.set_required_items()
|
||||
|
||||
if not wo.fg_warehouse:
|
||||
wo.fg_warehouse = warehouse.get('fg_warehouse')
|
||||
try:
|
||||
wo.flags.ignore_mandatory = True
|
||||
wo.flags.ignore_validate = True
|
||||
wo.insert()
|
||||
return wo.name
|
||||
except OverProductionError:
|
||||
@ -1023,3 +1029,8 @@ def get_sub_assembly_items(bom_no, bom_data, to_produce_qty, indent=0):
|
||||
|
||||
if d.value:
|
||||
get_sub_assembly_items(d.value, bom_data, stock_qty, indent=indent+1)
|
||||
|
||||
def set_default_warehouses(row, default_warehouses):
|
||||
for field in ['wip_warehouse', 'fg_warehouse']:
|
||||
if not row.get(field):
|
||||
row[field] = default_warehouses.get(field)
|
@ -76,7 +76,6 @@ class WorkOrder(Document):
|
||||
|
||||
self.set_required_items(reset_only_qty = len(self.get("required_items")))
|
||||
|
||||
|
||||
def validate_sales_order(self):
|
||||
if self.sales_order:
|
||||
self.check_sales_order_on_hold_or_close()
|
||||
@ -546,7 +545,7 @@ class WorkOrder(Document):
|
||||
if node.is_bom:
|
||||
operations.extend(_get_operations(node.name, qty=node.exploded_qty))
|
||||
|
||||
bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
|
||||
bom_qty = frappe.get_cached_value("BOM", self.bom_no, "quantity")
|
||||
operations.extend(_get_operations(self.bom_no, qty=1.0/bom_qty))
|
||||
|
||||
for correct_index, operation in enumerate(operations, start=1):
|
||||
@ -627,7 +626,7 @@ class WorkOrder(Document):
|
||||
frappe.delete_doc("Job Card", d.name)
|
||||
|
||||
def validate_production_item(self):
|
||||
if frappe.db.get_value("Item", self.production_item, "has_variants"):
|
||||
if frappe.get_cached_value("Item", self.production_item, "has_variants"):
|
||||
frappe.throw(_("Work Order cannot be raised against a Item Template"), ItemHasVariantError)
|
||||
|
||||
if self.production_item:
|
||||
|
Loading…
Reference in New Issue
Block a user