Merge pull request #32491 from ruthra-kumar/performance_issue_on_migrate_remarks_patch

refactor: remove duplicate entries on remarks migration patch
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 1a572d9..78c3526 100644
--- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -99,7 +99,7 @@
 			.where(loan_disbursement.clearance_date.isnull())
 			.where(loan_disbursement.disbursement_account.isin([self.bank_account, self.account]))
 			.orderby(loan_disbursement.disbursement_date)
-			.orderby(loan_disbursement.name, frappe.qb.desc)
+			.orderby(loan_disbursement.name, order=frappe.qb.desc)
 		).run(as_dict=1)
 
 		loan_repayment = frappe.qb.DocType("Loan Repayment")
@@ -126,7 +126,9 @@
 		if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
 			query = query.where((loan_repayment.repay_from_salary == 0))
 
-		query = query.orderby(loan_repayment.posting_date).orderby(loan_repayment.name, frappe.qb.desc)
+		query = query.orderby(loan_repayment.posting_date).orderby(
+			loan_repayment.name, order=frappe.qb.desc
+		)
 
 		loan_repayments = query.run(as_dict=True)
 
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index 2ee356a..2f3516e 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -186,8 +186,10 @@
   {
    "fetch_from": "bank_account.bank",
    "fieldname": "bank",
-   "fieldtype": "Read Only",
-   "label": "Bank"
+   "fieldtype": "Link",
+   "label": "Bank",
+   "options": "Bank",
+   "read_only": 1
   },
   {
    "fetch_from": "bank_account.bank_account_no",
@@ -366,10 +368,11 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-09-18 12:24:14.178853",
+ "modified": "2022-09-30 16:19:43.680025",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Request",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
@@ -401,5 +404,6 @@
   }
  ],
  "sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
index b126d57..6f8b382 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
@@ -1553,7 +1553,7 @@
  "icon": "fa fa-file-text",
  "is_submittable": 1,
  "links": [],
- "modified": "2022-03-22 13:00:24.166684",
+ "modified": "2022-09-27 13:00:24.166684",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Invoice",
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 6e3a076..fbe0ef3 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -239,14 +239,14 @@
 					frappe.bold(d.warehouse),
 					frappe.bold(d.qty),
 				)
-				if flt(available_stock) <= 0:
+				if is_stock_item and flt(available_stock) <= 0:
 					frappe.throw(
 						_("Row #{}: Item Code: {} is not available under warehouse {}.").format(
 							d.idx, item_code, warehouse
 						),
 						title=_("Item Unavailable"),
 					)
-				elif flt(available_stock) < flt(d.qty):
+				elif is_stock_item and flt(available_stock) < flt(d.qty):
 					frappe.throw(
 						_(
 							"Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}."
@@ -632,11 +632,12 @@
 		pos_sales_qty = get_pos_reserved_qty(item_code, warehouse)
 		return bin_qty - pos_sales_qty, is_stock_item
 	else:
-		is_stock_item = False
+		is_stock_item = True
 		if frappe.db.exists("Product Bundle", item_code):
 			return get_bundle_availability(item_code, warehouse), is_stock_item
 		else:
-			# Is a service item
+			is_stock_item = False
+			# Is a service item or non_stock item
 			return 0, is_stock_item
 
 
@@ -650,7 +651,9 @@
 		available_qty = item_bin_qty - item_pos_reserved_qty
 
 		max_available_bundles = available_qty / item.qty
-		if bundle_bin_qty > max_available_bundles:
+		if bundle_bin_qty > max_available_bundles and frappe.get_value(
+			"Item", item.item_code, "is_stock_item"
+		):
 			bundle_bin_qty = max_available_bundles
 
 	pos_sales_qty = get_pos_reserved_qty(bundle_item_code, warehouse)
@@ -740,3 +743,7 @@
 		]:
 			payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company)
 			append_payment(payment_mode[0])
+
+
+def on_doctype_update():
+	frappe.db.add_index("POS Invoice", ["return_against"])
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 986fc03..3020e6d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -98,7 +98,6 @@
   "section_break_44",
   "apply_discount_on",
   "base_discount_amount",
-  "additional_discount_account",
   "column_break_46",
   "additional_discount_percentage",
   "discount_amount",
@@ -1388,12 +1387,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "additional_discount_account",
-   "fieldtype": "Link",
-   "label": "Additional Discount Account",
-   "options": "Account"
-  },
-  {
    "default": "0",
    "fieldname": "ignore_default_payment_terms_template",
    "fieldtype": "Check",
@@ -1445,7 +1438,7 @@
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-09-13 23:39:54.525037",
+ "modified": "2022-09-27 11:07:55.766844",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index d185300..2b633cb 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -669,9 +669,6 @@
 
 		exchange_rate_map, net_rate_map = get_purchase_document_details(self)
 
-		enable_discount_accounting = cint(
-			frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-		)
 		provisional_accounting_for_non_stock_items = cint(
 			frappe.db.get_value(
 				"Company", self.company, "enable_provisional_accounting_for_non_stock_items"
@@ -1159,9 +1156,6 @@
 	def make_tax_gl_entries(self, gl_entries):
 		# tax table gl entries
 		valuation_tax = {}
-		enable_discount_accounting = cint(
-			frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-		)
 
 		for tax in self.get("taxes"):
 			amount, base_amount = self.get_tax_amounts(tax, None)
@@ -1249,15 +1243,6 @@
 						)
 					)
 
-	@property
-	def enable_discount_accounting(self):
-		if not hasattr(self, "_enable_discount_accounting"):
-			self._enable_discount_accounting = cint(
-				frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
-			)
-
-		return self._enable_discount_accounting
-
 	def make_internal_transfer_gl_entries(self, gl_entries):
 		if self.is_internal_transfer() and flt(self.base_total_taxes_and_charges):
 			account_currency = get_account_currency(self.unrealized_profit_loss_account)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 0a4f25b..f901257 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1543,6 +1543,37 @@
 		pi.save()
 		self.assertEqual(pi.items[0].conversion_factor, 1000)
 
+	def test_batch_expiry_for_purchase_invoice(self):
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+
+		item = self.make_item(
+			"_Test Batch Item For Return Check",
+			{
+				"is_purchase_item": 1,
+				"is_stock_item": 1,
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "TBIRC.#####",
+			},
+		)
+
+		pi = make_purchase_invoice(
+			qty=1,
+			item_code=item.name,
+			update_stock=True,
+		)
+
+		pi.load_from_db()
+		batch_no = pi.items[0].batch_no
+		self.assertTrue(batch_no)
+
+		frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(nowdate(), -1))
+
+		return_pi = make_return_doc(pi.doctype, pi.name)
+		return_pi.save().submit()
+
+		self.assertTrue(return_pi.docstatus == 1)
+
 
 def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
 	gl_entries = frappe.db.sql(
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 7fa2fe2..fca7e3a 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -74,7 +74,6 @@
   "manufacturer_part_no",
   "accounting",
   "expense_account",
-  "discount_account",
   "col_break5",
   "is_fixed_asset",
   "asset_location",
@@ -861,12 +860,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "discount_account",
-   "fieldtype": "Link",
-   "label": "Discount Account",
-   "options": "Account"
-  },
-  {
    "fieldname": "product_bundle",
    "fieldtype": "Link",
    "label": "Product Bundle",
@@ -877,7 +870,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-06-17 05:31:10.520171",
+ "modified": "2022-09-27 10:54:23.980713",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e51938b..afd5a59 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -22,9 +22,12 @@
 from erpnext.accounts.party import get_due_date, get_party_account, get_party_details
 from erpnext.accounts.utils import get_account_currency
 from erpnext.assets.doctype.asset.depreciation import (
+	depreciate_asset,
 	get_disposal_account_and_cost_center,
 	get_gl_entries_on_asset_disposal,
 	get_gl_entries_on_asset_regain,
+	reset_depreciation_schedule,
+	reverse_depreciation_entry_made_after_disposal,
 )
 from erpnext.controllers.accounts_controller import validate_account_head
 from erpnext.controllers.selling_controller import SellingController
@@ -1081,23 +1084,25 @@
 
 					if self.is_return:
 						fixed_asset_gl_entries = get_gl_entries_on_asset_regain(
-							asset, item.base_net_amount, item.finance_book
+							asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name")
 						)
 						asset.db_set("disposal_date", None)
 
 						if asset.calculate_depreciation:
-							self.reverse_depreciation_entry_made_after_disposal(asset)
-							self.reset_depreciation_schedule(asset)
+							posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date")
+							reverse_depreciation_entry_made_after_disposal(asset, posting_date)
+							reset_depreciation_schedule(asset, self.posting_date)
 
 					else:
+						if asset.calculate_depreciation:
+							depreciate_asset(asset, self.posting_date)
+							asset.reload()
+
 						fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
-							asset, item.base_net_amount, item.finance_book
+							asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name")
 						)
 						asset.db_set("disposal_date", self.posting_date)
 
-						if asset.calculate_depreciation:
-							self.depreciate_asset(asset)
-
 					for gle in fixed_asset_gl_entries:
 						gle["against"] = self.customer
 						gl_entries.append(self.get_gl_dict(gle, item=item))
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 782e08e..ce44ae3 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -8,7 +8,7 @@
 from frappe.model.dynamic_links import get_dynamic_link_map
 from frappe.model.naming import make_autoname
 from frappe.tests.utils import change_settings
-from frappe.utils import add_days, flt, getdate, nowdate
+from frappe.utils import add_days, flt, getdate, nowdate, today
 
 import erpnext
 from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@@ -3196,6 +3196,37 @@
 			"Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled
 		)
 
+	def test_batch_expiry_for_sales_invoice_return(self):
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		item = make_item(
+			"_Test Batch Item For Return Check",
+			{
+				"is_purchase_item": 1,
+				"is_stock_item": 1,
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "TBIRC.#####",
+			},
+		)
+
+		pr = make_purchase_receipt(qty=1, item_code=item.name)
+
+		batch_no = pr.items[0].batch_no
+		si = create_sales_invoice(qty=1, item_code=item.name, update_stock=1, batch_no=batch_no)
+
+		si.load_from_db()
+		batch_no = si.items[0].batch_no
+		self.assertTrue(batch_no)
+
+		frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+		return_si = make_return_doc(si.doctype, si.name)
+		return_si.save().submit()
+
+		self.assertTrue(return_si.docstatus == 1)
+
 
 def get_sales_invoice_for_e_invoice():
 	si = make_sales_invoice_for_ewaybill()
@@ -3289,6 +3320,7 @@
 			"serial_no": args.serial_no,
 			"conversion_factor": 1,
 			"incoming_rate": args.incoming_rate or 0,
+			"batch_no": args.batch_no or None,
 		},
 	)
 
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 0b5df9e..84c2c9a 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -335,6 +335,9 @@
 		"party": ["in", parties],
 	}
 
+	if party_type == "Customer":
+		filters.update({"against_voucher": ["is", "not set"]})
+
 	if company:
 		filters["company"] = company
 	if from_date and to_date:
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index e77e828..82f38da 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -237,9 +237,9 @@
 		or filters.get("party")
 		or filters.get("group_by") in ["Group by Account", "Group by Party"]
 	):
-		conditions.append("posting_date >=%(from_date)s")
+		conditions.append("(posting_date >=%(from_date)s or is_opening = 'Yes')")
 
