Merge pull request #21946 from rohitwaghchaure/fixed-v13-beta-2-issues-develop

fix: manufacturing dashboard and work order summary chart
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index b57e678..4480110 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -199,10 +199,13 @@
 		if item.get(enable_check):
 			_book_deferred_revenue_or_expense(item)
 
-def process_deferred_accounting(posting_date=today()):
+def process_deferred_accounting(posting_date=None):
 	''' Converts deferred income/expense into income/expense
 		Executed via background jobs on every month end '''
 
+	if not posting_date:
+		posting_date = today()
+
 	if not cint(frappe.db.get_singles_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')):
 		return
 
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 4e09f99..2aa9618 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -135,12 +135,5 @@
 	}
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('Accounts Payable', 9);
 
diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
index d5f18b0..9c6b063 100644
--- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
+++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
@@ -104,12 +104,5 @@
 	}
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('Accounts Payable Summary', 9);
 
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 6208eb6..8dc558a 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -199,12 +199,5 @@
 	}
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('Accounts Receivable', 9);
 
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index b316f10..32ecc63 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -122,11 +122,4 @@
 	}
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('Accounts Receivable Summary', 9);
diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
index d7efbad..80bccaf 100644
--- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
+++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py
@@ -111,7 +111,7 @@
 								   0
 							  end), 0) as depreciation_amount_during_the_period
 			from `tabAsset` a, `tabDepreciation Schedule` ds
