Fixed merge conflict
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 85e3403..282d6e4 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '10.1.20'
+__version__ = '10.1.21'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 44658f7..78dcee9 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -336,7 +336,7 @@
 			for item in self.get("items"):
 				if item.get('item_code'):
 					for fname, val in get_pos_profile_item_details(pos,
-						frappe._dict(item.as_dict()), pos).items():
+						frappe._dict(item.as_dict()), pos, True).items():
 
 						if (not for_validate) or (for_validate and not item.get(fname)):
 							item.set(fname, val)
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index 4aadd76..a9b1813 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -20,6 +20,10 @@
 		frm.trigger('set_contact_link');
 	},
 
+	with_items: function(frm) {
+		frm.trigger('toggle_mandatory');
+	},
+
 	customer_address: function(frm, cdt, cdn) {
 		erpnext.utils.get_address_display(frm, 'customer_address', 'address_display', false);
 	},
@@ -35,6 +39,7 @@
 		var doc = frm.doc;
 		frm.events.enquiry_from(frm);
 		frm.trigger('set_contact_link');
+		frm.trigger('toggle_mandatory');
 		erpnext.toggle_naming_series();
 
 		if(!doc.__islocal && doc.status!=="Lost") {
@@ -82,6 +87,10 @@
 			method: "erpnext.crm.doctype.opportunity.opportunity.make_supplier_quotation",
 			frm: cur_frm
 		})
+	},
+
+	toggle_mandatory: function(frm) {
+		frm.toggle_reqd("items", frm.doc.with_items ? 1:0);
 	}
 })
 
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index eb73946..1a40e7d 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -358,7 +358,7 @@
 
 	return allocated_leaves
 
-
+@frappe.whitelist()
 def get_holidays(employee, from_date, to_date):
 	'''get holidays between two dates for the given employee'''
 	holiday_list = get_holiday_list_for_employee(employee)
diff --git a/erpnext/patches/v9_2/rename_translated_domains_in_en.py b/erpnext/patches/v9_2/rename_translated_domains_in_en.py
index c787b84..fc3d01c 100644
--- a/erpnext/patches/v9_2/rename_translated_domains_in_en.py
+++ b/erpnext/patches/v9_2/rename_translated_domains_in_en.py
@@ -2,6 +2,7 @@
 from frappe import _
 
 def execute():
+	frappe.reload_doc('stock', 'doctype', 'item')
 	language = frappe.get_single("System Settings").language
 
 	if language and language.startswith('en'): return
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index fb2faba..b878a1e 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -10,7 +10,7 @@
 
 	if doc.gstin:
 		doc.gstin = doc.gstin.upper()
-		if doc.gstin != "NA":
+		if doc.gstin not in ["NA", "na"]:
 			p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
 			if not p.match(doc.gstin):
 				frappe.throw(_("Invalid GSTIN or Enter NA for Unregistered"))
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index fc9254b..20685de 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -65,6 +65,10 @@
 });
 
 erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
+	onload: function(doc, dt, dn) {
+		this._super();
+	},
+
 	refresh: function(doc, dt, dn) {
 		var me = this;
 		this._super();
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index fe13432..635e937 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -52,6 +52,7 @@
 		where
 			i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1
 			and i.item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt})
