Merge branch 'develop' into mergify/bp/develop/pr-30385
diff --git a/README.md b/README.md
index 9609353..c26660c 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
     </p>
 
 [![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml/badge.svg?branch=develop)](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
+[![UI](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml/badge.svg?branch=develop&event=schedule)](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
 [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
 [![codecov](https://codecov.io/gh/frappe/erpnext/branch/develop/graph/badge.svg?token=0TwvyUg3I5)](https://codecov.io/gh/frappe/erpnext)
 [![docker pulls](https://img.shields.io/docker/pulls/frappe/erpnext-worker.svg)](https://hub.docker.com/r/frappe/erpnext-worker)
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index a3ef384..8ae90ce 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -160,7 +160,7 @@
 			let root_company = treeview.page.fields_dict.root_company.get_value();
 
 			if(root_company) {
-				frappe.throw(__("Please add the account to root level Company - ") + root_company);
+				frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
 			} else {
 				treeview.new_node();
 			}
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
index 990d6d9..a964965 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
@@ -200,7 +200,7 @@
 				})
 				.then((result) => {
 					if (result.length > 0) {
-						frm.add_custom_button("Report Error", () => {
+						frm.add_custom_button(__("Report Error"), () => {
 							let fake_xhr = {
 								responseText: JSON.stringify({
 									exc: result[0].error,
diff --git a/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py b/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py
index 3bce4d5..402469f 100644
--- a/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py
+++ b/erpnext/accounts/doctype/cash_flow_mapping/cash_flow_mapping.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 from frappe.model.document import Document
 
 
@@ -16,6 +17,6 @@
 		]
 		if len(checked_fields) > 1:
 			frappe.throw(
-				frappe._("You can only select a maximum of one option from the list of check boxes."),
-				title="Error",
+				_("You can only select a maximum of one option from the list of check boxes."),
+				title=_("Error"),
 			)
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
index 04a8e8e..edea37d 100644
--- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
@@ -68,9 +68,8 @@
 					str(key.key).format(transaction_date=nowdate(), to_currency="INR", from_currency="USD")
 				]
 		except Exception:
-			frappe.throw("Invalid result key. Response: " + response.text)
+			frappe.throw(_("Invalid result key. Response:") + " " + response.text)
 		if not isinstance(value, (int, float)):
 			frappe.throw(_("Returned exchange rate is neither integer not float."))
 
 		self.url = response.url
-		frappe.msgprint("Exchange rate of USD to INR is " + str(value))
diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
index d037302..ed35d1e 100644
--- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
+++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
@@ -42,12 +42,7 @@
 			pos_profiles = list(map(lambda x: x[0], pos_profiles))
 
 			if pos_profiles:
-				message = (
-					"POS Profile "
-					+ frappe.bold(", ".join(pos_profiles))
-					+ " contains \
-					Mode of Payment "
-					+ frappe.bold(str(self.name))
-					+ ". Please remove them to disable this mode."
-				)
-				frappe.throw(_(message), title="Not Allowed")
+				message = _(
+					"POS Profile {} contains Mode of Payment {}. Please remove them to disable this mode."
+				).format(frappe.bold(", ".join(pos_profiles)), frappe.bold(str(self.name)))
+				frappe.throw(message, title=_("Not Allowed"))
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 65fd4af..e83dc0f 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -61,13 +61,13 @@
 
 		if len(item_groups) != len(set(item_groups)):
 			frappe.throw(
-				_("Duplicate item group found in the item group table"), title="Duplicate Item Group"
+				_("Duplicate item group found in the item group table"), title=_("Duplicate Item Group")
 			)
 
 		if len(customer_groups) != len(set(customer_groups)):
 			frappe.throw(
 				_("Duplicate customer group found in the cutomer group table"),
-				title="Duplicate Customer Group",
+				title=_("Duplicate Customer Group"),
 			)
 
 	def validate_payment_methods(self):
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
index 29f2e98..7dd77fb 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
@@ -8,7 +8,7 @@
 	},
 	refresh: function(frm){
 		if(!frm.doc.__islocal) {
-			frm.add_custom_button('Send Emails',function(){
+			frm.add_custom_button(__('Send Emails'), function(){
 				frappe.call({
 					method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails",
 					args: {
@@ -24,7 +24,7 @@
 					}
 				});
 			});
-			frm.add_custom_button('Download',function(){
+			frm.add_custom_button(__('Download'), function(){
 				var url = frappe.urllib.get_full_url(
 					'/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?'
 					+ 'document_name='+encodeURIComponent(frm.doc.name))
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 5f6e610..ee29d2a 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -141,7 +141,7 @@
 				})
 			}, __("Get Items From"));
 		}
-		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
+		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted);
 
 		if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
 			frappe.model.with_doc("Supplier", me.frm.doc.supplier, function() {
@@ -571,10 +571,10 @@
 	},
 
 	is_subcontracted: function(frm) {
-		if (frm.doc.is_subcontracted === "Yes") {
+		if (frm.doc.is_subcontracted) {
 			erpnext.buying.get_default_bom(frm);
 		}
-		frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
+		frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted);
 	},
 
 	update_stock: function(frm) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index bd01164..9f87c5a 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -543,11 +543,10 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "No",
+   "default": "0",
    "fieldname": "is_subcontracted",
-   "fieldtype": "Select",
-   "label": "Raw Materials Supplied",
-   "options": "No\nYes",
+   "fieldtype": "Check",
+   "label": "Is Subcontracted",
    "print_hide": 1
   },
   {
@@ -1366,7 +1365,7 @@
    "width": "50px"
   },
   {
-   "depends_on": "eval:doc.update_stock && doc.is_subcontracted==\"Yes\"",
+   "depends_on": "eval:doc.update_stock && doc.is_subcontracted",
    "fieldname": "supplier_warehouse",
    "fieldtype": "Link",
    "label": "Supplier Warehouse",
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 843f66d..73390dd 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -901,7 +901,7 @@
 		)
 
 		pi = make_purchase_invoice(
-			item_code="_Test FG Item", qty=10, rate=500, update_stock=1, is_subcontracted="Yes"
+			item_code="_Test FG Item", qty=10, rate=500, update_stock=1, is_subcontracted=1
 		)
 
 		self.assertEqual(len(pi.get("supplied_items")), 2)
@@ -1611,7 +1611,7 @@
 	pi.conversion_rate = args.conversion_rate or 1
 	pi.is_return = args.is_return
 	pi.return_against = args.return_against
-	pi.is_subcontracted = args.is_subcontracted or "No"
+	pi.is_subcontracted = args.is_subcontracted or 0
 	pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
 	pi.cost_center = args.parent_cost_center
 
@@ -1674,7 +1674,7 @@
 	pi.is_return = args.is_return
 	pi.is_return = args.is_return
 	pi.credit_to = args.return_against or "Creditors - _TC"
-	pi.is_subcontracted = args.is_subcontracted or "No"
+	pi.is_subcontracted = args.is_subcontracted or 0
 	if args.supplier_warehouse:
 		pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
 
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index f9b2efd..6651195 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -623,7 +623,7 @@
   },
   {
    "default": "0",
-   "depends_on": "eval:parent.is_subcontracted == 'Yes'",
+   "depends_on": "eval:parent.is_subcontracted",
    "fieldname": "include_exploded_items",
    "fieldtype": "Check",
    "label": "Include Exploded Items",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 7d98c22..1efd3dc 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1412,7 +1412,7 @@
 					)
 				)
 			else:
-				frappe.throw(_("Select change amount account"), title="Mandatory Field")
+				frappe.throw(_("Select change amount account"), title=_("Mandatory Field"))
 
 	def make_write_off_gl_entry(self, gl_entries):
 		# write off entries, applicable if only pos
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 35c2f84..a519d8b 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -34,7 +34,9 @@
 
 	def validate_thresholds(self):
 		for d in self.get("rates"):
-			if d.cumulative_threshold and d.cumulative_threshold < d.single_threshold:
+			if (
+				d.cumulative_threshold and d.single_threshold and d.cumulative_threshold < d.single_threshold
+			):
 				frappe.throw(
 					_("Row #{0}: Cumulative threshold cannot be less than Single Transaction threshold").format(
 						d.idx
diff --git a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
index e658049..605ce83 100644
--- a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
+++ b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html
@@ -1,7 +1,8 @@
 {%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%}
-{%- set einvoice = json.loads(doc.signed_einvoice) -%}
 
 <div class="page-break">
+	{% if doc.signed_einvoice %}
+	{%- set einvoice = json.loads(doc.signed_einvoice) -%}
 	<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
 		{% if letter_head and not no_letterhead %}
 			<div class="letter-head">{{ letter_head }}</div>
@@ -170,4 +171,10 @@
 			</tbody>
 		</table>
 	</div>
+	{% else %}
+	<div class="text-center" style="color: var(--gray-500); font-size: 14px;">
+		You must generate IRN before you can preview GST E-Invoice.
+	</div>
+	{% endif %}
 </div>
+
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index 7b1e979..07552e3 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -201,17 +201,17 @@
 			net_provisional_profit_loss += provisional_profit_loss.get(key)
 
 	return [
-		{"value": net_asset, "label": "Total Asset", "datatype": "Currency", "currency": currency},
+		{"value": net_asset, "label": _("Total Asset"), "datatype": "Currency", "currency": currency},
 		{
 			"value": net_liability,
-			"label": "Total Liability",
+			"label": _("Total Liability"),
 			"datatype": "Currency",
 			"currency": currency,
 		},
-		{"value": net_equity, "label": "Total Equity", "datatype": "Currency", "currency": currency},
+		{"value": net_equity, "label": _("Total Equity"), "datatype": "Currency", "currency": currency},
 		{
 			"value": net_provisional_profit_loss,
-			"label": "Provisional Profit / Loss (Credit)",
+			"label": _("Provisional Profit / Loss (Credit)"),
 			"indicator": "Green" if net_provisional_profit_loss > 0 else "Red",
 			"datatype": "Currency",
 			"currency": currency,
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
index ca341f4..7b774ba 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
@@ -97,8 +97,8 @@
 			if filters["period"] == "Yearly":
 				labels = [
 					_("Budget") + " " + str(year[0]),
-					_("Actual ") + " " + str(year[0]),
-					_("Variance ") + " " + str(year[0]),
+					_("Actual") + " " + str(year[0]),
+					_("Variance") + " " + str(year[0]),
 				]
 				for label in labels:
 					columns.append(
diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py
index 8e8465c..ecad9f1 100644
--- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py
+++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py
@@ -230,7 +230,7 @@
 	columns.append(
 		{
 			"fieldname": "total",
-			"label": "Total",
+			"label": _("Total"),
 			"fieldtype": "Currency",
 			"options": "currency",
 			"width": 150,
diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py
index 8db72de..1a00399 100644
--- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py
+++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py
@@ -29,7 +29,7 @@
 			"options": "Item Group",
 			"width": 150,
 		},
-		{"fieldname": "item", "fieldtype": "Link", "options": "Item", "label": "Item", "width": 150},
+		{"fieldname": "item", "fieldtype": "Link", "options": "Item", "label": _("Item"), "width": 150},
 		{"fieldname": "item_name", "fieldtype": "Data", "label": _("Item Name"), "width": 150},
 		{
 			"fieldname": "customer",
diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
index 00f5948..3f178f4 100644
--- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
+++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
@@ -115,9 +115,9 @@
 		{"fieldname": "credit", "label": _("Credit"), "fieldtype": "Currency", "width": 140},
 		{"fieldname": "remarks", "label": _("Remarks"), "fieldtype": "Data", "width": 200},
 		{"fieldname": "age", "label": _("Age"), "fieldtype": "Int", "width": 50},
-		{"fieldname": "range1", "label": "0-30", "fieldtype": "Currency", "width": 140},
-		{"fieldname": "range2", "label": "30-60", "fieldtype": "Currency", "width": 140},
-		{"fieldname": "range3", "label": "60-90", "fieldtype": "Currency", "width": 140},
+		{"fieldname": "range1", "label": _("0-30"), "fieldtype": "Currency", "width": 140},
+		{"fieldname": "range2", "label": _("30-60"), "fieldtype": "Currency", "width": 140},
+		{"fieldname": "range3", "label": _("60-90"), "fieldtype": "Currency", "width": 140},
 		{"fieldname": "range4", "label": _("90 Above"), "fieldtype": "Currency", "width": 140},
 		{
 			"fieldname": "delay_in_payment",
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.json b/erpnext/accounts/report/tax_detail/test_tax_detail.json
index 3a4b175..e490316 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.json
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.json
@@ -302,7 +302,7 @@
   "is_opening": "No",
   "is_paid": 0,
   "is_return": 0,
-  "is_subcontracted": "No",
+  "is_subcontracted": 0,
   "items": [
    {
     "allow_zero_valuation_rate": 0,
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 7291daf..a4d2c82 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -87,7 +87,7 @@
 					missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
 
 			if missing_cwip_accounts_for_company:
-				msg = _("""To enable Capital Work in Progress Accounting, """)
+				msg = _("""To enable Capital Work in Progress Accounting,""") + " "
 				msg += _("""you must select Capital Work in Progress Account in accounts table""")
 				msg += "<br><br>"
 				msg += _("You can also set default CWIP account in Company {}").format(
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index e61efad..143f215 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -46,10 +46,9 @@
 				if d.target_location:
 					frappe.throw(
 						_(
-							"Issuing cannot be done to a location. \
-						Please enter employee who has issued Asset {0}"
+							"Issuing cannot be done to a location. Please enter employee who has issued Asset {0}"
 						).format(d.asset),
-						title="Incorrect Movement Purpose",
+						title=_("Incorrect Movement Purpose"),
 					)
 				if not d.to_employee:
 					frappe.throw(_("Employee is required while issuing Asset {0}").format(d.asset))
@@ -58,10 +57,9 @@
 				if d.to_employee:
 					frappe.throw(
 						_(
-							"Transferring cannot be done to an Employee. \
-						Please enter location where Asset {0} has to be transferred"
+							"Transferring cannot be done to an Employee. Please enter location where Asset {0} has to be transferred"
 						).format(d.asset),
-						title="Incorrect Movement Purpose",
+						title=_("Incorrect Movement Purpose"),
 					)
 				if not d.target_location:
 					frappe.throw(_("Target Location is required while transferring Asset {0}").format(d.asset))
@@ -89,8 +87,7 @@
 					if d.to_employee and d.target_location:
 						frappe.throw(
 							_(
-								"Asset {0} cannot be received at a location and \
-							given to employee in a single movement"
+								"Asset {0} cannot be received at a location and given to employee in a single movement"
 							).format(d.asset)
 						)
 
diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js
index 3fe6b2d..f5e4e72 100644
--- a/erpnext/assets/doctype/asset_repair/asset_repair.js
+++ b/erpnext/assets/doctype/asset_repair/asset_repair.js
@@ -32,7 +32,7 @@
 
 	refresh: function(frm) {
 		if (frm.doc.docstatus) {
-			frm.add_custom_button("View General Ledger", function() {
+			frm.add_custom_button(__("View General Ledger"), function() {
 				frappe.route_options = {
 					"voucher_no": frm.doc.name
 				};
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index 9953c61..20865e8 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -37,7 +37,7 @@
 				_("Asset Value Adjustment cannot be posted before Asset's purchase date <b>{0}</b>.").format(
 					formatdate(asset_purchase_date)
 				),
-				title="Incorrect Date",
+				title=_("Incorrect Date"),
 			)
 
 	def set_difference_amount(self):
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 2005dac..c9e6798 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -179,7 +179,7 @@
 				if (doc.status != "On Hold") {
 					if(flt(doc.per_received) < 100 && allow_receipt) {
 						cur_frm.add_custom_button(__('Purchase Receipt'), this.make_purchase_receipt, __('Create'));
-						if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
+						if(doc.is_subcontracted && me.has_unsupplied_items()) {
 							cur_frm.add_custom_button(__('Material to Supplier'),
 								function() { me.make_stock_entry(); }, __("Transfer"));
 						}
@@ -636,7 +636,7 @@
 frappe.provide("erpnext.buying");
 
 frappe.ui.form.on("Purchase Order", "is_subcontracted", function(frm) {
-	if (frm.doc.is_subcontracted === "Yes") {
+	if (frm.doc.is_subcontracted) {
 		erpnext.buying.get_default_bom(frm);
 	}
 });
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 896208f..9a1f9d1 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -457,16 +457,15 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "No",
+   "default": "0",
    "fieldname": "is_subcontracted",
-   "fieldtype": "Select",
+   "fieldtype": "Check",
    "in_standard_filter": 1,
-   "label": "Supply Raw Materials",
-   "options": "No\nYes",
+   "label": "Is Subcontracted",
    "print_hide": 1
   },
   {
-   "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
+   "depends_on": "eval:doc.is_subcontracted",
    "fieldname": "supplier_warehouse",
    "fieldtype": "Link",
    "label": "Supplier Warehouse",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 582bd8d..5860c4c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -194,7 +194,7 @@
 				)
 
 	def validate_bom_for_subcontracting_items(self):
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			for item in self.items:
 				if not item.bom:
 					frappe.throw(
@@ -294,7 +294,7 @@
 		self.set_status(update=True, status=status)
 		self.update_requested_qty()
 		self.update_ordered_qty()
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			self.update_reserved_qty_for_subcontract()
 
 		self.notify_update()
@@ -311,7 +311,7 @@
 		self.update_ordered_qty()
 		self.validate_budget()
 
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			self.update_reserved_qty_for_subcontract()
 
 		frappe.get_doc("Authorization Control").validate_approving_authority(
@@ -331,7 +331,7 @@
 		if self.has_drop_ship_item():
 			self.update_delivered_qty_in_sales_order()
 
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			self.update_reserved_qty_for_subcontract()
 
 		self.check_on_hold_or_closed_status()
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index e4fb970..1a7f2dd 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -390,7 +390,7 @@
 		frappe.get_doc("Item Tax Template", "Test Update Items Template - _TC").delete()
 
 	def test_update_child_uom_conv_factor_change(self):
-		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
+		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted=1)
 		total_reqd_qty = sum([d.get("required_qty") for d in po.as_dict().get("supplied_items")])
 
 		trans_item = json.dumps(
@@ -573,7 +573,7 @@
 		automatically_fetch_payment_terms(enable=0)
 
 	def test_subcontracting(self):
-		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
+		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted=1)
 		self.assertEqual(len(po.get("supplied_items")), 2)
 
 	def test_warehouse_company_validation(self):
@@ -617,7 +617,7 @@
 				"doctype": "Purchase Order",
 				"company": "_Test Company",
 				"supplier": "_Test Supplier",
-				"is_subcontracted": "No",
+				"is_subcontracted": 0,
 				"schedule_date": add_days(nowdate(), 1),
 				"currency": frappe.get_cached_value("Company", "_Test Company", "default_currency"),
 				"conversion_factor": 1,
@@ -764,7 +764,7 @@
 		)
 
 		# Submit PO
-		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
+		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted=1)
 
 		bin2 = frappe.db.get_value(
 			"Bin",
@@ -919,7 +919,7 @@
 		po = create_purchase_order(
 			item_code=item_code,
 			qty=1,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 			include_exploded_items=1,
 		)
@@ -936,7 +936,7 @@
 		po1 = create_purchase_order(
 			item_code=item_code,
 			qty=1,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 			include_exploded_items=0,
 		)
@@ -957,7 +957,7 @@
 		po = create_purchase_order(
 			item_code=item_code,
 			qty=order_qty,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 		)
 
@@ -1050,7 +1050,7 @@
 		po = create_purchase_order(
 			item_code=item_code,
 			qty=order_qty,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 			do_not_save=True,
 		)
@@ -1283,7 +1283,7 @@
 	po.schedule_date = add_days(nowdate(), 1)
 	po.company = args.company or "_Test Company"
 	po.supplier = args.supplier or "_Test Supplier"
-	po.is_subcontracted = args.is_subcontracted or "No"
+	po.is_subcontracted = args.is_subcontracted or 0
 	po.currency = args.currency or frappe.get_cached_value("Company", po.company, "default_currency")
 	po.conversion_factor = args.conversion_factor or 1
 	po.supplier_warehouse = args.supplier_warehouse or None
@@ -1309,7 +1309,7 @@
 	if not args.do_not_save:
 		po.insert()
 		if not args.do_not_submit:
-			if po.is_subcontracted == "Yes":
+			if po.is_subcontracted:
 				supp_items = po.get("supplied_items")
 				for d in supp_items:
 					if not d.reserve_warehouse:
diff --git a/erpnext/buying/doctype/purchase_order/test_records.json b/erpnext/buying/doctype/purchase_order/test_records.json
index 74b8f1b..896050c 100644
--- a/erpnext/buying/doctype/purchase_order/test_records.json
+++ b/erpnext/buying/doctype/purchase_order/test_records.json
@@ -8,7 +8,7 @@
   "doctype": "Purchase Order", 
   "base_grand_total": 5000.0, 
   "grand_total": 5000.0, 
-  "is_subcontracted": "Yes", 
+  "is_subcontracted": 1, 
   "naming_series": "_T-Purchase Order-", 
   "base_net_total": 5000.0, 
   "items": [
@@ -42,7 +42,7 @@
   "doctype": "Purchase Order", 
   "base_grand_total": 5000.0, 
   "grand_total": 5000.0, 
-  "is_subcontracted": "No", 
+  "is_subcontracted": 0, 
   "naming_series": "_T-Purchase Order-", 
   "base_net_total": 5000.0, 
   "items": [
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index a18c527..f72c598 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -572,7 +572,7 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:parent.is_subcontracted == 'Yes'",
+   "depends_on": "eval:parent.is_subcontracted",
    "fieldname": "bom",
    "fieldtype": "Link",
    "label": "BOM",
@@ -581,7 +581,7 @@
   },
   {
    "default": "0",
-   "depends_on": "eval:parent.is_subcontracted == 'Yes'",
+   "depends_on": "eval:parent.is_subcontracted",
    "fieldname": "include_exploded_items",
    "fieldtype": "Check",
    "label": "Include Exploded Items",
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 567e41f..8d1939a 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -773,11 +773,10 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "No",
+   "default": "0",
    "fieldname": "is_subcontracted",
-   "fieldtype": "Select",
+   "fieldtype": "Check",
    "label": "Is Subcontracted",
-   "options": "\nYes\nNo",
    "print_hide": 1
   },
   {
diff --git a/erpnext/buying/doctype/supplier_quotation/test_records.json b/erpnext/buying/doctype/supplier_quotation/test_records.json
index 0f835d2..8acac32 100644
--- a/erpnext/buying/doctype/supplier_quotation/test_records.json
+++ b/erpnext/buying/doctype/supplier_quotation/test_records.json
@@ -7,7 +7,7 @@
   "doctype": "Supplier Quotation", 
   "base_grand_total": 5000.0, 
   "grand_total": 5000.0, 
-  "is_subcontracted": "No", 
+  "is_subcontracted": 0, 
   "naming_series": "_T-Supplier Quotation-", 
   "base_net_total": 5000.0, 
   "items": [
diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py
index 992bc80..486bf23 100644
--- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py
+++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py
@@ -213,7 +213,8 @@
 		end_date = get_scorecard_date(sc.period, start_date)
 	if scp_count > 0:
 		frappe.msgprint(
-			_("Created {0} scorecards for {1} between: ").format(scp_count, sc.supplier)
+			_("Created {0} scorecards for {1} between:").format(scp_count, sc.supplier)
+			+ " "
 			+ str(first_start_date)
 			+ " - "
 			+ str(last_end_date)
diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py
index 130adc9..ab7d487 100644
--- a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py
+++ b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py
@@ -80,6 +80,6 @@
 				)[0]
 				my_variables.append(var)
 			except Exception:
-				frappe.throw(_("Unable to find variable: ") + str(match.group(1)), InvalidFormulaVariable)
+				frappe.throw(_("Unable to find variable:") + " " + str(match.group(1)), InvalidFormulaVariable)
 
 	return my_variables
diff --git a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py
index 11a7449..dbdc62e 100644
--- a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py
+++ b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py
@@ -48,7 +48,7 @@
 		"data": {
 			"labels": labels,
 			"datasets": [
-				{"name": _("{0}").format(filters.get("period")) + _(" Purchase Value"), "values": datapoints}
+				{"name": _(filters.get("period")) + " " + _("Purchase Value"), "values": datapoints}
 			],
 		},
 		"type": "line",
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
index 5ba52f1..6889322 100644
--- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
@@ -35,7 +35,7 @@
 				return {
 					filters: {
 						docstatus: 1,
-						is_subcontracted: 'Yes',
+						is_subcontracted: 1,
 						company: frappe.query_report.get_filter_value('company')
 					}
 				}
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
index 1b2705a..3d66637 100644
--- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
@@ -45,7 +45,7 @@
 def get_filters(report_filters):
 	filters = [
 		["Purchase Order", "docstatus", "=", 1],
-		["Purchase Order", "is_subcontracted", "=", "Yes"],
+		["Purchase Order", "is_subcontracted", "=", 1],
 		[
 			"Purchase Order",
 			"transaction_date",
diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py
index 004657b..2e90de6 100644
--- a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py
+++ b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py
@@ -78,7 +78,7 @@
 
 def get_po(filters):
 	record_filters = [
-		["is_subcontracted", "=", "Yes"],
+		["is_subcontracted", "=", 1],
 		["supplier", "=", filters.supplier],
 		["transaction_date", "<=", filters.to_date],
 		["transaction_date", ">=", filters.from_date],
diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
index 26e4243..57f8741 100644
--- a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
+++ b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
@@ -17,7 +17,7 @@
 
 class TestSubcontractedItemToBeReceived(FrappeTestCase):
 	def test_pending_and_received_qty(self):
-		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
+		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted=1)
 		transfer_param = []
 		make_stock_entry(
 			item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
index 98b18da..6b8a3b1 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
@@ -72,7 +72,7 @@
 		],
 		filters=[
 			["Purchase Order", "per_received", "<", "100"],
-			["Purchase Order", "is_subcontracted", "=", "Yes"],
+			["Purchase Order", "is_subcontracted", "=", 1],
 			["Purchase Order", "supplier", "=", filters.supplier],
 			["Purchase Order", "transaction_date", "<=", filters.to_date],
 			["Purchase Order", "transaction_date", ">=", filters.from_date],
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index 401176d..2791a26 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -19,7 +19,7 @@
 class TestSubcontractedItemToBeTransferred(FrappeTestCase):
 	def test_pending_and_transferred_qty(self):
 		po = create_purchase_order(
-			item_code="_Test FG Item", is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			item_code="_Test FG Item", is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		# Material Receipt of RMs
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 3a20d3f..8a9318e 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -2586,7 +2586,7 @@
 		parent.update_ordered_qty()
 		parent.update_ordered_and_reserved_qty()
 		parent.update_receiving_percentage()
-		if parent.is_subcontracted == "Yes":
+		if parent.is_subcontracted:
 			parent.update_reserved_qty_for_subcontract()
 			parent.create_raw_materials_supplied("supplied_items")
 			parent.save()
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 4789207..eda3686 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -167,7 +167,7 @@
 					_("Row #{0}: Accepted Warehouse and Supplier Warehouse cannot be same").format(item.idx)
 				)
 
-			if item.get("from_warehouse") and self.get("is_subcontracted") == "Yes":
+			if item.get("from_warehouse") and self.get("is_subcontracted"):
 				frappe.throw(
 					_(
 						"Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subcontractor"
@@ -339,10 +339,7 @@
 		return supplied_items_cost
 
 	def validate_for_subcontracting(self):
-		if not self.is_subcontracted and self.sub_contracted_items:
-			frappe.throw(_("Please enter 'Is Subcontracted' as Yes or No"))
-
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			if self.doctype in ["Purchase Receipt", "Purchase Invoice"] and not self.supplier_warehouse:
 				frappe.throw(_("Supplier Warehouse mandatory for sub-contracted {0}").format(self.doctype))
 
@@ -363,14 +360,14 @@
 					item.bom = None
 
 	def create_raw_materials_supplied(self, raw_material_table):
-		if self.is_subcontracted == "Yes":
+		if self.is_subcontracted:
 			self.set_materials_for_subcontracted_items(raw_material_table)
 
 		elif self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
 			for item in self.get("items"):
 				item.rm_supp_cost = 0.0
 
-		if self.is_subcontracted == "No" and self.get("supplied_items"):
+		if not self.is_subcontracted and self.get("supplied_items"):
 			self.set("supplied_items", [])
 
 	@property
@@ -466,7 +463,10 @@
 		stock_items = self.get_stock_items()
 
 		for d in self.get("items"):
-			if d.item_code in stock_items and d.warehouse:
+			if d.item_code not in stock_items:
+				continue
+
+			if d.warehouse:
 				pr_qty = flt(d.qty) * flt(d.conversion_factor)
 
 				if pr_qty:
@@ -491,6 +491,7 @@
 					sle = self.get_sl_entries(
 						d, {"actual_qty": flt(pr_qty), "serial_no": cstr(d.serial_no).strip()}
 					)
+
 					if self.is_return:
 						outgoing_rate = get_rate_for_return(
 							self.doctype, self.name, d.item_code, self.return_against, item_row=d
@@ -520,18 +521,18 @@
 
 						sl_entries.append(from_warehouse_sle)
 
-				if flt(d.rejected_qty) != 0:
-					sl_entries.append(
-						self.get_sl_entries(
-							d,
-							{
-								"warehouse": d.rejected_warehouse,
-								"actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor),
-								"serial_no": cstr(d.rejected_serial_no).strip(),
-								"incoming_rate": 0.0,
-							},
-						)
+			if flt(d.rejected_qty) != 0:
+				sl_entries.append(
+					self.get_sl_entries(
+						d,
+						{
+							"warehouse": d.rejected_warehouse,
+							"actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor),
+							"serial_no": cstr(d.rejected_serial_no).strip(),
+							"incoming_rate": 0.0,
+						},
 					)
+				)
 
 		self.make_sl_entries_for_supplier_warehouse(sl_entries)
 		self.make_sl_entries(
@@ -803,7 +804,7 @@
 		if self.doctype == "Material Request":
 			return
 
-		if hasattr(self, "is_subcontracted") and self.is_subcontracted == "Yes":
+		if hasattr(self, "is_subcontracted") and self.is_subcontracted:
 			validate_item_type(self, "is_sub_contracted_item", "subcontracted")
 		else:
 			validate_item_type(self, "is_purchase_item", "purchase")
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index 7083088..4bce06f 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -407,7 +407,7 @@
 
 	def set_consumed_qty_in_po(self):
 		# Update consumed qty back in the purchase order
-		if self.is_subcontracted != "Yes":
+		if not self.is_subcontracted:
 			return
 
 		self.__get_purchase_orders()
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
index 7aa0b77..d532236 100644
--- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
+++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
@@ -37,7 +37,7 @@
 			let msg,color;
 
 			if (days>0){
-				msg = __("Your Session will be expire in ") + days + __(" days.");
+				msg = __("Your Session will be expire in {0} days.", [days]);
 				color = "green";
 			}
 			else {
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js
index 6874caa..d4ac0ba 100644
--- a/erpnext/crm/doctype/social_media_post/social_media_post.js
+++ b/erpnext/crm/doctype/social_media_post/social_media_post.js
@@ -86,7 +86,7 @@
 				frm.trigger('add_post_btn');
 			}
 			if (frm.doc.post_status !='Deleted') {
-				frm.add_custom_button(('Delete Post'), function() {
+				frm.add_custom_button(__('Delete Post'), function() {
 					frappe.confirm(__('Are you sure want to delete the Post from Social Media platforms?'),
 						function() {
 							frappe.call({
diff --git a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py
index 9dae1d5..db36581 100644
--- a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py
+++ b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.py
@@ -3,11 +3,12 @@
 
 
 import frappe
+from frappe import _
 
 
 def execute(filters=None):
 	columns = [
-		{"fieldname": "creation_date", "label": "Date", "fieldtype": "Date", "width": 300},
+		{"fieldname": "creation_date", "label": _("Date"), "fieldtype": "Date", "width": 300},
 		{
 			"fieldname": "first_response_time",
 			"fieldtype": "Duration",
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
index d5fb969..e6f08f7 100644
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
+++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
@@ -47,7 +47,7 @@
   "item_search_settings_section",
   "redisearch_warning",
   "search_index_fields",
-  "show_categories_in_search_autocomplete",
+  "is_redisearch_enabled",
   "is_redisearch_loaded",
   "shop_by_category_section",
   "slideshow",
@@ -293,6 +293,7 @@
    "fieldname": "search_index_fields",
    "fieldtype": "Small Text",
    "label": "Search Index Fields",
+   "mandatory_depends_on": "is_redisearch_enabled",
    "read_only_depends_on": "eval:!doc.is_redisearch_loaded"
   },
   {
@@ -302,13 +303,6 @@
    "label": "Item Search Settings"
   },
   {
-   "default": "1",
-   "fieldname": "show_categories_in_search_autocomplete",
-   "fieldtype": "Check",
-   "label": "Show Categories in Search Autocomplete",
-   "read_only_depends_on": "eval:!doc.is_redisearch_loaded"
-  },
-  {
    "default": "0",
    "fieldname": "is_redisearch_loaded",
    "fieldtype": "Check",
@@ -365,12 +359,19 @@
    "fieldname": "show_price_in_quotation",
    "fieldtype": "Check",
    "label": "Show Price in Quotation"
+  },
+  {
+   "default": "0",
+   "fieldname": "is_redisearch_enabled",
+   "fieldtype": "Check",
+   "label": "Enable Redisearch",
+   "read_only_depends_on": "eval:!doc.is_redisearch_loaded"
   }
  ],
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-09-02 14:02:44.785824",
+ "modified": "2022-04-01 18:35:56.106756",
  "modified_by": "Administrator",
  "module": "E-commerce",
  "name": "E Commerce Settings",
@@ -389,5 +390,6 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py
index 881d833..f85667e 100644
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py
+++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py
@@ -9,6 +9,7 @@
 
 from erpnext.e_commerce.redisearch_utils import (
 	create_website_items_index,
+	define_autocomplete_dictionary,
 	get_indexable_web_fields,
 	is_search_module_loaded,
 )
@@ -21,6 +22,8 @@
 class ECommerceSettings(Document):
 	def onload(self):
 		self.get("__onload").quotation_series = frappe.get_meta("Quotation").get_options("naming_series")
+
+		# flag >> if redisearch is installed and loaded
 		self.is_redisearch_loaded = is_search_module_loaded()
 
 	def validate(self):
@@ -34,6 +37,20 @@
 
 		frappe.clear_document_cache("E Commerce Settings", "E Commerce Settings")
 
+		self.is_redisearch_enabled_pre_save = frappe.db.get_single_value(
+			"E Commerce Settings", "is_redisearch_enabled"
+		)
+
+	def after_save(self):
+		self.create_redisearch_indexes()
+
+	def create_redisearch_indexes(self):
+		# if redisearch is enabled (value changed) create indexes and dictionary
+		value_changed = self.is_redisearch_enabled != self.is_redisearch_enabled_pre_save
+		if self.is_redisearch_loaded and self.is_redisearch_enabled and value_changed:
+			define_autocomplete_dictionary()
+			create_website_items_index()
+
 	def validate_field_filters(self):
 		if not (self.enable_field_filters and self.filter_fields):
 			return
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.js b/erpnext/e_commerce/doctype/website_item/website_item.js
index 7108cab..7295e4b 100644
--- a/erpnext/e_commerce/doctype/website_item/website_item.js
+++ b/erpnext/e_commerce/doctype/website_item/website_item.js
@@ -2,7 +2,7 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Website Item', {
-	onload: function(frm) {
+	onload: (frm) => {
 		// should never check Private
 		frm.fields_dict["website_image"].df.is_private = 0;
 
@@ -13,18 +13,35 @@
 		});
 	},
 
-	image: function() {
+	refresh: (frm) => {
+		frm.add_custom_button(__("Prices"), function() {
+			frappe.set_route("List", "Item Price", {"item_code": frm.doc.item_code});
+		}, __("View"));
+
+		frm.add_custom_button(__("Stock"), function() {
+			frappe.route_options = {
+				"item_code": frm.doc.item_code
+			};
+			frappe.set_route("query-report", "Stock Balance");
+		}, __("View"));
+
+		frm.add_custom_button(__("E Commerce Settings"), function() {
+			frappe.set_route("Form", "E Commerce Settings");
+		}, __("View"));
+	},
+
+	image: () => {
 		refresh_field("image_view");
 	},
 
-	copy_from_item_group: function(frm) {
+	copy_from_item_group: (frm) => {
 		return frm.call({
 			doc: frm.doc,
 			method: "copy_specification_from_item_group"
 		});
 	},
 
-	set_meta_tags(frm) {
+	set_meta_tags: (frm) => {
 		frappe.utils.set_meta_tag(frm.doc.route);
 	}
 });
diff --git a/erpnext/e_commerce/redisearch_utils.py b/erpnext/e_commerce/redisearch_utils.py
index 82829bf..f2dd796 100644
--- a/erpnext/e_commerce/redisearch_utils.py
+++ b/erpnext/e_commerce/redisearch_utils.py
@@ -1,8 +1,12 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
+import json
+
 import frappe
+from frappe import _
 from frappe.utils.redis_wrapper import RedisWrapper
+from redis import ResponseError
 from redisearch import AutoCompleter, Client, IndexDefinition, Suggestion, TagField, TextField
 
 WEBSITE_ITEM_INDEX = "website_items_index"
@@ -22,6 +26,12 @@
 	return [df.fieldname for df in valid_fields]
 
 
+def is_redisearch_enabled():
+	"Return True only if redisearch is loaded and enabled."
+	is_redisearch_enabled = frappe.db.get_single_value("E Commerce Settings", "is_redisearch_enabled")
+	return is_search_module_loaded() and is_redisearch_enabled
+
+
 def is_search_module_loaded():
 	try:
 		cache = frappe.cache()
@@ -32,14 +42,14 @@
 		)
 		return "search" in parsed_output
 	except Exception:
-		return False
+		return False  # handling older redis versions
 
 
-def if_redisearch_loaded(function):
-	"Decorator to check if Redisearch is loaded."
+def if_redisearch_enabled(function):
+	"Decorator to check if Redisearch is enabled."
 
 	def wrapper(*args, **kwargs):
-		if is_search_module_loaded():
+		if is_redisearch_enabled():
 			func = function(*args, **kwargs)
 			return func
 		return
@@ -51,22 +61,25 @@
 	return "{0}|{1}".format(frappe.conf.db_name, key).encode("utf-8")
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def create_website_items_index():
 	"Creates Index Definition."
 
 	# CREATE index
 	client = Client(make_key(WEBSITE_ITEM_INDEX), conn=frappe.cache())
 
-	# DROP if already exists
 	try:
-		client.drop_index()
-	except Exception:
+		client.drop_index()  # drop if already exists
+	except ResponseError:
+		# will most likely raise a ResponseError if index does not exist
+		# ignore and create index
 		pass
+	except Exception:
+		raise_redisearch_error()
 
 	idx_def = IndexDefinition([make_key(WEBSITE_ITEM_KEY_PREFIX)])
 
-	# Based on e-commerce settings
+	# Index fields mentioned in e-commerce settings
 	idx_fields = frappe.db.get_single_value("E Commerce Settings", "search_index_fields")
 	idx_fields = idx_fields.split(",") if idx_fields else []
 
@@ -91,20 +104,20 @@
 	return TextField(field)
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def insert_item_to_index(website_item_doc):
 	# Insert item to index
 	key = get_cache_key(website_item_doc.name)
 	cache = frappe.cache()
 	web_item = create_web_item_map(website_item_doc)
 
-	for k, v in web_item.items():
-		super(RedisWrapper, cache).hset(make_key(key), k, v)
+	for field, value in web_item.items():
+		super(RedisWrapper, cache).hset(make_key(key), field, value)
 
 	insert_to_name_ac(website_item_doc.web_item_name, website_item_doc.name)
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def insert_to_name_ac(web_name, doc_name):
 	ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=frappe.cache())
 	ac.add_suggestions(Suggestion(web_name, payload=doc_name))
@@ -114,20 +127,20 @@
 	fields_to_index = get_fields_indexed()
 	web_item = {}
 
-	for f in fields_to_index:
-		web_item[f] = website_item_doc.get(f) or ""
+	for field in fields_to_index:
+		web_item[field] = website_item_doc.get(field) or ""
 
 	return web_item
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def update_index_for_item(website_item_doc):
 	# Reinsert to Cache
 	insert_item_to_index(website_item_doc)
 	define_autocomplete_dictionary()
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def delete_item_from_index(website_item_doc):
 	cache = frappe.cache()
 	key = get_cache_key(website_item_doc.name)
@@ -135,13 +148,13 @@
 	try:
 		cache.delete(key)
 	except Exception:
-		return False
+		raise_redisearch_error()
 
 	delete_from_ac_dict(website_item_doc)
 	return True
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def delete_from_ac_dict(website_item_doc):
 	"""Removes this items's name from autocomplete dictionary"""
 	cache = frappe.cache()
@@ -149,40 +162,60 @@
 	name_ac.delete(website_item_doc.web_item_name)
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
 def define_autocomplete_dictionary():
-	"""Creates an autocomplete search dictionary for `name`.
-	Also creats autocomplete dictionary for `categories` if
-	checked in E Commerce Settings"""
+	"""
+	Defines/Redefines an autocomplete search dictionary for Website Item Name.
+	Also creats autocomplete dictionary for Published Item Groups.
+	"""
 
 	cache = frappe.cache()
-	name_ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=cache)
-	cat_ac = AutoCompleter(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE), conn=cache)
-
-	ac_categories = frappe.db.get_single_value(
-		"E Commerce Settings", "show_categories_in_search_autocomplete"
-	)
+	item_ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=cache)
+	item_group_ac = AutoCompleter(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE), conn=cache)
 
 	# Delete both autocomplete dicts
 	try:
 		cache.delete(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE))
 		cache.delete(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE))
 	except Exception:
-		return False
+		raise_redisearch_error()
 
+	create_items_autocomplete_dict(autocompleter=item_ac)
+	create_item_groups_autocomplete_dict(autocompleter=item_group_ac)
+
+
+@if_redisearch_enabled
+def create_items_autocomplete_dict(autocompleter):
+	"Add items as suggestions in Autocompleter."
 	items = frappe.get_all(
 		"Website Item", fields=["web_item_name", "item_group"], filters={"published": 1}
 	)
 
 	for item in items:
-		name_ac.add_suggestions(Suggestion(item.web_item_name))
-		if ac_categories and item.item_group:
-			cat_ac.add_suggestions(Suggestion(item.item_group))
-
-	return True
+		autocompleter.add_suggestions(Suggestion(item.web_item_name))
 
 
-@if_redisearch_loaded
+@if_redisearch_enabled
+def create_item_groups_autocomplete_dict(autocompleter):
+	"Add item groups with weightage as suggestions in Autocompleter."
+	published_item_groups = frappe.get_all(
+		"Item Group", fields=["name", "route", "weightage"], filters={"show_in_website": 1}
+	)
+	if not published_item_groups:
+		return
+
+	for item_group in published_item_groups:
+		payload = json.dumps({"name": item_group.name, "route": item_group.route})
+		autocompleter.add_suggestions(
+			Suggestion(
+				string=item_group.name,
+				score=frappe.utils.flt(item_group.weightage) or 1.0,
+				payload=payload,  # additional info that can be retrieved later
+			)
+		)
+
+
+@if_redisearch_enabled
 def reindex_all_web_items():
 	items = frappe.get_all("Website Item", fields=get_fields_indexed(), filters={"published": True})
 
@@ -191,8 +224,8 @@
 		web_item = create_web_item_map(item)
 		key = make_key(get_cache_key(item.name))
 
-		for k, v in web_item.items():
-			super(RedisWrapper, cache).hset(key, k, v)
+		for field, value in web_item.items():
+			super(RedisWrapper, cache).hset(key, field, value)
 
 
 def get_cache_key(name):
@@ -210,7 +243,12 @@
 	return fields_to_index
 
 
-# TODO: Remove later
-# # Figure out a way to run this at startup
-define_autocomplete_dictionary()
-create_website_items_index()
+def raise_redisearch_error():
+	"Create an Error Log and raise error."
+	traceback = frappe.get_traceback()
+	log = frappe.log_error(traceback, frappe._("Redisearch Error"))
+	log_link = frappe.utils.get_link_to_form("Error Log", log.name)
+
+	frappe.throw(
+		msg=_("Something went wrong. Check {0}").format(log_link), title=_("Redisearch Error")
+	)
diff --git a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
index 4db6f98..b3072c2 100644
--- a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
+++ b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.py
@@ -41,10 +41,8 @@
 			if self.day == calendar.day_name[getdate(date).weekday()]:
 				course_schedule = self.make_course_schedule(date)
 				try:
-					print("pass")
 					course_schedule.save()
 				except OverlapError:
-					print("fail")
 					course_schedules_errors.append(date)
 				else:
 					course_schedules.append(course_schedule)
diff --git a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
index 0fb2550..bbeb654 100644
--- a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
+++ b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
@@ -69,13 +69,13 @@
 		l = len(self.courses)
 		for d in self.courses:
 			if not d.student_group_name:
-				frappe.throw(_("""Student Group Name is mandatory in row {0}""".format(d.idx)))
+				frappe.throw(_("Student Group Name is mandatory in row {0}").format(d.idx))
 
 			if d.group_based_on == "Course" and not d.course:
-				frappe.throw(_("""Course is mandatory in row {0}""".format(d.idx)))
+				frappe.throw(_("Course is mandatory in row {0}").format(d.idx))
 
 			if d.group_based_on == "Batch" and not d.batch:
-				frappe.throw(_("""Batch is mandatory in row {0}""".format(d.idx)))
+				frappe.throw(_("Batch is mandatory in row {0}").format(d.idx))
 
 			frappe.publish_realtime(
 				"student_group_creation_progress", {"progress": [d.idx, l]}, user=frappe.session.user
diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py
index d849900..87bdddd 100644
--- a/erpnext/hr/doctype/department_approver/department_approver.py
+++ b/erpnext/hr/doctype/department_approver/department_approver.py
@@ -87,7 +87,7 @@
 			field_name, frappe.bold(employee.employee_name)
 		)
 		if department_list:
-			error_msg += _(" or for Department: {0}").format(frappe.bold(employee_department))
+			error_msg += " " + _("or for Department: {0}").format(frappe.bold(employee_department))
 		frappe.throw(error_msg, title=_(field_name + " Missing"))
 
 	return set(tuple(approver) for approver in approvers)
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 98408af..27479a5 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -39,11 +39,15 @@
 	def validate(self):
 		self.validate_period()
 		self.validate_allocation_overlap()
-		self.validate_back_dated_allocation()
-		self.set_total_leaves_allocated()
-		self.validate_total_leaves_allocated()
 		self.validate_lwp()
 		set_employee_name(self)
+		self.set_total_leaves_allocated()
+		self.validate_leave_days_and_dates()
+
+	def validate_leave_days_and_dates(self):
+		# all validations that should run on save as well as on update after submit
+		self.validate_back_dated_allocation()
+		self.validate_total_leaves_allocated()
 		self.validate_leave_allocation_days()
 
 	def validate_leave_allocation_days(self):
@@ -56,14 +60,19 @@
 			leave_allocated = 0
 			if leave_period:
 				leave_allocated = get_leave_allocation_for_period(
-					self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date
+					self.employee,
+					self.leave_type,
+					leave_period[0].from_date,
+					leave_period[0].to_date,
+					exclude_allocation=self.name,
 				)
 			leave_allocated += flt(self.new_leaves_allocated)
 			if leave_allocated > max_leaves_allowed:
 				frappe.throw(
 					_(
-						"Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period"
-					).format(self.leave_type, self.employee)
+						"Total allocated leaves are more than maximum allocation allowed for {0} leave type for employee {1} in the period"
+					).format(self.leave_type, self.employee),
+					OverAllocationError,
 				)
 
 	def on_submit(self):
@@ -84,6 +93,12 @@
 	def on_update_after_submit(self):
 		if self.has_value_changed("new_leaves_allocated"):
 			self.validate_against_leave_applications()
+
+			# recalculate total leaves allocated
+			self.total_leaves_allocated = flt(self.unused_leaves) + flt(self.new_leaves_allocated)
+			# run required validations again since total leaves are being updated
+			self.validate_leave_days_and_dates()
+
 			leaves_to_be_added = self.new_leaves_allocated - self.get_existing_leave_count()
 			args = {
 				"leaves": leaves_to_be_added,
@@ -92,6 +107,7 @@
 				"is_carry_forward": 0,
 			}
 			create_leave_ledger_entry(self, args, True)
+			self.db_update()
 
 	def get_existing_leave_count(self):
 		ledger_entries = frappe.get_all(
@@ -279,27 +295,27 @@
 	)
 
 
-def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
-	leave_allocated = 0
-	leave_allocations = frappe.db.sql(
-		"""
-		select employee, leave_type, from_date, to_date, total_leaves_allocated
-		from `tabLeave Allocation`
-		where employee=%(employee)s and leave_type=%(leave_type)s
-			and docstatus=1
-			and (from_date between %(from_date)s and %(to_date)s
-				or to_date between %(from_date)s and %(to_date)s
-				or (from_date < %(from_date)s and to_date > %(to_date)s))
-	""",
-		{"from_date": from_date, "to_date": to_date, "employee": employee, "leave_type": leave_type},
-		as_dict=1,
-	)
+def get_leave_allocation_for_period(
+	employee, leave_type, from_date, to_date, exclude_allocation=None
+):
+	from frappe.query_builder.functions import Sum
 
-	if leave_allocations:
-		for leave_alloc in leave_allocations:
-			leave_allocated += leave_alloc.total_leaves_allocated
-
-	return leave_allocated
+	Allocation = frappe.qb.DocType("Leave Allocation")
+	return (
+		frappe.qb.from_(Allocation)
+		.select(Sum(Allocation.total_leaves_allocated).as_("total_allocated_leaves"))
+		.where(
+			(Allocation.employee == employee)
+			& (Allocation.leave_type == leave_type)
+			& (Allocation.docstatus == 1)
+			& (Allocation.name != exclude_allocation)
+			& (
+				(Allocation.from_date.between(from_date, to_date))
+				| (Allocation.to_date.between(from_date, to_date))
+				| ((Allocation.from_date < from_date) & (Allocation.to_date > to_date))
+			)
+		)
+	).run()[0][0] or 0.0
 
 
 @frappe.whitelist()
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
index a53d4a8..dde52d7 100644
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
@@ -1,24 +1,26 @@
 import unittest
 
 import frappe
+from frappe.tests.utils import FrappeTestCase
 from frappe.utils import add_days, add_months, getdate, nowdate
 
 import erpnext
 from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.doctype.leave_allocation.leave_allocation import (
+	BackDatedAllocationError,
+	OverAllocationError,
+)
 from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation
 from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type
 
 
-class TestLeaveAllocation(unittest.TestCase):
-	@classmethod
-	def setUpClass(cls):
-		frappe.db.sql("delete from `tabLeave Period`")
+class TestLeaveAllocation(FrappeTestCase):
+	def setUp(self):
+		frappe.db.delete("Leave Period")
+		frappe.db.delete("Leave Allocation")
 
-		emp_id = make_employee("test_emp_leave_allocation@salary.com")
-		cls.employee = frappe.get_doc("Employee", emp_id)
-
-	def tearDown(self):
-		frappe.db.rollback()
+		emp_id = make_employee("test_emp_leave_allocation@salary.com", company="_Test Company")
+		self.employee = frappe.get_doc("Employee", emp_id)
 
 	def test_overlapping_allocation(self):
 		leaves = [
@@ -65,7 +67,7 @@
 		# invalid period
 		self.assertRaises(frappe.ValidationError, doc.save)
 
-	def test_allocated_leave_days_over_period(self):
+	def test_validation_for_over_allocation(self):
 		doc = frappe.get_doc(
 			{
 				"doctype": "Leave Allocation",
@@ -80,7 +82,135 @@
 		)
 
 		# allocated leave more than period
-		self.assertRaises(frappe.ValidationError, doc.save)
+		self.assertRaises(OverAllocationError, doc.save)
+
+	def test_validation_for_over_allocation_post_submission(self):
+		allocation = frappe.get_doc(
+			{
+				"doctype": "Leave Allocation",
+				"__islocal": 1,
+				"employee": self.employee.name,
+				"employee_name": self.employee.employee_name,
+				"leave_type": "_Test Leave Type",
+				"from_date": getdate("2015-09-1"),
+				"to_date": getdate("2015-09-30"),
+				"new_leaves_allocated": 15,
+			}
+		).submit()
+		allocation.reload()
+		# allocated leaves more than period after submission
+		allocation.new_leaves_allocated = 35
+		self.assertRaises(OverAllocationError, allocation.save)
+
+	def test_validation_for_over_allocation_based_on_leave_setup(self):
+		frappe.delete_doc_if_exists("Leave Period", "Test Allocation Period")
+		leave_period = frappe.get_doc(
+			dict(
+				name="Test Allocation Period",
+				doctype="Leave Period",
+				from_date=add_months(nowdate(), -6),
+				to_date=add_months(nowdate(), 6),
+				company="_Test Company",
+				is_active=1,
+			)
+		).insert()
+
+		leave_type = create_leave_type(leave_type_name="_Test Allocation Validation", is_carry_forward=1)
+		leave_type.max_leaves_allowed = 25
+		leave_type.save()
+
+		# 15 leaves allocated in this period
+		allocation = create_leave_allocation(
+			leave_type=leave_type.name,
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			from_date=leave_period.from_date,
+			to_date=nowdate(),
+		)
+		allocation.submit()
+
+		# trying to allocate additional 15 leaves
+		allocation = create_leave_allocation(
+			leave_type=leave_type.name,
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			from_date=add_days(nowdate(), 1),
+			to_date=leave_period.to_date,
+		)
+		self.assertRaises(OverAllocationError, allocation.save)
+
+	def test_validation_for_over_allocation_based_on_leave_setup_post_submission(self):
+		frappe.delete_doc_if_exists("Leave Period", "Test Allocation Period")
+		leave_period = frappe.get_doc(
+			dict(
+				name="Test Allocation Period",
+				doctype="Leave Period",
+				from_date=add_months(nowdate(), -6),
+				to_date=add_months(nowdate(), 6),
+				company="_Test Company",
+				is_active=1,
+			)
+		).insert()
+
+		leave_type = create_leave_type(leave_type_name="_Test Allocation Validation", is_carry_forward=1)
+		leave_type.max_leaves_allowed = 30
+		leave_type.save()
+
+		# 15 leaves allocated
+		allocation = create_leave_allocation(
+			leave_type=leave_type.name,
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			from_date=leave_period.from_date,
+			to_date=nowdate(),
+		)
+		allocation.submit()
+		allocation.reload()
+
+		# allocate additional 15 leaves
+		allocation = create_leave_allocation(
+			leave_type=leave_type.name,
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			from_date=add_days(nowdate(), 1),
+			to_date=leave_period.to_date,
+		)
+		allocation.submit()
+		allocation.reload()
+
+		# trying to allocate 25 leaves in 2nd alloc within leave period
+		# total leaves = 40 which is more than `max_leaves_allowed` setting i.e. 30
+		allocation.new_leaves_allocated = 25
+		self.assertRaises(OverAllocationError, allocation.save)
+
+	def test_validate_back_dated_allocation_update(self):
+		leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1)
+		leave_type.save()
+
+		# initial leave allocation = 15
+		leave_allocation = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			leave_type="_Test_CF_leave",
+			from_date=add_months(nowdate(), -12),
+			to_date=add_months(nowdate(), -1),
+			carry_forward=0,
+		)
+		leave_allocation.submit()
+
+		# new_leaves = 15, carry_forwarded = 10
+		leave_allocation_1 = create_leave_allocation(
+			employee=self.employee.name,
+			employee_name=self.employee.employee_name,
+			leave_type="_Test_CF_leave",
+			carry_forward=1,
+		)
+		leave_allocation_1.submit()
+
+		# try updating initial leave allocation
+		leave_allocation.reload()
+		leave_allocation.new_leaves_allocated = 20
+		self.assertRaises(BackDatedAllocationError, leave_allocation.save)
 
 	def test_carry_forward_calculation(self):
 		leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1)
@@ -108,8 +238,10 @@
 			carry_forward=1,
 		)
 		leave_allocation_1.submit()
+		leave_allocation_1.reload()
 
 		self.assertEqual(leave_allocation_1.unused_leaves, 10)
+		self.assertEqual(leave_allocation_1.total_leaves_allocated, 25)
 
 		leave_allocation_1.cancel()
 
@@ -197,9 +329,12 @@
 			employee=self.employee.name, employee_name=self.employee.employee_name
 		)
 		leave_allocation.submit()
+		leave_allocation.reload()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 15)
+
 		leave_allocation.new_leaves_allocated = 40
 		leave_allocation.submit()
+		leave_allocation.reload()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 40)
 
 	def test_leave_subtraction_after_submit(self):
@@ -207,9 +342,12 @@
 			employee=self.employee.name, employee_name=self.employee.employee_name
 		)
 		leave_allocation.submit()
+		leave_allocation.reload()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 15)
+
 		leave_allocation.new_leaves_allocated = 10
 		leave_allocation.submit()
+		leave_allocation.reload()
 		self.assertTrue(leave_allocation.total_leaves_allocated, 10)
 
 	def test_validation_against_leave_application_after_submit(self):
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.py b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
index 5a12486..f6bd159 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
@@ -73,10 +73,10 @@
 				frappe.bold(self.employee), frappe.bold(self.shift_type), frappe.bold(shift_details.name)
 			)
 		if shift_details.start_date:
-			msg += _(" from {0}").format(getdate(self.start_date).strftime("%d-%m-%Y"))
+			msg += " " + _("from {0}").format(getdate(self.start_date).strftime("%d-%m-%Y"))
 			title = "Ongoing Shift"
 			if shift_details.end_date:
-				msg += _(" to {0}").format(getdate(self.end_date).strftime("%d-%m-%Y"))
+				msg += " " + _("to {0}").format(getdate(self.end_date).strftime("%d-%m-%Y"))
 				title = "Active Shift"
 		if msg:
 			frappe.throw(msg, title=title)
diff --git a/erpnext/hr/doctype/shift_request/shift_request.py b/erpnext/hr/doctype/shift_request/shift_request.py
index 1e3e8ff..b5beef7 100644
--- a/erpnext/hr/doctype/shift_request/shift_request.py
+++ b/erpnext/hr/doctype/shift_request/shift_request.py
@@ -109,7 +109,7 @@
 				self.throw_overlap_error(date_overlap)
 
 	def throw_overlap_error(self, d):
-		msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(
+		msg = _("Employee {0} has already applied for {1} between {2} and {3}").format(
 			self.employee, d["shift_type"], formatdate(d["from_date"]), formatdate(d["to_date"])
-		) + """ <b><a href="/app/Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
+		) + """ : <b><a href="/app/Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
 		frappe.throw(msg, OverlapError)
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
index 93a493c..ce7e50f 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
@@ -91,8 +91,7 @@
 		) > flt(parent_plan_details[0].total_estimated_cost):
 			frappe.throw(
 				_(
-					"You can only plan for upto {0} vacancies and budget {1} \
-				for {2} as per staffing plan {3} for parent company {4}."
+					"You can only plan for upto {0} vacancies and budget {1} for {2} as per staffing plan {3} for parent company {4}."
 				).format(
 					cint(parent_plan_details[0].vacancies),
 					parent_plan_details[0].total_estimated_cost,
@@ -128,8 +127,7 @@
 		):
 			frappe.throw(
 				_(
-					"{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. \
-				You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}."
+					"{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}."
 				).format(
 					cint(all_sibling_details.vacancies),
 					all_sibling_details.total_estimated_cost,
@@ -162,8 +160,7 @@
 		):
 			frappe.throw(
 				_(
-					"Subsidiary companies have already planned for {1} vacancies at a budget of {2}. \
-				Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies"
+					"Subsidiary companies have already planned for {1} vacancies at a budget of {2}. Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies"
 				).format(
 					self.company,
 					cint(children_details.vacancies),
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 8cffe88..304d1a7 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -387,13 +387,13 @@
 		gle_map = []
 
 		if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
-			remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(
+			remarks = _("Shortfall Repayment of {0}.<br>Repayment against Loan: {1}").format(
 				self.shortfall_amount, self.against_loan
 			)
 		elif self.shortfall_amount:
 			remarks = _("Shortfall Repayment of {0}").format(self.shortfall_amount)
 		else:
-			remarks = _("Repayment against Loan: ") + self.against_loan
+			remarks = _("Repayment against Loan:") + " " + self.against_loan
 
 		if self.repay_from_salary:
 			payment_account = self.payroll_payable_account
@@ -745,6 +745,8 @@
 	if payment_type == "Loan Closure":
 		amounts["payable_principal_amount"] = amounts["pending_principal_amount"]
 		amounts["interest_amount"] += amounts["unaccrued_interest"]
-		amounts["payable_amount"] = amounts["payable_principal_amount"] + amounts["interest_amount"]
+		amounts["payable_amount"] = (
+			amounts["payable_principal_amount"] + amounts["interest_amount"] + amounts["penalty_amount"]
+		)
 
 	return amounts
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index 256f660..9a23c07 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -250,7 +250,7 @@
 					_("Serial No {0} does not belong to Item {1}").format(
 						frappe.bold(serial_no), frappe.bold(item_code)
 					),
-					title="Invalid",
+					title=_("Invalid"),
 				)
 
 			if sr_details.warranty_expiry_date and getdate(sr_details.warranty_expiry_date) >= getdate(
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
index 29a1784..66f4426 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
@@ -20,7 +20,7 @@
 
 	def validate_purpose_table(self):
 		if not self.purposes:
-			frappe.throw(_("Add Items in the Purpose Table"), title="Purposes Required")
+			frappe.throw(_("Add Items in the Purpose Table"), title=_("Purposes Required"))
 
 	def validate_maintenance_date(self):
 		if self.maintenance_type == "Scheduled" and self.maintenance_schedule_detail:
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 524f45b..62fc072 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -251,7 +251,7 @@
 		self.assertEqual(bom.items[2].rate, 0)
 		# test in Purchase Order sourced_by_supplier is not added to Supplied Item
 		po = create_purchase_order(
-			item_code=item_code, qty=1, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			item_code=item_code, qty=1, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 		bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
 		supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 89f9ca6..60b32b8 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -501,7 +501,7 @@
 			po = frappe.new_doc("Purchase Order")
 			po.supplier = supplier
 			po.schedule_date = getdate(po_list[0].schedule_date) if po_list[0].schedule_date else nowdate()
-			po.is_subcontracted = "Yes"
+			po.is_subcontracted = 1
 			for row in po_list:
 				po_data = {
 					"item_code": row.production_item,
diff --git a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
index c0affd9..ac2f61c 100644
--- a/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
+++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 
 
 def execute(filters=None):
@@ -46,17 +47,22 @@
 def get_columns():
 	return [
 		{
-			"label": "Item Code",
+			"label": _("Item Code"),
 			"fieldtype": "Link",
 			"fieldname": "item_code",
 			"width": 300,
 			"options": "Item",
 		},
-		{"label": "Item Name", "fieldtype": "data", "fieldname": "item_name", "width": 100},
-		{"label": "BOM", "fieldtype": "Link", "fieldname": "bom", "width": 150, "options": "BOM"},
-		{"label": "Qty", "fieldtype": "data", "fieldname": "qty", "width": 100},
-		{"label": "UOM", "fieldtype": "data", "fieldname": "uom", "width": 100},
-		{"label": "BOM Level", "fieldtype": "Int", "fieldname": "bom_level", "width": 100},
-		{"label": "Standard Description", "fieldtype": "data", "fieldname": "description", "width": 150},
-		{"label": "Scrap", "fieldtype": "data", "fieldname": "scrap", "width": 100},
+		{"label": _("Item Name"), "fieldtype": "data", "fieldname": "item_name", "width": 100},
+		{"label": _("BOM"), "fieldtype": "Link", "fieldname": "bom", "width": 150, "options": "BOM"},
+		{"label": _("Qty"), "fieldtype": "data", "fieldname": "qty", "width": 100},
+		{"label": _("UOM"), "fieldtype": "data", "fieldname": "uom", "width": 100},
+		{"label": _("BOM Level"), "fieldtype": "Int", "fieldname": "bom_level", "width": 100},
+		{
+			"label": _("Standard Description"),
+			"fieldtype": "data",
+			"fieldname": "description",
+			"width": 150,
+		},
+		{"label": _("Scrap"), "fieldtype": "data", "fieldname": "scrap", "width": 100},
 	]
diff --git a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py
index 17f7f5e..2c8f82f 100644
--- a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py
+++ b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 from frappe.utils import flt
 
 
@@ -114,28 +115,28 @@
 def get_column(filters):
 	return [
 		{
-			"label": "Finished Good",
+			"label": _("Finished Good"),
 			"fieldtype": "Link",
 			"fieldname": "item_code",
 			"width": 300,
 			"options": "Item",
 		},
-		{"label": "Item Name", "fieldtype": "data", "fieldname": "item_name", "width": 100},
+		{"label": _("Item Name"), "fieldtype": "data", "fieldname": "item_name", "width": 100},
 		{
-			"label": "Document Type",
+			"label": _("Document Type"),
 			"fieldtype": "Link",
 			"fieldname": "document_type",
 			"width": 150,
 			"options": "DocType",
 		},
 		{
-			"label": "Document Name",
+			"label": _("Document Name"),
 			"fieldtype": "Dynamic Link",
 			"fieldname": "document_name",
 			"width": 150,
 		},
-		{"label": "BOM Level", "fieldtype": "Int", "fieldname": "bom_level", "width": 100},
-		{"label": "Order Qty", "fieldtype": "Float", "fieldname": "qty", "width": 120},
-		{"label": "Received Qty", "fieldtype": "Float", "fieldname": "produced_qty", "width": 160},
-		{"label": "Pending Qty", "fieldtype": "Float", "fieldname": "pending_qty", "width": 110},
+		{"label": _("BOM Level"), "fieldtype": "Int", "fieldname": "bom_level", "width": 100},
+		{"label": _("Order Qty"), "fieldtype": "Float", "fieldname": "qty", "width": 120},
+		{"label": _("Received Qty"), "fieldtype": "Float", "fieldname": "produced_qty", "width": 160},
+		{"label": _("Pending Qty"), "fieldtype": "Float", "fieldname": "pending_qty", "width": 110},
 	]
diff --git a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
index c6b7e58..063ebba 100644
--- a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
+++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 from frappe.utils import cint
 
 
@@ -99,59 +100,65 @@
 	columns = [
 		{
 			"fieldname": "work_order",
-			"label": "Work Order",
+			"label": _("Work Order"),
 			"fieldtype": "Link",
 			"options": "Work Order",
 			"width": 110,
 		},
-		{"fieldname": "bom_no", "label": "BOM", "fieldtype": "Link", "options": "BOM", "width": 120},
+		{"fieldname": "bom_no", "label": _("BOM"), "fieldtype": "Link", "options": "BOM", "width": 120},
 		{
 			"fieldname": "description",
-			"label": "Description",
+			"label": _("Description"),
 			"fieldtype": "Data",
 			"options": "",
 			"width": 230,
 		},
 		{
 			"fieldname": "item_code",
-			"label": "Item Code",
+			"label": _("Item Code"),
 			"fieldtype": "Link",
 			"options": "Item",
 			"width": 110,
 		},
 		{
 			"fieldname": "source_warehouse",
-			"label": "Source Warehouse",
+			"label": _("Source Warehouse"),
 			"fieldtype": "Link",
 			"options": "Warehouse",
 			"width": 110,
 		},
-		{"fieldname": "qty", "label": "Qty to Build", "fieldtype": "Data", "options": "", "width": 110},
-		{"fieldname": "status", "label": "Status", "fieldtype": "Data", "options": "", "width": 100},
+		{
+			"fieldname": "qty",
+			"label": _("Qty to Build"),
+			"fieldtype": "Data",
+			"options": "",
+			"width": 110,
+		},
+		{"fieldname": "status", "label": _("Status"), "fieldtype": "Data", "options": "", "width": 100},
 		{
 			"fieldname": "req_items",
-			"label": "# Req'd Items",
+			"label": _("# Req'd Items"),
 			"fieldtype": "Data",
 			"options": "",
 			"width": 105,
 		},
 		{
 			"fieldname": "instock",
-			"label": "# In Stock",
+			"label": _("# In Stock"),
 			"fieldtype": "Data",
 			"options": "",
 			"width": 105,
 		},
 		{
 			"fieldname": "buildable_qty",
-			"label": "Buildable Qty",
+			"label": _("Buildable Qty"),
 			"fieldtype": "Data",
 			"options": "",
 			"width": 100,
 		},
 		{
 			"fieldname": "ready_to_build",
-			"label": "Build All?",
+			"label": _("Build All?"),
 			"fieldtype": "Data",
 			"options": "",
 			"width": 90,
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index a64a72e..6e5ffed 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -4,6 +4,7 @@
 erpnext.patches.v13_0.add_bin_unique_constraint
 erpnext.patches.v11_0.refactor_naming_series
 erpnext.patches.v11_0.refactor_autoname_naming
+erpnext.patches.v14_0.change_is_subcontracted_fieldtype
 execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
 execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24
 erpnext.patches.v4_2.update_requested_and_ordered_qty #2021-03-31
diff --git a/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py b/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py
new file mode 100644
index 0000000..ba919a7
--- /dev/null
+++ b/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+
+
+def execute():
+	for doctype in ["Purchase Order", "Purchase Receipt", "Purchase Invoice", "Supplier Quotation"]:
+		frappe.db.sql(
+			"""
+				UPDATE `tab{doctype}`
+				SET is_subcontracted = 0
+				where is_subcontracted in ('', NULL, 'No')""".format(
+				doctype=doctype
+			)
+		)
+		frappe.db.sql(
+			"""
+				UPDATE `tab{doctype}`
+				SET is_subcontracted = 1
+				where is_subcontracted = 'Yes'""".format(
+				doctype=doctype
+			)
+		)
+
+		frappe.reload_doc(frappe.get_meta(doctype).module, "doctype", frappe.scrub(doctype))
diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py
index 31f26b2..6ec34b9 100644
--- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py
+++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.py
@@ -44,8 +44,7 @@
 		if max_benefits < claimed_amount:
 			frappe.throw(
 				_(
-					"Maximum benefit of employee {0} exceeds {1} by the sum {2} of previous claimed\
-			amount"
+					"Maximum benefit of employee {0} exceeds {1} by the sum {2} of previous claimed amount"
 				).format(self.employee, max_benefits, claimed_amount - max_benefits)
 			)
 
@@ -84,8 +83,7 @@
 		if max_benefits < pro_rata_amount + claimed_amount:
 			frappe.throw(
 				_(
-					"Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component\
-			amount and previous claimed amount"
+					"Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component amount and previous claimed amount"
 				).format(
 					self.employee, max_benefits, pro_rata_amount + claimed_amount - max_benefits
 				)
diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js
index 014a121..7290a9e 100644
--- a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js
+++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js
@@ -34,7 +34,7 @@
 	to_year(frm, cdt, cdn) {
 		let row = locals[cdt][cdn];
 		if (row.to_year <= row.from_year && row.to_year === 0) {
-			frappe.throw(__("To(Year) year can not be less than From(year) "));
+			frappe.throw(__("To(Year) year can not be less than From(year)"));
 		}
 	}
 });
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
index 496c37b..62e183e 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
@@ -112,7 +112,7 @@
 			},
 			callback: function (r) {
 				if (r.message && !r.message.submitted) {
-					frm.add_custom_button("Make Bank Entry", function () {
+					frm.add_custom_button(__("Make Bank Entry"), function () {
 						make_bank_entry(frm);
 					}).addClass("btn-primary");
 				}
diff --git a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
index e5348df..4223f9d 100644
--- a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
+++ b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
@@ -142,21 +142,21 @@
 	return [
 		{
 			"value": gross_pay,
-			"label": "Total Gross Pay",
+			"label": _("Total Gross Pay"),
 			"indicator": "Green",
 			"datatype": "Currency",
 			"currency": currency,
 		},
 		{
 			"value": total_deductions,
-			"label": "Total Deduction",
+			"label": _("Total Deduction"),
 			"datatype": "Currency",
 			"indicator": "Red",
 			"currency": currency,
 		},
 		{
 			"value": net_pay,
-			"label": "Total Net Pay",
+			"label": _("Total Net Pay"),
 			"datatype": "Currency",
 			"indicator": "Blue",
 			"currency": currency,
diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py
index 5c3dc2d..17e3155 100644
--- a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py
+++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 from frappe.utils import date_diff, nowdate
 
 
@@ -83,19 +84,24 @@
 
 def get_columns():
 	columns = [
-		{"fieldname": "name", "fieldtype": "Link", "label": "Task", "options": "Task", "width": 150},
-		{"fieldname": "subject", "fieldtype": "Data", "label": "Subject", "width": 200},
-		{"fieldname": "status", "fieldtype": "Data", "label": "Status", "width": 100},
-		{"fieldname": "priority", "fieldtype": "Data", "label": "Priority", "width": 80},
-		{"fieldname": "progress", "fieldtype": "Data", "label": "Progress (%)", "width": 120},
+		{"fieldname": "name", "fieldtype": "Link", "label": _("Task"), "options": "Task", "width": 150},
+		{"fieldname": "subject", "fieldtype": "Data", "label": _("Subject"), "width": 200},
+		{"fieldname": "status", "fieldtype": "Data", "label": _("Status"), "width": 100},
+		{"fieldname": "priority", "fieldtype": "Data", "label": _("Priority"), "width": 80},
+		{"fieldname": "progress", "fieldtype": "Data", "label": _("Progress (%)"), "width": 120},
 		{
 			"fieldname": "exp_start_date",
 			"fieldtype": "Date",
-			"label": "Expected Start Date",
+			"label": _("Expected Start Date"),
 			"width": 150,
 		},
-		{"fieldname": "exp_end_date", "fieldtype": "Date", "label": "Expected End Date", "width": 150},
-		{"fieldname": "completed_on", "fieldtype": "Date", "label": "Actual End Date", "width": 130},
-		{"fieldname": "delay", "fieldtype": "Data", "label": "Delay (In Days)", "width": 120},
+		{
+			"fieldname": "exp_end_date",
+			"fieldtype": "Date",
+			"label": _("Expected End Date"),
+			"width": 150,
+		},
+		{"fieldname": "completed_on", "fieldtype": "Date", "label": _("Actual End Date"), "width": 130},
+		{"fieldname": "delay", "fieldtype": "Data", "label": _("Delay (In Days)"), "width": 120},
 	]
 	return columns
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 54e5daa..bbf1ff6 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -81,7 +81,7 @@
 		}
 
 		this.frm.set_query("item_code", "items", function() {
-			if (me.frm.doc.is_subcontracted == "Yes") {
+			if (me.frm.doc.is_subcontracted) {
 				return{
 					query: "erpnext.controllers.queries.item_query",
 					filters:{ 'supplier': me.frm.doc.supplier, 'is_sub_contracted_item': 1 }
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index a4492e8..fa41e1b 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -239,7 +239,7 @@
 				() => set_value('currency', currency),
 				() => set_value('price_list_currency', currency),
 				() => set_value('status', 'Draft'),
-				() => set_value('is_subcontracted', 'No'),
+				() => set_value('is_subcontracted', 0),
 				() => {
 					if(this.frm.doc.company && !this.frm.doc.amended_from) {
 						this.frm.trigger("company");
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 9339c5d..eded165 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -483,7 +483,7 @@
 			if (frm.doc.doctype == 'Sales Order') {
 				filters = {"is_sales_item": 1};
 			} else if (frm.doc.doctype == 'Purchase Order') {
-				if (frm.doc.is_subcontracted == "Yes") {
+				if (frm.doc.is_subcontracted) {
 					filters = {"is_sub_contracted_item": 1};
 				} else {
 					filters = {"is_purchase_item": 1};
diff --git a/erpnext/regional/doctype/datev_settings/datev_settings.js b/erpnext/regional/doctype/datev_settings/datev_settings.js
index f047059..3c36549 100644
--- a/erpnext/regional/doctype/datev_settings/datev_settings.js
+++ b/erpnext/regional/doctype/datev_settings/datev_settings.js
@@ -3,6 +3,6 @@
 
 frappe.ui.form.on('DATEV Settings', {
 	refresh: function(frm) {
-		frm.add_custom_button('Show Report', () => frappe.set_route('query-report', 'DATEV'), "fa fa-table");
+		frm.add_custom_button(__('Show Report'), () => frappe.set_route('query-report', 'DATEV'), "fa fa-table");
 	}
 });
diff --git a/erpnext/regional/india/e_invoice/einvoice.js b/erpnext/regional/india/e_invoice/einvoice.js
index 348f0c6..17b018c 100644
--- a/erpnext/regional/india/e_invoice/einvoice.js
+++ b/erpnext/regional/india/e_invoice/einvoice.js
@@ -105,6 +105,30 @@
 						},
 						primary_action_label: __('Submit')
 					});
+					d.fields_dict.transporter.df.onchange = function () {
+						const transporter = d.fields_dict.transporter.value;
+						if (transporter) {
+							frappe.db.get_value('Supplier', transporter, ['gst_transporter_id', 'supplier_name'])
+								.then(({ message }) => {
+									d.set_value('gst_transporter_id', message.gst_transporter_id);
+									d.set_value('transporter_name', message.supplier_name);
+								});
+						} else {
+							d.set_value('gst_transporter_id', '');
+							d.set_value('transporter_name', '');
+						}
+					};
+					d.fields_dict.driver.df.onchange = function () {
+						const driver = d.fields_dict.driver.value;
+						if (driver) {
+							frappe.db.get_value('Driver', driver, ['full_name'])
+								.then(({ message }) => {
+									d.set_value('driver_name', message.full_name);
+								});
+						} else {
+							d.set_value('driver_name', '');
+						}
+					};
 					d.show();
 				};
 
@@ -153,7 +177,6 @@
 			'fieldname': 'gst_transporter_id',
 			'label': 'GST Transporter ID',
 			'fieldtype': 'Data',
-			'fetch_from': 'transporter.gst_transporter_id',
 			'default': frm.doc.gst_transporter_id
 		},
 		{
@@ -189,9 +212,9 @@
 			'fieldname': 'transporter_name',
 			'label': 'Transporter Name',
 			'fieldtype': 'Data',
-			'fetch_from': 'transporter.name',
 			'read_only': 1,
-			'default': frm.doc.transporter_name
+			'default': frm.doc.transporter_name,
+			'depends_on': 'transporter'
 		},
 		{
 			'fieldname': 'mode_of_transport',
@@ -206,7 +229,8 @@
 			'fieldtype': 'Data',
 			'fetch_from': 'driver.full_name',
 			'read_only': 1,
-			'default': frm.doc.driver_name
+			'default': frm.doc.driver_name,
+			'depends_on': 'driver'
 		},
 		{
 			'fieldname': 'lr_date',
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index cbdec56..8fd9c1c 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -387,7 +387,7 @@
 
 def get_payment_details(invoice):
 	payee_name = invoice.company
-	mode_of_payment = ", ".join([d.mode_of_payment for d in invoice.payments])
+	mode_of_payment = ""
 	paid_amount = invoice.base_paid_amount
 	outstanding_amount = invoice.outstanding_amount
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 87f277f..0b48f70 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -727,7 +727,7 @@
 					args: {
 						reference_doctype: me.frm.doctype,
 						reference_name: me.frm.docname,
-						content: __('Reason for hold: ')+data.reason_for_hold,
+						content: __('Reason for hold:') + ' ' + data.reason_for_hold,
 						comment_email: frappe.session.user,
 						comment_by: frappe.session.user_fullname
 					},
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 1177615..b62b27b 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -243,7 +243,7 @@
 				value: "+1",
 				item: { item_code, batch_no, serial_no, uom, rate }
 			});
-			me.set_search_value('');
+			me.search_field.set_focus();
 		});
 
 		this.search_field.$input.on('input', (e) => {
@@ -328,6 +328,7 @@
 
 	add_filtered_item_to_cart() {
 		this.$items_container.find(".item-wrapper").click();
+		this.set_search_value('');
 	}
 
 	resize_selector(minimize) {
diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
index 33badc3..3e4bfb2 100644
--- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
+++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
@@ -102,7 +102,7 @@
 def get_data_by_territory(filters, common_columns):
 	columns = [
 		{
-			"label": "Territory",
+			"label": _("Territory"),
 			"fieldname": "territory",
 			"fieldtype": "Link",
 			"options": "Territory",
diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
index 1c10a37..98633cb 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
@@ -65,7 +65,7 @@
 		_("Credit Limit") + ":Currency:120",
 		_("Outstanding Amt") + ":Currency:100",
 		_("Credit Balance") + ":Currency:120",
-		_("Bypass credit check at Sales Order ") + ":Check:80",
+		_("Bypass credit check at Sales Order") + ":Check:80",
 		_("Is Frozen") + ":Check:80",
 		_("Disabled") + ":Check:80",
 	]
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index 12ca7b3..091c20c 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -235,7 +235,7 @@
 	return {
 		"data": {
 			"labels": labels[:30],  # show max of 30 items in chart
-			"datasets": [{"name": _(" Total Sales Amount"), "values": datapoints[:30]}],
+			"datasets": [{"name": _("Total Sales Amount"), "values": datapoints[:30]}],
 		},
 		"type": "bar",
 	}
diff --git a/erpnext/selling/report/quotation_trends/quotation_trends.py b/erpnext/selling/report/quotation_trends/quotation_trends.py
index dfcec22..4e0758d 100644
--- a/erpnext/selling/report/quotation_trends/quotation_trends.py
+++ b/erpnext/selling/report/quotation_trends/quotation_trends.py
@@ -49,7 +49,7 @@
 		"data": {
 			"labels": labels,
 			"datasets": [
-				{"name": _("{0}").format(filters.get("period")) + _(" Quoted Amount"), "values": datapoints}
+				{"name": _(filters.get("period")) + " " + _("Quoted Amount"), "values": datapoints}
 			],
 		},
 		"type": "line",
diff --git a/erpnext/selling/report/sales_order_trends/sales_order_trends.py b/erpnext/selling/report/sales_order_trends/sales_order_trends.py
index 93707bd..719f1c5 100644
--- a/erpnext/selling/report/sales_order_trends/sales_order_trends.py
+++ b/erpnext/selling/report/sales_order_trends/sales_order_trends.py
@@ -47,9 +47,7 @@
 	return {
 		"data": {
 			"labels": labels,
-			"datasets": [
-				{"name": _("{0}").format(filters.get("period")) + _(" Sales Value"), "values": datapoints}
-			],
+			"datasets": [{"name": _(filters.get("period")) + " " + _("Sales Value"), "values": datapoints}],
 		},
 		"type": "line",
 		"lineOptions": {"regionFill": 1},
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 6cb9f7e..6ea4525 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -54,7 +54,7 @@
 				(supplied_item.rm_item_code == self.item_code)
 				& (po.name == supplied_item.parent)
 				& (po.docstatus == 1)
-				& (po.is_subcontracted == "Yes")
+				& (po.is_subcontracted)
 				& (po.status != "Closed")
 				& (po.per_received < 100)
 				& (supplied_item.reserve_warehouse == self.warehouse)
@@ -79,7 +79,7 @@
 				& (se.name == se_item.parent)
 				& (po.name == se.purchase_order)
 				& (po.docstatus == 1)
-				& (po.is_subcontracted == "Yes")
+				& (po.is_subcontracted == 1)
 				& (po.status != "Closed")
 				& (po.per_received < 100)
 			)
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 9e8b3bd..23301a6 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -55,10 +55,15 @@
 
 		if (frm.doc.has_variants) {
 			frm.set_intro(__("This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set"), true);
+
 			frm.add_custom_button(__("Show Variants"), function() {
 				frappe.set_route("List", "Item", {"variant_of": frm.doc.name});
 			}, __("View"));
 
+			frm.add_custom_button(__("Item Variant Settings"), function() {
+				frappe.set_route("Form", "Item Variant Settings");
+			}, __("View"));
+
 			frm.add_custom_button(__("Variant Details Report"), function() {
 				frappe.set_route("query-report", "Item Variant Details", {"item": frm.doc.name});
 			}, __("View"));
@@ -110,6 +115,13 @@
 					}
 				});
 			}, __('Actions'));
+		} else {
+			frm.add_custom_button(__("Website Item"), function() {
+				frappe.db.get_value("Website Item", {item_code: frm.doc.name}, "name", (d) => {
+					if (!d.name) frappe.throw(__("Website Item not found"));
+					frappe.set_route("Form", "Website Item", d.name);
+				});
+			}, __("View"));
 		}
 
 		erpnext.item.edit_prices_button(frm);
@@ -131,12 +143,6 @@
 			frappe.set_route('Form', 'Item', new_item.name);
 		});
 
-		if(frm.doc.has_variants) {
-			frm.add_custom_button(__("Item Variant Settings"), function() {
-				frappe.set_route("Form", "Item Variant Settings");
-			}, __("View"));
-		}
-
 		const stock_exists = (frm.doc.__onload
 			&& frm.doc.__onload.stock_exists) ? 1 : 0;
 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 9d7c22f..535f565 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -464,7 +464,7 @@
 			frappe.msgprint(
 				_("It can take upto few hours for accurate stock values to be visible after merging items."),
 				indicator="orange",
-				title="Note",
+				title=_("Note"),
 			)
 
 		if self.published_in_website:
diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py
index 33acf4b..3caed02 100644
--- a/erpnext/stock/doctype/item/item_dashboard.py
+++ b/erpnext/stock/doctype/item/item_dashboard.py
@@ -32,5 +32,6 @@
 			{"label": _("Manufacture"), "items": ["Production Plan", "Work Order", "Item Manufacturer"]},
 			{"label": _("Traceability"), "items": ["Serial No", "Batch"]},
 			{"label": _("Move"), "items": ["Stock Entry"]},
+			{"label": _("E-commerce"), "items": ["Website Item"]},
 		],
 	}
diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
index d829b2c..32c58c5 100644
--- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
@@ -41,7 +41,7 @@
 		supplier_warehouse = "Test Supplier Warehouse - _TC"
 		po = create_purchase_order(
 			item="Test Finished Goods - A",
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			qty=5,
 			rate=3000,
 			supplier_warehouse=supplier_warehouse,
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 4524914..a70ff17 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -209,16 +209,14 @@
 						if d.ordered_qty and d.ordered_qty > allowed_qty:
 							frappe.throw(
 								_(
-									"The total Issue / Transfer quantity {0} in Material Request {1}  \
-								cannot be greater than allowed requested quantity {2} for Item {3}"
+									"The total Issue / Transfer quantity {0} in Material Request {1}  cannot be greater than allowed requested quantity {2} for Item {3}"
 								).format(d.ordered_qty, d.parent, allowed_qty, d.item_code)
 							)
 
 					elif d.ordered_qty and d.ordered_qty > d.stock_qty:
 						frappe.throw(
 							_(
-								"The total Issue / Transfer quantity {0} in Material Request {1}  \
-							cannot be greater than requested quantity {2} for Item {3}"
+								"The total Issue / Transfer quantity {0} in Material Request {1} cannot be greater than requested quantity {2} for Item {3}"
 							).format(d.ordered_qty, d.parent, d.qty, d.item_code)
 						)
 
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index d3476a8..33d7745 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -33,7 +33,9 @@
 				location.sales_order
 				and frappe.db.get_value("Sales Order", location.sales_order, "per_picked") == 100
 			):
-				frappe.throw("Row " + str(location.idx) + " has been picked already!")
+				frappe.throw(
+					_("Row #{}: item {} has been picked already.").format(location.idx, location.item_code)
+				)
 
 	def before_submit(self):
 		for item in self.locations:
@@ -82,10 +84,9 @@
 				100 + flt(frappe.db.get_single_value("Stock Settings", "over_delivery_receipt_allowance"))
 			):
 				frappe.throw(
-					"You are picking more than required quantity for "
-					+ item_code
-					+ ". Check if there is any other pick list created for "
-					+ so_doc.name
+					_(
+						"You are picking more than required quantity for {}. Check if there is any other pick list created for {}"
+					).format(item_code, so_doc.name)
 				)
 
 		frappe.db.set_value("Sales Order Item", so_item, "picked_qty", already_picked + picked_qty)
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 0182ed5..51ec598 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -200,7 +200,7 @@
 			cur_frm.add_custom_button(__('Reopen'), this.reopen_purchase_receipt, __("Status"))
 		}
 
-		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
+		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted);
 	}
 
 	make_purchase_invoice() {
@@ -298,10 +298,10 @@
 frappe.provide("erpnext.buying");
 
 frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) {
-	if (frm.doc.is_subcontracted === "Yes") {
+	if (frm.doc.is_subcontracted) {
 		erpnext.buying.get_default_bom(frm);
 	}
-	frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
+	frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted);
 });
 
 frappe.ui.form.on('Purchase Receipt Item', {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 6d4b4a1..6e5f6f5 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -437,17 +437,16 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "No",
+   "default": "0",
    "fieldname": "is_subcontracted",
-   "fieldtype": "Select",
-   "label": "Raw Materials Consumed",
+   "fieldtype": "Check",
+   "label": "Is Subcontracted",
    "oldfieldname": "is_subcontracted",
    "oldfieldtype": "Select",
-   "options": "No\nYes",
    "print_hide": 1
   },
   {
-   "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
+   "depends_on": "eval:doc.is_subcontracted",
    "fieldname": "supplier_warehouse",
    "fieldtype": "Link",
    "label": "Supplier Warehouse",
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index a6f82b0..f3faba4 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -327,7 +327,7 @@
 			target="_Test Warehouse 1 - _TC",
 			basic_rate=100,
 		)
-		pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes")
+		pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted=1)
 		self.assertEqual(len(pr.get("supplied_items")), 2)
 
 		rm_supp_cost = sum(d.amount for d in pr.get("supplied_items"))
@@ -362,7 +362,7 @@
 			item_code="_Test FG Item",
 			qty=10,
 			rate=0,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			company="_Test Company with perpetual inventory",
 			warehouse="Stores - TCP1",
 			supplier_warehouse="Work In Progress - TCP1",
@@ -401,7 +401,7 @@
 			item_code=item_code,
 			qty=1,
 			include_exploded_items=0,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 		)
 
@@ -647,6 +647,45 @@
 		return_pr.cancel()
 		pr.cancel()
 
+	def test_purchase_receipt_for_rejected_gle_without_accepted_warehouse(self):
+		from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
+
+		rejected_warehouse = "_Test Rejected Warehouse - TCP1"
+		if not frappe.db.exists("Warehouse", rejected_warehouse):
+			get_warehouse(
+				company="_Test Company with perpetual inventory",
+				abbr=" - TCP1",
+				warehouse_name="_Test Rejected Warehouse",
+			).name
+
+		pr = make_purchase_receipt(
+			company="_Test Company with perpetual inventory",
+			warehouse="Stores - TCP1",
+			received_qty=2,
+			rejected_qty=2,
+			rejected_warehouse=rejected_warehouse,
+			do_not_save=True,
+		)
+
+		pr.items[0].qty = 0.0
+		pr.items[0].warehouse = ""
+		pr.submit()
+
+		actual_qty = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{
+				"voucher_type": "Purchase Receipt",
+				"voucher_no": pr.name,
+				"warehouse": pr.items[0].rejected_warehouse,
+				"is_cancelled": 0,
+			},
+			"actual_qty",
+		)
+
+		self.assertEqual(actual_qty, 2)
+		self.assertFalse(pr.items[0].warehouse)
+		pr.cancel()
+
 	def test_purchase_return_for_serialized_items(self):
 		def _check_serial_no_values(serial_no, field_values):
 			serial_no = frappe.get_doc("Serial No", serial_no)
@@ -1122,7 +1161,7 @@
 		po = create_purchase_order(
 			item_code=item_code,
 			qty=order_qty,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 			supplier_warehouse="_Test Warehouse 1 - _TC",
 		)
 
@@ -1465,7 +1504,7 @@
 		pr.set_posting_time = 1
 	pr.company = args.company or "_Test Company"
 	pr.supplier = args.supplier or "_Test Supplier"
-	pr.is_subcontracted = args.is_subcontracted or "No"
+	pr.is_subcontracted = args.is_subcontracted or 0
 	pr.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
 	pr.currency = args.currency or "INR"
 	pr.is_return = args.is_return
diff --git a/erpnext/stock/doctype/purchase_receipt/test_records.json b/erpnext/stock/doctype/purchase_receipt/test_records.json
index 724e3d7..990ad12 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_records.json
+++ b/erpnext/stock/doctype/purchase_receipt/test_records.json
@@ -92,7 +92,7 @@
   "currency": "INR",
   "doctype": "Purchase Receipt",
   "base_grand_total": 5000.0,
-  "is_subcontracted": "Yes",
+  "is_subcontracted": 1,
   "base_net_total": 5000.0,
   "items": [
    {
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index e5994b2..03a4201 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -648,7 +648,7 @@
   },
   {
    "default": "0",
-   "depends_on": "eval:parent.is_subcontracted == 'Yes'",
+   "depends_on": "eval:parent.is_subcontracted",
    "fieldname": "include_exploded_items",
    "fieldtype": "Check",
    "label": "Include Exploded Items",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 7564bb2..1df56ef 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -214,7 +214,7 @@
 
 		if (frm.doc.docstatus === 1) {
 			if (frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer' && frm.doc.per_transferred < 100) {
-				frm.add_custom_button('End Transit', function() {
+				frm.add_custom_button(__('End Transit'), function() {
 					frappe.model.open_mapped_doc({
 						method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry",
 						frm: frm
@@ -633,7 +633,7 @@
 		// set allow_zero_valuation_rate to 0 if s_warehouse is selected.
 		let item = frappe.get_doc(cdt, cdn);
 		if (item.s_warehouse) {
-			item.allow_zero_valuation_rate = 0;
+			frappe.model.set_value(cdt, cdn, "allow_zero_valuation_rate", 0);
 		}
 	},
 
@@ -778,7 +778,7 @@
 			return {
 				"filters": {
 					"docstatus": 1,
-					"is_subcontracted": "Yes",
+					"is_subcontracted": 1,
 					"company": me.frm.doc.company
 				}
 			};
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index 42956a1..6561362 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -436,7 +436,7 @@
 			item_code=subcontracted_item,
 			qty=10,
 			rate=20,
-			is_subcontracted="Yes",
+			is_subcontracted=1,
 		)
 
 		self.assertEqual(pr1.items[0].valuation_rate, 120)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 4438acf..05dd105 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -55,6 +55,25 @@
 		}
 	},
 
+	scan_barcode: function(frm) {
+		const barcode_scanner = new erpnext.utils.BarcodeScanner({frm:frm});
+		barcode_scanner.process_scan();
+	},
+
+	scan_mode: function(frm) {
+		if (frm.doc.scan_mode) {
+			frappe.show_alert({
+				message: __("Scan mode enabled, existing quantity will not be fetched."),
+				indicator: "green"
+			});
+		}
+	},
+
+	set_warehouse: function(frm) {
+		let transaction_controller = new erpnext.TransactionController({frm:frm});
+		transaction_controller.autofill_warehouse(frm.doc.items, "warehouse", frm.doc.set_warehouse);
+	},
+
 	get_items: function(frm) {
 		let fields = [
 			{
@@ -148,15 +167,18 @@
 					batch_no: d.batch_no
 				},
 				callback: function(r) {
-					frappe.model.set_value(cdt, cdn, "qty", r.message.qty);
+					const row = frappe.model.get_doc(cdt, cdn);
+					if (!frm.doc.scan_mode) {
+						frappe.model.set_value(cdt, cdn, "qty", r.message.qty);
+					}
 					frappe.model.set_value(cdt, cdn, "valuation_rate", r.message.rate);
 					frappe.model.set_value(cdt, cdn, "current_qty", r.message.qty);
 					frappe.model.set_value(cdt, cdn, "current_valuation_rate", r.message.rate);
 					frappe.model.set_value(cdt, cdn, "current_amount", r.message.rate * r.message.qty);
-					frappe.model.set_value(cdt, cdn, "amount", r.message.rate * r.message.qty);
+					frappe.model.set_value(cdt, cdn, "amount", row.qty * row.valuation_rate);
 					frappe.model.set_value(cdt, cdn, "current_serial_no", r.message.serial_nos);
 
-					if (frm.doc.purpose == "Stock Reconciliation") {
+					if (frm.doc.purpose == "Stock Reconciliation" && !frm.doc.scan_mode) {
 						frappe.model.set_value(cdt, cdn, "serial_no", r.message.serial_nos);
 					}
 				}
@@ -204,7 +226,7 @@
 
 	warehouse: function(frm, cdt, cdn) {
 		var child = locals[cdt][cdn];
-		if (child.batch_no) {
+		if (child.batch_no && !frm.doc.scan_mode) {
 			frappe.model.set_value(child.cdt, child.cdn, "batch_no", "");
 		}
 
@@ -213,7 +235,7 @@
 
 	item_code: function(frm, cdt, cdn) {
 		var child = locals[cdt][cdn];
-		if (child.batch_no) {
+		if (child.batch_no && !frm.doc.scan_mode) {
 			frappe.model.set_value(cdt, cdn, "batch_no", "");
 		}
 
@@ -239,7 +261,14 @@
 			const serial_nos = child.serial_no.trim().split('\n');
 			frappe.model.set_value(cdt, cdn, "qty", serial_nos.length);
 		}
-	}
+	},
+
+	items_add: function(frm, cdt, cdn) {
+		var item = frappe.get_doc(cdt, cdn);
+		if (!item.warehouse && frm.doc.set_warehouse) {
+			frappe.model.set_value(cdt, cdn, "warehouse", frm.doc.set_warehouse);
+		}
+	},
 
 });
 
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
index a882a61..e545b8e 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
@@ -14,6 +14,12 @@
   "posting_date",
   "posting_time",
   "set_posting_time",
+  "section_break_8",
+  "set_warehouse",
+  "section_break_22",
+  "scan_barcode",
+  "column_break_12",
+  "scan_mode",
   "sb9",
   "items",
   "section_break_9",
@@ -139,13 +145,44 @@
   {
    "fieldname": "dimension_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_8",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "label": "Scan Barcode",
+   "options": "Barcode"
+  },
+  {
+   "default": "0",
+   "description": "Disables auto-fetching of existing quantity",
+   "fieldname": "scan_mode",
+   "fieldtype": "Check",
+   "label": "Scan Mode"
+  },
+  {
+   "fieldname": "set_warehouse",
+   "fieldtype": "Link",
+   "label": "Default Warehouse",
+   "options": "Warehouse"
+  },
+  {
+   "fieldname": "section_break_22",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_12",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-upload-alt",
  "idx": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-02-06 14:28:19.043905",
+ "modified": "2022-03-27 08:57:47.161959",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Reconciliation",
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 07a8566..5d5a27f 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -1,6 +1,7 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
+from typing import Optional
 
 import frappe
 from frappe import _, msgprint
@@ -706,29 +707,43 @@
 
 @frappe.whitelist()
 def get_stock_balance_for(
-	item_code, warehouse, posting_date, posting_time, batch_no=None, with_valuation_rate=True
+	item_code: str,
+	warehouse: str,
+	posting_date: str,
+	posting_time: str,
+	batch_no: Optional[str] = None,
+	with_valuation_rate: bool = True,
 ):
 	frappe.has_permission("Stock Reconciliation", "write", throw=True)
 
-	item_dict = frappe.db.get_value("Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1)
+	item_dict = frappe.get_cached_value(
+		"Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1
+	)
 
 	if not item_dict:
 		# In cases of data upload to Items table
 		msg = _("Item {} does not exist.").format(item_code)
 		frappe.throw(msg, title=_("Missing"))
 
-	serial_nos = ""
-	with_serial_no = True if item_dict.get("has_serial_no") else False
+	serial_nos = None
+	has_serial_no = bool(item_dict.get("has_serial_no"))
+	has_batch_no = bool(item_dict.get("has_batch_no"))
+
+	if not batch_no and has_batch_no:
+		# Not enough information to fetch data
+		return {"qty": 0, "rate": 0, "serial_nos": None}
+
+	# TODO: fetch only selected batch's values
 	data = get_stock_balance(
 		item_code,
 		warehouse,
 		posting_date,
 		posting_time,
 		with_valuation_rate=with_valuation_rate,
-		with_serial_no=with_serial_no,
+		with_serial_no=has_serial_no,
 	)
 
-	if with_serial_no:
+	if has_serial_no:
 		qty, rate, serial_nos = data
 	else:
 		qty, rate = data
diff --git a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
index 6bbba05..79c2fcc 100644
--- a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
+++ b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
@@ -16,15 +16,15 @@
   "amount",
   "allow_zero_valuation_rate",
   "serial_no_and_batch_section",
-  "serial_no",
-  "column_break_11",
   "batch_no",
+  "column_break_11",
+  "serial_no",
   "section_break_3",
   "current_qty",
-  "current_serial_no",
+  "current_amount",
   "column_break_9",
   "current_valuation_rate",
-  "current_amount",
+  "current_serial_no",
   "section_break_14",
   "quantity_difference",
   "column_break_16",
@@ -181,7 +181,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2021-05-21 12:13:33.041266",
+ "modified": "2022-04-02 04:19:40.380587",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Reconciliation Item",
@@ -190,5 +190,6 @@
  "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index f83f692..d3a230e 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -50,7 +50,7 @@
 	        "transaction_date": None,
 	        "conversion_rate": 1.0,
 	        "buying_price_list": None,
-	        "is_subcontracted": "Yes" / "No",
+	        "is_subcontracted": 0/1,
 	        "ignore_pricing_rule": 0/1
 	        "project": ""
 	        "set_warehouse": ""
@@ -124,7 +124,7 @@
 	if args.transaction_date and item.lead_time_days:
 		out.schedule_date = out.lead_time_date = add_days(args.transaction_date, item.lead_time_days)
 
-	if args.get("is_subcontracted") == "Yes":
+	if args.get("is_subcontracted"):
 		out.bom = args.get("bom") or get_default_bom(args.item_code)
 
 	get_gross_profit(out)
@@ -240,7 +240,7 @@
 		throw(_("Item {0} is a template, please select one of its variants").format(item.name))
 
 	elif args.transaction_type == "buying" and args.doctype != "Material Request":
-		if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != 1:
+		if args.get("is_subcontracted") and item.is_sub_contracted_item != 1:
 			throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
 
 
@@ -261,7 +261,7 @@
 	                "transaction_date": None,
 	                "conversion_rate": 1.0,
 	                "buying_price_list": None,
-	                "is_subcontracted": "Yes" / "No",
+	                "is_subcontracted": 0/1,
 	                "ignore_pricing_rule": 0/1
 	                "project": "",
 	                barcode: "",
diff --git a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
index ea27dd2..61927f5 100644
--- a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
+++ b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
@@ -68,7 +68,7 @@
 			options: [
 				{fieldname: 'stock_capacity', label: __('Capacity (Stock UOM)')},
 				{fieldname: 'percent_occupied', label: __('% Occupied')},
-				{fieldname: 'actual_qty', label: __('Balance Qty (Stock ')}
+				{fieldname: 'actual_qty', label: __('Balance Qty (Stock)')}
 			]
 		},
 		change: function(sort_by, sort_order) {
diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py
index a96ffef..ee151b7 100644
--- a/erpnext/stock/reorder_item.py
+++ b/erpnext/stock/reorder_item.py
@@ -246,8 +246,7 @@
 		_("Dear System Manager,")
 		+ "<br>"
 		+ _(
-			"An error occured for certain Items while creating Material Requests based on Re-order level. \
-		Please rectify these issues :"
+			"An error occured for certain Items while creating Material Requests based on Re-order level. Please rectify these issues :"
 		)
 		+ "<br>"
 	)
diff --git a/erpnext/stock/report/bom_search/bom_search.py b/erpnext/stock/report/bom_search/bom_search.py
index 3be87ab..56a65c3 100644
--- a/erpnext/stock/report/bom_search/bom_search.py
+++ b/erpnext/stock/report/bom_search/bom_search.py
@@ -3,6 +3,7 @@
 
 
 import frappe
+from frappe import _
 
 
 def execute(filters=None):
@@ -34,10 +35,10 @@
 	return [
 		{
 			"fieldname": "parent",
-			"label": "BOM",
+			"label": _("BOM"),
 			"width": 200,
 			"fieldtype": "Dynamic Link",
 			"options": "doctype",
 		},
-		{"fieldname": "doctype", "label": "Type", "width": 200, "fieldtype": "Data"},
+		{"fieldname": "doctype", "label": _("Type"), "width": 200, "fieldtype": "Data"},
 	], data
diff --git a/erpnext/stock/report/item_variant_details/item_variant_details.py b/erpnext/stock/report/item_variant_details/item_variant_details.py
index d1bf220..e3a2a65 100644
--- a/erpnext/stock/report/item_variant_details/item_variant_details.py
+++ b/erpnext/stock/report/item_variant_details/item_variant_details.py
@@ -71,7 +71,7 @@
 	columns = [
 		{
 			"fieldname": "variant_name",
-			"label": "Variant",
+			"label": _("Variant"),
 			"fieldtype": "Link",
 			"options": "Item",
 			"width": 200,
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
index 6cc9061..837c4a6 100644
--- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
@@ -4,6 +4,7 @@
 import json
 
 import frappe
+from frappe import _
 
 SLE_FIELDS = (
 	"name",
@@ -105,155 +106,155 @@
 		{
 			"fieldname": "name",
 			"fieldtype": "Link",
-			"label": "Stock Ledger Entry",
+			"label": _("Stock Ledger Entry"),
 			"options": "Stock Ledger Entry",
 		},
 		{
 			"fieldname": "posting_date",
 			"fieldtype": "Date",
-			"label": "Posting Date",
+			"label": _("Posting Date"),
 		},
 		{
 			"fieldname": "posting_time",
 			"fieldtype": "Time",
-			"label": "Posting Time",
+			"label": _("Posting Time"),
 		},
 		{
 			"fieldname": "creation",
 			"fieldtype": "Datetime",
-			"label": "Creation",
+			"label": _("Creation"),
 		},
 		{
 			"fieldname": "voucher_type",
 			"fieldtype": "Link",
-			"label": "Voucher Type",
+			"label": _("Voucher Type"),
 			"options": "DocType",
 		},
 		{
 			"fieldname": "voucher_no",
 			"fieldtype": "Dynamic Link",
-			"label": "Voucher No",
+			"label": _("Voucher No"),
 			"options": "voucher_type",
 		},
 		{
 			"fieldname": "batch_no",
 			"fieldtype": "Link",
-			"label": "Batch",
+			"label": _("Batch"),
 			"options": "Batch",
 		},
 		{
 			"fieldname": "use_batchwise_valuation",
 			"fieldtype": "Check",
-			"label": "Batchwise Valuation",
+			"label": _("Batchwise Valuation"),
 		},
 		{
 			"fieldname": "actual_qty",
 			"fieldtype": "Float",
-			"label": "Qty Change",
+			"label": _("Qty Change"),
 		},
 		{
 			"fieldname": "incoming_rate",
 			"fieldtype": "Float",
-			"label": "Incoming Rate",
+			"label": _("Incoming Rate"),
 		},
 		{
 			"fieldname": "consumption_rate",
 			"fieldtype": "Float",
-			"label": "Consumption Rate",
+			"label": _("Consumption Rate"),
 		},
 		{
 			"fieldname": "qty_after_transaction",
 			"fieldtype": "Float",
-			"label": "(A) Qty After Transaction",
+			"label": _("(A) Qty After Transaction"),
 		},
 		{
 			"fieldname": "expected_qty_after_transaction",
 			"fieldtype": "Float",
-			"label": "(B) Expected Qty After Transaction",
+			"label": _("(B) Expected Qty After Transaction"),
 		},
 		{
 			"fieldname": "difference_in_qty",
 			"fieldtype": "Float",
-			"label": "A - B",
+			"label": _("A - B"),
 		},
 		{
 			"fieldname": "stock_queue",
 			"fieldtype": "Data",
-			"label": "FIFO/LIFO Queue",
+			"label": _("FIFO/LIFO Queue"),
 		},
 		{
 			"fieldname": "fifo_queue_qty",
 			"fieldtype": "Float",
-			"label": "(C) Total qty in queue",
+			"label": _("(C) Total qty in queue"),
 		},
 		{
 			"fieldname": "fifo_qty_diff",
 			"fieldtype": "Float",
-			"label": "A - C",
+			"label": _("A - C"),
 		},
 		{
 			"fieldname": "stock_value",
 			"fieldtype": "Float",
-			"label": "(D) Balance Stock Value",
+			"label": _("(D) Balance Stock Value"),
 		},
 		{
 			"fieldname": "fifo_stock_value",
 			"fieldtype": "Float",
-			"label": "(E) Balance Stock Value in Queue",
+			"label": _("(E) Balance Stock Value in Queue"),
 		},
 		{
 			"fieldname": "fifo_value_diff",
 			"fieldtype": "Float",
-			"label": "D - E",
+			"label": _("D - E"),
 		},
 		{
 			"fieldname": "stock_value_difference",
 			"fieldtype": "Float",
-			"label": "(F) Stock Value Difference",
+			"label": _("(F) Stock Value Difference"),
 		},
 		{
 			"fieldname": "stock_value_from_diff",
 			"fieldtype": "Float",
-			"label": "Balance Stock Value using (F)",
+			"label": _("Balance Stock Value using (F)"),
 		},
 		{
 			"fieldname": "diff_value_diff",
 			"fieldtype": "Float",
-			"label": "K - D",
+			"label": _("K - D"),
 		},
 		{
 			"fieldname": "fifo_stock_diff",
 			"fieldtype": "Float",
-			"label": "(G) Stock Value difference (FIFO queue)",
+			"label": _("(G) Stock Value difference (FIFO queue)"),
 		},
 		{
 			"fieldname": "fifo_difference_diff",
 			"fieldtype": "Float",
-			"label": "F - G",
+			"label": _("F - G"),
 		},
 		{
 			"fieldname": "valuation_rate",
 			"fieldtype": "Float",
-			"label": "(H) Valuation Rate",
+			"label": _("(H) Valuation Rate"),
 		},
 		{
 			"fieldname": "fifo_valuation_rate",
 			"fieldtype": "Float",
-			"label": "(I) Valuation Rate as per FIFO",
+			"label": _("(I) Valuation Rate as per FIFO"),
 		},
 		{
 			"fieldname": "fifo_valuation_diff",
 			"fieldtype": "Float",
-			"label": "H - I",
+			"label": _("H - I"),
 		},
 		{
 			"fieldname": "balance_value_by_qty",
 			"fieldtype": "Float",
-			"label": "(J) Valuation = Value (D) ÷ Qty (A)",
+			"label": _("(J) Valuation = Value (D) ÷ Qty (A)"),
 		},
 		{
 			"fieldname": "valuation_diff",
 			"fieldtype": "Float",
-			"label": "H - J",
+			"label": _("H - J"),
 		},
 	]
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 967b2b2..3e0ddab 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -715,7 +715,7 @@
 			)
 
 		# Recalculate subcontracted item's rate in case of subcontracted purchase receipt/invoice
-		if frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_subcontracted") == "Yes":
+		if frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_subcontracted"):
 			doc = frappe.get_doc(sle.voucher_type, sle.voucher_no)
 			doc.update_valuation_rate(reset_outgoing_rate=False)
 			for d in doc.items + doc.supplied_items:
diff --git a/erpnext/stock/tests/test_valuation.py b/erpnext/stock/tests/test_valuation.py
index 506a666..e60c1ca 100644
--- a/erpnext/stock/tests/test_valuation.py
+++ b/erpnext/stock/tests/test_valuation.py
@@ -60,9 +60,9 @@
 		self.queue.remove_stock(1, 5)
 		self.assertEqual(self.queue, [[-1, 5]])
 
-		# XXX
-		self.queue.remove_stock(1, 10)
+		self.queue.remove_stock(1)
 		self.assertTotalQty(-2)
+		self.assertEqual(self.queue, [[-2, 5]])
 
 		self.queue.add_stock(2, 10)
 		self.assertTotalQty(0)
@@ -93,7 +93,7 @@
 		self.queue.remove_stock(3, 20)
 		self.assertEqual(self.queue, [[1, 10], [5, 20]])
 
-	def test_collapsing_of_queue(self):
+	def test_queue_with_unknown_rate(self):
 		self.queue.add_stock(1, 1)
 		self.queue.add_stock(1, 2)
 		self.queue.add_stock(1, 3)
@@ -102,8 +102,7 @@
 		self.assertTotalValue(10)
 
 		self.queue.remove_stock(3, 1)
-		# XXX
-		self.assertEqual(self.queue, [[1, 7]])
+		self.assertEqual(self.queue, [[1, 4]])
 
 	def test_rounding_off(self):
 		self.queue.add_stock(1.0, 1.0)
@@ -172,6 +171,32 @@
 			self.assertTotalQty(total_qty)
 			self.assertTotalValue(total_value)
 
+	@given(stock_queue_generator, st.floats(min_value=0.1, max_value=1e6))
+	def test_fifo_qty_value_nonneg_hypothesis_with_outgoing_rate(self, stock_queue, outgoing_rate):
+		self.queue = FIFOValuation([])
+		total_qty = 0.0
+		total_value = 0.0
+
+		for qty, rate in stock_queue:
+			# don't allow negative stock
+			if qty == 0 or total_qty + qty < 0 or abs(qty) < 0.1:
+				continue
+			if qty > 0:
+				self.queue.add_stock(qty, rate)
+				total_qty += qty
+				total_value += qty * rate
+			else:
+				qty = abs(qty)
+				consumed = self.queue.remove_stock(qty, outgoing_rate)
+				self.assertAlmostEqual(
+					qty, sum(q for q, _ in consumed), msg=f"incorrect consumption {consumed}"
+				)
+				total_qty -= qty
+				total_value -= sum(q * r for q, r in consumed)
+			self.assertTotalQty(total_qty)
+			self.assertTotalValue(total_value)
+			self.assertGreaterEqual(total_value, 0)
+
 
 class TestLIFOValuation(unittest.TestCase):
 	def setUp(self):
diff --git a/erpnext/stock/valuation.py b/erpnext/stock/valuation.py
index 648b218..35f4f12 100644
--- a/erpnext/stock/valuation.py
+++ b/erpnext/stock/valuation.py
@@ -60,9 +60,7 @@
 
 	# specifying the attributes to save resources
 	# ref: https://docs.python.org/3/reference/datamodel.html#slots
-	__slots__ = [
-		"queue",
-	]
+	__slots__ = ["queue"]
 
 	def __init__(self, state: Optional[List[StockBin]]):
 		self.queue: List[StockBin] = state if state is not None else []
@@ -123,15 +121,9 @@
 						index = idx
 						break
 
-				# If no entry found with outgoing rate, collapse queue
+				# If no entry found with outgoing rate, consume as per FIFO
 				if index is None:  # nosemgrep
-					new_stock_value = sum(d[QTY] * d[RATE] for d in self.queue) - qty * outgoing_rate
-					new_stock_qty = sum(d[QTY] for d in self.queue) - qty
-					self.queue = [
-						[new_stock_qty, new_stock_value / new_stock_qty if new_stock_qty > 0 else outgoing_rate]
-					]
-					consumed_bins.append([qty, outgoing_rate])
-					break
+					index = 0
 			else:
 				index = 0
 
@@ -172,9 +164,7 @@
 
 	# specifying the attributes to save resources
 	# ref: https://docs.python.org/3/reference/datamodel.html#slots
-	__slots__ = [
-		"stack",
-	]
+	__slots__ = ["stack"]
 
 	def __init__(self, state: Optional[List[StockBin]]):
 		self.stack: List[StockBin] = state if state is not None else []
diff --git a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py
index 5b51ef8..57fa7bf 100644
--- a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py
+++ b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.py
@@ -3,15 +3,16 @@
 
 
 import frappe
+from frappe import _
 
 
 def execute(filters=None):
 	columns = [
-		{"fieldname": "creation_date", "label": "Date", "fieldtype": "Date", "width": 300},
+		{"fieldname": "creation_date", "label": _("Date"), "fieldtype": "Date", "width": 300},
 		{
 			"fieldname": "first_response_time",
 			"fieldtype": "Duration",
-			"label": "First Response Time",
+			"label": _("First Response Time"),
 			"width": 300,
 		},
 	]
diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py
index 77a749e..3ed056f 100644
--- a/erpnext/templates/pages/product_search.py
+++ b/erpnext/templates/pages/product_search.py
@@ -1,6 +1,8 @@
 # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
+import json
+
 import frappe
 from frappe.utils import cint, cstr
 from redisearch import AutoCompleter, Client, Query
@@ -9,7 +11,7 @@
 	WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE,
 	WEBSITE_ITEM_INDEX,
 	WEBSITE_ITEM_NAME_AUTOCOMPLETE,
-	is_search_module_loaded,
+	is_redisearch_enabled,
 	make_key,
 )
 from erpnext.e_commerce.shopping_cart.product_info import set_product_info_for_website
@@ -74,8 +76,8 @@
 def product_search(query, limit=10, fuzzy_search=True):
 	search_results = {"from_redisearch": True, "results": []}
 
-	if not is_search_module_loaded():
-		# Redisearch module not loaded
+	if not is_redisearch_enabled():
+		# Redisearch module not enabled
 		search_results["from_redisearch"] = False
 		search_results["results"] = get_product_data(query, 0, limit)
 		return search_results
@@ -86,6 +88,8 @@
 	red = frappe.cache()
 	query = clean_up_query(query)
 
+	# TODO: Check perf/correctness with Suggestions & Query vs only Query
+	# TODO: Use Levenshtein Distance in Query (max=3)
 	ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=red)
 	client = Client(make_key(WEBSITE_ITEM_INDEX), conn=red)
 	suggestions = ac.get_suggestions(
@@ -121,8 +125,8 @@
 def get_category_suggestions(query):
 	search_results = {"results": []}
 
-	if not is_search_module_loaded():
-		# Redisearch module not loaded, query db
+	if not is_redisearch_enabled():
+		# Redisearch module not enabled, query db
 		categories = frappe.db.get_all(
 			"Item Group",
 			filters={"name": ["like", "%{0}%".format(query)], "show_in_website": 1},
@@ -135,8 +139,10 @@
 		return search_results
 
 	ac = AutoCompleter(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE), conn=frappe.cache())
-	suggestions = ac.get_suggestions(query, num=10)
+	suggestions = ac.get_suggestions(query, num=10, with_payloads=True)
 
-	search_results["results"] = [s.string for s in suggestions]
+	results = [json.loads(s.payload) for s in suggestions]
+
+	search_results["results"] = results
 
 	return search_results
diff --git a/erpnext/tests/test_subcontracting.py b/erpnext/tests/test_subcontracting.py
index 07291e8..bf12181 100644
--- a/erpnext/tests/test_subcontracting.py
+++ b/erpnext/tests/test_subcontracting.py
@@ -50,7 +50,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -112,7 +112,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -175,7 +175,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -239,7 +239,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -298,7 +298,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -363,7 +363,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -421,7 +421,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -492,7 +492,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -529,7 +529,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -609,7 +609,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -675,7 +675,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -751,7 +751,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
@@ -834,7 +834,7 @@
 
 		itemwise_details = make_stock_in_entry(rm_items=rm_items)
 		po = create_purchase_order(
-			rm_items=items, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC"
+			rm_items=items, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC"
 		)
 
 		for d in rm_items:
diff --git a/erpnext/utilities/doctype/video/video.js b/erpnext/utilities/doctype/video/video.js
index 9cb5a15..e6c6efb 100644
--- a/erpnext/utilities/doctype/video/video.js
+++ b/erpnext/utilities/doctype/video/video.js
@@ -4,7 +4,7 @@
 frappe.ui.form.on('Video', {
 	refresh: function (frm) {
 		frm.events.toggle_youtube_statistics_section(frm);
-		frm.add_custom_button("Watch Video", () => frappe.help.show_video(frm.doc.url, frm.doc.title));
+		frm.add_custom_button(__("Watch Video"), () => frappe.help.show_video(frm.doc.url, frm.doc.title));
 	},
 
 	toggle_youtube_statistics_section: (frm) => {
diff --git a/erpnext/utilities/report/youtube_interactions/youtube_interactions.py b/erpnext/utilities/report/youtube_interactions/youtube_interactions.py
index a65a75f..a2cb4e8 100644
--- a/erpnext/utilities/report/youtube_interactions/youtube_interactions.py
+++ b/erpnext/utilities/report/youtube_interactions/youtube_interactions.py
@@ -67,7 +67,7 @@
 		{
 			"value": total_views,
 			"indicator": "Blue",
-			"label": "Total Views",
+			"label": _("Total Views"),
 			"datatype": "Float",
 		}
 	]
diff --git a/requirements.txt b/requirements.txt
index 39591ca..657054f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 # frappe   # https://github.com/frappe/frappe is installed during bench-init
 gocardless-pro~=1.22.0
 googlemaps
-pandas~=1.1.5
+pandas>=1.1.5,<2.0.0
 plaid-python~=7.2.1
 pycountry~=20.7.3
 PyGithub~=1.55
@@ -10,4 +10,4 @@
 taxjar~=1.9.2
 tweepy~=3.10.0
 Unidecode~=1.2.0
-redisearch==2.0.0
\ No newline at end of file
+redisearch~=2.1.0