-	conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')")
+	conditions.append("(posting_date <=%(to_date)s)")
 
 	if filters.get("project"):
 		conditions.append("project in %(project)s")
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index 33bd3c7..06e3c61 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -370,7 +370,7 @@
 				where parent=`tabSales Invoice`.name
 					and ifnull(`tab{table}`.{field}, '') = %({field})s)"""
 
-	conditions += get_sales_invoice_item_field_condition("mode_of_payments", "Sales Invoice Payment")
+	conditions += get_sales_invoice_item_field_condition("mode_of_payment", "Sales Invoice Payment")
 	conditions += get_sales_invoice_item_field_condition("cost_center")
 	conditions += get_sales_invoice_item_field_condition("warehouse")
 	conditions += get_sales_invoice_item_field_condition("brand")
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index 6bd08ad..6d2cd8e 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -172,6 +172,7 @@
 	query_filters = {
 		"company": filters.company,
 		"from_date": filters.from_date,
+		"to_date": filters.to_date,
 		"report_type": report_type,
 		"year_start_date": filters.year_start_date,
 		"project": filters.project,
@@ -200,7 +201,7 @@
 		where
 			company=%(company)s
 			{additional_conditions}
-			and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
+			and (posting_date < %(from_date)s or (ifnull(is_opening, 'No') = 'Yes' and posting_date <= %(to_date)s))
 			and account in (select name from `tabAccount` where report_type=%(report_type)s)
 			and is_cancelled = 0
 		group by account""".format(
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
index 5fcfdff..ee22348 100644
--- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
@@ -104,12 +104,17 @@
 		where company=%(company)s
 			and is_cancelled=0
 			and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
-			and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
+			and (posting_date < %(from_date)s or (ifnull(is_opening, 'No') = 'Yes' and posting_date <= %(to_date)s))
 			{account_filter}
 		group by party""".format(
 			account_filter=account_filter
 		),
-		{"company": filters.company, "from_date": filters.from_date, "party_type": filters.party_type},
+		{
+			"company": filters.company,
+			"from_date": filters.from_date,
+			"to_date": filters.to_date,
+			"party_type": filters.party_type,
+		},
 		as_dict=True,
 	)
 
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index c5eb7d8..9ede678 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -86,7 +86,7 @@
 				)
 			)
 
-		query = query.orderby(FY.year_start_date, Order.desc)
+		query = query.orderby(FY.year_start_date, order=Order.desc)
 		fiscal_years = query.run(as_dict=True)
 
 		frappe.cache().hset("fiscal_years", company, fiscal_years)
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index a43a16c..5512d41 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -230,7 +230,7 @@
 				datasets: [{
 					color: 'green',
 					values: asset_values,
-					formatted: asset_values.map(d => d.toFixed(2))
+					formatted: asset_values.map(d => d?.toFixed(2))
 				}]
 			},
 			type: 'line'
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 991df4e..f0505ff 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -388,7 +388,7 @@
    "in_standard_filter": 1,
    "label": "Status",
    "no_copy": 1,
-   "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt",
+   "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt\nCapitalized\nDecapitalized",
    "read_only": 1
   },
   {
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 8ac7ed6..ca6be9b 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -828,7 +828,9 @@
 
 
 def update_maintenance_status():
-	assets = frappe.get_all("Asset", filters={"docstatus": 1, "maintenance_required": 1})
+	assets = frappe.get_all(
+		"Asset", filters={"docstatus": 1, "maintenance_required": 1, "disposal_date": ("is", "not set")}
+	)
 
 	for asset in assets:
 		asset = frappe.get_doc("Asset", asset.name)
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 7438638..9794170 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -4,11 +4,12 @@
 
 import frappe
 from frappe import _
-from frappe.utils import cint, flt, getdate, today
+from frappe.utils import add_months, cint, flt, getdate, nowdate, today
 
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
 	get_checks_for_pl_and_bs_accounts,
 )
+from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
 
 
 def post_depreciation_entries(date=None, commit=True):
@@ -196,6 +197,11 @@
 			_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status)
 		)
 
+	date = today()
+
+	depreciate_asset(asset, date)
+	asset.reload()
+
 	depreciation_series = frappe.get_cached_value(
 		"Company", asset.company, "series_for_depreciation_entry"
 	)
@@ -203,7 +209,7 @@
 	je = frappe.new_doc("Journal Entry")
 	je.voucher_type = "Journal Entry"
 	je.naming_series = depreciation_series
-	je.posting_date = today()
+	je.posting_date = date
 	je.company = asset.company
 	je.remark = "Scrap Entry for asset {0}".format(asset_name)
 
@@ -214,7 +220,7 @@
 	je.flags.ignore_permissions = True
 	je.submit()
 
-	frappe.db.set_value("Asset", asset_name, "disposal_date", today())
+	frappe.db.set_value("Asset", asset_name, "disposal_date", date)
 	frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
 	asset.set_status("Scrapped")
 
@@ -225,6 +231,9 @@
 def restore_asset(asset_name):
 	asset = frappe.get_doc("Asset", asset_name)
 
+	reverse_depreciation_entry_made_after_disposal(asset, asset.disposal_date)
+	reset_depreciation_schedule(asset, asset.disposal_date)
+
 	je = asset.journal_entry_for_scrap
 
 	asset.db_set("disposal_date", None)
@@ -235,7 +244,94 @@
 	asset.set_status()
 
 
-def get_gl_entries_on_asset_regain(asset, selling_amount=0, finance_book=None):
+def depreciate_asset(asset, date):
+	asset.flags.ignore_validate_update_after_submit = True
+	asset.prepare_depreciation_data(date_of_disposal=date)
+	asset.save()
+
+	make_depreciation_entry(asset.name, date)
+
+
+def reset_depreciation_schedule(asset, date):
+	asset.flags.ignore_validate_update_after_submit = True
+
+	# recreate original depreciation schedule of the asset
+	asset.prepare_depreciation_data(date_of_return=date)
+
+	modify_depreciation_schedule_for_asset_repairs(asset)
+	asset.save()
+
+
+def modify_depreciation_schedule_for_asset_repairs(asset):
+	asset_repairs = frappe.get_all(
+		"Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"]
+	)
+
+	for repair in asset_repairs:
+		if repair.increase_in_asset_life:
+			asset_repair = frappe.get_doc("Asset Repair", repair.name)
+			asset_repair.modify_depreciation_schedule()
+			asset.prepare_depreciation_data()
+
+
+def reverse_depreciation_entry_made_after_disposal(asset, date):
+	row = -1
+	finance_book = asset.get("schedules")[0].get("finance_book")
+	for schedule in asset.get("schedules"):
+		if schedule.finance_book != finance_book:
+			row = 0
+			finance_book = schedule.finance_book
+		else:
+			row += 1
+
+		if schedule.schedule_date == date:
+			if not disposal_was_made_on_original_schedule_date(
+				asset, schedule, row, date
+			) or disposal_happens_in_the_future(date):
+
+				reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
+				reverse_journal_entry.posting_date = nowdate()
+				frappe.flags.is_reverse_depr_entry = True
+				reverse_journal_entry.submit()
+
+				frappe.flags.is_reverse_depr_entry = False
+				asset.flags.ignore_validate_update_after_submit = True
+				schedule.journal_entry = None
+				depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry)
+				asset.finance_books[0].value_after_depreciation += depreciation_amount
+				asset.save()
+
+
+def get_depreciation_amount_in_je(journal_entry):
+	if journal_entry.accounts[0].debit_in_account_currency:
+		return journal_entry.accounts[0].debit_in_account_currency
+	else:
+		return journal_entry.accounts[0].credit_in_account_currency
+
+
+# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
+def disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_disposal):
+	for finance_book in asset.get("finance_books"):
+		if schedule.finance_book == finance_book.finance_book:
+			orginal_schedule_date = add_months(
+				finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation)
+			)
+
+			if orginal_schedule_date == posting_date_of_disposal:
+				return True
+	return False
+
+
+def disposal_happens_in_the_future(posting_date_of_disposal):
+	if posting_date_of_disposal > getdate():
+		return True
+
+	return False
+
+
+def get_gl_entries_on_asset_regain(
+	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+):
 	(
 		fixed_asset_account,
 		asset,
@@ -247,28 +343,45 @@
 	) = get_asset_details(asset, finance_book)
 
 	gl_entries = [
-		{
-			"account": fixed_asset_account,
-			"debit_in_account_currency": asset.gross_purchase_amount,
-			"debit": asset.gross_purchase_amount,
-			"cost_center": depreciation_cost_center,
-		},
-		{
-			"account": accumulated_depr_account,
-			"credit_in_account_currency": accumulated_depr_amount,
-			"credit": accumulated_depr_amount,
-			"cost_center": depreciation_cost_center,
-		},
+		asset.get_gl_dict(
+			{
+				"account": fixed_asset_account,
+				"debit_in_account_currency": asset.gross_purchase_amount,
+				"debit": asset.gross_purchase_amount,
+				"cost_center": depreciation_cost_center,
+				"posting_date": getdate(),
+			},
+			item=asset,
+		),
+		asset.get_gl_dict(
+			{
+				"account": accumulated_depr_account,
+				"credit_in_account_currency": accumulated_depr_amount,
+				"credit": accumulated_depr_amount,
+				"cost_center": depreciation_cost_center,
+				"posting_date": getdate(),
+			},
+			item=asset,
+		),
 	]
 
 	profit_amount = abs(flt(value_after_depreciation)) - abs(flt(selling_amount))
 	if profit_amount:
-		get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center)
+		get_profit_gl_entries(
+			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+		)
+
+	if voucher_type and voucher_no:
+		for entry in gl_entries:
+			entry["voucher_type"] = voucher_type
+			entry["voucher_no"] = voucher_no
 
 	return gl_entries
 
 
-def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None):
+def get_gl_entries_on_asset_disposal(
+	asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+):
 	(
 		fixed_asset_account,
 		asset,
@@ -280,23 +393,38 @@
 	) = get_asset_details(asset, finance_book)
 
 	gl_entries = [
-		{
-			"account": fixed_asset_account,
-			"credit_in_account_currency": asset.gross_purchase_amount,
-			"credit": asset.gross_purchase_amount,
-			"cost_center": depreciation_cost_center,
-		},
-		{
-			"account": accumulated_depr_account,
-			"debit_in_account_currency": accumulated_depr_amount,
-			"debit": accumulated_depr_amount,
-			"cost_center": depreciation_cost_center,
-		},
+		asset.get_gl_dict(
+			{
+				"account": fixed_asset_account,
+				"credit_in_account_currency": asset.gross_purchase_amount,
+				"credit": asset.gross_purchase_amount,
+				"cost_center": depreciation_cost_center,
+				"posting_date": getdate(),
+			},
+			item=asset,
+		),
+		asset.get_gl_dict(
+			{
+				"account": accumulated_depr_account,
+				"debit_in_account_currency": accumulated_depr_amount,
+				"debit": accumulated_depr_amount,
+				"cost_center": depreciation_cost_center,
+				"posting_date": getdate(),
+			},
+			item=asset,
+		),
 	]
 
 	profit_amount = flt(selling_amount) - flt(value_after_depreciation)
 	if profit_amount:
-		get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center)
+		get_profit_gl_entries(
+			asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+		)
+
+	if voucher_type and voucher_no:
+		for entry in gl_entries:
+			entry["voucher_type"] = voucher_type
+			entry["voucher_no"] = voucher_no
 
 	return gl_entries
 
@@ -333,15 +461,21 @@
 	)
 
 
-def get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center):
+def get_profit_gl_entries(
+	asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+):
 	debit_or_credit = "debit" if profit_amount < 0 else "credit"
 	gl_entries.append(
-		{
-			"account": disposal_account,
-			"cost_center": depreciation_cost_center,
-			debit_or_credit: abs(profit_amount),
-			debit_or_credit + "_in_account_currency": abs(profit_amount),
-		}
+		asset.get_gl_dict(
+			{
+				"account": disposal_account,
+				"cost_center": depreciation_cost_center,
+				debit_or_credit: abs(profit_amount),
+				debit_or_credit + "_in_account_currency": abs(profit_amount),
+				"posting_date": getdate(),
+			},
+			item=asset,
+		)
 	)
 
 
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index e7af9bd..370b13b 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -4,10 +4,23 @@
 import unittest
 
 import frappe
-from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate
+from frappe.utils import (
+	add_days,
+	add_months,
+	cstr,
+	flt,
+	get_first_day,
+	get_last_day,
+	getdate,
+	nowdate,
+)
 
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
-from erpnext.assets.doctype.asset.asset import make_sales_invoice, split_asset
+from erpnext.assets.doctype.asset.asset import (
+	make_sales_invoice,
+	split_asset,
+	update_maintenance_status,
+)
 from erpnext.assets.doctype.asset.depreciation import (
 	post_depreciation_entries,
 	restore_asset,
@@ -178,28 +191,48 @@
 		self.assertEqual(doc.items[0].is_fixed_asset, 1)
 
 	def test_scrap_asset(self):
+		date = nowdate()
+		purchase_date = add_months(get_first_day(date), -2)
+
 		asset = create_asset(
 			calculate_depreciation=1,
-			available_for_use_date="2020-01-01",
-			purchase_date="2020-01-01",
+			available_for_use_date=purchase_date,
+			purchase_date=purchase_date,
 			expected_value_after_useful_life=10000,
 			total_number_of_depreciations=10,
 			frequency_of_depreciation=1,
 			submit=1,
 		)
 
-		post_depreciation_entries(date=add_months("2020-01-01", 4))
+		post_depreciation_entries(date=add_months(purchase_date, 2))
+		asset.load_from_db()
+
+		accumulated_depr_amount = flt(
+			asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
+			asset.precision("gross_purchase_amount"),
+		)
+		self.assertEquals(accumulated_depr_amount, 18000.0)
 
 		scrap_asset(asset.name)
-
 		asset.load_from_db()
+
+		accumulated_depr_amount = flt(
+			asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
+			asset.precision("gross_purchase_amount"),
+		)
+		pro_rata_amount, _, _ = asset.get_pro_rata_amt(
+			asset.finance_books[0], 9000, add_months(get_last_day(purchase_date), 1), date
+		)
+		pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount"))
+		self.assertEquals(accumulated_depr_amount, 18000.00 + pro_rata_amount)
+
 		self.assertEqual(asset.status, "Scrapped")
 		self.assertTrue(asset.journal_entry_for_scrap)
 
 		expected_gle = (
-			("_Test Accumulated Depreciations - _TC", 36000.0, 0.0),
+			("_Test Accumulated Depreciations - _TC", 18000.0 + pro_rata_amount, 0.0),
 			("_Test Fixed Asset - _TC", 0.0, 100000.0),
-			("_Test Gain/Loss on Asset Disposal - _TC", 64000.0, 0.0),
+			("_Test Gain/Loss on Asset Disposal - _TC", 82000.0 - pro_rata_amount, 0.0),
 		)
 
 		gle = frappe.db.sql(
@@ -216,7 +249,64 @@
 		self.assertFalse(asset.journal_entry_for_scrap)
 		self.assertEqual(asset.status, "Partially Depreciated")
 
+		accumulated_depr_amount = flt(
+			asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
+			asset.precision("gross_purchase_amount"),
+		)
+		this_month_depr_amount = 9000.0 if get_last_day(date) == date else 0
+
+		self.assertEquals(accumulated_depr_amount, 18000.0 + this_month_depr_amount)
+
 	def test_gle_made_by_asset_sale(self):
+		date = nowdate()
+		purchase_date = add_months(get_first_day(date), -2)
+
+		asset = create_asset(
+			calculate_depreciation=1,
+			available_for_use_date=purchase_date,
+			purchase_date=purchase_date,
+			expected_value_after_useful_life=10000,
+			total_number_of_depreciations=10,
+			frequency_of_depreciation=1,
+			submit=1,
+		)
+
+		post_depreciation_entries(date=add_months(purchase_date, 2))
+
+		si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company")
+		si.customer = "_Test Customer"
+		si.due_date = nowdate()
+		si.get("items")[0].rate = 25000
+		si.insert()
+		si.submit()
+
+		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
+
+		pro_rata_amount, _, _ = asset.get_pro_rata_amt(
+			asset.finance_books[0], 9000, add_months(get_last_day(purchase_date), 1), date
+		)
+		pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount"))
+
+		expected_gle = (
+			("_Test Accumulated Depreciations - _TC", 18000.0 + pro_rata_amount, 0.0),
+			("_Test Fixed Asset - _TC", 0.0, 100000.0),
+			("_Test Gain/Loss on Asset Disposal - _TC", 57000.0 - pro_rata_amount, 0.0),
+			("Debtors - _TC", 25000.0, 0.0),
+		)
+
+		gle = frappe.db.sql(
+			"""select account, debit, credit from `tabGL Entry`
+			where voucher_type='Sales Invoice' and voucher_no = %s
+			order by account""",
+			si.name,
+		)
+
+		self.assertSequenceEqual(gle, expected_gle)
+
+		si.cancel()
+		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
+
+	def test_asset_with_maintenance_required_status_after_sale(self):
 		asset = create_asset(
 			calculate_depreciation=1,
 			available_for_use_date="2020-06-06",
@@ -224,6 +314,7 @@
 			expected_value_after_useful_life=10000,
 			total_number_of_depreciations=3,
 			frequency_of_depreciation=10,
+			maintenance_required=1,
 			depreciation_start_date="2020-12-31",
 			submit=1,
 		)
@@ -239,24 +330,9 @@
 
 		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
 
-		expected_gle = (
-			("_Test Accumulated Depreciations - _TC", 20490.2, 0.0),
-			("_Test Fixed Asset - _TC", 0.0, 100000.0),
-			("_Test Gain/Loss on Asset Disposal - _TC", 54509.8, 0.0),
-			("Debtors - _TC", 25000.0, 0.0),
-		)
+		update_maintenance_status()
 
-		gle = frappe.db.sql(
-			"""select account, debit, credit from `tabGL Entry`
-			where voucher_type='Sales Invoice' and voucher_no = %s
-			order by account""",
-			si.name,
-		)
-
-		self.assertSequenceEqual(gle, expected_gle)
-
-		si.cancel()
-		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
+		self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
 
 	def test_asset_splitting(self):
 		asset = create_asset(
@@ -1376,6 +1452,7 @@
 			"number_of_depreciations_booked": args.number_of_depreciations_booked or 0,
 			"gross_purchase_amount": args.gross_purchase_amount or 100000,
 			"purchase_receipt_amount": args.purchase_receipt_amount or 100000,
+			"maintenance_required": args.maintenance_required or 0,
 			"warehouse": args.warehouse or "_Test Warehouse - _TC",
 			"available_for_use_date": args.available_for_use_date or "2020-06-06",
 			"location": args.location or "Test Location",
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 2e6f0ad..08355f0 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -12,8 +12,11 @@
 
 import erpnext
 from erpnext.assets.doctype.asset.depreciation import (
+	depreciate_asset,
 	get_gl_entries_on_asset_disposal,
 	get_value_after_depreciation_on_disposal_date,
+	reset_depreciation_schedule,
+	reverse_depreciation_entry_made_after_disposal,
 )
 from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
 from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import (
@@ -424,11 +427,15 @@
 			asset = self.get_asset(item)
 
 			if asset.calculate_depreciation:
-				self.depreciate_asset(asset)
+				depreciate_asset(asset, self.posting_date)
 				asset.reload()
 
 			fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
-				asset, item.asset_value, item.get("finance_book") or self.get("finance_book")
+				asset,
+				item.asset_value,
+				item.get("finance_book") or self.get("finance_book"),
+				self.get("doctype"),
+				self.get("name"),
 			)
 
 			asset.db_set("disposal_date", self.posting_date)
@@ -516,8 +523,8 @@
 				self.set_consumed_asset_status(asset)
 
 				if asset.calculate_depreciation:
-					self.reverse_depreciation_entry_made_after_disposal(asset)
-					self.reset_depreciation_schedule(asset)
+					reverse_depreciation_entry_made_after_disposal(asset, self.posting_date)
+					reset_depreciation_schedule(asset, self.posting_date)
 
 	def get_asset(self, item):
 		asset = frappe.get_doc("Asset", item.asset)
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index aad2607..28158a3 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -20,7 +20,6 @@
   "maintain_same_rate",
   "allow_multiple_items",
   "bill_for_rejected_quantity_in_purchase_invoice",
-  "enable_discount_accounting",
   "subcontract",
   "backflush_raw_materials_of_subcontract_based_on",
   "column_break_11",
@@ -134,13 +133,6 @@
   {
    "fieldname": "column_break_12",
    "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
-   "fieldname": "enable_discount_accounting",
-   "fieldtype": "Check",
-   "label": "Enable Discount Accounting for Buying"
   }
  ],
  "icon": "fa fa-cog",
@@ -148,7 +140,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2022-09-01 18:01:34.994657",
+ "modified": "2022-09-27 10:50:27.050252",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py
index 7b18cdb..be1ebde 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.py
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.py
@@ -5,15 +5,10 @@
 
 
 import frappe
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
 from frappe.model.document import Document
-from frappe.utils import cint
 
 
 class BuyingSettings(Document):
-	def on_update(self):
-		self.toggle_discount_accounting_fields()
-
 	def validate(self):
 		for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
 			frappe.db.set_default(key, self.get(key, ""))
@@ -26,60 +21,3 @@
 			self.get("supp_master_name") == "Naming Series",
 			hide_name_field=False,
 		)
-
-	def toggle_discount_accounting_fields(self):
-		enable_discount_accounting = cint(self.enable_discount_accounting)
-
-		make_property_setter(
-			"Purchase Invoice Item",
-			"discount_account",
-			"hidden",
-			not (enable_discount_accounting),
-			"Check",
-			validate_fields_for_doctype=False,
-		)
-		if enable_discount_accounting:
-			make_property_setter(
-				"Purchase Invoice Item",
-				"discount_account",
-				"mandatory_depends_on",
-				"eval: doc.discount_amount",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-		else:
-			make_property_setter(
-				"Purchase Invoice Item",
-				"discount_account",
-				"mandatory_depends_on",
-				"",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-
-		make_property_setter(
-			"Purchase Invoice",
-			"additional_discount_account",
-			"hidden",
-			not (enable_discount_accounting),
-			"Check",
-			validate_fields_for_doctype=False,
-		)
-		if enable_discount_accounting:
-			make_property_setter(
-				"Purchase Invoice",
-				"additional_discount_account",
-				"mandatory_depends_on",
-				"eval: doc.discount_amount",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
-		else:
-			make_property_setter(
-				"Purchase Invoice",
-				"additional_discount_account",
-				"mandatory_depends_on",
-				"",
-				"Code",
-				validate_fields_for_doctype=False,
-			)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index fc99d77..ddf81ca 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -33,6 +33,7 @@
 		frm.set_query("fg_item", "items", function() {
 			return {
 				filters: {
+					'is_stock_item': 1,
 					'is_sub_contracted_item': 1,
 					'default_bom': ['!=', '']
 				}
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 dbdc62e..d089473 100644
--- a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py
+++ b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py
@@ -53,4 +53,5 @@
 		},
 		"type": "line",
 		"lineOptions": {"regionFill": 1},
+		"fieldtype": "Currency",
 	}
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 8686cb5..22291a3 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -38,7 +38,6 @@
 	validate_party_frozen_disabled,
 )
 from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year
-from erpnext.assets.doctype.asset.depreciation import make_depreciation_entry
 from erpnext.buying.utils import update_last_purchase_rate
 from erpnext.controllers.print_settings import (
 	set_print_templates_for_item_table,
@@ -1891,88 +1890,6 @@
 				_("Select finance book for the item {0} at row {1}").format(item.item_code, item.idx)
 			)
 
-	def depreciate_asset(self, asset):
-		asset.flags.ignore_validate_update_after_submit = True
-		asset.prepare_depreciation_data(date_of_disposal=self.posting_date)
-		asset.save()
-
-		make_depreciation_entry(asset.name, self.posting_date)
-
-	def reset_depreciation_schedule(self, asset):
-		asset.flags.ignore_validate_update_after_submit = True
-
-		# recreate original depreciation schedule of the asset
-		asset.prepare_depreciation_data(date_of_return=self.posting_date)
-
-		self.modify_depreciation_schedule_for_asset_repairs(asset)
-		asset.save()
-
-	def modify_depreciation_schedule_for_asset_repairs(self, asset):
-		asset_repairs = frappe.get_all(
-			"Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"]
-		)
-
-		for repair in asset_repairs:
-			if repair.increase_in_asset_life:
-				asset_repair = frappe.get_doc("Asset Repair", repair.name)
-				asset_repair.modify_depreciation_schedule()
-				asset.prepare_depreciation_data()
-
-	def reverse_depreciation_entry_made_after_disposal(self, asset):
-		from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
-
-		posting_date_of_original_disposal = self.get_posting_date_of_disposal_entry()
-
-		row = -1
-		finance_book = asset.get("schedules")[0].get("finance_book")
-		for schedule in asset.get("schedules"):
-			if schedule.finance_book != finance_book:
-				row = 0
-				finance_book = schedule.finance_book
-			else:
-				row += 1
-
-			if schedule.schedule_date == posting_date_of_original_disposal:
-				if not self.disposal_was_made_on_original_schedule_date(
-					asset, schedule, row, posting_date_of_original_disposal
-				) or self.disposal_happens_in_the_future(posting_date_of_original_disposal):
-
-					reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
-					reverse_journal_entry.posting_date = nowdate()
-					frappe.flags.is_reverse_depr_entry = True
-					reverse_journal_entry.submit()
-
-					frappe.flags.is_reverse_depr_entry = False
-					asset.flags.ignore_validate_update_after_submit = True
-					schedule.journal_entry = None
-					asset.save()
-
-	def get_posting_date_of_disposal_entry(self):
-		if self.doctype == "Sales Invoice" and self.return_against:
-			return frappe.db.get_value("Sales Invoice", self.return_against, "posting_date")
-		else:
-			return self.posting_date
-
-	# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
-	def disposal_was_made_on_original_schedule_date(
-		self, asset, schedule, row, posting_date_of_disposal
-	):
-		for finance_book in asset.get("finance_books"):
-			if schedule.finance_book == finance_book.finance_book:
-				orginal_schedule_date = add_months(
-					finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation)
-				)
-
-				if orginal_schedule_date == posting_date_of_disposal:
-					return True
-		return False
-
-	def disposal_happens_in_the_future(self, posting_date_of_disposal):
-		if posting_date_of_disposal > getdate():
-			return True
-
-		return False
-
 
 @frappe.whitelist()
 def get_tax_rate(account_head):
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 4f8b5c7..8eae0a0 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -212,21 +212,15 @@
 	meta = frappe.get_meta(doctype, cached=True)
 	searchfields = meta.get_search_fields()
 
-	# these are handled separately
-	ignored_search_fields = ("item_name", "description")
-	for ignored_field in ignored_search_fields:
-		if ignored_field in searchfields:
-			searchfields.remove(ignored_field)
-
 	columns = ""
-	extra_searchfields = [
-		field
-		for field in searchfields
-		if not field in ["name", "item_group", "description", "item_name"]
-	]
+	extra_searchfields = [field for field in searchfields if not field in ["name", "description"]]
 
 	if extra_searchfields:
-		columns = ", " + ", ".join(extra_searchfields)
+		columns += ", " + ", ".join(extra_searchfields)
+
+	if "description" in searchfields:
+		columns += """, if(length(tabItem.description) > 40, \
+			concat(substr(tabItem.description, 1, 40), "..."), description) as description"""
 
 	searchfields = searchfields + [
 		field
@@ -266,12 +260,10 @@
 	if frappe.db.count(doctype, cache=True) < 50000:
 		# scan description only if items are less than 50000
 		description_cond = "or tabItem.description LIKE %(txt)s"
+
 	return frappe.db.sql(
 		"""select
-			tabItem.name, tabItem.item_name, tabItem.item_group,
-		if(length(tabItem.description) > 40, \
-			concat(substr(tabItem.description, 1, 40), "..."), description) as description
-		{columns}
+			tabItem.name {columns}
 		from tabItem
 		where tabItem.docstatus < 2
 			and tabItem.disabled=0
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 202a880..aa4468c 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -69,9 +69,18 @@
 
 	def validate_items(self):
 		for item in self.items:
-			if not frappe.get_value("Item", item.item_code, "is_sub_contracted_item"):
+			is_stock_item, is_sub_contracted_item = frappe.get_value(
+				"Item", item.item_code, ["is_stock_item", "is_sub_contracted_item"]
+			)
+
+			if not is_stock_item:
+				msg = f"Item {item.item_name} must be a stock item."
+				frappe.throw(_(msg))
+
+			if not is_sub_contracted_item:
 				msg = f"Item {item.item_name} must be a subcontracted item."
 				frappe.throw(_(msg))
+
 			if item.bom:
 				bom = frappe.get_doc("BOM", item.bom)
 				if not bom.is_active:
@@ -841,7 +850,7 @@
 			for fg_item_code in fg_item_code_list:
 				for rm_item in rm_items:
 
-					if rm_item.get("main_item_code") or rm_item.get("item_code") == fg_item_code:
+					if rm_item.get("main_item_code") == fg_item_code or rm_item.get("item_code") == fg_item_code:
 						rm_item_code = rm_item.get("rm_item_code")
 
 						items_dict = {
diff --git a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
index 116db2f..7cd1710 100644
--- a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
+++ b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
@@ -44,7 +44,7 @@
 		},
 		{
 			fieldname: "opportunity_source",
-			label: __("Oppoturnity Source"),
+			label: __("Opportunity Source"),
 			fieldtype: "Link",
 			options: "Lead Source",
 		},
@@ -62,4 +62,4 @@
 			default: frappe.defaults.get_user_default("Company")
 		}
 	]
