Merge pull request #4814 from rmehta/exclude-bom-from-delete-company

[fix] exclude BOM from delete company records and unset company in others
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 158ae35..4e3fa17 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
 from __future__ import unicode_literals
-__version__ = '6.21.4'
+__version__ = '6.21.6'
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index f0524c0..822702b 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -17,11 +17,14 @@
 
 def validate_filters(filters):
 	if not filters.fiscal_year:
-		frappe.throw(_("Fiscal Year {0} is required"))
-	filters.year_start_date, filters.year_end_date = frappe.db.get_value("Fiscal Year", filters.fiscal_year,
-		["year_start_date", "year_end_date"])
-	filters.year_start_date = getdate(filters.year_start_date)
-	filters.year_end_date = getdate(filters.year_end_date)
+		frappe.throw(_("Fiscal Year {0} is required").format(filters.fiscal_year))
+
+	fiscal_year = frappe.db.get_value("Fiscal Year", filters.fiscal_year, ["year_start_date", "year_end_date"], as_dict=True)
+	if not fiscal_year:
+		frappe.throw(_("Fiscal Year {0} does not exist").format(filters.fiscal_year))
+	else:
+		filters.year_start_date = getdate(fiscal_year.year_start_date)
+		filters.year_end_date = getdate(fiscal_year.year_end_date)
 
 	if not filters.from_date:
 		filters.from_date = filters.year_start_date
diff --git a/erpnext/docs/user/manual/en/accounts/payment-request.md b/erpnext/docs/user/manual/en/accounts/payment-request.md
index 68d4397..1b71f2f 100644
--- a/erpnext/docs/user/manual/en/accounts/payment-request.md
+++ b/erpnext/docs/user/manual/en/accounts/payment-request.md
@@ -11,7 +11,7 @@
 Select appropriate Payment Gateway Account on Payment Request. Account head specified on payment gateway will 
 considered to create journal entry. 
 
-Note: Invoice/Order Currency and Payment Gateway Account corruncy should be same.
+Note: Invoice/Order currency and Payment Gateway Account currency should be same.
 
 <img class="screenshot" alt="Payment Request" src="{{docs_base_url}}/assets/img/accounts/pr-details-1.png">
 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 3700590..aa4ae96 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -7,7 +7,7 @@
 app_description = """ERP made simple"""
 app_icon = "icon-th"
 app_color = "#e74c3c"
-app_version = "6.21.4"
+app_version = "6.21.6"
 app_email = "info@erpnext.com"
 app_license = "GNU General Public License (v3)"
 source_link = "https://github.com/frappe/erpnext"
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index c486391..16e78a6 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -92,14 +92,26 @@
 		cur_frm.toggle_enable("exp_approver", doc.approval_status=="Draft");
 		cur_frm.toggle_enable("approval_status", (doc.exp_approver==user && doc.docstatus==0));
 
-		if(doc.docstatus==0 && doc.exp_approver==user && doc.approval_status=="Approved")
+		if (doc.docstatus==0 && doc.exp_approver==user && doc.approval_status=="Approved")
 			 cur_frm.savesubmit();
 
-		if(doc.docstatus==1 && frappe.model.can_create("Journal Entry") && doc.approval_status=="Approved" &&
-			cint(doc.total_amount_reimbursed) < cint(doc.total_sanctioned_amount))
-				cur_frm.add_custom_button(__("Bank Entry"),
-				 	cur_frm.cscript.make_bank_entry, __("Make"));
+		if (doc.docstatus===1 && doc.approval_status=="Approved") {
+			if (cint(doc.total_amount_reimbursed) < cint(doc.total_sanctioned_amount) && frappe.model.can_create("Journal Entry")) {
+				cur_frm.add_custom_button(__("Bank Entry"), cur_frm.cscript.make_bank_entry, __("Make"));
 				cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
+			}
+
+			if (cint(doc.total_amount_reimbursed) > 0 && frappe.model.can_read("Journal Entry")) {
+				cur_frm.add_custom_button(__('Bank Entries'), function() {
+					frappe.route_options = {
+						"Journal Entry Account.reference_type": me.frm.doc.doctype,
+						"Journal Entry Account.reference_name": me.frm.doc.name,
+						company: me.frm.doc.company
+					};
+					frappe.set_route("List", "Journal Entry");
+				}, __("View"));
+			}
+		}
 	}
 }
 
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index b6698df..5c93ef0 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -280,7 +280,7 @@
 					var party_type = "Supplier";
 					var party_account_field = 'credit_to';
 				}