-			where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
+			where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent and ifnull(ds.journal_entry, '') != ''
 			group by a.asset_category
 			union
 			SELECT a.asset_category,
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.js b/erpnext/accounts/report/balance_sheet/balance_sheet.js
index c4c24c0..4a4ad4d 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.js
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.js
@@ -4,6 +4,8 @@
 frappe.require("assets/erpnext/js/financial_statements.js", function() {
 	frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
 
+	erpnext.utils.add_dimensions('Balance Sheet', 10);
+
 	frappe.query_reports["Balance Sheet"]["filters"].push({
 		"fieldname": "accumulated_values",
 		"label": __("Accumulated Values"),
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js
index e5d0c89..a984bf4 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.js
+++ b/erpnext/accounts/report/cash_flow/cash_flow.js
@@ -5,6 +5,8 @@
 	frappe.query_reports["Cash Flow"] = $.extend({},
 		erpnext.financial_statements);
 
+	erpnext.utils.add_dimensions('Cash Flow', 10);
+
 	// The last item in the array is the definition for Presentation Currency
 	// filter. It won't be used in cash flow for now so we pop it. Please take
 	// of this if you are working here.
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index 2aecd6b..1fc0f79 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -164,12 +164,5 @@
 	]
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('General Ledger', 15)
 
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
index f88906a..b709ab9 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js
@@ -4,11 +4,18 @@
 frappe.query_reports["Item-wise Purchase Register"] = {
 	"filters": [
 		{
-			"fieldname":"date_range",
-			"label": __("Date Range"),
-			"fieldtype": "DateRange",
-			"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
-			"reqd": 1
+			"fieldname":"from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+			"reqd": 1,
+		},
+		{
+			"fieldname":"to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.get_today(),
+			"reqd": 1,
 		},
 		{
 			"fieldname": "item_code",
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index 1f78c7a..9777ed1 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -14,7 +14,6 @@
 
 def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
 	if not filters: filters = {}
-	filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
 	columns = get_columns(additional_table_columns, filters)
 
 	company_currency = erpnext.get_company_currency(filters.company)
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
index 8a9c76f..39fb3ca 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
@@ -4,11 +4,18 @@
 frappe.query_reports["Item-wise Sales Register"] = {
 	"filters": [
 		{
-			"fieldname": "date_range",
-			"label": __("Date Range"),
-			"fieldtype": "DateRange",
-			"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
-			"reqd": 1
+			"fieldname":"from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+			"reqd": 1,
+		},
+		{
+			"fieldname":"to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.get_today(),
+			"reqd": 1,
 		},
 		{
 			"fieldname": "customer",
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index 92a22e6..bb78ee2 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -14,7 +14,6 @@
 
 def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
 	if not filters: filters = {}
-	filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
 	columns = get_columns(additional_table_columns, filters)
 
 	company_currency = frappe.get_cached_value('Company',  filters.get("company"),  "default_currency")
diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
index 2b946c0..1c461ef 100644
--- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
+++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
@@ -6,6 +6,8 @@
 	frappe.query_reports["Profit and Loss Statement"] = $.extend({},
 		erpnext.financial_statements);
 
+	erpnext.utils.add_dimensions('Profit and Loss Statement', 10);
+
 	frappe.query_reports["Profit and Loss Statement"]["filters"].push(
 		{
 			"fieldname": "project",
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js
index b2b95b2..f34ea57 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.js
+++ b/erpnext/accounts/report/purchase_register/purchase_register.js
@@ -56,11 +56,4 @@
 	]
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Purchase Register"].filters.splice(7, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
\ No newline at end of file
+erpnext.utils.add_dimensions('Purchase Register', 7);
\ No newline at end of file
diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js
index 9dee656..85bbcea 100644
--- a/erpnext/accounts/report/sales_register/sales_register.js
+++ b/erpnext/accounts/report/sales_register/sales_register.js
@@ -68,12 +68,5 @@
 	]
 }
 
-erpnext.dimension_filters.forEach((dimension) => {
-	frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
-		"fieldname": dimension["fieldname"],
-		"label": __(dimension["label"]),
-		"fieldtype": "Link",
-		"options": dimension["document_type"]
-	});
-});
+erpnext.utils.add_dimensions('Sales Register', 7);
 
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js
index 07752e1..9c0854c 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.js
+++ b/erpnext/accounts/report/trial_balance/trial_balance.js
@@ -102,14 +102,7 @@
 		"initial_depth": 3
 	}
 
-	erpnext.dimension_filters.forEach((dimension) => {
-		frappe.query_reports["Trial Balance"].filters.splice(6, 0 ,{
-			"fieldname": dimension["fieldname"],
-			"label": __(dimension["label"]),
-			"fieldtype": "Link",
-			"options": dimension["document_type"]
-		});
-	});
+	erpnext.utils.add_dimensions('Trial Balance', 6);
 });
 
 
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.js b/erpnext/buying/doctype/buying_settings/buying_settings.js
index a27950a..01b40cd 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.js
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.js
@@ -11,7 +11,7 @@
 	{
 		fieldname: "supp_master_name",
 		title: "Supplier Naming By",
-		description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a set ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
+		description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a set ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
 	},
 	{
 		fieldname: "buying_price_list",
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 5fbc460..f6a8d27 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -188,12 +188,6 @@
 		# scan description only if items are less than 50000
 		description_cond = 'or tabItem.description LIKE %(txt)s'
 
-	extra_cond = " and tabItem.has_variants=0"
-	if (filters and isinstance(filters, dict)
-		and filters.get("doctype") == "BOM"):
-		extra_cond = ""
-		del filters["doctype"]
-
 	return frappe.db.sql("""select tabItem.name,
 		if(length(tabItem.item_name) > 40,
 			concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
@@ -204,10 +198,10 @@
 		from tabItem
 		where tabItem.docstatus < 2
 			and tabItem.disabled=0
+			and tabItem.has_variants=0
 			and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
 			and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
 				{description_cond})
-			{extra_cond}
 			{fcond} {mcond}
 		order by
 			if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
@@ -218,7 +212,6 @@
 			key=searchfield,
 			columns=columns,
 			scond=searchfields,
-			extra_cond=extra_cond,
 			fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
 			mcond=get_match_cond(doctype).replace('%', '%%'),
 			description_cond = description_cond),
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 1e0a48c..b696ac3 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -361,7 +361,7 @@
 					self.po_no = ', '.join(list(set([d.po_no for d in po_nos if d.po_no])))
 
 	def set_gross_profit(self):
-		if self.doctype == "Sales Order":
+		if self.doctype in ["Sales Order", "Quotation"]:
 			for item in self.items:
 				item.gross_profit = flt(((item.base_rate - item.valuation_rate) * item.stock_qty), self.precision("amount", item))
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 86de808..90d2930 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -226,7 +226,7 @@
 
 	def check_expense_account(self, item):
 		if not item.get("expense_account"):
-			frappe.throw(_("Expense or Difference account is mandatory for Item {0} as it impacts overall stock value").format(item.item_code))
+			frappe.throw(_("Expense Account not set for Item {0}. Please set an Expense Account for the item in the Items table").format(item.item_code))
 
 		else:
 			is_expense_account = frappe.db.get_value("Account",
diff --git a/erpnext/education/desk_page/education/education.json b/erpnext/education/desk_page/education/education.json
index fc2697f..b341ec4 100644
--- a/erpnext/education/desk_page/education/education.json
+++ b/erpnext/education/desk_page/education/education.json
@@ -64,6 +64,11 @@
    "hidden": 0,
    "label": "Assessment Reports",
    "links": "[\n    {\n        \"dependencies\": [\n            \"Assessment Result\"\n        ],\n        \"doctype\": \"Assessment Result\",\n        \"is_query_report\": true,\n        \"label\": \"Course wise Assessment Report\",\n        \"name\": \"Course wise Assessment Report\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Assessment Result\"\n        ],\n        \"doctype\": \"Assessment Result\",\n        \"is_query_report\": true,\n        \"label\": \"Final Assessment Grades\",\n        \"name\": \"Final Assessment Grades\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Assessment Plan\"\n        ],\n        \"doctype\": \"Assessment Plan\",\n        \"is_query_report\": true,\n        \"label\": \"Assessment Plan Status\",\n        \"name\": \"Assessment Plan Status\",\n        \"type\": \"report\"\n    },\n    {\n        \"label\": \"Student Report Generation Tool\",\n        \"name\": \"Student Report Generation Tool\",\n        \"type\": \"doctype\"\n    }\n]"
+  },
+  {
+   "hidden": 0,
+   "label": "Reports",
+   "links": "[\n    {\n        \"dependencies\": [\n            \"Fees\"\n        ],\n        \"doctype\": \"Fees\",\n        \"is_query_report\": true,\n        \"label\": \"Student Fee Collection\",\n        \"name\": \"Student Fee Collection\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Student Attendance\"\n        ],\n        \"doctype\": \"Student Attendance\",\n        \"is_query_report\": true,\n        \"label\": \"Student Monthly Attendance Sheet\",\n        \"name\": \"Student Monthly Attendance Sheet\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Student Attendance\"\n        ],\n        \"doctype\": \"Student Attendance\",\n        \"is_query_report\": true,\n        \"label\": \"Absent Student Report\",\n        \"name\": \"Absent Student Report\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Program Enrollment\"\n        ],\n        \"doctype\": \"Program Enrollment\",\n        \"is_query_report\": true,\n        \"label\": \"Student and Guardian Contact Details\",\n        \"name\": \"Student and Guardian Contact Details\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Student Attendance\"\n        ],\n        \"doctype\": \"Student Attendance\",\n        \"is_query_report\": true,\n        \"label\": \"Student Batch-Wise Attendance\",\n        \"name\": \"Student Batch-Wise Attendance\",\n        \"type\": \"report\"\n    }\n]"
   }
  ],
  "category": "Domains",
@@ -77,7 +82,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Education",
- "modified": "2020-04-01 11:28:51.011309",
+ "modified": "2020-05-22 01:09:13.058482",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Education",
diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py
new file mode 100644
index 0000000..c36dfb1
--- /dev/null
+++ b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'assessment_plan',
+		'non_standard_fieldnames': {
+		},
+		'transactions': [
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Result']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/course_dashboard.py b/erpnext/education/doctype/course/course_dashboard.py
new file mode 100644
index 0000000..752af29
--- /dev/null
+++ b/erpnext/education/doctype/course/course_dashboard.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'course',
+		'non_standard_fieldnames': {
+		},
+		'transactions': [
+			{
+				'label': _('Course'),
+				'items': ['Course Enrollment', 'Course Schedule']
+			},
+			{
+				'label': _('Student'),
+				'items': ['Student Group']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan']
+			},
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py
index ca0e160..7046038 100644
--- a/erpnext/erpnext_integrations/connectors/shopify_connection.py
+++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py
@@ -95,10 +95,10 @@
 		items = get_order_items(shopify_order.get("line_items"), shopify_settings)
 
 		if not items:
-			message = 'Following items are exists in order but relevant record not found in Product master'
+			message = 'Following items exists in the shopify order but relevant records were not found in the shopify Product master'
 			message += "\n" + ", ".join(product_not_exists)
 
-			make_shopify_log(status="Error", exception=e, rollback=True)
+			make_shopify_log(status="Error", exception=message, rollback=True)
 
 			return ''
 
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
index 44f87e0..1b0c9f6 100644
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
@@ -182,7 +182,8 @@
 	company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr')
 
 	default_warehouse = _("Stores - {0}", sys_lang).format(company_abbr)
-	if not frappe.db.exists("Warehouse", default_warehouse):
+	if not frappe.db.exists("Warehouse", default_warehouse) \
+		and not woocommerce_settings.warehouse:
 		frappe.throw(_("Please set Warehouse in Woocommerce Settings"))
 
 	for item in order.get("line_items"):
diff --git a/erpnext/healthcare/dashboard_fixtures.py b/erpnext/healthcare/dashboard_fixtures.py
index 59da71a..967117d 100644
--- a/erpnext/healthcare/dashboard_fixtures.py
+++ b/erpnext/healthcare/dashboard_fixtures.py
@@ -19,7 +19,7 @@
 	else:
 		company = frappe.get_list("Company", limit=1)
 		if company:
-			return company.name
+			return company[0].name
 	return None
 
 def get_dashboards():
diff --git a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
index 3952a81..15c9434 100644
--- a/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
+++ b/erpnext/healthcare/doctype/patient_assessment/patient_assessment.json
@@ -11,6 +11,7 @@
   "patient",
   "assessment_template",
   "column_break_4",
+  "company",
   "healthcare_practitioner",
   "assessment_datetime",
   "assessment_description",
@@ -127,11 +128,18 @@
    "fieldname": "assessment_description",
    "fieldtype": "Small Text",
    "label": "Assessment Description"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Company",
+   "options": "Company"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-21 13:23:09.815007",
+ "modified": "2020-05-25 14:38:38.302399",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Patient Assessment",
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.json b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
index c352287..016cfbc 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.json
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.json
@@ -85,11 +85,9 @@
   {
    "fieldname": "company",
    "fieldtype": "Link",
-   "hidden": 1,
+   "in_standard_filter": 1,
    "label": "Company",
-   "options": "Company",
-   "print_hide": 1,
-   "report_hide": 1
+   "options": "Company"
   },
   {
    "fieldname": "section_break_6",
@@ -167,7 +165,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-04 19:17:02.707203",
+ "modified": "2020-05-25 14:36:46.990469",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Sample Collection",
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
index ca78b66..9edfeb2 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.json
@@ -10,6 +10,7 @@
   "patient",
   "patient_name",
   "column_break_4",
+  "company",
   "status",
   "start_date",
   "section_break_3",
@@ -98,10 +99,17 @@
    "label": "Status",
    "options": "Not Started\nIn Progress\nCompleted\nCancelled",
    "read_only": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Company",
+   "options": "Company"
   }
  ],
  "links": [],
- "modified": "2020-04-21 13:13:43.956014",
+ "modified": "2020-05-25 14:38:53.649315",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Therapy Plan",
diff --git a/erpnext/healthcare/setup.py b/erpnext/healthcare/setup.py
index 2087f49..0684080 100644
--- a/erpnext/healthcare/setup.py
+++ b/erpnext/healthcare/setup.py
@@ -195,10 +195,21 @@
 
 def add_healthcare_service_unit_tree_root():
 	record = [
-	 {
-	  "doctype": "Healthcare Service Unit",
-	  "healthcare_service_unit_name": "All Healthcare Service Units",
-	  "is_group": 1
-	 }
+		{
+			"doctype": "Healthcare Service Unit",
+			"healthcare_service_unit_name": "All Healthcare Service Units",
+			"is_group": 1,
+			"company": get_company()
+	 	}
 	]
 	insert_record(record)
+
+def get_company():
+	company = frappe.defaults.get_defaults().company
+	if company:
+		return company
+	else:
+		company = frappe.get_list("Company", limit=1)
+		if company:
+			return company[0].name
+	return None
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index f092578..9abaa07 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -512,10 +512,10 @@
 def get_patient_vitals(patient, from_date=None, to_date=None):
 	if not patient: return
 
-	vitals = frappe.db.get_all('Vital Signs', {
+	vitals = frappe.db.get_all('Vital Signs', filters={
 			'docstatus': 1,
 			'patient': patient
-		}, order_by='signs_date, signs_time')
+		}, order_by='signs_date, signs_time', fields=['*'])
 
 	if len(vitals):
 		return vitals
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index 2d0e885..33132a6 100644
--- a/erpnext/hr/desk_page/hr/hr.json
+++ b/erpnext/hr/desk_page/hr/hr.json
@@ -89,11 +89,10 @@
  "docstatus": 0,
  "doctype": "Desk Page",
  "extends_another_page": 0,
- "hide_custom": 0,
  "idx": 0,
  "is_standard": 1,
  "label": "HR",
- "modified": "2020-05-20 11:20:54.255557",
+ "modified": "2020-05-23 12:41:52.543438",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR",
@@ -127,7 +126,7 @@
    "type": "DocType"
   },
   {
-   "label": "Salary Register",
+   "label": "Monthly Attendance Sheet",
    "link_to": "Monthly Attendance Sheet",
    "type": "Report"
   },
diff --git a/erpnext/hr/doctype/appraisal_template/appraisal_template.py b/erpnext/hr/doctype/appraisal_template/appraisal_template.py
index e5d3c42..d0dfad4 100644
--- a/erpnext/hr/doctype/appraisal_template/appraisal_template.py
+++ b/erpnext/hr/doctype/appraisal_template/appraisal_template.py
@@ -3,7 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cint
+from frappe.utils import cint, flt
 from frappe import _
 
 from frappe.model.document import Document
@@ -11,11 +11,11 @@
 class AppraisalTemplate(Document):
 	def validate(self):
 		self.check_total_points()
-		
-	def check_total_points(self):	
+
+	def check_total_points(self):
 		total_points = 0
 		for d in self.get("goals"):
-			total_points += int(d.per_weightage or 0)
+			total_points += flt(d.per_weightage)
 
 		if cint(total_points) != 100:
 			frappe.throw(_("Sum of points for all goals should be 100. It is {0}").format(total_points))
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 84f2c83..f2968bc 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -438,14 +438,23 @@
 	leave_allocation = {}
 	for d in allocation_records:
 		allocation = allocation_records.get(d, frappe._dict())
+
+		total_allocated_leaves = frappe.db.get_value('Leave Allocation', {
+			'from_date': ('<=', date),
+			'to_date': ('>=', date),
+			'leave_type': allocation.leave_type,
+		}, 'SUM(total_leaves_allocated)') or 0
+
 		remaining_leaves = get_leave_balance_on(employee, d, date, to_date = allocation.to_date,
 			consider_all_leaves_in_the_allocation_period=True)
+
 		end_date = allocation.to_date
 		leaves_taken = get_leaves_for_period(employee, d, allocation.from_date, end_date) * -1
 		leaves_pending = get_pending_leaves_for_period(employee, d, allocation.from_date, end_date)
 
 		leave_allocation[d] = {
-			"total_leaves": allocation.total_leaves_allocated,
+			"total_leaves": total_allocated_leaves,
+			"expired_leaves": total_allocated_leaves - (remaining_leaves + leaves_taken),
 			"leaves_taken": leaves_taken,
 			"pending_leaves": leaves_pending,
 			"remaining_leaves": remaining_leaves}
diff --git a/erpnext/hr/doctype/leave_application/leave_application_dashboard.html b/erpnext/hr/doctype/leave_application/leave_application_dashboard.html
index 2385b6a..295f3b4 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_dashboard.html
+++ b/erpnext/hr/doctype/leave_application/leave_application_dashboard.html
@@ -4,11 +4,12 @@
 <table class="table table-bordered small">
 	<thead>
 		<tr>
-			<th style="width: 20%">{{ __("Leave Type") }}</th>
-			<th style="width: 20%" class="text-right">{{ __("Total Allocated Leaves") }}</th>
-			<th style="width: 20%" class="text-right">{{ __("Used Leaves") }}</th>
-			<th style="width: 20%" class="text-right">{{ __("Pending Leaves") }}</th>
-			<th style="width: 20%" class="text-right">{{ __("Available Leaves") }}</th>
+			<th style="width: 16%">{{ __("Leave Type") }}</th>
+			<th style="width: 16%" class="text-right">{{ __("Total Allocated Leaves") }}</th>
+			<th style="width: 16%" class="text-right">{{ __("Expired Leaves") }}</th>
+			<th style="width: 16%" class="text-right">{{ __("Used Leaves") }}</th>
+			<th style="width: 16%" class="text-right">{{ __("Pending Leaves") }}</th>
+			<th style="width: 16%" class="text-right">{{ __("Available Leaves") }}</th>
 		</tr>
 
 	</thead>
@@ -17,6 +18,7 @@
 			<tr>
 				<td> {%= key %} </td>
 				<td class="text-right"> {%= value["total_leaves"] %} </td>
+				<td class="text-right"> {%= value["expired_leaves"] %} </td>
 				<td class="text-right"> {%= value["leaves_taken"] %} </td>
 				<td class="text-right"> {%= value["pending_leaves"] %} </td>
 				<td class="text-right"> {%= value["remaining_leaves"] %} </td>
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index 61faea1..edf05e8 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -22,6 +22,9 @@
 
 	args = frappe.local.form_dict
 
+	if getdate(args.from_date) > getdate(args.to_date):
+		frappe.throw(_("To Date should be greater than From Date"))
+
 	w = UnicodeWriter()
 	w = add_header(w)
 
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index 97be5cd..db1d191 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -3,13 +3,13 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import flt
+from frappe.utils import flt, add_days
 from frappe import _
-from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on, get_leave_allocation_records
+from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
 
 def execute(filters=None):
 	if filters.to_date <= filters.from_date:
-		frappe.throw(_('From date can not be greater than than To date'))
+		frappe.throw(_('"From date" can not be greater than or equal to "To date"'))
 
 	columns = get_columns()
 	data = get_data(filters)
@@ -104,14 +104,17 @@
 				new_allocation, expired_leaves = get_allocated_and_expired_leaves(filters.from_date, filters.to_date, employee.name, leave_type)
 
 
-				opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
-				closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
+				opening = get_leave_balance_on(employee.name, leave_type, add_days(filters.from_date, -1)) #allocation boundary condition
 
 				row.leaves_allocated = new_allocation
 				row.leaves_expired = expired_leaves - leaves_taken if expired_leaves - leaves_taken > 0 else 0
 				row.opening_balance = opening
 				row.leaves_taken = leaves_taken
-				row.closing_balance = closing
+
+				# not be shown on the basis of days left it create in user mind for carry_forward leave
+				row.closing_balance = (new_allocation + opening - (row.leaves_expired + leaves_taken))
+
+
 				row.indent = 1
 				data.append(row)
 				new_leaves_allocated = 0
@@ -177,7 +180,7 @@
 	}, as_dict=1)
 
 	for record in records:
-		if record.to_date <= getdate(to_date):
+		if record.to_date < getdate(to_date):
 			expired_leaves += record.leaves
 
 		if record.from_date >= getdate(from_date):
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
index a5cdecf..92715d3 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
@@ -6,7 +6,7 @@
 from frappe import _
 from frappe.utils import flt
 from erpnext.hr.doctype.leave_application.leave_application \
-	import get_leave_balance_on, get_leaves_for_period
+	import get_leave_details
 
 from erpnext.hr.report.employee_leave_balance.employee_leave_balance \
 	import get_department_leave_approver_map
@@ -61,14 +61,14 @@
 
 		if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
 			row = [employee.name, employee.employee_name, employee.department]
-
+			available_leave = get_leave_details(employee.name, filters.date)
 			for leave_type in leave_types:
-
+				remaining = 0
+				if leave_type in available_leave["leave_allocation"]:
 				# opening balance
-				opening = get_leave_balance_on(employee.name, leave_type, filters.date)
+					remaining = available_leave["leave_allocation"][leave_type]['remaining_leaves']
 
-
-				row += [opening]
+				row += [remaining]
 
 			data.append(row)
 
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index 60767b5..47daab1 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -135,7 +135,7 @@
 		row += [emp, emp_det.employee_name]
 
 		total_p = total_a = total_l = total_h = total_um= 0.0
-		ggg = []
+		emp_status_map = []
 		for day in range(filters["total_days_in_month"]):
 			status = None
 			status = att_map.get(emp).get(day + 1)
@@ -152,11 +152,10 @@
 								status = "Holiday"
 							total_h += 1
 
-			ggg.append(status_map.get(status, ""))
+			abbr = status_map.get(status, "")
+			emp_status_map.append(abbr)
 
-			if not filters.summarized_view:
-				row += ggg
-			else:
+			if  filters.summarized_view:
 				if status == "Present" or status == "Work From Home":
 					total_p += 1
 				elif status == "Absent":
@@ -170,6 +169,9 @@
 				elif not status:
 					total_um += 1
 
+		if not filters.summarized_view:
+			row += emp_status_map
+
 		if filters.summarized_view:
 			row += [total_p, total_l, total_a, total_h, total_um]
 
@@ -203,7 +205,7 @@
 					row.append("0.0")
 
 			row.extend([time_default_counts[0][0],time_default_counts[0][1]])
-		emp_att_map[emp] = ggg
+		emp_att_map[emp] = emp_status_map
 		record.append(row)
 
 	return record, emp_att_map
@@ -216,7 +218,7 @@
 		columns = [_(filters.group_by)+ ":Link/Branch:120"]
 
 	columns += [
-		_("Employee") + ":Link/Employee:120", _("Employee Name") + ":Link/Employee:120"
+		_("Employee") + ":Link/Employee:120", _("Employee Name") + ":Data/:120"
 	]
 	days = []
 	for day in range(filters["total_days_in_month"]):
diff --git a/erpnext/loan_management/desk_page/loan_management/loan_management.json b/erpnext/loan_management/desk_page/loan_management/loan_management.json
index f9ea978..d2a1763 100644
--- a/erpnext/loan_management/desk_page/loan_management/loan_management.json
+++ b/erpnext/loan_management/desk_page/loan_management/loan_management.json
@@ -36,11 +36,11 @@
  "extends_another_page": 0,
  "idx": 0,
  "is_standard": 1,
- "label": "Loan Management",
- "modified": "2020-04-02 11:28:51.380509",
+ "label": "Loan",
+ "modified": "2020-05-22 11:28:51.380509",
  "modified_by": "Administrator",
  "module": "Loan Management",
- "name": "Loan Management",
+ "name": "Loan",
  "owner": "Administrator",
  "pin_to_bottom": 0,
  "pin_to_top": 0,
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 898955e..47b4207 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -29,10 +29,7 @@
 
 		frm.set_query("item", function() {
 			return {
-				query: "erpnext.controllers.queries.item_query",
-				filters: {
-					"doctype": "BOM"
-				}
+				query: "erpnext.manufacturing.doctype.bom.bom.item_query"
 			};
 		});
 
@@ -44,9 +41,12 @@
 			};
 		});
 
-		frm.set_query("item_code", "items", function() {
+		frm.set_query("item_code", "items", function(doc) {
 			return {
-				query: "erpnext.controllers.queries.item_query"
+				query: "erpnext.manufacturing.doctype.bom.bom.item_query",
+				filters: {
+					"item_code": doc.item
+				}
 			};
 		});
 
@@ -96,6 +96,12 @@
 				frm.trigger("make_work_order");
 			}, __("Create"));
 
+			if (frm.doc.has_variants) {
+				frm.add_custom_button(__("Variant BOM"), function() {
+					frm.trigger("make_variant_bom");
+				}, __("Create"));
+			}
+
 			if (frm.doc.inspection_required) {
 				frm.add_custom_button(__("Quality Inspection"), function() {
 					frm.trigger("make_quality_inspection");
@@ -124,7 +130,7 @@
 		}
 
 
-		if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
+		if (frm.doc.has_variants) {
 			frm.set_intro(__('This is a Template BOM and will be used to make the work order for {0} of the item {1}',
 				[
 					`<a class="variants-intro">variants</a>`,
@@ -138,9 +144,52 @@
 	},
 
 	make_work_order: function(frm) {
+		frm.events.setup_variant_prompt(frm, "Work Order", (frm, item, data, variant_items) => {
+			frappe.call({
+				method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
+				args: {
+					bom_no: frm.doc.name,
+					item: item,
+					qty: data.qty || 0.0,
+					project: frm.doc.project,
+					variant_items: variant_items
+				},
+				freeze: true,
+				callback: function(r) {
+					if(r.message) {
+						let doc = frappe.model.sync(r.message)[0];
+						frappe.set_route("Form", doc.doctype, doc.name);
+					}
+				}
+			});
+		});
+	},
+
+	make_variant_bom: function(frm) {
+		frm.events.setup_variant_prompt(frm, "Variant BOM", (frm, item, data, variant_items) => {
+			frappe.call({
+				method: "erpnext.manufacturing.doctype.bom.bom.make_variant_bom",
+				args: {
+					source_name: frm.doc.name,
+					bom_no: frm.doc.name,
+					item: item,
+					variant_items: variant_items
+				},
+				freeze: true,
+				callback: function(r) {
+					if(r.message) {
+						let doc = frappe.model.sync(r.message)[0];
+						frappe.set_route("Form", doc.doctype, doc.name);
+					}
+				}
+			});
+		}, true);
+	},
+
+	setup_variant_prompt: function(frm, title, callback, skip_qty_field) {
 		const fields = [];
 
-		if (frm.doc.__onload && frm.doc.__onload["has_variants"]) {
+		if (frm.doc.has_variants) {
 			fields.push({
 				fieldtype: 'Link',
 				label: __('Variant Item'),
@@ -158,34 +207,106 @@
 			});
 		}
 
-		fields.push({
-			fieldtype: 'Float',
-			label: __('Qty To Manufacture'),
-			fieldname: 'qty',
-			reqd: 1,
-			default: 1
+		if (!skip_qty_field) {
+			fields.push({
+				fieldtype: 'Float',
+				label: __('Qty To Manufacture'),
+				fieldname: 'qty',
+				reqd: 1,
+				default: 1
+			});
+		}
+
+		var has_template_rm = frm.doc.items.filter(d => d.has_variants === 1) || [];
+		if (has_template_rm && has_template_rm.length > 0) {
+			fields.push({
+				fieldname: "items",
+				fieldtype: "Table",
+				label: __("Raw Materials"),
+				fields: [
+					{
+						fieldname: "item_code",
+						options: "Item",
+						label: __("Template Item"),
+						fieldtype: "Link",
+						in_list_view: 1,
+						reqd: 1,
+					},
+					{
+						fieldname: "varint_item_code",
+						options: "Item",
+						label: __("Variant Item"),
+						fieldtype: "Link",
+						in_list_view: 1,
+						reqd: 1,
+						get_query: function(data) {
+							if (!data.item_code) {
+								frappe.throw(__("Select template item"));
+							}
+
+							return {
+								query: "erpnext.controllers.queries.item_query",
+								filters: {
+									"variant_of": data.item_code
+								}
+							};
+						}
+					},
+					{
+						fieldname: "qty",
+						label: __("Quantity"),
+						fieldtype: "Float",
+						in_list_view: 1,
+						reqd: 1,
+					},
+					{
+						fieldname: "source_warehouse",
+						label: __("Source Warehouse"),
+						fieldtype: "Link",
+						options: "Warehouse"
+					},
+					{
+						fieldname: "operation",
+						label: __("Operation"),
+						fieldtype: "Data",
+						hidden: 1,
+					}
+				],
+				in_place_edit: true,
+				data: [],
+				get_data: function () {
+					return [];
+				},
+			});
+		}
+
+		let dialog = frappe.prompt(fields, data => {
+			let item = data.item || frm.doc.item;
+			let variant_items = data.items || [];
+
+			variant_items.forEach(d => {
+				if (!d.varint_item_code) {
+					frappe.throw(__("Select variant item code for the template item {0}", [d.item_code]));
+				}
+			})
+
+			callback(frm, item, data, variant_items);
+
+		}, __(title), __("Create"));
+
+		has_template_rm.forEach(d => {
+			dialog.fields_dict.items.df.data.push({
+				"item_code": d.item_code,
+				"varint_item_code": "",
+				"qty": d.qty,
+				"source_warehouse": d.source_warehouse,
+				"operation": d.operation
+			});
 		});
 
-		frappe.prompt(fields, data => {
-			let item = data.item || frm.doc.item;
-
-			frappe.call({
-				method: "erpnext.manufacturing.doctype.work_order.work_order.make_work_order",
-				args: {
-					bom_no: frm.doc.name,
-					item: item,
-					qty: data.qty || 0.0,
-					project: frm.doc.project
-				},
-				freeze: true,
-				callback: function(r) {
-					if(r.message) {
-						var doc = frappe.model.sync(r.message)[0];
-						frappe.set_route("Form", doc.doctype, doc.name);
-					}
-				}
-			});
-		}, __("Enter Value"), __("Create"));
+		if (has_template_rm) {
+			dialog.fields_dict.items.grid.refresh();
+		}
 	},
 
 	make_quality_inspection: function(frm) {
diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json
index 4ce0ecf..f551b91 100644
--- a/erpnext/manufacturing/doctype/bom/bom.json
+++ b/erpnext/manufacturing/doctype/bom/bom.json
@@ -53,6 +53,7 @@
   "section_break_25",
   "description",
   "column_break_27",
+  "has_variants",
   "section_break0",
   "exploded_items",
   "website_section",
@@ -498,6 +499,17 @@
    "options": "Currency",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fetch_from": "item.has_variants",
+   "fieldname": "has_variants",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Has Variants",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "icon": "fa fa-sitemap",
@@ -505,7 +517,7 @@
  "image_field": "image",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-05 14:29:32.634952",
+ "modified": "2020-05-21 12:29:32.634952",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 6ac653e..1bdac57 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -3,13 +3,16 @@
 
 from __future__ import unicode_literals
 import frappe, erpnext
-from frappe.utils import cint, cstr, flt
+from frappe.utils import cint, cstr, flt, today
 from frappe import _
 from erpnext.setup.utils import get_exchange_rate
 from frappe.website.website_generator import WebsiteGenerator
 from erpnext.stock.get_item_details import get_conversion_factor
 from erpnext.stock.get_item_details import get_price_list_rate
 from frappe.core.doctype.version.version import get_diff
+from erpnext.controllers.queries import get_match_cond
+from erpnext.stock.doctype.item.item import get_item_details
+from frappe.model.mapper import get_mapped_doc
 
 import functools
 
@@ -59,11 +62,6 @@
 
 		self.name = name
 
-	def onload(self):
-		super(BOM, self).onload()
-		if self.get("item") and cint(frappe.db.get_value("Item", self.item, "has_variants")):
-			self.set_onload("has_variants", True)
-
 	def validate(self):
 		self.route = frappe.scrub(self.name).replace('_', '-')
 		self.clear_operations()
@@ -103,9 +101,7 @@
 		self.manage_default_bom()
 
 	def get_item_det(self, item_code):
-		item = frappe.db.sql("""select name, item_name, docstatus, description, image,
-			is_sub_contracted_item, stock_uom, default_bom, last_purchase_rate, include_item_in_manufacturing
-			from `tabItem` where name=%s""", item_code, as_dict = 1)
+		item = get_item_details(item_code)
 
 		if not item:
 			frappe.throw(_("Item: {0} does not exist in the system").format(item_code))
@@ -150,10 +146,10 @@
 
 		item = self.get_item_det(args['item_code'])
 
-		args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+		args['bom_no'] = args['bom_no'] or item and cstr(item['default_bom']) or ''
 		args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or
-			item and item[0].include_item_in_manufacturing or 0)
-		args.update(item[0])
+			item and item.include_item_in_manufacturing or 0)
+		args.update(item)
 
 		rate = self.get_rm_rate(args)
 		ret_item = {
@@ -185,40 +181,14 @@
 			self.rm_cost_as_per = "Valuation Rate"
 
 		if arg.get('scrap_items'):
-			rate = self.get_valuation_rate(arg)
+			rate = get_valuation_rate(arg)
 		elif arg:
 			#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 = flt(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) * (arg.get("conversion_factor") or 1)
-					elif self.rm_cost_as_per == 'Last Purchase Rate':
-						rate = flt(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"))
-						args = frappe._dict({
-							"doctype": "BOM",
-							"price_list": self.buying_price_list,
-							"qty": arg.get("qty") or 1,
-							"uom": arg.get("uom") or arg.get("stock_uom"),
-							"stock_uom": arg.get("stock_uom"),
-							"transaction_type": "buying",
-							"company": self.company,
-							"currency": self.currency,
-							"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
-						})
-						item_doc = frappe.get_doc("Item", arg.get("item_code"))
-						out = frappe._dict()
-						get_price_list_rate(args, item_doc, out)
-						rate = out.price_list_rate
+					rate = get_bom_item_rate(arg, self)
 
 					if not rate:
 						if self.rm_cost_as_per == "Price List":
@@ -286,31 +256,6 @@
 			where is_active = 1 and name = %s""", bom_no, as_dict=1)
 		return bom and bom[0]['unit_cost'] or 0
 
-	def get_valuation_rate(self, args):
-		""" Get weighted average of valuation rate from all warehouses """
-
-		total_qty, total_value, valuation_rate = 0.0, 0.0, 0.0
-		for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
-			where item_code=%s""", args['item_code'], as_dict=1):
-				total_qty += flt(d.actual_qty)
-				total_value += flt(d.stock_value)
-
-		if total_qty:
-			valuation_rate =  total_value / total_qty
-
-		if valuation_rate <= 0:
-			last_valuation_rate = frappe.db.sql("""select valuation_rate
-				from `tabStock Ledger Entry`
-				where item_code = %s and valuation_rate > 0
-				order by posting_date desc, posting_time desc, creation desc limit 1""", args['item_code'])
-
-			valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
-
-		if not valuation_rate:
-			valuation_rate = frappe.db.get_value("Item", args['item_code'], "valuation_rate")
-
-		return flt(valuation_rate)
-
 	def manage_default_bom(self):
 		""" Uncheck others if current one is selected as default or
 			check the current one as default if it the only bom for the selected item,
@@ -624,6 +569,62 @@
 				if not d.batch_size or d.batch_size <= 0:
 					d.batch_size = 1
 
+def get_bom_item_rate(args, bom_doc):
+	if bom_doc.rm_cost_as_per == 'Valuation Rate':
+		rate = get_valuation_rate(args) * (args.get("conversion_factor") or 1)
+	elif bom_doc.rm_cost_as_per == 'Last Purchase Rate':
+		rate = ( flt(args.get('last_purchase_rate')) \
+			or frappe.db.get_value("Item", args['item_code'], "last_purchase_rate")) \
+				* (args.get("conversion_factor") or 1)
+	elif bom_doc.rm_cost_as_per == "Price List":
+		if not bom_doc.buying_price_list:
+			frappe.throw(_("Please select Price List"))
+		bom_args = frappe._dict({
+			"doctype": "BOM",
+			"price_list": bom_doc.buying_price_list,
+			"qty": args.get("qty") or 1,
+			"uom": args.get("uom") or args.get("stock_uom"),
+			"stock_uom": args.get("stock_uom"),
+			"transaction_type": "buying",
+			"company": bom_doc.company,
+			"currency": bom_doc.currency,
+			"conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function
+			"conversion_factor": args.get("conversion_factor") or 1,
+			"plc_conversion_rate": 1,
+			"ignore_party": True
+		})
+		item_doc = frappe.get_cached_doc("Item", args.get("item_code"))
+		out = frappe._dict()
+		get_price_list_rate(bom_args, item_doc, out)
+		rate = out.price_list_rate
+
+	return rate
+
+def get_valuation_rate(args):
+	""" Get weighted average of valuation rate from all warehouses """
+
+	total_qty, total_value, valuation_rate = 0.0, 0.0, 0.0
+	for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
+		where item_code=%s""", args['item_code'], as_dict=1):
+			total_qty += flt(d.actual_qty)
+			total_value += flt(d.stock_value)
+
+	if total_qty:
+		valuation_rate =  total_value / total_qty
+
+	if valuation_rate <= 0:
+		last_valuation_rate = frappe.db.sql("""select valuation_rate
+			from `tabStock Ledger Entry`
+			where item_code = %s and valuation_rate > 0
+			order by posting_date desc, posting_time desc, creation desc limit 1""", args['item_code'])
+
+		valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
+
+	if not valuation_rate:
+		valuation_rate = frappe.db.get_value("Item", args['item_code'], "valuation_rate")
+
+	return flt(valuation_rate)
+
 def get_list_context(context):
 	context.title = _("Bill of Materials")
 	# context.introduction = _('Boms')
@@ -639,6 +640,8 @@
 				sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
 				item.image,
 				bom.project,
+				bom_item.rate,
+				bom_item.amount,
 				item.stock_uom,
 				item.item_group,
 				item.allow_alternative_item,
@@ -655,6 +658,7 @@
 			where
 				bom_item.docstatus < 2
 				and bom.name = %(bom)s
+				and ifnull(item.has_variants, 0) = 0
 				and item.is_stock_item in (1, {is_stock_item})
 				{where_conditions}
 				group by item_code, stock_uom
@@ -897,3 +901,84 @@
 					out.removed.append([df.fieldname, d.as_dict()])
 
 	return out
+
+def item_query(doctype, txt, searchfield, start, page_len, filters):
+	meta = frappe.get_meta("Item", cached=True)
+	searchfields = meta.get_search_fields()
+
+	order_by = "idx desc, name, item_name"
+
+	fields = ["name", "item_group", "item_name", "description"]
+	fields.extend([field for field in searchfields
+		if not field in ["name", "item_group", "description"]])
+
+	searchfields = searchfields + [field for field in [searchfield or "name", "item_code", "item_group", "item_name"]
+		if not field in searchfields]
+
+	query_filters = {
+		"disabled": 0,
+		"ifnull(end_of_life, '5050-50-50')": (">", today())
+	}
+
+	or_cond_filters = {}
+	if txt:
+		for s_field in searchfields:
+			or_cond_filters[s_field] = ("like", "%{0}%".format(txt))
+
+		barcodes = frappe.get_all("Item Barcode",
+			fields=["distinct parent as item_code"],
+			filters = {"barcode": ("like", "%{0}%".format(txt))})
+
+		barcodes = [d.item_code for d in barcodes]
+		if barcodes:
+			or_cond_filters["name"] = ("in", barcodes)
+
+	for cond in get_match_cond(doctype, as_condition=False):
+		for key, value in cond.items():
+			if key == doctype:
+				key = "name"
+
+			query_filters[key] = ("in", value)
+
+	if filters and filters.get("item_code"):
+		has_variants = frappe.get_cached_value("Item", filters.get("item_code"), "has_variants")
+		if not has_variants:
+			query_filters["has_variants"] = 0
+
+	return frappe.get_all("Item",
+		fields = fields, filters=query_filters,
+		or_filters = or_cond_filters, order_by=order_by,
+		limit_start=start, limit_page_length=page_len, as_list=1)
+
+@frappe.whitelist()
+def make_variant_bom(source_name, bom_no, item, variant_items, target_doc=None):
+	from erpnext.manufacturing.doctype.work_order.work_order import add_variant_item
+
+	def postprocess(source, doc):
+		doc.item = item
+		doc.quantity = 1
+
+		item_data = get_item_details(item)
+		doc.update({
+			"item_name": item_data.item_name,
+			"description": item_data.description,
+			"uom": item_data.stock_uom,
+			"allow_alternative_item": item_data.allow_alternative_item
+		})
+
+		add_variant_item(variant_items, doc, source_name)
+
+	doc = get_mapped_doc('BOM', source_name, {
+		'BOM': {
+			'doctype': 'BOM',
+			'validation': {
+				'docstatus': ['=', 1]
+			}
+		},
+		'BOM Item': {
+			'doctype': 'BOM Item',
+			'condition': lambda doc: doc.has_variants == 0
+		},
+	}, target_doc, postprocess)
+
+	return doc
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom_list.js b/erpnext/manufacturing/doctype/bom/bom_list.js
index 2b06ed7..94cb466 100644
--- a/erpnext/manufacturing/doctype/bom/bom_list.js
+++ b/erpnext/manufacturing/doctype/bom/bom_list.js
@@ -1,7 +1,9 @@
 frappe.listview_settings['BOM'] = {
-	add_fields: ["is_active", "is_default", "total_cost"],
+	add_fields: ["is_active", "is_default", "total_cost", "has_variants"],
 	get_indicator: function(doc) {
-		if(doc.is_default) {
+		if(doc.is_active && doc.has_variants) {
+			return [__("Template"), "orange", "has_variants,=,Yes"];
+		} else if(doc.is_default) {
 			return [__("Default"), "green", "is_default,=,Yes"];
 		} else if(doc.is_active) {
 			return [__("Active"), "blue", "is_active,=,Yes"];
diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json
index f094be4..e34be61 100644
--- a/erpnext/manufacturing/doctype/bom_item/bom_item.json
+++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json
@@ -1,8 +1,10 @@
 {
+ "actions": [],
  "creation": "2013-02-22 01:27:49",
  "doctype": "DocType",
  "document_type": "Setup",
  "editable_grid": 1,
+ "engine": "InnoDB",
  "field_order": [
   "item_code",
   "item_name",
@@ -33,6 +35,7 @@
   "scrap",
   "qty_consumed_per_unit",
   "section_break_27",
+  "has_variants",
   "include_item_in_manufacturing",
   "original_item"
  ],
@@ -57,6 +60,7 @@
    "label": "Item Name"
   },
   {
+   "depends_on": "eval:parent.with_operations == 1",
    "fieldname": "operation",
    "fieldtype": "Link",
    "label": "Item operation",
@@ -258,11 +262,22 @@
    "label": "Original Item",
    "options": "Item",
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fetch_from": "item_code.has_variants",
+   "fieldname": "has_variants",
+   "fieldtype": "Check",
+   "label": "Has Variants",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-11-22 11:38:52.087303",
+ "links": [],
+ "modified": "2020-04-09 14:30:26.535546",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "BOM Item",
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index c125571..a244f58 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -449,6 +449,32 @@
 				}
 			});
 		}
+	},
+
+	item_code: function(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+
+		if (row.item_code) {
+			frappe.call({
+				method: "erpnext.stock.doctype.item.item.get_item_details",
+				args: {
+					item_code: row.item_code,
+					company: frm.doc.company
+				},
+				callback: function(r) {
+					if (r.message) {
+						frappe.model.set_value(cdt, cdn, {
+							"required_qty": 1,
+							"item_name": r.message.item_name,
+							"description": r.message.description,
+							"source_warehouse": r.message.default_warehouse,
+							"allow_alternative_item": r.message.allow_alternative_item,
+							"include_item_in_manufacturing": r.message.include_item_in_manufacturing
+						});
+					}
+				}
+			});
+		}
 	}
 });
 
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index c278955..e2233a3 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -8,9 +8,9 @@
 from frappe import _
 from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate, get_link_to_form, time_diff_in_hours
 from frappe.model.document import Document
-from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
+from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict, get_bom_item_rate
 from dateutil.relativedelta import relativedelta
-from erpnext.stock.doctype.item.item import validate_end_of_life
+from erpnext.stock.doctype.item.item import validate_end_of_life, get_item_defaults
 from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
 from erpnext.projects.doctype.timesheet.timesheet import OverlapError
 from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
@@ -541,6 +541,8 @@
 				# For instance in BOM Explosion Item child table, the items coming from sub assembly items
 				for item in sorted(item_dict.values(), key=lambda d: d['idx'] or 9999):
 					self.append('required_items', {
+						'rate': item.rate,
+						'amount': item.amount,
 						'operation': item.operation,
 						'item_code': item.item_code,
 						'item_name': item.item_name,
@@ -637,9 +639,10 @@
 		filters = filters, fields = ['operation'], as_list=1)
 
 @frappe.whitelist()
-def get_item_details(item, project = None):
+def get_item_details(item, project = None, skip_bom_info=False):
 	res = frappe.db.sql("""
-		select stock_uom, description
+		select stock_uom, description, item_name, allow_alternative_item,
+			include_item_in_manufacturing
 		from `tabItem`
 		where disabled=0
 			and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)
@@ -650,6 +653,7 @@
 		return {}
 
 	res = res[0]
+	if skip_bom_info: return res
 
 	filters = {"item": item, "is_default": 1}
 
@@ -681,7 +685,7 @@
 	return res
 
 @frappe.whitelist()
-def make_work_order(bom_no, item, qty=0, project=None):
+def make_work_order(bom_no, item, qty=0, project=None, variant_items=None):
 	if not frappe.has_permission("Work Order", "write"):
 		frappe.throw(_("Not permitted"), frappe.PermissionError)
 
@@ -696,8 +700,44 @@
 		wo_doc.qty = flt(qty)
 		wo_doc.get_items_and_operations_from_bom()
 
+	if variant_items:
+		add_variant_item(variant_items, wo_doc, bom_no, "required_items")
+
 	return wo_doc
 
+def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"):
+	if isinstance(variant_items, string_types):
+		variant_items = json.loads(variant_items)
+
+	for item in variant_items:
+		args = frappe._dict({
+			"item_code": item.get("varint_item_code"),
+			"required_qty": item.get("qty"),
+			"qty": item.get("qty"), # for bom
+			"source_warehouse": item.get("source_warehouse"),
+			"operation": item.get("operation")
+		})
+
+		bom_doc = frappe.get_cached_doc("BOM", bom_no)
+		item_data = get_item_details(args.item_code, skip_bom_info=True)
+		args.update(item_data)
+
+		args["rate"] = get_bom_item_rate({
+			"item_code": args.get("item_code"),
+			"qty": args.get("required_qty"),
+			"uom": args.get("stock_uom"),
+			"stock_uom": args.get("stock_uom"),
+			"conversion_factor": 1
+		}, bom_doc)
+
+		if not args.source_warehouse:
+			args["source_warehouse"] = get_item_defaults(item.get("varint_item_code"),
+				wo_doc.company).default_warehouse
+
+		args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate"))
+		args["uom"] = item_data.stock_uom
+		wo_doc.append(table_name, args)
+
 @frappe.whitelist()
 def check_if_scrap_warehouse_mandatory(bom_no):
 	res = {"set_scrap_wh_mandatory": False }
diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
index 4442162..3acf572 100644
--- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
+++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
@@ -1,526 +1,144 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2016-04-18 07:38:26.314642", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2016-04-18 07:38:26.314642",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "operation",
+  "item_code",
+  "source_warehouse",
+  "column_break_3",
+  "item_name",
+  "description",
+  "allow_alternative_item",
+  "include_item_in_manufacturing",
+  "qty_section",
+  "required_qty",
+  "rate",
+  "amount",
+  "column_break_11",
+  "transferred_qty",
+  "consumed_qty",
+  "available_qty_at_source_warehouse",
+  "available_qty_at_wip_warehouse"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "operation", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Operation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Operation", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "operation",
+   "fieldtype": "Link",
+   "label": "Operation",
+   "options": "Operation"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_code", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Item Code", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item Code",
+   "options": "Item"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "source_warehouse", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Source Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Warehouse", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "source_warehouse",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_list_view": 1,
+   "label": "Source Warehouse",
+   "options": "Warehouse"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Item Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "item_name",
+   "fieldtype": "Data",
+   "label": "Item Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "description",
+   "fieldtype": "Text",
+   "label": "Description",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "qty_section", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "qty_section",
+   "fieldtype": "Section Break",
+   "label": "Qty"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "required_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Required Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "required_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Required Qty"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!parent.skip_transfer", 
-   "fieldname": "transferred_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Transferred Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "eval:!parent.skip_transfer",
+   "fieldname": "transferred_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Transferred Qty",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "allow_alternative_item", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Allow Alternative Item", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "allow_alternative_item",
+   "fieldtype": "Check",
+   "label": "Allow Alternative Item"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "include_item_in_manufacturing", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Include Item In Manufacturing", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "include_item_in_manufacturing",
+   "fieldtype": "Check",
+   "label": "Include Item In Manufacturing"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_11", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:!parent.skip_transfer", 
-   "fieldname": "consumed_qty", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Consumed Qty", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "eval:!parent.skip_transfer",
+   "fieldname": "consumed_qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Consumed Qty",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "available_qty_at_source_warehouse", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Available Qty at Source Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "available_qty_at_source_warehouse",
+   "fieldtype": "Float",
+   "label": "Available Qty at Source Warehouse",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "available_qty_at_wip_warehouse", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Available Qty at WIP Warehouse", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "available_qty_at_wip_warehouse",
+   "fieldtype": "Float",
+   "label": "Available Qty at WIP Warehouse",
+   "read_only": 1
+  },
+  {
+   "fieldname": "rate",
+   "fieldtype": "Currency",
+   "label": "Rate",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Amount",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-20 19:04:38.508839", 
- "modified_by": "Administrator", 
- "module": "Manufacturing", 
- "name": "Work Order Item", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-13 18:46:32.966416",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py
index b5127f1..1b49df6 100644
--- a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py
+++ b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py
@@ -45,7 +45,7 @@
 	def execute_report(self):
 		self.prepare_periodical_data()
 		self.forecast_future_data()
-		self.data = self.period_wise_data.values()
+		self.prepare_final_data()
 		self.add_total()
 
 		columns = self.get_columns()
@@ -108,7 +108,17 @@
 		""".format(doc=self.doctype, child_doc=self.child_doctype, date_field=date_field, cond=cond),
 			tuple(input_data), as_dict=1)
 
+	def prepare_final_data(self):
+		self.data = []
+
+		if not self.period_wise_data: return
+
+		for key in self.period_wise_data:
+			self.data.append(self.period_wise_data.get(key))
+
 	def add_total(self):
+		if not self.data: return
+
 		total_row = {
 			"item_code": _(frappe.bold("Total Quantity"))
 		}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index af7cb8e..929f8d6 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -678,16 +678,18 @@
 erpnext.patches.v12_0.fix_quotation_expired_status
 erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
 erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
-erpnext.patches.v12_0.remove_duplicate_leave_ledger_entries
+erpnext.patches.v12_0.remove_duplicate_leave_ledger_entries #2020-05-22
 erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
 execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
 execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
 erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
 erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
-erpnext.patches.v12_0.set_serial_no_status
+erpnext.patches.v12_0.set_serial_no_status #2020-05-21
 erpnext.patches.v12_0.update_price_list_currency_in_bom
 execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
 erpnext.patches.v13_0.update_actual_start_and_end_date_in_wo
-erpnext.patches.v13_0.set_company_field_in_healthcare_doctypes
+erpnext.patches.v13_0.set_company_field_in_healthcare_doctypes #2020-05-25
 erpnext.patches.v12_0.update_bom_in_so_mr
 execute:frappe.delete_doc("Report", "Department Analytics")
+execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
+erpnext.patches.v12_0.update_uom_conversion_factor
diff --git a/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py b/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py
index 98a2fcf..24286dc 100644
--- a/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py
+++ b/erpnext/patches/v12_0/remove_duplicate_leave_ledger_entries.py
@@ -6,6 +6,7 @@
 
 def execute():
 	"""Delete duplicate leave ledger entries of type allocation created."""
+	frappe.reload_doc('hr', 'doctype', 'leave_ledger_entry')
 	if not frappe.db.a_row_exists("Leave Ledger Entry"):
 		return
 
@@ -14,31 +15,32 @@
 
 def get_duplicate_records():
 	"""Fetch all but one duplicate records from the list of expired leave allocation."""
-	return frappe.db.sql_list("""
-		WITH duplicate_records AS
-		(SELECT
-			name, transaction_name, is_carry_forward,
-			ROW_NUMBER() over(partition by transaction_name order by creation)as row
-		FROM `tabLeave Ledger Entry` l
-		WHERE (EXISTS
-			(SELECT name
-				FROM `tabLeave Ledger Entry`
-				WHERE
-					transaction_name = l.transaction_name
-					AND transaction_type = 'Leave Allocation'
-					AND name <> l.name
-					AND employee = l.employee
-					AND docstatus = 1
-					AND leave_type = l.leave_type
-					AND is_carry_forward=l.is_carry_forward
-					AND to_date = l.to_date
-					AND from_date = l.from_date
-					AND is_expired = 1
-		)))
-		SELECT name FROM duplicate_records WHERE row > 1
+	return frappe.db.sql("""
+		SELECT name, employee, transaction_name, leave_type, is_carry_forward, from_date, to_date
+		FROM `tabLeave Ledger Entry`
+		WHERE
+			transaction_type = 'Leave Allocation'
+			AND docstatus = 1
+			AND is_expired = 1
+		GROUP BY
+			employee, transaction_name, leave_type, is_carry_forward, from_date, to_date
+		HAVING
+			count(name) > 1
+		ORDER BY
+			creation
 	""")
 
 def delete_duplicate_ledger_entries(duplicate_records_list):
 	"""Delete duplicate leave ledger entries."""
-	if duplicate_records_list:
-		frappe.db.sql(''' DELETE FROM `tabLeave Ledger Entry` WHERE name in {0}'''.format(tuple(duplicate_records_list))) #nosec
\ No newline at end of file
+	if not duplicate_records_list: return
+	for d in duplicate_records_list:
+		frappe.db.sql('''
+			DELETE FROM `tabLeave Ledger Entry`
+			WHERE name != %s
+				AND employee = %s
+				AND transaction_name = %s
+				AND leave_type = %s
+				AND is_carry_forward = %s
+				AND from_date = %s
+				AND to_date = %s
+		''', tuple(d))
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/set_serial_no_status.py b/erpnext/patches/v12_0/set_serial_no_status.py
index 4ec84ef..3b5f5ef 100644
--- a/erpnext/patches/v12_0/set_serial_no_status.py
+++ b/erpnext/patches/v12_0/set_serial_no_status.py
@@ -5,13 +5,22 @@
 def execute():
 	frappe.reload_doc('stock', 'doctype', 'serial_no')
 
-	for serial_no in frappe.db.sql("""select name, delivery_document_type, warranty_expiry_date from `tabSerial No`
-		where (status is NULL OR status='')""", as_dict = 1):
+	serial_no_list = frappe.db.sql("""select name, delivery_document_type, warranty_expiry_date, warehouse from `tabSerial No`
+		where (status is NULL OR status='')""", as_dict = 1)
+	if len(serial_no_list) > 20000:
+		frappe.db.auto_commit_on_many_writes = True
+
+	for serial_no in serial_no_list:
 		if serial_no.get("delivery_document_type"):
 			status = "Delivered"
 		elif serial_no.get("warranty_expiry_date") and getdate(serial_no.get("warranty_expiry_date")) <= getdate(nowdate()):
 			status = "Expired"
+		elif not serial_no.get("warehouse"):
+			status = "Inactive"
 		else:
 			status = "Active"
 
-		frappe.db.set_value("Serial No", serial_no.get("name"), "status", status)
\ No newline at end of file
+		frappe.db.set_value("Serial No", serial_no.get("name"), "status", status)
+
+	if frappe.db.auto_commit_on_many_writes:
+		frappe.db.auto_commit_on_many_writes = False
diff --git a/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py b/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py
index 60aec05..b8efb21 100644
--- a/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py
+++ b/erpnext/patches/v12_0/unset_customer_supplier_based_on_type_of_item_price.py
@@ -1,15 +1,29 @@
 from __future__ import unicode_literals
 import frappe
 
+
 def execute():
-    invalid_selling_item_price = frappe.db.sql(
-        """SELECT name FROM `tabItem Price` WHERE selling = 1 and buying = 0 and (supplier IS NOT NULL or supplier = '')"""
-    )
-    invalid_buying_item_price = frappe.db.sql(
-        """SELECT name FROM `tabItem Price` WHERE selling = 0 and buying = 1 and (customer IS NOT NULL or customer = '')"""
-    )
-    docs_to_modify = invalid_buying_item_price + invalid_selling_item_price
-    for d in docs_to_modify:
-        # saving the doc will auto reset invalid customer/supplier field
-        doc = frappe.get_doc("Item Price", d[0])
-        doc.save()
\ No newline at end of file
+    """
+    set proper customer and supplier details for item price
+    based on selling and buying values
+    """
+
+    # update for selling
+    frappe.db.sql(
+        """UPDATE `tabItem Price` ip, `tabPrice List` pl
+        SET ip.`reference` = ip.`customer`, ip.`supplier` = NULL
+        WHERE ip.`selling` = 1
+        AND ip.`buying` = 0
+        AND (ip.`supplier` IS NOT NULL OR ip.`supplier` = '')
+        AND ip.`price_list` = pl.`name`
+        AND pl.`enabled` = 1""")
+
+    # update for buying
+    frappe.db.sql(
+        """UPDATE `tabItem Price` ip, `tabPrice List` pl
+        SET ip.`reference` = ip.`supplier`, ip.`customer` = NULL
+        WHERE ip.`selling` = 0
+        AND ip.`buying` = 1
+        AND (ip.`customer` IS NOT NULL OR ip.`customer` = '')
+        AND ip.`price_list` = pl.`name`
+        AND pl.`enabled` = 1""")
diff --git a/erpnext/patches/v12_0/update_uom_conversion_factor.py b/erpnext/patches/v12_0/update_uom_conversion_factor.py
new file mode 100644
index 0000000..b5a20aa
--- /dev/null
+++ b/erpnext/patches/v12_0/update_uom_conversion_factor.py
@@ -0,0 +1,11 @@
+from __future__ import unicode_literals
+import frappe, json
+
+def execute():
+	from erpnext.setup.setup_wizard.operations.install_fixtures import add_uom_data
+
+	frappe.reload_doc("setup", "doctype", "UOM Conversion Factor")
+	frappe.reload_doc("setup", "doctype", "UOM")
+	frappe.reload_doc("stock", "doctype", "UOM Category")
+
+	add_uom_data()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
index 9d0dae4..a7d4c66 100644
--- a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
+++ b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
@@ -3,8 +3,8 @@
 
 def execute():
 	company = frappe.db.get_single_value('Global Defaults', 'default_company')
-	doctypes = ['Clinical Procedure', 'Inpatient Record', 'Lab Test', 'Patient Appointment', 'Patient Encounter', 'Vital Signs']
+	doctypes = ['Clinical Procedure', 'Inpatient Record', 'Lab Test', 'Sample Collection' 'Patient Appointment', 'Patient Encounter', 'Vital Signs', 'Therapy Session', 'Therapy Plan', 'Patient Assessment']
 	for entry in doctypes:
 		if frappe.db.exists('DocType', entry):
-			frappe.reload_doc("Healthcare", "doctype", entry)
+			frappe.reload_doc('Healthcare', 'doctype', entry)
 			frappe.db.sql("update `tab{dt}` set company = '{company}' where ifnull(company, '') = ''".format(dt=entry, company=company))
diff --git a/erpnext/patches/v7_0/update_mins_to_first_response.py b/erpnext/patches/v7_0/update_mins_to_first_response.py
index 1df4b42..1668135 100644
--- a/erpnext/patches/v7_0/update_mins_to_first_response.py
+++ b/erpnext/patches/v7_0/update_mins_to_first_response.py
@@ -1,7 +1,7 @@
 from __future__ import unicode_literals
 import frappe
 
-from frappe.core.doctype.communication.email import update_mins_to_first_communication
+from frappe.core.doctype.communication.communication import update_mins_to_first_communication
 
 def execute():
 	frappe.reload_doctype('Issue')
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index e94d1ff..2695502 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -23,8 +23,6 @@
 		"public/js/queries.js",
 		"public/js/sms_manager.js",
 		"public/js/utils/party.js",
-		"public/js/templates/address_list.html",
-		"public/js/templates/contact_list.html",
 		"public/js/controllers/stock_controller.js",
 		"public/js/payment/payments.js",
 		"public/js/controllers/taxes_and_totals.js",
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 28c2102..524a958 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1652,8 +1652,10 @@
 					if(!r.exc) {
 						$.each(me.frm.doc.items || [], function(i, item) {
 							if(item.item_code && r.message.hasOwnProperty(item.item_code)) {
-								item.item_tax_template = r.message[item.item_code].item_tax_template;
-								item.item_tax_rate = r.message[item.item_code].item_tax_rate;
+								if (!item.item_tax_template) {
+									item.item_tax_template = r.message[item.item_code].item_tax_template;
+									item.item_tax_rate = r.message[item.item_code].item_tax_rate;
+								}
 								me.add_taxes_from_item_tax_template(item.item_tax_rate);
 							} else {
 								item.item_tax_template = "";
@@ -1709,7 +1711,7 @@
 	},
 
 	set_gross_profit: function(item) {
-		if (this.frm.doc.doctype == "Sales Order" && item.valuation_rate) {
+		if (["Sales Order", "Quotation"].includes(this.frm.doc.doctype) && item.valuation_rate) {
 			var rate = flt(item.rate) * flt(this.frm.doc.conversion_rate || 1);
 			item.gross_profit = flt(((rate - item.valuation_rate) * item.stock_qty), precision("amount", item));
 		}
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 296c628..cf98b75 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -62,7 +62,7 @@
 	}
 };
 
-function get_filters(){
+function get_filters() {
 	let filters = [
 		{
 			"fieldname":"company",
@@ -162,15 +162,6 @@
 		}
 	]
 
-	erpnext.dimension_filters.forEach((dimension) => {
-		filters.push({
-			"fieldname": dimension["fieldname"],
-			"label": __(dimension["label"]),
-			"fieldtype": "Link",
-			"options": dimension["document_type"]
-		});
-	});
-
 	return filters;
 }
 
diff --git a/erpnext/public/js/templates/address_list.html b/erpnext/public/js/templates/address_list.html
deleted file mode 100644
index 0f967b6..0000000
--- a/erpnext/public/js/templates/address_list.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<div class="clearfix"></div>
-{% for(var i=0, l=addr_list.length; i<l; i++) { %}
-<div class="address-box">
-	<p class="h6">
-		{%= i+1 %}. {%= addr_list[i].address_title %}{% if(addr_list[i].address_type!="Other") { %}
-		<span class="text-muted">({%= __(addr_list[i].address_type) %})</span>{% } %}
-		{% if(addr_list[i].is_primary_address) { %}
-		<span class="text-muted">({%= __("Primary") %})</span>{% } %}
-		{% if(addr_list[i].is_shipping_address) { %}
-		<span class="text-muted">({%= __("Shipping") %})</span>{% } %}
-
-		<a href="#Form/Address/{%= encodeURIComponent(addr_list[i].name) %}" class="btn btn-default btn-xs pull-right"
-			style="margin-top:-3px; margin-right: -5px;">
-			{%= __("Edit") %}</a>
-	</p>
-	<p>{%= addr_list[i].display %}</p>
-</div>
-{% } %}
-{% if(!addr_list.length) { %}
-<p class="text-muted small">{%= __("No address added yet.") %}</p>
-{% } %}
-<p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p>
\ No newline at end of file
diff --git a/erpnext/public/js/templates/contact_list.html b/erpnext/public/js/templates/contact_list.html
deleted file mode 100644
index 7e69691..0000000
--- a/erpnext/public/js/templates/contact_list.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<div class="clearfix"></div>
-{% for(var i=0, l=contact_list.length; i<l; i++) { %}
-	<div class="address-box">
-		<p class="h6">
-			{%= contact_list[i].first_name %} {%= contact_list[i].last_name %}
-			{% if(contact_list[i].is_primary_contact) { %}
-				<span class="text-muted">({%= __("Primary") %})</span>
-			{% } %}
-			{% if(contact_list[i].designation){ %}
-			 <span class="text-muted">&ndash; {%= contact_list[i].designation %}</span>
-			{% } %}
-			<a href="#Form/Contact/{%= encodeURIComponent(contact_list[i].name) %}"
-				class="btn btn-xs btn-default pull-right"
-				style="margin-top:-3px; margin-right: -5px;">
-				{%= __("Edit") %}</a>
-		</p>
-		{% if (contact_list[i].phones || contact_list[i].email_ids) { %}
-		<p>
-			{% if(contact_list[i].phone) { %}
-				{%= __("Phone") %}: {%= contact_list[i].phone %}<span class="text-muted"> ({%= __("Primary") %})</span><br>
-			{% endif %}
-			{% if(contact_list[i].mobile_no) { %}
-				{%= __("Mobile No") %}: {%= contact_list[i].mobile_no %}<span class="text-muted"> ({%= __("Primary") %})</span><br>
-			{% endif %}
-			{% if(contact_list[i].phone_nos) { %}
-				{% for(var j=0, k=contact_list[i].phone_nos.length; j<k; j++) { %}
-					{%= __("Phone") %}: {%= contact_list[i].phone_nos[j].phone %}<br>
-				{% } %}
-			{% endif %}
-		</p>
-		<p>
-			{% if(contact_list[i].email_id) { %}
-				{%= __("Email") %}: {%= contact_list[i].email_id %}<span class="text-muted"> ({%= __("Primary") %})</span><br>
-			{% endif %}
-			{% if(contact_list[i].email_ids) { %}
-				{% for(var j=0, k=contact_list[i].email_ids.length; j<k; j++) { %}
-					{%= __("Email") %}: {%= contact_list[i].email_ids[j].email_id %}<br>
-				{% } %}
-			{% endif %}
-		</p>
-		{% endif %}
-		<p>
-		{% if (contact_list[i].address) { %}
-			{%= __("Address") %}: {%= contact_list[i].address %}<br>
-		{% endif %}
-		</p>
-	</div>
-{% } %}
-{% if(!contact_list.length) { %}
-<p class="text-muted small">{%= __("No contacts added yet.") %}</p>
-{% } %}
-<p><button class="btn btn-xs btn-default btn-contact">
-	{{ __("New Contact") }}</button>
-</p>
\ No newline at end of file
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 58969f2..2cd79b5 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -191,6 +191,23 @@
 		})
 	},
 
+	add_dimensions: function(report_name, index) {
+		let filters = frappe.query_reports[report_name].filters;
+
+		erpnext.dimension_filters.forEach((dimension) => {
+			let found = filters.some(el => el.fieldname === dimension['fieldname']);
+
+			if (!found) {
+				filters.splice(index, 0 ,{
+					"fieldname": dimension["fieldname"],
+					"label": __(dimension["label"]),
+					"fieldtype": "Link",
+					"options": dimension["document_type"]
+				});
+			}
+		});
+	},
+
 	make_subscription: function(doctype, docname) {
 		frappe.call({
 			method: "frappe.automation.doctype.auto_repeat.auto_repeat.make_auto_repeat",
diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py
index 6784ea8..6b9567c 100644
--- a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py
+++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py
@@ -58,7 +58,7 @@
 				"naming_series": self.invoice_series,
 				"document_type": line.TipoDocumento.text,
 				"bill_date": get_datetime_str(line.Data.text),
-				"invoice_no": line.Numero.text,
+				"bill_no": line.Numero.text,
 				"total_discount": 0,
 				"items": [],
 				"buying_price_list": self.default_buying_price_list
@@ -249,7 +249,7 @@
 
 		return existing_supplier_name
 	else:
-		
+
 		new_supplier = frappe.new_doc("Supplier")
 		new_supplier.supplier_name = re.sub('&amp', '&', args.supplier)
 		new_supplier.supplier_group = supplier_group
diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py
index a01c6ce..772bbf5 100644
--- a/erpnext/regional/united_arab_emirates/utils.py
+++ b/erpnext/regional/united_arab_emirates/utils.py
@@ -1,6 +1,8 @@
 from __future__ import unicode_literals
+import frappe
 from frappe.utils import flt
 from erpnext.controllers.taxes_and_totals import get_itemised_tax
+from six import iteritems
 
 def update_itemised_tax_data(doc):
 	if not doc.taxes: return
@@ -9,7 +11,14 @@
 
 	for row in doc.items:
 		tax_rate = 0.0
-		if itemised_tax.get(row.item_code):
+		item_tax_rate = frappe.parse_json(row.item_tax_rate)
+
+		# First check if tax rate is present
+		# If not then look up in item_wise_tax_detail
+		if item_tax_rate:
+			for account, rate in iteritems(item_tax_rate):
+				tax_rate += rate
+		elif itemised_tax.get(row.item_code):
 			tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
 
 		row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 7cfec5a..0e771c3 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -197,9 +197,9 @@
 	cond = "qo.docstatus = 1 and qo.status != 'Expired' and qo.valid_till < %s"
 	# check if those QUO have SO against it
 	so_against_quo = """
-		SELECT 
+		SELECT
 			so.name FROM `tabSales Order` so, `tabSales Order Item` so_item
-		WHERE 
+		WHERE
 			so_item.docstatus = 1 and so.docstatus = 1
 			and so_item.parent = so.name
 			and so_item.prevdoc_docname = qo.name"""
diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json
index d50397c..59ae7b2 100644
--- a/erpnext/selling/doctype/quotation_item/quotation_item.json
+++ b/erpnext/selling/doctype/quotation_item/quotation_item.json
@@ -48,6 +48,10 @@
   "base_net_amount",
   "pricing_rules",
   "is_free_item",
+  "section_break_43",
+  "valuation_rate",
+  "column_break_45",
+  "gross_profit",
   "item_weight_details",
   "weight_per_unit",
   "total_weight",
@@ -602,12 +606,40 @@
    "label": "Against Blanket Order",
    "no_copy": 1,
    "print_hide": 1
+  },
+  {
+   "fieldname": "section_break_43",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "valuation_rate",
+   "fieldtype": "Currency",
+   "label": "Valuation Rate",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "column_break_45",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "gross_profit",
+   "fieldtype": "Currency",
+   "label": "Gross Profit",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-03-30 18:40:28.782720",
+ "modified": "2020-05-19 20:48:43.222229",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation Item",
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 0fbe49e..875904f 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -107,6 +107,9 @@
 
 		erpnext.company.set_chart_of_accounts_options(frm.doc);
 
+		if (!frappe.user.has_role('System Manager')) {
+			frm.get_field("delete_company_transactions").hide();
+		}
 	},
 
 	make_default_tax_template: function(frm) {
@@ -134,7 +137,7 @@
 			var d = frappe.prompt({
 				fieldtype:"Data",
 				fieldname: "company_name",
-				label: __("Please re-type company name to confirm"),
+				label: __("Please enter the company name to confirm"),
 				reqd: 1,
 				description: __("Please make sure you really want to delete all the transactions for this company. Your master data will remain as it is. This action cannot be undone.")
 			},
diff --git a/erpnext/setup/setup_wizard/data/uom_conversion_data.json b/erpnext/setup/setup_wizard/data/uom_conversion_data.json
index 174ecd5..27a917d 100644
--- a/erpnext/setup/setup_wizard/data/uom_conversion_data.json
+++ b/erpnext/setup/setup_wizard/data/uom_conversion_data.json
@@ -1571,5 +1571,19 @@
 		"to_uom": "Parts Per Million",
 		"abbr": "ppm",
 		"value": "10000"
+	},
+	{
+		"category": "Mass",
+		"from_uom": "Pound",
+		"to_uom": "Ounce",
+		"abbr": "oz",
+		"value": "16"
+	},
+	{
+		"category": "Mass",
+		"from_uom": "Gram",
+		"to_uom": "Ounce",
+		"abbr": "oz",
+		"value": "0.035274"
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 8bb0a05..0d70d91 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -336,13 +336,14 @@
 				"category_name": _(d.get("category"))
 			}).insert(ignore_permissions=True)
 
-		uom_conversion = frappe.get_doc({
-			"doctype": "UOM Conversion Factor",
-			"category": _(d.get("category")),
-			"from_uom": _(d.get("from_uom")),
-			"to_uom": _(d.get("to_uom")),
-			"value": d.get("value")
-		}).insert(ignore_permissions=True)
+		if not frappe.db.exists("UOM Conversion Factor", {"from_uom": _(d.get("from_uom")), "to_uom": _(d.get("to_uom"))}):
+			uom_conversion = frappe.get_doc({
+				"doctype": "UOM Conversion Factor",
+				"category": _(d.get("category")),
+				"from_uom": _(d.get("from_uom")),
+				"to_uom": _(d.get("to_uom")),
+				"value": d.get("value")
+			}).insert(ignore_permissions=True)
 
 def add_market_segments():
 	records = [
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 4ac546e..d04c8c2 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -319,7 +319,7 @@
 def set_price_list_and_rate(quotation, cart_settings):
 	"""set price list based on billing territory"""
 
-	_set_price_list(quotation, cart_settings)
+	_set_price_list(cart_settings, quotation)
 
 	# reset values
 	quotation.price_list_currency = quotation.currency = \
@@ -334,23 +334,28 @@
 		# set it in cookies for using in product page
 		frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
 
-def _set_price_list(quotation, cart_settings):
+def _set_price_list(cart_settings, quotation=None):
 	"""Set price list based on customer or shopping cart default"""
 	from erpnext.accounts.party import get_default_price_list
 
 	# check if customer price list exists
 	selling_price_list = None
-	if quotation.party_name:
-		selling_price_list = frappe.db.get_value('Customer', quotation.party_name, 'default_price_list')
+	if quotation and quotation.get("party_name"):
+		selling_price_list = frappe.db.get_value('Customer', quotation.get("party_name"), 'default_price_list')
 
 	# else check for territory based price list
 	if not selling_price_list:
 		selling_price_list = cart_settings.price_list
 
-	if not selling_price_list and quotation.party_name:
-		selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.party_name))
+	party_name = quotation.get("party_name") if quotation else get_party().get("name")
 
-	quotation.selling_price_list = selling_price_list
+	if not selling_price_list and party_name:
+		selling_price_list = get_default_price_list(frappe.get_doc("Customer", party_name))
+
+	if quotation:
+		quotation.selling_price_list = selling_price_list
+
+	return selling_price_list
 
 def set_taxes(quotation, cart_settings):
 	"""set taxes based on billing territory"""
diff --git a/erpnext/shopping_cart/product_info.py b/erpnext/shopping_cart/product_info.py
index 21ee335..7c08f5b 100644
--- a/erpnext/shopping_cart/product_info.py
+++ b/erpnext/shopping_cart/product_info.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 
 import frappe
-from erpnext.shopping_cart.cart import _get_cart_quotation
+from erpnext.shopping_cart.cart import _get_cart_quotation, _set_price_list
 from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings \
 	import get_shopping_cart_settings, show_quantity_in_website
 from erpnext.utilities.product import get_price, get_qty_in_stock, get_non_stock_item_status
@@ -21,9 +21,11 @@
 	if not skip_quotation_creation:
 		cart_quotation = _get_cart_quotation()
 
+	selling_price_list = cart_quotation.get("selling_price_list") if cart_quotation else _set_price_list(cart_settings, None)
+
 	price = get_price(
 		item_code,
-		cart_quotation.selling_price_list,
+		selling_price_list,
 		cart_settings.default_customer_group,
 		cart_settings.company
 	)
@@ -42,7 +44,7 @@
 
 	if product_info["price"]:
 		if frappe.session.user != "Guest":
-			item = cart_quotation.get({"item_code": item_code})
+			item = cart_quotation.get({"item_code": item_code}) if cart_quotation else None
 			if item:
 				product_info["qty"] = item[0].qty
 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 7a1c127..3436a5d 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -1144,6 +1144,17 @@
 	item.clear_cache()
 
 @frappe.whitelist()
+def get_item_details(item_code, company=None):
+	out = frappe._dict()
+	if company:
+		out = get_item_defaults(item_code, company) or frappe._dict()
+
+	doc = frappe.get_cached_doc("Item", item_code)
+	out.update(doc.as_dict())
+
+	return out
+
+@frappe.whitelist()
 def get_uom_conv_factor(uom, stock_uom):
 	uoms = [uom, stock_uom]
 	value = ""
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index d46b98b..3a5ef76 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -31,10 +31,16 @@
 			};
 		});
 		frm.set_query('item_code', 'locations', () => {
+			return erpnext.queries.item({ "is_stock_item": 1 });
+		});
+		frm.set_query('batch_no', 'locations', (frm, cdt, cdn) => {
+			const row = locals[cdt][cdn];
 			return {
+				query: 'erpnext.controllers.queries.get_batch_no',
 				filters: {
-					is_stock_item: 1
-				}
+					item_code: row.item_code,
+					warehouse: row.warehouse
+				},
 			};
 		});
 	},
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 231af1a..93b29c8 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -24,6 +24,9 @@
 		for item in self.locations:
 			if not frappe.get_cached_value('Item', item.item_code, 'has_serial_no'):
 				continue
+			if not item.serial_no:
+				frappe.throw(_("Row #{0}: {1} does not have any available serial numbers in {2}".format(
+					frappe.bold(item.idx), frappe.bold(item.item_code), frappe.bold(item.warehouse))))
 			if len(item.serial_no.split('\n')) == item.picked_qty:
 				continue
 			frappe.throw(_('For item {0} at row {1}, count of serial numbers does not match with the picked quantity')
@@ -300,6 +303,7 @@
 	set_delivery_note_missing_values(delivery_note)
 
 	delivery_note.pick_list = pick_list.name
+	delivery_note.customer = pick_list.customer if pick_list.customer else None
 
 	return delivery_note
 
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index 731a730..d9f8b62 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -420,14 +420,14 @@
    "fieldtype": "Select",
    "in_standard_filter": 1,
    "label": "Status",
-   "options": "\nActive\nDelivered\nExpired",
+   "options": "\nActive\nInactive\nDelivered\nExpired",
    "read_only": 1
   }
  ],
  "icon": "fa fa-barcode",
  "idx": 1,
  "links": [],
- "modified": "2020-04-08 13:29:58.517772",
+ "modified": "2020-05-21 19:29:58.517772",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Serial No",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 914eea3..f3514c7 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -42,6 +42,8 @@
 			self.status = "Delivered"
 		elif self.warranty_expiry_date and getdate(self.warranty_expiry_date) <= getdate(nowdate()):
 			self.status = "Expired"
+		elif not self.warehouse:
+			self.status = "Inactive"
 		else:
 			self.status = "Active"
 
diff --git a/erpnext/stock/doctype/serial_no/serial_no_list.js b/erpnext/stock/doctype/serial_no/serial_no_list.js
index 651f790..7526d1d 100644
--- a/erpnext/stock/doctype/serial_no/serial_no_list.js
+++ b/erpnext/stock/doctype/serial_no/serial_no_list.js
@@ -5,6 +5,8 @@
 			return [__("Delivered"), "green", "delivery_document_type,is,set"];
 		} else if (doc.warranty_expiry_date && frappe.datetime.get_diff(doc.warranty_expiry_date, frappe.datetime.nowdate()) <= 0) {
 			return [__("Expired"), "red", "warranty_expiry_date,not in,|warranty_expiry_date,<=,Today|delivery_document_type,is,not set"];
+		} else if (!doc.warehouse) {
+			return [__("Inactive"), "grey", "warehouse,is,not set"];
 		} else {
 			return [__("Active"), "green", "delivery_document_type,is,not set"];
 		}
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index 6f97572..877d0c3 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -36,7 +36,7 @@
 	{
 		fieldname: "valuation_method",
 		title: __("Valuation Method"),
-		description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/stock/articles/item-valuation-fifo-and-moving-average'>here</a>" + __(" to know more about them.")
+		description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/stock/articles/item-valuation-fifo-and-moving-average' target='_blank'>here</a>" + __(" to know more about them.")
 	},
 	{
 		fieldname: "show_barcode_field",
diff --git a/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
index 447611f..009a44f 100644
--- a/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
+++ b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
@@ -8,12 +8,12 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-19 18:55:41.457289",
+ "modified": "2020-05-26 15:55:41.457289",
  "modified_by": "Administrator",
  "name": "Introduction to Stock Entry",
  "owner": "Administrator",
  "show_full_form": 0,
- "title": "Introduction to the multi-purpose stock transaction",
+ "title": "Introduction to Stock Entry",
  "validate_action": 1,
  "video_url": "https://www.youtube.com/watch?v=Njt107hlY3I"
 }
\ No newline at end of file
diff --git a/erpnext/www/all-products/index.html b/erpnext/www/all-products/index.html
index f090214..0126b59 100644
--- a/erpnext/www/all-products/index.html
+++ b/erpnext/www/all-products/index.html
@@ -11,7 +11,7 @@
 		<div class="input-group input-group-sm mb-3">
 			<input type="search" class="form-control" placeholder="{{_('Search')}}"
 				aria-label="{{_('Product Search')}}" aria-describedby="product-search"
-				value="{{ frappe.form_dict.search or '' }}"
+				value="{{ frappe.sanitize_html(frappe.form_dict.search) or '' }}"
 			>
 		</div>
 	</div>