-};
\ No newline at end of file
+};
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index a08feb4..b8f51f8 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -391,12 +391,12 @@
 		"erpnext.crm.doctype.social_media_post.social_media_post.process_scheduled_social_media_posts",
 	],
 	"hourly": [
-		"erpnext.accounts.doctype.subscription.subscription.process_all",
 		"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.automatic_synchronization",
 		"erpnext.projects.doctype.project.project.hourly_reminder",
 		"erpnext.projects.doctype.project.project.collect_project_status",
 	],
 	"hourly_long": [
+		"erpnext.accounts.doctype.subscription.subscription.process_all",
 		"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries",
 		"erpnext.bulk_transaction.doctype.bulk_transaction_log.bulk_transaction_log.retry_failing_transaction",
 	],
@@ -508,6 +508,7 @@
 	"Landed Cost Item",
 	"Asset Value Adjustment",
 	"Asset Repair",
+	"Asset Capitalization",
 	"Loyalty Program",
 	"Stock Reconciliation",
 	"POS Profile",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 70637d3..ff84991 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -1019,7 +1019,6 @@
 			where
 				bom_item.docstatus < 2
 				and bom.name = %(bom)s
-				and ifnull(item.has_variants, 0) = 0
 				and item.is_stock_item in (1, {is_stock_item})
 				{where_conditions}
 				group by item_code, stock_uom
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 20f1503..f3640b9 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -557,37 +557,52 @@
 
 			if(!frm.doc.skip_transfer){
 				// If "Material Consumption is check in Manufacturing Settings, allow Material Consumption
-				if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))
-				&& frm.doc.status != 'Stopped') {
-					frm.has_finish_btn = true;
+				if (flt(doc.material_transferred_for_manufacturing) > 0 && frm.doc.status != 'Stopped') {
+					if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))) {
+						frm.has_finish_btn = true;
 
-					if (frm.doc.__onload && frm.doc.__onload.material_consumption == 1) {
-						// Only show "Material Consumption" when required_qty > consumed_qty
-						var counter = 0;
-						var tbl = frm.doc.required_items || [];
-						var tbl_lenght = tbl.length;
-						for (var i = 0, len = tbl_lenght; i < len; i++) {
-							let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
-							if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
-								counter += 1;
+						if (frm.doc.__onload && frm.doc.__onload.material_consumption == 1) {
+							// Only show "Material Consumption" when required_qty > consumed_qty
+							var counter = 0;
+							var tbl = frm.doc.required_items || [];
+							var tbl_lenght = tbl.length;
+							for (var i = 0, len = tbl_lenght; i < len; i++) {
+								let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
+								if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
+									counter += 1;
+								}
+							}
+							if (counter > 0) {
+								var consumption_btn = frm.add_custom_button(__('Material Consumption'), function() {
+									const backflush_raw_materials_based_on = frm.doc.__onload.backflush_raw_materials_based_on;
+									erpnext.work_order.make_consumption_se(frm, backflush_raw_materials_based_on);
+								});
+								consumption_btn.addClass('btn-primary');
 							}
 						}
-						if (counter > 0) {
-							var consumption_btn = frm.add_custom_button(__('Material Consumption'), function() {
-								const backflush_raw_materials_based_on = frm.doc.__onload.backflush_raw_materials_based_on;
-								erpnext.work_order.make_consumption_se(frm, backflush_raw_materials_based_on);
-							});
-							consumption_btn.addClass('btn-primary');
+
+						var finish_btn = frm.add_custom_button(__('Finish'), function() {
+							erpnext.work_order.make_se(frm, 'Manufacture');
+						});
+
+						if(doc.material_transferred_for_manufacturing>=doc.qty) {
+							// all materials transferred for manufacturing, make this primary
+							finish_btn.addClass('btn-primary');
 						}
-					}
+					} else {
+						frappe.db.get_doc("Manufacturing Settings").then((doc) => {
+							let allowance_percentage = doc.overproduction_percentage_for_work_order;
 
-					var finish_btn = frm.add_custom_button(__('Finish'), function() {
-						erpnext.work_order.make_se(frm, 'Manufacture');
-					});
+							if (allowance_percentage > 0) {
+								let allowed_qty = frm.doc.qty + ((allowance_percentage / 100) * frm.doc.qty);
 
-					if(doc.material_transferred_for_manufacturing>=doc.qty) {
-						// all materials transferred for manufacturing, make this primary
-						finish_btn.addClass('btn-primary');
+								if ((flt(doc.produced_qty) < allowed_qty)) {
+									frm.add_custom_button(__('Finish'), function() {
+										erpnext.work_order.make_se(frm, 'Manufacture');
+									});
+								}
+							}
+						});
 					}
 				}
 			} else {
diff --git a/erpnext/manufacturing/report/job_card_summary/job_card_summary.py b/erpnext/manufacturing/report/job_card_summary/job_card_summary.py
index 5083b73..63c2d97 100644
--- a/erpnext/manufacturing/report/job_card_summary/job_card_summary.py
+++ b/erpnext/manufacturing/report/job_card_summary/job_card_summary.py
@@ -85,8 +85,8 @@
 		open_job_cards.append(periodic_data.get("Open").get(d))
 		completed.append(periodic_data.get("Completed").get(d))
 
-	datasets.append({"name": "Open", "values": open_job_cards})
-	datasets.append({"name": "Completed", "values": completed})
+	datasets.append({"name": _("Open"), "values": open_job_cards})
+	datasets.append({"name": _("Completed"), "values": completed})
 
 	chart = {"data": {"labels": labels, "datasets": datasets}, "type": "bar"}
 
diff --git a/erpnext/manufacturing/report/work_order_summary/work_order_summary.py b/erpnext/manufacturing/report/work_order_summary/work_order_summary.py
index 2368bfd..41ffcbb 100644
--- a/erpnext/manufacturing/report/work_order_summary/work_order_summary.py
+++ b/erpnext/manufacturing/report/work_order_summary/work_order_summary.py
@@ -83,6 +83,7 @@
 	for d in data:
 		status_wise_data[d.status] += 1
 
+	labels = [_(label) for label in labels]
 	values = [status_wise_data[label] for label in labels]
 
 	chart = {
@@ -95,7 +96,7 @@
 
 
 def get_chart_based_on_age(data):
-	labels = ["0-30 Days", "30-60 Days", "60-90 Days", "90 Above"]
+	labels = [_("0-30 Days"), _("30-60 Days"), _("60-90 Days"), _("90 Above")]
 
 	age_wise_data = {"0-30 Days": 0, "30-60 Days": 0, "60-90 Days": 0, "90 Above": 0}
 
@@ -135,8 +136,8 @@
 		pending.append(periodic_data.get("Pending").get(d))
 		completed.append(periodic_data.get("Completed").get(d))
 
-	datasets.append({"name": "Pending", "values": pending})
-	datasets.append({"name": "Completed", "values": completed})
+	datasets.append({"name": _("Pending"), "values": pending})
+	datasets.append({"name": _("Completed"), "values": completed})
 
 	chart = {
 		"data": {"labels": labels, "datasets": datasets},
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 2a0ca8c..fc63f12 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -315,3 +315,4 @@
 erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes
 erpnext.patches.v14_0.fix_subcontracting_receipt_gl_entries
 erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger
+erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization
diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py
index a1d40b7..0bd3fcd 100644
--- a/erpnext/patches/v13_0/update_old_loans.py
+++ b/erpnext/patches/v13_0/update_old_loans.py
@@ -100,6 +100,7 @@
 					"mode_of_payment": loan.mode_of_payment,
 					"loan_account": loan.loan_account,
 					"payment_account": loan.payment_account,
+					"disbursement_account": loan.payment_account,
 					"interest_income_account": loan.interest_income_account,
 					"penalty_income_account": loan.penalty_income_account,
 				},
@@ -190,6 +191,7 @@
 	loan_type_doc.company = loan.company
 	loan_type_doc.mode_of_payment = loan.mode_of_payment
 	loan_type_doc.payment_account = loan.payment_account
+	loan_type_doc.disbursement_account = loan.payment_account
 	loan_type_doc.loan_account = loan.loan_account
 	loan_type_doc.interest_income_account = loan.interest_income_account
 	loan_type_doc.penalty_income_account = penalty_account
diff --git a/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py b/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py
new file mode 100644
index 0000000..09e20a9
--- /dev/null
+++ b/erpnext/patches/v14_0/create_accounting_dimensions_for_asset_capitalization.py
@@ -0,0 +1,31 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
+
+
+def execute():
+	accounting_dimensions = frappe.db.get_all(
+		"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
+	)
+
+	if not accounting_dimensions:
+		return
+
+	doctype = "Asset Capitalization"
+
+	for d in accounting_dimensions:
+		field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
+
+		if field:
+			continue
+
+		df = {
+			"fieldname": d.fieldname,
+			"label": d.label,
+			"fieldtype": "Link",
+			"options": d.document_type,
+			"insert_after": "accounting_dimensions_section",
+		}
+
+		create_custom_field(doctype, df, ignore_validate=True)
+
+	frappe.clear_cache(doctype=doctype)
diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py
index 606c0c2..7a35fd2 100644
--- a/erpnext/projects/report/project_summary/project_summary.py
+++ b/erpnext/projects/report/project_summary/project_summary.py
@@ -91,9 +91,9 @@
 		"data": {
 			"labels": labels[:30],
 			"datasets": [
-				{"name": "Overdue", "values": overdue[:30]},
-				{"name": "Completed", "values": completed[:30]},
-				{"name": "Total Tasks", "values": total[:30]},
+				{"name": _("Overdue"), "values": overdue[:30]},
+				{"name": _("Completed"), "values": completed[:30]},
+				{"name": _("Total Tasks"), "values": total[:30]},
 			],
 		},
 		"type": "bar",
diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js
index b643cca..1c3f43e 100644
--- a/erpnext/public/js/help_links.js
+++ b/erpnext/public/js/help_links.js
@@ -671,7 +671,7 @@
 		label: "Item Valuation",
 		url:
 			docsUrl +
-			"user/manual/en/stock/articles/item-valuation-fifo-and-moving-average",
+			"user/manual/en/stock/articles/calculation-of-valuation-rate-in-fifo-and-moving-average",
 	},
 ];
 
