diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js index 7468e34020c..705da5a3a69 100644 --- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js +++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js @@ -4,6 +4,39 @@ frappe.query_reports["BOM Operations Time"] = { "filters": [ - + { + "fieldname": "item_code", + "label": __("Item Code"), + "fieldtype": "Link", + "width": "100", + "options": "Item", + "get_query": () =>{ + return { + filters: { "disabled": 0, "is_stock_item": 1 } + } + } + }, + { + "fieldname": "bom_id", + "label": __("BOM ID"), + "fieldtype": "MultiSelectList", + "width": "80", + "options": "BOM", + "get_data": function(txt) { + return frappe.db.get_link_options("BOM", txt); + }, + "get_query": () =>{ + return { + filters: { "docstatus": 1, "is_active": 1 } + } + } + }, + { + "fieldname": "workstation", + "label": __("Workstation"), + "fieldtype": "Link", + "width": "100", + "options": "Workstation" + }, ] }; diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py index e7a818abd5d..0bed46ac70b 100644 --- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py +++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py @@ -4,7 +4,8 @@ import frappe from frappe import _ - +from frappe.model.meta import get_field_precision +from frappe.utils import flt def execute(filters=None): data = get_data(filters) @@ -12,19 +13,15 @@ def execute(filters=None): return columns, data def get_data(filters): - data = [] + bom_wise_data = {} + bom_data, report_data = [], [] - bom_data = [] - for d in frappe.db.sql(""" - SELECT - bom.name, bom.item, bom.item_name, bom.uom, - bomps.operation, bomps.workstation, bomps.time_in_mins - FROM `tabBOM` bom, `tabBOM Operation` bomps - WHERE - bom.docstatus = 1 and bom.is_active = 1 and bom.name = bomps.parent - """, as_dict=1): + bom_operation_data = get_filtered_data(filters) + + for d in bom_operation_data: row = get_args() if d.name not in bom_data: + bom_wise_data[d.name] = [] bom_data.append(d.name) row.update(d) else: @@ -34,14 +31,49 @@ def get_data(filters): "time_in_mins": d.time_in_mins }) - data.append(row) + # maintain BOM wise data for grouping such as: + # {"BOM A": [{Row1}, {Row2}], "BOM B": ...} + bom_wise_data[d.name].append(row) used_as_subassembly_items = get_bom_count(bom_data) - for d in data: - d.used_as_subassembly_items = used_as_subassembly_items.get(d.name, 0) + for d in bom_wise_data: + for row in bom_wise_data[d]: + row.used_as_subassembly_items = used_as_subassembly_items.get(row.name, 0) + report_data.append(row) - return data + return report_data + +def get_filtered_data(filters): + bom = frappe.qb.DocType("BOM") + bom_ops = frappe.qb.DocType("BOM Operation") + + bom_ops_query = ( + frappe.qb.from_(bom) + .join(bom_ops).on(bom.name == bom_ops.parent) + .select( + bom.name, bom.item, bom.item_name, bom.uom, + bom_ops.operation, bom_ops.workstation, bom_ops.time_in_mins + ).where( + (bom.docstatus == 1) + & (bom.is_active == 1) + ) + ) + + if filters.get("item_code"): + bom_ops_query = bom_ops_query.where(bom.item == filters.get("item_code")) + + if filters.get("bom_id"): + bom_ops_query = bom_ops_query.where(bom.name.isin(filters.get("bom_id"))) + + if filters.get("workstation"): + bom_ops_query = bom_ops_query.where( + bom_ops.workstation == filters.get("workstation") + ) + + bom_operation_data = bom_ops_query.run(as_dict=True) + + return bom_operation_data def get_bom_count(bom_data): data = frappe.get_all("BOM Item", @@ -68,13 +100,13 @@ def get_columns(filters): "options": "BOM", "fieldname": "name", "fieldtype": "Link", - "width": 140 + "width": 220 }, { - "label": _("BOM Item Code"), + "label": _("Item Code"), "options": "Item", "fieldname": "item", "fieldtype": "Link", - "width": 140 + "width": 150 }, { "label": _("Item Name"), "fieldname": "item_name", @@ -85,13 +117,13 @@ def get_columns(filters): "options": "UOM", "fieldname": "uom", "fieldtype": "Link", - "width": 140 + "width": 100 }, { "label": _("Operation"), "options": "Operation", "fieldname": "operation", "fieldtype": "Link", - "width": 120 + "width": 140 }, { "label": _("Workstation"), "options": "Workstation", @@ -101,11 +133,11 @@ def get_columns(filters): }, { "label": _("Time (In Mins)"), "fieldname": "time_in_mins", - "fieldtype": "Int", - "width": 140 + "fieldtype": "Float", + "width": 120 }, { "label": _("Sub-assembly BOM Count"), "fieldname": "used_as_subassembly_items", "fieldtype": "Int", - "width": 180 + "width": 200 }]