Merge pull request #23141 from deepeshgarg007/sle_cancel_v13_beta

fix: Reverse SLE not created for fraction qty or qty less than 1
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 18294f3..9f65825 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__ = '13.0.0-beta.3'
+__version__ = '13.0.0-beta.4'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index c6de641..164f120 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -244,6 +244,8 @@
 
 		super(Account, self).on_trash(True)
 
+@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""select name from tabAccount
 		where is_group = 1 and docstatus != 2 and company = %s
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index cfdae93..dda1708 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -841,13 +841,33 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
-	return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
-		from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
-		where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
-		and (jv_detail.reference_type is null or jv_detail.reference_type = '')
-		and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(searchfield),
-		(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
+	if not frappe.db.has_column('Journal Entry', searchfield):
+		return []
+
+	return frappe.db.sql("""
+		SELECT jv.name, jv.posting_date, jv.user_remark
+		FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
+		WHERE jv_detail.parent = jv.name
+			AND jv_detail.account = %(account)s
+			AND IFNULL(jv_detail.party, '') = %(party)s
+			AND (
+				jv_detail.reference_type IS NULL
+				OR jv_detail.reference_type = ''
+			)
+			AND jv.docstatus = 1
+			AND jv.`{0}` LIKE %(txt)s
+		ORDER BY jv.name DESC
+		LIMIT %(offset)s, %(limit)s
+		""".format(searchfield), dict(
+				account=filters.get("account"),
+				party=cstr(filters.get("party")),
+				txt="%{0}%".format(txt),
+				offset=start,
+				limit=page_len
+			)
+		)
 
 
 @frappe.whitelist()
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py
index 4702e58..e5880aa 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/payment_order.py
@@ -27,6 +27,7 @@
 			frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
 		where parent = %(parent)s and mode_of_payment like %(txt)s
@@ -38,6 +39,7 @@
 		})
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
 		where parent = %(parent)s and supplier like %(txt)s and
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
index 8eb0a22..9899219 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -24,7 +24,7 @@
 		if user:
 			frappe.throw(_("POS Closing Entry {} against {} between selected period"
 				.format(frappe.bold("already exists"), frappe.bold(self.user))), title=_("Invalid Period"))
-		
+
 		if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
 			frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
 
@@ -41,6 +41,7 @@
 			{"data": self, "currency": currency})
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
 	cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'])
 	return [c['user'] for c in cashiers_list]
@@ -48,12 +49,12 @@
 @frappe.whitelist()
 def get_pos_invoices(start, end, user):
 	data = frappe.db.sql("""
-	select 
+	select
 		name, timestamp(posting_date, posting_time) as "timestamp"
-	from 
+	from
 		`tabPOS Invoice`
-	where 
-		owner = %s and docstatus = 1 and 
+	where
+		owner = %s and docstatus = 1 and
 		(consolidated_invoice is NULL or consolidated_invoice = '')
 	""", (user), as_dict=1)
 
@@ -101,7 +102,7 @@
 		for t in d.taxes:
 			existing_tax = [tx for tx in taxes if tx.account_head == t.account_head and tx.rate == t.rate]
 			if existing_tax:
-				existing_tax[0].amount += flt(t.tax_amount); 
+				existing_tax[0].amount += flt(t.tax_amount);
 			else:
 				taxes.append(frappe._dict({
 					'account_head': t.account_head,
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index ef431d7..8ec6a53 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -31,8 +31,7 @@
 		frm.set_query("print_format", function() {
 			return {
 				filters: [
-					['Print Format', 'doc_type', '=', 'Sales Invoice'],
-					['Print Format', 'print_format_type', '=', 'Jinja'],
+					['Print Format', 'doc_type', '=', 'POS Invoice']
 				]
 			};
 		});
@@ -45,10 +44,6 @@
 			};
 		});
 
