Merge branch 'develop' into github-issue-33344
diff --git a/README.md b/README.md
index 0708266..44bd729 100644
--- a/README.md
+++ b/README.md
@@ -65,7 +65,7 @@
 1. [Frappe School](https://frappe.school) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
 2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
 3. [Discussion Forum](https://discuss.erpnext.com/) - Engage with community of ERPNext users and service providers.
-4. [Telegram Group](https://t.me/erpnexthelp) - Get instant help from huge community of users.
+4. [Telegram Group](https://erpnext_public.t.me) - Get instant help from huge community of users.
 
 
 ## Contributing
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
index 75f8f06..9e67c4c 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
@@ -29,6 +29,7 @@
 					"root_type",
 					"is_group",
 					"tax_rate",
+					"account_currency",
 				]:
 
 					account_number = cstr(child.get("account_number")).strip()
@@ -95,7 +96,17 @@
 		is_group = child.get("is_group")
 	elif len(
 		set(child.keys())
-		- set(["account_name", "account_type", "root_type", "is_group", "tax_rate", "account_number"])
+		- set(
+			[
+				"account_name",
+				"account_type",
+				"root_type",
+				"is_group",
+				"tax_rate",
+				"account_number",
+				"account_currency",
+			]
+		)
 	):
 		is_group = 1
 	else:
@@ -185,6 +196,7 @@
 			"root_type",
 			"tax_rate",
 			"account_number",
+			"account_currency",
 		],
 		order_by="lft, rgt",
 	)
@@ -267,6 +279,7 @@
 				"root_type",
 				"is_group",
 				"tax_rate",
+				"account_currency",
 			]:
 				continue
 
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 220b747..cb7da17 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -36,7 +36,7 @@
 
 	no_of_columns = max([len(d) for d in data])
 
-	if no_of_columns > 7:
+	if no_of_columns > 8:
 		frappe.throw(
 			_("More columns found than expected. Please compare the uploaded file with standard template"),
 			title=(_("Wrong Template")),
@@ -233,6 +233,7 @@
 			is_group,
 			account_type,
 			root_type,
+			account_currency,
 		) = i
 
 		if not account_name:
@@ -253,6 +254,8 @@
 			charts_map[account_name]["account_type"] = account_type
 		if root_type:
 			charts_map[account_name]["root_type"] = root_type
+		if account_currency:
+			charts_map[account_name]["account_currency"] = account_currency
 		path = return_parent(data, account_name)[::-1]
 		paths.append(path)  # List of path is created
 		line_no += 1
@@ -315,6 +318,7 @@
 		"Is Group",
 		"Account Type",
 		"Root Type",
+		"Account Currency",
 	]
 	writer = UnicodeWriter()
 	writer.writerow(fields)
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
index 655c4ec..115b415 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -21,8 +21,24 @@
 		if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
 			frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
 
+		self.validate_duplicate_pos_invoices()
 		self.validate_pos_invoices()
 
+	def validate_duplicate_pos_invoices(self):
+		pos_occurences = {}
+		for idx, inv in enumerate(self.pos_transactions, 1):
+			pos_occurences.setdefault(inv.pos_invoice, []).append(idx)
+
+		error_list = []
+		for key, value in pos_occurences.items():
+			if len(value) > 1:
+				error_list.append(
+					_("{} is added multiple times on rows: {}".format(frappe.bold(key), frappe.bold(value)))
+				)
+
+		if error_list:
+			frappe.throw(error_list, title=_("Duplicate POS Invoices found"), as_list=True)
+
 	def validate_pos_invoices(self):
 		invalid_rows = []
 		for d in self.pos_transactions:
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
index 3a237a4..b1e2208 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -17,6 +17,22 @@
 	def validate(self):
 		self.validate_customer()
 		self.validate_pos_invoice_status()
+		self.validate_duplicate_pos_invoices()
+
+	def validate_duplicate_pos_invoices(self):
+		pos_occurences = {}
+		for idx, inv in enumerate(self.pos_invoices, 1):
+			pos_occurences.setdefault(inv.pos_invoice, []).append(idx)
+
+		error_list = []
+		for key, value in pos_occurences.items():
+			if len(value) > 1:
+				error_list.append(
+					_("{} is added multiple times on rows: {}".format(frappe.bold(key), frappe.bold(value)))
+				)
+
+		if error_list:
+			frappe.throw(error_list, title=_("Duplicate POS Invoices found"), as_list=True)
 
 	def validate_customer(self):
 		if self.merge_invoices_based_on == "Customer Group":
@@ -425,6 +441,8 @@
 
 		if closing_entry:
 			closing_entry.set_status(update=True, status="Failed")
+			if type(error_message) == list:
+				error_message = frappe.json.dumps(error_message)
 			closing_entry.db_set("error_message", error_message)
 		raise
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index f588d5c..21addab 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -5,6 +5,7 @@
 import frappe
 from frappe import _, throw
 from frappe.model.mapper import get_mapped_doc
+from frappe.query_builder.functions import Sum
 from frappe.utils import cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate
 
 import erpnext
@@ -1465,19 +1466,16 @@
 	def update_billing_status_in_pr(self, update_modified=True):
 		updated_pr = []
 		po_details = []
+
+		pr_details_billed_amt = self.get_pr_details_billed_amt()
+
 		for d in self.get("items"):
 			if d.pr_detail:
-				billed_amt = frappe.db.sql(
-					"""select sum(amount) from `tabPurchase Invoice Item`
-					where pr_detail=%s and docstatus=1""",
-					d.pr_detail,
-				)
-				billed_amt = billed_amt and billed_amt[0][0] or 0
 				frappe.db.set_value(
 					"Purchase Receipt Item",
 					d.pr_detail,
 					"billed_amt",
-					billed_amt,
+					flt(pr_details_billed_amt.get(d.pr_detail)),
 					update_modified=update_modified,
 				)
 				updated_pr.append(d.purchase_receipt)
@@ -1493,6 +1491,24 @@
 			pr_doc = frappe.get_doc("Purchase Receipt", pr)
 			update_billing_percentage(pr_doc, update_modified=update_modified)
 
+	def get_pr_details_billed_amt(self):
+		# Get billed amount based on purchase receipt item reference (pr_detail) in purchase invoice
+
+		pr_details_billed_amt = {}
+		pr_details = [d.get("pr_detail") for d in self.get("items") if d.get("pr_detail")]
+		if pr_details:
+			doctype = frappe.qb.DocType("Purchase Invoice Item")
+			query = (
+				frappe.qb.from_(doctype)
+				.select(doctype.pr_detail, Sum(doctype.amount))
+				.where(doctype.pr_detail.isin(pr_details) & doctype.docstatus == 1)
+				.groupby(doctype.pr_detail)
+			)
+
+			pr_details_billed_amt = frappe._dict(query.run(as_list=1))
+
+		return pr_details_billed_amt
+
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		self.due_date = 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 2c829b2..f0146ea 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -278,7 +278,7 @@
 			tax_amount = get_tcs_amount(parties, inv, tax_details, vouchers, advance_vouchers)
 
 	if cint(tax_details.round_off_tax_amount):
-		tax_amount = round(tax_amount)
+		tax_amount = normal_round(tax_amount)
 
 	return tax_amount, tax_deducted, tax_deducted_on_advances, voucher_wise_amount
 
@@ -603,3 +603,20 @@
 		valid = True
 
 	return valid
+
+
+def normal_round(number):
+	"""
+	Rounds a number to the nearest integer.
+	:param number: The number to round.
+	"""
+	decimal_part = number - int(number)
+
+	if decimal_part >= 0.5:
+		decimal_part = 1
+	else:
+		decimal_part = 0
+
+	number = int(number) + decimal_part
+
+	return number
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index e23265b..fde4de8 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -395,6 +395,7 @@
 
 class GrossProfitGenerator(object):
 	def __init__(self, filters=None):
+		self.sle = {}
 		self.data = []
 		self.average_buying_rate = {}
 		self.filters = frappe._dict(filters)
@@ -404,7 +405,6 @@
 		if filters.group_by == "Invoice":
 			self.group_items_by_invoice()
 
-		self.load_stock_ledger_entries()
 		self.load_product_bundle()
 		self.load_non_stock_items()
 		self.get_returned_invoice_items()
@@ -633,7 +633,7 @@
 			return flt(row.qty) * item_rate
 
 		else:
-			my_sle = self.sle.get((item_code, row.warehouse))
+			my_sle = self.get_stock_ledger_entries(item_code, row.warehouse)
 			if (row.update_stock or row.dn_detail) and my_sle:
 				parenttype, parent = row.parenttype, row.parent
 				if row.dn_detail:
@@ -651,7 +651,7 @@
 					dn["item_row"],
 					dn["warehouse"],
 				)
-				my_sle = self.sle.get((item_code, warehouse))
+				my_sle = self.get_stock_ledger_entries(item_code, row.warehouse)
 				return self.calculate_buying_amount_from_sle(
 					row, my_sle, parenttype, parent, item_row, item_code
 				)
@@ -667,15 +667,12 @@
 	def get_buying_amount_from_so_dn(self, sales_order, so_detail, item_code):
 		from frappe.query_builder.functions import Sum
 
-		delivery_note = frappe.qb.DocType("Delivery Note")
 		delivery_note_item = frappe.qb.DocType("Delivery Note Item")
 
 		query = (
-			frappe.qb.from_(delivery_note)
-			.inner_join(delivery_note_item)
-			.on(delivery_note.name == delivery_note_item.parent)
+			frappe.qb.from_(delivery_note_item)
 			.select(Sum(delivery_note_item.incoming_rate * delivery_note_item.stock_qty))
-			.where(delivery_note.docstatus == 1)
+			.where(delivery_note_item.docstatus == 1)
 			.where(delivery_note_item.item_code == item_code)
 			.where(delivery_note_item.against_sales_order == sales_order)
 			.where(delivery_note_item.so_detail == so_detail)
@@ -947,24 +944,36 @@
 			"Item", item_code, ["item_name", "description", "item_group", "brand"]
 		)
 
-	def load_stock_ledger_entries(self):
-		res = frappe.db.sql(
-			"""select item_code, voucher_type, voucher_no,
-				voucher_detail_no, stock_value, warehouse, actual_qty as qty
-			from `tabStock Ledger Entry`
-			where company=%(company)s and is_cancelled = 0
-			order by
-				item_code desc, warehouse desc, posting_date desc,
-				posting_time desc, creation desc""",
-			self.filters,
-			as_dict=True,
-		)
-		self.sle = {}
-		for r in res:
-			if (r.item_code, r.warehouse) not in self.sle:
-				self.sle[(r.item_code, r.warehouse)] = []
+	def get_stock_ledger_entries(self, item_code, warehouse):
+		if item_code and warehouse:
+			if (item_code, warehouse) not in self.sle:
+				sle = qb.DocType("Stock Ledger Entry")
+				res = (
+					qb.from_(sle)
+					.select(
+						sle.item_code,
+						sle.voucher_type,
+						sle.voucher_no,
+						sle.voucher_detail_no,
+						sle.stock_value,
+						sle.warehouse,
+						sle.actual_qty.as_("qty"),
+					)
+					.where(
+						(sle.company == self.filters.company)
+						& (sle.item_code == item_code)
+						& (sle.warehouse == warehouse)
+						& (sle.is_cancelled == 0)
+					)
+					.orderby(sle.item_code)
+					.orderby(sle.warehouse, sle.posting_date, sle.posting_time, sle.creation, order=Order.desc)
+					.run(as_dict=True)
+				)
 
-			self.sle[(r.item_code, r.warehouse)].append(r)
+				self.sle[(item_code, warehouse)] = res
+
+			return self.sle[(item_code, warehouse)]
+		return []
 
 	def load_product_bundle(self):
 		self.product_bundles = {}
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js
index c28b2b3..3d2dff1 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js
@@ -43,9 +43,9 @@
 	if(frm.doc.depreciation_method != "Manual") return;
 
 	var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation);