diff --git a/erpnext/public/js/utils/barcode_scanner.js b/erpnext/public/js/utils/barcode_scanner.js
index a6bff2c..83b108b 100644
--- a/erpnext/public/js/utils/barcode_scanner.js
+++ b/erpnext/public/js/utils/barcode_scanner.js
@@ -21,6 +21,11 @@
 		this.items_table_name = opts.items_table_name || "items";
 		this.items_table = this.frm.doc[this.items_table_name];
 
+		// optional sound name to play when scan either fails or passes.
+		// see https://frappeframework.com/docs/v14/user/en/python-api/hooks#sounds
+		this.success_sound = opts.play_success_sound;
+		this.fail_sound = opts.play_fail_sound;
+
 		// any API that takes `search_value` as input and returns dictionary as follows
 		// {
 		//     item_code: "HORSESHOE", // present if any item was found
@@ -54,19 +59,24 @@
 					if (!data || Object.keys(data).length === 0) {
 						this.show_alert(__("Cannot find Item with this Barcode"), "red");
 						this.clean_up();
+						this.play_fail_sound();
 						reject();
 						return;
 					}
 
 					me.update_table(data).then(row => {
-						row ? resolve(row) : reject();
+						this.play_success_sound();
+						resolve(row);
+					}).catch(() => {
+						this.play_fail_sound();
+						reject();
 					});
 				});
 		});
 	}
 
 	update_table(data) {
-		return new Promise(resolve => {
+		return new Promise((resolve, reject) => {
 			let cur_grid = this.frm.fields_dict[this.items_table_name].grid;
 
 			const {item_code, barcode, batch_no, serial_no, uom} = data;
@@ -77,6 +87,7 @@
 				if (this.dont_allow_new_row) {
 					this.show_alert(__("Maximum quantity scanned for item {0}.", [item_code]), "red");
 					this.clean_up();
+					reject();
 					return;
 				}
 
@@ -88,6 +99,7 @@
 
 			if (this.is_duplicate_serial_no(row, serial_no)) {
 				this.clean_up();
+				reject();
 				return;
 			}
 
@@ -219,6 +231,14 @@
 		return this.items_table.find((d) => !d.item_code);
 	}
 
+	play_success_sound() {
+		this.success_sound && frappe.utils.play_sound(this.success_sound);
+	}
+
+	play_fail_sound() {
+		this.fail_sound && frappe.utils.play_sound(this.fail_sound);
+	}
+
 	clean_up() {
 		this.scan_barcode_field.set_value("");
 		refresh_field(this.items_table_name);
diff --git a/erpnext/public/scss/order-page.scss b/erpnext/public/scss/order-page.scss
new file mode 100644
index 0000000..6f5fe5d
--- /dev/null
+++ b/erpnext/public/scss/order-page.scss
@@ -0,0 +1,115 @@
+#page-order {
+    .main-column {
+        .page-content-wrapper {
+
+            .breadcrumb-container {
+                @media screen and (min-width: 567px) {
+                    padding-left: var(--padding-sm);
+                }
+            }
+
+            .container.my-4 {
+                background-color: var(--fg-color);
+
+                @media screen and (min-width: 567px) {
+                    padding: 1.25rem 1.5rem;
+                    border-radius: var(--border-radius-md);
+                    box-shadow: var(--card-shadow);
+                }
+            }
+        }
+    }
+}
+
+.indicator-container {
+    @media screen and (max-width: 567px) {
+        padding-bottom: 0.8rem;
+    }
+}
+
+.order-items {
+    padding: 1.5rem 0;
+    border-bottom: 1px solid var(--border-color);
+    color: var(--gray-700);
+
+    @media screen and (max-width: 567px) {
+        align-items: flex-start !important;
+    }
+    .col-2 {
+        @media screen and (max-width: 567px) {
+            flex: auto;
+            max-width: 28%;
+        }
+    }
+
+    .order-item-name {
+        font-size: var(--text-base);
+        font-weight: 500;
+    }
+
+    .btn:focus,
+    .btn:hover {
+        background-color: var(--control-bg);
+    }
+
+
+    .col-6 {
+        @media screen and (max-width: 567px) {
+            max-width: 100%;
+        }
+
+        &.order-item-name {
+            font-size: var(--text-base);
+        }
+    }
+}
+
+.item-grand-total {
+    font-size: var(--text-base);
+}
+
+.list-item-name,
+.item-total,
+.order-container,
+.order-qty {
+    font-size: var(--text-md);
+}
+
+.d-s-n {
+    @media screen and (max-width: 567px) {
+        display: none;
+    }
+}
+
+.d-l-n {
+    @media screen and (min-width: 567px) {
+        display: none;
+    }
+}
+
+.border-btm {
+    border-bottom: 1px solid var(--border-color);
+}
+
+.order-taxes {
+    display: flex;
+
+    @media screen and (min-width: 567px) {
+        justify-content: flex-end;
+    }
+
+    .col-4 {
+        padding-right: 0;
+
+        .col-8 {
+            padding-left: 0;
+            padding-right: 0;
+        }
+
+        @media screen and (max-width: 567px) {
+            padding-left: 0;
+            flex: auto;
+            max-width: 100%;
+        }
+    }
+}
\ No newline at end of file
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 9ea8416..b5e97f1 100644
--- a/erpnext/public/scss/website.scss
+++ b/erpnext/public/scss/website.scss
@@ -1,3 +1,4 @@
+@import './order-page';
 
 .filter-options {
 	max-height: 300px;
@@ -32,19 +33,29 @@
 	height: 24px;
 }
 
-.website-list .result {
-	margin-top: 2rem;
-}
+.website-list {
+	background-color: var(--fg-color);
+	padding: 0 var(--padding-lg);
+	border-radius: var(--border-radius-md);
 
-.result {
-	border-bottom: 1px solid var(--border-color);
+	@media screen and (max-width: 567px) {
+		margin-left: -2rem;
+	}
+
+	&.result {
+		border-bottom: 1px solid var(--border-color);
+	}
 }
 
 .transaction-list-item {
 	padding: 1rem 0;
-	border-top: 1px solid var(--border-color);
+	border-bottom: 1px solid var(--border-color);
 	position: relative;
 
+	&:only-child, &:last-child {
+		border: 0;
+	}
+
 	a.transaction-item-link {
 		position: absolute;
 		top: 0;
@@ -68,3 +79,13 @@
 		line-height: 1.3;
 	}
 }
+
+.list-item-name, .item-total {
+	font-size: var(--font-size-sm);
+}
+
+.items-preview {
+	@media screen and (max-width: 567px) {
+		margin-top: 1rem;
+	}
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index da7576e..24375d8 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -660,7 +660,7 @@
 			} else {
 				return;
 			}
-		} else if (available_qty < qty_needed) {
+		} else if (is_stock_item && available_qty < qty_needed) {
 			frappe.throw({
 				message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.', [bold_item_code, bold_warehouse, bold_available_qty]),
 				indicator: 'orange'
@@ -694,7 +694,7 @@
 			callback(res) {
 				if (!me.item_stock_map[item_code])
 					me.item_stock_map[item_code] = {};
-				me.item_stock_map[item_code][warehouse] = res.message[0];
+				me.item_stock_map[item_code][warehouse] = res.message;
 			}
 		});
 	}
diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js
index b75ffb2..f9b5bb2 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_details.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_details.js
@@ -242,13 +242,14 @@
 				if (this.value) {
 					me.events.form_updated(me.current_item, 'warehouse', this.value).then(() => {
 						me.item_stock_map = me.events.get_item_stock_map();
-						const available_qty = me.item_stock_map[me.item_row.item_code] && me.item_stock_map[me.item_row.item_code][this.value];
+						const available_qty = me.item_stock_map[me.item_row.item_code][this.value][0];
+						const is_stock_item = Boolean(me.item_stock_map[me.item_row.item_code][this.value][1]);
 						if (available_qty === undefined) {
 							me.events.get_available_stock(me.item_row.item_code, this.value).then(() => {
 								// item stock map is updated now reset warehouse
 								me.warehouse_control.set_value(this.value);
 							})
-						} else if (available_qty === 0) {
+						} else if (available_qty === 0 && is_stock_item) {
 							me.warehouse_control.set_value('');
 							const bold_item_code = me.item_row.item_code.bold();
 							const bold_warehouse = this.value.bold();
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 6bcab73..1b9f168 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -6,7 +6,7 @@
 
 import frappe
 from frappe.tests.utils import FrappeTestCase
-from frappe.utils import cstr, flt, nowdate, nowtime
+from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today
 
 from erpnext.accounts.doctype.account.test_account import get_inventory_account
 from erpnext.accounts.utils import get_balance_on
@@ -1091,6 +1091,36 @@
 			frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype})
 		)
 
+	def test_batch_expiry_for_delivery_note(self):
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+		from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+
+		item = make_item(
+			"_Test Batch Item For Return Check",
+			{
+				"is_purchase_item": 1,
+				"is_stock_item": 1,
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "TBIRC.#####",
+			},
+		)
+
+		pi = make_purchase_receipt(qty=1, item_code=item.name)
+
+		dn = create_delivery_note(qty=1, item_code=item.name, batch_no=pi.items[0].batch_no)
+
+		dn.load_from_db()
+		batch_no = dn.items[0].batch_no
+		self.assertTrue(batch_no)
+
+		frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+		return_dn = make_return_doc(dn.doctype, dn.name)
+		return_dn.save().submit()
+
+		self.assertTrue(return_dn.docstatus == 1)
+
 
 def create_delivery_note(**args):
 	dn = frappe.new_doc("Delivery Note")
@@ -1117,6 +1147,7 @@
 			"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
 			"cost_center": args.cost_center or "_Test Cost Center - _TC",
 			"serial_no": args.serial_no,
+			"batch_no": args.batch_no or None,
 			"target_warehouse": args.target_warehouse,
 		},
 	)
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 7e1476d..e61f0f5 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -10,6 +10,31 @@
 		frm.add_fetch('attribute', 'to_range', 'to_range');
 		frm.add_fetch('attribute', 'increment', 'increment');
 		frm.add_fetch('tax_type', 'tax_rate', 'tax_rate');
+
+		frm.make_methods = {
+			'Sales Order': () => {
+				open_form(frm, "Sales Order", "Sales Order Item", "items");
+			},
+			'Delivery Note': () => {
+				open_form(frm, "Delivery Note", "Delivery Note Item", "items");
+			},
+			'Sales Invoice': () => {
+				open_form(frm, "Sales Invoice", "Sales Invoice Item", "items");
+			},
+			'Purchase Order': () => {
+				open_form(frm, "Purchase Order", "Purchase Order Item", "items");
+			},
+			'Purchase Receipt': () => {
+				open_form(frm, "Purchase Receipt", "Purchase Receipt Item", "items");
+			},
+			'Purchase Invoice': () => {
+				open_form(frm, "Purchase Invoice", "Purchase Invoice Item", "items");
+			},
+			'Material Request': () => {
+				open_form(frm, "Material Request", "Material Request Item", "items");
+			},
+		};
+
 	},
 	onload: function(frm) {
 		erpnext.item.setup_queries(frm);
@@ -858,3 +883,17 @@
 
 
 ];
+
+function open_form(frm, doctype, child_doctype, parentfield) {
+	frappe.model.with_doctype(doctype, () => {
+		let new_doc = frappe.model.get_new_doc(doctype);
+
+		let new_child_doc = frappe.model.add_child(new_doc, child_doctype, parentfield);
+		new_child_doc.item_code = frm.doc.name;
+		new_child_doc.item_name = frm.doc.item_name;
+		new_child_doc.uom = frm.doc.stock_uom;
+		new_child_doc.description = frm.doc.description;
+
+		frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
+	});
+}
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 143fe40..c8bb1b9 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -937,17 +937,21 @@
 				"Purchase Order Item",
 				"Material Request Item",
 				"Product Bundle",
+				"BOM",
 			]
 
 		for doctype in linked_doctypes:
 			filters = {"item_code": self.name, "docstatus": 1}
 
-			if doctype == "Product Bundle":
-				filters = {"new_item_code": self.name}
+			if doctype in ("Product Bundle", "BOM"):
+				if doctype == "Product Bundle":
+					filters = {"new_item_code": self.name}
+					fieldname = "new_item_code as docname"
+				else:
+					filters = {"item": self.name, "docstatus": 1}
+					fieldname = "name as docname"
 
-				if linked_doc := frappe.db.get_value(
-					doctype, filters, ["new_item_code as docname"], as_dict=True
-				):
+				if linked_doc := frappe.db.get_value(doctype, filters, fieldname, as_dict=True):
 					return linked_doc.update({"doctype": doctype})
 
 			elif doctype in (
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 1cee553..e35c8bf 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -5,6 +5,7 @@
 import json
 
 import frappe
+from frappe.custom.doctype.property_setter.property_setter import make_property_setter
 from frappe.test_runner import make_test_objects
 from frappe.tests.utils import FrappeTestCase, change_settings
 from frappe.utils import add_days, today
@@ -816,6 +817,30 @@
 		item.reload()
 		self.assertEqual(item.is_stock_item, 1)
 
+	def test_serach_fields_for_item(self):
+		from erpnext.controllers.queries import item_query
+
+		make_property_setter("Item", None, "search_fields", "item_name", "Data", for_doctype="Doctype")
+
+		item = make_item(properties={"item_name": "Test Item", "description": "Test Description"})
+		data = item_query(
+			"Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True
+		)
+		self.assertEqual(data[0].name, item.name)
+		self.assertEqual(data[0].item_name, item.item_name)
+		self.assertTrue("description" not in data[0])
+
+		make_property_setter(
+			"Item", None, "search_fields", "item_name, description", "Data", for_doctype="Doctype"
+		)
+		data = item_query(
+			"Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True
+		)
+		self.assertEqual(data[0].name, item.name)
+		self.assertEqual(data[0].item_name, item.item_name)
+		self.assertEqual(data[0].description, item.description)
+		self.assertTrue("description" in data[0])
+
 
 def set_item_variant_settings(fields):
 	doc = frappe.get_doc("Item Variant Settings")
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index adddb41..9c1c7e5 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -183,7 +183,7 @@
 				frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx))
 			item_code = item.item_code
 			reference = item.sales_order_item or item.material_request_item
