Merge pull request #17690 from rohitwaghchaure/set_default_warehouse_from_the_stock_settings_v12

fix: while making the item, default warehouse not set even if the stock settings has the warehouse
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 29bae4b..26e445b 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -463,8 +463,8 @@
 	after = add_years(None, -1).strftime('%Y-%m-%d')
 	group_by='group by date(creation)'
 
-	data = get_communication_data(doctype, name, after=after, group_by='group by date(`tabCommunication`.creation)',
-		fields='date(`tabCommunication`.creation), count(`tabCommunication`.name)',as_dict=False)
+	data = get_communication_data(doctype, name, after=after, group_by='group by date(creation)',
+		fields='date(C.creation) as creation, count(C.name)',as_dict=False)
 
 	# fetch and append data from Activity Log
 	data += frappe.db.sql("""select {fields}
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 3c35e6c..9248ac0 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -205,7 +205,12 @@
 				'item_code': d.item_code,
 				'bom_no': d.bom_no != null ? d.bom_no: '',
 				"scrap_items": scrap_items,
-				'qty': d.qty
+				'qty': d.qty,
+				"stock_qty": d.stock_qty,
+				"include_item_in_manufacturing": d.include_item_in_manufacturing,
+				"uom": d.uom,
+				"stock_uom": d.stock_uom,
+				"conversion_factor": d.conversion_factor
 			},
 			callback: function(r) {
 				d = locals[cdt][cdn];
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 1063340..5c73758 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -172,13 +172,14 @@
 			#Customer Provided parts will have zero rate
 			if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
 				if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
-					rate = self.get_bom_unitcost(arg['bom_no'])
+					rate = self.get_bom_unitcost(arg['bom_no']) * (arg.get("conversion_factor") or 1)
 				else:
 					if self.rm_cost_as_per == 'Valuation Rate':
-						rate = self.get_valuation_rate(arg)
+						rate = self.get_valuation_rate(arg) * (arg.get("conversion_factor") or 1)
 					elif self.rm_cost_as_per == 'Last Purchase Rate':
-						rate = arg.get('last_purchase_rate') \
-							or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
+						rate = (arg.get('last_purchase_rate') \
+							or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")) \
+								* (arg.get("conversion_factor") or 1)
 					elif self.rm_cost_as_per == "Price List":
 						if not self.buying_price_list:
 							frappe.throw(_("Please select Price List"))
@@ -191,7 +192,7 @@
 							"transaction_type": "buying",
 							"company": self.company,
 							"currency": self.currency,
-							"conversion_rate": self.conversion_rate or 1,
+							"conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function
 							"conversion_factor": arg.get("conversion_factor") or 1,
 							"plc_conversion_rate": 1,
 							"ignore_party": True
@@ -203,13 +204,13 @@
 
 					if not rate:
 						if self.rm_cost_as_per == "Price List":
-							frappe.msgprint(_("Price not found for item {0} and price list {1}")
+							frappe.msgprint(_("Price not found for item {0} in price list {1}")
 								.format(arg["item_code"], self.buying_price_list), alert=True)
 						else:
 							frappe.msgprint(_("{0} not found for item {1}")
 								.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
 
-		return flt(rate)
+		return flt(rate) / (self.conversion_rate or 1)
 
 	def update_cost(self, update_parent=True, from_child_bom=False, save=True):
 		if self.docstatus == 2:
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 6d85ef3..e230e59 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -9,6 +9,7 @@
 from frappe.test_runner import make_test_records
 from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
 from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
+from six import string_types
 
 test_records = frappe.get_test_records('BOM')
 
@@ -63,16 +64,8 @@
 			and item_code='_Test Item 2' and docstatus=1 and parenttype='BOM'""")
 		rm_rate = rm_rate[0][0] if rm_rate else 0
 
-		# update valuation rate of item '_Test Item 2'
-		warehouse_list = frappe.db.sql_list("""select warehouse from `tabBin`
-			where item_code='_Test Item 2' and actual_qty > 0""")
-
-		if not warehouse_list:
-			warehouse_list.append("_Test Warehouse - _TC")
-
-		for warehouse in warehouse_list:
-			create_stock_reconciliation(item_code="_Test Item 2", warehouse=warehouse,
-				qty=200, rate=rm_rate + 10)
+		# Reset item valuation rate
+		reset_item_valuation_rate(item_code='_Test Item 2', qty=200, rate=rm_rate + 10)
 
 		# update cost of all BOMs based on latest valuation rate
 		update_cost()
