From b559245f2af52eb4fdf7cccf4ba77934fe9ad687 Mon Sep 17 00:00:00 2001 From: Vishal Date: Thu, 15 Dec 2022 11:17:14 +0530 Subject: [PATCH 1/6] feat: Add operating cost based on bom quanity without creating job card --- erpnext/manufacturing/doctype/bom/bom.js | 28 +++++++++++++++------- erpnext/manufacturing/doctype/bom/bom.json | 24 ++++++++++++++++++- erpnext/manufacturing/doctype/bom/bom.py | 26 ++++++++++++-------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 4dd8205a70c..5ee98de3767 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -65,7 +65,13 @@ frappe.ui.form.on("BOM", { }); }, - onload_post_render(frm) { + validate: function(frm) { + if (frm.doc.fg_based_operating_cost && frm.doc.with_operations) { + frappe.throw({message: __("Please check either with operations or FG Based Operating Cost."), title: __("Mandatory")}); + } + }, + + onload_post_render: function(frm) { frm.get_field("items").grid.set_multiple_add("item_code", "qty"); }, @@ -536,14 +542,20 @@ erpnext.bom.calculate_op_cost = function(doc) { doc.operating_cost = 0.0; doc.base_operating_cost = 0.0; - for(var i=0;i Date: Thu, 15 Dec 2022 11:56:17 +0530 Subject: [PATCH 2/6] fix: minor changes added --- erpnext/manufacturing/doctype/bom/bom.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 7048d131af0..8ab79e68be9 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -614,7 +614,7 @@ class BOM(WebsiteGenerator): """Update workstation rate and calculates totals""" self.operating_cost = 0 self.base_operating_cost = 0 - if (self.get("with_operations")): + if self.get("with_operations"): for d in self.get("operations"): if d.workstation: self.update_rate_and_time(d, update_hour_rate) @@ -628,8 +628,10 @@ class BOM(WebsiteGenerator): self.operating_cost += flt(operating_cost) self.base_operating_cost += flt(base_operating_cost) - elif(self.get("fg_based_operating_cost")): - total_operating_cost = flt(self.get("quantity")) * flt(self.get("operating_cost_per_bom_quantity")) + elif self.get("fg_based_operating_cost"): + total_operating_cost = flt(self.get("quantity")) * flt( + self.get("operating_cost_per_bom_quantity") + ) self.operating_cost = total_operating_cost self.base_operating_cost = flt(total_operating_cost * self.conversion_rate, 2) From f0c0a64984c00efee34568be1e1b3a6878388301 Mon Sep 17 00:00:00 2001 From: Vishal Date: Mon, 19 Dec 2022 12:24:04 +0530 Subject: [PATCH 3/6] fix: test case added for FG_BASED OPERTING COST --- erpnext/manufacturing/doctype/bom/test_bom.py | 27 +++++++++++++++++++ .../doctype/bom/test_records.json | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 16f5c793720..d60feb2b391 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -202,6 +202,33 @@ class TestBOM(FrappeTestCase): self.assertEqual(bom.items[0].rate, 20) + def test_bom_cost_with_fg_based_operating_cost(self): + bom = frappe.copy_doc(test_records[4]) + bom.insert() + + raw_material_cost = 0.0 + op_cost = 0.0 + + op_cost = bom.quantity * bom.operating_cost_per_bom_quantity + + for row in bom.items: + raw_material_cost += row.amount + + base_raw_material_cost = raw_material_cost * flt( + bom.conversion_rate, bom.precision("conversion_rate") + ) + base_op_cost = op_cost * flt(bom.conversion_rate, bom.precision("conversion_rate")) + + # test amounts in selected currency, almostEqual checks for 7 digits by default + self.assertAlmostEqual(bom.operating_cost, op_cost) + self.assertAlmostEqual(bom.raw_material_cost, raw_material_cost) + self.assertAlmostEqual(bom.total_cost, raw_material_cost + op_cost) + + # test amounts in selected currency + self.assertAlmostEqual(bom.base_operating_cost, base_op_cost) + self.assertAlmostEqual(bom.base_raw_material_cost, base_raw_material_cost) + self.assertAlmostEqual(bom.base_total_cost, base_raw_material_cost + base_op_cost) + def test_subcontractor_sourced_item(self): item_code = "_Test Subcontracted FG Item 1" set_backflush_based_on("Material Transferred for Subcontract") diff --git a/erpnext/manufacturing/doctype/bom/test_records.json b/erpnext/manufacturing/doctype/bom/test_records.json index 507d319b515..e9cbdfe638a 100644 --- a/erpnext/manufacturing/doctype/bom/test_records.json +++ b/erpnext/manufacturing/doctype/bom/test_records.json @@ -162,5 +162,31 @@ "item": "_Test Variant Item", "quantity": 1.0, "with_operations": 1 + }, + { + "items": [ + { + "amount": 5000.0, + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 2.0, + "rate": 3000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "is_active": 1, + "is_default": 1, + "currency": "USD", + "item": "_Test Variant Item", + "quantity": 1.0, + "with_operations": 0, + "fg_based_operating_cost": 1, + "operating_cost_per_bom_quantity": 140 } ] From c51f9e0a9792fca2cd81725f353578338be77e53 Mon Sep 17 00:00:00 2001 From: Vishal Date: Tue, 10 Jan 2023 07:48:26 +0530 Subject: [PATCH 4/6] fix: bom.json updated --- erpnext/manufacturing/doctype/bom/bom.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index 2d936ea92e4..c2b331fcfd1 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -578,8 +578,8 @@ { "fieldname": "scrap_items_section", "fieldtype": "Section Break", - "label": "Scrap Items", - "hide_border": 1 + "hide_border": 1, + "label": "Scrap Items" }, { "default": "0", @@ -605,7 +605,7 @@ "image_field": "image", "is_submittable": 1, "links": [], - "modified": "2023-01-03 18:42:27.732107", + "modified": "2023-01-10 07:47:08.652616", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM", From a5cbdea8e45c695ed70b15ca7d7fa45e0ac898a4 Mon Sep 17 00:00:00 2001 From: Vishal Date: Tue, 10 Jan 2023 13:40:12 +0530 Subject: [PATCH 5/6] fix: minor change in bom.js added --- erpnext/manufacturing/doctype/bom/bom.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 5ee98de3767..b16847faf30 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -543,15 +543,15 @@ erpnext.bom.calculate_op_cost = function(doc) { doc.base_operating_cost = 0.0; if(doc.with_operations) { - for(var i=0;i { + let operating_cost = flt(flt(item.hour_rate) * flt(item.time_in_mins) / 60, 2); + let base_operating_cost = flt(operating_cost * doc.conversion_rate, 2); + frappe.model.set_value('BOM Operation',item.name, "operating_cost", operating_cost); + frappe.model.set_value('BOM Operation',item.name, "base_operating_cost", base_operating_cost); doc.operating_cost += operating_cost; doc.base_operating_cost += base_operating_cost; - } + }); } else if(doc.fg_based_operating_cost) { let total_operating_cost = doc.quantity * flt(doc.operating_cost_per_bom_quantity); doc.operating_cost = total_operating_cost; From 694fc3e20c584a4c63ff339b0223b358ffa4f79e Mon Sep 17 00:00:00 2001 From: Vishal Date: Wed, 11 Jan 2023 18:52:30 +0530 Subject: [PATCH 6/6] fix: hide with_operation on selection on fg_based and vice versa --- erpnext/manufacturing/doctype/bom/bom.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index b16847faf30..4304193afae 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -71,6 +71,14 @@ frappe.ui.form.on("BOM", { } }, + with_operations: function(frm) { + frm.set_df_property("fg_based_operating_cost", "hidden", frm.doc.with_operations ? 1 : 0); + }, + + fg_based_operating_cost: function(frm) { + frm.set_df_property("with_operations", "hidden", frm.doc.fg_based_operating_cost ? 1 : 0); + }, + onload_post_render: function(frm) { frm.get_field("items").grid.set_multiple_add("item_code", "qty"); }, @@ -538,16 +546,17 @@ erpnext.bom.update_cost = function(doc) { }; erpnext.bom.calculate_op_cost = function(doc) { - var op = doc.operations || []; doc.operating_cost = 0.0; doc.base_operating_cost = 0.0; if(doc.with_operations) { - op.forEach((item) => { + doc.operations.forEach((item) => { let operating_cost = flt(flt(item.hour_rate) * flt(item.time_in_mins) / 60, 2); let base_operating_cost = flt(operating_cost * doc.conversion_rate, 2); - frappe.model.set_value('BOM Operation',item.name, "operating_cost", operating_cost); - frappe.model.set_value('BOM Operation',item.name, "base_operating_cost", base_operating_cost); + frappe.model.set_value('BOM Operation',item.name, { + "operating_cost": operating_cost, + "base_operating_cost": base_operating_cost + }); doc.operating_cost += operating_cost; doc.base_operating_cost += base_operating_cost;