-			key = (item_code, item.uom, item.warehouse, reference)
+			key = (item_code, item.uom, item.warehouse, item.batch_no, reference)
 
 			item.idx = None
 			item.name = None
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index b77c3a5..6269724 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -1241,6 +1241,37 @@
 
 		self.assertEqual(query[0].value, 0)
 
+	def test_batch_expiry_for_purchase_receipt(self):
+		from erpnext.controllers.sales_and_purchase_return import make_return_doc
+
+		item = make_item(
+			"_Test Batch Item For Return Check",
+			{
+				"is_purchase_item": 1,
+				"is_stock_item": 1,
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "TBIRC.#####",
+			},
+		)
+
+		pi = make_purchase_receipt(
+			qty=1,
+			item_code=item.name,
+			update_stock=True,
+		)
+
+		pi.load_from_db()
+		batch_no = pi.items[0].batch_no
+		self.assertTrue(batch_no)
+
+		frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+		return_pi = make_return_doc(pi.doctype, pi.name)
+		return_pi.save().submit()
+
+		self.assertTrue(return_pi.docstatus == 1)
+
 
 def prepare_data_for_internal_transfer():
 	from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 738ac33..8bcd772 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -1073,8 +1073,8 @@
 			# No work order could mean independent Manufacture entry, if so skip validation
 			if self.work_order and self.fg_completed_qty > allowed_qty:
 				frappe.throw(
-					_("For quantity {0} should not be greater than work order quantity {1}").format(
-						flt(self.fg_completed_qty), wo_qty
+					_("For quantity {0} should not be greater than allowed quantity {1}").format(
+						flt(self.fg_completed_qty), allowed_qty
 					)
 				)
 
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 329cd7d..c64370d 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -153,6 +153,11 @@
 
 	def validate_batch(self):
 		if self.batch_no and self.voucher_type != "Stock Entry":
+			if (self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0) or (
+				self.voucher_type in ["Delivery Note", "Sales Invoice"] and self.actual_qty > 0
+			):
+				return
+
 			expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date")
 			if expiry_date:
 				if getdate(self.posting_date) > getdate(expiry_date):
diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py
index 7a1b8c0..0ec4e1c 100644
--- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py
+++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py
@@ -45,4 +45,5 @@
 			"datasets": [{"name": _("Total Delivered Amount"), "values": datapoints}],
 		},
 		"type": "bar",