@@ -96,7 +89,7 @@
 		self.assertEqual(bom.base_raw_material_cost, 480000)
 		self.assertEqual(bom.base_total_cost, 486000)
 
-	def test_bom_cost_multi_uom_multi_currency(self):
+	def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
 		frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependant", 1)
 		for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
 			frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s",
@@ -131,5 +124,35 @@
 		self.assertEqual(bom.base_raw_material_cost, 27000)
 		self.assertEqual(bom.base_total_cost, 33000)
 
+	def test_bom_cost_multi_uom_based_on_valuation_rate(self):
+		bom = frappe.copy_doc(test_records[2])
+		bom.set_rate_of_sub_assembly_item_based_on_bom = 0
+		bom.rm_cost_as_per = "Valuation Rate"
+		bom.items[0].uom = "_Test UOM 1"
+		bom.items[0].conversion_factor = 6
+		bom.insert()
+
+		reset_item_valuation_rate(item_code='_Test Item', qty=200, rate=200)
+
+		bom.update_cost()
+
+		self.assertEqual(bom.items[0].rate, 20)
+
 def get_default_bom(item_code="_Test FG Item 2"):
-	return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
\ No newline at end of file
+	return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
+
+def reset_item_valuation_rate(item_code, warehouse_list=None, qty=None, rate=None):
+	if warehouse_list and isinstance(warehouse_list, string_types):
+		warehouse_list = [warehouse_list]
+
+	if not warehouse_list:
+		warehouse_list = frappe.db.sql_list("""
+			select warehouse from `tabBin`
+			where item_code=%s and actual_qty > 0
+		""", item_code)
+
+		if not warehouse_list:
+			warehouse_list.append("_Test Warehouse - _TC")
+
+	for warehouse in warehouse_list:
+		create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=qty, rate=rate)
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 16dcd5a..f694af8 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -439,7 +439,7 @@
 		pl_details = get_price_list_currency_and_exchange_rate(args)
 		args.update(pl_details)
 		validate_price_list(args)
-		if meta.get_field("currency") and args.price_list:
+		if meta.get_field("currency"):
 			validate_conversion_rate(args, meta)
 
 		price_list_rate = get_price_list_rate_for(args, item_doc.name) or 0
@@ -616,21 +616,22 @@
 		get_field_precision(meta.get_field("conversion_rate"),
 			frappe._dict({"fields": args})))
 
-	if (not args.plc_conversion_rate
-		and args.price_list_currency==frappe.db.get_value("Price List", args.price_list, "currency", cache=True)):
-		args.plc_conversion_rate = 1.0
+	if args.price_list:
+		if (not args.plc_conversion_rate
+			and args.price_list_currency==frappe.db.get_value("Price List", args.price_list, "currency", cache=True)):
+			args.plc_conversion_rate = 1.0
 
-	# validate price list currency conversion rate
-	if not args.get("price_list_currency"):
-		throw(_("Price List Currency not selected"))
-	else:
-		validate_conversion_rate(args.price_list_currency, args.plc_conversion_rate,
-			meta.get_label("plc_conversion_rate"), args.company)
+		# validate price list currency conversion rate
+		if not args.get("price_list_currency"):
+			throw(_("Price List Currency not selected"))
+		else:
+			validate_conversion_rate(args.price_list_currency, args.plc_conversion_rate,
+				meta.get_label("plc_conversion_rate"), args.company)
 
-		if meta.get_field("plc_conversion_rate"):
-			args.plc_conversion_rate = flt(args.plc_conversion_rate,
-				get_field_precision(meta.get_field("plc_conversion_rate"),
-				frappe._dict({"fields": args})))
+			if meta.get_field("plc_conversion_rate"):
+				args.plc_conversion_rate = flt(args.plc_conversion_rate,
+					get_field_precision(meta.get_field("plc_conversion_rate"),
+					frappe._dict({"fields": args})))
 
 def get_party_item_code(args, item_doc, out):
 	if args.transaction_type=="selling" and args.customer: