fix: bom update cost issue (#21372)

* fix: bom update cost is not working

* added test case for bom cost
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 6ccd12a..a83d193 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -246,12 +246,13 @@
 			if rate:
 				d.rate = rate
 			d.amount = flt(d.rate) * flt(d.qty)
+			d.db_update()
 
 		if self.docstatus == 1:
 			self.flags.ignore_validate_update_after_submit = True
 			self.calculate_cost()
 		if save:
-			self.save()
+			self.db_update()
 		self.update_exploded_items()
 
 		# update parent BOMs
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 2758a42..e6c10ad 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -82,7 +82,7 @@
 
 @frappe.whitelist()
 def enqueue_update_cost():
-	frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost")
+	frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost", timeout=40000)
 	frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes."))
 
 def update_latest_price_in_all_boms():
@@ -98,6 +98,9 @@
 	doc.replace_bom()
 
 def update_cost():
+	frappe.db.auto_commit_on_many_writes = 1
 	bom_list = get_boms_in_bottom_up_order()
 	for bom in bom_list:
-		frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
\ No newline at end of file
+		frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
+
+	frappe.db.auto_commit_on_many_writes = 0
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
index 154addf..ac9a409 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
@@ -5,6 +5,9 @@
 from __future__ import unicode_literals
 import unittest
 import frappe
+from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
 
 test_records = frappe.get_test_records('BOM')
 
@@ -27,4 +30,31 @@
 		# reverse, as it affects other testcases
 		update_tool.current_bom = bom_doc.name
 		update_tool.new_bom = current_bom
-		update_tool.replace_bom()
\ No newline at end of file
+		update_tool.replace_bom()
+
+	def test_bom_cost(self):
+		for item in ["BOM Cost Test Item 1", "BOM Cost Test Item 2", "BOM Cost Test Item 3"]:
+			item_doc = create_item(item, valuation_rate=100)
+			if item_doc.valuation_rate != 100.00:
+				frappe.db.set_value("Item", item_doc.name, "valuation_rate", 100)
+
+		bom_no = frappe.db.get_value('BOM', {'item': 'BOM Cost Test Item 1'}, "name")
+		if not bom_no:
+			doc = make_bom(item = 'BOM Cost Test Item 1',
+				raw_materials =['BOM Cost Test Item 2', 'BOM Cost Test Item 3'], currency="INR")
+		else:
+			doc = frappe.get_doc("BOM", bom_no)
+
+		self.assertEquals(doc.total_cost, 200)
+
+		frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 200)
+		update_cost()
+
+		doc.load_from_db()
+		self.assertEquals(doc.total_cost, 300)
+
+		frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 100)
+		update_cost()
+
+		doc.load_from_db()
+		self.assertEquals(doc.total_cost, 200)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index f70c9cc..26f580d 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -192,9 +192,10 @@
 	args = frappe._dict(args)
 
 	bom = frappe.get_doc({
-		'doctype': "BOM",
+		'doctype': 'BOM',
 		'is_default': 1,
 		'item': args.item,
+		'currency': args.currency or 'USD',
 		'quantity': args.quantity or 1,
 		'company': args.company or '_Test Company'
 	})
@@ -211,4 +212,5 @@
 		})
 
 	bom.insert(ignore_permissions=True)
-	bom.submit()
\ No newline at end of file
+	bom.submit()
+	return bom
\ No newline at end of file