Merge pull request #29375 from marination/bom-ops-report
fix: (enhance) BOM Operations Report
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 7468e34..0eb22a2 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": "100",
+ "options": "BOM",
+ "get_data": function(txt) {
+ return frappe.db.get_link_options("BOM", txt);
+ },
+ "get_query": () =>{
+ return {
+ filters: { "docstatus": 1, "is_active": 1, "with_operations": 1 }
+ }
+ }
+ },
+ {
+ "fieldname": "workstation",
+ "label": __("Workstation"),
+ "fieldtype": "Link",
+ "width": "100",
+ "options": "Workstation"
+ },
]
};
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
index 665c5b9..8162017 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
@@ -1,14 +1,16 @@
{
- "add_total_row": 0,
+ "add_total_row": 1,
+ "columns": [],
"creation": "2020-03-03 01:41:20.862521",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
+ "filters": [],
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
- "modified": "2020-03-03 01:41:20.862521",
+ "modified": "2022-01-20 14:21:47.771591",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Operations Time",
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 e7a818a..eda9eb9 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py
@@ -12,19 +12,15 @@
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 +30,49 @@
"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 +99,13 @@
"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 +116,13 @@
"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 +132,11 @@
}, {
"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
}]