+			and ifnull(i.end_of_life, curdate()) >= curdate()
 			and {condition}
 		limit {start}, {page_length}""".format(start=start,
 			page_length=page_length, lft=lft, rgt=rgt, condition=condition),
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index a6137f9..caa44ac 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -140,7 +140,7 @@
    "remember_last_selected_value": 0,
    "report_hide": 0,
    "reqd": 0,
-   "search_index": 0,
+   "search_index": 1,
    "set_only_once": 1,
    "translatable": 0,
    "unique": 0
@@ -236,7 +236,7 @@
    "remember_last_selected_value": 0,
    "report_hide": 0,
    "reqd": 1,
-   "search_index": 0,
+   "search_index": 1,
    "set_only_once": 0,
    "translatable": 0,
    "unique": 0
@@ -3188,7 +3188,7 @@
    "remember_last_selected_value": 0,
    "report_hide": 0,
    "reqd": 0,
-   "search_index": 1,
+   "search_index": 0,
    "set_only_once": 0,
    "translatable": 0,
    "unique": 0
@@ -3717,7 +3717,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 1,
- "modified": "2018-03-12 03:13:18.516087",
+ "modified": "2018-04-11 12:21:48.715529",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 552d284..7e456dd 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -411,7 +411,7 @@
 		item_supplier = item_doc.get("supplier_items", {"supplier": args.supplier})
 		out.supplier_part_no = item_supplier[0].supplier_part_no if item_supplier else None
 
-def get_pos_profile_item_details(company, args, pos_profile=None):
+def get_pos_profile_item_details(company, args, pos_profile=None, update_data=False):
 	res = frappe._dict()
 
 	if not pos_profile:
@@ -419,7 +419,7 @@
 
 	if pos_profile:
 		for fieldname in ("income_account", "cost_center", "warehouse", "expense_account"):
-			if not args.get(fieldname) and pos_profile.get(fieldname):
+			if (not args.get(fieldname) or update_data) and pos_profile.get(fieldname):
 				res[fieldname] = pos_profile.get(fieldname)
 
 		if res.get("warehouse"):
diff --git a/erpnext/stock/report/stock_balance/stock_balance.js b/erpnext/stock/report/stock_balance/stock_balance.js
index 4aa240d..90945e9 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.js
+++ b/erpnext/stock/report/stock_balance/stock_balance.js
@@ -9,7 +9,7 @@
 			"fieldtype": "Date",
 			"width": "80",
 			"reqd": 1,
-			"default": frappe.sys_defaults.year_start_date,
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
 		},
 		{
 			"fieldname":"to_date",
@@ -31,7 +31,12 @@
 			"label": __("Item"),
 			"fieldtype": "Link",
 			"width": "80",
-			"options": "Item"
+			"options": "Item",
+			"get_query": function() {
+				return {
+					query: "erpnext.controllers.queries.item_query"
+				}
+			}
 		},
 		{
 			"fieldname": "warehouse",
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 7997c37..83e06dc 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -4,7 +4,8 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import flt, cint, getdate
+from frappe.utils import flt, cint, getdate, now
+from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition
 
 from six import iteritems
 
@@ -14,10 +15,11 @@
 	validate_filters(filters)
 
 	columns = get_columns()
-	item_map = get_item_details(filters)
-	item_reorder_detail_map = get_item_reorder_details(filters)
-	iwb_map = get_item_warehouse_map(filters)
-	
+	items = get_items(filters)
+	sle = get_stock_ledger_entries(filters, items)
+	iwb_map = get_item_warehouse_map(filters, sle)
+	item_map = get_item_details(items, sle, filters)
+	item_reorder_detail_map = get_item_reorder_details(item_map.keys())
 
 	data = []
 	for (company, item, warehouse) in sorted(iwb_map):
@@ -90,21 +92,9 @@
 	else:
 		frappe.throw(_("'To Date' is required"))
 
-	if filters.get("item_group"):		
-		ig_details = frappe.db.get_value("Item Group", filters.get("item_group"), 
-			["lft", "rgt"], as_dict=1)
-			
-		if ig_details:
-			conditions += """ 
-				and exists (select name from `tabItem Group` ig 
-				where ig.lft >= %s and ig.rgt <= %s and item.item_group = ig.name)
-			""" % (ig_details.lft, ig_details.rgt)
-		
-	if filters.get("item_code"):
-		conditions += " and sle.item_code = '%s'" % frappe.db.escape(filters.get("item_code"), percent=False)
-
 	if filters.get("warehouse"):
-		warehouse_details = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
+		warehouse_details = frappe.db.get_value("Warehouse",
+			filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
 		if warehouse_details:
 			conditions += " and exists (select name from `tabWarehouse` wh \
 				where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)"%(warehouse_details.lft,
@@ -112,30 +102,29 @@
 
 	return conditions
 
-def get_stock_ledger_entries(filters):
+def get_stock_ledger_entries(filters, items):
+	item_conditions_sql = ''
+	if items:
+		item_conditions_sql = ' and sle.item_code in ({})'\
+			.format(', '.join(['"' + frappe.db.escape(i) + '"' for i in items]))
+
 	conditions = get_conditions(filters)
-	
-	join_table_query = ""
-	if filters.get("item_group"):
-		join_table_query = "inner join `tabItem` item on item.name = sle.item_code"
-	
+
 	return frappe.db.sql("""
 		select
 			sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
 			sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference
 		from