+		"fieldtype": "Currency",
 	}
diff --git a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
index 23e3c8a..df01b14 100644
--- a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
+++ b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
@@ -4,6 +4,8 @@
 
 import frappe
 from frappe import _
+from frappe.query_builder import Field
+from frappe.query_builder.functions import Min, Timestamp
 from frappe.utils import add_days, getdate, today
 
 import erpnext
@@ -28,7 +30,7 @@
 def get_unsync_date(filters):
 	date = filters.from_date
 	if not date:
-		date = frappe.db.sql(""" SELECT min(posting_date) from `tabStock Ledger Entry`""")
+		date = (frappe.qb.from_("Stock Ledger Entry").select(Min(Field("posting_date")))).run()
 		date = date[0][0]
 
 	if not date:
@@ -54,22 +56,27 @@
 	result = []
 
 	voucher_wise_dict = {}
-	data = frappe.db.sql(
-		"""
-			SELECT
-				name, posting_date, posting_time, voucher_type, voucher_no,
-				stock_value_difference, stock_value, warehouse, item_code
-			FROM
-				`tabStock Ledger Entry`
-			WHERE
-				posting_date
-				= %s and company = %s
-				and is_cancelled = 0
-			ORDER BY timestamp(posting_date, posting_time) asc, creation asc
-		""",
-		(from_date, report_filters.company),
-		as_dict=1,
-	)
+	sle = frappe.qb.DocType("Stock Ledger Entry")
+	data = (
+		frappe.qb.from_(sle)
+		.select(
+			sle.name,
+			sle.posting_date,
+			sle.posting_time,
+			sle.voucher_type,
+			sle.voucher_no,
+			sle.stock_value_difference,
+			sle.stock_value,
+			sle.warehouse,
+			sle.item_code,
+		)
+		.where(
+			(sle.posting_date == from_date)
+			& (sle.company == report_filters.company)
+			& (sle.is_cancelled == 0)
+		)
+		.orderby(Timestamp(sle.posting_date, sle.posting_time), sle.creation)
+	).run(as_dict=True)
 
 	for d in data:
 		voucher_wise_dict.setdefault((d.item_code, d.warehouse), []).append(d)
diff --git a/erpnext/stock/report/item_price_stock/item_price_stock.py b/erpnext/stock/report/item_price_stock/item_price_stock.py
index 15218e6..1b07f59 100644
--- a/erpnext/stock/report/item_price_stock/item_price_stock.py
+++ b/erpnext/stock/report/item_price_stock/item_price_stock.py
@@ -62,22 +62,28 @@
 
 
 def get_item_price_qty_data(filters):
-	conditions = ""
-	if filters.get("item_code"):
-		conditions += "where a.item_code=%(item_code)s"
+	item_price = frappe.qb.DocType("Item Price")
+	bin = frappe.qb.DocType("Bin")
 
-	item_results = frappe.db.sql(
-		"""select a.item_code, a.item_name, a.name as price_list_name,
-		a.brand as brand, b.warehouse as warehouse, b.actual_qty as actual_qty
-		from `tabItem Price` a left join `tabBin` b
-		ON a.item_code = b.item_code
-		{conditions}""".format(
-			conditions=conditions
-		),
-		filters,
-		as_dict=1,
+	query = (
+		frappe.qb.from_(item_price)
+		.left_join(bin)
+		.on(item_price.item_code == bin.item_code)
+		.select(
+			item_price.item_code,
+			item_price.item_name,
+			item_price.name.as_("price_list_name"),
+			item_price.brand.as_("brand"),
+			bin.warehouse.as_("warehouse"),
+			bin.actual_qty.as_("actual_qty"),
+		)
 	)
 
+	if filters.get("item_code"):
+		query = query.where(item_price.item_code == filters.get("item_code"))
+
+	item_results = query.run(as_dict=True)
+
 	price_list_names = list(set(item.price_list_name for item in item_results))
 
 	buying_price_map = get_price_map(price_list_names, buying=1)
diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py
index fe2d55a..b62a6ee 100644
--- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py
+++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py
@@ -46,4 +46,5 @@
 		},
 		"type": "bar",
 		"colors": ["#5e64ff"],
+		"fieldtype": "Currency",
 	}
diff --git a/erpnext/templates/includes/footer/footer_extension.html b/erpnext/templates/includes/footer/footer_extension.html
index c7f0d06..0072dc2 100644
--- a/erpnext/templates/includes/footer/footer_extension.html
+++ b/erpnext/templates/includes/footer/footer_extension.html
@@ -6,7 +6,7 @@
 		aria-label="{{ _('Your email address...') }}"
 		aria-describedby="footer-subscribe-button">
 	<div class="input-group-append">
-		<button class="btn btn-sm btn-default"
+		<button class="btn btn-sm btn-secondary pl-3 pr-3 ml-2"
 			type="button" id="footer-subscribe-button">{{ _("Get Updates") }}</button>
 	</div>
 </div>
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index f56dc3a..dc9ee23 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -1,5 +1,5 @@
 {% macro product_image_square(website_image, css_class="") %}