-				
+
 				var party = me.frm.doc[frappe.model.scrub(party_type)];
 				if(party) {
 					return frappe.call({
@@ -643,7 +643,9 @@
 					"item_code": d.item_code,
 					"item_group": d.item_group,
 					"brand": d.brand,
-					"qty": d.qty
+					"qty": d.qty,
+					"parenttype": d.parenttype,
+					"parent": d.parent
 				});
 			}
 		};
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 07d494a..557a392 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -36,7 +36,7 @@
 		if (columnDef.df.fieldname=="account") {
 			value = dataContext.account_name;
 
-			columnDef.df.link_onclick = 
+			columnDef.df.link_onclick =
 				"erpnext.financial_statements.open_general_ledger(" + JSON.stringify(dataContext) + ")";
 			columnDef.df.is_tree = true;
 		}
@@ -60,8 +60,8 @@
 		frappe.route_options = {
 			"account": data.account,
 			"company": frappe.query_report.filters_by_name.company.get_value(),
-			"from_date": data.year_start_date,
-			"to_date": data.year_end_date
+			"from_date": data.from_date || data.year_start_date,
+			"to_date": data.to_date || data.year_end_date
 		};
 		frappe.set_route("query-report", "General Ledger");
 	},
diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py
index 8b0189f..890f317 100644
--- a/erpnext/setup/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/setup_wizard/setup_wizard.py
@@ -372,7 +372,7 @@
 		customer = args.get("customer_" + str(i))
 		if customer:
 			try:
-				frappe.get_doc({
+				doc = frappe.get_doc({
 					"doctype":"Customer",
 					"customer_name": customer,
 					"customer_type": "Company",
@@ -383,7 +383,7 @@
 
 				if args.get("customer_contact_" + str(i)):
 					create_contact(args.get("customer_contact_" + str(i)),
-						"customer", customer)
+						"customer", doc.name)
 			except frappe.NameError:
 				pass
 
@@ -392,7 +392,7 @@
 		supplier = args.get("supplier_" + str(i))
 		if supplier:
 			try:
-				frappe.get_doc({
+				doc = frappe.get_doc({
 					"doctype":"Supplier",
 					"supplier_name": supplier,
 					"supplier_type": _("Local"),
@@ -401,7 +401,7 @@
 
 				if args.get("supplier_contact_" + str(i)):
 					create_contact(args.get("supplier_contact_" + str(i)),
-						"supplier", supplier)
+						"supplier", doc.name)
 			except frappe.NameError:
 				pass
 
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 5548350..22dbe51 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -196,7 +196,7 @@
 		or args.get("cost_center"))
 
 def get_price_list_rate(args, item_doc, out):
-	meta = frappe.get_meta(args.doctype)
+	meta = frappe.get_meta(args.parenttype or args.doctype)
 
 	if meta.get_field("currency"):
 		validate_price_list(args)
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 7d82da1..0a9abc2 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -14,21 +14,19 @@
 	iwb_map = get_item_warehouse_map(filters)
 
 	data = []
-	for company in sorted(iwb_map):
-		for item in sorted(iwb_map[company]):
-			for wh in sorted(iwb_map[company][item]):
-				qty_dict = iwb_map[company][item][wh]
-				data.append([item, item_map[item]["item_name"],
-					item_map[item]["item_group"],
-					item_map[item]["brand"],
-					item_map[item]["description"], wh,
-					item_map[item]["stock_uom"], qty_dict.opening_qty,
-					qty_dict.opening_val, qty_dict.in_qty,
-					qty_dict.in_val, qty_dict.out_qty,
-					qty_dict.out_val, qty_dict.bal_qty,
-					qty_dict.bal_val, qty_dict.val_rate,
-					company
-				])
+	for (company, item, warehouse) in sorted(iwb_map):
+		qty_dict = iwb_map[(company, item, warehouse)]
+		data.append([item, item_map[item]["item_name"],
+			item_map[item]["item_group"],
+			item_map[item]["brand"],
+			item_map[item]["description"], warehouse,
+			item_map[item]["stock_uom"], qty_dict.opening_qty,
+			qty_dict.opening_val, qty_dict.in_qty,
+			qty_dict.in_val, qty_dict.out_qty,
+			qty_dict.out_val, qty_dict.bal_qty,
+			qty_dict.bal_val, qty_dict.val_rate,
+			company
+		])
 
 	return columns, data
 
@@ -36,22 +34,22 @@
 	"""return columns based on filters"""
 
 	columns = [
-		_("Item")+":Link/Item:100", 
-		_("Item Name")+"::150", 
-		_("Item Group")+"::100", 
-		_("Brand")+"::90", 
-		_("Description")+"::140", 
-		_("Warehouse")+":Link/Warehouse:100", 
-		_("Stock UOM")+":Link/UOM:90", 
-		_("Opening Qty")+":Float:100", 
-		_("Opening Value")+":Float:110", 
-		_("In Qty")+":Float:80", 
-		_("In Value")+":Float:80", 
-		_("Out Qty")+":Float:80", 
-		_("Out Value")+":Float:80", 
-		_("Balance Qty")+":Float:100", 
-		_("Balance Value")+":Float:100", 
-		_("Valuation Rate")+":Float:90", 
+		_("Item")+":Link/Item:100",
+		_("Item Name")+"::150",
+		_("Item Group")+"::100",
+		_("Brand")+"::90",
+		_("Description")+"::140",
+		_("Warehouse")+":Link/Warehouse:100",
+		_("Stock UOM")+":Link/UOM:90",
+		_("Opening Qty")+":Float:100",
+		_("Opening Value")+":Float:110",
+		_("In Qty")+":Float:80",
+		_("In Value")+":Float:80",
+		_("Out Qty")+":Float:80",
+		_("Out Value")+":Float:80",
+		_("Balance Qty")+":Float:100",
+		_("Balance Value")+":Float:100",
+		_("Valuation Rate")+":Float:90",
 		_("Company")+":Link/Company:100"
 	]
 
@@ -63,7 +61,7 @@
 		frappe.throw(_("'From Date' is required"))
 
 	if filters.get("to_date"):
-		conditions += " and posting_date <= '%s'" % filters["to_date"]
+		conditions += " and posting_date <= '%s'" % frappe.db.escape(filters["to_date"])
 	else:
 		frappe.throw(_("'To Date' is required"))
 
@@ -76,25 +74,30 @@
 def get_stock_ledger_entries(filters):
 	conditions = get_conditions(filters)
 	return frappe.db.sql("""select item_code, warehouse, posting_date, actual_qty, valuation_rate,
-	company, voucher_type, qty_after_transaction, stock_value_difference
-		from `tabStock Ledger Entry`
+			company, voucher_type, qty_after_transaction, stock_value_difference
+		from `tabStock Ledger Entry` force index (posting_sort_index)
 		where docstatus < 2 %s order by posting_date, posting_time, name""" %
 		conditions, as_dict=1)
 
 def get_item_warehouse_map(filters):
-	sle = get_stock_ledger_entries(filters)
 	iwb_map = {}
+	from_date = getdate(filters["from_date"])
+	to_date = getdate(filters["to_date"])
+
+	sle = get_stock_ledger_entries(filters)
 
 	for d in sle:
-		iwb_map.setdefault(d.company, {}).setdefault(d.item_code, {}).\
-		setdefault(d.warehouse, frappe._dict({\
+		key = (d.company, d.item_code, d.warehouse)
+		if key not in iwb_map:
+			iwb_map[key] = frappe._dict({
 				"opening_qty": 0.0, "opening_val": 0.0,
 				"in_qty": 0.0, "in_val": 0.0,
 				"out_qty": 0.0, "out_val": 0.0,
 				"bal_qty": 0.0, "bal_val": 0.0,
 				"val_rate": 0.0, "uom": None
-			}))
-		qty_dict = iwb_map[d.company][d.item_code][d.warehouse]
+			})
+
+		qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)]
 
 		if d.voucher_type == "Stock Reconciliation":
 			qty_diff = flt(d.qty_after_transaction) - qty_dict.bal_qty
@@ -102,18 +105,19 @@
 			qty_diff = flt(d.actual_qty)
 
 		value_diff = flt(d.stock_value_difference)
-		
-		if d.posting_date < getdate(filters["from_date"]):
+
+		if d.posting_date < from_date:
 			qty_dict.opening_qty += qty_diff
 			qty_dict.opening_val += value_diff
-		elif d.posting_date >= getdate(filters["from_date"]) and d.posting_date <= getdate(filters["to_date"]):
+
+		elif d.posting_date >= from_date and d.posting_date <= to_date:
 			if qty_diff > 0:
 				qty_dict.in_qty += qty_diff
 				qty_dict.in_val += value_diff
 			else:
 				qty_dict.out_qty += abs(qty_diff)
 				qty_dict.out_val += abs(value_diff)
-				
+
 		qty_dict.val_rate = d.valuation_rate
 		qty_dict.bal_qty += qty_diff
 		qty_dict.bal_val += value_diff
diff --git a/setup.py b/setup.py
index fc52b1d..b91fd22 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 from setuptools import setup, find_packages
 from pip.req import parse_requirements
 
-version = "6.21.4"
+version = "6.21.6"
 requirements = parse_requirements("requirements.txt", session="")
 
 setup(