-			`tabStock Ledger Entry` sle force index (posting_sort_index) %s
-		where sle.docstatus < 2 %s 
+			`tabStock Ledger Entry` sle force index (posting_sort_index)
+		where sle.docstatus < 2 %s %s
 		order by sle.posting_date, sle.posting_time, sle.name""" %
-		(join_table_query, conditions), as_dict=1)
+		(item_conditions_sql, conditions), as_dict=1)
 
-def get_item_warehouse_map(filters):
+def get_item_warehouse_map(filters, sle):
 	iwb_map = {}
 	from_date = getdate(filters.get("from_date"))
 	to_date = getdate(filters.get("to_date"))
 
-	sle = get_stock_ledger_entries(filters)
-
 	for d in sle:
 		key = (d.company, d.item_code, d.warehouse)
 		if key not in iwb_map:
@@ -193,20 +182,33 @@
 
 	return iwb_map
 
-def get_item_details(filters):
-	condition = ''
-	value = ()
+def get_items(filters):
+	conditions = []
 	if filters.get("item_code"):
-		condition = "where item_code=%s"
-		value = (filters.get("item_code"),)
+		conditions.append("item.name=%(item_code)s")
+	else:
+		if filters.get("brand"):
+			conditions.append("item.brand=%(brand)s")
+		if filters.get("item_group"):
+			conditions.append(get_item_group_condition(filters.get("item_group")))
 
-	items = frappe.db.sql("""
-		select name, item_name, stock_uom, item_group, brand, description
-		from tabItem
-		{condition}
-	""".format(condition=condition), value, as_dict=1)
+	items = []
+	if conditions:
+		items = frappe.db.sql_list("""select name from `tabItem` item where {}"""
+			.format(" and ".join(conditions)), filters)
+	return items
 
-	item_details = dict((d.name , d) for d in items)
+def get_item_details(items, sle, filters):
+	item_details = {}
+	if not items:
+		items = list(set([d.item_code for d in sle]))
+
+	for item in frappe.db.sql("""
+		select name, item_name, description, item_group, brand, stock_uom
+		from `tabItem`
+		where name in ({0})
+		""".format(', '.join(['"' + frappe.db.escape(i) + '"' for i in items])), as_dict=1):
+			item_details.setdefault(item.name, item)
 
 	if filters.get('show_variant_attributes', 0) == 1:
 		variant_values = get_variant_values_for(item_details.keys())
@@ -214,18 +216,12 @@
 
 	return item_details
 
-def get_item_reorder_details(filters):
-	condition = ''
-	value = ()
-	if filters.get("item_code"):
-		condition = "where parent=%s"
-		value = (filters.get("item_code"),)
-
+def get_item_reorder_details(items):
 	item_reorder_details = frappe.db.sql("""
 		select parent, warehouse, warehouse_reorder_qty, warehouse_reorder_level
 		from `tabItem Reorder`
-		{condition}
-	""".format(condition=condition), value, as_dict=1)
+		where parent in ({0})
+	""".format(', '.join(['"' + frappe.db.escape(i) + '"' for i in items])), as_dict=1)
 
 	return dict((d.parent + d.warehouse, d) for d in item_reorder_details)
 
@@ -235,12 +231,10 @@
 		if sle_count > 500000:
 			frappe.throw(_("Please set filter based on Item or Warehouse"))
 
-
 def get_variants_attributes():
 	'''Return all item variant attributes.'''
 	return [i.name for i in frappe.get_all('Item Attribute')]
 