-	$.each(frm.doc.schedules || [], function(i, row) {
+
+	$.each(frm.doc.depreciation_schedule || [], function(i, row) {
 		accumulated_depreciation  += flt(row.depreciation_amount);
-		frappe.model.set_value(row.doctype, row.name,
-			"accumulated_depreciation_amount", accumulated_depreciation);
+		frappe.model.set_value(row.doctype, row.name, "accumulated_depreciation_amount", accumulated_depreciation);
 	})
 };
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json
index 898c482..d38508d 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json
@@ -10,7 +10,9 @@
   "asset",
   "naming_series",
   "column_break_2",
+  "gross_purchase_amount",
   "opening_accumulated_depreciation",
+  "number_of_depreciations_booked",
   "finance_book",
   "finance_book_id",
   "depreciation_details_section",
@@ -148,18 +150,36 @@
    "read_only": 1
   },
   {
-   "depends_on": "opening_accumulated_depreciation",
    "fieldname": "opening_accumulated_depreciation",
    "fieldtype": "Currency",
+   "hidden": 1,
    "label": "Opening Accumulated Depreciation",
    "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "gross_purchase_amount",
+   "fieldtype": "Currency",
+   "hidden": 1,
+   "label": "Gross Purchase Amount",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "number_of_depreciations_booked",
+   "fieldtype": "Int",
+   "hidden": 1,
+   "label": "Number of Depreciations Booked",
+   "print_hide": 1,
    "read_only": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-01-16 21:08:21.421260",
+ "modified": "2023-02-26 16:37:23.734806",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Asset Depreciation Schedule",
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
index 6f02662..b75fbcb 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
@@ -4,7 +4,15 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import add_days, add_months, cint, flt, get_last_day, is_last_day_of_the_month
+from frappe.utils import (
+	add_days,
+	add_months,
+	cint,
+	flt,
+	get_last_day,
+	getdate,
+	is_last_day_of_the_month,
+)
 
 
 class AssetDepreciationSchedule(Document):
@@ -83,15 +91,58 @@
 		date_of_return=None,
 		update_asset_finance_book_row=True,
 	):
+		have_asset_details_been_modified = self.have_asset_details_been_modified(asset_doc)
+		not_manual_depr_or_have_manual_depr_details_been_modified = (
+			self.not_manual_depr_or_have_manual_depr_details_been_modified(row)
+		)
+
 		self.set_draft_asset_depr_schedule_details(asset_doc, row)
-		self.make_depr_schedule(asset_doc, row, date_of_disposal, update_asset_finance_book_row)
-		self.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
+
+		if self.should_prepare_depreciation_schedule(
+			have_asset_details_been_modified, not_manual_depr_or_have_manual_depr_details_been_modified
+		):
+			self.make_depr_schedule(asset_doc, row, date_of_disposal, update_asset_finance_book_row)
+			self.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
+
+	def have_asset_details_been_modified(self, asset_doc):
+		return (
+			asset_doc.gross_purchase_amount != self.gross_purchase_amount
+			or asset_doc.opening_accumulated_depreciation != self.opening_accumulated_depreciation
+			or asset_doc.number_of_depreciations_booked != self.number_of_depreciations_booked
+		)
+
+	def not_manual_depr_or_have_manual_depr_details_been_modified(self, row):
+		return (
+			self.depreciation_method != "Manual"
+			or row.total_number_of_depreciations != self.total_number_of_depreciations
+			or row.frequency_of_depreciation != self.frequency_of_depreciation
+			or getdate(row.depreciation_start_date) != self.get("depreciation_schedule")[0].schedule_date
+			or row.expected_value_after_useful_life != self.expected_value_after_useful_life
+		)
+
+	def should_prepare_depreciation_schedule(
+		self, have_asset_details_been_modified, not_manual_depr_or_have_manual_depr_details_been_modified
+	):
+		if not self.get("depreciation_schedule"):
+			return True
+
+		old_asset_depr_schedule_doc = self.get_doc_before_save()
+
+		if self.docstatus != 0 and not old_asset_depr_schedule_doc:
+			return True
+
+		if have_asset_details_been_modified or not_manual_depr_or_have_manual_depr_details_been_modified:
+			return True
+
+		return False
 
 	def set_draft_asset_depr_schedule_details(self, asset_doc, row):
 		self.asset = asset_doc.name
 		self.finance_book = row.finance_book
 		self.finance_book_id = row.idx
 		self.opening_accumulated_depreciation = asset_doc.opening_accumulated_depreciation
+		self.number_of_depreciations_booked = asset_doc.number_of_depreciations_booked
+		self.gross_purchase_amount = asset_doc.gross_purchase_amount
 		self.depreciation_method = row.depreciation_method
 		self.total_number_of_depreciations = row.total_number_of_depreciations
 		self.frequency_of_depreciation = row.frequency_of_depreciation
@@ -102,7 +153,7 @@
 	def make_depr_schedule(
 		self, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True
 	):
-		if row.depreciation_method != "Manual" and not self.get("depreciation_schedule"):
+		if not self.get("depreciation_schedule"):
 			self.depreciation_schedule = []
 
 		if not asset_doc.available_for_use_date:
@@ -293,7 +344,9 @@
 		ignore_booked_entry=False,
 	):
 		straight_line_idx = [
-			d.idx for d in self.get("depreciation_schedule") if d.depreciation_method == "Straight Line"
+			d.idx
+			for d in self.get("depreciation_schedule")
+			if d.depreciation_method == "Straight Line" or d.depreciation_method == "Manual"
 		]
 
 		accumulated_depreciation = flt(self.opening_accumulated_depreciation)
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
index 51a6a86..59d43b1 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
@@ -151,6 +151,7 @@
 		filters.filter_based_on,
 		"Monthly",
 		company=filters.company,
+		ignore_fiscal_year=True,
 	)
 
 	for d in period_list:
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index fc6793a..9fcb769 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -252,7 +252,6 @@
 			child.parent = par.name and par.docstatus = 1
 			and par.is_return = 1 and par.return_against = %s
 		group by item_code