-		frm.set_query("print_format", function() {
-			return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} };
-		});
-
 		frm.set_query('company_address', function(doc) {
 			if(!doc.company) {
 				frappe.throw(__('Please set Company'));
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 8655b4b..789b4c3 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -105,6 +105,7 @@
 	return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
 	user = frappe.session['user']
 	company = filters.get('company') or frappe.defaults.get_user_default('company')
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index d90ae28..cff7d5b 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -433,14 +433,14 @@
 	return doc
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
 	items = [filters.get('value')]
 	if filters.get('apply_on') != 'Item Code':
 		field = frappe.scrub(filters.get('apply_on'))
+		items = [d.name for d in frappe.db.get_all("Item", filters={field: filters.get('value')})]
 
-		items = frappe.db.sql_list("""select name
-			from `tabItem` where {0} = %s""".format(field), filters.get('value'))
-
-	return frappe.get_all('UOM Conversion Detail',
-		filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
-		fields = ["distinct uom"], as_list=1)
+	return frappe.get_all('UOM Conversion Detail', filters={
+			'parent': ('in', items),
+			'uom': ("like", "{0}%".format(txt))
+		}, fields = ["distinct uom"], as_list=1)
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
index 0e9c808..d825c6f 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
@@ -8,7 +8,7 @@
 		'fieldname': 'taxes_and_charges',
 		'non_standard_fieldnames': {
 			'Tax Rule': 'sales_tax_template',
-			'Subscription': 'tax_template',
+			'Subscription': 'sales_tax_template',
 			'Restaurant': 'default_tax_template'
 		},
 		'transactions': [
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 7df090b..ce6baa6 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -290,6 +290,7 @@
 		return []
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
 	account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
 	if not account:
@@ -319,6 +320,7 @@
 	)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
 	account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
 
@@ -355,6 +357,7 @@
 	)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""
 		SELECT
diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
index 1869a29..60c528b 100644
--- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
@@ -106,6 +106,7 @@
 		maintenance_log.save()
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_team_members(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.get_values('Maintenance Team Member', { 'parent': filters.get("maintenance_team") })
 
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
index f169f01..148357f 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
@@ -41,6 +41,7 @@
 		asset_maintenance_doc.save()
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters):
 	asset_maintenance_tasks = frappe.db.get_values('Asset Maintenance Task', {'parent':filters.get("asset_maintenance")}, 'maintenance_task')
 	return asset_maintenance_tasks
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 25065ab..9f2b971 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -94,7 +94,7 @@
 				if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
 					this.frm.add_custom_button(__('Update Items'), () => {
 						erpnext.utils.update_child_items({
-							frm: frm,
+							frm: this.frm,
 							child_docname: "items",
 							child_doctype: "Purchase Order Detail",
 							cannot_add_row: false,
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 4b85230..b54a585 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -207,6 +207,7 @@
 	return list_context
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
 		where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 5c59fe0..babc5bd 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -12,6 +12,7 @@
 
 # searches for active employees
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def employee_query(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	fields = get_fields("Employee", ["name", "employee_name"])
@@ -42,6 +43,7 @@
 
 # searches for leads which are not converted
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def lead_query(doctype, txt, searchfield, start, page_len, filters):
 	fields = get_fields("Lead", ["name", "lead_name", "company_name"])
 
@@ -72,6 +74,7 @@
 
  # searches for customer
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def customer_query(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	cust_master_name = frappe.defaults.get_user_default("cust_master_name")
@@ -110,8 +113,10 @@
 
 # searches for supplier
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	supp_master_name = frappe.defaults.get_user_default("supp_master_name")
+
 	if supp_master_name == "Supplier Name":
 		fields = ["name", "supplier_group"]
 	else:
@@ -142,32 +147,49 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
 	company_currency = erpnext.get_company_currency(filters.get('company'))
 
-	tax_accounts = frappe.db.sql("""select name, parent_account	from tabAccount
-		where tabAccount.docstatus!=2
-			and account_type in (%s)
-			and is_group = 0
-			and company = %s
-			and account_currency = %s
-			and `%s` LIKE %s
-		order by idx desc, name
-		limit %s, %s""" %
-		(", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
-		tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
-			start, page_len]))
+	def get_accounts(with_account_type_filter):
+		account_type_condition = ''
+		if with_account_type_filter:
+			account_type_condition = "AND account_type in %(account_types)s"
+
+		accounts = frappe.db.sql("""
+			SELECT name, parent_account
+			FROM `tabAccount`
+			WHERE `tabAccount`.docstatus!=2
+				{account_type_condition}
+				AND is_group = 0
+				AND company = %(company)s
+				AND account_currency = %(currency)s
+				AND `{searchfield}` LIKE %(txt)s
+			ORDER BY idx DESC, name
+			LIMIT %(offset)s, %(limit)s
+		""".format(account_type_condition=account_type_condition, searchfield=searchfield),
+			dict(
+				account_types=filters.get("account_type"),
+				company=filters.get("company"),
+				currency=company_currency,
+				txt="%{}%".format(txt),
+				offset=start,
+				limit=page_len
+			)
+		)
+
+		return accounts
+
+	tax_accounts = get_accounts(True)
+
 	if not tax_accounts:
-		tax_accounts = frappe.db.sql("""select name, parent_account	from tabAccount
-			where tabAccount.docstatus!=2 and is_group = 0
-				and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
-			% ("%s", "%s", searchfield, "%s", "%s", "%s"),
-			(filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
+		tax_accounts = get_accounts(False)
 
 	return tax_accounts
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
 	conditions = []
 
@@ -215,7 +237,6 @@
 			idx desc,
 			name, item_name
 		limit %(start)s, %(page_len)s """.format(
-			key=searchfield,
 			columns=columns,
 			scond=searchfields,
 			fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
@@ -231,6 +252,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def bom(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	fields = get_fields("BOM", ["name", "item"])
@@ -258,6 +280,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_project_name(doctype, txt, searchfield, start, page_len, filters):
 	cond = ''
 	if filters.get('customer'):
@@ -285,6 +308,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
 	fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
 
@@ -315,6 +339,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
 	cond = ""
 	if filters.get("posting_date"):
@@ -373,6 +398,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_account_list(doctype, txt, searchfield, start, page_len, filters):
 	filter_list = []
 
@@ -395,21 +421,8 @@
 		fields = ["name", "parent_account"],
 		limit_start=start, limit_page_length=page_len, as_list=True)
 
-def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
-	return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
-		from `tabBlanket Order` bo, `tabBlanket Order Item` boi
-		where
-			boi.parent = bo.name
-			and boi.item_code = {item_code}
-			and bo.blanket_order_type = '{blanket_order_type}'
-			and bo.company = {company}
-			and bo.docstatus = 1"""
-		.format(item_code = frappe.db.escape(filters.get("item")),
-			blanket_order_type = filters.get("blanket_order_type"),
-			company = frappe.db.escape(filters.get("company"))
-		))
-
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
 		from `tabBlanket Order` bo, `tabBlanket Order Item` boi
@@ -426,6 +439,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_income_account(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 
@@ -452,6 +466,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 
@@ -476,6 +491,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
 	# Should be used when item code is passed in filters.
 	conditions, bin_conditions = [], []
@@ -519,6 +535,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
 	query = """select batch_id from `tabBatch`
 			where disabled = 0
@@ -532,6 +549,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
 	item_filters = [
 		['manufacturer', 'like', '%' + txt + '%'],
@@ -550,6 +568,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
 	query = """
 		select pr.name
@@ -564,6 +583,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
 	query = """
 		select pi.name
@@ -578,6 +598,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
 
 	item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 7536172..3e27670 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -97,6 +97,7 @@
 		return quiz_progress
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
 	if filters.get('program'):
 		return frappe.db.sql("""select course, course_name from `tabProgram Course`
@@ -115,6 +116,7 @@
 				})
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_students(doctype, txt, searchfield, start, page_len, filters):
 	if not filters.get("academic_term"):
 		filters["academic_term"] = frappe.defaults.get_defaults().academic_term
diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py
index 8b61c89..0260b80 100644
--- a/erpnext/education/doctype/student_group/student_group.py
+++ b/erpnext/education/doctype/student_group/student_group.py
@@ -108,6 +108,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def fetch_students(doctype, txt, searchfield, start, page_len, filters):
 	if filters.get("group_based_on") != "Activity":
 		enrolled_students = get_program_enrollment(filters.get('academic_year'), filters.get('academic_term'),
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
index 3dc7c1e..5da5a06 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
@@ -71,6 +71,7 @@
 		frappe.throw(_(msg))
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
 	fields = ['name', 'practitioner_name', 'mobile_phone']
 
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
index cf63b65..b4a4e29 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
@@ -217,6 +217,7 @@
 	inpatient_record.save(ignore_permissions = True)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_leave_from(doctype, txt, searchfield, start, page_len, filters):
 	docname = filters['docname']
 
diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py
index d4c118f..afd54b8 100644
--- a/erpnext/hr/doctype/department_approver/department_approver.py
+++ b/erpnext/hr/doctype/department_approver/department_approver.py
@@ -11,6 +11,7 @@
 	pass
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_approvers(doctype, txt, searchfield, start, page_len, filters):
 
 	if not filters.get("employee"):
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 8062342..c51f655 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -911,6 +911,7 @@
 	return out
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_query(doctype, txt, searchfield, start, page_len, filters):
 	meta = frappe.get_meta("Item", cached=True)
 	searchfields = meta.get_search_fields()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index f962a11..b7d968e 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -632,6 +632,7 @@
 		return bom
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_bom_operations(doctype, txt, searchfield, start, page_len, filters):
 	if txt:
 		filters['operation'] = ('like', '%%%s%%' % txt)
diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
index e3e440e..dc424b7 100644
--- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
+++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
@@ -30,7 +30,7 @@
 				"width": 180
 			}
 		])
-	
+
 	columns.extend([
 		{
 			"label": _("Finished Good"),
@@ -73,7 +73,7 @@
 	])
 
 	return columns
-	
+
 def get_data(filters):
 	cond = "1=1"
 
@@ -95,6 +95,7 @@
 	return results
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_work_orders(doctype, txt, searchfield, start, page_len, filters):
 	cond = "1=1"
 	if filters.get('bom_no'):
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
index 5ac3923..ebc01c6 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
@@ -369,6 +369,3 @@
 			"fieldtype": "Float",
 			"width": 140
 		}])
-
-def document_query(doctype, txt, searchfield, start, page_len, filters):
-	pass
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index d7d00e6..ef844fb 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -223,6 +223,7 @@
 	return benefit_amount
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
 	if len(filters) < 2:
 		return {}
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index ad9b6d8..554484f 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -540,6 +540,7 @@
 		frappe.msgprint(_("Could not submit some Salary Slips"))
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""
 		select name from `tabPayroll Entry`
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index f8af30a..9eef16b 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -239,7 +239,8 @@
 	if exact_match:
 		data = get_product_info_for_website(exact_match[0])
 		product_info = data.product_info
-		product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
+		if product_info:
+			product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
 		if not data.cart_settings.show_price:
 			product_info = None
 	else:
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 6350f86..5bbd29c 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -239,6 +239,7 @@
 	}
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index cf2fd26..fb84094 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -193,6 +193,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_project(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 	return frappe.db.sql(""" select name from `tabProject`
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index 7fe22be..9e807f7 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -214,6 +214,7 @@
 			and sales_invoice is null""".format(cond), {'project': project, 'parent': parent}, as_dict=1)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_timesheet(doctype, txt, searchfield, start, page_len, filters):
 	if not filters: filters = {}
 
diff --git a/erpnext/projects/utils.py b/erpnext/projects/utils.py
index d0d88eb..c39f908 100644
--- a/erpnext/projects/utils.py
+++ b/erpnext/projects/utils.py
@@ -7,6 +7,7 @@
 import frappe
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def query_task(doctype, txt, searchfield, start, page_len, filters):
 	from frappe.desk.reportview import build_match_conditions
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index fe7e0c8..82427da 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -673,6 +673,9 @@
 	if country != 'India':
 		return
 
+	if not doc.total_taxes_and_charges:
+		return
+
 	if doc.reverse_charge == 'Y':
 		gst_accounts = get_gst_accounts(doc.company)
 		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
@@ -713,7 +716,10 @@
 	country = frappe.get_cached_value('Company', doc.company, 'country')
 
 	if country != 'India':
-		return
+		return gl_entries
+
+	if not doc.total_taxes_and_charges:
+		return gl_entries
 
 	if doc.reverse_charge == 'Y':
 		gst_accounts = get_gst_accounts(doc.company)
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index e614acd..ca62488 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -340,6 +340,7 @@
 	return lp_details
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
 	from erpnext.controllers.queries import get_fields
 	fields = ["name", "customer_name", "customer_group", "territory"]
@@ -542,6 +543,7 @@
 	return address
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
 	customer = filters.get('customer')
 	return frappe.db.sql("""
diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py
index 22e30e3..09e474d 100644
--- a/erpnext/selling/doctype/customer/customer_dashboard.py
+++ b/erpnext/selling/doctype/customer/customer_dashboard.py
@@ -12,7 +12,8 @@
 			'Payment Entry': 'party',
 			'Quotation': 'party_name',
 			'Opportunity': 'party_name',
-			'Bank Account': 'party'
+			'Bank Account': 'party',
+			'Subscription': 'party'
 		},
 		'dynamic_links': {
 			'party_name': ['Customer', 'quotation_to']
diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py
index 0c85a1b..d3281f7 100644
--- a/erpnext/selling/doctype/product_bundle/product_bundle.py
+++ b/erpnext/selling/doctype/product_bundle/product_bundle.py
@@ -29,6 +29,7 @@
 				frappe.throw(_("Row #{0}: Child Item should not be a Product Bundle. Please remove Item {1} and Save").format(item.idx, frappe.bold(item.item_code)))
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index ffb6635..f882898 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -888,6 +888,7 @@
 
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_supplier(doctype, txt, searchfield, start, page_len, filters):
 	supp_master_name = frappe.defaults.get_user_default("supp_master_name")
 	if supp_master_name == "Supplier Name":
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 f7b7ed8..83bd71d 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -14,10 +14,9 @@
 def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None):
 	data = dict()
 	warehouse = ""
-	display_items_in_stock = 0
 
 	if pos_profile:
-		warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock'])
+		warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse'])
 
 	if not frappe.db.exists('Item Group', item_group):
 		item_group = get_root_of('Item Group')
@@ -85,7 +84,7 @@
 			item_price = item_prices.get(item_code) or {}
 			item_stock_qty = get_stock_availability(item_code, warehouse)
 
-			if display_items_in_stock and not item_stock_qty:
+			if not item_stock_qty:
 				pass
 			else:
 				row = {}
@@ -160,6 +159,7 @@
 	return cond % tuple(item_groups)
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_group_query(doctype, txt, searchfield, start, page_len, filters):
 	item_groups = []
 	cond = "1=1"
@@ -179,12 +179,12 @@
 
 @frappe.whitelist()
 def check_opening_entry(user):
-	open_vouchers = frappe.db.get_all("POS Opening Entry", 
-		filters = { 
-			"user": user, 
+	open_vouchers = frappe.db.get_all("POS Opening Entry",
+		filters = {
+			"user": user,
 			"pos_closing_entry": ["in", ["", None]],
 			"docstatus": 1
-		}, 
+		},
 		fields = ["name", "company", "pos_profile", "period_start_date"],
 		order_by = "period_start_date desc"
 	)
@@ -229,7 +229,7 @@
 		invoice_list = frappe.db.get_all('POS Invoice', filters={
 			'status': status
 		}, fields=fields)
-	
+
 	return invoice_list
 
 @frappe.whitelist()
@@ -244,7 +244,7 @@
 		if fieldname == 'email_id':
 			contact_doc.set('email_ids', [{ 'email_id': value, 'is_primary': 1}])
 			frappe.db.set_value('Customer', customer, 'email_id', value)
-		elif fieldname == 'mobile_no': 
+		elif fieldname == 'mobile_no':
 			contact_doc.set('phone_nos', [{ 'phone': value, 'is_primary_mobile_no': 1}])
 			frappe.db.set_value('Customer', customer, 'mobile_no', value)
 		contact_doc.save()
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 483ef78..ae5471b 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -35,7 +35,8 @@
 	create_opening_voucher() {
 		const table_fields = [
 			{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 },
-			{ fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 }
+			{ fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount", 
+				options: "company:company_currency", reqd: 1 }
 		];
 
 		const dialog = new frappe.ui.Dialog({
@@ -66,7 +67,7 @@
 							frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => {
 								dialog.fields_dict.balance_details.df.data = [];
 								payment_reconciliation.forEach(pay => {
-									const { mode_of_payment, closing_amount } = pay;
+									const { mode_of_payment } = pay;
 									dialog.fields_dict.balance_details.df.data.push({
 										mode_of_payment: mode_of_payment
 									});
@@ -152,7 +153,7 @@
 			},
 			() => this.make_new_invoice(),
 			() => frappe.dom.unfreeze(),
-			() => this.page.set_title(__('Point of Sale Beta')),
+			() => this.page.set_title(__('Point of Sale')),
 		]);
 	}
 
diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py
index b29c305..96e6093 100644
--- a/erpnext/setup/doctype/party_type/party_type.py
+++ b/erpnext/setup/doctype/party_type/party_type.py
@@ -10,6 +10,7 @@
 	pass
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_party_type(doctype, txt, searchfield, start, page_len, filters):
 	cond = ''
 	if filters and filters.get('account'):
diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py
index 522dfc6..190cb62 100644
--- a/erpnext/stock/doctype/item_alternative/item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/item_alternative.py
@@ -43,6 +43,7 @@
 			frappe.throw(_("Already record exists for the item {0}").format(self.item_code))
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_alternative_items(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" (select alternative_item_code from `tabItem Alternative`
 			where item_code = %(item_code)s and alternative_item_code like %(txt)s)
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 25f1ed9..335175f 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -370,6 +370,7 @@
 	return supplier_items
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, page_len, filters):
 	conditions = ""
 	if txt:
@@ -403,6 +404,7 @@
 	return material_requests
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	doc = frappe.get_doc("Material Request", filters.get("doc"))
 	item_list = []
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index 4f831d7..a7a29cc 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -176,6 +176,7 @@
 		self.update_item_details()
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_details(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 	return frappe.db.sql("""select name, item_name, description from `tabItem`
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index 568e742..c3bb514 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -59,6 +59,7 @@
 				(quality_inspection, self.modified, self.reference_name, self.item_code))
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def item_query(doctype, txt, searchfield, start, page_len, filters):
 	if filters.get("from"):
 		from frappe.desk.reportview import get_match_cond
@@ -88,6 +89,7 @@
 			{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
 
 @frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
 def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.get_all('Quality Inspection',
 		limit_start=start,
diff --git a/erpnext/templates/generators/item/item_configure.js b/erpnext/templates/generators/item/item_configure.js
index 163c955..5fd9011 100644
--- a/erpnext/templates/generators/item/item_configure.js
+++ b/erpnext/templates/generators/item/item_configure.js
@@ -193,17 +193,14 @@
 			filtered_items_count === 1 ?
 				filtered_items[0] : '';
 
-		// Allow Add to Cart if adding out of stock items enabled in Shopping Cart else check stock.
-		const in_stock = product_info.allow_items_not_in_stock ? 1 : product_info.in_stock;
-		const add_to_cart = `<a href data-action="btn_add_to_cart" data-item-code="${one_item}">${__('Add to cart')}</a>`;
-		const product_action =  in_stock ? add_to_cart : `<a style="color:#74808b;">${__('Not in Stock')}</a>`;
-
 		const item_add_to_cart = one_item ? `
 			<div class="alert alert-success d-flex justify-content-between align-items-center" role="alert">
 				<div>
 					<div>${one_item} ${product_info && product_info.price ? '(' + product_info.price.formatted_price_sales_uom + ')' : ''}</div>
 				</div>
-				${product_action}
+				<a href data-action="btn_add_to_cart" data-item-code="${one_item}">
+					${__('Add to cart')}
+				</a>
 			</div>
 		`: '';