-<div class="product-image product-image-square
+<div class="product-image product-image-square h-100 rounded
 	{% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
 	{% if website_image -%}
 	style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');"
diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html
index 3f2c1f2..d95b289 100644
--- a/erpnext/templates/includes/order/order_macros.html
+++ b/erpnext/templates/includes/order/order_macros.html
@@ -3,7 +3,7 @@
 {% macro item_name_and_description(d) %}
 	<div class="row item_name_and_description">
 		<div class="col-xs-4 col-sm-2 order-image-col">
-			<div class="order-image">
+			<div class="order-image h-100">
 				{% if d.thumbnail or d.image %}
 					{{ product_image(d.thumbnail or d.image, no_border=True) }}
 				{% else %}
@@ -18,6 +18,9 @@
 			<div class="text-muted small item-description">
 				{{ html2text(d.description) | truncate(140) }}
 			</div>
+			<span class="text-muted mt-2 d-l-n order-qty">
+				{{ _("Qty ") }}({{ d.get_formatted("qty") }})
+			</span>
 		</div>
 	</div>
 {% endmacro %}
diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html
index b821e62..0060ab3 100644
--- a/erpnext/templates/includes/order/order_taxes.html
+++ b/erpnext/templates/includes/order/order_taxes.html
@@ -1,84 +1,111 @@
 {% if doc.taxes %}
-<tr>
-	<td class="text-left" colspan="1">
-		{{ _("Net Total") }}
-	</td>
-	<td class="text-right totals" colspan="3">
-		{{ doc.get_formatted("net_total") }}
-	</td>
-</tr>
+	<div class="w-100 order-taxes mt-5">
+		<div class="col-4 d-flex  border-btm pb-5">
+			<div class="item-grand-total col-8">
+				{{ _("Net Total") }}
+			</div>
+			<div class="item-grand-total col-4 text-right pr-0">
+				{{ doc.get_formatted("net_total") }}
+			</div>
+		</div>
+	</div>
 {% endif %}
 
 {% for d in doc.taxes %}
 	{% if d.base_tax_amount %}
-	<tr>
-		<td class="text-left" colspan="1">
-			{{ d.description }}
-		</td>
-		<td class="text-right totals" colspan="3">
-			{{ d.get_formatted("base_tax_amount") }}
-		</td>
-	</tr>
+		<div class="order-taxes w-100 mt-5">
+			<div class="col-4 d-flex  border-btm pb-5">
+				<div class="item-grand-total col-8">
+					{{ d.description }}
+				</div>
+				<div class="item-grand-total col-4 text-right pr-0">
+					{{ doc.get_formatted("net_total") }}
+				</div>
+			</div>
+		</div>
 	{% endif %}
 {% endfor %}
 
 {% if doc.doctype == 'Quotation' %}
 	{% if doc.coupon_code %}
-		<tr>
-			<td class="text-left total-discount" colspan="1">
-				{{ _("Savings") }}
-			</td>
-			<td class="text-right tot_quotation_discount total-discount totals" colspan="3">
-				{% set tot_quotation_discount = [] %}
-				{%- for item in doc.items -%}
-					{% if tot_quotation_discount.append((((item.price_list_rate * item.qty)
-						* item.discount_percentage) / 100)) %}
-					{% endif %}
-				{% endfor %}
-				{{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }}
-			</td>
-		</tr>
+		<div class="w-100 mt-5 order-taxes font-weight-bold">
+			<div class="col-4 d-flex  border-btm pb-5">
+				<div class="item-grand-total col-8">
+					{{ _("Savings") }}
+				</div>
+				<div class="item-grand-total col-4 text-right pr-0">
+					{% set tot_quotation_discount = [] %}
+					{%- for item in doc.items -%}
+						{% if tot_quotation_discount.append((((item.price_list_rate * item.qty)
+							* item.discount_percentage) / 100)) %}
+						{% endif %}
+					{% endfor %}
+					{{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} </div>
+			</div>
+		</div>
 	{% endif %}
 {% endif %}
 
 {% if doc.doctype == 'Sales Order' %}
 	{% if doc.coupon_code %}
-		<tr>
-			<td class="text-left total-discount" colspan="2" style="padding-right: 2rem;">
-				{{ _("Applied Coupon Code") }}
-			</td>
-			<td class="text-right total-discount">
-				<span>
-				{%- for row in frappe.get_all(doctype="Coupon Code",
-				fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%}
-					<span>{{ row.coupon_code }}</span>
-				{% endfor %}
-				</span>
-			</td>
-		</tr>
-		<tr>
-			<td class="text-left total-discount" colspan="2">
-				{{ _("Savings") }}
-			</td>
-			<td class="text-right total-discount">
-				<span>
-				{% set tot_SO_discount = [] %}
-				{%- for item in doc.items -%}
-				{% if tot_SO_discount.append((((item.price_list_rate * item.qty)
-					* item.discount_percentage) / 100)) %}{% endif %}
-				{% endfor %}
-				{{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }}
-				</span>
-			</td>
-		</tr>
+		<div class="w-100 order-taxes mt-5">
+			<div class="col-4 d-flex  border-btm pb-5">
+				<div class="item-grand-total col-8">
+					{{ _("Total Amount") }}
+				</div>
+				<div class="item-grand-total col-4 text-right pr-0">
+					<span>
+						{% set total_amount = [] %}
+						{%- for item in doc.items -%}
+						{% if total_amount.append((item.price_list_rate * item.qty)) %}{% endif %}
+						{% endfor %}
+						{{ frappe.utils.fmt_money((total_amount | sum),currency=doc.currency) }}
+					</span>
+				</div>
+			</div>
+		</div>
+		<div class="order-taxes w-100 mt-5">
+			<div class="col-4 d-flex">
+				<div class="item-grand-total col-8">
+					{{ _("Applied Coupon Code") }}
+				</div>
+				<div class="item-grand-total col-4 text-right pr-0">
+					<span>
+						{%- for row in frappe.get_all(doctype="Coupon Code",
+						fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%}
+							<span>{{ row.coupon_code }}</span>
+						{% endfor %}
+					</span>
+				</div>
+			</div>
+		</div>
+		<div class="order-taxes mt-5">
+			<div class="col-4 d-flex border-btm pb-5">
+				<div class="item-grand-total col-8">
+					{{ _("Savings") }}
+				</div>
+				<div class="item-grand-total col-4 text-right pr-0">
+					<span>
+						{% set tot_SO_discount = [] %}
+						{%- for item in doc.items -%}
+						{% if tot_SO_discount.append((((item.price_list_rate * item.qty)
+						* item.discount_percentage) / 100)) %}{% endif %}
+						{% endfor %}
+						{{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }}
+					</span>
+				</div>
+			</div>
+		</div>
 	{% endif %}
 {% endif %}
 
-<tr>
-	<th class="text-left item-grand-total" colspan="1">
-		{{ _("Grand Total") }}
-	</th>
-	<th class="text-right item-grand-total totals" colspan="3">
-		{{ doc.get_formatted("grand_total") }}
-	</th>
-</tr>
+<div class="w-100 mt-5 order-taxes font-weight-bold">
+	<div class="col-4 d-flex">
+		<div class="item-grand-total col-8">
+			{{ _("Grand Total") }}
+		</div>
+		<div class="item-grand-total col-4 text-right pr-0">
+			{{ doc.get_formatted("grand_total") }}
+		</div>
+	</div>
+</div>
diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html
index 3cfb8d8..72d498c 100644
--- a/erpnext/templates/includes/transaction_row.html
+++ b/erpnext/templates/includes/transaction_row.html
@@ -1,20 +1,22 @@
 <div class="web-list-item transaction-list-item">
-	<div class="row">
+	<div class="row align-items-center">
 		<div class="col-sm-4">
-			<span class="indicator small {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }}">
-			{{ doc.name }}</span>
+			<span class="list-item-name font-weight-bold">{{ doc.name }}</span>
 			<div class="small text-muted transaction-time"
 				title="{{ frappe.utils.format_datetime(doc.modified, "medium") }}">
 				{{ frappe.utils.global_date_format(doc.modified) }}
 			</div>
 		</div>
-		<div class="col-sm-5">
+		<div class="col-sm-3">
+			<span class="indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }} list-item-status">{{doc.status}}</span>
+		</div>
+		<div class="col-sm-2">
 			<div class="small text-muted items-preview ellipsis ellipsis-width">
 				{{ doc.items_preview }}
 			</div>
 		</div>
 		{% if doc.get('grand_total') %}
-			<div class="col-sm-3 text-right bold">
+			<div class="col-sm-3 text-right font-weight-bold item-total">
 				{{ doc.get_formatted("grand_total") }}
 			</div>
 		{% endif %}
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index a10870d..6b354b2 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -5,149 +5,159 @@
 	{% include "templates/includes/breadcrumbs.html" %}
 {% endblock %}
 
-{% block title %}{{ doc.name }}{% endblock %}
+{% block title %}
+	{{ doc.name }}
+{% endblock %}
 
 {% block header %}
-	<h2 class="m-0">{{ doc.name }}</h2>
+	<h3 class="m-0">{{ doc.name }}</h3>
 {% endblock %}
 
 {% block header_actions %}
-	<div class="dropdown">
-		<button class="btn btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
-			<span class="font-md">{{ _('Actions') }}</span>
-			<b class="caret"></b>
-		</button>
-		<ul class="dropdown-menu dropdown-menu-right" role="menu">
-			{% if doc.doctype == 'Purchase Order' %}
-				<a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a>
-			{% endif %}
-			<a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}'
-				target="_blank" rel="noopener noreferrer">
-				{{ _("Print") }}
-			</a>
-		</ul>
+	<div class="row">
+		<div class="dropdown">
+			<button class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+				<span class="font-md">{{ _('Actions') }}</span>
+				<b class="caret"></b>
+			</button>
+			<ul class="dropdown-menu dropdown-menu-right" role="menu">
+				{% if doc.doctype == 'Purchase Order' and show_make_pi_button %}
+					<a class="dropdown-item"
+						href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}"
+						data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}
+					</a>
+				{% endif %}
+				<a class="dropdown-item"
+					href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}' target="_blank"
+					rel="noopener noreferrer">
+					{{ _("Print") }}
+				</a>
+			</ul>
+		</div>
+		<div class="form-column col-sm-6">
+			<div class="page-header-actions-block" data-html-block="header-actions">
+				<p>
+					<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
+						class="btn btn-primary btn-sm" id="pay-for-order">
+						{{ _("Pay") }} {{doc.get_formatted("grand_total") }}
+					</a>
+				</p>
+			</div>
+		</div>
 	</div>
 {% endblock %}
 
 {% block page_content %}