-		for update
 	""".format(
 			column, doc.doctype, doc.doctype
 		),
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fd19d25..fba886c 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -311,15 +311,10 @@
 		"on_submit": [
 			"erpnext.regional.create_transaction_log",
 			"erpnext.regional.italy.utils.sales_invoice_on_submit",
-			"erpnext.regional.saudi_arabia.utils.create_qr_code",
 		],
-		"on_cancel": [
-			"erpnext.regional.italy.utils.sales_invoice_on_cancel",
-			"erpnext.regional.saudi_arabia.utils.delete_qr_code_file",
-		],
+		"on_cancel": ["erpnext.regional.italy.utils.sales_invoice_on_cancel"],
 		"on_trash": "erpnext.regional.check_deletion_permission",
 	},
-	"POS Invoice": {"on_submit": ["erpnext.regional.saudi_arabia.utils.create_qr_code"]},
 	"Purchase Invoice": {
 		"validate": [
 			"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
@@ -347,7 +342,6 @@
 	"Email Unsubscribe": {
 		"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
 	},
-	"Company": {"on_trash": ["erpnext.regional.saudi_arabia.utils.delete_vat_settings_for_company"]},
 	"Integration Request": {
 		"validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment"
 	},
diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
index 158f143..ba05355 100644
--- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
+++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
@@ -64,8 +64,6 @@
    "fieldtype": "Section Break"
   },
   {
-   "fetch_from": "prevdoc_detail_docname.sales_person",
-   "fetch_if_empty": 1,
    "fieldname": "service_person",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -110,13 +108,15 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-05-27 17:47:21.474282",
+ "modified": "2023-02-27 11:09:33.114458",
  "modified_by": "Administrator",
  "module": "Maintenance",
  "name": "Maintenance Visit Purpose",
+ "naming_rule": "Random",
  "owner": "Administrator",
  "permissions": [],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
index 7beecac..e7f67ca 100644
--- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
+++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
@@ -25,8 +25,9 @@
 	],
 	"formatter": function(value, row, column, data, default_formatter) {
 		value = default_formatter(value, row, column, data);
+
 		if (column.id == "item") {
-			if (data["enough_parts_to_build"] > 0) {
+			if (data["in_stock_qty"] >= data["required_qty"]) {
 				value = `<a style='color:green' href="/app/item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
 			} else {
 				value = `<a style='color:red' href="/app/item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index e6be933..2abd65b 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -250,18 +250,14 @@
 erpnext.patches.v13_0.update_category_in_ltds_certificate
 erpnext.patches.v13_0.fetch_thumbnail_in_website_items
 erpnext.patches.v13_0.update_maintenance_schedule_field_in_visit
-erpnext.patches.v13_0.create_ksa_vat_custom_fields # 07-01-2022
 erpnext.patches.v14_0.migrate_crm_settings
-erpnext.patches.v13_0.rename_ksa_qr_field
 erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
-erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
 erpnext.patches.v13_0.agriculture_deprecation_warning
 erpnext.patches.v13_0.hospitality_deprecation_warning
 erpnext.patches.v13_0.update_asset_quantity_field
 erpnext.patches.v13_0.delete_bank_reconciliation_detail
 erpnext.patches.v13_0.enable_provisional_accounting
 erpnext.patches.v13_0.non_profit_deprecation_warning
-erpnext.patches.v13_0.enable_ksa_vat_docs #1
 erpnext.patches.v13_0.show_india_localisation_deprecation_warning
 erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
 erpnext.patches.v13_0.reset_corrupt_defaults
@@ -269,6 +265,8 @@
 erpnext.patches.v15_0.delete_taxjar_doctypes
 erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets
 erpnext.patches.v14_0.update_reference_due_date_in_journal_entry
+erpnext.patches.v15_0.saudi_depreciation_warning
+erpnext.patches.v15_0.delete_saudi_doctypes
 
 [post_model_sync]
 execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
diff --git a/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py b/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py
deleted file mode 100644
index 093463a..0000000
--- a/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import frappe
-
-from erpnext.regional.saudi_arabia.setup import make_custom_fields
-
-
-def execute():
-	company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
-	if not company:
-		return
-
-	make_custom_fields()
diff --git a/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py b/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
deleted file mode 100644
index 84b6c37..0000000
--- a/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2020, Wahni Green Technologies and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-
-from erpnext.regional.saudi_arabia.setup import add_print_formats
-
-
-def execute():
-	company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
-	if company:
-		add_print_formats()
-		return
-
-	if frappe.db.exists("DocType", "Print Format"):
-		frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
-		frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
-		for d in ("KSA VAT Invoice", "KSA POS Invoice"):
-			frappe.db.set_value("Print Format", d, "disabled", 1)
diff --git a/erpnext/patches/v13_0/enable_ksa_vat_docs.py b/erpnext/patches/v13_0/enable_ksa_vat_docs.py
deleted file mode 100644
index 4adf4d7..0000000
--- a/erpnext/patches/v13_0/enable_ksa_vat_docs.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import frappe
-
-from erpnext.regional.saudi_arabia.setup import add_permissions, add_print_formats
-
-
-def execute():
-	company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
-	if not company:
-		return
-
-	add_print_formats()
-	add_permissions()
diff --git a/erpnext/patches/v13_0/rename_ksa_qr_field.py b/erpnext/patches/v13_0/rename_ksa_qr_field.py
deleted file mode 100644
index e4b9141..0000000
--- a/erpnext/patches/v13_0/rename_ksa_qr_field.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2020, Wahni Green Technologies and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-from frappe.model.utils.rename_field import rename_field
-
-
-def execute():
-	company = frappe.get_all("Company", filters={"country": "Saudi Arabia"})
-	if not company:
-		return
-
-	if frappe.db.exists("DocType", "Sales Invoice"):
-		frappe.reload_doc("accounts", "doctype", "sales_invoice", force=True)
-
-		# rename_field method assumes that the field already exists or the doc is synced
-		if not frappe.db.has_column("Sales Invoice", "ksa_einv_qr"):
-			create_custom_fields(
-				{
-					"Sales Invoice": [
-						dict(
-							fieldname="ksa_einv_qr",
-							label="KSA E-Invoicing QR",
-							fieldtype="Attach Image",
-							read_only=1,
-							no_copy=1,
-							hidden=1,
-						)
-					]
-				}
-			)
-
-		if frappe.db.has_column("Sales Invoice", "qr_code"):
-			rename_field("Sales Invoice", "qr_code", "ksa_einv_qr")
-			frappe.delete_doc_if_exists("Custom Field", "Sales Invoice-qr_code")
diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
index 371ecbc..5c46bf3 100644
--- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
+++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
@@ -27,7 +27,13 @@
 
 	records = (
 		frappe.qb.from_(asset)
-		.select(asset.name, asset.opening_accumulated_depreciation, asset.docstatus)
+		.select(
+			asset.name,
+			asset.opening_accumulated_depreciation,
+			asset.gross_purchase_amount,
+			asset.number_of_depreciations_booked,
+			asset.docstatus,
+		)
 		.where(asset.calculate_depreciation == 1)
 		.where(asset.docstatus < 2)
 	).run(as_dict=True)
diff --git a/erpnext/patches/v15_0/delete_saudi_doctypes.py b/erpnext/patches/v15_0/delete_saudi_doctypes.py
new file mode 100644
index 0000000..371e335
--- /dev/null
+++ b/erpnext/patches/v15_0/delete_saudi_doctypes.py
@@ -0,0 +1,25 @@
+import click
+import frappe
+
+
+def execute():
+	if "ksa" in frappe.get_installed_apps():
+		return
+
+	doctypes = ["KSA VAT Setting", "KSA VAT Purchase Account", "KSA VAT Sales Account"]
+	for doctype in doctypes:
+		frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+	print_formats = ["KSA POS Invoice", "KSA VAT Invoice"]
+	for print_format in print_formats:
+		frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True)
+
+	reports = ["KSA VAT"]
+	for report in reports:
+		frappe.delete_doc("Report", report, ignore_missing=True, force=True)
+
+	click.secho(
+		"Region Saudi Arabia(KSA) is moved to a separate app"
+		"Please install the app to continue using the module: https://github.com/8848digital/KSA",
+		fg="yellow",
+	)
diff --git a/erpnext/patches/v15_0/saudi_depreciation_warning.py b/erpnext/patches/v15_0/saudi_depreciation_warning.py
new file mode 100644
index 0000000..6af8efe
--- /dev/null
+++ b/erpnext/patches/v15_0/saudi_depreciation_warning.py
@@ -0,0 +1,12 @@
+import click
+import frappe
+
+
+def execute():
+	if "ksa" in frappe.get_installed_apps():
+		return
+	click.secho(
+		"Region Saudi Arabia(KSA) is moved to a separate app\n"
+		"Please install the app to continue using the KSA Features: https://github.com/8848digital/KSA",
+		fg="yellow",
+	)
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 51dcd64..58aa8d7 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -221,9 +221,9 @@
 			callback: function(r) {
 				if (r.message && r.message.length) {
 					r.message.forEach((dimension) => {
-						let found = filters.some(el => el.fieldname === dimension['fieldname']);
+						let existing_filter = filters.filter(el => el.fieldname === dimension['fieldname']);
 
-						if (!found) {
+						if (!existing_filter.length) {
 							filters.splice(index, 0, {
 								"fieldname": dimension["fieldname"],
 								"label": __(dimension["doctype"]),
@@ -232,6 +232,11 @@
 									return frappe.db.get_link_options(dimension["doctype"], txt);
 								},
 							});
+						} else {
+							existing_filter[0]['fieldtype'] = "MultiSelectList";
+							existing_filter[0]['get_data'] = function(txt) {
+								return frappe.db.get_link_options(dimension["doctype"], txt);
+							}
 						}
 					});
 				}
diff --git a/erpnext/regional/doctype/ksa_vat_purchase_account/__init__.py b/erpnext/regional/doctype/ksa_vat_purchase_account/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/doctype/ksa_vat_purchase_account/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.json b/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.json
deleted file mode 100644
index 89ba3e9..0000000
--- a/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "actions": [],
- "creation": "2021-07-13 09:17:09.862163",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "title",
-  "item_tax_template",
-  "account"
- ],
- "fields": [
-  {
-   "fieldname": "account",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Account",
-   "options": "Account",
-   "reqd": 1
-  },
-  {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Title",
-   "reqd": 1
-  },
-  {
-   "fieldname": "item_tax_template",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Tax Template",
-   "options": "Item Tax Template",
-   "reqd": 1
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-08-04 06:42:38.205597",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA VAT Purchase Account",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.py b/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.py
deleted file mode 100644
index 3920bc5..0000000
--- a/erpnext/regional/doctype/ksa_vat_purchase_account/ksa_vat_purchase_account.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Havenir Solutions and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class KSAVATPurchaseAccount(Document):
-	pass
diff --git a/erpnext/regional/doctype/ksa_vat_sales_account/__init__.py b/erpnext/regional/doctype/ksa_vat_sales_account/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/doctype/ksa_vat_sales_account/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.js b/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.js
deleted file mode 100644
index 72613f4..0000000
--- a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2021, Havenir Solutions and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('KSA VAT Sales Account', {
-	// refresh: function(frm) {
-
-	// }
-});
diff --git a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.json b/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.json
deleted file mode 100644
index df27478..0000000
--- a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "actions": [],
- "creation": "2021-07-13 08:46:33.820968",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "title",
-  "item_tax_template",
-  "account"
- ],
- "fields": [
-  {
-   "fieldname": "account",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Account",
-   "options": "Account",
-   "reqd": 1
-  },
-  {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Title",
-   "reqd": 1
-  },
-  {
-   "fieldname": "item_tax_template",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Tax Template",
-   "options": "Item Tax Template",
-   "reqd": 1
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-08-04 06:42:00.081407",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA VAT Sales Account",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.py b/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.py
deleted file mode 100644
index 7c2689f..0000000
--- a/erpnext/regional/doctype/ksa_vat_sales_account/ksa_vat_sales_account.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Havenir Solutions and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class KSAVATSalesAccount(Document):
-	pass
diff --git a/erpnext/regional/doctype/ksa_vat_sales_account/test_ksa_vat_sales_account.py b/erpnext/regional/doctype/ksa_vat_sales_account/test_ksa_vat_sales_account.py
deleted file mode 100644
index 1d6a6a7..0000000
--- a/erpnext/regional/doctype/ksa_vat_sales_account/test_ksa_vat_sales_account.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Havenir Solutions and Contributors
-# See license.txt
-
-# import frappe
-import unittest
-
-
-class TestKSAVATSalesAccount(unittest.TestCase):
-	pass
diff --git a/erpnext/regional/doctype/ksa_vat_setting/__init__.py b/erpnext/regional/doctype/ksa_vat_setting/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.js b/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.js
deleted file mode 100644
index 00b62b9..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2021, Havenir Solutions and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('KSA VAT Setting', {
-	onload: function () {
-		frappe.breadcrumbs.add('Accounts', 'KSA VAT Setting');
-	}
-});
diff --git a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.json b/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.json
deleted file mode 100644
index 3361946..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "actions": [],
- "autoname": "field:company",
- "creation": "2021-07-13 08:49:01.100356",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "company",
-  "ksa_vat_sales_accounts",
-  "ksa_vat_purchase_accounts"
- ],
- "fields": [
-  {
-   "fieldname": "company",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Company",
-   "options": "Company",
-   "reqd": 1,
-   "unique": 1
-  },
-  {
-   "fieldname": "ksa_vat_sales_accounts",
-   "fieldtype": "Table",
-   "label": "KSA VAT Sales Accounts",
-   "options": "KSA VAT Sales Account",
-   "reqd": 1
-  },
-  {
-   "fieldname": "ksa_vat_purchase_accounts",
-   "fieldtype": "Table",
-   "label": "KSA VAT Purchase Accounts",
-   "options": "KSA VAT Purchase Account",
-   "reqd": 1
-  }
- ],
- "links": [],
- "modified": "2021-08-26 04:29:06.499378",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA VAT Setting",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "company",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.py b/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.py
deleted file mode 100644
index bdae116..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Havenir Solutions and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class KSAVATSetting(Document):
-	pass
diff --git a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting_list.js b/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting_list.js
deleted file mode 100644
index 269cbec..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/ksa_vat_setting_list.js
+++ /dev/null
@@ -1,5 +0,0 @@
-frappe.listview_settings['KSA VAT Setting'] = {
-	onload () {
-		frappe.breadcrumbs.add('Accounts');
-	}
-}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/ksa_vat_setting/test_ksa_vat_setting.py b/erpnext/regional/doctype/ksa_vat_setting/test_ksa_vat_setting.py
deleted file mode 100644
index 7207901..0000000
--- a/erpnext/regional/doctype/ksa_vat_setting/test_ksa_vat_setting.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Havenir Solutions and Contributors
-# See license.txt
-
-# import frappe
-import unittest
-
-
-class TestKSAVATSetting(unittest.TestCase):
-	pass
diff --git a/erpnext/regional/print_format/ksa_pos_invoice/__init__.py b/erpnext/regional/print_format/ksa_pos_invoice/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/print_format/ksa_pos_invoice/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json b/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json
deleted file mode 100644
index c2a3092..0000000
--- a/erpnext/regional/print_format/ksa_pos_invoice/ksa_pos_invoice.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "absolute_value": 0,
- "align_labels_right": 0,
- "creation": "2021-12-07 13:25:05.424827",
- "css": "",
- "custom_format": 1,
- "default_print_language": "en",
- "disabled": 1,
- "doc_type": "POS Invoice",
- "docstatus": 0,
- "doctype": "Print Format",
- "font_size": 0,
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t<img src={{doc.ksa_einv_qr}}>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Cashier\") }}:</b> {{ doc.owner }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Time\") }}:</b> {{  doc.get_formatted(\"posting_time\") }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"35%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"net_amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t    {% if '%' in row.description %}\n\t\t\t\t\t    {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t    {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 60%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
- "idx": 0,
- "line_breaks": 0,
- "margin_bottom": 0.0,
- "margin_left": 0.0,
- "margin_right": 0.0,
- "margin_top": 0.0,
- "modified": "2021-12-08 10:25:01.930885",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA POS Invoice",
- "owner": "Administrator",
- "page_number": "Hide",
- "print_format_builder": 0,
- "print_format_builder_beta": 0,
- "print_format_type": "Jinja",
- "raw_printing": 0,
- "show_section_headings": 0,
- "standard": "Yes"
-}
\ No newline at end of file
diff --git a/erpnext/regional/print_format/ksa_vat_invoice/__init__.py b/erpnext/regional/print_format/ksa_vat_invoice/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/print_format/ksa_vat_invoice/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json b/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json
deleted file mode 100644
index 6b64d47..0000000
--- a/erpnext/regional/print_format/ksa_vat_invoice/ksa_vat_invoice.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "absolute_value": 0,
- "align_labels_right": 0,
- "creation": "2021-10-29 22:46:26.039023",
- "css": ".qr-code{\n    float:right;\n}\n\n.invoice-heading {\n  margin: 0;\n}\n\n.ksa-invoice-table {\n  border: 1px solid #888a8e;\n  border-collapse: collapse;\n  width: 100%;\n  margin: 20px 0;\n  font-size: 16px;\n}\n\n.ksa-invoice-table.two-columns td:nth-child(2) {\n  direction: rtl;\n}\n\n.ksa-invoice-table th {\n  border: 1px solid #888a8e;\n  max-width: 50%;\n  padding: 8px;\n}\n\n.ksa-invoice-table td {\n  padding: 5px;\n  border: 1px solid #888a8e;\n  max-width: 50%;\n}\n\n.ksa-invoice-table thead,\n.ksa-invoice-table tfoot {\n  text-transform: uppercase;\n}\n\n.qr-rtl {\n  direction: rtl;\n}\n\n.qr-flex{\n    display: flex;\n    justify-content: space-between;\n}",
- "custom_format": 1,
- "default_print_language": "en",
- "disabled": 1,
- "doc_type": "Sales Invoice",
- "docstatus": 0,
- "doctype": "Print Format",
- "font_size": 14,
- "html": "<div class=\"ksa-vat-format\">\n    <div class=\"qr-flex\">\n        <div style=\"qr-flex: 1\">\n            <h2 class=\"invoice-heading\">TAX INVOICE</h2>\n            <h2 class=\"invoice-heading\">\u0641\u0627\u062a\u0648\u0631\u0629 \u0636\u0631\u064a\u0628\u064a\u0629</h2>\n        </div>\n        \n        <img class=\"qr-code\" src={{doc.ksa_einv_qr}}>\n    </div>\n    {% set company = frappe.get_doc(\"Company\", doc.company)%}\n    {% if (doc.company_address) %}\n        {% set supplier_address_doc = frappe.get_doc('Address', doc.company_address) %}\n    {% endif %}\n    \n    {% if(doc.customer_address) %}\n        {% set customer_address = frappe.get_doc('Address', doc.customer_address ) %}\n    {% endif %}\n    \n    {% if(doc.shipping_address_name) %}\n        {% set customer_shipping_address = frappe.get_doc('Address', doc.shipping_address_name ) %}\n    {% endif %}  \n        \n    <table class=\"ksa-invoice-table two-columns\">\n      <thead>\n        <tr>\n          <th>{{ company.name }}</th>\n          <th style=\"text-align: right;\">{{ company.company_name_in_arabic }}</th>\n        </tr>\n      </thead>\n\n      <tbody>\n        <!-- Invoice Info -->\n        <tr>\n          <td>Invoice#: {{doc.name}}</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.name}}</td>\n        </tr>\n        <tr>\n          <td>Invoice Date: {{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0641\u0627\u062a\u0648\u0631\u0629: {{doc.posting_date}}</td>\n        </tr>\n        <tr>\n          <td>Date of Supply:{{doc.posting_date}}</td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0648\u0631\u064a\u062f: {{doc.posting_date}}</td>\n        </tr>\n        \n        <!--Supplier Info -->\n        <tr>\n          <td>Supplier:</td>\n          <td>\u0627\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n\t\t{% if (company.tax_id) %}\n        <tr>\n          <td>Supplier Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0645\u0648\u0631\u062f:</td>\n        </tr>\n        <tr>\n          <td>{{ company.tax_id }}</td>\n          <td>{{ company.tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td>{{ company.name }}</td>\n          <td>{{ company.company_name_in_arabic }} </td>\n        </tr>\n        \n        \n        {% if(supplier_address_doc) %}\n        <tr>\n          <td>{{ supplier_address_doc.address_line1}} </td>\n          <td>{{ supplier_address_doc.address_in_arabic}} </td>\n        </tr>\n        <tr>\n          <td>Phone: {{ supplier_address_doc.phone }}</td>\n          <td>\u0647\u0627\u062a\u0641: {{ supplier_address_doc.phone }}</td>\n        </tr>\n        <tr>\n          <td>Email: {{ supplier_address_doc.email_id }}</td>\n          <td>\u0628\u0631\u064a\u062f \u0627\u0644\u0643\u062a\u0631\u0648\u0646\u064a: {{ supplier_address_doc.email_id }}</td>\n        </tr>\n        {% endif %}\n        \n        <!-- Customer Info -->\n        <tr>\n          <td>CUSTOMER:</td>\n          <td>\u0639\u0645\u064a\u0644:</td>\n        </tr>\n\t\t{% set customer_tax_id = frappe.db.get_value('Customer', doc.customer, 'tax_id') %}\n\t\t{% if customer_tax_id %}\n        <tr>\n          <td>Customer Tax Identification Number:</td>\n          <td>\u0631\u0642\u0645 \u0627\u0644\u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0636\u0631\u064a\u0628\u064a \u0644\u0644\u0639\u0645\u064a\u0644:</td>\n        </tr>\n        <tr>\n          <td>{{ customer_tax_id }}</td>\n          <td>{{ customer_tax_id }}</td>\n        </tr>\n        {% endif %}\n        <tr>\n          <td> {{ doc.customer }}</td>\n          <td> {{ doc.customer_name_in_arabic }} </td>\n        </tr>\n        \n        {% if(customer_address) %}\n        <tr>\n          <td>{{ customer_address.address_line1}} </td>\n          <td>{{ customer_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n        {% if(customer_shipping_address) %}\n        <tr>\n          <td>SHIPPING ADDRESS:</td>\n          <td>\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0634\u062d\u0646:</td>\n        </tr>\n        \n        <tr>\n          <td>{{ customer_shipping_address.address_line1}} </td>\n          <td>{{ customer_shipping_address.address_in_arabic}} </td>\n        </tr>\n        {% endif %}\n        \n\t\t{% if(doc.po_no) %}\n        <tr>\n          <td>OTHER INFORMATION</td>\n          <td>\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0623\u062e\u0631\u0649</td>\n        </tr>\n        \n        <tr>\n          <td>Purchase Order Number: {{ doc.po_no }}</td>\n          <td>\u0631\u0642\u0645 \u0623\u0645\u0631 \u0627\u0644\u0634\u0631\u0627\u0621: {{ doc.po_no }}</td>\n        </tr>\n        {% endif %}\n        \n        <tr>\n          <td>Payment Due Date: {{  doc.due_date}} </td>\n          <td>\u062a\u0627\u0631\u064a\u062e \u0627\u0633\u062a\u062d\u0642\u0627\u0642 \u0627\u0644\u062f\u0641\u0639: {{  doc.due_date}}</td>\n        </tr>\n      </tbody>\n    </table>\n\n    <!--Dynamic Colspan for total row columns-->\n    {% set col = namespace(one = 2, two = 1) %}\n    {% set length = doc.taxes | length %}\n    {% set length = length / 2 | round %}\n    {% set col.one = col.one + length %}\n    {% set col.two = col.two + length %}\n  \n    {%- if(doc.taxes | length % 2 > 0 ) -%}\n      {% set col.two = col.two + 1 %}\n    {% endif %}\n    \n    <!-- Items -->\n    {% set total = namespace(amount = 0) %}\n    <table class=\"ksa-invoice-table\">\n      <thead>\n        <tr>\n          <th>Nature of goods or services <br />\u0637\u0628\u064a\u0639\u0629 \u0627\u0644\u0633\u0644\u0639 \u0623\u0648 \u0627\u0644\u062e\u062f\u0645\u0627\u062a</th>\n          <th>\n            Unit price <br />\n            \u0633\u0639\u0631 \u0627\u0644\u0648\u062d\u062f\u0629\n          </th>\n          <th>\n            Quantity <br />\n            \u0627\u0644\u0643\u0645\u064a\u0629\n          </th>\n          <th>\n            Taxable Amount <br />\n            \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u062e\u0627\u0636\u0639 \u0644\u0644\u0636\u0631\u064a\u0628\u0629\n          </th>\n          \n          {% for row in doc.taxes %}\n            <th style=\"min-width: 130px\">{{row.description}}</th>\n          {% endfor %}\n          \n          <th>\n            Total <br />\n            \u0627\u0644\u0645\u062c\u0645\u0648\u0639\n          </th>\n        </tr>\n      </thead>\n      <tbody>\n        {%- for item in doc.items -%}\n        {% set total.amount = item.amount %}\n        <tr>\n          <td>{{ item.item_code or item.item_name }}</td>\n          <td>{{ item.get_formatted(\"rate\") }}</td>\n          <td>{{ item.qty }}</td>\n          <td>{{ item.get_formatted(\"amount\") }}</td>\n           {% for row in doc.taxes %}\n                {% set data_object = json.loads(row.item_wise_tax_detail) %}\n                {% set key = item.item_code or item.item_name %}\n                {% set tax_amount = frappe.utils.flt(data_object[key][1]/doc.conversion_rate, row.precision('tax_amount')) %}\n                <td>\n                   <div class=\"qr-flex\">\n                    {%- if(data_object[key][0])-%}\n                    <span>{{ frappe.format(data_object[key][0], {'fieldtype': 'Percent'}) }}</span>\n                    {%- endif -%}\n                    <span>\n                    {%- if(data_object[key][1])-%}\n                        {{ frappe.format_value(tax_amount, currency=doc.currency) }}</span>\n                        {% set total.amount = total.amount + tax_amount %}\n                    {%- endif -%}\n                    </div>\n                </td>\n            {% endfor %}\n          <td>{{  frappe.format_value(frappe.utils.flt(total.amount, doc.precision('total_taxes_and_charges')), currency=doc.currency) }}</td>\n        </tr>\n        {%- endfor -%}\n      </tbody>\n      <tfoot>\n        <tr>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n          \n          <td colspan={{ col.one }} class=\"qr-rtl\">\n            \u0627\u0644\u0625\u062c\u0645\u0627\u0644\u064a \u0628\u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n            <br />\n            \u0625\u062c\u0645\u0627\u0644\u064a \u0636\u0631\u064a\u0628\u0629 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0645\u0636\u0627\u0641\u0629\n          </td>\n          <td colspan={{ col.two }}>\n            Total (Excluding VAT)\n            <br />\n            Total VAT\n          </td>\n          <td>\n            {{ doc.get_formatted(\"total\") }} <br />\n            {{ doc.get_formatted(\"total_taxes_and_charges\") }}\n          </td>\n        </tr>\n        <tr>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n          <td  colspan={{  col.one }} class=\"qr-rtl\">\n              \u0625\u062c\u0645\u0627\u0644\u064a \u0627\u0644\u0645\u0628\u0644\u063a \u0627\u0644\u0645\u0633\u062a\u062d\u0642</td>\n          <td  colspan={{  col.two }}>Total Amount Due</td>\n          <td>{{ doc.get_formatted(\"grand_total\") }}</td>\n        </tr>\n      </tfoot>\n    </table>\n\n\t{%- if doc.terms -%}\n    <p>\n      {{doc.terms}}\n    </p>\n\t{%- endif -%}\n</div>\n",
- "idx": 0,
- "line_breaks": 0,
- "margin_bottom": 15.0,
- "margin_left": 15.0,
- "margin_right": 15.0,
- "margin_top": 15.0,
- "modified": "2021-12-07 13:43:38.018593",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA VAT Invoice",
- "owner": "Administrator",
- "page_number": "Hide",
- "print_format_builder": 0,
- "print_format_builder_beta": 0,
- "print_format_type": "Jinja",
- "raw_printing": 0,
- "show_section_headings": 0,
- "standard": "Yes"
-}
\ No newline at end of file
diff --git a/erpnext/regional/report/ksa_vat/__init__.py b/erpnext/regional/report/ksa_vat/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/report/ksa_vat/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.js b/erpnext/regional/report/ksa_vat/ksa_vat.js
deleted file mode 100644
index 59e72c3..0000000
--- a/erpnext/regional/report/ksa_vat/ksa_vat.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2016, Havenir Solutions and contributors
-// For license information, please see license.txt
-/* eslint-disable */
-
-frappe.query_reports["KSA VAT"] = {
-	onload() {
-		frappe.breadcrumbs.add('Accounts');
-	},
-	"filters": [
-		{
-			"fieldname": "company",
-			"label": __("Company"),
-			"fieldtype": "Link",
-			"options": "Company",
-			"reqd": 1,
-			"default": frappe.defaults.get_user_default("Company")
-		},
-		{
-			"fieldname": "from_date",
-			"label": __("From Date"),
-			"fieldtype": "Date",
-			"reqd": 1,
-			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
-		},
-		{
-			"fieldname": "to_date",
-			"label": __("To Date"),
-			"fieldtype": "Date",
-			"reqd": 1,
-			"default": frappe.datetime.get_today()
-		}
-	],
-	"formatter": function(value, row, column, data, default_formatter) {
-		if (data
-			&& (data.title=='VAT on Sales' || data.title=='VAT on Purchases')
-			&& data.title==value) {
-			value = $(`<span>${value}</span>`);
-			var $value = $(value).css("font-weight", "bold");
-			value = $value.wrap("<p></p>").parent().html();
-			return value
-		}else if (data.title=='Grand Total'){
-			if (data.title==value) {
-				value = $(`<span>${value}</span>`);
-				var $value = $(value).css("font-weight", "bold");
-				value = $value.wrap("<p></p>").parent().html();
-				return value
-			}else{
-				value = default_formatter(value, row, column, data);
-				value = $(`<span>${value}</span>`);
-				var $value = $(value).css("font-weight", "bold");
-				value = $value.wrap("<p></p>").parent().html();
-				return value
-			}
-		}else{
-			value = default_formatter(value, row, column, data);
-			return value;
-		}
-	},
-};
diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.json b/erpnext/regional/report/ksa_vat/ksa_vat.json
deleted file mode 100644
index 036e260..0000000
--- a/erpnext/regional/report/ksa_vat/ksa_vat.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "add_total_row": 0,
- "columns": [],
- "creation": "2021-07-13 08:54:38.000949",
- "disable_prepared_report": 1,
- "disabled": 1,
- "docstatus": 0,
- "doctype": "Report",
- "filters": [],
- "idx": 0,
- "is_standard": "Yes",
- "modified": "2021-08-26 04:14:37.202594",
- "modified_by": "Administrator",
- "module": "Regional",
- "name": "KSA VAT",
- "owner": "Administrator",
- "prepared_report": 1,
- "ref_doctype": "GL Entry",
- "report_name": "KSA VAT",
- "report_type": "Script Report",
- "roles": [
-  {
-   "role": "System Manager"
-  },
-  {
-   "role": "Accounts Manager"
-  },
-  {
-   "role": "Accounts User"
-  }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.py b/erpnext/regional/report/ksa_vat/ksa_vat.py
deleted file mode 100644
index 15996d2..0000000
--- a/erpnext/regional/report/ksa_vat/ksa_vat.py
+++ /dev/null
@@ -1,231 +0,0 @@
-# Copyright (c) 2013, Havenir Solutions and contributors
-# For license information, please see license.txt
-
-
-import json
-
-import frappe
-from frappe import _
-from frappe.utils import get_url_to_list
-
-
-def execute(filters=None):
-	columns = columns = get_columns()
-	data = get_data(filters)
-	return columns, data
-
-
-def get_columns():
-	return [
-		{
-			"fieldname": "title",
-			"label": _("Title"),
-			"fieldtype": "Data",
-			"width": 300,
-		},
-		{
-			"fieldname": "amount",
-			"label": _("Amount (SAR)"),
-			"fieldtype": "Currency",
-			"options": "currency",
-			"width": 150,
-		},
-		{
-			"fieldname": "adjustment_amount",
-			"label": _("Adjustment (SAR)"),
-			"fieldtype": "Currency",
-			"options": "currency",
-			"width": 150,
-		},
-		{
-			"fieldname": "vat_amount",
-			"label": _("VAT Amount (SAR)"),
-			"fieldtype": "Currency",
-			"options": "currency",
-			"width": 150,
-		},
-		{
-			"fieldname": "currency",
-			"label": _("Currency"),
-			"fieldtype": "Currency",
-			"width": 150,
-			"hidden": 1,
-		},
-	]
-
-
-def get_data(filters):
-	data = []
-
-	# Validate if vat settings exist
-	company = filters.get("company")
-	company_currency = frappe.get_cached_value("Company", company, "default_currency")
-
-	if frappe.db.exists("KSA VAT Setting", company) is None:
-		url = get_url_to_list("KSA VAT Setting")
-		frappe.msgprint(_('Create <a href="{}">KSA VAT Setting</a> for this company').format(url))
-		return data
-
-	ksa_vat_setting = frappe.get_doc("KSA VAT Setting", company)
-
-	# Sales Heading
-	append_data(data, "VAT on Sales", "", "", "", company_currency)
-
-	grand_total_taxable_amount = 0
-	grand_total_taxable_adjustment_amount = 0
-	grand_total_tax = 0
-
-	for vat_setting in ksa_vat_setting.ksa_vat_sales_accounts:
-		(
-			total_taxable_amount,
-			total_taxable_adjustment_amount,
-			total_tax,
-		) = get_tax_data_for_each_vat_setting(vat_setting, filters, "Sales Invoice")
-
-		# Adding results to data
-		append_data(
-			data,
-			vat_setting.title,
-			total_taxable_amount,
-			total_taxable_adjustment_amount,
-			total_tax,
-			company_currency,
-		)
-
-		grand_total_taxable_amount += total_taxable_amount
-		grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
-		grand_total_tax += total_tax
-
-	# Sales Grand Total
-	append_data(
-		data,
-		"Grand Total",
-		grand_total_taxable_amount,
-		grand_total_taxable_adjustment_amount,
-		grand_total_tax,
-		company_currency,
-	)
-
-	# Blank Line
-	append_data(data, "", "", "", "", company_currency)
-
-	# Purchase Heading
-	append_data(data, "VAT on Purchases", "", "", "", company_currency)
-
-	grand_total_taxable_amount = 0
-	grand_total_taxable_adjustment_amount = 0
-	grand_total_tax = 0
-
-	for vat_setting in ksa_vat_setting.ksa_vat_purchase_accounts:
-		(
-			total_taxable_amount,
-			total_taxable_adjustment_amount,
-			total_tax,
-		) = get_tax_data_for_each_vat_setting(vat_setting, filters, "Purchase Invoice")
-
-		# Adding results to data
-		append_data(
-			data,
-			vat_setting.title,
-			total_taxable_amount,
-			total_taxable_adjustment_amount,
-			total_tax,
-			company_currency,
-		)
-
-		grand_total_taxable_amount += total_taxable_amount
-		grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
-		grand_total_tax += total_tax
-
-	# Purchase Grand Total
-	append_data(
-		data,
-		"Grand Total",
-		grand_total_taxable_amount,
-		grand_total_taxable_adjustment_amount,
-		grand_total_tax,
-		company_currency,
-	)
-
-	return data
-
-
-def get_tax_data_for_each_vat_setting(vat_setting, filters, doctype):
-	"""
-	(KSA, {filters}, 'Sales Invoice') => 500, 153, 10 \n
-	calculates and returns \n
-	total_taxable_amount, total_taxable_adjustment_amount, total_tax"""
-	from_date = filters.get("from_date")
-	to_date = filters.get("to_date")
-
-	# Initiate variables
-	total_taxable_amount = 0
-	total_taxable_adjustment_amount = 0
-	total_tax = 0
-	# Fetch All Invoices
-	invoices = frappe.get_all(
-		doctype,
-		filters={"docstatus": 1, "posting_date": ["between", [from_date, to_date]]},
-		fields=["name", "is_return"],
-	)
-
-	for invoice in invoices:
-		invoice_items = frappe.get_all(
-			f"{doctype} Item",
-			filters={
-				"docstatus": 1,
-				"parent": invoice.name,
-				"item_tax_template": vat_setting.item_tax_template,
-			},
-			fields=["item_code", "net_amount"],
-		)
-
-		for item in invoice_items:
-			# Summing up total taxable amount
-			if invoice.is_return == 0:
-				total_taxable_amount += item.net_amount
-
-			if invoice.is_return == 1:
-				total_taxable_adjustment_amount += item.net_amount
-
-			# Summing up total tax
-			total_tax += get_tax_amount(item.item_code, vat_setting.account, doctype, invoice.name)
-
-	return total_taxable_amount, total_taxable_adjustment_amount, total_tax
-
-
-def append_data(data, title, amount, adjustment_amount, vat_amount, company_currency):
-	"""Returns data with appended value."""
-	data.append(
-		{
-			"title": _(title),
-			"amount": amount,
-			"adjustment_amount": adjustment_amount,
-			"vat_amount": vat_amount,
-			"currency": company_currency,
-		}
-	)
-
-
-def get_tax_amount(item_code, account_head, doctype, parent):
-	if doctype == "Sales Invoice":
-		tax_doctype = "Sales Taxes and Charges"
-
-	elif doctype == "Purchase Invoice":
-		tax_doctype = "Purchase Taxes and Charges"
-
-	item_wise_tax_detail = frappe.get_value(
-		tax_doctype,
-		{"docstatus": 1, "parent": parent, "account_head": account_head},
-		"item_wise_tax_detail",
-	)
-
-	tax_amount = 0
-	if item_wise_tax_detail and len(item_wise_tax_detail) > 0:
-		item_wise_tax_detail = json.loads(item_wise_tax_detail)
-		for key, value in item_wise_tax_detail.items():
-			if key == item_code:
-				tax_amount = value[1]
-				break
-
-	return tax_amount
diff --git a/erpnext/regional/saudi_arabia/__init__.py b/erpnext/regional/saudi_arabia/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/saudi_arabia/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py
deleted file mode 100644
index 7f41c46..0000000
--- a/erpnext/regional/saudi_arabia/setup.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-from frappe.permissions import add_permission, update_permission_property
-from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import (
-	create_ksa_vat_setting,
-)
-from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-
-
-def setup(company=None, patch=True):
-	add_print_formats()
-	add_permissions()
-	make_custom_fields()
-
-
-def add_print_formats():
-	frappe.reload_doc("regional", "print_format", "detailed_tax_invoice", force=True)
-	frappe.reload_doc("regional", "print_format", "simplified_tax_invoice", force=True)
-	frappe.reload_doc("regional", "print_format", "tax_invoice", force=True)
-	frappe.reload_doc("regional", "print_format", "ksa_vat_invoice", force=True)
-	frappe.reload_doc("regional", "print_format", "ksa_pos_invoice", force=True)
-
-	for d in (
-		"Simplified Tax Invoice",
-		"Detailed Tax Invoice",
-		"Tax Invoice",
-		"KSA VAT Invoice",
-		"KSA POS Invoice",
-	):
-		frappe.db.set_value("Print Format", d, "disabled", 0)
-
-
-def add_permissions():
-	"""Add Permissions for KSA VAT Setting."""
-	add_permission("KSA VAT Setting", "All", 0)
-	for role in ("Accounts Manager", "Accounts User", "System Manager"):
-		add_permission("KSA VAT Setting", role, 0)
-		update_permission_property("KSA VAT Setting", role, 0, "write", 1)
-		update_permission_property("KSA VAT Setting", role, 0, "create", 1)
-
-	"""Enable KSA VAT Report"""
-	frappe.db.set_value("Report", "KSA VAT", "disabled", 0)
-
-
-def make_custom_fields():
-	"""Create Custom fields
-	- QR code Image file
-	- Company Name in Arabic
-	- Address in Arabic
-	"""
-	is_zero_rated = dict(
-		fieldname="is_zero_rated",
-		label="Is Zero Rated",
-		fieldtype="Check",
-		fetch_from="item_code.is_zero_rated",
-		insert_after="description",
-		print_hide=1,
-	)
-
-	is_exempt = dict(
-		fieldname="is_exempt",
-		label="Is Exempt",
-		fieldtype="Check",
-		fetch_from="item_code.is_exempt",
-		insert_after="is_zero_rated",
-		print_hide=1,
-	)
-
-	purchase_invoice_fields = [
-		dict(
-			fieldname="company_trn",
-			label="Company TRN",
-			fieldtype="Read Only",
-			insert_after="shipping_address",
-			fetch_from="company.tax_id",
-			print_hide=1,
-		),
-		dict(
-			fieldname="supplier_name_in_arabic",
-			label="Supplier Name in Arabic",
-			fieldtype="Read Only",
-			insert_after="supplier_name",
-			fetch_from="supplier.supplier_name_in_arabic",
-			print_hide=1,
-		),
-	]
-
-	sales_invoice_fields = [
-		dict(
-			fieldname="company_trn",
-			label="Company TRN",
-			fieldtype="Read Only",
-			insert_after="company_address",
-			fetch_from="company.tax_id",
-			print_hide=1,
-		),
-		dict(
-			fieldname="customer_name_in_arabic",
-			label="Customer Name in Arabic",
-			fieldtype="Read Only",
-			insert_after="customer_name",
-			fetch_from="customer.customer_name_in_arabic",
-			print_hide=1,
-		),
-		dict(
-			fieldname="ksa_einv_qr",
-			label="KSA E-Invoicing QR",
-			fieldtype="Attach Image",
-			read_only=1,
-			no_copy=1,
-			hidden=1,
-		),
-	]
-
-	custom_fields = {
-		"Item": [is_zero_rated, is_exempt],
-		"Customer": [
-			dict(
-				fieldname="customer_name_in_arabic",
-				label="Customer Name in Arabic",
-				fieldtype="Data",
-				insert_after="customer_name",
-			),
-		],
-		"Supplier": [
-			dict(
-				fieldname="supplier_name_in_arabic",
-				label="Supplier Name in Arabic",
-				fieldtype="Data",
-				insert_after="supplier_name",
-			),
-		],
-		"Purchase Invoice": purchase_invoice_fields,
-		"Purchase Order": purchase_invoice_fields,
-		"Purchase Receipt": purchase_invoice_fields,
-		"Sales Invoice": sales_invoice_fields,
-		"POS Invoice": sales_invoice_fields,
-		"Sales Order": sales_invoice_fields,
-		"Delivery Note": sales_invoice_fields,
-		"Sales Invoice Item": [is_zero_rated, is_exempt],
-		"POS Invoice Item": [is_zero_rated, is_exempt],
-		"Purchase Invoice Item": [is_zero_rated, is_exempt],
-		"Sales Order Item": [is_zero_rated, is_exempt],
-		"Delivery Note Item": [is_zero_rated, is_exempt],
-		"Quotation Item": [is_zero_rated, is_exempt],
-		"Purchase Order Item": [is_zero_rated, is_exempt],
-		"Purchase Receipt Item": [is_zero_rated, is_exempt],
-		"Supplier Quotation Item": [is_zero_rated, is_exempt],
-		"Address": [
-			dict(
-				fieldname="address_in_arabic",
-				label="Address in Arabic",
-				fieldtype="Data",
-				insert_after="address_line2",
-			)
-		],
-		"Company": [
-			dict(
-				fieldname="company_name_in_arabic",
-				label="Company Name In Arabic",
-				fieldtype="Data",
-				insert_after="company_name",
-			)
-		],
-	}
-
-	create_custom_fields(custom_fields, ignore_validate=True, update=True)
-
-
-def update_regional_tax_settings(country, company):
-	create_ksa_vat_setting(company)
diff --git a/erpnext/regional/saudi_arabia/utils.py b/erpnext/regional/saudi_arabia/utils.py
deleted file mode 100644
index cac5ec1..0000000
--- a/erpnext/regional/saudi_arabia/utils.py
+++ /dev/null
@@ -1,169 +0,0 @@
-import io
-import os
-from base64 import b64encode
-
-import frappe
-from frappe import _
-from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-from frappe.utils.data import add_to_date, get_time, getdate
-from pyqrcode import create as qr_create
-
-from erpnext import get_region
-
-
-def create_qr_code(doc, method=None):
-	region = get_region(doc.company)
-	if region not in ["Saudi Arabia"]:
-		return
-
-	# if QR Code field not present, create it. Invoices without QR are invalid as per law.
-	if not hasattr(doc, "ksa_einv_qr"):
-		create_custom_fields(
-			{
-				doc.doctype: [
-					dict(
-						fieldname="ksa_einv_qr",
-						label="KSA E-Invoicing QR",
-						fieldtype="Attach Image",
-						read_only=1,
-						no_copy=1,
-						hidden=1,
-					)
-				]
-			}
-		)
-
-	# Don't create QR Code if it already exists
-	qr_code = doc.get("ksa_einv_qr")
-	if qr_code and frappe.db.exists({"doctype": "File", "file_url": qr_code}):
-		return
-
-	meta = frappe.get_meta(doc.doctype)
-
-	if "ksa_einv_qr" in [d.fieldname for d in meta.get_image_fields()]:
-		"""TLV conversion for
-		1. Seller's Name
-		2. VAT Number
-		3. Time Stamp
-		4. Invoice Amount
-		5. VAT Amount
-		"""
-		tlv_array = []
-		# Sellers Name
-
-		seller_name = frappe.db.get_value("Company", doc.company, "company_name_in_arabic")
-
-		if not seller_name:
-			frappe.throw(_("Arabic name missing for {} in the company document").format(doc.company))
-
-		tag = bytes([1]).hex()
-		length = bytes([len(seller_name.encode("utf-8"))]).hex()
-		value = seller_name.encode("utf-8").hex()
-		tlv_array.append("".join([tag, length, value]))
-
-		# VAT Number
-		tax_id = frappe.db.get_value("Company", doc.company, "tax_id")
-		if not tax_id:
-			frappe.throw(_("Tax ID missing for {} in the company document").format(doc.company))
-
-		tag = bytes([2]).hex()
-		length = bytes([len(tax_id)]).hex()
-		value = tax_id.encode("utf-8").hex()
-		tlv_array.append("".join([tag, length, value]))
-
-		# Time Stamp
-		posting_date = getdate(doc.posting_date)
-		time = get_time(doc.posting_time)
-		seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
-		time_stamp = add_to_date(posting_date, seconds=seconds)
-		time_stamp = time_stamp.strftime("%Y-%m-%dT%H:%M:%SZ")
-
-		tag = bytes([3]).hex()
-		length = bytes([len(time_stamp)]).hex()
-		value = time_stamp.encode("utf-8").hex()
-		tlv_array.append("".join([tag, length, value]))
-
-		# Invoice Amount
-		invoice_amount = str(doc.base_grand_total)
-		tag = bytes([4]).hex()
-		length = bytes([len(invoice_amount)]).hex()
-		value = invoice_amount.encode("utf-8").hex()
-		tlv_array.append("".join([tag, length, value]))
-
-		# VAT Amount
-		vat_amount = str(get_vat_amount(doc))
-
-		tag = bytes([5]).hex()
-		length = bytes([len(vat_amount)]).hex()
-		value = vat_amount.encode("utf-8").hex()
-		tlv_array.append("".join([tag, length, value]))
-
-		# Joining bytes into one
-		tlv_buff = "".join(tlv_array)
-
-		# base64 conversion for QR Code
-		base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
-
-		qr_image = io.BytesIO()
-		url = qr_create(base64_string, error="L")
-		url.png(qr_image, scale=2, quiet_zone=1)
-
-		name = frappe.generate_hash(doc.name, 5)
-
-		# making file
-		filename = f"QRCode-{name}.png".replace(os.path.sep, "__")
-		_file = frappe.get_doc(
-			{
-				"doctype": "File",
-				"file_name": filename,
-				"is_private": 0,
-				"content": qr_image.getvalue(),
-				"attached_to_doctype": doc.get("doctype"),
-				"attached_to_name": doc.get("name"),
-				"attached_to_field": "ksa_einv_qr",
-			}
-		)
-
-		_file.save()
-
-		# assigning to document
-		doc.db_set("ksa_einv_qr", _file.file_url)
-		doc.notify_update()
-
-
-def get_vat_amount(doc):
-	vat_settings = frappe.db.get_value("KSA VAT Setting", {"company": doc.company})
-	vat_accounts = []
-	vat_amount = 0
-
-	if vat_settings:
-		vat_settings_doc = frappe.get_cached_doc("KSA VAT Setting", vat_settings)
-
-		for row in vat_settings_doc.get("ksa_vat_sales_accounts"):
-			vat_accounts.append(row.account)
-
-	for tax in doc.get("taxes"):
-		if tax.account_head in vat_accounts:
-			vat_amount += tax.base_tax_amount
-
-	return vat_amount
-
-
-def delete_qr_code_file(doc, method=None):
-	region = get_region(doc.company)
-	if region not in ["Saudi Arabia"]:
-		return
-
-	if hasattr(doc, "ksa_einv_qr"):
-		if doc.get("ksa_einv_qr"):
-			file_doc = frappe.get_list("File", {"file_url": doc.get("ksa_einv_qr")})
-			if len(file_doc):
-				frappe.delete_doc("File", file_doc[0].name)
-
-
-def delete_vat_settings_for_company(doc, method=None):
-	if doc.country != "Saudi Arabia":
-		return
-
-	if frappe.db.exists("KSA VAT Setting", doc.name):
-		frappe.delete_doc("KSA VAT Setting", doc.name)
diff --git a/erpnext/regional/saudi_arabia/wizard/__init__.py b/erpnext/regional/saudi_arabia/wizard/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/saudi_arabia/wizard/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/saudi_arabia/wizard/data/__init__.py b/erpnext/regional/saudi_arabia/wizard/data/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/saudi_arabia/wizard/data/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json b/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json
deleted file mode 100644
index 60951a9..0000000
--- a/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json
+++ /dev/null
@@ -1,47 +0,0 @@
-[
-    {
-        "type": "Sales Account",
-        "accounts": [
-            {
-                "title": "Standard rated Sales",
-                "item_tax_template": "KSA VAT 5%",
-                "account": "VAT 5%"
-            },
-            {
-                "title": "Zero rated domestic sales",
-                "item_tax_template": "KSA VAT Zero",
-                "account": "VAT Zero"
-            },
-            {
-                "title": "Exempted sales",
-                "item_tax_template": "KSA VAT Exempted",
-                "account": "VAT Exempted"
-            }
-        ]
-    },
-    {
-        "type": "Purchase Account",
-        "accounts": [
-            {
-                "title": "Standard rated domestic purchases",
-                "item_tax_template": "KSA VAT 5%",
-                "account": "VAT 5%"
-            },
-            {
-                "title": "Imports subject to VAT paid at customs",
-                "item_tax_template": "KSA Excise 50%",
-                "account": "Excise 50%"
-            },
-            {
-                "title": "Zero rated purchases",
-                "item_tax_template": "KSA VAT Zero",
-                "account": "VAT Zero"
-            },
-            {
-                "title": "Exempted purchases",
-                "item_tax_template": "KSA VAT Exempted",
-                "account": "VAT Exempted"
-            }
-        ]
-    }
-]
\ No newline at end of file
diff --git a/erpnext/regional/saudi_arabia/wizard/operations/__init__.py b/erpnext/regional/saudi_arabia/wizard/operations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/regional/saudi_arabia/wizard/operations/__init__.py
+++ /dev/null
diff --git a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py b/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py
deleted file mode 100644
index 66d9df2..0000000
--- a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import json
-import os
-
-import frappe
-
-
-def create_ksa_vat_setting(company):
-	"""On creation of first company. Creates KSA VAT Setting"""
-
-	company = frappe.get_doc("Company", company)
-
-	file_path = os.path.join(os.path.dirname(__file__), "..", "data", "ksa_vat_settings.json")
-	with open(file_path, "r") as json_file:
-		account_data = json.load(json_file)
-
-	# Creating KSA VAT Setting
-	ksa_vat_setting = frappe.get_doc({"doctype": "KSA VAT Setting", "company": company.name})
-
-	for data in account_data:
-		if data["type"] == "Sales Account":
-			for row in data["accounts"]:
-				item_tax_template = row["item_tax_template"]
-				account = row["account"]
-				ksa_vat_setting.append(
-					"ksa_vat_sales_accounts",
-					{
-						"title": row["title"],
-						"item_tax_template": f"{item_tax_template} - {company.abbr}",
-						"account": f"{account} - {company.abbr}",
-					},
-				)
-
-		elif data["type"] == "Purchase Account":
-			for row in data["accounts"]:
-				item_tax_template = row["item_tax_template"]
-				account = row["account"]
-				ksa_vat_setting.append(
-					"ksa_vat_purchase_accounts",
-					{
-						"title": row["title"],
-						"item_tax_template": f"{item_tax_template} - {company.abbr}",
-						"account": f"{account} - {company.abbr}",
-					},
-				)
-
-	ksa_vat_setting.save()
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index fb64772..ee07525 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -309,9 +309,12 @@
 
 	make_work_order() {
 		var me = this;
-		this.frm.call({
-			doc: this.frm.doc,
-			method: 'get_work_order_items',
+		me.frm.call({
+			method: "erpnext.selling.doctype.sales_order.sales_order.get_work_order_items",
+			args: {
+				sales_order: this.frm.docname,
+			},
+			freeze: true,
 			callback: function(r) {
 				if(!r.message) {
 					frappe.msgprint({
@@ -321,14 +324,7 @@
 					});
 					return;
 				}
-				else if(!r.message) {
-					frappe.msgprint({
-						title: __('Work Order not created'),
-						message: __('Work Order already created for all items with BOM'),
-						indicator: 'orange'
-					});
-					return;
-				} else {
+				else {
 					const fields = [{
 						label: 'Items',
 						fieldtype: 'Table',
@@ -429,9 +425,9 @@
 	make_raw_material_request() {
 		var me = this;
 		this.frm.call({
-			doc: this.frm.doc,
-			method: 'get_work_order_items',
+			method: "erpnext.selling.doctype.sales_order.sales_order.get_work_order_items",
 			args: {
+				sales_order: this.frm.docname,
 				for_raw_material_request: 1
 			},
 			callback: function(r) {
@@ -450,6 +446,7 @@
 	}
 
 	make_raw_material_request_dialog(r) {
+		var me = this;
 		var fields = [
 			{fieldtype:'Check', fieldname:'include_exploded_items',
 				label: __('Include Exploded Items')},
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index ca6a51a..385d0f3 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -6,11 +6,12 @@
 
 import frappe
 import frappe.utils
-from frappe import _
+from frappe import _, qb
 from frappe.contacts.doctype.address.address import get_company_address
 from frappe.desk.notifications import clear_doctype_notifications
 from frappe.model.mapper import get_mapped_doc
 from frappe.model.utils import get_fetch_values
+from frappe.query_builder.functions import Sum
 from frappe.utils import add_days, cint, cstr, flt, get_link_to_form, getdate, nowdate, strip_html
 
 from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
@@ -414,51 +415,6 @@
 			self.indicator_color = "green"
 			self.indicator_title = _("Paid")
 
-	@frappe.whitelist()
-	def get_work_order_items(self, for_raw_material_request=0):
-		"""Returns items with BOM that already do not have a linked work order"""
-		items = []
-		item_codes = [i.item_code for i in self.items]
-		product_bundle_parents = [
-			pb.new_item_code
-			for pb in frappe.get_all(
-				"Product Bundle", {"new_item_code": ["in", item_codes]}, ["new_item_code"]
-			)
-		]
-
-		for table in [self.items, self.packed_items]:
-			for i in table:
-				bom = get_default_bom(i.item_code)
-				stock_qty = i.qty if i.doctype == "Packed Item" else i.stock_qty
-
-				if not for_raw_material_request:
-					total_work_order_qty = flt(
-						frappe.db.sql(
-							"""select sum(qty) from `tabWork Order`
-						where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2""",
-							(i.item_code, self.name, i.name),
-						)[0][0]
-					)
-					pending_qty = stock_qty - total_work_order_qty
-				else:
-					pending_qty = stock_qty
-
-				if pending_qty and i.item_code not in product_bundle_parents:
-					items.append(
-						dict(
-							name=i.name,
-							item_code=i.item_code,
-							description=i.description,
-							bom=bom or "",
-							warehouse=i.warehouse,
-							pending_qty=pending_qty,
-							required_qty=pending_qty if for_raw_material_request else 0,
-							sales_order_item=i.name,
-						)
-					)
-
-		return items
-
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date):
 			delivery_date = auto_repeat_doc.get_next_schedule_date(schedule_date=ref_doc_delivery_date)
@@ -1350,3 +1306,57 @@
 		return
 
 	frappe.db.set_value("Sales Order Item", sales_order_item, "produced_qty", total_produced_qty)
+
+
+@frappe.whitelist()
+def get_work_order_items(sales_order, for_raw_material_request=0):
+	"""Returns items with BOM that already do not have a linked work order"""
+	if sales_order:
+		so = frappe.get_doc("Sales Order", sales_order)
+
+		wo = qb.DocType("Work Order")
+
+		items = []
+		item_codes = [i.item_code for i in so.items]
+		product_bundle_parents = [
+			pb.new_item_code
+			for pb in frappe.get_all(
+				"Product Bundle", {"new_item_code": ["in", item_codes]}, ["new_item_code"]
+			)
+		]
+
+		for table in [so.items, so.packed_items]:
+			for i in table:
+				bom = get_default_bom(i.item_code)
+				stock_qty = i.qty if i.doctype == "Packed Item" else i.stock_qty
+
+				if not for_raw_material_request:
+					total_work_order_qty = flt(
+						qb.from_(wo)
+						.select(Sum(wo.qty))
+						.where(
+							(wo.production_item == i.item_code)
+							& (wo.sales_order == so.name) * (wo.sales_order_item == i.name)
+							& (wo.docstatus.lte(2))
+						)
+						.run()[0][0]
+					)
+					pending_qty = stock_qty - total_work_order_qty
+				else:
+					pending_qty = stock_qty
+
+				if pending_qty and i.item_code not in product_bundle_parents:
+					items.append(
+						dict(
+							name=i.name,
+							item_code=i.item_code,
+							description=i.description,
+							bom=bom or "",
+							warehouse=i.warehouse,
+							pending_qty=pending_qty,
+							required_qty=pending_qty if for_raw_material_request else 0,
+							sales_order_item=i.name,
+						)
+					)
+
+		return items
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index d4d7c58..627914f 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -1217,6 +1217,8 @@
 		self.assertTrue(si.get("payment_schedule"))
 
 	def test_make_work_order(self):
+		from erpnext.selling.doctype.sales_order.sales_order import get_work_order_items
+
 		# Make a new Sales Order
 		so = make_sales_order(
 			**{
@@ -1230,7 +1232,7 @@
 		# Raise Work Orders
 		po_items = []
 		so_item_name = {}
-		for item in so.get_work_order_items():
+		for item in get_work_order_items(so.name):
 			po_items.append(
 				{
 					"warehouse": item.get("warehouse"),
@@ -1448,6 +1450,7 @@
 
 		from erpnext.controllers.item_variant import create_variant
 		from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+		from erpnext.selling.doctype.sales_order.sales_order import get_work_order_items
 
 		make_item(  # template item
 			"Test-WO-Tshirt",
@@ -1487,7 +1490,7 @@
 				]
 			}
 		)
-		wo_items = so.get_work_order_items()
+		wo_items = get_work_order_items(so.name)
 
 		self.assertEqual(wo_items[0].get("item_code"), "Test-WO-Tshirt-R")
 		self.assertEqual(wo_items[0].get("bom"), red_var_bom.name)
@@ -1497,6 +1500,8 @@
 		self.assertEqual(wo_items[1].get("bom"), template_bom.name)
 
 	def test_request_for_raw_materials(self):
+		from erpnext.selling.doctype.sales_order.sales_order import get_work_order_items
+
 		item = make_item(
 			"_Test Finished Item",
 			{
@@ -1529,7 +1534,7 @@
 		so = make_sales_order(**{"item_list": [{"item_code": item.item_code, "qty": 1, "rate": 1000}]})
 		so.submit()
 		mr_dict = frappe._dict()
-		items = so.get_work_order_items(1)
+		items = get_work_order_items(so.name, 1)
 		mr_dict["items"] = items
 		mr_dict["include_exploded_items"] = 0
 		mr_dict["ignore_existing_ordered_qty"] = 1
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index 44c4d54..2624db3 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -216,7 +216,7 @@
 	)
 
 	if filters.get("item_group"):
-		query = query.where(db_so_item.item_group == frappe.db.escape(filters.item_group))
+		query = query.where(db_so_item.item_group == filters.item_group)
 
 	if filters.get("from_date"):
 		query = query.where(db_so.transaction_date >= filters.from_date)
@@ -225,7 +225,7 @@
 		query = query.where(db_so.transaction_date <= filters.to_date)
 
 	if filters.get("item_code"):
-		query = query.where(db_so_item.item_group == frappe.db.escape(filters.item_code))
+		query = query.where(db_so_item.item_code == filters.item_code)
 
 	if filters.get("customer"):
 		query = query.where(db_so.customer == filters.customer)
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 8ff01f5..5ce6e9c 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -418,8 +418,6 @@
 			callback: function(r) {
 				if(r.message) {
 					frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message);
-				} else {
-				    frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message);
 				}
 			}
 		});
diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py
index facefa3..ece5a7d 100755
--- a/erpnext/setup/doctype/employee/employee.py
+++ b/erpnext/setup/doctype/employee/employee.py
@@ -8,7 +8,6 @@
 	get_doc_permissions,
 	has_permission,
 	remove_user_permission,
-	set_user_permission_if_allowed,
 )
 from frappe.utils import cstr, getdate, today, validate_email_address
 from frappe.utils.nestedset import NestedSet
@@ -96,7 +95,7 @@
 			return
 
 		add_user_permission("Employee", self.name, self.user_id)
-		set_user_permission_if_allowed("Company", self.company, self.user_id)
+		add_user_permission("Company", self.company, self.user_id)
 
 	def update_user(self):
 		# add employee role if missing
diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
index 4256a7d..481a3a5 100644
--- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
+++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
@@ -3,13 +3,17 @@
 
 
 import frappe
-from frappe import _
+from frappe import _, qb
 from frappe.desk.notifications import clear_notifications
 from frappe.model.document import Document
-from frappe.utils import cint
+from frappe.utils import cint, create_batch
 
 
 class TransactionDeletionRecord(Document):
+	def __init__(self, *args, **kwargs):
+		super(TransactionDeletionRecord, self).__init__(*args, **kwargs)
+		self.batch_size = 5000
+
 	def validate(self):
 		frappe.only_for("System Manager")
 		self.validate_doctypes_to_be_ignored()
@@ -155,8 +159,9 @@
 			"DocField", filters={"fieldtype": "Table", "parent": doctype}, pluck="options"
 		)
 
-		for table in child_tables:
-			frappe.db.delete(table, {"parent": ["in", parent_docs_to_be_deleted]})
+		for batch in create_batch(parent_docs_to_be_deleted, self.batch_size):
+			for table in child_tables:
+				frappe.db.delete(table, {"parent": ["in", batch]})
 
 	def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
 		frappe.db.delete(doctype, {company_fieldname: self.company})
@@ -181,13 +186,16 @@
 		frappe.db.sql("""update `tabSeries` set current = %s where name=%s""", (last, prefix))
 
 	def delete_version_log(self, doctype, company_fieldname):
-		frappe.db.sql(
-			"""delete from `tabVersion` where ref_doctype=%s and docname in
-			(select name from `tab{0}` where `{1}`=%s)""".format(
-				doctype, company_fieldname
-			),
-			(doctype, self.company),
-		)
+		dt = qb.DocType(doctype)
+		names = qb.from_(dt).select(dt.name).where(dt[company_fieldname] == self.company).run(as_list=1)
+		names = [x[0] for x in names]
+
+		if names:
+			versions = qb.DocType("Version")
+			for batch in create_batch(names, self.batch_size):
+				qb.from_(versions).delete().where(
+					(versions.ref_doctype == doctype) & (versions.docname.isin(batch))
+				).run()
 
 	def delete_communications(self, doctype, company_fieldname):
 		reference_docs = frappe.get_all(doctype, filters={company_fieldname: self.company})
@@ -199,7 +207,8 @@
 		)
 		communication_names = [c.name for c in communications]
 
-		frappe.delete_doc("Communication", communication_names, ignore_permissions=True)
+		for batch in create_batch(communication_names, self.batch_size):
+			frappe.delete_doc("Communication", batch, ignore_permissions=True)
 
 
 @frappe.whitelist()
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 45e39c5..5750914 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -4015,34 +4015,6 @@
 			"tax_rate": 18.00
 		}
 	},
-
-	"Saudi Arabia": {
-		"KSA VAT 15%": {
-			"account_name": "VAT 15%",
-			"tax_rate": 15.00
-		},
-		"KSA VAT 5%": {
-			"account_name": "VAT 5%",
-			"tax_rate": 5.00
-		},
-		"KSA VAT Zero": {
-			"account_name": "VAT Zero",
-			"tax_rate": 0.00
-		},
-		"KSA VAT Exempted": {
-			"account_name": "VAT Exempted",
-			"tax_rate": 0.00
-		},
-		"KSA Excise 50%": {
-			"account_name": "Excise 50%",
-			"tax_rate": 50.00
-		},
-		"KSA Excise 100%": {
-			"account_name": "Excise 100%",
-			"tax_rate": 100.00
-		}
-	},
-
 	"Serbia": {
 		"Serbia Tax": {
 			"account_name": "VAT",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index ea3cf19..ae56645 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -97,12 +97,12 @@
 		}
 
 		if (frm.doc.docstatus == 1 && !frm.doc.inter_company_reference) {
-			let internal = me.frm.doc.is_internal_customer;
+			let internal = frm.doc.is_internal_customer;
 			if (internal) {
-				let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Purchase Receipt" :
+				let button_label = (frm.doc.company === frm.doc.represents_company) ? "Internal Purchase Receipt" :
 					"Inter Company Purchase Receipt";
 
-				me.frm.add_custom_button(button_label, function() {
+				frm.add_custom_button(__(button_label), function() {
 					frappe.model.open_mapped_doc({
 						method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
 						frm: frm,
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 5bcb05a..9a9ddf4 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -33,6 +33,9 @@
 			'Material Request': () => {
 				open_form(frm, "Material Request", "Material Request Item", "items");
 			},
+			'Stock Entry': () => {
+				open_form(frm, "Stock Entry", "Stock Entry Detail", "items");
+			},
 		};
 
 	},
@@ -893,6 +896,9 @@
 		new_child_doc.item_name = frm.doc.item_name;
 		new_child_doc.uom = frm.doc.stock_uom;
 		new_child_doc.description = frm.doc.description;
+		if (!new_child_doc.qty) {
+			new_child_doc.qty = 1.0;
+		}
 
 		frappe.run_serially([
 			() => frappe.ui.form.make_quick_entry(doctype, null, null, new_doc),
diff --git a/erpnext/stock/doctype/item_price/item_price.js b/erpnext/stock/doctype/item_price/item_price.js
index 12cf6cf..ce489ff 100644
--- a/erpnext/stock/doctype/item_price/item_price.js
+++ b/erpnext/stock/doctype/item_price/item_price.js
@@ -2,7 +2,18 @@
 // License: GNU General Public License v3. See license.txt
 
 frappe.ui.form.on("Item Price", {
-	onload: function (frm) {
+	setup(frm) {
+		frm.set_query("item_code", function() {
+			return {
+				filters: {
+					"disabled": 0,
+					"has_variants": 0
+				}
+			};
+		});
+	},
+
+	onload(frm) {
 		// Fetch price list details
 		frm.add_fetch("price_list", "buying", "buying");
 		frm.add_fetch("price_list", "selling", "selling");
diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py
index bcd31ad..54d1ae6 100644
--- a/erpnext/stock/doctype/item_price/item_price.py
+++ b/erpnext/stock/doctype/item_price/item_price.py
@@ -3,7 +3,7 @@
 
 
 import frappe
-from frappe import _
+from frappe import _, bold
 from frappe.model.document import Document
 from frappe.query_builder import Criterion
 from frappe.query_builder.functions import Cast_
@@ -21,6 +21,7 @@
 		self.update_price_list_details()
 		self.update_item_details()
 		self.check_duplicates()
+		self.validate_item_template()
 
 	def validate_item(self):
 		if not frappe.db.exists("Item", self.item_code):
@@ -49,6 +50,12 @@
 				"Item", self.item_code, ["item_name", "description"]
 			)
 
+	def validate_item_template(self):
+		if frappe.get_cached_value("Item", self.item_code, "has_variants"):
+			msg = f"Item Price cannot be created for the template item {bold(self.item_code)}"
+
+			frappe.throw(_(msg))
+
 	def check_duplicates(self):
 
 		item_price = frappe.qb.DocType("Item Price")
diff --git a/erpnext/stock/doctype/item_price/test_item_price.py b/erpnext/stock/doctype/item_price/test_item_price.py
index 30d933e..8fd4938 100644
--- a/erpnext/stock/doctype/item_price/test_item_price.py
+++ b/erpnext/stock/doctype/item_price/test_item_price.py
@@ -16,6 +16,28 @@
 		frappe.db.sql("delete from `tabItem Price`")
 		make_test_records_for_doctype("Item Price", force=True)
 
+	def test_template_item_price(self):
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		item = make_item(
+			"Test Template Item 1",
+			{
+				"has_variants": 1,
+				"variant_based_on": "Manufacturer",
+			},
+		)
+
+		doc = frappe.get_doc(
+			{
+				"doctype": "Item Price",
+				"price_list": "_Test Price List",
+				"item_code": item.name,
+				"price_list_rate": 100,
+			}
+		)
+
+		self.assertRaises(frappe.ValidationError, doc.save)
+
 	def test_duplicate_item(self):
 		doc = frappe.copy_doc(test_records[0])
 		self.assertRaises(ItemPriceDuplicateItem, doc.save)
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index b3af309..111a0861 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -55,7 +55,6 @@
 			self.get_items_from_purchase_receipts()
 
 		self.set_applicable_charges_on_item()
-		self.validate_applicable_charges_for_item()
 
 	def check_mandatory(self):
 		if not self.get("purchase_receipts"):
@@ -115,6 +114,13 @@
 				total_item_cost += item.get(based_on_field)
 
 			for item in self.get("items"):
+				if not total_item_cost and not item.get(based_on_field):
+					frappe.throw(
+						_(
+							"It's not possible to distribute charges equally when total amount is zero, please set 'Distribute Charges Based On' as 'Quantity'"
+						)
+					)
+
 				item.applicable_charges = flt(
 					flt(item.get(based_on_field)) * (flt(self.total_taxes_and_charges) / flt(total_item_cost)),
 					item.precision("applicable_charges"),
@@ -162,6 +168,7 @@
 			)
 
 	def on_submit(self):
+		self.validate_applicable_charges_for_item()
 		self.update_landed_cost()
 
 	def on_cancel(self):
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 979b5c4..00fa168 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -175,6 +175,59 @@
 		)
 		self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 50.0)
 
+	def test_landed_cost_voucher_for_zero_purchase_rate(self):
+		"Test impact of LCV on future stock balances."
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		item = make_item("LCV Stock Item", {"is_stock_item": 1})
+		warehouse = "Stores - _TC"
+
+		pr = make_purchase_receipt(
+			item_code=item.name,
+			warehouse=warehouse,
+			qty=10,
+			rate=0,
+			posting_date=add_days(frappe.utils.nowdate(), -2),
+		)
+
+		self.assertEqual(
+			frappe.db.get_value(
+				"Stock Ledger Entry",
+				{"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "is_cancelled": 0},
+				"stock_value_difference",
+			),
+			0,
+		)
+
+		lcv = make_landed_cost_voucher(
+			company=pr.company,
+			receipt_document_type="Purchase Receipt",
+			receipt_document=pr.name,
+			charges=100,
+			distribute_charges_based_on="Distribute Manually",
+			do_not_save=True,
+		)
+
+		lcv.get_items_from_purchase_receipts()
+		lcv.items[0].applicable_charges = 100
+		lcv.save()
+		lcv.submit()
+
+		self.assertTrue(
+			frappe.db.exists(
+				"Stock Ledger Entry",
+				{"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "is_cancelled": 0},
+			)
+		)
+		self.assertEqual(
+			frappe.db.get_value(
+				"Stock Ledger Entry",
+				{"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "is_cancelled": 0},
+				"stock_value_difference",
+			),
+			100,
+		)
+
 	def test_landed_cost_voucher_against_purchase_invoice(self):
 
 		pi = make_purchase_invoice(
@@ -516,7 +569,7 @@
 
 	lcv = frappe.new_doc("Landed Cost Voucher")
 	lcv.company = args.company or "_Test Company"
-	lcv.distribute_charges_based_on = "Amount"
+	lcv.distribute_charges_based_on = args.distribute_charges_based_on or "Amount"
 
 	lcv.set(
 		"purchase_receipts",
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 6426fe8..dcbc460 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -587,6 +587,9 @@
 
 	def set_missing_values(source, target):
 		target.purpose = source.material_request_type
+		target.from_warehouse = source.set_from_warehouse
+		target.to_warehouse = source.set_warehouse
+
 		if source.job_card:
 			target.purpose = "Material Transfer for Manufacture"
 
@@ -722,6 +725,7 @@
 def make_in_transit_stock_entry(source_name, in_transit_warehouse):
 	ste_doc = make_stock_entry(source_name)
 	ste_doc.add_to_transit = 1
+	ste_doc.to_warehouse = in_transit_warehouse
 
 	for row in ste_doc.items:
 		row.t_warehouse = in_transit_warehouse
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index af0d148..c8a4bd3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -473,7 +473,7 @@
 					)
 
 					divisional_loss = flt(
-						valuation_amount_as_per_doc - stock_value_diff, d.precision("base_net_amount")
+						valuation_amount_as_per_doc - flt(stock_value_diff), d.precision("base_net_amount")
 					)
 
 					if divisional_loss:
@@ -887,18 +887,10 @@
 
 	# Update Billing % based on pending accepted qty
 	total_amount, total_billed_amount = 0, 0
-	for item in pr_doc.items:
-		return_data = frappe.get_all(
-			"Purchase Receipt",
-			fields=["sum(abs(`tabPurchase Receipt Item`.qty)) as qty"],
-			filters=[
-				["Purchase Receipt", "docstatus", "=", 1],
-				["Purchase Receipt", "is_return", "=", 1],
-				["Purchase Receipt Item", "purchase_receipt_item", "=", item.name],
-			],
-		)
+	item_wise_returned_qty = get_item_wise_returned_qty(pr_doc)
 
-		returned_qty = return_data[0].qty if return_data else 0
+	for item in pr_doc.items:
+		returned_qty = flt(item_wise_returned_qty.get(item.name))
 		returned_amount = flt(returned_qty) * flt(item.rate)
 		pending_amount = flt(item.amount) - returned_amount
 		total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt
@@ -915,6 +907,27 @@
 		pr_doc.notify_update()
 
 
+def get_item_wise_returned_qty(pr_doc):
+	items = [d.name for d in pr_doc.items]
+
+	return frappe._dict(
+		frappe.get_all(
+			"Purchase Receipt",
+			fields=[
+				"`tabPurchase Receipt Item`.purchase_receipt_item",
+				"sum(abs(`tabPurchase Receipt Item`.qty)) as qty",
+			],
+			filters=[
+				["Purchase Receipt", "docstatus", "=", 1],
+				["Purchase Receipt", "is_return", "=", 1],
+				["Purchase Receipt Item", "purchase_receipt_item", "in", items],
+			],
+			group_by="`tabPurchase Receipt Item`.purchase_receipt_item",
+			as_list=1,
+		)
+	)
+
+
 @frappe.whitelist()
 def make_purchase_invoice(source_name, target_doc=None):
 	from erpnext.accounts.party import get_payment_terms_template
@@ -1121,13 +1134,25 @@
 						account.expense_account, {"amount": 0.0, "base_amount": 0.0}
 					)
 
-					item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account][
-						"amount"
-					] += (account.amount * item.get(based_on_field) / total_item_cost)
+					if total_item_cost > 0:
+						item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][
+							account.expense_account
+						]["amount"] += (
+							account.amount * item.get(based_on_field) / total_item_cost
+						)
 
-					item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account][
-						"base_amount"
-					] += (account.base_amount * item.get(based_on_field) / total_item_cost)
+						item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][
+							account.expense_account
+						]["base_amount"] += (
+							account.base_amount * item.get(based_on_field) / total_item_cost
+						)
+					else:
+						item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][
+							account.expense_account
+						]["amount"] += item.applicable_charges
+						item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][
+							account.expense_account
+						]["base_amount"] += item.applicable_charges
 
 	return item_account_wise_cost
 
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 557bb59..7a350b9 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -859,7 +859,8 @@
    "label": "Purchase Receipt Item",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "search_index": 1
   },
   {
    "collapsible": 1,
@@ -974,7 +975,8 @@
    "label": "Purchase Invoice Item",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "search_index": 1
   },
   {
    "fieldname": "product_bundle",
@@ -1010,7 +1012,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-11-02 12:49:28.746701",
+ "modified": "2023-01-18 15:48:58.114923",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 8b63c0f..da17cde 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -306,7 +306,7 @@
 		query = query.where(sle.item_code.isin(items))
 
 	for field in ["voucher_no", "batch_no", "project", "company"]:
-		if filters.get(field):
+		if filters.get(field) and field not in inventory_dimension_fields:
 			query = query.where(sle[field] == filters.get(field))
 
 	query = apply_warehouse_filter(query, sle, filters)
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 5a0a863..bec3ce2 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -9916,3 +9916,5 @@
 Delivered at Place,Geliefert benannter Ort,
 Delivered at Place Unloaded,Geliefert benannter Ort entladen,
 Delivered Duty Paid,Geliefert verzollt,
+Discount Validity,Frist für den Rabatt,
+Discount Validity Based On,Frist für den Rabatt berechnet sich nach,