-
 def get_variant_values_for(items):
 	'''Returns variant values for items.'''
 	attribute_map = {}
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index d4f5ab5..660357c 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -35,7 +35,12 @@
 			"fieldname":"item_code",
 			"label": __("Item"),
 			"fieldtype": "Link",
-			"options": "Item"
+			"options": "Item",
+			"get_query": function() {
+				return {
+					query: "erpnext.controllers.queries.item_query"
+				}
+			}
 		},
 		{
 			"fieldname":"item_group",
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index ef198f0..c9286a3 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -7,13 +7,12 @@
 
 def execute(filters=None):
 	columns = get_columns()
-	item_conditions = get_item_conditions(filters)
-	item_details = get_item_details(filters, item_conditions)
-	sl_entries = get_stock_ledger_entries(filters, item_conditions, item_details)
+	items = get_items(filters)
+	sl_entries = get_stock_ledger_entries(filters, items)
+	item_details = get_item_details(items, sl_entries)
 	opening_row = get_opening_balance(filters, columns)
 
 	data = []
-
 	if opening_row:
 		data.append(opening_row)
 
@@ -53,12 +52,12 @@
 
 	return columns
 
-def get_stock_ledger_entries(filters, item_conditions, item_details):
+def get_stock_ledger_entries(filters, items):
 	item_conditions_sql = ''
-	if item_conditions:
-		items = ['"' + frappe.db.escape(i) + '"' for i in item_details.keys()]
-		if items:
-			item_conditions_sql = 'and sle.item_code in ({})'.format(', '.join(items))
+	if items:
+		item_conditions_sql = 'and sle.item_code in ({})'\
+			.format(', '.join(['"' + frappe.db.escape(i) + '"' for i in items]))
+
 	return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
 			item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
 			stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project
@@ -73,25 +72,35 @@
 			item_conditions_sql = item_conditions_sql
 		), filters, as_dict=1)
 
-def get_item_details(filters, item_conditions):
-	item_details = {}
-	for item in frappe.db.sql("""select name, item_name, description, item_group,
-			brand, stock_uom from `tabItem` item {item_conditions}"""\
-			.format(item_conditions=item_conditions), filters, as_dict=1):
-		item_details.setdefault(item.name, item)
-
-	return item_details
-
-def get_item_conditions(filters):
+def get_items(filters):
 	conditions = []
 	if filters.get("item_code"):
 		conditions.append("item.name=%(item_code)s")
-	if filters.get("brand"):
-		conditions.append("item.brand=%(brand)s")
-	if filters.get("item_group"):
-		conditions.append(get_item_group_condition(filters.get("item_group")))
+	else:
+		if filters.get("brand"):
+			conditions.append("item.brand=%(brand)s")
+		if filters.get("item_group"):
+			conditions.append(get_item_group_condition(filters.get("item_group")))
 
-	return "where {}".format(" and ".join(conditions)) if conditions else ""
+	items = []
+	if conditions:
+		items = frappe.db.sql_list("""select name from `tabItem` item where {}"""
+			.format(" and ".join(conditions)), filters)
+	return items
+
+def get_item_details(items, sl_entries):
+	item_details = {}
+	if not items:
+		items = list(set([d.item_code for d in sl_entries]))
+
+	for item in frappe.db.sql("""
+		select name, item_name, description, item_group, brand, stock_uom
+		from `tabItem`
+		where name in ({0})
+		""".format(', '.join(['"' + frappe.db.escape(i) + '"' for i in items])), as_dict=1):
+			item_details.setdefault(item.name, item)
+
+	return item_details
 
 def get_sle_conditions(filters):
 	conditions = []
diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js
index 2dbbc5b..937c0a2 100644
--- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js
+++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.js
@@ -19,7 +19,12 @@
 			"fieldname":"item_code",
 			"label": __("Item"),
 			"fieldtype": "Link",
-			"options": "Item"
+			"options": "Item",
+			"get_query": function() {
+				return {
+					query: "erpnext.controllers.queries.item_query"
+				}
+			}
 		},
 		{
 			"fieldname":"brand",