-	<div class="row transaction-subheading">
-		<div class="col-6">
-			<span class="font-md indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "darkgrey") }}">
-				{% if doc.doctype == "Quotation" and not doc.docstatus %}
-					{{ _("Pending") }}
-				{% else %}
-					{{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
+	<div>
+		<div class="row transaction-subheading  mt-1">
+			<div class="col-6 text-muted small mt-1">
+				{{ frappe.utils.format_date(doc.transaction_date, 'medium') }}
+				{% if doc.valid_till %}
+					<p>
+						{{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }}
+					</p>
 				{% endif %}
-			</span>
+			</div>
 		</div>
-		<div class="col-6 text-muted text-right small pt-3">
-			{{ frappe.utils.format_date(doc.transaction_date, 'medium') }}
-			{% if doc.valid_till %}
-			<p>
-			{{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }}
-			</p>
-			{% endif %}
-		</div>
-	</div>
-
-	<p class="small my-3">
-		{%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase Order'] else doc.customer_name %}
-		<b>{{ party_name }}</b>
-
-		{% if doc.contact_display and doc.contact_display != party_name %}
-			<br>
-			{{ doc.contact_display }}
-		{% endif %}
-	</p>
-
-	{% if doc._header %}
-		{{ doc._header }}
-	{% endif %}
-
-	<div class="order-container">
-		<!-- items -->
-		<table class="order-item-table w-100 table">
-			<thead class="order-items order-item-header">
-				<th width="60%">
-					{{ _("Item") }}
-				</th>
-				<th width="20%" class="text-right">
-					{{ _("Quantity") }}
-				</th>
-				<th width="20%" class="text-right">
-					{{ _("Amount") }}
-				</th>
-			</thead>
-			<tbody>
-			{% for d in doc.items %}
-			<tr class="order-items">
-				<td>
-					{{ item_name_and_description(d) }}
-				</td>
-				<td class="text-right">
-					{{ d.qty }}
-					{% if d.delivered_qty is defined and d.delivered_qty != None %}
-						<p class="text-muted small">{{ _("Delivered") }}&nbsp;{{ d.delivered_qty }}</p>
+		<div class="row indicator-container mt-2">
+			<div class="col-10">
+				<span class="indicator-pill {{ doc.indicator_color or (" blue" if doc.docstatus==1 else "darkgrey" ) }}">
+					{% if doc.doctype == "Quotation" and not doc.docstatus %}
+						{{ _("Pending") }}
+					{% else %}
+						{{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
 					{% endif %}
-				</td>
-				<td class="text-right">
-					{{ d.get_formatted("amount")	 }}
-					<p class="text-muted small">{{ _("Rate:") }}&nbsp;{{ d.get_formatted("rate") }}</p>
-				</td>
-			</tr>
-			{% endfor %}
-			</tbody>
-		</table>
-		<!-- taxes -->
-		<div class="order-taxes d-flex justify-content-end">
-			<table>
+				</span>
+			</div>
+			<div class="text-right col-2">
+				{%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase
+				Order'] else doc.customer_name %}
+				<b>{{ party_name }}</b>
+
+				{% if doc.contact_display and doc.contact_display != party_name %}
+					<br>
+					{{ doc.contact_display }}
+				{% endif %}
+			</div>
+		</div>
+
+		{% if doc._header %}
+			{{ doc._header }}
+		{% endif %}
+
+		<div class="order-container mt-4">
+			<!-- items -->
+			<div class="w-100">
+				<div class="order-items order-item-header mb-1 row text-muted">
+					<span class="col-5">
+						{{ _("Item") }}
+					</span>
+					<span class="d-s-n col-3">
+						{{ _("Quantity") }}
+					</span>
+					<span class="col-2 pl-10">
+						{{ _("Rate") }}
+					</span>
+					<span class="col-2 text-right">
+						{{ _("Amount") }}
+					</span>
+				</div>
+				{% for d in doc.items %}
+				<div class="order-items row align-items-center">
+					<span class="order-item-name col-5 pr-0">
+						{{ item_name_and_description(d) }}
+					</span>
+
+					<span class="d-s-n col-3 pl-10">
+						{{ d.get_formatted("qty") }}
+					</span>
+					<span class="order-rate pl-4 col-2">
+						{{ d.get_formatted("rate") }}
+					</span>
+					<span class="col-2 text-right">
+						{{ d.get_formatted("amount") }}
+					</span>
+				</div>
+				{% endfor %}
+			</div>
+
+			<!-- taxes -->
+			<div class="">
 				{% include "erpnext/templates/includes/order/order_taxes.html" %}
-			</table>
+			</div>
 		</div>
 	</div>
 
 	{% if enabled_checkout and ((doc.doctype=="Sales Order" and doc.per_billed <= 0)
-		or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0)) %}
+		or (doc.doctype=="Sales Invoice" and doc.outstanding_amount> 0)) %}
 		<div class="panel panel-default">
-			<div class="panel-heading">
-				<div class="row">
-					<div class="form-column col-sm-6 address-title">
-						<strong>Payment</strong>
-					</div>
-				</div>
-			</div>
 			<div class="panel-collapse">
 				<div class="panel-body text-muted small">
 					<div class="row">
 						<div class="form-column col-sm-6">
 							{% if available_loyalty_points %}
+							<div class="panel-heading">
+								<div class="row">
+									<div class="form-column col-sm-6 address-title">
+										<strong>Loyalty Points</strong>
+									</div>
+								</div>
+							</div>
+
 							<div class="form-group">
 								<div class="h6">Enter Loyalty Points</div>
 								<div class="control-input-wrapper">
 									<div class="control-input">
-										<input class="form-control" type="number" min="0" max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem">
+										<input class="form-control" type="number" min="0"
+											max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem">
 									</div>
-									<p class="help-box small text-muted d-none d-sm-block"> Available Points: {{ available_loyalty_points }} </p>
+									<p class="help-box small text-muted d-none d-sm-block"> Available Points: {{
+										available_loyalty_points }} </p>
 								</div>
 							</div>
 							{% endif %}
 						</div>
-
-						<div class="form-column col-sm-6">
-							<div id="loyalty-points-status" style="text-align: right"></div>
-							<div class="page-header-actions-block" data-html-block="header-actions">
-								<p class="mt-2" style="float: right;">
-									<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
-										class="btn btn-primary btn-sm"
-										id="pay-for-order">
-										{{ _("Pay") }} {{ doc.get_formatted("grand_total") }}
-									</a>
-								</p>
-							</div>
-						</div>
-
 					</div>
-
 				</div>
 			</div>
 		</div>
@@ -172,17 +182,17 @@
 			</div>
 		</div>
 	{% endif %}
-	</div>
 
 	{% if doc.terms %}
 		<div class="terms-and-condition text-muted small">
-			<hr><p>{{ doc.terms }}</p>
+			<hr>
+			<p>{{ doc.terms }}</p>
 		</div>
 	{% endif %}
 {% endblock %}
 
 {% block script %}
-	<script> {% include "templates/pages/order.js" %} </script>
+	<script> {% include "templates/pages/order.js" %}</script>
 	<script>
 		window.doc_info = {
 			customer: '{{doc.customer}}',
@@ -192,4 +202,4 @@
 			currency: '{{ doc.currency }}'
 		}
 	</script>
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
index 3e6d57a..e1e12bd 100644
--- a/erpnext/templates/pages/order.py
+++ b/erpnext/templates/pages/order.py
@@ -52,6 +52,9 @@
 		)
 		context.available_loyalty_points = int(loyalty_program_details.get("loyalty_points"))
 
+	# show Make Purchase Invoice button based on permission
+	context.show_make_pi_button = frappe.has_permission("Purchase Invoice", "create")
+
 
 def get_attachments(dt, dn):
 	return frappe.get_all(
diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py
index bfcba07..eed7c12 100644
--- a/erpnext/utilities/bulk_transaction.py
+++ b/erpnext/utilities/bulk_transaction.py
@@ -9,7 +9,6 @@
 def transaction_processing(data, from_doctype, to_doctype):
 	if isinstance(data, str):
 		deserialized_data = json.loads(data)
-
 	else:
 		deserialized_data = data
 
@@ -30,30 +29,29 @@
 
 
 def job(deserialized_data, from_doctype, to_doctype):
-	failed_history = []
-	i = 0
+	fail_count = 0
 	for d in deserialized_data:
-		failed = []
-
 		try:
-			i += 1
 			doc_name = d.get("name")
 			frappe.db.savepoint("before_creation_state")
 			task(doc_name, from_doctype, to_doctype)
-
 		except Exception as e:
 			frappe.db.rollback(save_point="before_creation_state")
-			failed_history.append(e)
-			failed.append(e)
+			fail_count += 1
 			update_logger(
-				doc_name, e, from_doctype, to_doctype, status="Failed", log_date=str(date.today())
+				doc_name,
+				str(frappe.get_traceback()),
+				from_doctype,
+				to_doctype,
+				status="Failed",
+				log_date=str(date.today()),
 			)
-		if not failed:
+		else:
 			update_logger(
 				doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today())
 			)
 
-	show_job_status(failed_history, deserialized_data, to_doctype)
+	show_job_status(fail_count, len(deserialized_data), to_doctype)
 
 
 def task(doc_name, from_doctype, to_doctype):
@@ -94,7 +92,7 @@
 			"Purchase Invoice": purchase_order.make_purchase_invoice,
 			"Purchase Receipt": purchase_order.make_purchase_receipt,
 		},
-		"Purhcase Invoice": {
+		"Purchase Invoice": {
 			"Purchase Receipt": purchase_invoice.make_purchase_receipt,
 			"Payment": payment_entry.get_payment_entry,
 		},
@@ -150,15 +148,14 @@
 			log_doc.save()
 
 
-def show_job_status(failed_history, deserialized_data, to_doctype):
-	if not failed_history:
+def show_job_status(fail_count, deserialized_data_count, to_doctype):
+	if not fail_count:
 		frappe.msgprint(
 			_("Creation of {0} successful").format(to_doctype),
 			title="Successful",
 			indicator="green",
 		)
-
-	if len(failed_history) != 0 and len(failed_history) < len(deserialized_data):
+	elif fail_count != 0 and fail_count < deserialized_data_count:
 		frappe.msgprint(
 			_(
 				"""Creation of {0} partially successful.
@@ -167,8 +164,7 @@
 			title="Partially successful",
 			indicator="orange",
 		)
-
-	if len(failed_history) == len(deserialized_data):
+	else:
 		frappe.msgprint(
 			_(
 				"""Creation of {0} failed.
@@ -180,9 +176,7 @@
 
 
 def record_exists(log_doc, doc_name, status):
-
 	record = mark_retrired_transaction(log_doc, doc_name)
-
 	if record and status == "Failed":
 		return False
 	elif record and status == "Success":
diff --git a/erpnext/www/book_appointment/index.css b/erpnext/www/book_appointment/index.css
index 2776108..3b1b97c 100644
--- a/erpnext/www/book_appointment/index.css
+++ b/erpnext/www/book_appointment/index.css
@@ -45,7 +45,7 @@
 
 .time-slot.selected {
     color: white;
-    background: #5e64ff;
+    background: var(--primary-color);
 }
 
 .time-slot.selected .text-muted {
diff --git a/erpnext/www/book_appointment/index.html b/erpnext/www/book_appointment/index.html
index 207175f..ad964d9 100644
--- a/erpnext/www/book_appointment/index.html
+++ b/erpnext/www/book_appointment/index.html
@@ -12,8 +12,8 @@
     <!-- title: Book an appointment -->
     <div id="select-date-time">
         <div class="text-center mt-5">
-            <h3>Book an appointment</h3>
-            <p class="lead text-muted" id="lead-text">Select the date and your timezone</p>
+            <h3>{{ _("Book an appointment") }}</h3>
+            <p class="lead text-muted" id="lead-text">{{ _("Select the date and your timezone") }}</p>
         </div>
         <div class="row justify-content-center mt-3">
             <div class="col-md-6 align-self-center ">
@@ -31,7 +31,7 @@
         </div>
         <div class="row justify-content-center mt-3">
             <div class="col-md-4 mb-3">
-                <button class="btn btn-primary form-control" id="next-button">Next</button>
+                <button class="btn btn-primary form-control" id="next-button">{{ _("Next") }}</button>
             </div>
         </div>
     </div>
@@ -39,24 +39,24 @@
 <!--Enter Details-->
 <div id="enter-details" class="mb-5">
     <div class="text-center mt-5">
-        <h3>Add details</h3>
-        <p class="lead text-muted">Selected date is <span class="date-span"></span> at <span class="time-span">
+        <h3>{{ _("Add details") }}</h3>
+        <p class="lead text-muted">{{ _("Selected date is") }} <span class="date-span"></span> {{ _("at") }} <span class="time-span">
             </span></p>
     </div>
     <div class="row justify-content-center mt-3">
         <div class="col-md-4 align-items-center">
             <form id="customer-form" action='#'>
-            <input class="form-control mt-3" type="text" name="customer_name" id="customer_name" placeholder="Your Name (required)" required>
+            <input class="form-control mt-3" type="text" name="customer_name" id="customer_name" placeholder="{{ _('Your Name (required)') }}" required>
             <input class="form-control mt-3" type="tel" name="customer_number" id="customer_number" placeholder="+910000000000">
             <input class="form-control mt-3" type="text" name="customer_skype" id="customer_skype" placeholder="Skype">
-            <input class="form-control mt-3"type="email" name="customer_email" id="customer_email" placeholder="Email Address (required)" required>
+            <input class="form-control mt-3"type="email" name="customer_email" id="customer_email" placeholder="{{ _('Email Address (required)') }}" required>
 
             <textarea class="form-control mt-3" name="customer_notes" id="customer_notes" cols="30" rows="10"
-                placeholder="Notes"></textarea>
+                placeholder="{{ _('Notes') }}"></textarea>
             </form>
             <div class="row mt-3 " id="submit-button-area">
-                <div class="col-md mt-3" style="grid-area: back;"><button class="btn btn-dark form-control" onclick="initialise_select_date()">Go back</button></div>
-                <div class="col-md mt-3" style="grid-area: submit;"><button class="btn btn-primary form-control " onclick="submit()" id="submit-button">Submit</button></div>
+                <div class="col-md mt-3" style="grid-area: back;"><button class="btn btn-dark form-control" onclick="initialise_select_date()">{{ _("Go back") }}</button></div>
+                <div class="col-md mt-3" style="grid-area: submit;"><button class="btn btn-primary form-control " onclick="submit()" id="submit-button">{{ _("Submit") }}</button></div>
             </div>
         </div>
     </div>
diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js
index 5562cbd..46ac155 100644
--- a/erpnext/www/book_appointment/index.js
+++ b/erpnext/www/book_appointment/index.js
@@ -69,7 +69,7 @@
     window.selected_timezone = timezone.value;
     update_time_slots(date_picker.value, timezone.value);
     let lead_text = document.getElementById('lead-text');
-    lead_text.innerHTML = "Select Time"
+    lead_text.innerHTML = __("Select Time")
 }
 
 async function get_time_slots(date, timezone) {
@@ -89,7 +89,7 @@
     clear_time_slots();
     if (window.slots.length <= 0) {
         let message_div = document.createElement('p');
-        message_div.innerHTML = "There are no slots available on this date";
+        message_div.innerHTML = __("There are no slots available on this date");
         timeslot_container.appendChild(message_div);
         return
     }
@@ -128,7 +128,7 @@
     let start_time_string = moment(time).tz(timezone).format("LT");
     let end_time = moment(time).tz(timezone).add(window.appointment_settings.appointment_duration, 'minutes');
     let end_time_string = end_time.format("LT");
-    return `<span style="font-size: 1.2em;">${start_time_string}</span><br><span class="text-muted small">to ${end_time_string}</span>`;
+    return `<span style="font-size: 1.2em;">${start_time_string}</span><br><span class="text-muted small">${__("to") } ${end_time_string}</span>`;
 }
 
 function select_time() {
@@ -227,9 +227,9 @@
         },
         callback: (response)=>{
             if (response.message.status == "Unverified") {
-                frappe.show_alert("Please check your email to confirm the appointment")
+                frappe.show_alert(__("Please check your email to confirm the appointment"))
             } else {
-                frappe.show_alert("Appointment Created Successfully");
+                frappe.show_alert(__("Appointment Created Successfully"));
             }
             setTimeout(()=>{
                 let redirect_url = "/";
@@ -239,7 +239,7 @@
                 window.location.href = redirect_url;},5000)
         },
         error: (err)=>{
-            frappe.show_alert("Something went wrong please try again");
+            frappe.show_alert(__("Something went wrong please try again"));
             button.disabled = false;
         }
     });
diff --git a/erpnext/www/book_appointment/verify/index.html b/erpnext/www/book_appointment/verify/index.html
index 9bcd3d2..58c07e8 100644
--- a/erpnext/www/book_appointment/verify/index.html
+++ b/erpnext/www/book_appointment/verify/index.html
@@ -8,11 +8,11 @@
 
     {% if success==True %}
         <div class="alert alert-success">
-            Your email has been verified and your appointment has been scheduled
+            {{ _("Your email has been verified and your appointment has been scheduled") }}
         </div>
     {% else %}
         <div class="alert alert-danger">
-            Verification failed please check the link
+            {{ _("Verification failed please check the link") }}
         </div>
     {% endif %}
 {% endblock%}