Merge pull request #37539 from HarryPaulo/fix-purchase-order-analyse-invoiced-qty

fix: billed_qty to show a sum of all invoiced qty from the purchase order item.
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 3a2c3cb..8f76492 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -302,3 +302,30 @@
 		default_dimensions_map[dimension.company][dimension.fieldname] = dimension.default_dimension
 
 	return dimension_filters, default_dimensions_map
+
+
+def create_accounting_dimensions_for_doctype(doctype):
+	accounting_dimensions = frappe.db.get_all(
+		"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
+	)
+
+	if not accounting_dimensions:
+		return
+
+	for d in accounting_dimensions:
+		field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
+
+		if field:
+			continue
+
+		df = {
+			"fieldname": d.fieldname,
+			"label": d.label,
+			"fieldtype": "Link",
+			"options": d.document_type,
+			"insert_after": "accounting_dimensions_section",
+		}
+
+		create_custom_field(doctype, df, ignore_validate=True)
+
+	frappe.clear_cache(doctype=doctype)
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index ce15bcf..5f0b434 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -1,13 +1,9 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
 import json
 
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import flt, get_url, nowdate
+from frappe.utils import flt, nowdate
 from frappe.utils.background_jobs import enqueue
 
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
@@ -363,33 +359,6 @@
 	def get_payment_success_url(self):
 		return self.payment_success_url
 
-	def on_payment_authorized(self, status=None):
-		if not status:
-			return
-
-		shopping_cart_settings = frappe.get_doc("E Commerce Settings")
-
-		if status in ["Authorized", "Completed"]:
-			redirect_to = None
-			self.set_as_paid()
-
-			# if shopping cart enabled and in session
-			if (
-				shopping_cart_settings.enabled
-				and hasattr(frappe.local, "session")
-				and frappe.local.session.user != "Guest"
-			) and self.payment_channel != "Phone":
-
-				success_url = shopping_cart_settings.payment_success_url
-				if success_url:
-					redirect_to = ({"Orders": "/orders", "Invoices": "/invoices", "My Account": "/me"}).get(
-						success_url, "/me"
-					)
-				else:
-					redirect_to = get_url("/orders/{0}".format(self.reference_name))
-
-			return redirect_to
-
 	def create_subscription(self, payment_provider, gateway_controller, data):
 		if payment_provider == "stripe":
 			with payment_app_import_guard():
@@ -546,13 +515,12 @@
 
 
 def get_gateway_details(args):  # nosemgrep
-	"""return gateway and payment account of default payment gateway"""
-	if args.get("payment_gateway_account"):
-		return get_payment_gateway_account(args.get("payment_gateway_account"))
-
-	if args.order_type == "Shopping Cart":
-		payment_gateway_account = frappe.get_doc("E Commerce Settings").payment_gateway_account
-		return get_payment_gateway_account(payment_gateway_account)
+	"""
+	Return gateway and payment account of default payment gateway
+	"""
+	gateway_account = args.get("payment_gateway_account", {"is_default": 1})
+	if gateway_account:
+		return get_payment_gateway_account(gateway_account)
 
 	gateway_account = get_payment_gateway_account({"is_default": 1})
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index e489882..2d1f445 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -36,6 +36,7 @@
   "currency_and_price_list",
   "currency",
   "conversion_rate",
+  "use_transaction_date_exchange_rate",
   "column_break2",
   "buying_price_list",
   "price_list_currency",
@@ -1588,13 +1589,20 @@
    "label": "Repost Required",
    "options": "Account",
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "use_transaction_date_exchange_rate",
+   "fieldtype": "Check",
+   "label": "Use Transaction Date Exchange Rate",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-10-01 21:01:47.282533",
+ "modified": "2023-10-16 16:24:51.886231",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
index 75223c2..f6e5c56 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
@@ -22,7 +22,7 @@
 
 @frappe.whitelist()
 def get_plan_rate(
-	plan, quantity=1, customer=None, start_date=None, end_date=None, prorate_factor=1
+	plan, quantity=1, customer=None, start_date=None, end_date=None, prorate_factor=1, party=None
 ):
 	plan = frappe.get_doc("Subscription Plan", plan)
 	if plan.price_determination == "Fixed Rate":
@@ -40,6 +40,7 @@
 			customer_group=customer_group,
 			company=None,
 			qty=quantity,
+			party=party,
 		)
 		if not price:
 			return 0
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py
index 87c5e6d..ac0dd51 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py
@@ -8,7 +8,7 @@
 from frappe import _
 from frappe.contacts.doctype.address.address import get_default_address
 from frappe.model.document import Document
-from frappe.utils import cint, cstr
+from frappe.utils import cstr
 from frappe.utils.nestedset import get_root_of
 
 from erpnext.setup.doctype.customer_group.customer_group import get_parent_customer_groups
@@ -34,7 +34,6 @@
 		self.validate_tax_template()
 		self.validate_from_to_dates("from_date", "to_date")
 		self.validate_filters()
-		self.validate_use_for_shopping_cart()
 
 	def validate_tax_template(self):
 		if self.tax_type == "Sales":
@@ -106,21 +105,6 @@
 			if tax_rule[0].priority == self.priority:
 				frappe.throw(_("Tax Rule Conflicts with {0}").format(tax_rule[0].name), ConflictingTaxRule)
 
-	def validate_use_for_shopping_cart(self):
-		"""If shopping cart is enabled and no tax rule exists for shopping cart, enable this one"""
-		if (
-			not self.use_for_shopping_cart
-			and cint(frappe.db.get_single_value("E Commerce Settings", "enabled"))
-			and not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1, "name": ["!=", self.name]})
-		):
-
-			self.use_for_shopping_cart = 1
-			frappe.msgprint(
-				_(
-					"Enabling 'Use for Shopping Cart', as Shopping Cart is enabled and there should be at least one Tax Rule for Shopping Cart"
-				)
-			)
-
 
 @frappe.whitelist()
 def get_party_details(party, party_type, args=None):
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index e3b671f..b9c7a0b 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -116,7 +116,7 @@
 		# build all keys, since we want to exclude vouchers beyond the report date
 		for ple in self.ple_entries:
 			# get the balance object for voucher_type
-			key = (ple.voucher_type, ple.voucher_no, ple.party)
+			key = (ple.account, ple.voucher_type, ple.voucher_no, ple.party)
 			if not key in self.voucher_balance:
 				self.voucher_balance[key] = frappe._dict(
 					voucher_type=ple.voucher_type,
@@ -183,7 +183,7 @@
 			):
 				return
 
-		key = (ple.against_voucher_type, ple.against_voucher_no, ple.party)
+		key = (ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party)
 
 		# If payment is made against credit note
 		# and credit note is made against a Sales Invoice
@@ -192,13 +192,13 @@
 			if ple.against_voucher_no in self.return_entries:
 				return_against = self.return_entries.get(ple.against_voucher_no)
 				if return_against:
-					key = (ple.against_voucher_type, return_against, ple.party)
+					key = (ple.account, ple.against_voucher_type, return_against, ple.party)
 
 		row = self.voucher_balance.get(key)
 
 		if not row:
 			# no invoice, this is an invoice / stand-alone payment / credit note
-			row = self.voucher_balance.get((ple.voucher_type, ple.voucher_no, ple.party))
+			row = self.voucher_balance.get((ple.account, ple.voucher_type, ple.voucher_no, ple.party))
 
 		row.party_type = ple.party_type
 		return row
diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
index 4307689..cbeb6d3 100644
--- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
@@ -1,6 +1,7 @@
 import unittest
 
 import frappe
+from frappe import qb
 from frappe.tests.utils import FrappeTestCase, change_settings
 from frappe.utils import add_days, flt, getdate, today
 
@@ -23,29 +24,6 @@
 	def tearDown(self):
 		frappe.db.rollback()
 
-	def create_usd_account(self):
-		name = "Debtors USD"
-		exists = frappe.db.get_list(
-			"Account", filters={"company": "_Test Company 2", "account_name": "Debtors USD"}
-		)
-		if exists:
-			self.debtors_usd = exists[0].name
-		else:
-			debtors = frappe.get_doc(
-				"Account",
-				frappe.db.get_list(
-					"Account", filters={"company": "_Test Company 2", "account_name": "Debtors"}
-				)[0].name,
-			)
-
-			debtors_usd = frappe.new_doc("Account")
-			debtors_usd.company = debtors.company
-			debtors_usd.account_name = "Debtors USD"
-			debtors_usd.account_currency = "USD"
-			debtors_usd.parent_account = debtors.parent_account
-			debtors_usd.account_type = debtors.account_type
-			self.debtors_usd = debtors_usd.save().name
-
 	def create_sales_invoice(self, no_payment_schedule=False, do_not_submit=False):
 		frappe.set_user("Administrator")
 		si = create_sales_invoice(
@@ -643,3 +621,94 @@
 		self.assertEqual(len(report[1]), 2)
 		output_for = set([x.party for x in report[1]])
 		self.assertEqual(output_for, expected_output)
+
+	def test_report_output_if_party_is_missing(self):
+		acc_name = "Additional Debtors"
+		if not frappe.db.get_value(
+			"Account", filters={"account_name": acc_name, "company": self.company}
+		):
+			additional_receivable_acc = frappe.get_doc(
+				{
+					"doctype": "Account",
+					"account_name": acc_name,
+					"parent_account": "Accounts Receivable - " + self.company_abbr,
+					"company": self.company,
+					"account_type": "Receivable",
+				}
+			).save()
+			self.debtors2 = additional_receivable_acc.name
+
+		je = frappe.new_doc("Journal Entry")
+		je.company = self.company
+		je.posting_date = today()
+		je.append(
+			"accounts",
+			{
+				"account": self.debit_to,
+				"party_type": "Customer",
+				"party": self.customer,
+				"debit_in_account_currency": 150,
+				"credit_in_account_currency": 0,
+				"cost_center": self.cost_center,
+			},
+		)
+		je.append(
+			"accounts",
+			{
+				"account": self.debtors2,
+				"party_type": "Customer",
+				"party": self.customer,
+				"debit_in_account_currency": 200,
+				"credit_in_account_currency": 0,
+				"cost_center": self.cost_center,
+			},
+		)
+		je.append(
+			"accounts",
+			{
+				"account": self.cash,
+				"debit_in_account_currency": 0,
+				"credit_in_account_currency": 350,
+				"cost_center": self.cost_center,
+			},
+		)
+		je.save().submit()
+
+		# manually remove party from Payment Ledger
+		ple = qb.DocType("Payment Ledger Entry")
+		qb.update(ple).set(ple.party, None).where(ple.voucher_no == je.name).run()
+
+		filters = {
+			"company": self.company,
+			"report_date": today(),
+			"range1": 30,
+			"range2": 60,
+			"range3": 90,
+			"range4": 120,
+		}
+
+		report_ouput = execute(filters)[1]
+		expected_data = [
+			[self.debtors2, je.doctype, je.name, "Customer", self.customer, 200.0, 0.0, 0.0, 200.0],
+			[self.debit_to, je.doctype, je.name, "Customer", self.customer, 150.0, 0.0, 0.0, 150.0],
+		]
+		self.assertEqual(len(report_ouput), 2)
+		# fetch only required fields
+		report_output = [
+			[
+				x.party_account,
+				x.voucher_type,
+				x.voucher_no,
+				"Customer",
+				self.customer,
+				x.invoiced,
+				x.paid,
+				x.credit_note,
+				x.outstanding,
+			]
+			for x in report_ouput
+		]
+		# use account name to sort
+		# post sorting output should be [[Additional Debtors, ...], [Debtors, ...]]
+		report_output = sorted(report_output, key=lambda x: x[0])
+		self.assertEqual(expected_data, report_output)
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 8c73e56..71cb01b 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -24,6 +24,7 @@
   "bill_for_rejected_quantity_in_purchase_invoice",
   "disable_last_purchase_rate",
   "show_pay_button",
+  "use_transaction_date_exchange_rate",
   "subcontract",
   "backflush_raw_materials_of_subcontract_based_on",
   "column_break_11",
@@ -164,6 +165,13 @@
    "fieldname": "over_order_allowance",
    "fieldtype": "Float",
    "label": "Over Order Allowance (%)"
+  },
+  {
+   "default": "0",
+   "description": "While making Purchase Invoice from Purchase Order, use Exchange Rate on Invoice's transaction date rather than inheriting it from Purchase Order. Only applies for Purchase Invoice.",
+   "fieldname": "use_transaction_date_exchange_rate",
+   "fieldtype": "Check",
+   "label": "Use Transaction Date Exchange Rate"
   }
  ],
  "icon": "fa fa-cog",
@@ -171,7 +179,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-03-02 17:02:14.404622",
+ "modified": "2023-10-16 16:22:03.201078",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index e170044..cc5d643 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -584,6 +584,17 @@
 					self.currency, self.company_currency, transaction_date, args
 				)
 
+			if (
+				self.currency
+				and buying_or_selling == "Buying"
+				and frappe.db.get_single_value("Buying Settings", "use_transaction_date_exchange_rate")
+				and self.doctype == "Purchase Invoice"
+			):
+				self.use_transaction_date_exchange_rate = True
+				self.conversion_rate = get_exchange_rate(
+					self.currency, self.company_currency, transaction_date, args
+				)
+
 	def set_missing_item_details(self, for_validate=False):
 		"""set missing item values"""
 		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index e68ee90..c8785a5 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -9,6 +9,8 @@
 from frappe import _
 from frappe.utils import cstr, flt
 
+from erpnext.utilities.product import get_item_codes_by_attributes
+
 
 class ItemVariantExistsError(frappe.ValidationError):
 	pass
@@ -24,7 +26,8 @@
 
 @frappe.whitelist()
 def get_variant(template, args=None, variant=None, manufacturer=None, manufacturer_part_no=None):
-	"""Validates Attributes and their Values, then looks for an exactly
+	"""
+	Validates Attributes and their Values, then looks for an exactly
 	matching Item Variant
 
 	:param item: Template Item
@@ -34,13 +37,14 @@
 
 	if item_template.variant_based_on == "Manufacturer" and manufacturer:
 		return make_variant_based_on_manufacturer(item_template, manufacturer, manufacturer_part_no)
-	else:
-		if isinstance(args, str):
-			args = json.loads(args)
 
-		if not args:
-			frappe.throw(_("Please specify at least one attribute in the Attributes table"))
-		return find_variant(template, args, variant)
+	if isinstance(args, str):
+		args = json.loads(args)
+
+	if not args:
+		frappe.throw(_("Please specify at least one attribute in the Attributes table"))
+
+	return find_variant(template, args, variant)
 
 
 def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part_no):
@@ -157,17 +161,6 @@
 
 
 def find_variant(template, args, variant_item_code=None):
-	conditions = [
-		"""(iv_attribute.attribute={0} and iv_attribute.attribute_value={1})""".format(
-			frappe.db.escape(key), frappe.db.escape(cstr(value))
-		)
-		for key, value in args.items()
-	]
-
-	conditions = " or ".join(conditions)
-
-	from erpnext.e_commerce.variant_selector.utils import get_item_codes_by_attributes
-
 	possible_variants = [
 		i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code
 	]
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 418a56f..c01ac81 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -4,7 +4,6 @@
 
 import frappe
 from frappe import _, bold, throw
-from frappe.contacts.doctype.address.address import get_address_display
 from frappe.utils import cint, flt, get_link_to_form, nowtime
 
 from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -593,6 +592,12 @@
 				)
 
 	def set_customer_address(self):
+		try:
+			from frappe.contacts.doctype.address.address import render_address
+		except ImportError:
+			# Older frappe versions where this function is not available
+			from frappe.contacts.doctype.address.address import get_address_display as render_address
+
 		address_dict = {
 			"customer_address": "address_display",
 			"shipping_address_name": "shipping_address",
@@ -602,7 +607,8 @@
 
 		for address_field, address_display_field in address_dict.items():
 			if self.get(address_field):
-				self.set(address_display_field, get_address_display(self.get(address_field)))
+				address = frappe.call(render_address, self.get(address_field), ignore_permissions=True)
+				self.set(address_display_field, address)
 
 	def validate_for_duplicate_items(self):
 		check_list, chk_dupl_itm = [], []
diff --git a/erpnext/e_commerce/__init__.py b/erpnext/e_commerce/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/api.py b/erpnext/e_commerce/api.py
deleted file mode 100644
index bfada0f..0000000
--- a/erpnext/e_commerce/api.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import json
-
-import frappe
-from frappe.utils import cint
-
-from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder
-from erpnext.e_commerce.product_data_engine.query import ProductQuery
-from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website
-
-
-@frappe.whitelist(allow_guest=True)
-def get_product_filter_data(query_args=None):
-	"""
-	Returns filtered products and discount filters.
-	:param query_args (dict): contains filters to get products list
-
-	Query Args filters:
-	search (str): Search Term.
-	field_filters (dict): Keys include item_group, brand, etc.
-	attribute_filters(dict): Keys include Color, Size, etc.
-	start (int): Offset items by
-	item_group (str): Valid Item Group
-	from_filters (bool): Set as True to jump to page 1
-	"""
-	if isinstance(query_args, str):
-		query_args = json.loads(query_args)
-
-	query_args = frappe._dict(query_args)
-	if query_args:
-		search = query_args.get("search")
-		field_filters = query_args.get("field_filters", {})
-		attribute_filters = query_args.get("attribute_filters", {})
-		start = cint(query_args.start) if query_args.get("start") else 0
-		item_group = query_args.get("item_group")
-		from_filters = query_args.get("from_filters")
-	else:
-		search, attribute_filters, item_group, from_filters = None, None, None, None
-		field_filters = {}
-		start = 0
-
-	# if new filter is checked, reset start to show filtered items from page 1
-	if from_filters:
-		start = 0
-
-	sub_categories = []
-	if item_group:
-		sub_categories = get_child_groups_for_website(item_group, immediate=True)
-
-	engine = ProductQuery()
-	try:
-		result = engine.query(
-			attribute_filters, field_filters, search_term=search, start=start, item_group=item_group
-		)
-	except Exception:
-		frappe.log_error("Product query with filter failed")
-		return {"exc": "Something went wrong!"}
-
-	# discount filter data
-	filters = {}
-	discounts = result["discounts"]
-
-	if discounts:
-		filter_engine = ProductFiltersBuilder()
-		filters["discount_filters"] = filter_engine.get_discount_filters(discounts)
-
-	return {
-		"items": result["items"] or [],
-		"filters": filters,
-		"settings": engine.settings,
-		"sub_categories": sub_categories,
-		"items_count": result["items_count"],
-	}
-
-
-@frappe.whitelist(allow_guest=True)
-def get_guest_redirect_on_action():
-	return frappe.db.get_single_value("E Commerce Settings", "redirect_on_action")
diff --git a/erpnext/e_commerce/doctype/__init__.py b/erpnext/e_commerce/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/__init__.py b/erpnext/e_commerce/doctype/e_commerce_settings/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/e_commerce_settings/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js
deleted file mode 100644
index c37fa2f..0000000
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on("E Commerce Settings", {
-	onload: function(frm) {
-		if(frm.doc.__onload && frm.doc.__onload.quotation_series) {
-			frm.fields_dict.quotation_series.df.options = frm.doc.__onload.quotation_series;
-			frm.refresh_field("quotation_series");
-		}
-
-		frm.set_query('payment_gateway_account', function() {
-			return { 'filters': { 'payment_channel': "Email" } };
-		});
-	},
-	refresh: function(frm) {
-		if (frm.doc.enabled) {
-			frm.get_field('store_page_docs').$wrapper.removeClass('hide-control').html(
-				`<div>${__("Follow these steps to create a landing page for your store")}:
-					<a href="https://docs.erpnext.com/docs/user/manual/en/website/store-landing-page"
-						style="color: var(--gray-600)">
-						docs/store-landing-page
-					</a>
-				</div>`
-			);
-		}
-
-		frappe.model.with_doctype("Website Item", () => {
-			const web_item_meta = frappe.get_meta('Website Item');
-
-			const valid_fields = web_item_meta.fields.filter(df =>
-				["Link", "Table MultiSelect"].includes(df.fieldtype) && !df.hidden
-			).map(df =>
-				({ label: df.label, value: df.fieldname })
-			);
-
-			frm.get_field("filter_fields").grid.update_docfield_property(
-				'fieldname', 'options', valid_fields
-			);
-		});
-	},
-	enabled: function(frm) {
-		if (frm.doc.enabled === 1) {
-			frm.set_value('enable_variants', 1);
-		}
-		else {
-			frm.set_value('company', '');
-			frm.set_value('price_list', '');
-			frm.set_value('default_customer_group', '');
-			frm.set_value('quotation_series', '');
-		}
-	},
-
-	enable_checkout: function(frm) {
-		if (frm.doc.enable_checkout) {
-			erpnext.utils.check_payments_app();
-		}
-	}
-});
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
deleted file mode 100644
index e6f08f7..0000000
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json
+++ /dev/null
@@ -1,395 +0,0 @@
-{
- "actions": [],
- "creation": "2021-02-10 17:13:39.139103",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "products_per_page",
-  "filter_categories_section",
-  "enable_field_filters",
-  "filter_fields",
-  "enable_attribute_filters",
-  "filter_attributes",
-  "display_settings_section",
-  "hide_variants",
-  "enable_variants",
-  "show_price",
-  "column_break_9",
-  "show_stock_availability",
-  "show_quantity_in_website",
-  "allow_items_not_in_stock",
-  "column_break_13",
-  "show_apply_coupon_code_in_website",
-  "show_contact_us_button",
-  "show_attachments",
-  "section_break_18",
-  "company",
-  "price_list",
-  "enabled",
-  "store_page_docs",
-  "column_break_21",
-  "default_customer_group",
-  "quotation_series",
-  "checkout_settings_section",
-  "enable_checkout",
-  "show_price_in_quotation",
-  "column_break_27",
-  "save_quotations_as_draft",
-  "payment_gateway_account",
-  "payment_success_url",
-  "add_ons_section",
-  "enable_wishlist",
-  "column_break_22",
-  "enable_reviews",
-  "column_break_23",
-  "enable_recommendations",
-  "item_search_settings_section",
-  "redisearch_warning",
-  "search_index_fields",
-  "is_redisearch_enabled",
-  "is_redisearch_loaded",
-  "shop_by_category_section",
-  "slideshow",
-  "guest_display_settings_section",
-  "hide_price_for_guest",
-  "redirect_on_action"
- ],
- "fields": [
-  {
-   "default": "6",
-   "fieldname": "products_per_page",
-   "fieldtype": "Int",
-   "label": "Products per Page"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "filter_categories_section",
-   "fieldtype": "Section Break",
-   "label": "Filters and Categories"
-  },
-  {
-   "default": "0",
-   "fieldname": "hide_variants",
-   "fieldtype": "Check",
-   "label": "Hide Variants"
-  },
-  {
-   "default": "0",
-   "description": "The field filters will also work as categories in the <b>Shop by Category</b> page.",
-   "fieldname": "enable_field_filters",
-   "fieldtype": "Check",
-   "label": "Enable Field Filters (Categories)"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_attribute_filters",
-   "fieldtype": "Check",
-   "label": "Enable Attribute Filters"
-  },
-  {
-   "depends_on": "enable_field_filters",
-   "fieldname": "filter_fields",
-   "fieldtype": "Table",
-   "label": "Website Item Fields",
-   "options": "Website Filter Field"
-  },
-  {
-   "depends_on": "enable_attribute_filters",
-   "fieldname": "filter_attributes",
-   "fieldtype": "Table",
-   "label": "Attributes",
-   "options": "Website Attribute"
-  },
-  {
-   "default": "0",
-   "fieldname": "enabled",
-   "fieldtype": "Check",
-   "in_list_view": 1,
-   "label": "Enable Shopping Cart"
-  },
-  {
-   "depends_on": "doc.enabled",
-   "fieldname": "store_page_docs",
-   "fieldtype": "HTML"
-  },
-  {
-   "fieldname": "display_settings_section",
-   "fieldtype": "Section Break",
-   "label": "Display Settings"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_attachments",
-   "fieldtype": "Check",
-   "label": "Show Public Attachments"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_price",
-   "fieldtype": "Check",
-   "label": "Show Price"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_stock_availability",
-   "fieldtype": "Check",
-   "label": "Show Stock Availability"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_variants",
-   "fieldtype": "Check",
-   "label": "Enable Variant Selection"
-  },
-  {
-   "fieldname": "column_break_13",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_contact_us_button",
-   "fieldtype": "Check",
-   "label": "Show Contact Us Button"
-  },
-  {
-   "default": "0",
-   "depends_on": "show_stock_availability",
-   "fieldname": "show_quantity_in_website",
-   "fieldtype": "Check",
-   "label": "Show Stock Quantity"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_apply_coupon_code_in_website",
-   "fieldtype": "Check",
-   "label": "Show Apply Coupon Code"
-  },
-  {
-   "default": "0",
-   "fieldname": "allow_items_not_in_stock",
-   "fieldtype": "Check",
-   "label": "Allow items not in stock to be added to cart"
-  },
-  {
-   "fieldname": "section_break_18",
-   "fieldtype": "Section Break",
-   "label": "Shopping Cart"
-  },
-  {
-   "depends_on": "enabled",
-   "fieldname": "company",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Company",
-   "mandatory_depends_on": "eval: doc.enabled === 1",
-   "options": "Company",
-   "remember_last_selected_value": 1
-  },
-  {
-   "depends_on": "enabled",
-   "description": "Prices will not be shown if Price List is not set",
-   "fieldname": "price_list",
-   "fieldtype": "Link",
-   "label": "Price List",
-   "mandatory_depends_on": "eval: doc.enabled === 1",
-   "options": "Price List"
-  },
-  {
-   "fieldname": "column_break_21",
-   "fieldtype": "Column Break"
-  },
-  {
-   "depends_on": "enabled",
-   "fieldname": "default_customer_group",
-   "fieldtype": "Link",
-   "ignore_user_permissions": 1,
-   "label": "Default Customer Group",
-   "mandatory_depends_on": "eval: doc.enabled === 1",
-   "options": "Customer Group"
-  },
-  {
-   "depends_on": "enabled",
-   "fieldname": "quotation_series",
-   "fieldtype": "Select",
-   "label": "Quotation Series",
-   "mandatory_depends_on": "eval: doc.enabled === 1"
-  },
-  {
-   "collapsible": 1,
-   "collapsible_depends_on": "eval:doc.enable_checkout",
-   "depends_on": "enabled",
-   "fieldname": "checkout_settings_section",
-   "fieldtype": "Section Break",
-   "label": "Checkout Settings"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_checkout",
-   "fieldtype": "Check",
-   "label": "Enable Checkout"
-  },
-  {
-   "default": "Orders",
-   "depends_on": "enable_checkout",
-   "description": "After payment completion redirect user to selected page.",
-   "fieldname": "payment_success_url",
-   "fieldtype": "Select",
-   "label": "Payment Success Url",
-   "mandatory_depends_on": "enable_checkout",
-   "options": "\nOrders\nInvoices\nMy Account"
-  },
-  {
-   "fieldname": "column_break_27",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval: doc.enable_checkout == 0",
-   "fieldname": "save_quotations_as_draft",
-   "fieldtype": "Check",
-   "label": "Save Quotations as Draft"
-  },
-  {
-   "depends_on": "enable_checkout",
-   "fieldname": "payment_gateway_account",
-   "fieldtype": "Link",
-   "label": "Payment Gateway Account",
-   "mandatory_depends_on": "enable_checkout",
-   "options": "Payment Gateway Account"
-  },
-  {
-   "collapsible": 1,
-   "depends_on": "enable_field_filters",
-   "fieldname": "shop_by_category_section",
-   "fieldtype": "Section Break",
-   "label": "Shop by Category"
-  },
-  {
-   "fieldname": "slideshow",
-   "fieldtype": "Link",
-   "label": "Slideshow",
-   "options": "Website Slideshow"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "add_ons_section",
-   "fieldtype": "Section Break",
-   "label": "Add-ons"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_wishlist",
-   "fieldtype": "Check",
-   "label": "Enable Wishlist"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_reviews",
-   "fieldtype": "Check",
-   "label": "Enable Reviews and Ratings"
-  },
-  {
-   "fieldname": "search_index_fields",
-   "fieldtype": "Small Text",
-   "label": "Search Index Fields",
-   "mandatory_depends_on": "is_redisearch_enabled",
-   "read_only_depends_on": "eval:!doc.is_redisearch_loaded"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "item_search_settings_section",
-   "fieldtype": "Section Break",
-   "label": "Item Search Settings"
-  },
-  {
-   "default": "0",
-   "fieldname": "is_redisearch_loaded",
-   "fieldtype": "Check",
-   "hidden": 1,
-   "label": "Is Redisearch Loaded"
-  },
-  {
-   "depends_on": "eval:!doc.is_redisearch_loaded",
-   "fieldname": "redisearch_warning",
-   "fieldtype": "HTML",
-   "label": "Redisearch Warning",
-   "options": "<p class=\"alert alert-warning\">Redisearch is not loaded. If you want to use the advanced product search feature, refer <a class=\"alert-link\" href=\"https://docs.erpnext.com/docs/v13/user/manual/en/setting-up/articles/installing-redisearch\" target=\"_blank\">here</a>.</p>"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval:doc.show_price",
-   "fieldname": "hide_price_for_guest",
-   "fieldtype": "Check",
-   "label": "Hide Price for Guest"
-  },
-  {
-   "fieldname": "column_break_9",
-   "fieldtype": "Column Break"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "guest_display_settings_section",
-   "fieldtype": "Section Break",
-   "label": "Guest Display Settings"
-  },
-  {
-   "description": "Link to redirect Guest on actions that need login such as add to cart, wishlist, etc. <b>E.g.: /login</b>",
-   "fieldname": "redirect_on_action",
-   "fieldtype": "Data",
-   "label": "Redirect on Action"
-  },
-  {
-   "fieldname": "column_break_22",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "column_break_23",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_recommendations",
-   "fieldtype": "Check",
-   "label": "Enable Recommendations"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval: doc.enable_checkout == 0",
-   "fieldname": "show_price_in_quotation",
-   "fieldtype": "Check",
-   "label": "Show Price in Quotation"
-  },
-  {
-   "default": "0",
-   "fieldname": "is_redisearch_enabled",
-   "fieldtype": "Check",
-   "label": "Enable Redisearch",
-   "read_only_depends_on": "eval:!doc.is_redisearch_loaded"
-  }
- ],
- "index_web_pages_for_search": 1,
- "issingle": 1,
- "links": [],
- "modified": "2022-04-01 18:35:56.106756",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "E Commerce Settings",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "System Manager",
-   "share": 1,
-   "write": 1
-  }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "states": [],
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py
deleted file mode 100644
index c27d29a..0000000
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-from frappe.utils import comma_and, flt, unique
-
-from erpnext.e_commerce.redisearch_utils import (
-	create_website_items_index,
-	define_autocomplete_dictionary,
-	get_indexable_web_fields,
-	is_search_module_loaded,
-)
-
-
-class ShoppingCartSetupError(frappe.ValidationError):
-	pass
-
-
-class ECommerceSettings(Document):
-	def onload(self):
-		self.get("__onload").quotation_series = frappe.get_meta("Quotation").get_options("naming_series")
-
-		# flag >> if redisearch is installed and loaded
-		self.is_redisearch_loaded = is_search_module_loaded()
-
-	def validate(self):
-		self.validate_field_filters(self.filter_fields, self.enable_field_filters)
-		self.validate_attribute_filters()
-		self.validate_checkout()
-		self.validate_search_index_fields()
-
-		if self.enabled:
-			self.validate_price_list_exchange_rate()
-
-		frappe.clear_document_cache("E Commerce Settings", "E Commerce Settings")
-
-		self.is_redisearch_enabled_pre_save = frappe.db.get_single_value(
-			"E Commerce Settings", "is_redisearch_enabled"
-		)
-
-	def after_save(self):
-		self.create_redisearch_indexes()
-
-	def create_redisearch_indexes(self):
-		# if redisearch is enabled (value changed) create indexes and dictionary
-		value_changed = self.is_redisearch_enabled != self.is_redisearch_enabled_pre_save
-		if self.is_redisearch_loaded and self.is_redisearch_enabled and value_changed:
-			define_autocomplete_dictionary()
-			create_website_items_index()
-
-	@staticmethod
-	def validate_field_filters(filter_fields, enable_field_filters):
-		if not (enable_field_filters and filter_fields):
-			return
-
-		web_item_meta = frappe.get_meta("Website Item")
-		valid_fields = [
-			df.fieldname for df in web_item_meta.fields if df.fieldtype in ["Link", "Table MultiSelect"]
-		]
-
-		for row in filter_fields:
-			if row.fieldname not in valid_fields:
-				frappe.throw(
-					_(
-						"Filter Fields Row #{0}: Fieldname {1} must be of type 'Link' or 'Table MultiSelect'"
-					).format(row.idx, frappe.bold(row.fieldname))
-				)
-
-	def validate_attribute_filters(self):
-		if not (self.enable_attribute_filters and self.filter_attributes):
-			return
-
-		# if attribute filters are enabled, hide_variants should be disabled
-		self.hide_variants = 0
-
-	def validate_checkout(self):
-		if self.enable_checkout and not self.payment_gateway_account:
-			self.enable_checkout = 0
-
-	def validate_search_index_fields(self):
-		if not self.search_index_fields:
-			return
-
-		fields = self.search_index_fields.replace(" ", "")
-		fields = unique(fields.strip(",").split(","))  # Remove extra ',' and remove duplicates
-
-		# All fields should be indexable
-		allowed_indexable_fields = get_indexable_web_fields()
-
-		if not (set(fields).issubset(allowed_indexable_fields)):
-			invalid_fields = list(set(fields).difference(allowed_indexable_fields))
-			num_invalid_fields = len(invalid_fields)
-			invalid_fields = comma_and(invalid_fields)
-
-			if num_invalid_fields > 1:
-				frappe.throw(
-					_("{0} are not valid options for Search Index Field.").format(frappe.bold(invalid_fields))
-				)
-			else:
-				frappe.throw(
-					_("{0} is not a valid option for Search Index Field.").format(frappe.bold(invalid_fields))
-				)
-
-		self.search_index_fields = ",".join(fields)
-
-	def validate_price_list_exchange_rate(self):
-		"Check if exchange rate exists for Price List currency (to Company's currency)."
-		from erpnext.setup.utils import get_exchange_rate
-
-		if not self.enabled or not self.company or not self.price_list:
-			return  # this function is also called from hooks, check values again
-
-		company_currency = frappe.get_cached_value("Company", self.company, "default_currency")
-		price_list_currency = frappe.db.get_value("Price List", self.price_list, "currency")
-
-		if not company_currency:
-			msg = f"Please specify currency in Company {self.company}"
-			frappe.throw(_(msg), title=_("Missing Currency"), exc=ShoppingCartSetupError)
-
-		if not price_list_currency:
-			msg = f"Please specify currency in Price List {frappe.bold(self.price_list)}"
-			frappe.throw(_(msg), title=_("Missing Currency"), exc=ShoppingCartSetupError)
-
-		if price_list_currency != company_currency:
-			from_currency, to_currency = price_list_currency, company_currency
-
-			# Get exchange rate checks Currency Exchange Records too
-			exchange_rate = get_exchange_rate(from_currency, to_currency, args="for_selling")
-
-			if not flt(exchange_rate):
-				msg = f"Missing Currency Exchange Rates for {from_currency}-{to_currency}"
-				frappe.throw(_(msg), title=_("Missing"), exc=ShoppingCartSetupError)
-
-	def validate_tax_rule(self):
-		if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1}, "name"):
-			frappe.throw(frappe._("Set Tax Rule for shopping cart"), ShoppingCartSetupError)
-
-	def get_tax_master(self, billing_territory):
-		tax_master = self.get_name_from_territory(
-			billing_territory, "sales_taxes_and_charges_masters", "sales_taxes_and_charges_master"
-		)
-		return tax_master and tax_master[0] or None
-
-	def get_shipping_rules(self, shipping_territory):
-		return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule")
-
-	def on_change(self):
-		old_doc = self.get_doc_before_save()
-
-		if old_doc:
-			old_fields = old_doc.search_index_fields
-			new_fields = self.search_index_fields
-
-			# if search index fields get changed
-			if not (new_fields == old_fields):
-				create_website_items_index()
-
-
-def validate_cart_settings(doc=None, method=None):
-	frappe.get_doc("E Commerce Settings", "E Commerce Settings").run_method("validate")
-
-
-def get_shopping_cart_settings():
-	return frappe.get_cached_doc("E Commerce Settings")
-
-
-@frappe.whitelist(allow_guest=True)
-def is_cart_enabled():
-	return get_shopping_cart_settings().enabled
-
-
-def show_quantity_in_website():
-	return get_shopping_cart_settings().show_quantity_in_website
-
-
-def check_shopping_cart_enabled():
-	if not get_shopping_cart_settings().enabled:
-		frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError)
-
-
-def show_attachments():
-	return get_shopping_cart_settings().show_attachments
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py
deleted file mode 100644
index 662db4d..0000000
--- a/erpnext/e_commerce/doctype/e_commerce_settings/test_e_commerce_settings.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-import unittest
-
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	ShoppingCartSetupError,
-)
-
-
-class TestECommerceSettings(unittest.TestCase):
-	def tearDown(self):
-		frappe.db.rollback()
-
-	def test_tax_rule_validation(self):
-		frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0")
-		frappe.db.commit()  # nosemgrep
-
-		cart_settings = frappe.get_doc("E Commerce Settings")
-		cart_settings.enabled = 1
-		if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1}, "name"):
-			self.assertRaises(ShoppingCartSetupError, cart_settings.validate_tax_rule)
-
-		frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 1")
-
-	def test_invalid_filter_fields(self):
-		"Check if Item fields are blocked in E Commerce Settings filter fields."
-		from frappe.custom.doctype.custom_field.custom_field import create_custom_field
-
-		setup_e_commerce_settings({"enable_field_filters": 1})
-
-		create_custom_field(
-			"Item",
-			dict(owner="Administrator", fieldname="test_data", label="Test", fieldtype="Data"),
-		)
-		settings = frappe.get_doc("E Commerce Settings")
-		settings.append("filter_fields", {"fieldname": "test_data"})
-
-		self.assertRaises(frappe.ValidationError, settings.save)
-
-
-def setup_e_commerce_settings(values_dict):
-	"Accepts a dict of values that updates E Commerce Settings."
-	if not values_dict:
-		return
-
-	doc = frappe.get_doc("E Commerce Settings", "E Commerce Settings")
-	doc.update(values_dict)
-	doc.save()
-
-
-test_dependencies = ["Tax Rule"]
diff --git a/erpnext/e_commerce/doctype/item_review/__init__.py b/erpnext/e_commerce/doctype/item_review/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/item_review/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/item_review/item_review.js b/erpnext/e_commerce/doctype/item_review/item_review.js
deleted file mode 100644
index a57c370..0000000
--- a/erpnext/e_commerce/doctype/item_review/item_review.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Item Review', {
-	// refresh: function(frm) {
-
-	// }
-});
diff --git a/erpnext/e_commerce/doctype/item_review/item_review.json b/erpnext/e_commerce/doctype/item_review/item_review.json
deleted file mode 100644
index 57f719f..0000000
--- a/erpnext/e_commerce/doctype/item_review/item_review.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "actions": [],
- "beta": 1,
- "creation": "2021-03-23 16:47:26.542226",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "website_item",
-  "user",
-  "customer",
-  "column_break_3",
-  "item",
-  "published_on",
-  "reviews_section",
-  "review_title",
-  "rating",
-  "comment"
- ],
- "fields": [
-  {
-   "fieldname": "website_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "read_only": 1,
-   "reqd": 1
-  },
-  {
-   "fieldname": "user",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "User",
-   "options": "User",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_3",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "website_item.item_code",
-   "fieldname": "item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item",
-   "options": "Item",
-   "read_only": 1
-  },
-  {
-   "fieldname": "reviews_section",
-   "fieldtype": "Section Break",
-   "label": "Reviews"
-  },
-  {
-   "fieldname": "rating",
-   "fieldtype": "Rating",
-   "in_list_view": 1,
-   "label": "Rating",
-   "read_only": 1
-  },
-  {
-   "fieldname": "comment",
-   "fieldtype": "Small Text",
-   "label": "Comment",
-   "read_only": 1
-  },
-  {
-   "fieldname": "review_title",
-   "fieldtype": "Data",
-   "label": "Review Title",
-   "read_only": 1
-  },
-  {
-   "fieldname": "customer",
-   "fieldtype": "Link",
-   "label": "Customer",
-   "options": "Customer",
-   "read_only": 1
-  },
-  {
-   "fieldname": "published_on",
-   "fieldtype": "Data",
-   "label": "Published on",
-   "read_only": 1
-  }
- ],
- "index_web_pages_for_search": 1,
- "links": [],
- "modified": "2021-08-10 12:08:58.119691",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Item Review",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "System Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Website Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "report": 1,
-   "role": "Customer",
-   "share": 1
-  }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/item_review/item_review.py b/erpnext/e_commerce/doctype/item_review/item_review.py
deleted file mode 100644
index 3e540e3..0000000
--- a/erpnext/e_commerce/doctype/item_review/item_review.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from datetime import datetime
-
-import frappe
-from frappe import _
-from frappe.contacts.doctype.contact.contact import get_contact_name
-from frappe.model.document import Document
-from frappe.utils import cint, flt
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-
-
-class UnverifiedReviewer(frappe.ValidationError):
-	pass
-
-
-class ItemReview(Document):
-	def after_insert(self):
-		# regenerate cache on review creation
-		reviews_dict = get_queried_reviews(self.website_item)
-		set_reviews_in_cache(self.website_item, reviews_dict)
-
-	def after_delete(self):
-		# regenerate cache on review deletion
-		reviews_dict = get_queried_reviews(self.website_item)
-		set_reviews_in_cache(self.website_item, reviews_dict)
-
-
-@frappe.whitelist()
-def get_item_reviews(web_item, start=0, end=10, data=None):
-	"Get Website Item Review Data."
-	start, end = cint(start), cint(end)
-	settings = get_shopping_cart_settings()
-
-	# Get cached reviews for first page (start=0)
-	# avoid cache when page is different
-	from_cache = not bool(start)
-
-	if not data:
-		data = frappe._dict()
-
-	if settings and settings.get("enable_reviews"):
-		reviews_cache = frappe.cache().hget("item_reviews", web_item)
-		if from_cache and reviews_cache:
-			data = reviews_cache
-		else:
-			data = get_queried_reviews(web_item, start, end, data)
-			if from_cache:
-				set_reviews_in_cache(web_item, data)
-
-	return data
-
-
-def get_queried_reviews(web_item, start=0, end=10, data=None):
-	"""
-	Query Website Item wise reviews and cache if needed.
-	Cache stores only first page of reviews i.e. 10 reviews maximum.
-	Returns:
-	        dict: Containing reviews, average ratings, % of reviews per rating and total reviews.
-	"""
-	if not data:
-		data = frappe._dict()
-
-	data.reviews = frappe.db.get_all(
-		"Item Review",
-		filters={"website_item": web_item},
-		fields=["*"],
-		limit_start=start,
-		limit_page_length=end,
-	)
-
-	rating_data = frappe.db.get_all(
-		"Item Review",
-		filters={"website_item": web_item},
-		fields=["avg(rating) as average, count(*) as total"],
-	)[0]
-
-	data.average_rating = flt(rating_data.average, 1)
-	data.average_whole_rating = flt(data.average_rating, 0)
-
-	# get % of reviews per rating
-	reviews_per_rating = []
-	for i in range(1, 6):
-		count = frappe.db.get_all(
-			"Item Review", filters={"website_item": web_item, "rating": i}, fields=["count(*) as count"]
-		)[0].count
-
-		percent = flt((count / rating_data.total or 1) * 100, 0) if count else 0
-		reviews_per_rating.append(percent)
-
-	data.reviews_per_rating = reviews_per_rating
-	data.total_reviews = rating_data.total
-
-	return data
-
-
-def set_reviews_in_cache(web_item, reviews_dict):
-	frappe.cache().hset("item_reviews", web_item, reviews_dict)
-
-
-@frappe.whitelist()
-def add_item_review(web_item, title, rating, comment=None):
-	"""Add an Item Review by a user if non-existent."""
-	if frappe.session.user == "Guest":
-		# guest user should not reach here ideally in the case they do via an API, throw error
-		frappe.throw(_("You are not verified to write a review yet."), exc=UnverifiedReviewer)
-
-	if not frappe.db.exists("Item Review", {"user": frappe.session.user, "website_item": web_item}):
-		doc = frappe.get_doc(
-			{
-				"doctype": "Item Review",
-				"user": frappe.session.user,
-				"customer": get_customer(),
-				"website_item": web_item,
-				"item": frappe.db.get_value("Website Item", web_item, "item_code"),
-				"review_title": title,
-				"rating": rating,
-				"comment": comment,
-			}
-		)
-		doc.published_on = datetime.today().strftime("%d %B %Y")
-		doc.insert()
-
-
-def get_customer(silent=False):
-	"""
-	silent: Return customer if exists else return nothing. Dont throw error.
-	"""
-	user = frappe.session.user
-	contact_name = get_contact_name(user)
-	customer = None
-
-	if contact_name:
-		contact = frappe.get_doc("Contact", contact_name)
-		for link in contact.links:
-			if link.link_doctype == "Customer":
-				customer = link.link_name
-				break
-
-	if customer:
-		return frappe.db.get_value("Customer", customer)
-	elif silent:
-		return None
-	else:
-		# should not reach here unless via an API
-		frappe.throw(
-			_("You are not a verified customer yet. Please contact us to proceed."), exc=UnverifiedReviewer
-		)
diff --git a/erpnext/e_commerce/doctype/item_review/test_item_review.py b/erpnext/e_commerce/doctype/item_review/test_item_review.py
deleted file mode 100644
index 8a4befc..0000000
--- a/erpnext/e_commerce/doctype/item_review/test_item_review.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-import unittest
-
-import frappe
-from frappe.core.doctype.user_permission.test_user_permission import create_user
-
-from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import (
-	setup_e_commerce_settings,
-)
-from erpnext.e_commerce.doctype.item_review.item_review import (
-	UnverifiedReviewer,
-	add_item_review,
-	get_item_reviews,
-)
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-from erpnext.e_commerce.shopping_cart.cart import get_party
-from erpnext.stock.doctype.item.test_item import make_item
-
-
-class TestItemReview(unittest.TestCase):
-	def setUp(self):
-		item = make_item("Test Mobile Phone")
-		if not frappe.db.exists("Website Item", {"item_code": "Test Mobile Phone"}):
-			make_website_item(item, save=True)
-
-		setup_e_commerce_settings({"enable_reviews": 1})
-		frappe.local.shopping_cart_settings = None
-
-	def tearDown(self):
-		frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete()
-		setup_e_commerce_settings({"enable_reviews": 0})
-
-	def test_add_and_get_item_reviews_from_customer(self):
-		"Add / Get Reviews from a User that is a valid customer (has added to cart or purchased in the past)"
-		# create user
-		web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"})
-		test_user = create_user("test_reviewer@example.com", "Customer")
-		frappe.set_user(test_user.name)
-
-		# create customer and contact against user
-		customer = get_party()
-
-		# post review on "Test Mobile Phone"
-		try:
-			add_item_review(web_item, "Great Product", 3, "Would recommend this product")
-			review_name = frappe.db.get_value("Item Review", {"website_item": web_item})
-		except Exception:
-			self.fail(f"Error while publishing review for {web_item}")
-
-		review_data = get_item_reviews(web_item, 0, 10)
-
-		self.assertEqual(len(review_data.reviews), 1)
-		self.assertEqual(review_data.average_rating, 3)
-		self.assertEqual(review_data.reviews_per_rating[2], 100)
-
-		# tear down
-		frappe.set_user("Administrator")
-		frappe.delete_doc("Item Review", review_name)
-		customer.delete()
-
-	def test_add_item_review_from_non_customer(self):
-		"Check if logged in user (who is not a customer yet) is blocked from posting reviews."
-		web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"})
-		test_user = create_user("test_reviewer@example.com", "Customer")
-		frappe.set_user(test_user.name)
-
-		with self.assertRaises(UnverifiedReviewer):
-			add_item_review(web_item, "Great Product", 3, "Would recommend this product")
-
-		# tear down
-		frappe.set_user("Administrator")
-
-	def test_add_item_reviews_from_guest_user(self):
-		"Check if Guest user is blocked from posting reviews."
-		web_item = frappe.db.get_value("Website Item", {"item_code": "Test Mobile Phone"})
-		frappe.set_user("Guest")
-
-		with self.assertRaises(UnverifiedReviewer):
-			add_item_review(web_item, "Great Product", 3, "Would recommend this product")
-
-		# tear down
-		frappe.set_user("Administrator")
diff --git a/erpnext/e_commerce/doctype/recommended_items/__init__.py b/erpnext/e_commerce/doctype/recommended_items/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/recommended_items/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/recommended_items/recommended_items.json b/erpnext/e_commerce/doctype/recommended_items/recommended_items.json
deleted file mode 100644
index 1821532..0000000
--- a/erpnext/e_commerce/doctype/recommended_items/recommended_items.json
+++ /dev/null
@@ -1,88 +0,0 @@
-{
- "actions": [],
- "creation": "2021-07-12 20:52:12.503470",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "website_item",
-  "website_item_name",
-  "column_break_2",
-  "item_code",
-  "more_information_section",
-  "route",
-  "column_break_6",
-  "website_item_image",
-  "website_item_thumbnail"
- ],
- "fields": [
-  {
-   "fieldname": "website_item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Website Item",
-   "options": "Website Item"
-  },
-  {
-   "fetch_from": "website_item.web_item_name",
-   "fieldname": "website_item_name",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Website Item Name",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_2",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "more_information_section",
-   "fieldtype": "Section Break",
-   "label": "More Information"
-  },
-  {
-   "fetch_from": "website_item.route",
-   "fieldname": "route",
-   "fieldtype": "Small Text",
-   "label": "Route",
-   "read_only": 1
-  },
-  {
-   "fetch_from": "website_item.website_image",
-   "fieldname": "website_item_image",
-   "fieldtype": "Attach",
-   "label": "Website Item Image",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_6",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "website_item.thumbnail",
-   "fieldname": "website_item_thumbnail",
-   "fieldtype": "Data",
-   "label": "Website Item Thumbnail",
-   "read_only": 1
-  },
-  {
-   "fetch_from": "website_item.item_code",
-   "fieldname": "item_code",
-   "fieldtype": "Data",
-   "label": "Item Code"
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2022-06-28 16:44:24.718728",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Recommended Items",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "states": [],
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/recommended_items/recommended_items.py b/erpnext/e_commerce/doctype/recommended_items/recommended_items.py
deleted file mode 100644
index 16b6e52..0000000
--- a/erpnext/e_commerce/doctype/recommended_items/recommended_items.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class RecommendedItems(Document):
-	pass
diff --git a/erpnext/e_commerce/doctype/website_item/__init__.py b/erpnext/e_commerce/doctype/website_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/website_item/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/website_item/templates/website_item.html b/erpnext/e_commerce/doctype/website_item/templates/website_item.html
deleted file mode 100644
index db12309..0000000
--- a/erpnext/e_commerce/doctype/website_item/templates/website_item.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block page_content %}
-<h1>{{ title }}</h1>
-{% endblock %}
-
-<!-- this is a sample default web page template -->
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html b/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html
deleted file mode 100644
index d7014b4..0000000
--- a/erpnext/e_commerce/doctype/website_item/templates/website_item_row.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<div>
-	<a href="{{ doc.route }}">{{ doc.title or doc.name }}</a>
-</div>
-<!-- this is a sample default list template -->
diff --git a/erpnext/e_commerce/doctype/website_item/test_website_item.py b/erpnext/e_commerce/doctype/website_item/test_website_item.py
deleted file mode 100644
index 2ba84c0..0000000
--- a/erpnext/e_commerce/doctype/website_item/test_website_item.py
+++ /dev/null
@@ -1,564 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-from erpnext.controllers.item_variant import create_variant
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import (
-	setup_e_commerce_settings,
-)
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website
-from erpnext.stock.doctype.item.item import DataValidationError
-from erpnext.stock.doctype.item.test_item import make_item
-
-WEBITEM_DESK_TESTS = ("test_website_item_desk_item_sync", "test_publish_variant_and_template")
-WEBITEM_PRICE_TESTS = (
-	"test_website_item_price_for_logged_in_user",
-	"test_website_item_price_for_guest_user",
-)
-
-
-class TestWebsiteItem(unittest.TestCase):
-	@classmethod
-	def setUpClass(cls):
-		setup_e_commerce_settings(
-			{
-				"company": "_Test Company",
-				"enabled": 1,
-				"default_customer_group": "_Test Customer Group",
-				"price_list": "_Test Price List India",
-			}
-		)
-
-	@classmethod
-	def tearDownClass(cls):
-		frappe.db.rollback()
-
-	def setUp(self):
-		if self._testMethodName in WEBITEM_DESK_TESTS:
-			make_item(
-				"Test Web Item",
-				{
-					"has_variant": 1,
-					"variant_based_on": "Item Attribute",
-					"attributes": [{"attribute": "Test Size"}],
-				},
-			)
-		elif self._testMethodName in WEBITEM_PRICE_TESTS:
-			create_user_and_customer_if_not_exists(
-				"test_contact_customer@example.com", "_Test Contact For _Test Customer"
-			)
-			create_regular_web_item()
-			make_web_item_price(item_code="Test Mobile Phone")
-
-			# Note: When testing web item pricing rule logged-in user pricing rule must differ from guest pricing rule or test will falsely pass.
-			# 	  This is because make_web_pricing_rule creates a pricing rule "selling": 1, without specifying "applicable_for". Therefor,
-			# 	  when testing for logged-in user the test will get the previous pricing rule because "selling" is still true.
-			#
-			#     I've attempted to mitigate this by setting applicable_for=Customer, and customer=Guest however, this only results in PermissionError failing the test.
-			make_web_pricing_rule(
-				title="Test Pricing Rule for Test Mobile Phone", item_code="Test Mobile Phone", selling=1
-			)
-			make_web_pricing_rule(
-				title="Test Pricing Rule for Test Mobile Phone (Customer)",
-				item_code="Test Mobile Phone",
-				selling=1,
-				discount_percentage="25",
-				applicable_for="Customer",
-				customer="_Test Customer",
-			)
-
-	def test_index_creation(self):
-		"Check if index is getting created in db."
-		from erpnext.e_commerce.doctype.website_item.website_item import on_doctype_update
-
-		on_doctype_update()
-
-		indices = frappe.db.sql("show index from `tabWebsite Item`", as_dict=1)
-		expected_columns = {"route", "item_group", "brand"}
-		for index in indices:
-			expected_columns.discard(index.get("Column_name"))
-
-		if expected_columns:
-			self.fail(f"Expected db index on these columns: {', '.join(expected_columns)}")
-
-	def test_website_item_desk_item_sync(self):
-		"Check creation/updation/deletion of Website Item and its impact on Item master."
-		web_item = None
-		item = make_item("Test Web Item")  # will return item if exists
-		try:
-			web_item = make_website_item(item, save=False)
-			web_item.save()
-		except Exception:
-			self.fail(f"Error while creating website item for {item}")
-
-		# check if website item was created
-		self.assertTrue(bool(web_item))
-		self.assertTrue(bool(web_item.route))
-
-		item.reload()
-		self.assertEqual(web_item.published, 1)
-		self.assertEqual(item.published_in_website, 1)  # check if item was back updated
-		self.assertEqual(web_item.item_group, item.item_group)
-
-		# check if changing item data changes it in website item
-		item.item_name = "Test Web Item 1"
-		item.stock_uom = "Unit"
-		item.save()
-		web_item.reload()
-		self.assertEqual(web_item.item_name, item.item_name)
-		self.assertEqual(web_item.stock_uom, item.stock_uom)
-
-		# check if disabling item unpublished website item
-		item.disabled = 1
-		item.save()
-		web_item.reload()
-		self.assertEqual(web_item.published, 0)
-
-		# check if website item deletion, unpublishes desk item
-		web_item.delete()
-		item.reload()
-		self.assertEqual(item.published_in_website, 0)
-
-		item.delete()
-
-	def test_publish_variant_and_template(self):
-		"Check if template is published on publishing variant."
-		# template "Test Web Item" created on setUp
-		variant = create_variant("Test Web Item", {"Test Size": "Large"})
-		variant.save()
-
-		# check if template is not published
-		self.assertIsNone(frappe.db.exists("Website Item", {"item_code": variant.variant_of}))
-
-		variant_web_item = make_website_item(variant, save=False)
-		variant_web_item.save()
-
-		# check if template is published
-		try:
-			template_web_item = frappe.get_doc("Website Item", {"item_code": variant.variant_of})
-		except frappe.DoesNotExistError:
-			self.fail(f"Template of {variant.item_code}, {variant.variant_of} not published")
-
-		# teardown
-		variant_web_item.delete()
-		template_web_item.delete()
-		variant.delete()
-
-	def test_impact_on_merging_items(self):
-		"Check if merging items is blocked if old and new items both have website items"
-		first_item = make_item("Test First Item")
-		second_item = make_item("Test Second Item")
-
-		first_web_item = make_website_item(first_item, save=False)
-		first_web_item.save()
-		second_web_item = make_website_item(second_item, save=False)
-		second_web_item.save()
-
-		with self.assertRaises(DataValidationError):
-			frappe.rename_doc("Item", "Test First Item", "Test Second Item", merge=True)
-
-		# tear down
-		second_web_item.delete()
-		first_web_item.delete()
-		second_item.delete()
-		first_item.delete()
-
-	# Website Item Portal Tests Begin
-
-	def test_website_item_breadcrumbs(self):
-		"""
-		Check if breadcrumbs include homepage, product listing navigation page,
-		parent item group(s) and item group
-		"""
-		from erpnext.setup.doctype.item_group.item_group import get_parent_item_groups
-
-		item_code = "Test Breadcrumb Item"
-		item = make_item(
-			item_code,
-			{
-				"item_group": "_Test Item Group B - 1",
-			},
-		)
-
-		if not frappe.db.exists("Website Item", {"item_code": item_code}):
-			web_item = make_website_item(item, save=False)
-			web_item.save()
-		else:
-			web_item = frappe.get_cached_doc("Website Item", {"item_code": item_code})
-
-		frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1)
-		frappe.db.set_value("Item Group", "_Test Item Group B", "show_in_website", 1)
-
-		breadcrumbs = get_parent_item_groups(item.item_group)
-
-		settings = frappe.get_cached_doc("E Commerce Settings")
-		if settings.enable_field_filters:
-			base_breadcrumb = "Shop by Category"
-		else:
-			base_breadcrumb = "All Products"
-
-		self.assertEqual(breadcrumbs[0]["name"], "Home")
-		self.assertEqual(breadcrumbs[1]["name"], base_breadcrumb)
-		self.assertEqual(breadcrumbs[2]["name"], "_Test Item Group B")  # parent item group
-		self.assertEqual(breadcrumbs[3]["name"], "_Test Item Group B - 1")
-
-		# tear down
-		web_item.delete()
-		item.delete()
-
-	def test_website_item_price_for_logged_in_user(self):
-		"Check if price details are fetched correctly while logged in."
-		item_code = "Test Mobile Phone"
-
-		# show price in e commerce settings
-		setup_e_commerce_settings({"show_price": 1})
-
-		# price and pricing rule added via setUp
-
-		# login as customer with pricing rule
-		frappe.set_user("test_contact_customer@example.com")
-
-		# check if price and slashed price is fetched correctly
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertTrue(bool(data.product_info["price"]))
-
-		price_object = data.product_info["price"]
-		self.assertEqual(price_object.get("discount_percent"), 25.0)
-		self.assertEqual(price_object.get("price_list_rate"), 750)
-		self.assertEqual(price_object.get("formatted_mrp"), "₹ 1,000.00")
-		self.assertEqual(price_object.get("formatted_price"), "₹ 750.00")
-		self.assertEqual(price_object.get("formatted_discount_percent"), "25.0%")
-
-		# switch to admin and disable show price
-		frappe.set_user("Administrator")
-		setup_e_commerce_settings({"show_price": 0})
-
-		# price should not be fetched for logged in user.
-		frappe.set_user("test_contact_customer@example.com")
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertFalse(bool(data.product_info["price"]))
-
-		# tear down
-		frappe.set_user("Administrator")
-
-	def test_website_item_price_for_guest_user(self):
-		"Check if price details are fetched correctly for guest user."
-		item_code = "Test Mobile Phone"
-
-		# show price for guest user in e commerce settings
-		setup_e_commerce_settings({"show_price": 1, "hide_price_for_guest": 0})
-
-		# price and pricing rule added via setUp
-
-		# switch to guest user
-		frappe.set_user("Guest")
-
-		# price should be fetched
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertTrue(bool(data.product_info["price"]))
-
-		price_object = data.product_info["price"]
-		self.assertEqual(price_object.get("discount_percent"), 10)
-		self.assertEqual(price_object.get("price_list_rate"), 900)
-
-		# hide price for guest user
-		frappe.set_user("Administrator")
-		setup_e_commerce_settings({"hide_price_for_guest": 1})
-		frappe.set_user("Guest")
-
-		# price should not be fetched
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertFalse(bool(data.product_info["price"]))
-
-		# tear down
-		frappe.set_user("Administrator")
-
-	def test_website_item_stock_when_out_of_stock(self):
-		"""
-		Check if stock details are fetched correctly for empty inventory when:
-		1) Showing stock availability enabled:
-		        - Warehouse unset
-		        - Warehouse set
-		2) Showing stock availability disabled
-		"""
-		item_code = "Test Mobile Phone"
-		create_regular_web_item()
-		setup_e_commerce_settings({"show_stock_availability": 1})
-
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-
-		# check if stock details are fetched and item not in stock without warehouse set
-		self.assertFalse(bool(data.product_info["in_stock"]))
-		self.assertFalse(bool(data.product_info["stock_qty"]))
-
-		# set warehouse
-		frappe.db.set_value(
-			"Website Item", {"item_code": item_code}, "website_warehouse", "_Test Warehouse - _TC"
-		)
-
-		# check if stock details are fetched and item not in stock with warehouse set
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertFalse(bool(data.product_info["in_stock"]))
-		self.assertEqual(data.product_info["stock_qty"], 0)
-
-		# disable show stock availability
-		setup_e_commerce_settings({"show_stock_availability": 0})
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-
-		# check if stock detail attributes are not fetched if stock availability is hidden
-		self.assertIsNone(data.product_info.get("in_stock"))
-		self.assertIsNone(data.product_info.get("stock_qty"))
-		self.assertIsNone(data.product_info.get("show_stock_qty"))
-
-		# tear down
-		frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete()
-
-	def test_website_item_stock_when_in_stock(self):
-		"""
-		Check if stock details are fetched correctly for available inventory when:
-		1) Showing stock availability enabled:
-		        - Warehouse set
-		        - Warehouse unset
-		2) Showing stock availability disabled
-		"""
-		from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
-
-		item_code = "Test Mobile Phone"
-		create_regular_web_item()
-		setup_e_commerce_settings({"show_stock_availability": 1})
-		frappe.local.shopping_cart_settings = None
-
-		# set warehouse
-		frappe.db.set_value(
-			"Website Item", {"item_code": item_code}, "website_warehouse", "_Test Warehouse - _TC"
-		)
-
-		# stock up item
-		stock_entry = make_stock_entry(
-			item_code=item_code, target="_Test Warehouse - _TC", qty=2, rate=100
-		)
-
-		# check if stock details are fetched and item is in stock with warehouse set
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertTrue(bool(data.product_info["in_stock"]))
-		self.assertEqual(data.product_info["stock_qty"], 2)
-
-		# unset warehouse
-		frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "")
-
-		# check if stock details are fetched and item not in stock without warehouse set
-		# (even though it has stock in some warehouse)
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-		self.assertFalse(bool(data.product_info["in_stock"]))
-		self.assertFalse(data.product_info["stock_qty"])
-
-		# disable show stock availability
-		setup_e_commerce_settings({"show_stock_availability": 0})
-		frappe.local.shopping_cart_settings = None
-		data = get_product_info_for_website(item_code, skip_quotation_creation=True)
-
-		# check if stock detail attributes are not fetched if stock availability is hidden
-		self.assertIsNone(data.product_info.get("in_stock"))
-		self.assertIsNone(data.product_info.get("stock_qty"))
-		self.assertIsNone(data.product_info.get("show_stock_qty"))
-
-		# tear down
-		stock_entry.cancel()
-		frappe.get_cached_doc("Website Item", {"item_code": "Test Mobile Phone"}).delete()
-
-	def test_recommended_item(self):
-		"Check if added recommended items are fetched correctly."
-		item_code = "Test Mobile Phone"
-		web_item = create_regular_web_item(item_code)
-
-		setup_e_commerce_settings({"enable_recommendations": 1, "show_price": 1})
-
-		# create recommended web item and price for it
-		recommended_web_item = create_regular_web_item("Test Mobile Phone 1")
-		make_web_item_price(item_code="Test Mobile Phone 1")
-
-		# add recommended item to first web item
-		web_item.append("recommended_items", {"website_item": recommended_web_item.name})
-		web_item.save()
-
-		frappe.local.shopping_cart_settings = None
-		e_commerce_settings = get_shopping_cart_settings()
-		recommended_items = web_item.get_recommended_items(e_commerce_settings)
-
-		# test results if show price is enabled
-		self.assertEqual(len(recommended_items), 1)
-		recomm_item = recommended_items[0]
-		self.assertEqual(recomm_item.get("website_item_name"), "Test Mobile Phone 1")
-		self.assertTrue(bool(recomm_item.get("price_info")))  # price fetched
-
-		price_info = recomm_item.get("price_info")
-		self.assertEqual(price_info.get("price_list_rate"), 1000)
-		self.assertEqual(price_info.get("formatted_price"), "₹ 1,000.00")
-
-		# test results if show price is disabled
-		setup_e_commerce_settings({"show_price": 0})
-
-		frappe.local.shopping_cart_settings = None
-		e_commerce_settings = get_shopping_cart_settings()
-		recommended_items = web_item.get_recommended_items(e_commerce_settings)
-
-		self.assertEqual(len(recommended_items), 1)
-		self.assertFalse(bool(recommended_items[0].get("price_info")))  # price not fetched
-
-		# tear down
-		web_item.delete()
-		recommended_web_item.delete()
-		frappe.get_cached_doc("Item", "Test Mobile Phone 1").delete()
-
-	def test_recommended_item_for_guest_user(self):
-		"Check if added recommended items are fetched correctly for guest user."
-		item_code = "Test Mobile Phone"
-		web_item = create_regular_web_item(item_code)
-
-		# price visible to guests
-		setup_e_commerce_settings(
-			{"enable_recommendations": 1, "show_price": 1, "hide_price_for_guest": 0}
-		)
-
-		# create recommended web item and price for it
-		recommended_web_item = create_regular_web_item("Test Mobile Phone 1")
-		make_web_item_price(item_code="Test Mobile Phone 1")
-
-		# add recommended item to first web item
-		web_item.append("recommended_items", {"website_item": recommended_web_item.name})
-		web_item.save()
-
-		frappe.set_user("Guest")
-
-		frappe.local.shopping_cart_settings = None
-		e_commerce_settings = get_shopping_cart_settings()
-		recommended_items = web_item.get_recommended_items(e_commerce_settings)
-
-		# test results if show price is enabled
-		self.assertEqual(len(recommended_items), 1)
-		self.assertTrue(bool(recommended_items[0].get("price_info")))  # price fetched
-
-		# price hidden from guests
-		frappe.set_user("Administrator")
-		setup_e_commerce_settings({"hide_price_for_guest": 1})
-		frappe.set_user("Guest")
-
-		frappe.local.shopping_cart_settings = None
-		e_commerce_settings = get_shopping_cart_settings()
-		recommended_items = web_item.get_recommended_items(e_commerce_settings)
-
-		# test results if show price is enabled
-		self.assertEqual(len(recommended_items), 1)
-		self.assertFalse(bool(recommended_items[0].get("price_info")))  # price fetched
-
-		# tear down
-		frappe.set_user("Administrator")
-		web_item.delete()
-		recommended_web_item.delete()
-		frappe.get_cached_doc("Item", "Test Mobile Phone 1").delete()
-
-
-def create_regular_web_item(item_code=None, item_args=None, web_args=None):
-	"Create Regular Item and Website Item."
-	item_code = item_code or "Test Mobile Phone"
-	item = make_item(item_code, properties=item_args)
-
-	if not frappe.db.exists("Website Item", {"item_code": item_code}):
-		web_item = make_website_item(item, save=False)
-		if web_args:
-			web_item.update(web_args)
-		web_item.save()
-	else:
-		web_item = frappe.get_cached_doc("Website Item", {"item_code": item_code})
-
-	return web_item
-
-
-def make_web_item_price(**kwargs):
-	item_code = kwargs.get("item_code")
-	if not item_code:
-		return
-
-	if not frappe.db.exists("Item Price", {"item_code": item_code}):
-		item_price = frappe.get_doc(
-			{
-				"doctype": "Item Price",
-				"item_code": item_code,
-				"price_list": kwargs.get("price_list") or "_Test Price List India",
-				"price_list_rate": kwargs.get("price_list_rate") or 1000,
-			}
-		)
-		item_price.insert()
-	else:
-		item_price = frappe.get_cached_doc("Item Price", {"item_code": item_code})
-
-	return item_price
-
-
-def make_web_pricing_rule(**kwargs):
-	title = kwargs.get("title")
-	if not title:
-		return
-
-	if not frappe.db.exists("Pricing Rule", title):
-		pricing_rule = frappe.get_doc(
-			{
-				"doctype": "Pricing Rule",
-				"title": title,
-				"apply_on": kwargs.get("apply_on") or "Item Code",
-				"items": [{"item_code": kwargs.get("item_code")}],
-				"selling": kwargs.get("selling") or 0,
-				"buying": kwargs.get("buying") or 0,
-				"rate_or_discount": kwargs.get("rate_or_discount") or "Discount Percentage",
-				"discount_percentage": kwargs.get("discount_percentage") or 10,
-				"company": kwargs.get("company") or "_Test Company",
-				"currency": kwargs.get("currency") or "INR",
-				"for_price_list": kwargs.get("price_list") or "_Test Price List India",
-				"applicable_for": kwargs.get("applicable_for") or "",
-				"customer": kwargs.get("customer") or "",
-			}
-		)
-		pricing_rule.insert()
-	else:
-		pricing_rule = frappe.get_doc("Pricing Rule", {"title": title})
-
-	return pricing_rule
-
-
-def create_user_and_customer_if_not_exists(email, first_name=None):
-	if frappe.db.exists("User", email):
-		return
-
-	frappe.get_doc(
-		{
-			"doctype": "User",
-			"user_type": "Website User",
-			"email": email,
-			"send_welcome_email": 0,
-			"first_name": first_name or email.split("@")[0],
-		}
-	).insert(ignore_permissions=True)
-
-	contact = frappe.get_last_doc("Contact", filters={"email_id": email})
-	link = contact.append("links", {})
-	link.link_doctype = "Customer"
-	link.link_name = "_Test Customer"
-	link.link_title = "_Test Customer"
-	contact.save()
-
-
-test_dependencies = ["Price List", "Item Price", "Customer", "Contact", "Item"]
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.js b/erpnext/e_commerce/doctype/website_item/website_item.js
deleted file mode 100644
index b6595cc..0000000
--- a/erpnext/e_commerce/doctype/website_item/website_item.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Website Item', {
-	onload: (frm) => {
-		// should never check Private
-		frm.fields_dict["website_image"].df.is_private = 0;
-	},
-
-	refresh: (frm) => {
-		frm.add_custom_button(__("Prices"), function() {
-			frappe.set_route("List", "Item Price", {"item_code": frm.doc.item_code});
-		}, __("View"));
-
-		frm.add_custom_button(__("Stock"), function() {
-			frappe.route_options = {
-				"item_code": frm.doc.item_code
-			};
-			frappe.set_route("query-report", "Stock Balance");
-		}, __("View"));
-
-		frm.add_custom_button(__("E Commerce Settings"), function() {
-			frappe.set_route("Form", "E Commerce Settings");
-		}, __("View"));
-	},
-
-	copy_from_item_group: (frm) => {
-		return frm.call({
-			doc: frm.doc,
-			method: "copy_specification_from_item_group"
-		});
-	},
-
-	set_meta_tags: (frm) => {
-		frappe.utils.set_meta_tag(frm.doc.route);
-	}
-});
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.json b/erpnext/e_commerce/doctype/website_item/website_item.json
deleted file mode 100644
index 6f551a0..0000000
--- a/erpnext/e_commerce/doctype/website_item/website_item.json
+++ /dev/null
@@ -1,414 +0,0 @@
-{
- "actions": [],
- "allow_guest_to_view": 1,
- "allow_import": 1,
- "autoname": "naming_series",
- "creation": "2021-02-09 21:06:14.441698",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "naming_series",
-  "web_item_name",
-  "route",
-  "has_variants",
-  "variant_of",
-  "published",
-  "column_break_3",
-  "item_code",
-  "item_name",
-  "item_group",
-  "stock_uom",
-  "column_break_11",
-  "description",
-  "brand",
-  "display_section",
-  "website_image",
-  "website_image_alt",
-  "column_break_13",
-  "slideshow",
-  "thumbnail",
-  "stock_information_section",
-  "website_warehouse",
-  "column_break_24",
-  "on_backorder",
-  "section_break_17",
-  "short_description",
-  "web_long_description",
-  "column_break_27",
-  "website_specifications",
-  "copy_from_item_group",
-  "display_additional_information_section",
-  "show_tabbed_section",
-  "tabs",
-  "recommended_items_section",
-  "recommended_items",
-  "offers_section",
-  "offers",
-  "section_break_6",
-  "ranking",
-  "set_meta_tags",
-  "column_break_22",
-  "website_item_groups",
-  "advanced_display_section",
-  "website_content"
- ],
- "fields": [
-  {
-   "description": "Website display name",
-   "fetch_from": "item_code.item_name",
-   "fetch_if_empty": 1,
-   "fieldname": "web_item_name",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Website Item Name",
-   "reqd": 1
-  },
-  {
-   "fieldname": "column_break_3",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "item_code",
-   "fieldtype": "Link",
-   "label": "Item Code",
-   "options": "Item",
-   "read_only_depends_on": "eval:!doc.__islocal",
-   "reqd": 1
-  },
-  {
-   "fetch_from": "item_code.item_name",
-   "fieldname": "item_name",
-   "fieldtype": "Data",
-   "label": "Item Name",
-   "read_only": 1
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "section_break_6",
-   "fieldtype": "Section Break",
-   "label": "Search and SEO"
-  },
-  {
-   "fieldname": "route",
-   "fieldtype": "Small Text",
-   "in_list_view": 1,
-   "label": "Route",
-   "no_copy": 1
-  },
-  {
-   "description": "Items with higher ranking will be shown higher",
-   "fieldname": "ranking",
-   "fieldtype": "Int",
-   "label": "Ranking"
-  },
-  {
-   "description": "Show a slideshow at the top of the page",
-   "fieldname": "slideshow",
-   "fieldtype": "Link",
-   "label": "Slideshow",
-   "options": "Website Slideshow"
-  },
-  {
-   "description": "Item Image (if not slideshow)",
-   "fieldname": "website_image",
-   "fieldtype": "Attach Image",
-   "hidden": 1,
-   "in_preview": 1,
-   "label": "Website Image",
-   "print_hide": 1
-  },
-  {
-   "description": "Image Alternative Text",
-   "fieldname": "website_image_alt",
-   "fieldtype": "Data",
-   "label": "Image Description"
-  },
-  {
-   "fieldname": "thumbnail",
-   "fieldtype": "Data",
-   "label": "Thumbnail",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_13",
-   "fieldtype": "Column Break"
-  },
-  {
-   "description": "Show Stock availability based on this warehouse. If the parent warehouse is selected, then the system will display the consolidated available quantity of all child warehouses.",
-   "fieldname": "website_warehouse",
-   "fieldtype": "Link",
-   "ignore_user_permissions": 1,
-   "label": "Website Warehouse",
-   "options": "Warehouse"
-  },
-  {
-   "description": "List this Item in multiple groups on the website.",
-   "fieldname": "website_item_groups",
-   "fieldtype": "Table",
-   "label": "Website Item Groups",
-   "options": "Website Item Group"
-  },
-  {
-   "fieldname": "set_meta_tags",
-   "fieldtype": "Button",
-   "label": "Set Meta Tags"
-  },
-  {
-   "fieldname": "section_break_17",
-   "fieldtype": "Section Break",
-   "label": "Display Information"
-  },
-  {
-   "fieldname": "copy_from_item_group",
-   "fieldtype": "Button",
-   "label": "Copy From Item Group"
-  },
-  {
-   "fieldname": "website_specifications",
-   "fieldtype": "Table",
-   "label": "Website Specifications",
-   "options": "Item Website Specification"
-  },
-  {
-   "fieldname": "web_long_description",
-   "fieldtype": "Text Editor",
-   "label": "Website Description"
-  },
-  {
-   "description": "You can use any valid Bootstrap 4 markup in this field. It will be shown on your Item Page.",
-   "fieldname": "website_content",
-   "fieldtype": "HTML Editor",
-   "label": "Website Content"
-  },
-  {
-   "fetch_from": "item_code.item_group",
-   "fieldname": "item_group",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Group",
-   "options": "Item Group",
-   "read_only": 1,
-   "search_index": 1
-  },
-  {
-   "default": "1",
-   "fieldname": "published",
-   "fieldtype": "Check",
-   "label": "Published"
-  },
-  {
-   "default": "0",
-   "depends_on": "has_variants",
-   "fetch_from": "item_code.has_variants",
-   "fieldname": "has_variants",
-   "fieldtype": "Check",
-   "in_standard_filter": 1,
-   "label": "Has Variants",
-   "no_copy": 1,
-   "read_only": 1
-  },
-  {
-   "depends_on": "variant_of",
-   "fetch_from": "item_code.variant_of",
-   "fieldname": "variant_of",
-   "fieldtype": "Link",
-   "ignore_user_permissions": 1,
-   "in_standard_filter": 1,
-   "label": "Variant Of",
-   "options": "Item",
-   "read_only": 1,
-   "search_index": 1,
-   "set_only_once": 1
-  },
-  {
-   "fetch_from": "item_code.stock_uom",
-   "fieldname": "stock_uom",
-   "fieldtype": "Link",
-   "label": "Stock UOM",
-   "options": "UOM",
-   "read_only": 1
-  },
-  {
-   "depends_on": "brand",
-   "fetch_from": "item_code.brand",
-   "fieldname": "brand",
-   "fieldtype": "Link",
-   "label": "Brand",
-   "options": "Brand",
-   "search_index": 1
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "advanced_display_section",
-   "fieldtype": "Section Break",
-   "label": "Advanced Display Content"
-  },
-  {
-   "fieldname": "display_section",
-   "fieldtype": "Section Break",
-   "label": "Display Images"
-  },
-  {
-   "fieldname": "column_break_27",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "column_break_22",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "item_code.description",
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "label": "Item Description",
-   "read_only": 1
-  },
-  {
-   "default": "WEB-ITM-.####",
-   "fieldname": "naming_series",
-   "fieldtype": "Select",
-   "hidden": 1,
-   "label": "Naming Series",
-   "no_copy": 1,
-   "options": "WEB-ITM-.####",
-   "print_hide": 1
-  },
-  {
-   "fieldname": "display_additional_information_section",
-   "fieldtype": "Section Break",
-   "label": "Display Additional Information"
-  },
-  {
-   "depends_on": "show_tabbed_section",
-   "fieldname": "tabs",
-   "fieldtype": "Table",
-   "label": "Tabs",
-   "options": "Website Item Tabbed Section"
-  },
-  {
-   "default": "0",
-   "fieldname": "show_tabbed_section",
-   "fieldtype": "Check",
-   "label": "Add Section with Tabs"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "offers_section",
-   "fieldtype": "Section Break",
-   "label": "Offers"
-  },
-  {
-   "fieldname": "offers",
-   "fieldtype": "Table",
-   "label": "Offers to Display",
-   "options": "Website Offer"
-  },
-  {
-   "fieldname": "column_break_11",
-   "fieldtype": "Column Break"
-  },
-  {
-   "description": "Short Description for List View",
-   "fieldname": "short_description",
-   "fieldtype": "Small Text",
-   "label": "Short Website Description"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "recommended_items_section",
-   "fieldtype": "Section Break",
-   "label": "Recommended Items"
-  },
-  {
-   "fieldname": "recommended_items",
-   "fieldtype": "Table",
-   "label": "Recommended/Similar Items",
-   "options": "Recommended Items"
-  },
-  {
-   "fieldname": "stock_information_section",
-   "fieldtype": "Section Break",
-   "label": "Stock Information"
-  },
-  {
-   "fieldname": "column_break_24",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "description": "Indicate that Item is available on backorder and not usually pre-stocked",
-   "fieldname": "on_backorder",
-   "fieldtype": "Check",
-   "label": "On Backorder"
-  }
- ],
- "has_web_view": 1,
- "image_field": "website_image",
- "index_web_pages_for_search": 1,
- "links": [],
- "make_attachments_public": 1,
- "modified": "2023-09-12 14:19:22.822689",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Website Item",
- "naming_rule": "Expression (old style)",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "System Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Website Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Stock User",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Stock Manager",
-   "share": 1,
-   "write": 1
-  }
- ],
- "search_fields": "web_item_name, item_code, item_group",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "states": [],
- "title_field": "web_item_name",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py
deleted file mode 100644
index 81b8eca..0000000
--- a/erpnext/e_commerce/doctype/website_item/website_item.py
+++ /dev/null
@@ -1,469 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import json
-from typing import TYPE_CHECKING, List, Union
-
-if TYPE_CHECKING:
-	from erpnext.stock.doctype.item.item import Item
-
-import frappe
-from frappe import _
-from frappe.utils import cint, cstr, flt, random_string
-from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
-from frappe.website.website_generator import WebsiteGenerator
-
-from erpnext.e_commerce.doctype.item_review.item_review import get_item_reviews
-from erpnext.e_commerce.redisearch_utils import (
-	delete_item_from_index,
-	insert_item_to_index,
-	update_index_for_item,
-)
-from erpnext.e_commerce.shopping_cart.cart import _set_price_list
-from erpnext.setup.doctype.item_group.item_group import (
-	get_parent_item_groups,
-	invalidate_cache_for,
-)
-from erpnext.utilities.product import get_price
-
-
-class WebsiteItem(WebsiteGenerator):
-	website = frappe._dict(
-		page_title_field="web_item_name",
-		condition_field="published",
-		template="templates/generators/item/item.html",
-		no_cache=1,
-	)
-
-	def autoname(self):
-		# use naming series to accomodate items with same name (different item code)
-		from frappe.model.naming import get_default_naming_series, make_autoname
-
-		naming_series = get_default_naming_series("Website Item")
-		if not self.name and naming_series:
-			self.name = make_autoname(naming_series, doc=self)
-
-	def onload(self):
-		super(WebsiteItem, self).onload()
-
-	def validate(self):
-		super(WebsiteItem, self).validate()
-
-		if not self.item_code:
-			frappe.throw(_("Item Code is required"), title=_("Mandatory"))
-
-		self.validate_duplicate_website_item()
-		self.validate_website_image()
-		self.make_thumbnail()
-		self.publish_unpublish_desk_item(publish=True)
-
-		if not self.get("__islocal"):
-			wig = frappe.qb.DocType("Website Item Group")
-			query = (
-				frappe.qb.from_(wig)
-				.select(wig.item_group)
-				.where(
-					(wig.parentfield == "website_item_groups")
-					& (wig.parenttype == "Website Item")
-					& (wig.parent == self.name)
-				)
-			)
-			result = query.run(as_list=True)
-
-			self.old_website_item_groups = [x[0] for x in result]
-
-	def on_update(self):
-		invalidate_cache_for_web_item(self)
-		self.update_template_item()
-
-	def on_trash(self):
-		super(WebsiteItem, self).on_trash()
-		delete_item_from_index(self)
-		self.publish_unpublish_desk_item(publish=False)
-
-	def validate_duplicate_website_item(self):
-		existing_web_item = frappe.db.exists("Website Item", {"item_code": self.item_code})
-		if existing_web_item and existing_web_item != self.name:
-			message = _("Website Item already exists against Item {0}").format(frappe.bold(self.item_code))
-			frappe.throw(message, title=_("Already Published"))
-
-	def publish_unpublish_desk_item(self, publish=True):
-		if frappe.db.get_value("Item", self.item_code, "published_in_website") and publish:
-			return  # if already published don't publish again
-		frappe.db.set_value("Item", self.item_code, "published_in_website", publish)
-
-	def make_route(self):
-		"""Called from set_route in WebsiteGenerator."""
-		if not self.route:
-			return (
-				cstr(frappe.db.get_value("Item Group", self.item_group, "route"))
-				+ "/"
-				+ self.scrub((self.item_name if self.item_name else self.item_code) + "-" + random_string(5))
-			)
-
-	def update_template_item(self):
-		"""Publish Template Item if Variant is published."""
-		if self.variant_of:
-			if self.published:
-				# show template
-				template_item = frappe.get_doc("Item", self.variant_of)
-
-				if not template_item.published_in_website:
-					template_item.flags.ignore_permissions = True
-					make_website_item(template_item)
-
-	def validate_website_image(self):
-		if frappe.flags.in_import:
-			return
-
-		"""Validate if the website image is a public file"""
-		if not self.website_image:
-			return
-
-		# find if website image url exists as public
-		file_doc = frappe.get_all(
-			"File",
-			filters={"file_url": self.website_image},
-			fields=["name", "is_private"],
-			order_by="is_private asc",
-			limit_page_length=1,
-		)
-
-		if file_doc:
-			file_doc = file_doc[0]
-
-		if not file_doc:
-			frappe.msgprint(
-				_("Website Image {0} attached to Item {1} cannot be found").format(
-					self.website_image, self.name
-				)
-			)
-
-			self.website_image = None
-
-		elif file_doc.is_private:
-			frappe.msgprint(_("Website Image should be a public file or website URL"))
-
-			self.website_image = None
-
-	def make_thumbnail(self):
-		"""Make a thumbnail of `website_image`"""
-		if frappe.flags.in_import or frappe.flags.in_migrate:
-			return
-
-		import requests.exceptions
-
-		db_website_image = frappe.db.get_value(self.doctype, self.name, "website_image")
-		if not self.is_new() and self.website_image != db_website_image:
-			self.thumbnail = None
-
-		if self.website_image and not self.thumbnail:
-			file_doc = None
-
-			try:
-				file_doc = frappe.get_doc(
-					"File",
-					{
-						"file_url": self.website_image,
-						"attached_to_doctype": "Website Item",
-						"attached_to_name": self.name,
-					},
-				)
-			except frappe.DoesNotExistError:
-				pass
-				# cleanup
-				frappe.local.message_log.pop()
-
-			except requests.exceptions.HTTPError:
-				frappe.msgprint(_("Warning: Invalid attachment {0}").format(self.website_image))
-				self.website_image = None
-
-			except requests.exceptions.SSLError:
-				frappe.msgprint(
-					_("Warning: Invalid SSL certificate on attachment {0}").format(self.website_image)
-				)
-				self.website_image = None
-
-			# for CSV import
-			if self.website_image and not file_doc:
-				try:
-					file_doc = frappe.get_doc(
-						{
-							"doctype": "File",
-							"file_url": self.website_image,
-							"attached_to_doctype": "Website Item",
-							"attached_to_name": self.name,
-						}
-					).save()
-
-				except IOError:
-					self.website_image = None
-
-			if file_doc:
-				if not file_doc.thumbnail_url:
-					file_doc.make_thumbnail()
-
-				self.thumbnail = file_doc.thumbnail_url
-
-	def get_context(self, context):
-		context.show_search = True
-		context.search_link = "/search"
-		context.body_class = "product-page"
-
-		context.parents = get_parent_item_groups(self.item_group, from_item=True)  # breadcumbs
-		self.attributes = frappe.get_all(
-			"Item Variant Attribute",
-			fields=["attribute", "attribute_value"],
-			filters={"parent": self.item_code},
-		)
-
-		if self.slideshow:
-			context.update(get_slideshow(self))
-
-		self.set_metatags(context)
-		self.set_shopping_cart_data(context)
-
-		settings = context.shopping_cart.cart_settings
-
-		self.get_product_details_section(context)
-
-		if settings.get("enable_reviews"):
-			reviews_data = get_item_reviews(self.name)
-			context.update(reviews_data)
-			context.reviews = context.reviews[:4]
-
-		context.wished = False
-		if frappe.db.exists(
-			"Wishlist Item", {"item_code": self.item_code, "parent": frappe.session.user}
-		):
-			context.wished = True
-
-		context.user_is_customer = check_if_user_is_customer()
-
-		context.recommended_items = None
-		if settings and settings.enable_recommendations:
-			context.recommended_items = self.get_recommended_items(settings)
-
-		return context
-
-	def set_selected_attributes(self, variants, context, attribute_values_available):
-		for variant in variants:
-			variant.attributes = frappe.get_all(
-				"Item Variant Attribute",
-				filters={"parent": variant.name},
-				fields=["attribute", "attribute_value as value"],
-			)
-
-			# make an attribute-value map for easier access in templates
-			variant.attribute_map = frappe._dict(
-				{attr.attribute: attr.value for attr in variant.attributes}
-			)
-
-			for attr in variant.attributes:
-				values = attribute_values_available.setdefault(attr.attribute, [])
-				if attr.value not in values:
-					values.append(attr.value)
-
-				if variant.name == context.variant.name:
-					context.selected_attributes[attr.attribute] = attr.value
-
-	def set_attribute_values(self, attributes, context, attribute_values_available):
-		for attr in attributes:
-			values = context.attribute_values.setdefault(attr.attribute, [])
-
-			if cint(frappe.db.get_value("Item Attribute", attr.attribute, "numeric_values")):
-				for val in sorted(attribute_values_available.get(attr.attribute, []), key=flt):
-					values.append(val)
-			else:
-				# get list of values defined (for sequence)
-				for attr_value in frappe.db.get_all(
-					"Item Attribute Value",
-					fields=["attribute_value"],
-					filters={"parent": attr.attribute},
-					order_by="idx asc",
-				):
-
-					if attr_value.attribute_value in attribute_values_available.get(attr.attribute, []):
-						values.append(attr_value.attribute_value)
-
-	def set_metatags(self, context):
-		context.metatags = frappe._dict({})
-
-		safe_description = frappe.utils.to_markdown(self.description)
-
-		context.metatags.url = frappe.utils.get_url() + "/" + context.route
-
-		if context.website_image:
-			if context.website_image.startswith("http"):
-				url = context.website_image
-			else:
-				url = frappe.utils.get_url() + context.website_image
-			context.metatags.image = url
-
-		context.metatags.description = safe_description[:300]
-
-		context.metatags.title = self.web_item_name or self.item_name or self.item_code
-
-		context.metatags["og:type"] = "product"
-		context.metatags["og:site_name"] = "ERPNext"
-
-	def set_shopping_cart_data(self, context):
-		from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website
-
-		context.shopping_cart = get_product_info_for_website(
-			self.item_code, skip_quotation_creation=True
-		)
-
-	@frappe.whitelist()
-	def copy_specification_from_item_group(self):
-		self.set("website_specifications", [])
-		if self.item_group:
-			for label, desc in frappe.db.get_values(
-				"Item Website Specification", {"parent": self.item_group}, ["label", "description"]
-			):
-				row = self.append("website_specifications")
-				row.label = label
-				row.description = desc
-
-	def get_product_details_section(self, context):
-		"""Get section with tabs or website specifications."""
-		context.show_tabs = self.show_tabbed_section
-		if self.show_tabbed_section and (self.tabs or self.website_specifications):
-			context.tabs = self.get_tabs()
-		else:
-			context.website_specifications = self.website_specifications
-
-	def get_tabs(self):
-		tab_values = {}
-		tab_values["tab_1_title"] = "Product Details"
-		tab_values["tab_1_content"] = frappe.render_template(
-			"templates/generators/item/item_specifications.html",
-			{"website_specifications": self.website_specifications, "show_tabs": self.show_tabbed_section},
-		)
-
-		for row in self.tabs:
-			tab_values[f"tab_{row.idx + 1}_title"] = _(row.label)
-			tab_values[f"tab_{row.idx + 1}_content"] = row.content
-
-		return tab_values
-
-	def get_recommended_items(self, settings):
-		ri = frappe.qb.DocType("Recommended Items")
-		wi = frappe.qb.DocType("Website Item")
-
-		query = (
-			frappe.qb.from_(ri)
-			.join(wi)
-			.on(ri.item_code == wi.item_code)
-			.select(ri.item_code, ri.route, ri.website_item_name, ri.website_item_thumbnail)
-			.where((ri.parent == self.name) & (wi.published == 1))
-			.orderby(ri.idx)
-		)
-		items = query.run(as_dict=True)
-
-		if settings.show_price:
-			is_guest = frappe.session.user == "Guest"
-			# Show Price if logged in.
-			# If not logged in and price is hidden for guest, skip price fetch.
-			if is_guest and settings.hide_price_for_guest:
-				return items
-
-			selling_price_list = _set_price_list(settings, None)
-			for item in items:
-				item.price_info = get_price(
-					item.item_code, selling_price_list, settings.default_customer_group, settings.company
-				)
-
-		return items
-
-
-def invalidate_cache_for_web_item(doc):
-	"""Invalidate Website Item Group cache and rebuild ItemVariantsCacheManager."""
-	from erpnext.stock.doctype.item.item import invalidate_item_variants_cache_for_website
-
-	invalidate_cache_for(doc, doc.item_group)
-
-	website_item_groups = list(
-		set(
-			(doc.get("old_website_item_groups") or [])
-			+ [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group]
-		)
-	)
-
-	for item_group in website_item_groups:
-		invalidate_cache_for(doc, item_group)
-
-	# Update Search Cache
-	update_index_for_item(doc)
-
-	invalidate_item_variants_cache_for_website(doc)
-
-
-def on_doctype_update():
-	# since route is a Text column, it needs a length for indexing
-	frappe.db.add_index("Website Item", ["route(500)"])
-
-
-def check_if_user_is_customer(user=None):
-	from frappe.contacts.doctype.contact.contact import get_contact_name
-
-	if not user:
-		user = frappe.session.user
-
-	contact_name = get_contact_name(user)
-	customer = None
-
-	if contact_name:
-		contact = frappe.get_doc("Contact", contact_name)
-		for link in contact.links:
-			if link.link_doctype == "Customer":
-				customer = link.link_name
-				break
-
-	return True if customer else False
-
-
-@frappe.whitelist()
-def make_website_item(doc: "Item", save: bool = True) -> Union["WebsiteItem", List[str]]:
-	"Make Website Item from Item. Used via Form UI or patch."
-
-	if not doc:
-		return
-
-	if isinstance(doc, str):
-		doc = json.loads(doc)
-
-	if frappe.db.exists("Website Item", {"item_code": doc.get("item_code")}):
-		message = _("Website Item already exists against {0}").format(frappe.bold(doc.get("item_code")))
-		frappe.throw(message, title=_("Already Published"))
-
-	website_item = frappe.new_doc("Website Item")
-	website_item.web_item_name = doc.get("item_name")
-
-	fields_to_map = [
-		"item_code",
-		"item_name",
-		"item_group",
-		"stock_uom",
-		"brand",
-		"has_variants",
-		"variant_of",
-		"description",
-	]
-	for field in fields_to_map:
-		website_item.update({field: doc.get(field)})
-
-	# Needed for publishing/mapping via Form UI only
-	if not frappe.flags.in_migrate and (doc.get("image") and not website_item.website_image):
-		website_item.website_image = doc.get("image")
-
-	if not save:
-		return website_item
-
-	website_item.save()
-
-	# Add to search cache
-	insert_item_to_index(website_item)
-
-	return [website_item.name, website_item.web_item_name]
diff --git a/erpnext/e_commerce/doctype/website_item/website_item_list.js b/erpnext/e_commerce/doctype/website_item/website_item_list.js
deleted file mode 100644
index b9dd921..0000000
--- a/erpnext/e_commerce/doctype/website_item/website_item_list.js
+++ /dev/null
@@ -1,20 +0,0 @@
-frappe.listview_settings['Website Item'] = {
-	add_fields: ["item_name", "web_item_name", "published", "website_image", "has_variants", "variant_of"],
-	filters: [["published", "=", "1"]],
-
-	get_indicator: function(doc) {
-		if (doc.has_variants && doc.published) {
-			return [__("Template"), "orange", "has_variants,=,Yes|published,=,1"];
-		} else if (doc.has_variants && !doc.published) {
-			return [__("Template"), "grey", "has_variants,=,Yes|published,=,0"];
-		} else if (doc.variant_of  && doc.published) {
-			return [__("Variant"), "blue", "published,=,1|variant_of,=," + doc.variant_of];
-		} else if (doc.variant_of  && !doc.published) {
-			return [__("Variant"), "grey", "published,=,0|variant_of,=," + doc.variant_of];
-		} else if (doc.published) {
-			return [__("Published"), "green", "published,=,1"];
-		} else {
-			return [__("Not Published"), "grey", "published,=,0"];
-		}
-	}
-};
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/__init__.py b/erpnext/e_commerce/doctype/website_item_tabbed_section/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/website_item_tabbed_section/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json
deleted file mode 100644
index 6601dd8..0000000
--- a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "actions": [],
- "creation": "2021-03-18 20:32:15.321402",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "label",
-  "content"
- ],
- "fields": [
-  {
-   "fieldname": "label",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Label"
-  },
-  {
-   "fieldname": "content",
-   "fieldtype": "HTML Editor",
-   "in_list_view": 1,
-   "label": "Content"
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-03-18 20:35:26.991192",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Website Item Tabbed Section",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py
deleted file mode 100644
index 91148b8..0000000
--- a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class WebsiteItemTabbedSection(Document):
-	pass
diff --git a/erpnext/e_commerce/doctype/website_offer/__init__.py b/erpnext/e_commerce/doctype/website_offer/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/website_offer/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/website_offer/website_offer.json b/erpnext/e_commerce/doctype/website_offer/website_offer.json
deleted file mode 100644
index 627d548..0000000
--- a/erpnext/e_commerce/doctype/website_offer/website_offer.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "actions": [],
- "creation": "2021-04-21 13:37:14.162162",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "offer_title",
-  "offer_subtitle",
-  "offer_details"
- ],
- "fields": [
-  {
-   "fieldname": "offer_title",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Offer Title"
-  },
-  {
-   "fieldname": "offer_subtitle",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Offer Subtitle"
-  },
-  {
-   "fieldname": "offer_details",
-   "fieldtype": "Text Editor",
-   "label": "Offer Details"
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-04-21 13:56:04.660331",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Website Offer",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/website_offer/website_offer.py b/erpnext/e_commerce/doctype/website_offer/website_offer.py
deleted file mode 100644
index 8c92f75..0000000
--- a/erpnext/e_commerce/doctype/website_offer/website_offer.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import frappe
-from frappe.model.document import Document
-
-
-class WebsiteOffer(Document):
-	pass
-
-
-@frappe.whitelist(allow_guest=True)
-def get_offer_details(offer_id):
-	return frappe.db.get_value("Website Offer", {"name": offer_id}, ["offer_details"])
diff --git a/erpnext/e_commerce/doctype/wishlist/__init__.py b/erpnext/e_commerce/doctype/wishlist/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/wishlist/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py
deleted file mode 100644
index 9d27126..0000000
--- a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-import unittest
-
-import frappe
-from frappe.core.doctype.user_permission.test_user_permission import create_user
-
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-from erpnext.e_commerce.doctype.wishlist.wishlist import add_to_wishlist, remove_from_wishlist
-from erpnext.stock.doctype.item.test_item import make_item
-
-
-class TestWishlist(unittest.TestCase):
-	def setUp(self):
-		item = make_item("Test Phone Series X")
-		if not frappe.db.exists("Website Item", {"item_code": "Test Phone Series X"}):
-			make_website_item(item, save=True)
-
-		item = make_item("Test Phone Series Y")
-		if not frappe.db.exists("Website Item", {"item_code": "Test Phone Series Y"}):
-			make_website_item(item, save=True)
-
-	def tearDown(self):
-		frappe.get_cached_doc("Website Item", {"item_code": "Test Phone Series X"}).delete()
-		frappe.get_cached_doc("Website Item", {"item_code": "Test Phone Series Y"}).delete()
-		frappe.get_cached_doc("Item", "Test Phone Series X").delete()
-		frappe.get_cached_doc("Item", "Test Phone Series Y").delete()
-
-	def test_add_remove_items_in_wishlist(self):
-		"Check if items are added and removed from user's wishlist."
-		# add first item
-		add_to_wishlist("Test Phone Series X")
-
-		# check if wishlist was created and item was added
-		self.assertTrue(frappe.db.exists("Wishlist", {"user": frappe.session.user}))
-		self.assertTrue(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": frappe.session.user}
-			)
-		)
-
-		# add second item to wishlist
-		add_to_wishlist("Test Phone Series Y")
-		wishlist_length = frappe.db.get_value(
-			"Wishlist Item", {"parent": frappe.session.user}, "count(*)"
-		)
-		self.assertEqual(wishlist_length, 2)
-
-		remove_from_wishlist("Test Phone Series X")
-		remove_from_wishlist("Test Phone Series Y")
-
-		wishlist_length = frappe.db.get_value(
-			"Wishlist Item", {"parent": frappe.session.user}, "count(*)"
-		)
-		self.assertIsNone(frappe.db.exists("Wishlist Item", {"parent": frappe.session.user}))
-		self.assertEqual(wishlist_length, 0)
-
-		# tear down
-		frappe.get_doc("Wishlist", {"user": frappe.session.user}).delete()
-
-	def test_add_remove_in_wishlist_multiple_users(self):
-		"Check if items are added and removed from the correct user's wishlist."
-		test_user = create_user("test_reviewer@example.com", "Customer")
-		test_user_1 = create_user("test_reviewer_1@example.com", "Customer")
-
-		# add to wishlist for first user
-		frappe.set_user(test_user.name)
-		add_to_wishlist("Test Phone Series X")
-
-		# add to wishlist for second user
-		frappe.set_user(test_user_1.name)
-		add_to_wishlist("Test Phone Series X")
-
-		# check wishlist and its content for users
-		self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user.name}))
-		self.assertTrue(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}
-			)
-		)
-
-		self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user_1.name}))
-		self.assertTrue(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user_1.name}
-			)
-		)
-
-		# remove item for second user
-		remove_from_wishlist("Test Phone Series X")
-
-		# make sure item was removed for second user and not first
-		self.assertFalse(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user_1.name}
-			)
-		)
-		self.assertTrue(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}
-			)
-		)
-
-		# remove item for first user
-		frappe.set_user(test_user.name)
-		remove_from_wishlist("Test Phone Series X")
-		self.assertFalse(
-			frappe.db.exists(
-				"Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}
-			)
-		)
-
-		# tear down
-		frappe.set_user("Administrator")
-		frappe.get_doc("Wishlist", {"user": test_user.name}).delete()
-		frappe.get_doc("Wishlist", {"user": test_user_1.name}).delete()
diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.js b/erpnext/e_commerce/doctype/wishlist/wishlist.js
deleted file mode 100644
index d96e552..0000000
--- a/erpnext/e_commerce/doctype/wishlist/wishlist.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Wishlist', {
-	// refresh: function(frm) {
-
-	// }
-});
diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.json b/erpnext/e_commerce/doctype/wishlist/wishlist.json
deleted file mode 100644
index 922924e..0000000
--- a/erpnext/e_commerce/doctype/wishlist/wishlist.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "actions": [],
- "autoname": "field:user",
- "creation": "2021-03-10 18:52:28.769126",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "user",
-  "section_break_2",
-  "items"
- ],
- "fields": [
-  {
-   "fieldname": "user",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "User",
-   "options": "User",
-   "reqd": 1,
-   "unique": 1
-  },
-  {
-   "fieldname": "section_break_2",
-   "fieldtype": "Section Break"
-  },
-  {
-   "fieldname": "items",
-   "fieldtype": "Table",
-   "label": "Items",
-   "options": "Wishlist Item"
-  }
- ],
- "in_create": 1,
- "index_web_pages_for_search": 1,
- "links": [],
- "modified": "2021-07-08 13:11:21.693956",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Wishlist",
- "owner": "Administrator",
- "permissions": [
-  {
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "System Manager",
-   "share": 1
-  },
-  {
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Website Manager",
-   "share": 1
-  }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.py b/erpnext/e_commerce/doctype/wishlist/wishlist.py
deleted file mode 100644
index eb74027..0000000
--- a/erpnext/e_commerce/doctype/wishlist/wishlist.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import frappe
-from frappe.model.document import Document
-
-
-class Wishlist(Document):
-	pass
-
-
-@frappe.whitelist()
-def add_to_wishlist(item_code):
-	"""Insert Item into wishlist."""
-
-	if frappe.db.exists("Wishlist Item", {"item_code": item_code, "parent": frappe.session.user}):
-		return
-
-	web_item_data = frappe.db.get_value(
-		"Website Item",
-		{"item_code": item_code},
-		[
-			"website_image",
-			"website_warehouse",
-			"name",
-			"web_item_name",
-			"item_name",
-			"item_group",
-			"route",
-		],
-		as_dict=1,
-	)
-
-	wished_item_dict = {
-		"item_code": item_code,
-		"item_name": web_item_data.get("item_name"),
-		"item_group": web_item_data.get("item_group"),
-		"website_item": web_item_data.get("name"),
-		"web_item_name": web_item_data.get("web_item_name"),
-		"image": web_item_data.get("website_image"),
-		"warehouse": web_item_data.get("website_warehouse"),
-		"route": web_item_data.get("route"),
-	}
-
-	if not frappe.db.exists("Wishlist", frappe.session.user):
-		# initialise wishlist
-		wishlist = frappe.get_doc({"doctype": "Wishlist"})
-		wishlist.user = frappe.session.user
-		wishlist.append("items", wished_item_dict)
-		wishlist.save(ignore_permissions=True)
-	else:
-		wishlist = frappe.get_doc("Wishlist", frappe.session.user)
-		item = wishlist.append("items", wished_item_dict)
-		item.db_insert()
-
-	if hasattr(frappe.local, "cookie_manager"):
-		frappe.local.cookie_manager.set_cookie("wish_count", str(len(wishlist.items)))
-
-
-@frappe.whitelist()
-def remove_from_wishlist(item_code):
-	if frappe.db.exists("Wishlist Item", {"item_code": item_code, "parent": frappe.session.user}):
-		frappe.db.delete("Wishlist Item", {"item_code": item_code, "parent": frappe.session.user})
-		frappe.db.commit()  # nosemgrep
-
-		wishlist_items = frappe.db.get_values("Wishlist Item", filters={"parent": frappe.session.user})
-
-		if hasattr(frappe.local, "cookie_manager"):
-			frappe.local.cookie_manager.set_cookie("wish_count", str(len(wishlist_items)))
diff --git a/erpnext/e_commerce/doctype/wishlist_item/__init__.py b/erpnext/e_commerce/doctype/wishlist_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/doctype/wishlist_item/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json
deleted file mode 100644
index c0414a7..0000000
--- a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.json
+++ /dev/null
@@ -1,147 +0,0 @@
-{
- "actions": [],
- "creation": "2021-03-10 19:03:00.662714",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "item_code",
-  "website_item",
-  "web_item_name",
-  "column_break_3",
-  "item_name",
-  "item_group",
-  "item_details_section",
-  "description",
-  "column_break_7",
-  "route",
-  "image",
-  "image_view",
-  "section_break_8",
-  "warehouse_section",
-  "warehouse"
- ],
- "fields": [
-  {
-   "fetch_from": "website_item.item_code",
-   "fetch_if_empty": 1,
-   "fieldname": "item_code",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Item Code",
-   "options": "Item",
-   "reqd": 1
-  },
-  {
-   "fieldname": "website_item",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Website Item",
-   "options": "Website Item",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_3",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "item_code.item_name",
-   "fetch_if_empty": 1,
-   "fieldname": "item_name",
-   "fieldtype": "Data",
-   "label": "Item Name",
-   "read_only": 1
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "item_details_section",
-   "fieldtype": "Section Break",
-   "label": "Item Details",
-   "read_only": 1
-  },
-  {
-   "fetch_from": "item_code.description",
-   "fetch_if_empty": 1,
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "label": "Description",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_7",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "item_code.image",
-   "fetch_if_empty": 1,
-   "fieldname": "image",
-   "fieldtype": "Attach",
-   "hidden": 1,
-   "label": "Image"
-  },
-  {
-   "fetch_from": "item_code.image",
-   "fetch_if_empty": 1,
-   "fieldname": "image_view",
-   "fieldtype": "Image",
-   "hidden": 1,
-   "label": "Image View",
-   "options": "image",
-   "print_hide": 1
-  },
-  {
-   "fieldname": "warehouse_section",
-   "fieldtype": "Section Break",
-   "label": "Warehouse"
-  },
-  {
-   "fieldname": "warehouse",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Warehouse",
-   "options": "Warehouse",
-   "read_only": 1
-  },
-  {
-   "fieldname": "section_break_8",
-   "fieldtype": "Section Break"
-  },
-  {
-   "fetch_from": "item_code.item_group",
-   "fetch_if_empty": 1,
-   "fieldname": "item_group",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "read_only": 1
-  },
-  {
-   "fetch_from": "website_item.route",
-   "fetch_if_empty": 1,
-   "fieldname": "route",
-   "fieldtype": "Small Text",
-   "label": "Route",
-   "read_only": 1
-  },
-  {
-   "fetch_from": "website_item.web_item_name",
-   "fetch_if_empty": 1,
-   "fieldname": "web_item_name",
-   "fieldtype": "Data",
-   "label": "Website Item Name",
-   "read_only": 1
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-08-09 10:30:41.964802",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Wishlist Item",
- "owner": "Administrator",
- "permissions": [],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py
deleted file mode 100644
index 75ebccb..0000000
--- a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-# import frappe
-from frappe.model.document import Document
-
-
-class WishlistItem(Document):
-	pass
diff --git a/erpnext/e_commerce/legacy_search.py b/erpnext/e_commerce/legacy_search.py
deleted file mode 100644
index ef8e86d..0000000
--- a/erpnext/e_commerce/legacy_search.py
+++ /dev/null
@@ -1,134 +0,0 @@
-import frappe
-from frappe.search.full_text_search import FullTextSearch
-from frappe.utils import strip_html_tags
-from whoosh.analysis import StemmingAnalyzer
-from whoosh.fields import ID, KEYWORD, TEXT, Schema
-from whoosh.qparser import FieldsPlugin, MultifieldParser, WildcardPlugin
-from whoosh.query import Prefix
-
-# TODO: Make obsolete
-INDEX_NAME = "products"
-
-
-class ProductSearch(FullTextSearch):
-	"""Wrapper for WebsiteSearch"""
-
-	def get_schema(self):
-		return Schema(
-			title=TEXT(stored=True, field_boost=1.5),
-			name=ID(stored=True),
-			path=ID(stored=True),
-			content=TEXT(stored=True, analyzer=StemmingAnalyzer()),
-			keywords=KEYWORD(stored=True, scorable=True, commas=True),
-		)
-
-	def get_id(self):
-		return "name"
-
-	def get_items_to_index(self):
-		"""Get all routes to be indexed, this includes the static pages
-		in www/ and routes from published documents
-
-		Returns:
-		        self (object): FullTextSearch Instance
-		"""
-		items = get_all_published_items()
-		documents = [self.get_document_to_index(item) for item in items]
-		return documents
-
-	def get_document_to_index(self, item):
-		try:
-			item = frappe.get_doc("Item", item)
-			title = item.item_name
-			keywords = [item.item_group]
-
-			if item.brand:
-				keywords.append(item.brand)
-
-			if item.website_image_alt:
-				keywords.append(item.website_image_alt)
-
-			if item.has_variants and item.variant_based_on == "Item Attribute":
-				keywords = keywords + [attr.attribute for attr in item.attributes]
-
-			if item.web_long_description:
-				content = strip_html_tags(item.web_long_description)
-			elif item.description:
-				content = strip_html_tags(item.description)
-
-			return frappe._dict(
-				title=title,
-				name=item.name,
-				path=item.route,
-				content=content,
-				keywords=", ".join(keywords),
-			)
-		except Exception:
-			pass
-
-	def search(self, text, scope=None, limit=20):
-		"""Search from the current index
-
-		Args:
-		        text (str): String to search for
-		        scope (str, optional): Scope to limit the search. Defaults to None.
-		        limit (int, optional): Limit number of search results. Defaults to 20.
-
-		Returns:
-		        [List(_dict)]: Search results
-		"""
-		ix = self.get_index()
-
-		results = None
-		out = []
-
-		with ix.searcher() as searcher:
-			parser = MultifieldParser(["title", "content", "keywords"], ix.schema)
-			parser.remove_plugin_class(FieldsPlugin)
-			parser.remove_plugin_class(WildcardPlugin)
-			query = parser.parse(text)
-
-			filter_scoped = None
-			if scope:
-				filter_scoped = Prefix(self.id, scope)
-			results = searcher.search(query, limit=limit, filter=filter_scoped)
-
-			for r in results:
-				out.append(self.parse_result(r))
-
-		return out
-
-	def parse_result(self, result):
-		title_highlights = result.highlights("title")
-		content_highlights = result.highlights("content")
-		keyword_highlights = result.highlights("keywords")
-
-		return frappe._dict(
-			title=result["title"],
-			path=result["path"],
-			keywords=result["keywords"],
-			title_highlights=title_highlights,
-			content_highlights=content_highlights,
-			keyword_highlights=keyword_highlights,
-		)
-
-
-def get_all_published_items():
-	return frappe.get_all(
-		"Website Item", filters={"variant_of": "", "published": 1}, pluck="item_code"
-	)
-
-
-def update_index_for_path(path):
-	search = ProductSearch(INDEX_NAME)
-	return search.update_index_by_name(path)
-
-
-def remove_document_from_index(path):
-	search = ProductSearch(INDEX_NAME)
-	return search.remove_document_from_index(path)
-
-
-def build_index_for_all_routes():
-	search = ProductSearch(INDEX_NAME)
-	return search.build()
diff --git a/erpnext/e_commerce/product_data_engine/filters.py b/erpnext/e_commerce/product_data_engine/filters.py
deleted file mode 100644
index e5e5e97..0000000
--- a/erpnext/e_commerce/product_data_engine/filters.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-import frappe
-from frappe.utils import floor
-
-
-class ProductFiltersBuilder:
-	def __init__(self, item_group=None):
-		if not item_group:
-			self.doc = frappe.get_doc("E Commerce Settings")
-		else:
-			self.doc = frappe.get_doc("Item Group", item_group)
-
-		self.item_group = item_group
-
-	def get_field_filters(self):
-		from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website
-
-		if not self.item_group and not self.doc.enable_field_filters:
-			return
-
-		fields, filter_data = [], []
-		filter_fields = [row.fieldname for row in self.doc.filter_fields]  # fields in settings
-
-		# filter valid field filters i.e. those that exist in Website Item
-		web_item_meta = frappe.get_meta("Website Item", cached=True)
-		fields = [
-			web_item_meta.get_field(field) for field in filter_fields if web_item_meta.has_field(field)
-		]
-
-		for df in fields:
-			item_filters, item_or_filters = {"published": 1}, []
-			link_doctype_values = self.get_filtered_link_doctype_records(df)
-
-			if df.fieldtype == "Link":
-				if self.item_group:
-					include_child = frappe.db.get_value("Item Group", self.item_group, "include_descendants")
-					if include_child:
-						include_groups = get_child_groups_for_website(self.item_group, include_self=True)
-						include_groups = [x.name for x in include_groups]
-						item_or_filters.extend(
-							[
-								["item_group", "in", include_groups],
-								["Website Item Group", "item_group", "=", self.item_group],  # consider website item groups
-							]
-						)
-					else:
-						item_or_filters.extend(
-							[
-								["item_group", "=", self.item_group],
-								["Website Item Group", "item_group", "=", self.item_group],  # consider website item groups
-							]
-						)
-
-				# exclude variants if mentioned in settings
-				if frappe.db.get_single_value("E Commerce Settings", "hide_variants"):
-					item_filters["variant_of"] = ["is", "not set"]
-
-				# Get link field values attached to published items
-				item_values = frappe.get_all(
-					"Website Item",
-					fields=[df.fieldname],
-					filters=item_filters,
-					or_filters=item_or_filters,
-					distinct="True",
-					pluck=df.fieldname,
-				)
-
-				values = list(set(item_values) & link_doctype_values)  # intersection of both
-			else:
-				# table multiselect
-				values = list(link_doctype_values)
-
-			# Remove None
-			if None in values:
-				values.remove(None)
-
-			if values:
-				filter_data.append([df, values])
-
-		return filter_data
-
-	def get_filtered_link_doctype_records(self, field):
-		"""
-		Get valid link doctype records depending on filters.
-		Apply enable/disable/show_in_website filter.
-		Returns:
-		        set: A set containing valid record names
-		"""
-		link_doctype = field.get_link_doctype()
-		meta = frappe.get_meta(link_doctype, cached=True) if link_doctype else None
-		if meta:
-			filters = self.get_link_doctype_filters(meta)
-			link_doctype_values = set(d.name for d in frappe.get_all(link_doctype, filters))
-
-		return link_doctype_values if meta else set()
-
-	def get_link_doctype_filters(self, meta):
-		"Filters for Link Doctype eg. 'show_in_website'."
-		filters = {}
-		if not meta:
-			return filters
-
-		if meta.has_field("enabled"):
-			filters["enabled"] = 1
-		if meta.has_field("disabled"):
-			filters["disabled"] = 0
-		if meta.has_field("show_in_website"):
-			filters["show_in_website"] = 1
-
-		return filters
-
-	def get_attribute_filters(self):
-		if not self.item_group and not self.doc.enable_attribute_filters:
-			return
-
-		attributes = [row.attribute for row in self.doc.filter_attributes]
-
-		if not attributes:
-			return []
-
-		result = frappe.get_all(
-			"Item Variant Attribute",
-			filters={"attribute": ["in", attributes], "attribute_value": ["is", "set"]},
-			fields=["attribute", "attribute_value"],
-			distinct=True,
-		)
-
-		attribute_value_map = {}
-		for d in result:
-			attribute_value_map.setdefault(d.attribute, []).append(d.attribute_value)
-
-		out = []
-		for name, values in attribute_value_map.items():
-			out.append(frappe._dict(name=name, item_attribute_values=values))
-		return out
-
-	def get_discount_filters(self, discounts):
-		discount_filters = []
-
-		# [25.89, 60.5] min max
-		min_discount, max_discount = discounts[0], discounts[1]
-		# [25, 60] rounded min max
-		min_range_absolute, max_range_absolute = floor(min_discount), floor(max_discount)
-
-		min_range = int(min_discount - (min_range_absolute % 10))  # 20
-		max_range = int(max_discount - (max_range_absolute % 10))  # 60
-
-		min_range = (
-			(min_range + 10) if min_range != min_range_absolute else min_range
-		)  # 30 (upper limit of 25.89 in range of 10)
-		max_range = (max_range + 10) if max_range != max_range_absolute else max_range  # 60
-
-		for discount in range(min_range, (max_range + 1), 10):
-			label = f"{discount}% and below"
-			discount_filters.append([discount, label])
-
-		return discount_filters
diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py
deleted file mode 100644
index 975f876..0000000
--- a/erpnext/e_commerce/product_data_engine/query.py
+++ /dev/null
@@ -1,321 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-from frappe.utils import flt
-
-from erpnext.e_commerce.doctype.item_review.item_review import get_customer
-from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website
-from erpnext.utilities.product import get_non_stock_item_status
-
-
-class ProductQuery:
-	"""Query engine for product listing
-
-	Attributes:
-	        fields (list): Fields to fetch in query
-	        conditions (string): Conditions for query building
-	        or_conditions (string): Search conditions
-	        page_length (Int): Length of page for the query
-	        settings (Document): E Commerce Settings DocType
-	"""
-
-	def __init__(self):
-		self.settings = frappe.get_doc("E Commerce Settings")
-		self.page_length = self.settings.products_per_page or 20
-
-		self.or_filters = []
-		self.filters = [["published", "=", 1]]
-		self.fields = [
-			"web_item_name",
-			"name",
-			"item_name",
-			"item_code",
-			"website_image",
-			"variant_of",
-			"has_variants",
-			"item_group",
-			"web_long_description",
-			"short_description",
-			"route",
-			"website_warehouse",
-			"ranking",
-			"on_backorder",
-		]
-
-	def query(self, attributes=None, fields=None, search_term=None, start=0, item_group=None):
-		"""
-		Args:
-		        attributes (dict, optional): Item Attribute filters
-		        fields (dict, optional): Field level filters
-		        search_term (str, optional): Search term to lookup
-		        start (int, optional): Page start
-
-		Returns:
-		        dict: Dict containing items, item count & discount range
-		"""
-		# track if discounts included in field filters
-		self.filter_with_discount = bool(fields.get("discount"))
-		result, discount_list, website_item_groups, cart_items, count = [], [], [], [], 0
-
-		if fields:
-			self.build_fields_filters(fields)
-		if item_group:
-			self.build_item_group_filters(item_group)
-		if search_term:
-			self.build_search_filters(search_term)
-		if self.settings.hide_variants:
-			self.filters.append(["variant_of", "is", "not set"])
-
-		# query results
-		if attributes:
-			result, count = self.query_items_with_attributes(attributes, start)
-		else:
-			result, count = self.query_items(start=start)
-
-		# sort combined results by ranking
-		result = sorted(result, key=lambda x: x.get("ranking"), reverse=True)
-
-		if self.settings.enabled:
-			cart_items = self.get_cart_items()
-
-		result, discount_list = self.add_display_details(result, discount_list, cart_items)
-
-		discounts = []
-		if discount_list:
-			discounts = [min(discount_list), max(discount_list)]
-
-		result = self.filter_results_by_discount(fields, result)
-
-		return {"items": result, "items_count": count, "discounts": discounts}
-
-	def query_items(self, start=0):
-		"""Build a query to fetch Website Items based on field filters."""
-		# MySQL does not support offset without limit,
-		# frappe does not accept two parameters for limit
-		# https://dev.mysql.com/doc/refman/8.0/en/select.html#id4651989
-		count_items = frappe.db.get_all(
-			"Website Item",
-			filters=self.filters,
-			or_filters=self.or_filters,
-			limit_page_length=184467440737095516,
-			limit_start=start,  # get all items from this offset for total count ahead
-			order_by="ranking desc",
-		)
-		count = len(count_items)
-
-		# If discounts included, return all rows.
-		# Slice after filtering rows with discount (See `filter_results_by_discount`).
-		# Slicing before hand will miss discounted items on the 3rd or 4th page.
-		# Discounts are fetched on computing Pricing Rules so we cannot query them directly.
-		page_length = 184467440737095516 if self.filter_with_discount else self.page_length
-
-		items = frappe.db.get_all(
-			"Website Item",
-			fields=self.fields,
-			filters=self.filters,
-			or_filters=self.or_filters,
-			limit_page_length=page_length,
-			limit_start=start,
-			order_by="ranking desc",
-		)
-
-		return items, count
-
-	def query_items_with_attributes(self, attributes, start=0):
-		"""Build a query to fetch Website Items based on field & attribute filters."""
-		item_codes = []
-
-		for attribute, values in attributes.items():
-			if not isinstance(values, list):
-				values = [values]
-
-			# get items that have selected attribute & value
-			item_code_list = frappe.db.get_all(
-				"Item",
-				fields=["item_code"],
-				filters=[
-					["published_in_website", "=", 1],
-					["Item Variant Attribute", "attribute", "=", attribute],
-					["Item Variant Attribute", "attribute_value", "in", values],
-				],
-			)
-			item_codes.append({x.item_code for x in item_code_list})
-
-		if item_codes:
-			item_codes = list(set.intersection(*item_codes))
-			self.filters.append(["item_code", "in", item_codes])
-
-		items, count = self.query_items(start=start)
-
-		return items, count
-
-	def build_fields_filters(self, filters):
-		"""Build filters for field values
-
-		Args:
-		        filters (dict): Filters
-		"""
-		for field, values in filters.items():
-			if not values or field == "discount":
-				continue
-
-			# handle multiselect fields in filter addition
-			meta = frappe.get_meta("Website Item", cached=True)
-			df = meta.get_field(field)
-			if df.fieldtype == "Table MultiSelect":
-				child_doctype = df.options
-				child_meta = frappe.get_meta(child_doctype, cached=True)
-				fields = child_meta.get("fields")
-				if fields:
-					self.filters.append([child_doctype, fields[0].fieldname, "IN", values])
-			elif isinstance(values, list):
-				# If value is a list use `IN` query
-				self.filters.append([field, "in", values])
-			else:
-				# `=` will be faster than `IN` for most cases
-				self.filters.append([field, "=", values])
-
-	def build_item_group_filters(self, item_group):
-		"Add filters for Item group page and include Website Item Groups."
-		from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website
-
-		item_group_filters = []
-
-		item_group_filters.append(["Website Item", "item_group", "=", item_group])
-		# Consider Website Item Groups
-		item_group_filters.append(["Website Item Group", "item_group", "=", item_group])
-
-		if frappe.db.get_value("Item Group", item_group, "include_descendants"):
-			# include child item group's items as well
-			# eg. Group Node A, will show items of child 1 and child 2 as well
-			# on it's web page
-			include_groups = get_child_groups_for_website(item_group, include_self=True)
-			include_groups = [x.name for x in include_groups]
-			item_group_filters.append(["Website Item", "item_group", "in", include_groups])
-
-		self.or_filters.extend(item_group_filters)
-
-	def build_search_filters(self, search_term):
-		"""Query search term in specified fields
-
-		Args:
-		        search_term (str): Search candidate
-		"""
-		# Default fields to search from
-		default_fields = {"item_code", "item_name", "web_long_description", "item_group"}
-
-		# Get meta search fields
-		meta = frappe.get_meta("Website Item")
-		meta_fields = set(meta.get_search_fields())
-
-		# Join the meta fields and default fields set
-		search_fields = default_fields.union(meta_fields)
-		if frappe.db.count("Website Item", cache=True) > 50000:
-			search_fields.discard("web_long_description")
-
-		# Build or filters for query
-		search = "%{}%".format(search_term)
-		for field in search_fields:
-			self.or_filters.append([field, "like", search])
-
-	def add_display_details(self, result, discount_list, cart_items):
-		"""Add price and availability details in result."""
-		for item in result:
-			product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get(
-				"product_info"
-			)
-
-			if product_info and product_info["price"]:
-				# update/mutate item and discount_list objects
-				self.get_price_discount_info(item, product_info["price"], discount_list)
-
-			if self.settings.show_stock_availability:
-				self.get_stock_availability(item)
-
-			item.in_cart = item.item_code in cart_items
-
-			item.wished = False
-			if frappe.db.exists(
-				"Wishlist Item", {"item_code": item.item_code, "parent": frappe.session.user}
-			):
-				item.wished = True
-
-		return result, discount_list
-
-	def get_price_discount_info(self, item, price_object, discount_list):
-		"""Modify item object and add price details."""
-		fields = ["formatted_mrp", "formatted_price", "price_list_rate"]
-		for field in fields:
-			item[field] = price_object.get(field)
-
-		if price_object.get("discount_percent"):
-			item.discount_percent = flt(price_object.discount_percent)
-			discount_list.append(price_object.discount_percent)
-
-		if item.formatted_mrp:
-			item.discount = price_object.get("formatted_discount_percent") or price_object.get(
-				"formatted_discount_rate"
-			)
-
-	def get_stock_availability(self, item):
-		from erpnext.templates.pages.wishlist import (
-			get_stock_availability as get_stock_availability_from_template,
-		)
-
-		"""Modify item object and add stock details."""
-		item.in_stock = False
-		warehouse = item.get("website_warehouse")
-		is_stock_item = frappe.get_cached_value("Item", item.item_code, "is_stock_item")
-
-		if item.get("on_backorder"):
-			return
-
-		if not is_stock_item:
-			if warehouse:
-				# product bundle case
-				item.in_stock = get_non_stock_item_status(item.item_code, "website_warehouse")
-			else:
-				item.in_stock = True
-		elif warehouse:
-			item.in_stock = get_stock_availability_from_template(item.item_code, warehouse)
-
-	def get_cart_items(self):
-		customer = get_customer(silent=True)
-		if customer:
-			quotation = frappe.get_all(
-				"Quotation",
-				fields=["name"],
-				filters={
-					"party_name": customer,
-					"contact_email": frappe.session.user,
-					"order_type": "Shopping Cart",
-					"docstatus": 0,
-				},
-				order_by="modified desc",
-				limit_page_length=1,
-			)
-			if quotation:
-				items = frappe.get_all(
-					"Quotation Item", fields=["item_code"], filters={"parent": quotation[0].get("name")}
-				)
-				items = [row.item_code for row in items]
-				return items
-
-		return []
-
-	def filter_results_by_discount(self, fields, result):
-		if fields and fields.get("discount"):
-			discount_percent = frappe.utils.flt(fields["discount"][0])
-			result = [
-				row
-				for row in result
-				if row.get("discount_percent") and row.discount_percent <= discount_percent
-			]
-
-		if self.filter_with_discount:
-			# no limit was added to results while querying
-			# slice results manually
-			result[: self.page_length]
-
-		return result
diff --git a/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py
deleted file mode 100644
index 45bc20e..0000000
--- a/erpnext/e_commerce/product_data_engine/test_item_group_product_data_engine.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import unittest
-
-import frappe
-
-from erpnext.e_commerce.api import get_product_filter_data
-from erpnext.e_commerce.doctype.website_item.test_website_item import create_regular_web_item
-
-test_dependencies = ["Item", "Item Group"]
-
-
-class TestItemGroupProductDataEngine(unittest.TestCase):
-	"Test Products & Sub-Category Querying for Product Listing on Item Group Page."
-
-	def setUp(self):
-		item_codes = [
-			("Test Mobile A", "_Test Item Group B"),
-			("Test Mobile B", "_Test Item Group B"),
-			("Test Mobile C", "_Test Item Group B - 1"),
-			("Test Mobile D", "_Test Item Group B - 1"),
-			("Test Mobile E", "_Test Item Group B - 2"),
-		]
-		for item in item_codes:
-			item_code = item[0]
-			item_args = {"item_group": item[1]}
-			if not frappe.db.exists("Website Item", {"item_code": item_code}):
-				create_regular_web_item(item_code, item_args=item_args)
-
-		frappe.db.set_value("Item Group", "_Test Item Group B - 1", "show_in_website", 1)
-		frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 1)
-
-	def tearDown(self):
-		frappe.db.rollback()
-
-	def test_product_listing_in_item_group(self):
-		"Test if only products belonging to the Item Group are fetched."
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B",
-			}
-		)
-
-		items = result.get("items")
-		item_codes = [item.get("item_code") for item in items]
-
-		self.assertEqual(len(items), 2)
-		self.assertIn("Test Mobile A", item_codes)
-		self.assertNotIn("Test Mobile C", item_codes)
-
-	def test_products_in_multiple_item_groups(self):
-		"""Test if product is visible on multiple item group pages barring its own."""
-		website_item = frappe.get_doc("Website Item", {"item_code": "Test Mobile E"})
-
-		# show item belonging to '_Test Item Group B - 2' in '_Test Item Group B - 1' as well
-		website_item.append("website_item_groups", {"item_group": "_Test Item Group B - 1"})
-		website_item.save()
-
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B - 1",
-			}
-		)
-
-		items = result.get("items")
-		item_codes = [item.get("item_code") for item in items]
-
-		self.assertEqual(len(items), 3)
-		self.assertIn("Test Mobile E", item_codes)  # visible in other item groups
-		self.assertIn("Test Mobile C", item_codes)
-		self.assertIn("Test Mobile D", item_codes)
-
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B - 2",
-			}
-		)
-
-		items = result.get("items")
-
-		self.assertEqual(len(items), 1)
-		self.assertEqual(items[0].get("item_code"), "Test Mobile E")  # visible in own item group
-
-	def test_item_group_with_sub_groups(self):
-		"Test Valid Sub Item Groups in Item Group Page."
-		frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 0)
-
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B",
-			}
-		)
-
-		self.assertTrue(bool(result.get("sub_categories")))
-
-		child_groups = [d.name for d in result.get("sub_categories")]
-		# check if child group is fetched if shown in website
-		self.assertIn("_Test Item Group B - 1", child_groups)
-
-		frappe.db.set_value("Item Group", "_Test Item Group B - 2", "show_in_website", 1)
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B",
-			}
-		)
-		child_groups = [d.name for d in result.get("sub_categories")]
-
-		# check if child group is fetched if shown in website
-		self.assertIn("_Test Item Group B - 1", child_groups)
-		self.assertIn("_Test Item Group B - 2", child_groups)
-
-	def test_item_group_page_with_descendants_included(self):
-		"""
-		Test if 'include_descendants' pulls Items belonging to descendant Item Groups (Level 2 & 3).
-		> _Test Item Group B [Level 1]
-		        > _Test Item Group B - 1 [Level 2]
-		                > _Test Item Group B - 1 - 1 [Level 3]
-		"""
-		frappe.get_doc(
-			{  # create Level 3 nested child group
-				"doctype": "Item Group",
-				"is_group": 1,
-				"item_group_name": "_Test Item Group B - 1 - 1",
-				"parent_item_group": "_Test Item Group B - 1",
-			}
-		).insert()
-
-		create_regular_web_item(  # create an item belonging to level 3 item group
-			"Test Mobile F", item_args={"item_group": "_Test Item Group B - 1 - 1"}
-		)
-
-		frappe.db.set_value("Item Group", "_Test Item Group B - 1 - 1", "show_in_website", 1)
-
-		# enable 'include descendants' in Level 1
-		frappe.db.set_value("Item Group", "_Test Item Group B", "include_descendants", 1)
-
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {},
-				"attribute_filters": {},
-				"start": 0,
-				"item_group": "_Test Item Group B",
-			}
-		)
-
-		items = result.get("items")
-		item_codes = [item.get("item_code") for item in items]
-
-		# check if all sub groups' items are pulled
-		self.assertEqual(len(items), 6)
-		self.assertIn("Test Mobile A", item_codes)
-		self.assertIn("Test Mobile C", item_codes)
-		self.assertIn("Test Mobile E", item_codes)
-		self.assertIn("Test Mobile F", item_codes)
diff --git a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py
deleted file mode 100644
index c3b6ed5..0000000
--- a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py
+++ /dev/null
@@ -1,348 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-import unittest
-
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import (
-	setup_e_commerce_settings,
-)
-from erpnext.e_commerce.doctype.website_item.test_website_item import create_regular_web_item
-from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder
-from erpnext.e_commerce.product_data_engine.query import ProductQuery
-
-test_dependencies = ["Item", "Item Group"]
-
-
-class TestProductDataEngine(unittest.TestCase):
-	"Test Products Querying and Filters for Product Listing."
-
-	@classmethod
-	def setUpClass(cls):
-		item_codes = [
-			("Test 11I Laptop", "Products"),  # rank 1
-			("Test 12I Laptop", "Products"),  # rank 2
-			("Test 13I Laptop", "Products"),  # rank 3
-			("Test 14I Laptop", "Raw Material"),  # rank 4
-			("Test 15I Laptop", "Raw Material"),  # rank 5
-			("Test 16I Laptop", "Raw Material"),  # rank 6
-			("Test 17I Laptop", "Products"),  # rank 7
-		]
-		for index, item in enumerate(item_codes, start=1):
-			item_code = item[0]
-			item_args = {"item_group": item[1]}
-			web_args = {"ranking": index}
-			if not frappe.db.exists("Website Item", {"item_code": item_code}):
-				create_regular_web_item(item_code, item_args=item_args, web_args=web_args)
-
-		setup_e_commerce_settings(
-			{
-				"products_per_page": 4,
-				"enable_field_filters": 1,
-				"filter_fields": [{"fieldname": "item_group"}],
-				"enable_attribute_filters": 1,
-				"filter_attributes": [{"attribute": "Test Size"}],
-				"company": "_Test Company",
-				"enabled": 1,
-				"default_customer_group": "_Test Customer Group",
-				"price_list": "_Test Price List India",
-			}
-		)
-		frappe.local.shopping_cart_settings = None
-
-	@classmethod
-	def tearDownClass(cls):
-		frappe.db.rollback()
-
-	def test_product_list_ordering_and_paging(self):
-		"Test if website items appear by ranking on different pages."
-		engine = ProductQuery()
-		result = engine.query(attributes={}, fields={}, search_term=None, start=0, item_group=None)
-		items = result.get("items")
-
-		self.assertIsNotNone(items)
-		self.assertEqual(len(items), 4)
-		self.assertGreater(result.get("items_count"), 4)
-
-		# check if items appear as per ranking set in setUpClass
-		self.assertEqual(items[0].get("item_code"), "Test 17I Laptop")
-		self.assertEqual(items[1].get("item_code"), "Test 16I Laptop")
-		self.assertEqual(items[2].get("item_code"), "Test 15I Laptop")
-		self.assertEqual(items[3].get("item_code"), "Test 14I Laptop")
-
-		# check next page
-		result = engine.query(attributes={}, fields={}, search_term=None, start=4, item_group=None)
-		items = result.get("items")
-
-		# check if items appear as per ranking set in setUpClass on next page
-		self.assertEqual(items[0].get("item_code"), "Test 13I Laptop")
-		self.assertEqual(items[1].get("item_code"), "Test 12I Laptop")
-		self.assertEqual(items[2].get("item_code"), "Test 11I Laptop")
-
-	def test_change_product_ranking(self):
-		"Test if item on second page appear on first if ranking is changed."
-		item_code = "Test 12I Laptop"
-		old_ranking = frappe.db.get_value("Website Item", {"item_code": item_code}, "ranking")
-
-		# low rank, appears on second page
-		self.assertEqual(old_ranking, 2)
-
-		# set ranking as highest rank
-		frappe.db.set_value("Website Item", {"item_code": item_code}, "ranking", 10)
-
-		engine = ProductQuery()
-		result = engine.query(attributes={}, fields={}, search_term=None, start=0, item_group=None)
-		items = result.get("items")
-
-		# check if item is the first item on the first page
-		self.assertEqual(items[0].get("item_code"), item_code)
-		self.assertEqual(items[1].get("item_code"), "Test 17I Laptop")
-
-		# tear down
-		frappe.db.set_value("Website Item", {"item_code": item_code}, "ranking", old_ranking)
-
-	def test_product_list_field_filter_builder(self):
-		"Test if field filters are fetched correctly."
-		frappe.db.set_value("Item Group", "Raw Material", "show_in_website", 0)
-
-		filter_engine = ProductFiltersBuilder()
-		field_filters = filter_engine.get_field_filters()
-
-		# Web Items belonging to 'Products' and 'Raw Material' are available
-		# but only 'Products' has 'show_in_website' enabled
-		item_group_filters = field_filters[0]
-		docfield = item_group_filters[0]
-		valid_item_groups = item_group_filters[1]
-
-		self.assertEqual(docfield.options, "Item Group")
-		self.assertIn("Products", valid_item_groups)
-		self.assertNotIn("Raw Material", valid_item_groups)
-
-		frappe.db.set_value("Item Group", "Raw Material", "show_in_website", 1)
-		field_filters = filter_engine.get_field_filters()
-
-		#'Products' and 'Raw Materials' both have 'show_in_website' enabled
-		item_group_filters = field_filters[0]
-		docfield = item_group_filters[0]
-		valid_item_groups = item_group_filters[1]
-
-		self.assertEqual(docfield.options, "Item Group")
-		self.assertIn("Products", valid_item_groups)
-		self.assertIn("Raw Material", valid_item_groups)
-
-	def test_product_list_with_field_filter(self):
-		"Test if field filters are applied correctly."
-		field_filters = {"item_group": "Raw Material"}
-
-		engine = ProductQuery()
-		result = engine.query(
-			attributes={}, fields=field_filters, search_term=None, start=0, item_group=None
-		)
-		items = result.get("items")
-
-		# check if only 'Raw Material' are fetched in the right order
-		self.assertEqual(len(items), 3)
-		self.assertEqual(items[0].get("item_code"), "Test 16I Laptop")
-		self.assertEqual(items[1].get("item_code"), "Test 15I Laptop")
-
-	# def test_product_list_with_field_filter_table_multiselect(self):
-	# 	TODO
-	# 	pass
-
-	def test_product_list_attribute_filter_builder(self):
-		"Test if attribute filters are fetched correctly."
-		create_variant_web_item()
-
-		filter_engine = ProductFiltersBuilder()
-		attribute_filter = filter_engine.get_attribute_filters()[0]
-		attribute_values = attribute_filter.item_attribute_values
-
-		self.assertEqual(attribute_filter.name, "Test Size")
-		self.assertGreater(len(attribute_values), 0)
-		self.assertIn("Large", attribute_values)
-
-	def test_product_list_with_attribute_filter(self):
-		"Test if attribute filters are applied correctly."
-		create_variant_web_item()
-
-		attribute_filters = {"Test Size": ["Large"]}
-		engine = ProductQuery()
-		result = engine.query(
-			attributes=attribute_filters, fields={}, search_term=None, start=0, item_group=None
-		)
-		items = result.get("items")
-
-		# check if only items with Test Size 'Large' are fetched
-		self.assertEqual(len(items), 1)
-		self.assertEqual(items[0].get("item_code"), "Test Web Item-L")
-
-	def test_product_list_discount_filter_builder(self):
-		"Test if discount filters are fetched correctly."
-		from erpnext.e_commerce.doctype.website_item.test_website_item import (
-			make_web_item_price,
-			make_web_pricing_rule,
-		)
-
-		item_code = "Test 12I Laptop"
-		make_web_item_price(item_code=item_code)
-		make_web_pricing_rule(title=f"Test Pricing Rule for {item_code}", item_code=item_code, selling=1)
-
-		setup_e_commerce_settings({"show_price": 1})
-		frappe.local.shopping_cart_settings = None
-
-		engine = ProductQuery()
-		result = engine.query(attributes={}, fields={}, search_term=None, start=4, item_group=None)
-		self.assertTrue(bool(result.get("discounts")))
-
-		filter_engine = ProductFiltersBuilder()
-		discount_filters = filter_engine.get_discount_filters(result["discounts"])
-
-		self.assertEqual(len(discount_filters[0]), 2)
-		self.assertEqual(discount_filters[0][0], 10)
-		self.assertEqual(discount_filters[0][1], "10% and below")
-
-	def test_product_list_with_discount_filters(self):
-		"Test if discount filters are applied correctly."
-		from erpnext.e_commerce.doctype.website_item.test_website_item import (
-			make_web_item_price,
-			make_web_pricing_rule,
-		)
-
-		field_filters = {"discount": [10]}
-
-		make_web_item_price(item_code="Test 12I Laptop")
-		make_web_pricing_rule(
-			title="Test Pricing Rule for Test 12I Laptop",  # 10% discount
-			item_code="Test 12I Laptop",
-			selling=1,
-		)
-		make_web_item_price(item_code="Test 13I Laptop")
-		make_web_pricing_rule(
-			title="Test Pricing Rule for Test 13I Laptop",  # 15% discount
-			item_code="Test 13I Laptop",
-			discount_percentage=15,
-			selling=1,
-		)
-
-		setup_e_commerce_settings({"show_price": 1})
-		frappe.local.shopping_cart_settings = None
-
-		engine = ProductQuery()
-		result = engine.query(
-			attributes={}, fields=field_filters, search_term=None, start=0, item_group=None
-		)
-		items = result.get("items")
-
-		# check if only product with 10% and below discount are fetched
-		self.assertEqual(len(items), 1)
-		self.assertEqual(items[0].get("item_code"), "Test 12I Laptop")
-
-	def test_product_list_with_api(self):
-		"Test products listing using API."
-		from erpnext.e_commerce.api import get_product_filter_data
-
-		create_variant_web_item()
-
-		result = get_product_filter_data(
-			query_args={
-				"field_filters": {"item_group": "Products"},
-				"attribute_filters": {"Test Size": ["Large"]},
-				"start": 0,
-			}
-		)
-
-		items = result.get("items")
-
-		self.assertEqual(len(items), 1)
-		self.assertEqual(items[0].get("item_code"), "Test Web Item-L")
-
-	def test_product_list_with_variants(self):
-		"Test if variants are hideen on hiding variants in settings."
-		create_variant_web_item()
-
-		setup_e_commerce_settings({"enable_attribute_filters": 0, "hide_variants": 1})
-		frappe.local.shopping_cart_settings = None
-
-		attribute_filters = {"Test Size": ["Large"]}
-		engine = ProductQuery()
-		result = engine.query(
-			attributes=attribute_filters, fields={}, search_term=None, start=0, item_group=None
-		)
-		items = result.get("items")
-
-		# check if any variants are fetched even though published variant exists
-		self.assertEqual(len(items), 0)
-
-		# tear down
-		setup_e_commerce_settings({"enable_attribute_filters": 1, "hide_variants": 0})
-
-	def test_custom_field_as_filter(self):
-		"Test if custom field functions as filter correctly."
-		from frappe.custom.doctype.custom_field.custom_field import create_custom_field
-
-		create_custom_field(
-			"Website Item",
-			dict(
-				owner="Administrator",
-				fieldname="supplier",
-				label="Supplier",
-				fieldtype="Link",
-				options="Supplier",
-				insert_after="on_backorder",
-			),
-		)
-
-		frappe.db.set_value(
-			"Website Item", {"item_code": "Test 11I Laptop"}, "supplier", "_Test Supplier"
-		)
-		frappe.db.set_value(
-			"Website Item", {"item_code": "Test 12I Laptop"}, "supplier", "_Test Supplier 1"
-		)
-
-		settings = frappe.get_doc("E Commerce Settings")
-		settings.append("filter_fields", {"fieldname": "supplier"})
-		settings.save()
-
-		filter_engine = ProductFiltersBuilder()
-		field_filters = filter_engine.get_field_filters()
-		custom_filter = field_filters[1]
-		filter_values = custom_filter[1]
-
-		self.assertEqual(custom_filter[0].options, "Supplier")
-		self.assertEqual(len(filter_values), 2)
-		self.assertIn("_Test Supplier", filter_values)
-
-		# test if custom filter works in query
-		field_filters = {"supplier": "_Test Supplier 1"}
-		engine = ProductQuery()
-		result = engine.query(
-			attributes={}, fields=field_filters, search_term=None, start=0, item_group=None
-		)
-		items = result.get("items")
-
-		# check if only 'Raw Material' are fetched in the right order
-		self.assertEqual(len(items), 1)
-		self.assertEqual(items[0].get("item_code"), "Test 12I Laptop")
-
-
-def create_variant_web_item():
-	"Create Variant and Template Website Items."
-	from erpnext.controllers.item_variant import create_variant
-	from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-	from erpnext.stock.doctype.item.test_item import make_item
-
-	make_item(
-		"Test Web Item",
-		{
-			"has_variant": 1,
-			"variant_based_on": "Item Attribute",
-			"attributes": [{"attribute": "Test Size"}],
-		},
-	)
-	if not frappe.db.exists("Item", "Test Web Item-L"):
-		variant = create_variant("Test Web Item", {"Test Size": "Large"})
-		variant.save()
-
-	if not frappe.db.exists("Website Item", {"variant_of": "Test Web Item"}):
-		make_website_item(variant, save=True)
diff --git a/erpnext/e_commerce/product_ui/grid.js b/erpnext/e_commerce/product_ui/grid.js
deleted file mode 100644
index 20a6c30..0000000
--- a/erpnext/e_commerce/product_ui/grid.js
+++ /dev/null
@@ -1,201 +0,0 @@
-erpnext.ProductGrid = class {
-	/* Options:
-		- items: Items
-		- settings: E Commerce Settings
-		- products_section: Products Wrapper
-		- preference: If preference is not grid view, render but hide
-	*/
-	constructor(options) {
-		Object.assign(this, options);
-
-		if (this.preference !== "Grid View") {
-			this.products_section.addClass("hidden");
-		}
-
-		this.products_section.empty();
-		this.make();
-	}
-
-	make() {
-		let me = this;
-		let html = ``;
-
-		this.items.forEach(item => {
-			let title = item.web_item_name || item.item_name || item.item_code || "";
-			title =  title.length > 90 ? title.substr(0, 90) + "..." : title;
-
-			html += `<div class="col-sm-4 item-card"><div class="card text-left">`;
-			html += me.get_image_html(item, title);
-			html += me.get_card_body_html(item, title, me.settings);
-			html += `</div></div>`;
-		});
-
-		let $product_wrapper = this.products_section;
-		$product_wrapper.append(html);
-	}
-
-	get_image_html(item, title) {
-		let image = item.website_image;
-
-		if (image) {
-			return `
-				<div class="card-img-container">
-					<a href="/${ item.route || '#' }" style="text-decoration: none;">
-						<img class="card-img" src="${ image }" alt="${ title }">
-					</a>
-				</div>
-			`;
-		} else {
-			return `
-				<div class="card-img-container">
-					<a href="/${ item.route || '#' }" style="text-decoration: none;">
-						<div class="card-img-top no-image">
-							${ frappe.get_abbr(title) }
-						</div>
-					</a>
-				</div>
-			`;
-		}
-	}
-
-	get_card_body_html(item, title, settings) {
-		let body_html = `
-			<div class="card-body text-left card-body-flex" style="width:100%">
-				<div style="margin-top: 1rem; display: flex;">
-		`;
-		body_html += this.get_title(item, title);
-
-		// get floating elements
-		if (!item.has_variants) {
-			if (settings.enable_wishlist) {
-				body_html += this.get_wishlist_icon(item);
-			}
-			if (settings.enabled) {
-				body_html += this.get_cart_indicator(item);
-			}
-
-		}
-
-		body_html += `</div>`;
-		body_html += `<div class="product-category">${ item.item_group || '' }</div>`;
-
-		if (item.formatted_price) {
-			body_html += this.get_price_html(item);
-		}
-
-		body_html += this.get_stock_availability(item, settings);
-		body_html += this.get_primary_button(item, settings);
-		body_html += `</div>`; // close div on line 49
-
-		return body_html;
-	}
-
-	get_title(item, title) {
-		let title_html = `
-			<a href="/${ item.route || '#' }">
-				<div class="product-title">
-					${ title || '' }
-				</div>
-			</a>
-		`;
-		return title_html;
-	}
-
-	get_wishlist_icon(item) {
-		let icon_class = item.wished ? "wished" : "not-wished";
-		return `
-			<div class="like-action ${ item.wished ? "like-action-wished" : ''}"
-				data-item-code="${ item.item_code }">
-				<svg class="icon sm">
-					<use class="${ icon_class } wish-icon" href="#icon-heart"></use>
-				</svg>
-			</div>
-		`;
-	}
-
-	get_cart_indicator(item) {
-		return `
-			<div class="cart-indicator ${item.in_cart ? '' : 'hidden'}" data-item-code="${ item.item_code }">
-				1
-			</div>
-		`;
-	}
-
-	get_price_html(item) {
-		let price_html = `
-			<div class="product-price">
-				${ item.formatted_price || '' }
-		`;
-
-		if (item.formatted_mrp) {
-			price_html += `
-				<small class="striked-price">
-					<s>${ item.formatted_mrp ? item.formatted_mrp.replace(/ +/g, "") : "" }</s>
-				</small>
-				<small class="ml-1 product-info-green">
-					${ item.discount } OFF
-				</small>
-			`;
-		}
-		price_html += `</div>`;
-		return price_html;
-	}
-
-	get_stock_availability(item, settings) {
-		if (settings.show_stock_availability && !item.has_variants) {
-			if (item.on_backorder) {
-				return `
-					<span class="out-of-stock mb-2 mt-1" style="color: var(--primary-color)">
-						${ __("Available on backorder") }
-					</span>
-				`;
-			} else if (!item.in_stock) {
-				return `
-					<span class="out-of-stock mb-2 mt-1">
-						${ __("Out of stock") }
-					</span>
-				`;
-			}
-		}
-
-		return ``;
-	}
-
-	get_primary_button(item, settings) {
-		if (item.has_variants) {
-			return `
-				<a href="/${ item.route || '#' }">
-					<div class="btn btn-sm btn-explore-variants w-100 mt-4">
-						${ __('Explore') }
-					</div>
-				</a>
-			`;
-		} else if (settings.enabled && (settings.allow_items_not_in_stock || item.in_stock)) {
-			return `
-				<div id="${ item.name }" class="btn
-					btn-sm btn-primary btn-add-to-cart-list
-					w-100 mt-2 ${ item.in_cart ? 'hidden' : '' }"
-					data-item-code="${ item.item_code }">
-					<span class="mr-2">
-						<svg class="icon icon-md">
-							<use href="#icon-assets"></use>
-						</svg>
-					</span>
-					${ settings.enable_checkout ? __('Add to Cart') :  __('Add to Quote') }
-				</div>
-
-				<a href="/cart">
-					<div id="${ item.name }" class="btn
-						btn-sm btn-primary btn-add-to-cart-list
-						w-100 mt-4 go-to-cart-grid
-						${ item.in_cart ? '' : 'hidden' }"
-						data-item-code="${ item.item_code }">
-						${ settings.enable_checkout ? __('Go to Cart') :  __('Go to Quote') }
-					</div>
-				</a>
-			`;
-		} else {
-			return ``;
-		}
-	}
-};
\ No newline at end of file
diff --git a/erpnext/e_commerce/product_ui/list.js b/erpnext/e_commerce/product_ui/list.js
deleted file mode 100644
index c8fd767..0000000
--- a/erpnext/e_commerce/product_ui/list.js
+++ /dev/null
@@ -1,205 +0,0 @@
-erpnext.ProductList = class {
-	/* Options:
-		- items: Items
-		- settings: E Commerce Settings
-		- products_section: Products Wrapper
-		- preference: If preference is not list view, render but hide
-	*/
-	constructor(options) {
-		Object.assign(this, options);
-
-		if (this.preference !== "List View") {
-			this.products_section.addClass("hidden");
-		}
-
-		this.products_section.empty();
-		this.make();
-	}
-
-	make() {
-		let me = this;
-		let html = `<br><br>`;
-
-		this.items.forEach(item => {
-			let title = item.web_item_name || item.item_name || item.item_code || "";
-			title =  title.length > 200 ? title.substr(0, 200) + "..." : title;
-
-			html += `<div class='row list-row w-100 mb-4'>`;
-			html += me.get_image_html(item, title, me.settings);
-			html += me.get_row_body_html(item, title, me.settings);
-			html += `</div>`;
-		});
-
-		let $product_wrapper = this.products_section;
-		$product_wrapper.append(html);
-	}
-
-	get_image_html(item, title, settings) {
-		let image = item.website_image;
-		let wishlist_enabled = !item.has_variants && settings.enable_wishlist;
-		let image_html = ``;
-
-		if (image) {
-			image_html += `
-				<div class="col-2 border text-center rounded list-image">
-					<a class="product-link product-list-link" href="/${ item.route || '#' }">
-						<img itemprop="image" class="website-image h-100 w-100" alt="${ title }"
-							src="${ image }">
-					</a>
-					${ wishlist_enabled ? this.get_wishlist_icon(item): '' }
-				</div>
-			`;
-		} else {
-			image_html += `
-				<div class="col-2 border text-center rounded list-image">
-					<a class="product-link product-list-link" href="/${ item.route || '#' }"
-						style="text-decoration: none">
-						<div class="card-img-top no-image-list">
-							${ frappe.get_abbr(title) }
-						</div>
-					</a>
-					${ wishlist_enabled ? this.get_wishlist_icon(item): '' }
-				</div>
-			`;
-		}
-
-		return image_html;
-	}
-
-	get_row_body_html(item, title, settings) {
-		let body_html = `<div class='col-10 text-left'>`;
-		body_html += this.get_title_html(item, title, settings);
-		body_html += this.get_item_details(item, settings);
-		body_html += `</div>`;
-		return body_html;
-	}
-
-	get_title_html(item, title, settings) {
-		let title_html = `<div style="display: flex; margin-left: -15px;">`;
-		title_html += `
-			<div class="col-8" style="margin-right: -15px;">
-				<a href="/${ item.route || '#' }">
-					<div class="product-title">
-					${ title }
-					</div>
-				</a>
-			</div>
-		`;
-
-		if (settings.enabled) {
-			title_html += `<div class="col-4 cart-action-container ${item.in_cart ? 'd-flex' : ''}">`;
-			title_html += this.get_primary_button(item, settings);
-			title_html += `</div>`;
-		}
-		title_html += `</div>`;
-
-		return title_html;
-	}
-
-	get_item_details(item, settings) {
-		let details = `
-			<p class="product-code">
-				${ item.item_group } | Item Code : ${ item.item_code }
-			</p>
-			<div class="mt-2" style="color: var(--gray-600) !important; font-size: 13px;">
-				${ item.short_description || '' }
-			</div>
-			<div class="product-price">
-				${ item.formatted_price || '' }
-		`;
-
-		if (item.formatted_mrp) {
-			details += `
-				<small class="striked-price">
-					<s>${ item.formatted_mrp ? item.formatted_mrp.replace(/ +/g, "") : "" }</s>
-				</small>
-				<small class="ml-1 product-info-green">
-					${ item.discount } OFF
-				</small>
-			`;
-		}
-
-		details += this.get_stock_availability(item, settings);
-		details += `</div>`;
-
-		return details;
-	}
-
-	get_stock_availability(item, settings) {
-		if (settings.show_stock_availability && !item.has_variants) {
-			if (item.on_backorder) {
-				return `
-					<br>
-					<span class="out-of-stock mt-2" style="color: var(--primary-color)">
-						${ __("Available on backorder") }
-					</span>
-				`;
-			} else if (!item.in_stock) {
-				return `
-					<br>
-					<span class="out-of-stock mt-2">${ __("Out of stock") }</span>
-				`;
-			}
-		}
-		return ``;
-	}
-
-	get_wishlist_icon(item) {
-		let icon_class = item.wished ? "wished" : "not-wished";
-
-		return `
-			<div class="like-action-list ${ item.wished ? "like-action-wished" : ''}"
-				data-item-code="${ item.item_code }">
-				<svg class="icon sm">
-					<use class="${ icon_class } wish-icon" href="#icon-heart"></use>
-				</svg>
-			</div>
-		`;
-	}
-
-	get_primary_button(item, settings) {
-		if (item.has_variants) {
-			return `
-				<a href="/${ item.route || '#' }">
-					<div class="btn btn-sm btn-explore-variants btn mb-0 mt-0">
-						${ __('Explore') }
-					</div>
-				</a>
-			`;
-		} else if (settings.enabled && (settings.allow_items_not_in_stock || item.in_stock)) {
-			return `
-				<div id="${ item.name }" class="btn
-					btn-sm btn-primary btn-add-to-cart-list mb-0
-					${ item.in_cart ? 'hidden' : '' }"
-					data-item-code="${ item.item_code }"
-					style="margin-top: 0px !important; max-height: 30px; float: right;
-						padding: 0.25rem 1rem; min-width: 135px;">
-					<span class="mr-2">
-						<svg class="icon icon-md">
-							<use href="#icon-assets"></use>
-						</svg>
-					</span>
-					${ settings.enable_checkout ? __('Add to Cart') :  __('Add to Quote') }
-				</div>
-
-				<div class="cart-indicator list-indicator ${item.in_cart ? '' : 'hidden'}">
-					1
-				</div>
-
-				<a href="/cart">
-					<div id="${ item.name }" class="btn
-						btn-sm btn-primary btn-add-to-cart-list
-						ml-4 go-to-cart mb-0 mt-0
-						${ item.in_cart ? '' : 'hidden' }"
-						data-item-code="${ item.item_code }"
-						style="padding: 0.25rem 1rem; min-width: 135px;">
-						${ settings.enable_checkout ? __('Go to Cart') :  __('Go to Quote') }
-					</div>
-				</a>
-			`;
-		} else {
-			return ``;
-		}
-	}
-
-};
diff --git a/erpnext/e_commerce/product_ui/search.js b/erpnext/e_commerce/product_ui/search.js
deleted file mode 100644
index 1688cc1..0000000
--- a/erpnext/e_commerce/product_ui/search.js
+++ /dev/null
@@ -1,244 +0,0 @@
-erpnext.ProductSearch = class {
-	constructor(opts) {
-		/* Options: search_box_id (for custom search box) */
-		$.extend(this, opts);
-		this.MAX_RECENT_SEARCHES = 4;
-		this.search_box_id = this.search_box_id || "#search-box";
-		this.searchBox = $(this.search_box_id);
-
-		this.setupSearchDropDown();
-		this.bindSearchAction();
-	}
-
-	setupSearchDropDown() {
-		this.search_area = $("#dropdownMenuSearch");
-		this.setupSearchResultContainer();
-		this.populateRecentSearches();
-	}
-
-	bindSearchAction() {
-		let me = this;
-
-		// Show Search dropdown
-		this.searchBox.on("focus", () => {
-			this.search_dropdown.removeClass("hidden");
-		});
-
-		// If click occurs outside search input/results, hide results.
-		// Click can happen anywhere on the page
-		$("body").on("click", (e) => {
-			let searchEvent = $(e.target).closest(this.search_box_id).length;
-			let resultsEvent = $(e.target).closest('#search-results-container').length;
-			let isResultHidden = this.search_dropdown.hasClass("hidden");
-
-			if (!searchEvent && !resultsEvent && !isResultHidden) {
-				this.search_dropdown.addClass("hidden");
-			}
-		});
-
-		// Process search input
-		this.searchBox.on("input", (e) => {
-			let query = e.target.value;
-
-			if (query.length == 0) {
-				me.populateResults(null);
-				me.populateCategoriesList(null);
-			}
-
-			if (query.length < 3 || !query.length) return;
-
-			frappe.call({
-				method: "erpnext.templates.pages.product_search.search",
-				args: {
-					query: query
-				},
-				callback: (data) => {
-					let product_results = null, category_results = null;
-
-					// Populate product results
-					product_results = data.message ? data.message.product_results : null;
-					me.populateResults(product_results);
-
-					// Populate categories
-					if (me.category_container) {
-						category_results = data.message ? data.message.category_results : null;
-						me.populateCategoriesList(category_results);
-					}
-
-					// Populate recent search chips only on successful queries
-					if (!$.isEmptyObject(product_results) || !$.isEmptyObject(category_results)) {
-						me.setRecentSearches(query);
-					}
-				}
-			});
-
-			this.search_dropdown.removeClass("hidden");
-		});
-	}
-
-	setupSearchResultContainer() {
-		this.search_dropdown = this.search_area.append(`
-			<div class="overflow-hidden shadow dropdown-menu w-100 hidden"
-				id="search-results-container"
-				aria-labelledby="dropdownMenuSearch"
-				style="display: flex; flex-direction: column;">
-			</div>
-		`).find("#search-results-container");
-
-		this.setupCategoryContainer();
-		this.setupProductsContainer();
-		this.setupRecentsContainer();
-	}
-
-	setupProductsContainer() {
-		this.products_container = this.search_dropdown.append(`
-			<div id="product-results mt-2">
-				<div id="product-scroll" style="overflow: scroll; max-height: 300px">
-				</div>
-			</div>
-		`).find("#product-scroll");
-	}
-
-	setupCategoryContainer() {
-		this.category_container = this.search_dropdown.append(`
-			<div class="category-container mt-2 mb-1">
-				<div class="category-chips">
-				</div>
-			</div>
-		`).find(".category-chips");
-	}
-
-	setupRecentsContainer() {
-		let $recents_section = this.search_dropdown.append(`
-			<div class="mb-2 mt-2 recent-searches">
-				<div>
-					<b>${ __("Recent") }</b>
-				</div>
-			</div>
-		`).find(".recent-searches");
-
-		this.recents_container = $recents_section.append(`
-			<div id="recents" style="padding: .25rem 0 1rem 0;">
-			</div>
-		`).find("#recents");
-	}
-
-	getRecentSearches() {
-		return JSON.parse(localStorage.getItem("recent_searches") || "[]");
-	}
-
-	attachEventListenersToChips() {
-		let me  = this;
-		const chips = $(".recent-search");
-		window.chips = chips;
-
-		for (let chip of chips) {
-			chip.addEventListener("click", () => {
-				me.searchBox[0].value = chip.innerText.trim();
-
-				// Start search with `recent query`
-				me.searchBox.trigger("input");
-				me.searchBox.focus();
-			});
-		}
-	}
-
-	setRecentSearches(query) {
-		let recents = this.getRecentSearches();
-		if (recents.length >= this.MAX_RECENT_SEARCHES) {
-			// Remove the `first` query
-			recents.splice(0, 1);
-		}
-
-		if (recents.indexOf(query) >= 0) {
-			return;
-		}
-
-		recents.push(query);
-		localStorage.setItem("recent_searches", JSON.stringify(recents));
-
-		this.populateRecentSearches();
-	}
-
-	populateRecentSearches() {
-		let recents = this.getRecentSearches();
-
-		if (!recents.length) {
-			this.recents_container.html(`<span class=""text-muted">No searches yet.</span>`);
-			return;
-		}
-
-		let html = "";
-		recents.forEach((key) => {
-			html += `
-				<div class="recent-search mr-1" style="font-size: 13px">
-					<span class="mr-2">
-						<svg width="20" height="20" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-							<path d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14Z" stroke="var(--gray-500)"" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-							<path d="M8.00027 5.20947V8.00017L10 10" stroke="var(--gray-500)" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-						</svg>
-					</span>
-					${ key }
-				</div>
-			`;
-		});
-
-		this.recents_container.html(html);
-		this.attachEventListenersToChips();
-	}
-
-	populateResults(product_results) {
-		if (!product_results || product_results.length === 0) {
-			let empty_html = ``;
-			this.products_container.html(empty_html);
-			return;
-		}
-
-		let html = "";
-
-		product_results.forEach((res) => {
-			let thumbnail = res.thumbnail || '/assets/erpnext/images/ui-states/cart-empty-state.png';
-			html += `
-				<div class="dropdown-item" style="display: flex;">
-					<img class="item-thumb col-2" src=${encodeURI(thumbnail)} />
-					<div class="col-9" style="white-space: normal;">
-						<a href="/${res.route}">${res.web_item_name}</a><br>
-						<span class="brand-line">${res.brand ? "by " + res.brand : ""}</span>
-					</div>
-				</div>
-			`;
-		});
-
-		this.products_container.html(html);
-	}
-
-	populateCategoriesList(category_results) {
-		if (!category_results || category_results.length === 0) {
-			let empty_html = `
-				<div class="category-container mt-2">
-					<div class="category-chips">
-					</div>
-				</div>
-			`;
-			this.category_container.html(empty_html);
-			return;
-		}
-
-		let html = `
-			<div class="mb-2">
-				<b>${ __("Categories") }</b>
-			</div>
-		`;
-
-		category_results.forEach((category) => {
-			html += `
-				<a href="/${category.route}" class="btn btn-sm category-chip mr-2 mb-2"
-					style="font-size: 13px" role="button">
-				${ category.name }
-				</button>
-			`;
-		});
-
-		this.category_container.html(html);
-	}
-};
diff --git a/erpnext/e_commerce/product_ui/views.js b/erpnext/e_commerce/product_ui/views.js
deleted file mode 100644
index fb63b21..0000000
--- a/erpnext/e_commerce/product_ui/views.js
+++ /dev/null
@@ -1,548 +0,0 @@
-erpnext.ProductView =  class {
-	/* Options:
-		- View Type
-		- Products Section Wrapper,
-		- Item Group: If its an Item Group page
-	*/
-	constructor(options) {
-		Object.assign(this, options);
-		this.preference = this.view_type;
-		this.make();
-	}
-
-	make(from_filters=false) {
-		this.products_section.empty();
-		this.prepare_toolbar();
-		this.get_item_filter_data(from_filters);
-	}
-
-	prepare_toolbar() {
-		this.products_section.append(`
-			<div class="toolbar d-flex">
-			</div>
-		`);
-		this.prepare_search();
-		this.prepare_view_toggler();
-
-		new erpnext.ProductSearch();
-	}
-
-	prepare_view_toggler() {
-
-		if (!$("#list").length || !$("#image-view").length) {
-			this.render_view_toggler();
-			this.bind_view_toggler_actions();
-			this.set_view_state();
-		}
-	}
-
-	get_item_filter_data(from_filters=false) {
-		// Get and render all Product related views
-		let me = this;
-		this.from_filters = from_filters;
-		let args = this.get_query_filters();
-
-		this.disable_view_toggler(true);
-
-		frappe.call({
-			method: "erpnext.e_commerce.api.get_product_filter_data",
-			args: {
-				query_args: args
-			},
-			callback: function(result) {
-				if (!result || result.exc || !result.message || result.message.exc) {
-					me.render_no_products_section(true);
-				} else {
-					// Sub Category results are independent of Items
-					if (me.item_group && result.message["sub_categories"].length) {
-						me.render_item_sub_categories(result.message["sub_categories"]);
-					}
-
-					if (!result.message["items"].length) {
-						// if result has no items or result is empty
-						me.render_no_products_section();
-					} else {
-						// Add discount filters
-						me.re_render_discount_filters(result.message["filters"].discount_filters);
-
-						// Render views
-						me.render_list_view(result.message["items"], result.message["settings"]);
-						me.render_grid_view(result.message["items"], result.message["settings"]);
-
-						me.products = result.message["items"];
-						me.product_count = result.message["items_count"];
-					}
-
-					// Bind filter actions
-					if (!from_filters) {
-						// If `get_product_filter_data` was triggered after checking a filter,
-						// don't touch filters unnecessarily, only data must change
-						// filter persistence is handle on filter change event
-						me.bind_filters();
-						me.restore_filters_state();
-					}
-
-					// Bottom paging
-					me.add_paging_section(result.message["settings"]);
-				}
-
-				me.disable_view_toggler(false);
-			}
-		});
-	}
-
-	disable_view_toggler(disable=false) {
-		$('#list').prop('disabled', disable);
-		$('#image-view').prop('disabled', disable);
-	}
-
-	render_grid_view(items, settings) {
-		// loop over data and add grid html to it
-		let me = this;
-		this.prepare_product_area_wrapper("grid");
-
-		new erpnext.ProductGrid({
-			items: items,
-			products_section: $("#products-grid-area"),
-			settings: settings,
-			preference: me.preference
-		});
-	}
-
-	render_list_view(items, settings) {
-		let me = this;
-		this.prepare_product_area_wrapper("list");
-
-		new erpnext.ProductList({
-			items: items,
-			products_section: $("#products-list-area"),
-			settings: settings,
-			preference: me.preference
-		});
-	}
-
-	prepare_product_area_wrapper(view) {
-		let left_margin = view == "list" ? "ml-2" : "";
-		let top_margin = view == "list" ? "mt-6" : "mt-minus-1";
-		return this.products_section.append(`
-			<br>
-			<div id="products-${view}-area" class="row products-list ${ top_margin } ${ left_margin }"></div>
-		`);
-	}
-
-	get_query_filters() {
-		const filters = frappe.utils.get_query_params();
-		let {field_filters, attribute_filters} = filters;
-
-		field_filters = field_filters ? JSON.parse(field_filters) : {};
-		attribute_filters = attribute_filters ? JSON.parse(attribute_filters) : {};
-
-		return {
-			field_filters: field_filters,
-			attribute_filters: attribute_filters,
-			item_group: this.item_group,
-			start: filters.start || null,
-			from_filters: this.from_filters || false
-		};
-	}
-
-	add_paging_section(settings) {
-		$(".product-paging-area").remove();
-
-		if (this.products) {
-			let paging_html = `
-				<div class="row product-paging-area mt-5">
-					<div class="col-3">
-					</div>
-					<div class="col-9 text-right">
-			`;
-			let query_params = frappe.utils.get_query_params();
-			let start = query_params.start ? cint(JSON.parse(query_params.start)) : 0;
-			let page_length = settings.products_per_page || 0;
-
-			let prev_disable = start > 0 ? "" : "disabled";
-			let next_disable = (this.product_count > page_length) ? "" : "disabled";
-
-			paging_html += `
-				<button class="btn btn-default btn-prev" data-start="${ start - page_length }"
-					style="float: left" ${prev_disable}>
-					${ __("Prev") }
-				</button>`;
-
-			paging_html += `
-				<button class="btn btn-default btn-next" data-start="${ start + page_length }"
-					${next_disable}>
-					${ __("Next") }
-				</button>
-			`;
-
-			paging_html += `</div></div>`;
-
-			$(".page_content").append(paging_html);
-			this.bind_paging_action();
-		}
-	}
-
-	prepare_search() {
-		$(".toolbar").append(`
-			<div class="input-group col-8 p-0">
-				<div class="dropdown w-100" id="dropdownMenuSearch">
-					<input type="search" name="query" id="search-box" class="form-control font-md"
-						placeholder="Search for Products"
-						aria-label="Product" aria-describedby="button-addon2">
-					<div class="search-icon">
-						<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
-							fill="none"
-							stroke="currentColor" stroke-width="2" stroke-linecap="round"
-							stroke-linejoin="round"
-							class="feather feather-search">
-							<circle cx="11" cy="11" r="8"></circle>
-							<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
-						</svg>
-					</div>
-					<!-- Results dropdown rendered in product_search.js -->
-				</div>
-			</div>
-		`);
-	}
-
-	render_view_toggler() {
-		$(".toolbar").append(`<div class="toggle-container col-4 p-0"></div>`);
-
-		["btn-list-view", "btn-grid-view"].forEach(view => {
-			let icon = view === "btn-list-view" ? "list" : "image-view";
-			$(".toggle-container").append(`
-				<div class="form-group mb-0" id="toggle-view">
-					<button id="${ icon }" class="btn ${ view } mr-2">
-						<span>
-							<svg class="icon icon-md">
-								<use href="#icon-${ icon }"></use>
-							</svg>
-						</span>
-					</button>
-				</div>
-			`);
-		});
-	}
-
-	bind_view_toggler_actions() {
-		$("#list").click(function() {
-			let $btn = $(this);
-			$btn.removeClass('btn-primary');
-			$btn.addClass('btn-primary');
-			$(".btn-grid-view").removeClass('btn-primary');
-
-			$("#products-grid-area").addClass("hidden");
-			$("#products-list-area").removeClass("hidden");
-			localStorage.setItem("product_view", "List View");
-		});
-
-		$("#image-view").click(function() {
-			let $btn = $(this);
-			$btn.removeClass('btn-primary');
-			$btn.addClass('btn-primary');
-			$(".btn-list-view").removeClass('btn-primary');
-
-			$("#products-list-area").addClass("hidden");
-			$("#products-grid-area").removeClass("hidden");
-			localStorage.setItem("product_view", "Grid View");
-		});
-	}
-
-	set_view_state() {
-		if (this.preference === "List View") {
-			$("#list").addClass('btn-primary');
-			$("#image-view").removeClass('btn-primary');
-		} else {
-			$("#image-view").addClass('btn-primary');
-			$("#list").removeClass('btn-primary');
-		}
-	}
-
-	bind_paging_action() {
-		let me = this;
-		$('.btn-prev, .btn-next').click((e) => {
-			const $btn = $(e.target);
-			me.from_filters = false;
-
-			$btn.prop('disabled', true);
-			const start = $btn.data('start');
-
-			let query_params = frappe.utils.get_query_params();
-			query_params.start = start;
-			let path = window.location.pathname + '?' + frappe.utils.get_url_from_dict(query_params);
-			window.location.href = path;
-		});
-	}
-
-	re_render_discount_filters(filter_data) {
-		this.get_discount_filter_html(filter_data);
-		if (this.from_filters) {
-			// Bind filter action if triggered via filters
-			// if not from filter action, page load will bind actions
-			this.bind_discount_filter_action();
-		}
-		// discount filters are rendered with Items (later)
-		// unlike the other filters
-		this.restore_discount_filter();
-	}
-
-	get_discount_filter_html(filter_data) {
-		$("#discount-filters").remove();
-		if (filter_data) {
-			$("#product-filters").append(`
-				<div id="discount-filters" class="mb-4 filter-block pb-5">
-					<div class="filter-label mb-3">${ __("Discounts") }</div>
-				</div>
-			`);
-
-			let html = `<div class="filter-options">`;
-			filter_data.forEach(filter => {
-				html += `
-					<div class="checkbox">
-						<label data-value="${ filter[0] }">
-							<input type="radio"
-								class="product-filter discount-filter"
-								name="discount" id="${ filter[0] }"
-								data-filter-name="discount"
-								data-filter-value="${ filter[0] }"
-								style="width: 14px !important"
-							>
-								<span class="label-area" for="${ filter[0] }">
-									${ filter[1] }
-								</span>
-						</label>
-					</div>
-				`;
-			});
-			html += `</div>`;
-
-			$("#discount-filters").append(html);
-		}
-	}
-
-	restore_discount_filter() {
-		const filters = frappe.utils.get_query_params();
-		let field_filters = filters.field_filters;
-		if (!field_filters) return;
-
-		field_filters = JSON.parse(field_filters);
-
-		if (field_filters && field_filters["discount"]) {
-			const values = field_filters["discount"];
-			const selector = values.map(value => {
-				return `input[data-filter-name="discount"][data-filter-value="${value}"]`;
-			}).join(',');
-			$(selector).prop('checked', true);
-			this.field_filters = field_filters;
-		}
-	}
-
-	bind_discount_filter_action() {
-		let me = this;
-		$('.discount-filter').on('change', (e) => {
-			const $checkbox = $(e.target);
-			const is_checked = $checkbox.is(':checked');
-
-			const {
-				filterValue: filter_value
-			} = $checkbox.data();
-
-			delete this.field_filters["discount"];
-
-			if (is_checked) {
-				this.field_filters["discount"] = [];
-				this.field_filters["discount"].push(filter_value);
-			}
-
-			if (this.field_filters["discount"].length === 0) {
-				delete this.field_filters["discount"];
-			}
-
-			me.change_route_with_filters();
-		});
-	}
-
-	bind_filters() {
-		let me = this;
-		this.field_filters = {};
-		this.attribute_filters = {};
-
-		$('.product-filter').on('change', (e) => {
-			me.from_filters = true;
-
-			const $checkbox = $(e.target);
-			const is_checked = $checkbox.is(':checked');
-
-			if ($checkbox.is('.attribute-filter')) {
-				const {
-					attributeName: attribute_name,
-					attributeValue: attribute_value
-				} = $checkbox.data();
-
-				if (is_checked) {
-					this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || [];
-					this.attribute_filters[attribute_name].push(attribute_value);
-				} else {
-					this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || [];
-					this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name].filter(v => v !== attribute_value);
-				}
-
-				if (this.attribute_filters[attribute_name].length === 0) {
-					delete this.attribute_filters[attribute_name];
-				}
-			} else if ($checkbox.is('.field-filter') || $checkbox.is('.discount-filter')) {
-				const {
-					filterName: filter_name,
-					filterValue: filter_value
-				} = $checkbox.data();
-
-				if ($checkbox.is('.discount-filter')) {
-					// clear previous discount filter to accomodate new
-					delete this.field_filters["discount"];
-				}
-				if (is_checked) {
-					this.field_filters[filter_name] = this.field_filters[filter_name] || [];
-					if (!in_list(this.field_filters[filter_name], filter_value)) {
-						this.field_filters[filter_name].push(filter_value);
-					}
-				} else {
-					this.field_filters[filter_name] = this.field_filters[filter_name] || [];
-					this.field_filters[filter_name] = this.field_filters[filter_name].filter(v => v !== filter_value);
-				}
-
-				if (this.field_filters[filter_name].length === 0) {
-					delete this.field_filters[filter_name];
-				}
-			}
-
-			me.change_route_with_filters();
-		});
-
-		// bind filter lookup input box
-		$('.filter-lookup-input').on('keydown', frappe.utils.debounce((e) => {
-			const $input = $(e.target);
-			const keyword = ($input.val() || '').toLowerCase();
-			const $filter_options = $input.next('.filter-options');
-
-			$filter_options.find('.filter-lookup-wrapper').show();
-			$filter_options.find('.filter-lookup-wrapper').each((i, el) => {
-				const $el = $(el);
-				const value = $el.data('value').toLowerCase();
-				if (!value.includes(keyword)) {
-					$el.hide();
-				}
-			});
-		}, 300));
-	}
-
-	change_route_with_filters() {
-		let route_params = frappe.utils.get_query_params();
-
-		let start = this.if_key_exists(route_params.start) || 0;
-		if (this.from_filters) {
-			start = 0; // show items from first page if new filters are triggered
-		}
-
-		const query_string = this.get_query_string({
-			start: start,
-			field_filters: JSON.stringify(this.if_key_exists(this.field_filters)),
-			attribute_filters: JSON.stringify(this.if_key_exists(this.attribute_filters)),
-		});
-		window.history.pushState('filters', '', `${location.pathname}?` + query_string);
-
-		$('.page_content input').prop('disabled', true);
-
-		this.make(true);
-		$('.page_content input').prop('disabled', false);
-	}
-
-	restore_filters_state() {
-		const filters = frappe.utils.get_query_params();
-		let {field_filters, attribute_filters} = filters;
-
-		if (field_filters) {
-			field_filters = JSON.parse(field_filters);
-			for (let fieldname in field_filters) {
-				const values = field_filters[fieldname];
-				const selector = values.map(value => {
-					return `input[data-filter-name="${fieldname}"][data-filter-value="${value}"]`;
-				}).join(',');
-				$(selector).prop('checked', true);
-			}
-			this.field_filters = field_filters;
-		}
-		if (attribute_filters) {
-			attribute_filters = JSON.parse(attribute_filters);
-			for (let attribute in attribute_filters) {
-				const values = attribute_filters[attribute];
-				const selector = values.map(value => {
-					return `input[data-attribute-name="${attribute}"][data-attribute-value="${value}"]`;
-				}).join(',');
-				$(selector).prop('checked', true);
-			}
-			this.attribute_filters = attribute_filters;
-		}
-	}
-
-	render_no_products_section(error=false) {
-		let error_section = `
-			<div class="mt-4 w-100 alert alert-error font-md">
-				Something went wrong. Please refresh or contact us.
-			</div>
-		`;
-		let no_results_section = `
-			<div class="cart-empty frappe-card mt-4">
-				<div class="cart-empty-state">
-					<img src="/assets/erpnext/images/ui-states/cart-empty-state.png" alt="Empty Cart">
-				</div>
-				<div class="cart-empty-message mt-4">${ __('No products found') }</p>
-			</div>
-		`;
-
-		this.products_section.append(error ? error_section : no_results_section);
-	}
-
-	render_item_sub_categories(categories) {
-		if (categories && categories.length) {
-			let sub_group_html = `
-				<div class="sub-category-container scroll-categories">
-			`;
-
-			categories.forEach(category => {
-				sub_group_html += `
-					<a href="/${ category.route || '#' }" style="text-decoration: none;">
-						<div class="category-pill">
-							${ category.name }
-						</div>
-					</a>
-				`;
-			});
-			sub_group_html += `</div>`;
-
-			$("#product-listing").prepend(sub_group_html);
-		}
-	}
-
-	get_query_string(object) {
-		const url = new URLSearchParams();
-		for (let key in object) {
-			const value = object[key];
-			if (value) {
-				url.append(key, value);
-			}
-		}
-		return url.toString();
-	}
-
-	if_key_exists(obj) {
-		let exists = false;
-		for (let key in obj) {
-			if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key]) {
-				exists = true;
-				break;
-			}
-		}
-		return exists ? obj : undefined;
-	}
-};
\ No newline at end of file
diff --git a/erpnext/e_commerce/redisearch_utils.py b/erpnext/e_commerce/redisearch_utils.py
deleted file mode 100644
index 87ca9bd..0000000
--- a/erpnext/e_commerce/redisearch_utils.py
+++ /dev/null
@@ -1,255 +0,0 @@
-# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import json
-
-import frappe
-from frappe import _
-from frappe.utils.redis_wrapper import RedisWrapper
-from redis import ResponseError
-from redis.commands.search.field import TagField, TextField
-from redis.commands.search.indexDefinition import IndexDefinition
-from redis.commands.search.suggestion import Suggestion
-
-WEBSITE_ITEM_INDEX = "website_items_index"
-WEBSITE_ITEM_KEY_PREFIX = "website_item:"
-WEBSITE_ITEM_NAME_AUTOCOMPLETE = "website_items_name_dict"
-WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE = "website_items_category_dict"
-
-
-def get_indexable_web_fields():
-	"Return valid fields from Website Item that can be searched for."
-	web_item_meta = frappe.get_meta("Website Item", cached=True)
-	valid_fields = filter(
-		lambda df: df.fieldtype in ("Link", "Table MultiSelect", "Data", "Small Text", "Text Editor"),
-		web_item_meta.fields,
-	)
-
-	return [df.fieldname for df in valid_fields]
-
-
-def is_redisearch_enabled():
-	"Return True only if redisearch is loaded and enabled."
-	is_redisearch_enabled = frappe.db.get_single_value("E Commerce Settings", "is_redisearch_enabled")
-	return is_search_module_loaded() and is_redisearch_enabled
-
-
-def is_search_module_loaded():
-	try:
-		cache = frappe.cache()
-		for module in cache.module_list():
-			if module.get(b"name") == b"search":
-				return True
-	except Exception:
-		return False  # handling older redis versions
-
-
-def if_redisearch_enabled(function):
-	"Decorator to check if Redisearch is enabled."
-
-	def wrapper(*args, **kwargs):
-		if is_redisearch_enabled():
-			func = function(*args, **kwargs)
-			return func
-		return
-
-	return wrapper
-
-
-def make_key(key):
-	return frappe.cache().make_key(key)
-
-
-@if_redisearch_enabled
-def create_website_items_index():
-	"Creates Index Definition."
-
-	redis = frappe.cache()
-	index = redis.ft(WEBSITE_ITEM_INDEX)
-
-	try:
-		index.dropindex()  # drop if already exists
-	except ResponseError:
-		# will most likely raise a ResponseError if index does not exist
-		# ignore and create index
-		pass
-	except Exception:
-		raise_redisearch_error()
-
-	idx_def = IndexDefinition([make_key(WEBSITE_ITEM_KEY_PREFIX)])
-
-	# Index fields mentioned in e-commerce settings
-	idx_fields = frappe.db.get_single_value("E Commerce Settings", "search_index_fields")
-	idx_fields = idx_fields.split(",") if idx_fields else []
-
-	if "web_item_name" in idx_fields:
-		idx_fields.remove("web_item_name")
-
-	idx_fields = [to_search_field(f) for f in idx_fields]
-
-	# TODO: sortable?
-	index.create_index(
-		[TextField("web_item_name", sortable=True)] + idx_fields,
-		definition=idx_def,
-	)
-
-	reindex_all_web_items()
-	define_autocomplete_dictionary()
-
-
-def to_search_field(field):
-	if field == "tags":
-		return TagField("tags", separator=",")
-
-	return TextField(field)
-
-
-@if_redisearch_enabled
-def insert_item_to_index(website_item_doc):
-	# Insert item to index
-	key = get_cache_key(website_item_doc.name)
-	cache = frappe.cache()
-	web_item = create_web_item_map(website_item_doc)
-
-	for field, value in web_item.items():
-		super(RedisWrapper, cache).hset(make_key(key), field, value)
-
-	insert_to_name_ac(website_item_doc.web_item_name, website_item_doc.name)
-
-
-@if_redisearch_enabled
-def insert_to_name_ac(web_name, doc_name):
-	ac = frappe.cache().ft()
-	ac.sugadd(WEBSITE_ITEM_NAME_AUTOCOMPLETE, Suggestion(web_name, payload=doc_name))
-
-
-def create_web_item_map(website_item_doc):
-	fields_to_index = get_fields_indexed()
-	web_item = {}
-
-	for field in fields_to_index:
-		web_item[field] = website_item_doc.get(field) or ""
-
-	return web_item
-
-
-@if_redisearch_enabled
-def update_index_for_item(website_item_doc):
-	# Reinsert to Cache
-	insert_item_to_index(website_item_doc)
-	define_autocomplete_dictionary()
-
-
-@if_redisearch_enabled
-def delete_item_from_index(website_item_doc):
-	cache = frappe.cache()
-	key = get_cache_key(website_item_doc.name)
-
-	try:
-		cache.delete(key)
-	except Exception:
-		raise_redisearch_error()
-
-	delete_from_ac_dict(website_item_doc)
-	return True
-
-
-@if_redisearch_enabled
-def delete_from_ac_dict(website_item_doc):
-	"""Removes this items's name from autocomplete dictionary"""
-	ac = frappe.cache().ft()
-	ac.sugdel(website_item_doc.web_item_name)
-
-
-@if_redisearch_enabled
-def define_autocomplete_dictionary():
-	"""
-	Defines/Redefines an autocomplete search dictionary for Website Item Name.
-	Also creats autocomplete dictionary for Published Item Groups.
-	"""
-
-	cache = frappe.cache()
-
-	# Delete both autocomplete dicts
-	try:
-		cache.delete(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE))
-		cache.delete(make_key(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE))
-	except Exception:
-		raise_redisearch_error()
-
-	create_items_autocomplete_dict()
-	create_item_groups_autocomplete_dict()
-
-
-@if_redisearch_enabled
-def create_items_autocomplete_dict():
-	"Add items as suggestions in Autocompleter."
-
-	ac = frappe.cache().ft()
-	items = frappe.get_all(
-		"Website Item", fields=["web_item_name", "item_group"], filters={"published": 1}
-	)
-	for item in items:
-		ac.sugadd(WEBSITE_ITEM_NAME_AUTOCOMPLETE, Suggestion(item.web_item_name))
-
-
-@if_redisearch_enabled
-def create_item_groups_autocomplete_dict():
-	"Add item groups with weightage as suggestions in Autocompleter."
-
-	published_item_groups = frappe.get_all(
-		"Item Group", fields=["name", "route", "weightage"], filters={"show_in_website": 1}
-	)
-	if not published_item_groups:
-		return
-
-	ac = frappe.cache().ft()
-
-	for item_group in published_item_groups:
-		payload = json.dumps({"name": item_group.name, "route": item_group.route})
-		ac.sugadd(
-			WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE,
-			Suggestion(
-				string=item_group.name,
-				score=frappe.utils.flt(item_group.weightage) or 1.0,
-				payload=payload,  # additional info that can be retrieved later
-			),
-		)
-
-
-@if_redisearch_enabled
-def reindex_all_web_items():
-	items = frappe.get_all("Website Item", fields=get_fields_indexed(), filters={"published": True})
-
-	cache = frappe.cache()
-	for item in items:
-		web_item = create_web_item_map(item)
-		key = make_key(get_cache_key(item.name))
-
-		for field, value in web_item.items():
-			super(RedisWrapper, cache).hset(key, field, value)
-
-
-def get_cache_key(name):
-	name = frappe.scrub(name)
-	return f"{WEBSITE_ITEM_KEY_PREFIX}{name}"
-
-
-def get_fields_indexed():
-	fields_to_index = frappe.db.get_single_value("E Commerce Settings", "search_index_fields")
-	fields_to_index = fields_to_index.split(",") if fields_to_index else []
-
-	mandatory_fields = ["name", "web_item_name", "route", "thumbnail", "ranking"]
-	fields_to_index = fields_to_index + mandatory_fields
-
-	return fields_to_index
-
-
-def raise_redisearch_error():
-	"Create an Error Log and raise error."
-	log = frappe.log_error("Redisearch Error")
-	log_link = frappe.utils.get_link_to_form("Error Log", log.name)
-
-	frappe.throw(
-		msg=_("Something went wrong. Check {0}").format(log_link), title=_("Redisearch Error")
-	)
diff --git a/erpnext/e_commerce/shopping_cart/__init__.py b/erpnext/e_commerce/shopping_cart/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/shopping_cart/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py
deleted file mode 100644
index 7c7e169..0000000
--- a/erpnext/e_commerce/shopping_cart/cart.py
+++ /dev/null
@@ -1,721 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import frappe.defaults
-from frappe import _, throw
-from frappe.contacts.doctype.address.address import get_address_display
-from frappe.contacts.doctype.contact.contact import get_contact_name
-from frappe.utils import cint, cstr, flt, get_fullname
-from frappe.utils.nestedset import get_root_of
-
-from erpnext.accounts.utils import get_account_name
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.utilities.product import get_web_item_qty_in_stock
-
-
-class WebsitePriceListMissingError(frappe.ValidationError):
-	pass
-
-
-def set_cart_count(quotation=None):
-	if cint(frappe.db.get_singles_value("E Commerce Settings", "enabled")):
-		if not quotation:
-			quotation = _get_cart_quotation()
-		cart_count = cstr(cint(quotation.get("total_qty")))
-
-		if hasattr(frappe.local, "cookie_manager"):
-			frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
-
-
-@frappe.whitelist()
-def get_cart_quotation(doc=None):
-	party = get_party()
-
-	if not doc:
-		quotation = _get_cart_quotation(party)
-		doc = quotation
-		set_cart_count(quotation)
-
-	addresses = get_address_docs(party=party)
-
-	if not doc.customer_address and addresses:
-		update_cart_address("billing", addresses[0].name)
-
-	return {
-		"doc": decorate_quotation_doc(doc),
-		"shipping_addresses": get_shipping_addresses(party),
-		"billing_addresses": get_billing_addresses(party),
-		"shipping_rules": get_applicable_shipping_rules(party),
-		"cart_settings": frappe.get_cached_doc("E Commerce Settings"),
-	}
-
-
-@frappe.whitelist()
-def get_shipping_addresses(party=None):
-	if not party:
-		party = get_party()
-	addresses = get_address_docs(party=party)
-	return [
-		{"name": address.name, "title": address.address_title, "display": address.display}
-		for address in addresses
-		if address.address_type == "Shipping"
-	]
-
-
-@frappe.whitelist()
-def get_billing_addresses(party=None):
-	if not party:
-		party = get_party()
-	addresses = get_address_docs(party=party)
-	return [
-		{"name": address.name, "title": address.address_title, "display": address.display}
-		for address in addresses
-		if address.address_type == "Billing"
-	]
-
-
-@frappe.whitelist()
-def place_order():
-	quotation = _get_cart_quotation()
-	cart_settings = frappe.db.get_value(
-		"E Commerce Settings", None, ["company", "allow_items_not_in_stock"], as_dict=1
-	)
-	quotation.company = cart_settings.company
-
-	quotation.flags.ignore_permissions = True
-	quotation.submit()
-
-	if quotation.quotation_to == "Lead" and quotation.party_name:
-		# company used to create customer accounts
-		frappe.defaults.set_user_default("company", quotation.company)
-
-	if not (quotation.shipping_address_name or quotation.customer_address):
-		frappe.throw(_("Set Shipping Address or Billing Address"))
-
-	from erpnext.selling.doctype.quotation.quotation import _make_sales_order
-
-	sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
-	sales_order.payment_schedule = []
-
-	if not cint(cart_settings.allow_items_not_in_stock):
-		for item in sales_order.get("items"):
-			item.warehouse = frappe.db.get_value(
-				"Website Item", {"item_code": item.item_code}, "website_warehouse"
-			)
-			is_stock_item = frappe.db.get_value("Item", item.item_code, "is_stock_item")
-
-			if is_stock_item:
-				item_stock = get_web_item_qty_in_stock(item.item_code, "website_warehouse")
-				if not cint(item_stock.in_stock):
-					throw(_("{0} Not in Stock").format(item.item_code))
-				if item.qty > item_stock.stock_qty:
-					throw(_("Only {0} in Stock for item {1}").format(item_stock.stock_qty, item.item_code))
-
-	sales_order.flags.ignore_permissions = True
-	sales_order.insert()
-	sales_order.submit()
-
-	if hasattr(frappe.local, "cookie_manager"):
-		frappe.local.cookie_manager.delete_cookie("cart_count")
-
-	return sales_order.name
-
-
-@frappe.whitelist()
-def request_for_quotation():
-	quotation = _get_cart_quotation()
-	quotation.flags.ignore_permissions = True
-
-	if get_shopping_cart_settings().save_quotations_as_draft:
-		quotation.save()
-	else:
-		quotation.submit()
-	return quotation.name
-
-
-@frappe.whitelist()
-def update_cart(item_code, qty, additional_notes=None, with_items=False):
-	quotation = _get_cart_quotation()
-
-	empty_card = False
-	qty = flt(qty)
-	if qty == 0:
-		quotation_items = quotation.get("items", {"item_code": ["!=", item_code]})
-		if quotation_items:
-			quotation.set("items", quotation_items)
-		else:
-			empty_card = True
-
-	else:
-		warehouse = frappe.get_cached_value(
-			"Website Item", {"item_code": item_code}, "website_warehouse"
-		)
-
-		quotation_items = quotation.get("items", {"item_code": item_code})
-		if not quotation_items:
-			quotation.append(
-				"items",
-				{
-					"doctype": "Quotation Item",
-					"item_code": item_code,
-					"qty": qty,
-					"additional_notes": additional_notes,
-					"warehouse": warehouse,
-				},
-			)
-		else:
-			quotation_items[0].qty = qty
-			quotation_items[0].additional_notes = additional_notes
-			quotation_items[0].warehouse = warehouse
-
-	apply_cart_settings(quotation=quotation)
-
-	quotation.flags.ignore_permissions = True
-	quotation.payment_schedule = []
-	if not empty_card:
-		quotation.save()
-	else:
-		quotation.delete()
-		quotation = None
-
-	set_cart_count(quotation)
-
-	if cint(with_items):
-		context = get_cart_quotation(quotation)
-		return {
-			"items": frappe.render_template("templates/includes/cart/cart_items.html", context),
-			"total": frappe.render_template("templates/includes/cart/cart_items_total.html", context),
-			"taxes_and_totals": frappe.render_template(
-				"templates/includes/cart/cart_payment_summary.html", context
-			),
-		}
-	else:
-		return {"name": quotation.name}
-
-
-@frappe.whitelist()
-def get_shopping_cart_menu(context=None):
-	if not context:
-		context = get_cart_quotation()
-
-	return frappe.render_template("templates/includes/cart/cart_dropdown.html", context)
-
-
-@frappe.whitelist()
-def add_new_address(doc):
-	doc = frappe.parse_json(doc)
-	doc.update({"doctype": "Address"})
-	address = frappe.get_doc(doc)
-	address.save(ignore_permissions=True)
-
-	return address
-
-
-@frappe.whitelist(allow_guest=True)
-def create_lead_for_item_inquiry(lead, subject, message):
-	lead = frappe.parse_json(lead)
-	lead_doc = frappe.new_doc("Lead")
-	for fieldname in ("lead_name", "company_name", "email_id", "phone"):
-		lead_doc.set(fieldname, lead.get(fieldname))
-
-	lead_doc.set("lead_owner", "")
-
-	if not frappe.db.exists("Lead Source", "Product Inquiry"):
-		frappe.get_doc({"doctype": "Lead Source", "source_name": "Product Inquiry"}).insert(
-			ignore_permissions=True
-		)
-
-	lead_doc.set("source", "Product Inquiry")
-
-	try:
-		lead_doc.save(ignore_permissions=True)
-	except frappe.exceptions.DuplicateEntryError:
-		frappe.clear_messages()
-		lead_doc = frappe.get_doc("Lead", {"email_id": lead["email_id"]})
-
-	lead_doc.add_comment(
-		"Comment",
-		text="""
-		<div>
-			<h5>{subject}</h5>
-			<p>{message}</p>
-		</div>
-	""".format(
-			subject=subject, message=message
-		),
-	)
-
-	return lead_doc
-
-
-@frappe.whitelist()
-def get_terms_and_conditions(terms_name):
-	return frappe.db.get_value("Terms and Conditions", terms_name, "terms")
-
-
-@frappe.whitelist()
-def update_cart_address(address_type, address_name):
-	quotation = _get_cart_quotation()
-	address_doc = frappe.get_doc("Address", address_name).as_dict()
-	address_display = get_address_display(address_doc)
-
-	if address_type.lower() == "billing":
-		quotation.customer_address = address_name
-		quotation.address_display = address_display
-		quotation.shipping_address_name = quotation.shipping_address_name or address_name
-		address_doc = next((doc for doc in get_billing_addresses() if doc["name"] == address_name), None)
-	elif address_type.lower() == "shipping":
-		quotation.shipping_address_name = address_name
-		quotation.shipping_address = address_display
-		quotation.customer_address = quotation.customer_address or address_name
-		address_doc = next(
-			(doc for doc in get_shipping_addresses() if doc["name"] == address_name), None
-		)
-	apply_cart_settings(quotation=quotation)
-
-	quotation.flags.ignore_permissions = True
-	quotation.save()
-
-	context = get_cart_quotation(quotation)
-	context["address"] = address_doc
-
-	return {
-		"taxes": frappe.render_template("templates/includes/order/order_taxes.html", context),
-		"address": frappe.render_template("templates/includes/cart/address_card.html", context),
-	}
-
-
-def guess_territory():
-	territory = None
-	geoip_country = frappe.session.get("session_country")
-	if geoip_country:
-		territory = frappe.db.get_value("Territory", geoip_country)
-
-	return (
-		territory
-		or frappe.db.get_value("E Commerce Settings", None, "territory")
-		or get_root_of("Territory")
-	)
-
-
-def decorate_quotation_doc(doc):
-	for d in doc.get("items", []):
-		item_code = d.item_code
-		fields = ["web_item_name", "thumbnail", "website_image", "description", "route"]
-
-		# Variant Item
-		if not frappe.db.exists("Website Item", {"item_code": item_code}):
-			variant_data = frappe.db.get_values(
-				"Item",
-				filters={"item_code": item_code},
-				fieldname=["variant_of", "item_name", "image"],
-				as_dict=True,
-			)[0]
-			item_code = variant_data.variant_of
-			fields = fields[1:]
-			d.web_item_name = variant_data.item_name
-
-			if variant_data.image:  # get image from variant or template web item
-				d.thumbnail = variant_data.image
-				fields = fields[2:]
-
-		d.update(frappe.db.get_value("Website Item", {"item_code": item_code}, fields, as_dict=True))
-		website_warehouse = frappe.get_cached_value(
-			"Website Item", {"item_code": item_code}, "website_warehouse"
-		)
-		d.warehouse = website_warehouse
-
-	return doc
-
-
-def _get_cart_quotation(party=None):
-	"""Return the open Quotation of type "Shopping Cart" or make a new one"""
-	if not party:
-		party = get_party()
-
-	quotation = frappe.get_all(
-		"Quotation",
-		fields=["name"],
-		filters={
-			"party_name": party.name,
-			"contact_email": frappe.session.user,
-			"order_type": "Shopping Cart",
-			"docstatus": 0,
-		},
-		order_by="modified desc",
-		limit_page_length=1,
-	)
-
-	if quotation:
-		qdoc = frappe.get_doc("Quotation", quotation[0].name)
-	else:
-		company = frappe.db.get_value("E Commerce Settings", None, ["company"])
-		qdoc = frappe.get_doc(
-			{
-				"doctype": "Quotation",
-				"naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-",
-				"quotation_to": party.doctype,
-				"company": company,
-				"order_type": "Shopping Cart",
-				"status": "Draft",
-				"docstatus": 0,
-				"__islocal": 1,
-				"party_name": party.name,
-			}
-		)
-
-		qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
-		qdoc.contact_email = frappe.session.user
-
-		qdoc.flags.ignore_permissions = True
-		qdoc.run_method("set_missing_values")
-		apply_cart_settings(party, qdoc)
-
-	return qdoc
-
-
-def update_party(fullname, company_name=None, mobile_no=None, phone=None):
-	party = get_party()
-
-	party.customer_name = company_name or fullname
-	party.customer_type = "Company" if company_name else "Individual"
-
-	contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
-	contact = frappe.get_doc("Contact", contact_name)
-	contact.first_name = fullname
-	contact.last_name = None
-	contact.customer_name = party.customer_name
-	contact.mobile_no = mobile_no
-	contact.phone = phone
-	contact.flags.ignore_permissions = True
-	contact.save()
-
-	party_doc = frappe.get_doc(party.as_dict())
-	party_doc.flags.ignore_permissions = True
-	party_doc.save()
-
-	qdoc = _get_cart_quotation(party)
-	if not qdoc.get("__islocal"):
-		qdoc.customer_name = company_name or fullname
-		qdoc.run_method("set_missing_lead_customer_details")
-		qdoc.flags.ignore_permissions = True
-		qdoc.save()
-
-
-def apply_cart_settings(party=None, quotation=None):
-	if not party:
-		party = get_party()
-	if not quotation:
-		quotation = _get_cart_quotation(party)
-
-	cart_settings = frappe.get_doc("E Commerce Settings")
-
-	set_price_list_and_rate(quotation, cart_settings)
-
-	quotation.run_method("calculate_taxes_and_totals")
-
-	set_taxes(quotation, cart_settings)
-
-	_apply_shipping_rule(party, quotation, cart_settings)
-
-
-def set_price_list_and_rate(quotation, cart_settings):
-	"""set price list based on billing territory"""
-
-	_set_price_list(cart_settings, quotation)
-
-	# reset values
-	quotation.price_list_currency = (
-		quotation.currency
-	) = quotation.plc_conversion_rate = quotation.conversion_rate = None
-	for item in quotation.get("items"):
-		item.price_list_rate = item.discount_percentage = item.rate = item.amount = None
-
-	# refetch values
-	quotation.run_method("set_price_list_and_item_details")
-
-	if hasattr(frappe.local, "cookie_manager"):
-		# set it in cookies for using in product page
-		frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
-
-
-def _set_price_list(cart_settings, quotation=None):
-	"""Set price list based on customer or shopping cart default"""
-	from erpnext.accounts.party import get_default_price_list
-
-	party_name = quotation.get("party_name") if quotation else get_party().get("name")
-	selling_price_list = None
-
-	# check if default customer price list exists
-	if party_name and frappe.db.exists("Customer", party_name):
-		selling_price_list = get_default_price_list(frappe.get_doc("Customer", party_name))
-
-	# check default price list in shopping cart
-	if not selling_price_list:
-		selling_price_list = cart_settings.price_list
-
-	if quotation:
-		quotation.selling_price_list = selling_price_list
-
-	return selling_price_list
-
-
-def set_taxes(quotation, cart_settings):
-	"""set taxes based on billing territory"""
-	from erpnext.accounts.party import set_taxes
-
-	customer_group = frappe.db.get_value("Customer", quotation.party_name, "customer_group")
-
-	quotation.taxes_and_charges = set_taxes(
-		quotation.party_name,
-		"Customer",
-		quotation.transaction_date,
-		quotation.company,
-		customer_group=customer_group,
-		supplier_group=None,
-		tax_category=quotation.tax_category,
-		billing_address=quotation.customer_address,
-		shipping_address=quotation.shipping_address_name,
-		use_for_shopping_cart=1,
-	)
-	#
-	# 	# clear table
-	quotation.set("taxes", [])
-	#
-	# 	# append taxes
-	quotation.append_taxes_from_master()
-
-
-def get_party(user=None):
-	if not user:
-		user = frappe.session.user
-
-	contact_name = get_contact_name(user)
-	party = None
-
-	if contact_name:
-		contact = frappe.get_doc("Contact", contact_name)
-		if contact.links:
-			party_doctype = contact.links[0].link_doctype
-			party = contact.links[0].link_name
-
-	cart_settings = frappe.get_doc("E Commerce Settings")
-
-	debtors_account = ""
-
-	if cart_settings.enable_checkout:
-		debtors_account = get_debtors_account(cart_settings)
-
-	if party:
-		return frappe.get_doc(party_doctype, party)
-
-	else:
-		if not cart_settings.enabled:
-			frappe.local.flags.redirect_location = "/contact"
-			raise frappe.Redirect
-		customer = frappe.new_doc("Customer")
-		fullname = get_fullname(user)
-		customer.update(
-			{
-				"customer_name": fullname,
-				"customer_type": "Individual",
-				"customer_group": get_shopping_cart_settings().default_customer_group,
-				"territory": get_root_of("Territory"),
-			}
-		)
-
-		customer.append("portal_users", {"user": user})
-
-		if debtors_account:
-			customer.update({"accounts": [{"company": cart_settings.company, "account": debtors_account}]})
-
-		customer.flags.ignore_mandatory = True
-		customer.insert(ignore_permissions=True)
-
-		contact = frappe.new_doc("Contact")
-		contact.update({"first_name": fullname, "email_ids": [{"email_id": user, "is_primary": 1}]})
-		contact.append("links", dict(link_doctype="Customer", link_name=customer.name))
-		contact.flags.ignore_mandatory = True
-		contact.insert(ignore_permissions=True)
-
-		return customer
-
-
-def get_debtors_account(cart_settings):
-	if not cart_settings.payment_gateway_account:
-		frappe.throw(_("Payment Gateway Account not set"), _("Mandatory"))
-
-	payment_gateway_account_currency = frappe.get_doc(
-		"Payment Gateway Account", cart_settings.payment_gateway_account
-	).currency
-
-	account_name = _("Debtors ({0})").format(payment_gateway_account_currency)
-
-	debtors_account_name = get_account_name(
-		"Receivable",
-		"Asset",
-		is_group=0,
-		account_currency=payment_gateway_account_currency,
-		company=cart_settings.company,
-	)
-
-	if not debtors_account_name:
-		debtors_account = frappe.get_doc(
-			{
-				"doctype": "Account",
-				"account_type": "Receivable",
-				"root_type": "Asset",
-				"is_group": 0,
-				"parent_account": get_account_name(
-					root_type="Asset", is_group=1, company=cart_settings.company
-				),
-				"account_name": account_name,
-				"currency": payment_gateway_account_currency,
-			}
-		).insert(ignore_permissions=True)
-
-		return debtors_account.name
-
-	else:
-		return debtors_account_name
-
-
-def get_address_docs(
-	doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None
-):
-	if not party:
-		party = get_party()
-
-	if not party:
-		return []
-
-	address_names = frappe.db.get_all(
-		"Dynamic Link",
-		fields=("parent"),
-		filters=dict(parenttype="Address", link_doctype=party.doctype, link_name=party.name),
-	)
-
-	out = []
-
-	for a in address_names:
-		address = frappe.get_doc("Address", a.parent)
-		address.display = get_address_display(address.as_dict())
-		out.append(address)
-
-	return out
-
-
-@frappe.whitelist()
-def apply_shipping_rule(shipping_rule):
-	quotation = _get_cart_quotation()
-
-	quotation.shipping_rule = shipping_rule
-
-	apply_cart_settings(quotation=quotation)
-
-	quotation.flags.ignore_permissions = True
-	quotation.save()
-
-	return get_cart_quotation(quotation)
-
-
-def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
-	if not quotation.shipping_rule:
-		shipping_rules = get_shipping_rules(quotation, cart_settings)
-
-		if not shipping_rules:
-			return
-
-		elif quotation.shipping_rule not in shipping_rules:
-			quotation.shipping_rule = shipping_rules[0]
-
-	if quotation.shipping_rule:
-		quotation.run_method("apply_shipping_rule")
-		quotation.run_method("calculate_taxes_and_totals")
-
-
-def get_applicable_shipping_rules(party=None, quotation=None):
-	shipping_rules = get_shipping_rules(quotation)
-
-	if shipping_rules:
-		# we need this in sorted order as per the position of the rule in the settings page
-		return [[rule, rule] for rule in shipping_rules]
-
-
-def get_shipping_rules(quotation=None, cart_settings=None):
-	if not quotation:
-		quotation = _get_cart_quotation()
-
-	shipping_rules = []
-	if quotation.shipping_address_name:
-		country = frappe.db.get_value("Address", quotation.shipping_address_name, "country")
-		if country:
-			sr_country = frappe.qb.DocType("Shipping Rule Country")
-			sr = frappe.qb.DocType("Shipping Rule")
-			query = (
-				frappe.qb.from_(sr_country)
-				.join(sr)
-				.on(sr.name == sr_country.parent)
-				.select(sr.name)
-				.distinct()
-				.where((sr_country.country == country) & (sr.disabled != 1))
-			)
-			result = query.run(as_list=True)
-			shipping_rules = [x[0] for x in result]
-
-	return shipping_rules
-
-
-def get_address_territory(address_name):
-	"""Tries to match city, state and country of address to existing territory"""
-	territory = None
-
-	if address_name:
-		address_fields = frappe.db.get_value("Address", address_name, ["city", "state", "country"])
-		for value in address_fields:
-			territory = frappe.db.get_value("Territory", value)
-			if territory:
-				break
-
-	return territory
-
-
-def show_terms(doc):
-	return doc.tc_name
-
-
-@frappe.whitelist(allow_guest=True)
-def apply_coupon_code(applied_code, applied_referral_sales_partner):
-	quotation = True
-
-	if not applied_code:
-		frappe.throw(_("Please enter a coupon code"))
-
-	coupon_list = frappe.get_all("Coupon Code", filters={"coupon_code": applied_code})
-	if not coupon_list:
-		frappe.throw(_("Please enter a valid coupon code"))
-
-	coupon_name = coupon_list[0].name
-
-	from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code
-
-	validate_coupon_code(coupon_name)
-	quotation = _get_cart_quotation()
-	quotation.coupon_code = coupon_name
-	quotation.flags.ignore_permissions = True
-	quotation.save()
-
-	if applied_referral_sales_partner:
-		sales_partner_list = frappe.get_all(
-			"Sales Partner", filters={"referral_code": applied_referral_sales_partner}
-		)
-		if sales_partner_list:
-			sales_partner_name = sales_partner_list[0].name
-			quotation.referral_sales_partner = sales_partner_name
-			quotation.flags.ignore_permissions = True
-			quotation.save()
-
-	return quotation
diff --git a/erpnext/e_commerce/shopping_cart/product_info.py b/erpnext/e_commerce/shopping_cart/product_info.py
deleted file mode 100644
index 0248ca7..0000000
--- a/erpnext/e_commerce/shopping_cart/product_info.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-	show_quantity_in_website,
-)
-from erpnext.e_commerce.shopping_cart.cart import _get_cart_quotation, _set_price_list
-from erpnext.utilities.product import (
-	get_non_stock_item_status,
-	get_price,
-	get_web_item_qty_in_stock,
-)
-
-
-@frappe.whitelist(allow_guest=True)
-def get_product_info_for_website(item_code, skip_quotation_creation=False):
-	"""get product price / stock info for website"""
-
-	cart_settings = get_shopping_cart_settings()
-	if not cart_settings.enabled:
-		# return settings even if cart is disabled
-		return frappe._dict({"product_info": {}, "cart_settings": cart_settings})
-
-	cart_quotation = frappe._dict()
-	if not skip_quotation_creation:
-		cart_quotation = _get_cart_quotation()
-
-	selling_price_list = (
-		cart_quotation.get("selling_price_list")
-		if cart_quotation
-		else _set_price_list(cart_settings, None)
-	)
-
-	price = {}
-	if cart_settings.show_price:
-		is_guest = frappe.session.user == "Guest"
-		# Show Price if logged in.
-		# If not logged in, check if price is hidden for guest.
-		if not is_guest or not cart_settings.hide_price_for_guest:
-			price = get_price(
-				item_code, selling_price_list, cart_settings.default_customer_group, cart_settings.company
-			)
-
-	stock_status = None
-
-	if cart_settings.show_stock_availability:
-		on_backorder = frappe.get_cached_value("Website Item", {"item_code": item_code}, "on_backorder")
-		if on_backorder:
-			stock_status = frappe._dict({"on_backorder": True})
-		else:
-			stock_status = get_web_item_qty_in_stock(item_code, "website_warehouse")
-
-	product_info = {
-		"price": price,
-		"qty": 0,
-		"uom": frappe.db.get_value("Item", item_code, "stock_uom"),
-		"sales_uom": frappe.db.get_value("Item", item_code, "sales_uom"),
-	}
-
-	if stock_status:
-		if stock_status.on_backorder:
-			product_info["on_backorder"] = True
-		else:
-			product_info["stock_qty"] = stock_status.stock_qty
-			product_info["in_stock"] = (
-				stock_status.in_stock
-				if stock_status.is_stock_item
-				else get_non_stock_item_status(item_code, "website_warehouse")
-			)
-			product_info["show_stock_qty"] = show_quantity_in_website()
-
-	if product_info["price"]:
-		if frappe.session.user != "Guest":
-			item = cart_quotation.get({"item_code": item_code}) if cart_quotation else None
-			if item:
-				product_info["qty"] = item[0].qty
-
-	return frappe._dict({"product_info": product_info, "cart_settings": cart_settings})
-
-
-def set_product_info_for_website(item):
-	"""set product price uom for website"""
-	product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get(
-		"product_info"
-	)
-
-	if product_info:
-		item.update(product_info)
-		item["stock_uom"] = product_info.get("uom")
-		item["sales_uom"] = product_info.get("sales_uom")
-		if product_info.get("price"):
-			item["price_stock_uom"] = product_info.get("price").get("formatted_price")
-			item["price_sales_uom"] = product_info.get("price").get("formatted_price_sales_uom")
-		else:
-			item["price_stock_uom"] = ""
-			item["price_sales_uom"] = ""
diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
deleted file mode 100644
index 8210f97..0000000
--- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py
+++ /dev/null
@@ -1,398 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import unittest
-
-import frappe
-from frappe.tests.utils import change_settings
-from frappe.utils import add_months, cint, nowdate
-
-from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-from erpnext.e_commerce.shopping_cart.cart import (
-	_get_cart_quotation,
-	get_cart_quotation,
-	get_party,
-	request_for_quotation,
-	update_cart,
-)
-
-
-class TestShoppingCart(unittest.TestCase):
-	"""
-	Note:
-	Shopping Cart == Quotation
-	"""
-
-	def setUp(self):
-		frappe.set_user("Administrator")
-		self.enable_shopping_cart()
-		if not frappe.db.exists("Website Item", {"item_code": "_Test Item"}):
-			make_website_item(frappe.get_cached_doc("Item", "_Test Item"))
-
-		if not frappe.db.exists("Website Item", {"item_code": "_Test Item 2"}):
-			make_website_item(frappe.get_cached_doc("Item", "_Test Item 2"))
-
-	def tearDown(self):
-		frappe.db.rollback()
-		frappe.set_user("Administrator")
-		self.disable_shopping_cart()
-
-	@classmethod
-	def tearDownClass(cls):
-		frappe.db.sql("delete from `tabTax Rule`")
-
-	def test_get_cart_new_user(self):
-		self.login_as_customer(
-			"test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer"
-		)
-		create_address_and_contact(
-			address_title="_Test Address for Customer 2",
-			first_name="_Test Contact for Customer 2",
-			email="test_contact_two_customer@example.com",
-			customer="_Test Customer 2",
-		)
-		# test if lead is created and quotation with new lead is fetched
-		customer = frappe.get_doc("Customer", "_Test Customer 2")
-		quotation = _get_cart_quotation(party=customer)
-		self.assertEqual(quotation.quotation_to, "Customer")
-		self.assertEqual(
-			quotation.contact_person,
-			frappe.db.get_value("Contact", dict(email_id="test_contact_two_customer@example.com")),
-		)
-		self.assertEqual(quotation.contact_email, frappe.session.user)
-
-		return quotation
-
-	def test_get_cart_customer(self, customer="_Test Customer 2"):
-		def validate_quotation(customer_name):
-			# test if quotation with customer is fetched
-			party = frappe.get_doc("Customer", customer_name)
-			quotation = _get_cart_quotation(party=party)
-			self.assertEqual(quotation.quotation_to, "Customer")
-			self.assertEqual(quotation.party_name, customer_name)
-			self.assertEqual(quotation.contact_email, frappe.session.user)
-			return quotation
-
-		quotation = validate_quotation(customer)
-		return quotation
-
-	def test_add_to_cart(self):
-		self.login_as_customer(
-			"test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer"
-		)
-		create_address_and_contact(
-			address_title="_Test Address for Customer 2",
-			first_name="_Test Contact for Customer 2",
-			email="test_contact_two_customer@example.com",
-			customer="_Test Customer 2",
-		)
-		# clear existing quotations
-		self.clear_existing_quotations()
-
-		# add first item
-		update_cart("_Test Item", 1)
-
-		quotation = self.test_get_cart_customer("_Test Customer 2")
-
-		self.assertEqual(quotation.get("items")[0].item_code, "_Test Item")
-		self.assertEqual(quotation.get("items")[0].qty, 1)
-		self.assertEqual(quotation.get("items")[0].amount, 10)
-
-		# add second item
-		update_cart("_Test Item 2", 1)
-		quotation = self.test_get_cart_customer("_Test Customer 2")
-		self.assertEqual(quotation.get("items")[1].item_code, "_Test Item 2")
-		self.assertEqual(quotation.get("items")[1].qty, 1)
-		self.assertEqual(quotation.get("items")[1].amount, 20)
-
-		self.assertEqual(len(quotation.get("items")), 2)
-
-	def test_update_cart(self):
-		# first, add to cart
-		self.test_add_to_cart()
-
-		# update first item
-		update_cart("_Test Item", 5)
-		quotation = self.test_get_cart_customer("_Test Customer 2")
-		self.assertEqual(quotation.get("items")[0].item_code, "_Test Item")
-		self.assertEqual(quotation.get("items")[0].qty, 5)
-		self.assertEqual(quotation.get("items")[0].amount, 50)
-		self.assertEqual(quotation.net_total, 70)
-		self.assertEqual(len(quotation.get("items")), 2)
-
-	def test_remove_from_cart(self):
-		# first, add to cart
-		self.test_add_to_cart()
-
-		# remove first item
-		update_cart("_Test Item", 0)
-		quotation = self.test_get_cart_customer("_Test Customer 2")
-
-		self.assertEqual(quotation.get("items")[0].item_code, "_Test Item 2")
-		self.assertEqual(quotation.get("items")[0].qty, 1)
-		self.assertEqual(quotation.get("items")[0].amount, 20)
-		self.assertEqual(quotation.net_total, 20)
-		self.assertEqual(len(quotation.get("items")), 1)
-
-	@unittest.skip("Flaky in CI")
-	def test_tax_rule(self):
-		self.create_tax_rule()
-
-		self.login_as_customer(
-			"test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer"
-		)
-		create_address_and_contact(
-			address_title="_Test Address for Customer 2",
-			first_name="_Test Contact for Customer 2",
-			email="test_contact_two_customer@example.com",
-			customer="_Test Customer 2",
-		)
-
-		quotation = self.create_quotation()
-
-		from erpnext.accounts.party import set_taxes
-
-		tax_rule_master = set_taxes(
-			quotation.party_name,
-			"Customer",
-			None,
-			quotation.company,
-			customer_group=None,
-			supplier_group=None,
-			tax_category=quotation.tax_category,
-			billing_address=quotation.customer_address,
-			shipping_address=quotation.shipping_address_name,
-			use_for_shopping_cart=1,
-		)
-
-		self.assertEqual(quotation.taxes_and_charges, tax_rule_master)
-		self.assertEqual(quotation.total_taxes_and_charges, 1000.0)
-
-		self.remove_test_quotation(quotation)
-
-	@change_settings(
-		"E Commerce Settings",
-		{
-			"company": "_Test Company",
-			"enabled": 1,
-			"default_customer_group": "_Test Customer Group",
-			"price_list": "_Test Price List India",
-			"show_price": 1,
-		},
-	)
-	def test_add_item_variant_without_web_item_to_cart(self):
-		"Test adding Variants having no Website Items in cart via Template Web Item."
-		from erpnext.controllers.item_variant import create_variant
-		from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-		from erpnext.stock.doctype.item.test_item import make_item
-
-		template_item = make_item(
-			"Test-Tshirt-Temp",
-			{
-				"has_variant": 1,
-				"variant_based_on": "Item Attribute",
-				"attributes": [{"attribute": "Test Size"}, {"attribute": "Test Colour"}],
-			},
-		)
-		variant = create_variant("Test-Tshirt-Temp", {"Test Size": "Small", "Test Colour": "Red"})
-		variant.save()
-		make_website_item(template_item)  # publish template not variant
-
-		update_cart("Test-Tshirt-Temp-S-R", 1)
-
-		cart = get_cart_quotation()  # test if cart page gets data without errors
-		doc = cart.get("doc")
-
-		self.assertEqual(doc.get("items")[0].item_name, "Test-Tshirt-Temp-S-R")
-
-		# test if items are rendered without error
-		frappe.render_template("templates/includes/cart/cart_items.html", cart)
-
-	@change_settings("E Commerce Settings", {"save_quotations_as_draft": 1})
-	def test_cart_without_checkout_and_draft_quotation(self):
-		"Test impact of 'save_quotations_as_draft' checkbox."
-		frappe.local.shopping_cart_settings = None
-
-		# add item to cart
-		update_cart("_Test Item", 1)
-		quote_name = request_for_quotation()  # Request for Quote
-		quote_doctstatus = cint(frappe.db.get_value("Quotation", quote_name, "docstatus"))
-
-		self.assertEqual(quote_doctstatus, 0)
-
-		frappe.db.set_single_value("E Commerce Settings", "save_quotations_as_draft", 0)
-		frappe.local.shopping_cart_settings = None
-		update_cart("_Test Item", 1)
-		quote_name = request_for_quotation()  # Request for Quote
-		quote_doctstatus = cint(frappe.db.get_value("Quotation", quote_name, "docstatus"))
-
-		self.assertEqual(quote_doctstatus, 1)
-
-	def create_tax_rule(self):
-		tax_rule = frappe.get_test_records("Tax Rule")[0]
-		try:
-			frappe.get_doc(tax_rule).insert(ignore_if_duplicate=True)
-		except (frappe.DuplicateEntryError, ConflictingTaxRule):
-			pass
-
-	def create_quotation(self):
-		quotation = frappe.new_doc("Quotation")
-
-		values = {
-			"doctype": "Quotation",
-			"quotation_to": "Customer",
-			"order_type": "Shopping Cart",
-			"party_name": get_party(frappe.session.user).name,
-			"docstatus": 0,
-			"contact_email": frappe.session.user,
-			"selling_price_list": "_Test Price List Rest of the World",
-			"currency": "USD",
-			"taxes_and_charges": "_Test Tax 1 - _TC",
-			"conversion_rate": 1,
-			"transaction_date": nowdate(),
-			"valid_till": add_months(nowdate(), 1),
-			"items": [{"item_code": "_Test Item", "qty": 1}],
-			"taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1 - _TC").taxes,
-			"company": "_Test Company",
-		}
-
-		quotation.update(values)
-
-		quotation.insert(ignore_permissions=True)
-
-		return quotation
-
-	def remove_test_quotation(self, quotation):
-		frappe.set_user("Administrator")
-		quotation.delete()
-
-	# helper functions
-	def enable_shopping_cart(self):
-		settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings")
-
-		settings.update(
-			{
-				"enabled": 1,
-				"company": "_Test Company",
-				"default_customer_group": "_Test Customer Group",
-				"quotation_series": "_T-Quotation-",
-				"price_list": "_Test Price List India",
-			}
-		)
-
-		# insert item price
-		if not frappe.db.get_value(
-			"Item Price", {"price_list": "_Test Price List India", "item_code": "_Test Item"}
-		):
-			frappe.get_doc(
-				{
-					"doctype": "Item Price",
-					"price_list": "_Test Price List India",
-					"item_code": "_Test Item",
-					"price_list_rate": 10,
-				}
-			).insert()
-			frappe.get_doc(
-				{
-					"doctype": "Item Price",
-					"price_list": "_Test Price List India",
-					"item_code": "_Test Item 2",
-					"price_list_rate": 20,
-				}
-			).insert()
-
-		settings.save()
-		frappe.local.shopping_cart_settings = None
-
-	def disable_shopping_cart(self):
-		settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings")
-		settings.enabled = 0
-		settings.save()
-		frappe.local.shopping_cart_settings = None
-
-	def login_as_new_user(self):
-		self.create_user_if_not_exists("test_cart_user@example.com")
-		frappe.set_user("test_cart_user@example.com")
-
-	def login_as_customer(
-		self, email="test_contact_customer@example.com", name="_Test Contact For _Test Customer"
-	):
-		self.create_user_if_not_exists(email, name)
-		frappe.set_user(email)
-
-	def clear_existing_quotations(self):
-		quotations = frappe.get_all(
-			"Quotation",
-			filters={"party_name": get_party().name, "order_type": "Shopping Cart", "docstatus": 0},
-			order_by="modified desc",
-			pluck="name",
-		)
-
-		for quotation in quotations:
-			frappe.delete_doc("Quotation", quotation, ignore_permissions=True, force=True)
-
-	def create_user_if_not_exists(self, email, first_name=None):
-		if frappe.db.exists("User", email):
-			return
-
-		user = frappe.get_doc(
-			{
-				"doctype": "User",
-				"user_type": "Website User",
-				"email": email,
-				"send_welcome_email": 0,
-				"first_name": first_name or email.split("@")[0],
-			}
-		).insert(ignore_permissions=True)
-
-		user.add_roles("Customer")
-
-
-def create_address_and_contact(**kwargs):
-	if not frappe.db.get_value("Address", {"address_title": kwargs.get("address_title")}):
-		frappe.get_doc(
-			{
-				"doctype": "Address",
-				"address_title": kwargs.get("address_title"),
-				"address_type": kwargs.get("address_type") or "Office",
-				"address_line1": kwargs.get("address_line1") or "Station Road",
-				"city": kwargs.get("city") or "_Test City",
-				"state": kwargs.get("state") or "Test State",
-				"country": kwargs.get("country") or "India",
-				"links": [
-					{"link_doctype": "Customer", "link_name": kwargs.get("customer") or "_Test Customer"}
-				],
-			}
-		).insert()
-
-	if not frappe.db.get_value("Contact", {"first_name": kwargs.get("first_name")}):
-		contact = frappe.get_doc(
-			{
-				"doctype": "Contact",
-				"first_name": kwargs.get("first_name"),
-				"links": [
-					{"link_doctype": "Customer", "link_name": kwargs.get("customer") or "_Test Customer"}
-				],
-			}
-		)
-		contact.add_email(kwargs.get("email") or "test_contact_customer@example.com", is_primary=True)
-		contact.add_phone(kwargs.get("phone") or "+91 0000000000", is_primary_phone=True)
-		contact.insert()
-
-
-test_dependencies = [
-	"Sales Taxes and Charges Template",
-	"Price List",
-	"Item Price",
-	"Shipping Rule",
-	"Currency Exchange",
-	"Customer Group",
-	"Lead",
-	"Customer",
-	"Contact",
-	"Address",
-	"Item",
-	"Tax Rule",
-]
diff --git a/erpnext/e_commerce/shopping_cart/utils.py b/erpnext/e_commerce/shopping_cart/utils.py
deleted file mode 100644
index 3d48c28..0000000
--- a/erpnext/e_commerce/shopping_cart/utils.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import is_cart_enabled
-
-
-def show_cart_count():
-	if (
-		is_cart_enabled()
-		and frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User"
-	):
-		return True
-
-	return False
-
-
-def set_cart_count(login_manager):
-	# since this is run only on hooks login event
-	# make sure user is already a customer
-	# before trying to set cart count
-	user_is_customer = is_customer()
-	if not user_is_customer:
-		return
-
-	if show_cart_count():
-		from erpnext.e_commerce.shopping_cart.cart import set_cart_count
-
-		# set_cart_count will try to fetch existing cart quotation
-		# or create one if non existent (and create a customer too)
-		# cart count is calculated from this quotation's items
-		set_cart_count()
-
-
-def clear_cart_count(login_manager):
-	if show_cart_count():
-		frappe.local.cookie_manager.delete_cookie("cart_count")
-
-
-def update_website_context(context):
-	cart_enabled = is_cart_enabled()
-	context["shopping_cart_enabled"] = cart_enabled
-
-
-def is_customer():
-	if frappe.session.user and frappe.session.user != "Guest":
-		contact_name = frappe.get_value("Contact", {"email_id": frappe.session.user})
-		if contact_name:
-			contact = frappe.get_doc("Contact", contact_name)
-			for link in contact.links:
-				if link.link_doctype == "Customer":
-					return True
-
-		return False
diff --git a/erpnext/e_commerce/variant_selector/__init__.py b/erpnext/e_commerce/variant_selector/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/variant_selector/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/variant_selector/item_variants_cache.py b/erpnext/e_commerce/variant_selector/item_variants_cache.py
deleted file mode 100644
index f8439d5..0000000
--- a/erpnext/e_commerce/variant_selector/item_variants_cache.py
+++ /dev/null
@@ -1,130 +0,0 @@
-import frappe
-
-
-class ItemVariantsCacheManager:
-	def __init__(self, item_code):
-		self.item_code = item_code
-
-	def get_item_variants_data(self):
-		val = frappe.cache().hget("item_variants_data", self.item_code)
-
-		if not val:
-			self.build_cache()
-
-		return frappe.cache().hget("item_variants_data", self.item_code)
-
-	def get_attribute_value_item_map(self):
-		val = frappe.cache().hget("attribute_value_item_map", self.item_code)
-
-		if not val:
-			self.build_cache()
-
-		return frappe.cache().hget("attribute_value_item_map", self.item_code)
-
-	def get_item_attribute_value_map(self):
-		val = frappe.cache().hget("item_attribute_value_map", self.item_code)
-
-		if not val:
-			self.build_cache()
-
-		return frappe.cache().hget("item_attribute_value_map", self.item_code)
-
-	def get_optional_attributes(self):
-		val = frappe.cache().hget("optional_attributes", self.item_code)
-
-		if not val:
-			self.build_cache()
-
-		return frappe.cache().hget("optional_attributes", self.item_code)
-
-	def get_ordered_attribute_values(self):
-		val = frappe.cache().get_value("ordered_attribute_values_map")
-		if val:
-			return val
-
-		all_attribute_values = frappe.get_all(
-			"Item Attribute Value", ["attribute_value", "idx", "parent"], order_by="idx asc"
-		)
-
-		ordered_attribute_values_map = frappe._dict({})
-		for d in all_attribute_values:
-			ordered_attribute_values_map.setdefault(d.parent, []).append(d.attribute_value)
-
-		frappe.cache().set_value("ordered_attribute_values_map", ordered_attribute_values_map)
-		return ordered_attribute_values_map
-
-	def build_cache(self):
-		parent_item_code = self.item_code
-
-		attributes = [
-			a.attribute
-			for a in frappe.get_all(
-				"Item Variant Attribute", {"parent": parent_item_code}, ["attribute"], order_by="idx asc"
-			)
-		]
-
-		# Get Variants and tehir Attributes that are not disabled
-		iva = frappe.qb.DocType("Item Variant Attribute")
-		item = frappe.qb.DocType("Item")
-		query = (
-			frappe.qb.from_(iva)
-			.join(item)
-			.on(item.name == iva.parent)
-			.select(iva.parent, iva.attribute, iva.attribute_value)
-			.where((iva.variant_of == parent_item_code) & (item.disabled == 0))
-			.orderby(iva.name)
-		)
-		item_variants_data = query.run()
-
-		attribute_value_item_map = frappe._dict()
-		item_attribute_value_map = frappe._dict()
-
-		for row in item_variants_data:
-			item_code, attribute, attribute_value = row
-			# (attr, value) => [item1, item2]
-			attribute_value_item_map.setdefault((attribute, attribute_value), []).append(item_code)
-			# item => {attr1: value1, attr2: value2}
-			item_attribute_value_map.setdefault(item_code, {})[attribute] = attribute_value
-
-		optional_attributes = set()
-		for item_code, attr_dict in item_attribute_value_map.items():
-			for attribute in attributes:
-				if attribute not in attr_dict:
-					optional_attributes.add(attribute)
-
-		frappe.cache().hset("attribute_value_item_map", parent_item_code, attribute_value_item_map)
-		frappe.cache().hset("item_attribute_value_map", parent_item_code, item_attribute_value_map)
-		frappe.cache().hset("item_variants_data", parent_item_code, item_variants_data)
-		frappe.cache().hset("optional_attributes", parent_item_code, optional_attributes)
-
-	def clear_cache(self):
-		keys = [
-			"attribute_value_item_map",
-			"item_attribute_value_map",
-			"item_variants_data",
-			"optional_attributes",
-		]
-
-		for key in keys:
-			frappe.cache().hdel(key, self.item_code)
-
-	def rebuild_cache(self):
-		self.clear_cache()
-		enqueue_build_cache(self.item_code)
-
-
-def build_cache(item_code):
-	frappe.cache().hset("item_cache_build_in_progress", item_code, 1)
-	i = ItemVariantsCacheManager(item_code)
-	i.build_cache()
-	frappe.cache().hset("item_cache_build_in_progress", item_code, 0)
-
-
-def enqueue_build_cache(item_code):
-	if frappe.cache().hget("item_cache_build_in_progress", item_code):
-		return
-	frappe.enqueue(
-		"erpnext.e_commerce.variant_selector.item_variants_cache.build_cache",
-		item_code=item_code,
-		queue="long",
-	)
diff --git a/erpnext/e_commerce/variant_selector/test_variant_selector.py b/erpnext/e_commerce/variant_selector/test_variant_selector.py
deleted file mode 100644
index 8eb497c..0000000
--- a/erpnext/e_commerce/variant_selector/test_variant_selector.py
+++ /dev/null
@@ -1,125 +0,0 @@
-import frappe
-from frappe.tests.utils import FrappeTestCase
-
-from erpnext.controllers.item_variant import create_variant
-from erpnext.e_commerce.doctype.e_commerce_settings.test_e_commerce_settings import (
-	setup_e_commerce_settings,
-)
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-from erpnext.e_commerce.variant_selector.utils import get_next_attribute_and_values
-from erpnext.stock.doctype.item.test_item import make_item
-
-test_dependencies = ["Item"]
-
-
-class TestVariantSelector(FrappeTestCase):
-	@classmethod
-	def setUpClass(cls):
-		super().setUpClass()
-		template_item = make_item(
-			"Test-Tshirt-Temp",
-			{
-				"has_variant": 1,
-				"variant_based_on": "Item Attribute",
-				"attributes": [{"attribute": "Test Size"}, {"attribute": "Test Colour"}],
-			},
-		)
-
-		# create L-R, L-G, M-R, M-G and S-R
-		for size in (
-			"Large",
-			"Medium",
-		):
-			for colour in (
-				"Red",
-				"Green",
-			):
-				variant = create_variant("Test-Tshirt-Temp", {"Test Size": size, "Test Colour": colour})
-				variant.save()
-
-		variant = create_variant("Test-Tshirt-Temp", {"Test Size": "Small", "Test Colour": "Red"})
-		variant.save()
-
-		make_website_item(template_item)  # publish template not variants
-
-	def test_item_attributes(self):
-		"""
-		Test if the right attributes are fetched in the popup.
-		(Attributes must only come from active items)
-
-		Attribute selection must not be linked to Website Items.
-		"""
-		from erpnext.e_commerce.variant_selector.utils import get_attributes_and_values
-
-		attr_data = get_attributes_and_values("Test-Tshirt-Temp")
-
-		self.assertEqual(attr_data[0]["attribute"], "Test Size")
-		self.assertEqual(attr_data[1]["attribute"], "Test Colour")
-		self.assertEqual(len(attr_data[0]["values"]), 3)  # ['Small', 'Medium', 'Large']
-		self.assertEqual(len(attr_data[1]["values"]), 2)  # ['Red', 'Green']
-
-		# disable small red tshirt, now there are no small tshirts.
-		# but there are some red tshirts
-		small_variant = frappe.get_doc("Item", "Test-Tshirt-Temp-S-R")
-		small_variant.disabled = 1
-		small_variant.save()  # trigger cache rebuild
-
-		attr_data = get_attributes_and_values("Test-Tshirt-Temp")
-
-		# Only L and M attribute values must be fetched since S is disabled
-		self.assertEqual(len(attr_data[0]["values"]), 2)  # ['Medium', 'Large']
-
-		# teardown
-		small_variant.disabled = 0
-		small_variant.save()
-
-	def test_next_item_variant_values(self):
-		"""
-		Test if on selecting an attribute value, the next possible values
-		are filtered accordingly.
-		Values that dont apply should not be fetched.
-		E.g.
-		There is a ** Small-Red ** Tshirt. No other colour in this size.
-		On selecting ** Small **, only ** Red ** should be selectable next.
-		"""
-		next_values = get_next_attribute_and_values(
-			"Test-Tshirt-Temp", selected_attributes={"Test Size": "Small"}
-		)
-		next_colours = next_values["valid_options_for_attributes"]["Test Colour"]
-		filtered_items = next_values["filtered_items"]
-
-		self.assertEqual(len(next_colours), 1)
-		self.assertEqual(next_colours.pop(), "Red")
-		self.assertEqual(len(filtered_items), 1)
-		self.assertEqual(filtered_items.pop(), "Test-Tshirt-Temp-S-R")
-
-	def test_exact_match_with_price(self):
-		"""
-		Test price fetching and matching of variant without Website Item
-		"""
-		from erpnext.e_commerce.doctype.website_item.test_website_item import make_web_item_price
-
-		frappe.set_user("Administrator")
-		setup_e_commerce_settings(
-			{
-				"company": "_Test Company",
-				"enabled": 1,
-				"default_customer_group": "_Test Customer Group",
-				"price_list": "_Test Price List India",
-				"show_price": 1,
-			}
-		)
-
-		make_web_item_price(item_code="Test-Tshirt-Temp-S-R", price_list_rate=100)
-
-		frappe.local.shopping_cart_settings = None  # clear cached settings values
-		next_values = get_next_attribute_and_values(
-			"Test-Tshirt-Temp", selected_attributes={"Test Size": "Small", "Test Colour": "Red"}
-		)
-		print(">>>>", next_values)
-		price_info = next_values["product_info"]["price"]
-
-		self.assertEqual(next_values["exact_match"][0], "Test-Tshirt-Temp-S-R")
-		self.assertEqual(next_values["exact_match"][0], "Test-Tshirt-Temp-S-R")
-		self.assertEqual(price_info["price_list_rate"], 100.0)
-		self.assertEqual(price_info["formatted_price_sales_uom"], "₹ 100.00")
diff --git a/erpnext/e_commerce/variant_selector/utils.py b/erpnext/e_commerce/variant_selector/utils.py
deleted file mode 100644
index 88356f5..0000000
--- a/erpnext/e_commerce/variant_selector/utils.py
+++ /dev/null
@@ -1,251 +0,0 @@
-import frappe
-from frappe.utils import cint, flt
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.e_commerce.shopping_cart.cart import _set_price_list
-from erpnext.e_commerce.variant_selector.item_variants_cache import ItemVariantsCacheManager
-from erpnext.utilities.product import get_price
-
-
-def get_item_codes_by_attributes(attribute_filters, template_item_code=None):
-	items = []
-
-	for attribute, values in attribute_filters.items():
-		attribute_values = values
-
-		if not isinstance(attribute_values, list):
-			attribute_values = [attribute_values]
-
-		if not attribute_values:
-			continue
-
-		wheres = []
-		query_values = []
-		for attribute_value in attribute_values:
-			wheres.append("( attribute = %s and attribute_value = %s )")
-			query_values += [attribute, attribute_value]
-
-		attribute_query = " or ".join(wheres)
-
-		if template_item_code:
-			variant_of_query = "AND t2.variant_of = %s"
-			query_values.append(template_item_code)
-		else:
-			variant_of_query = ""
-
-		query = """
-			SELECT
-				t1.parent
-			FROM
-				`tabItem Variant Attribute` t1
-			WHERE
-				1 = 1
-				AND (
-					{attribute_query}
-				)
-				AND EXISTS (
-					SELECT
-						1
-					FROM
-						`tabItem` t2
-					WHERE
-						t2.name = t1.parent
-						{variant_of_query}
-				)
-			GROUP BY
-				t1.parent
-			ORDER BY
-				NULL
-		""".format(
-			attribute_query=attribute_query, variant_of_query=variant_of_query
-		)
-
-		item_codes = set([r[0] for r in frappe.db.sql(query, query_values)])  # nosemgrep
-		items.append(item_codes)
-
-	res = list(set.intersection(*items))
-
-	return res
-
-
-@frappe.whitelist(allow_guest=True)
-def get_attributes_and_values(item_code):
-	"""Build a list of attributes and their possible values.
-	This will ignore the values upon selection of which there cannot exist one item.
-	"""
-	item_cache = ItemVariantsCacheManager(item_code)
-	item_variants_data = item_cache.get_item_variants_data()
-
-	attributes = get_item_attributes(item_code)
-	attribute_list = [a.attribute for a in attributes]
-
-	valid_options = {}
-	for item_code, attribute, attribute_value in item_variants_data:
-		if attribute in attribute_list:
-			valid_options.setdefault(attribute, set()).add(attribute_value)
-
-	item_attribute_values = frappe.db.get_all(
-		"Item Attribute Value", ["parent", "attribute_value", "idx"], order_by="parent asc, idx asc"
-	)
-	ordered_attribute_value_map = frappe._dict()
-	for iv in item_attribute_values:
-		ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value)
-
-	# build attribute values in idx order
-	for attr in attributes:
-		valid_attribute_values = valid_options.get(attr.attribute, [])
-		ordered_values = ordered_attribute_value_map.get(attr.attribute, [])
-		attr["values"] = [v for v in ordered_values if v in valid_attribute_values]
-
-	return attributes
-
-
-@frappe.whitelist(allow_guest=True)
-def get_next_attribute_and_values(item_code, selected_attributes):
-	from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
-
-	"""Find the count of Items that match the selected attributes.
-	Also, find the attribute values that are not applicable for further searching.
-	If less than equal to 10 items are found, return item_codes of those items.
-	If one item is matched exactly, return item_code of that item.
-	"""
-	selected_attributes = frappe.parse_json(selected_attributes)
-
-	item_cache = ItemVariantsCacheManager(item_code)
-	item_variants_data = item_cache.get_item_variants_data()
-
-	attributes = get_item_attributes(item_code)
-	attribute_list = [a.attribute for a in attributes]
-	filtered_items = get_items_with_selected_attributes(item_code, selected_attributes)
-
-	next_attribute = None
-
-	for attribute in attribute_list:
-		if attribute not in selected_attributes:
-			next_attribute = attribute
-			break
-
-	valid_options_for_attributes = frappe._dict()
-
-	for a in attribute_list:
-		valid_options_for_attributes[a] = set()
-
-		selected_attribute = selected_attributes.get(a, None)
-		if selected_attribute:
-			# already selected attribute values are valid options
-			valid_options_for_attributes[a].add(selected_attribute)
-
-	for row in item_variants_data:
-		item_code, attribute, attribute_value = row
-		if (
-			item_code in filtered_items
-			and attribute not in selected_attributes
-			and attribute in attribute_list
-		):
-			valid_options_for_attributes[attribute].add(attribute_value)
-
-	optional_attributes = item_cache.get_optional_attributes()
-	exact_match = []
-	# search for exact match if all selected attributes are required attributes
-	if len(selected_attributes.keys()) >= (len(attribute_list) - len(optional_attributes)):
-		item_attribute_value_map = item_cache.get_item_attribute_value_map()
-		for item_code, attr_dict in item_attribute_value_map.items():
-			if item_code in filtered_items and set(attr_dict.keys()) == set(selected_attributes.keys()):
-				exact_match.append(item_code)
-
-	filtered_items_count = len(filtered_items)
-
-	# get product info if exact match
-	# from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website
-	if exact_match:
-		cart_settings = get_shopping_cart_settings()
-		product_info = get_item_variant_price_dict(exact_match[0], cart_settings)
-
-		if product_info:
-			product_info["is_stock_item"] = frappe.get_cached_value("Item", exact_match[0], "is_stock_item")
-			product_info["allow_items_not_in_stock"] = cint(cart_settings.allow_items_not_in_stock)
-	else:
-		product_info = None
-
-	product_id = ""
-	warehouse = ""
-	if exact_match or filtered_items:
-		if exact_match and len(exact_match) == 1:
-			product_id = exact_match[0]
-		elif filtered_items_count == 1:
-			product_id = list(filtered_items)[0]
-
-	if product_id:
-		warehouse = frappe.get_cached_value(
-			"Website Item", {"item_code": product_id}, "website_warehouse"
-		)
-
-	available_qty = 0.0
-	if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1:
-		warehouses = get_child_warehouses(warehouse)
-	else:
-		warehouses = [warehouse] if warehouse else []
-
-	for warehouse in warehouses:
-		available_qty += flt(
-			frappe.db.get_value("Bin", {"item_code": product_id, "warehouse": warehouse}, "actual_qty")
-		)
-
-	return {
-		"next_attribute": next_attribute,
-		"valid_options_for_attributes": valid_options_for_attributes,
-		"filtered_items_count": filtered_items_count,
-		"filtered_items": filtered_items if filtered_items_count < 10 else [],
-		"exact_match": exact_match,
-		"product_info": product_info,
-		"available_qty": available_qty,
-	}
-
-
-def get_items_with_selected_attributes(item_code, selected_attributes):
-	item_cache = ItemVariantsCacheManager(item_code)
-	attribute_value_item_map = item_cache.get_attribute_value_item_map()
-
-	items = []
-	for attribute, value in selected_attributes.items():
-		filtered_items = attribute_value_item_map.get((attribute, value), [])
-		items.append(set(filtered_items))
-
-	return set.intersection(*items)
-
-
-# utilities
-
-
-def get_item_attributes(item_code):
-	attributes = frappe.db.get_all(
-		"Item Variant Attribute",
-		fields=["attribute"],
-		filters={"parenttype": "Item", "parent": item_code},
-		order_by="idx asc",
-	)
-
-	optional_attributes = ItemVariantsCacheManager(item_code).get_optional_attributes()
-
-	for a in attributes:
-		if a.attribute in optional_attributes:
-			a.optional = True
-
-	return attributes
-
-
-def get_item_variant_price_dict(item_code, cart_settings):
-	if cart_settings.enabled and cart_settings.show_price:
-		is_guest = frappe.session.user == "Guest"
-		# Show Price if logged in.
-		# If not logged in, check if price is hidden for guest.
-		if not is_guest or not cart_settings.hide_price_for_guest:
-			price_list = _set_price_list(cart_settings, None)
-			price = get_price(
-				item_code, price_list, cart_settings.default_customer_group, cart_settings.company
-			)
-			return {"price": price}
-
-	return None
diff --git a/erpnext/e_commerce/web_template/__init__.py b/erpnext/e_commerce/web_template/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/hero_slider/__init__.py b/erpnext/e_commerce/web_template/hero_slider/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/hero_slider/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/hero_slider/hero_slider.html b/erpnext/e_commerce/web_template/hero_slider/hero_slider.html
deleted file mode 100644
index fe4fee3..0000000
--- a/erpnext/e_commerce/web_template/hero_slider/hero_slider.html
+++ /dev/null
@@ -1,86 +0,0 @@
-{%- macro slide(image, title, subtitle, action, label, index, align="Left", theme="Dark") -%}
-{%- set align_class = resolve_class({
-	'text-right': align == 'Right',
-	'text-center': align == 'Centre',
-	'text-left': align == 'Left',
-}) -%}
-
-{%- set heading_class = resolve_class({
-	'text-white': theme == 'Dark',
-	'': theme == 'Light',
-}) -%}
-<div class="carousel-item {{ 'active' if index=='1' else ''}}" style="height: 450px;">
-	<img class="d-block h-100 w-100" style="object-fit: cover;" src="{{ image }}" alt="{{ title }}">
-	{%- if title or subtitle -%}
-	<div class="carousel-body container d-flex {{ align_class }}">
-		<div class="carousel-content align-self-center">
-			{%- if title -%}<h1 class="{{ heading_class }}">{{ title }}</h1>{%- endif -%}
-			{%- if subtitle -%}<p class="{{ heading_class }} mt-2">{{ subtitle }}</p>{%- endif -%}
-			{%- if action -%}
-			<a href="{{ action }}" class="btn btn-primary mt-3">
-				{{ label }}
-			</a>
-			{%- endif -%}
-		</div>
-	</div>
-	{%- endif -%}
-</div>
-{%- endmacro -%}
-
-{%- set hero_slider_id = 'id-' + frappe.utils.generate_hash('HeroSlider', 12) -%}
-
-<div id="{{ hero_slider_id }}" class="section-carousel carousel slide" data-ride="carousel">
-	{%- if show_indicators -%}
-	<ol class="carousel-indicators">
-		{%- for index in ['1', '2', '3', '4', '5'] -%}
-		{%- if values['slide_' + index + '_image'] -%}
-			<li data-target="#{{ hero_slider_id }}" data-slide-to="{{ frappe.utils.cint(index) - 1 }}" class="{{ 'active' if index=='1' else ''}}"></li>
-		{%- endif -%}
-		{%- endfor -%}
-	</ol>
-	{%- endif -%}
-	<div class="carousel-inner {{ resolve_class({'rounded-carousel': rounded }) }}">
-		{%- for index in ['1', '2', '3', '4', '5'] -%}
-			{%- set image = values['slide_' + index + '_image'] -%}
-			{%- set title = values['slide_' + index + '_title'] -%}
-			{%- set subtitle = values['slide_' + index + '_subtitle'] -%}
-			{%- set primary_action = values['slide_' + index + '_primary_action'] -%}
-			{%- set primary_action_label = values['slide_' + index + '_primary_action_label'] -%}
-			{%- set align = values['slide_' + index + '_content_align'] -%}
-			{%- set theme = values['slide_' + index + '_theme'] -%}
-
-			{%- if image -%}
-				{{ slide(image, title, subtitle, primary_action, primary_action_label, index, align, theme) }}
-			{%- endif -%}
-
-		{%- endfor -%}
-	</div>
-	{%- if show_controls -%}
-	<a class="carousel-control-prev" href="#{{ hero_slider_id }}" role="button" data-slide="prev">
-		<div class="carousel-control">
-			<svg class="mr-1" width="20" height="20" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
-				<path d="M11.625 3.75L6.375 9L11.625 14.25" stroke="#4C5A67" stroke-linecap="round" stroke-linejoin="round"/>
-			</svg>
-		</div>
-		<span class="sr-only">Previous</span>
-	</a>
-	<a class="carousel-control-next" href="#{{ hero_slider_id }}" role="button" data-slide="next">
-		<div class="carousel-control">
-			<svg class="ml-1" width="20" height="20" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
-				<path d="M6.375 14.25L11.625 9L6.375 3.75" stroke="#4C5A67" stroke-linecap="round" stroke-linejoin="round"/>
-			</svg>
-		</div>
-		<span class="sr-only">Next</span>
-	</a>
-	{%- endif -%}
-</div>
-
-<script>
-	frappe.ready(function () {
-		$('.carousel').carousel({
-			interval: false,
-			pause: "hover",
-			wrap: true
-		})
-	});
-</script>
diff --git a/erpnext/e_commerce/web_template/hero_slider/hero_slider.json b/erpnext/e_commerce/web_template/hero_slider/hero_slider.json
deleted file mode 100644
index 39b2b3e..0000000
--- a/erpnext/e_commerce/web_template/hero_slider/hero_slider.json
+++ /dev/null
@@ -1,288 +0,0 @@
-{
- "__unsaved": 1,
- "creation": "2020-11-17 15:21:51.207221",
- "docstatus": 0,
- "doctype": "Web Template",
- "fields": [
-  {
-   "fieldname": "slider_name",
-   "fieldtype": "Data",
-   "label": "Slider Name",
-   "reqd": 1
-  },
-  {
-   "default": "1",
-   "fieldname": "show_indicators",
-   "fieldtype": "Check",
-   "label": "Show Indicators",
-   "reqd": 0
-  },
-  {
-   "default": "1",
-   "fieldname": "show_controls",
-   "fieldtype": "Check",
-   "label": "Show Controls",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1",
-   "fieldtype": "Section Break",
-   "label": "Slide 1",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_image",
-   "fieldtype": "Attach Image",
-   "label": "Image",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_subtitle",
-   "fieldtype": "Small Text",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_content_align",
-   "fieldtype": "Select",
-   "label": "Content Align",
-   "options": "Left\nCentre\nRight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_1_theme",
-   "fieldtype": "Select",
-   "label": "Slide Theme",
-   "options": "Dark\nLight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2",
-   "fieldtype": "Section Break",
-   "label": "Slide 2",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_image",
-   "fieldtype": "Attach Image",
-   "label": "Image ",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_title",
-   "fieldtype": "Data",
-   "label": "Title ",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_subtitle",
-   "fieldtype": "Small Text",
-   "label": "Subtitle ",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label ",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action ",
-   "reqd": 0
-  },
-  {
-   "default": "Left",
-   "fieldname": "slide_2_content_align",
-   "fieldtype": "Select",
-   "label": "Content Align",
-   "options": "Left\nCentre\nRight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_2_theme",
-   "fieldtype": "Select",
-   "label": "Slide Theme",
-   "options": "Dark\nLight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3",
-   "fieldtype": "Section Break",
-   "label": "Slide 3",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_image",
-   "fieldtype": "Attach Image",
-   "label": "Image",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_subtitle",
-   "fieldtype": "Small Text",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_content_align",
-   "fieldtype": "Select",
-   "label": "Content Align",
-   "options": "Left\nCentre\nRight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_3_theme",
-   "fieldtype": "Select",
-   "label": "Slide Theme",
-   "options": "Dark\nLight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4",
-   "fieldtype": "Section Break",
-   "label": "Slide 4",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_image",
-   "fieldtype": "Attach Image",
-   "label": "Image",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_subtitle",
-   "fieldtype": "Small Text",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_content_align",
-   "fieldtype": "Select",
-   "label": "Content Align",
-   "options": "Left\nCentre\nRight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_4_theme",
-   "fieldtype": "Select",
-   "label": "Slide Theme",
-   "options": "Dark\nLight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5",
-   "fieldtype": "Section Break",
-   "label": "Slide 5",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_image",
-   "fieldtype": "Attach Image",
-   "label": "Image",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_subtitle",
-   "fieldtype": "Small Text",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_content_align",
-   "fieldtype": "Select",
-   "label": "Content Align",
-   "options": "Left\nCentre\nRight",
-   "reqd": 0
-  },
-  {
-   "fieldname": "slide_5_theme",
-   "fieldtype": "Select",
-   "label": "Slide Theme",
-   "options": "Dark\nLight",
-   "reqd": 0
-  }
- ],
- "idx": 2,
- "modified": "2023-05-12 15:03:57.604060",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Hero Slider",
- "owner": "Administrator",
- "standard": 1,
- "template": "",
- "type": "Section"
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/web_template/item_card_group/__init__.py b/erpnext/e_commerce/web_template/item_card_group/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/item_card_group/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/item_card_group/item_card_group.html b/erpnext/e_commerce/web_template/item_card_group/item_card_group.html
deleted file mode 100644
index 07952f0..0000000
--- a/erpnext/e_commerce/web_template/item_card_group/item_card_group.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import item_card, item_card_body %}
-
-<div class="section-with-cards item-card-group-section">
-	<div class="item-group-header d-flex justify-content-between">
-		<div class="title-section">
-			{%- if title -%}
-			<h2 class="section-title">{{ title }}</h2>
-			{%- endif -%}
-			{%- if subtitle -%}
-			<p class="section-description">{{ subtitle }}</p>
-			{%- endif -%}
-		</div>
-		<div class="primary-action-section">
-			{%- if primary_action -%}
-			<a href="{{ action }}" class="btn btn-primary pull-right">
-				{{ primary_action_label }}
-			</a>
-			{%- endif -%}
-		</div>
-	</div>
-
-	<div class="row">
-		{%- for index in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] -%}
-		{%- set item = values['card_' + index + '_item'] -%}
-			{%- if item -%}
-				{%- set web_item = frappe.get_doc("Website Item", item) -%}
-				{{ item_card(
-					web_item, is_featured=values['card_' + index + '_featured'],
-					is_full_width=True, align="Center"
-				) }}
-			{%- endif -%}
-		{%- endfor -%}
-	</div>
-</div>
-
-<style>
-</style>
diff --git a/erpnext/e_commerce/web_template/item_card_group/item_card_group.json b/erpnext/e_commerce/web_template/item_card_group/item_card_group.json
deleted file mode 100644
index ad9e2a7..0000000
--- a/erpnext/e_commerce/web_template/item_card_group/item_card_group.json
+++ /dev/null
@@ -1,270 +0,0 @@
-{
- "__unsaved": 1,
- "creation": "2020-11-17 15:35:05.285322",
- "docstatus": 0,
- "doctype": "Web Template",
- "fields": [
-  {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 1
-  },
-  {
-   "fieldname": "subtitle",
-   "fieldtype": "Data",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "primary_action_label",
-   "fieldtype": "Data",
-   "label": "Primary Action Label",
-   "reqd": 0
-  },
-  {
-   "fieldname": "primary_action",
-   "fieldtype": "Data",
-   "label": "Primary Action",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_1",
-   "fieldtype": "Section Break",
-   "label": "Card 1",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_1_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_1_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_2",
-   "fieldtype": "Section Break",
-   "label": "Card 2",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_2_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_2_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_3",
-   "fieldtype": "Section Break",
-   "label": "Card 3",
-   "options": "",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_3_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_3_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_4",
-   "fieldtype": "Section Break",
-   "label": "Card 4",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_4_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_4_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_5",
-   "fieldtype": "Section Break",
-   "label": "Card 5",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_5_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_5_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_6",
-   "fieldtype": "Section Break",
-   "label": "Card 6",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_6_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_6_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_7",
-   "fieldtype": "Section Break",
-   "label": "Card 7",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_7_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_7_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_8",
-   "fieldtype": "Section Break",
-   "label": "Card 8",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_8_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_8_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_9",
-   "fieldtype": "Section Break",
-   "label": "Card 9",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_9_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_9_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_10",
-   "fieldtype": "Section Break",
-   "label": "Card 10",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_10_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_10_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_11",
-   "fieldtype": "Section Break",
-   "label": "Card 11",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_11_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_11_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_12",
-   "fieldtype": "Section Break",
-   "label": "Card 12",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_12_item",
-   "fieldtype": "Link",
-   "label": "Website Item",
-   "options": "Website Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "card_12_featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "reqd": 0
-  }
- ],
- "idx": 0,
- "modified": "2021-12-21 14:44:59.821335",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Item Card Group",
- "owner": "Administrator",
- "standard": 1,
- "template": "",
- "type": "Section"
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/web_template/product_card/__init__.py b/erpnext/e_commerce/web_template/product_card/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/product_card/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/product_card/product_card.html b/erpnext/e_commerce/web_template/product_card/product_card.html
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/product_card/product_card.html
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/product_card/product_card.json b/erpnext/e_commerce/web_template/product_card/product_card.json
deleted file mode 100644
index 2eb7374..0000000
--- a/erpnext/e_commerce/web_template/product_card/product_card.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "__unsaved": 1,
- "creation": "2020-11-17 15:28:47.809342",
- "docstatus": 0,
- "doctype": "Web Template",
- "fields": [
-  {
-   "fieldname": "item",
-   "fieldtype": "Link",
-   "label": "Item",
-   "options": "Item",
-   "reqd": 0
-  },
-  {
-   "fieldname": "featured",
-   "fieldtype": "Check",
-   "label": "Featured",
-   "options": "",
-   "reqd": 0
-  }
- ],
- "idx": 0,
- "modified": "2021-02-24 16:05:17.926610",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Product Card",
- "owner": "Administrator",
- "standard": 1,
- "template": "",
- "type": "Component"
-}
\ No newline at end of file
diff --git a/erpnext/e_commerce/web_template/product_category_cards/__init__.py b/erpnext/e_commerce/web_template/product_category_cards/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/e_commerce/web_template/product_category_cards/__init__.py
+++ /dev/null
diff --git a/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html
deleted file mode 100644
index 6d75a8b..0000000
--- a/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.html
+++ /dev/null
@@ -1,47 +0,0 @@
-{%- macro card(title, image, url, text_primary=False) -%}
-{%- set align_class = resolve_class({
-	'text-right': text_primary,
-	'text-centre': align == 'Center',
-	'text-left': align == 'Left',
-}) -%}
-<div class="card h-100">
-	{% if image %}
-	<img class="card-img-top" src="{{ image }}" alt="{{ title }}" style="max-height: 200px;">
-	{% else %}
-	<div class="placeholder-div" style="max-height: 200px;">
-		<span class="placeholder">
-			{{ frappe.utils.get_abbr(title or '') }}
-		</span>
-	</div>
-	{% endif %}
-
-	<div class="card-body text-center text-muted small">
-		{{ title or '' }}
-	</div>
-	<a href="{{ url or '#' }}" class="stretched-link"></a>
-</div>
-{%- endmacro -%}
-
-<div class="section-with-cards product-category-section">
-	{%- if title -%}
-	<h2 class="section-title">{{ title }}</h2>
-	{%- endif -%}
-	{%- if subtitle -%}
-	<p class="section-description">{{ subtitle }}</p>
-	{%- endif -%}
-	<!-- {%- set card_size = card_size or 'Small' -%} -->
-	<div class="{{ resolve_class({'mt-6': title}) }}">
-		<div class="card-grid">
-			{%- for index in ['1', '2', '3', '4', '5', '6', '7', '8'] -%}
-			{%- set category = values['category_' + index] -%}
-				{%- if category -%}
-					{%- set category = frappe.get_doc("Item Group", category) -%}
-					{{ card(category.name, category.image, category.route) }}
-				{%- endif -%}
-			{%- endfor -%}
-		</div>
-	</div>
-</div>
-
-<style>
-</style>
diff --git a/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json b/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json
deleted file mode 100644
index 0202165..0000000
--- a/erpnext/e_commerce/web_template/product_category_cards/product_category_cards.json
+++ /dev/null
@@ -1,85 +0,0 @@
-{
- "__unsaved": 1,
- "creation": "2020-11-17 15:25:50.855934",
- "docstatus": 0,
- "doctype": "Web Template",
- "fields": [
-  {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "label": "Title",
-   "reqd": 1
-  },
-  {
-   "fieldname": "subtitle",
-   "fieldtype": "Data",
-   "label": "Subtitle",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_1",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_2",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_3",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_4",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_5",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_6",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_7",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  },
-  {
-   "fieldname": "category_8",
-   "fieldtype": "Link",
-   "label": "Item Group",
-   "options": "Item Group",
-   "reqd": 0
-  }
- ],
- "idx": 0,
- "modified": "2021-02-24 16:03:33.835635",
- "modified_by": "Administrator",
- "module": "E-commerce",
- "name": "Product Category Cards",
- "owner": "Administrator",
- "standard": 1,
- "template": "",
- "type": "Section"
-}
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 2155699..5483a10 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -52,11 +52,7 @@
 filters_config = "erpnext.startup.filters.get_filters_config"
 additional_print_settings = "erpnext.controllers.print_settings.get_print_settings"
 
-on_session_creation = [
-	"erpnext.portal.utils.create_customer_or_supplier",
-	"erpnext.e_commerce.shopping_cart.utils.set_cart_count",
-]
-on_logout = "erpnext.e_commerce.shopping_cart.utils.clear_cart_count"
+on_session_creation = "erpnext.portal.utils.create_customer_or_supplier"
 
 treeviews = [
 	"Account",
@@ -90,15 +86,11 @@
 }
 
 # website
-update_website_context = [
-	"erpnext.e_commerce.shopping_cart.utils.update_website_context",
-]
-my_account_context = "erpnext.e_commerce.shopping_cart.utils.update_my_account_context"
 webform_list_context = "erpnext.controllers.website_list_for_contact.get_webform_list_context"
 
 calendars = ["Task", "Work Order", "Sales Order", "Holiday List", "ToDo"]
 
-website_generators = ["Item Group", "Website Item", "BOM", "Sales Partner"]
+website_generators = ["BOM", "Sales Partner"]
 
 website_context = {
 	"favicon": "/assets/erpnext/images/erpnext-favicon.svg",
@@ -349,9 +341,6 @@
 	"Event": {
 		"after_insert": "erpnext.crm.utils.link_events_with_prospect",
 	},
-	"Sales Taxes and Charges Template": {
-		"on_update": "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.validate_cart_settings"
-	},
 	"Sales Invoice": {
 		"on_submit": [
 			"erpnext.regional.create_transaction_log",
@@ -519,6 +508,7 @@
 	"Sales Invoice Item",
 	"Purchase Invoice Item",
 	"Purchase Order Item",
+	"Sales Order Item",
 	"Journal Entry Account",
 	"Material Request Item",
 	"Delivery Note Item",
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index dcb4212..c53cdf4 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -17,5 +17,4 @@
 Communication
 Telephony
 Bulk Transaction
-E-commerce
-Subcontracting
\ No newline at end of file
+Subcontracting
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 8f2d076..d59fe0e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -223,9 +223,6 @@
 erpnext.patches.v13_0.set_operation_time_based_on_operating_cost
 erpnext.patches.v13_0.create_gst_payment_entry_fields #27-11-2021
 erpnext.patches.v13_0.fix_invoice_statuses
-erpnext.patches.v13_0.create_website_items #30-09-2021
-erpnext.patches.v13_0.populate_e_commerce_settings
-erpnext.patches.v13_0.make_homepage_products_website_items
 erpnext.patches.v13_0.replace_supplier_item_group_with_party_specific_item
 erpnext.patches.v13_0.update_dates_in_tax_withholding_category
 erpnext.patches.v14_0.update_opportunity_currency_fields
@@ -242,7 +239,6 @@
 erpnext.patches.v13_0.healthcare_deprecation_warning
 erpnext.patches.v13_0.item_naming_series_not_mandatory
 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.v14_0.migrate_crm_settings
 erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
@@ -257,6 +253,7 @@
 erpnext.patches.v13_0.reset_corrupt_defaults
 erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
 erpnext.patches.v15_0.delete_taxjar_doctypes
+erpnext.patches.v15_0.delete_ecommerce_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
@@ -277,8 +274,6 @@
 erpnext.patches.v14_0.rearrange_company_fields
 erpnext.patches.v13_0.update_sane_transfer_against
 erpnext.patches.v14_0.migrate_cost_center_allocations
-erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
-erpnext.patches.v13_0.shopping_cart_to_ecommerce
 erpnext.patches.v13_0.update_reserved_qty_closed_wo
 erpnext.patches.v13_0.update_exchange_rate_settings
 erpnext.patches.v14_0.delete_amazon_mws_doctype
@@ -288,7 +283,6 @@
 erpnext.patches.v14_0.delete_non_profit_doctypes
 erpnext.patches.v13_0.set_return_against_in_pos_invoice_references
 erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022
-erpnext.patches.v13_0.copy_custom_field_filters_to_website_item
 erpnext.patches.v13_0.change_default_item_manufacturer_fieldtype
 erpnext.patches.v13_0.requeue_recoverable_reposts
 erpnext.patches.v14_0.discount_accounting_separation
@@ -345,5 +339,6 @@
 erpnext.patches.v14_0.update_invoicing_period_in_subscription
 execute:frappe.delete_doc("Page", "welcome-to-erpnext")
 erpnext.patches.v15_0.delete_payment_gateway_doctypes
+erpnext.patches.v14_0.create_accounting_dimensions_in_sales_order_item
 # below migration patch should always run last
-erpnext.patches.v14_0.migrate_gl_to_payment_ledger
+erpnext.patches.v14_0.migrate_gl_to_payment_ledger
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py b/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py
deleted file mode 100644
index 1bac0fd..0000000
--- a/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import json
-from typing import List, Union
-
-import frappe
-
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-
-
-def execute():
-	"""
-	Convert all Item links to Website Item link values in
-	exisitng 'Item Card Group' Web Page Block data.
-	"""
-	frappe.reload_doc("e_commerce", "web_template", "item_card_group")
-
-	blocks = frappe.db.get_all(
-		"Web Page Block",
-		filters={"web_template": "Item Card Group"},
-		fields=["parent", "web_template_values", "name"],
-	)
-
-	fields = generate_fields_to_edit()
-
-	for block in blocks:
-		web_template_value = json.loads(block.get("web_template_values"))
-
-		for field in fields:
-			item = web_template_value.get(field)
-			if not item:
-				continue
-
-			if frappe.db.exists("Website Item", {"item_code": item}):
-				website_item = frappe.db.get_value("Website Item", {"item_code": item})
-			else:
-				website_item = make_new_website_item(item)
-
-			if website_item:
-				web_template_value[field] = website_item
-
-		frappe.db.set_value(
-			"Web Page Block", block.name, "web_template_values", json.dumps(web_template_value)
-		)
-
-
-def generate_fields_to_edit() -> List:
-	fields = []
-	for i in range(1, 13):
-		fields.append(f"card_{i}_item")  # fields like 'card_1_item', etc.
-
-	return fields
-
-
-def make_new_website_item(item: str) -> Union[str, None]:
-	try:
-		doc = frappe.get_doc("Item", item)
-		web_item = make_website_item(doc)  # returns [website_item.name, item_name]
-		return web_item[0]
-	except Exception:
-		doc.log_error("Website Item creation failed")
-		return None
diff --git a/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py b/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py
deleted file mode 100644
index 4ad572f..0000000
--- a/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_field
-
-
-def execute():
-	"Add Field Filters, that are not standard fields in Website Item, as Custom Fields."
-
-	def move_table_multiselect_data(docfield):
-		"Copy child table data (Table Multiselect) from Item to Website Item for a docfield."
-		table_multiselect_data = get_table_multiselect_data(docfield)
-		field = docfield.fieldname
-
-		for row in table_multiselect_data:
-			# add copied multiselect data rows in Website Item
-			web_item = frappe.db.get_value("Website Item", {"item_code": row.parent})
-			web_item_doc = frappe.get_doc("Website Item", web_item)
-
-			child_doc = frappe.new_doc(docfield.options, parent_doc=web_item_doc, parentfield=field)
-
-			for field in ["name", "creation", "modified", "idx"]:
-				row[field] = None
-
-			child_doc.update(row)
-
-			child_doc.parenttype = "Website Item"
-			child_doc.parent = web_item
-
-			child_doc.insert()
-
-	def get_table_multiselect_data(docfield):
-		child_table = frappe.qb.DocType(docfield.options)
-		item = frappe.qb.DocType("Item")
-
-		table_multiselect_data = (  # query table data for field
-			frappe.qb.from_(child_table)
-			.join(item)
-			.on(item.item_code == child_table.parent)
-			.select(child_table.star)
-			.where((child_table.parentfield == docfield.fieldname) & (item.published_in_website == 1))
-		).run(as_dict=True)
-
-		return table_multiselect_data
-
-	settings = frappe.get_doc("E Commerce Settings")
-
-	if not (settings.enable_field_filters or settings.filter_fields):
-		return
-
-	item_meta = frappe.get_meta("Item")
-	valid_item_fields = [
-		df.fieldname for df in item_meta.fields if df.fieldtype in ["Link", "Table MultiSelect"]
-	]
-
-	web_item_meta = frappe.get_meta("Website Item")
-	valid_web_item_fields = [
-		df.fieldname for df in web_item_meta.fields if df.fieldtype in ["Link", "Table MultiSelect"]
-	]
-
-	for row in settings.filter_fields:
-		# skip if illegal field
-		if row.fieldname not in valid_item_fields:
-			continue
-
-		# if Item field is not in Website Item, add it as a custom field
-		if row.fieldname not in valid_web_item_fields:
-			df = item_meta.get_field(row.fieldname)
-			create_custom_field(
-				"Website Item",
-				dict(
-					owner="Administrator",
-					fieldname=df.fieldname,
-					label=df.label,
-					fieldtype=df.fieldtype,
-					options=df.options,
-					description=df.description,
-					read_only=df.read_only,
-					no_copy=df.no_copy,
-					insert_after="on_backorder",
-				),
-			)
-
-			# map field values
-			if df.fieldtype == "Table MultiSelect":
-				move_table_multiselect_data(df)
-			else:
-				frappe.db.sql(  # nosemgrep
-					"""
-						UPDATE `tabWebsite Item` wi, `tabItem` i
-						SET wi.{0} = i.{0}
-						WHERE wi.item_code = i.item_code
-					""".format(
-						row.fieldname
-					)
-				)
diff --git a/erpnext/patches/v13_0/create_website_items.py b/erpnext/patches/v13_0/create_website_items.py
deleted file mode 100644
index b010f0e..0000000
--- a/erpnext/patches/v13_0/create_website_items.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import frappe
-
-from erpnext.e_commerce.doctype.website_item.website_item import make_website_item
-
-
-def execute():
-	frappe.reload_doc("e_commerce", "doctype", "website_item")
-	frappe.reload_doc("e_commerce", "doctype", "website_item_tabbed_section")
-	frappe.reload_doc("e_commerce", "doctype", "website_offer")
-	frappe.reload_doc("e_commerce", "doctype", "recommended_items")
-	frappe.reload_doc("e_commerce", "doctype", "e_commerce_settings")
-	frappe.reload_doc("stock", "doctype", "item")
-
-	item_fields = [
-		"item_code",
-		"item_name",
-		"item_group",
-		"stock_uom",
-		"brand",
-		"has_variants",
-		"variant_of",
-		"description",
-		"weightage",
-	]
-	web_fields_to_map = [
-		"route",
-		"slideshow",
-		"website_image_alt",
-		"website_warehouse",
-		"web_long_description",
-		"website_content",
-		"website_image",
-		"thumbnail",
-	]
-
-	# get all valid columns (fields) from Item master DB schema
-	item_table_fields = frappe.db.sql("desc `tabItem`", as_dict=1)  # nosemgrep
-	item_table_fields = [d.get("Field") for d in item_table_fields]
-
-	# prepare fields to query from Item, check if the web field exists in Item master
-	web_query_fields = []
-	for web_field in web_fields_to_map:
-		if web_field in item_table_fields:
-			web_query_fields.append(web_field)
-			item_fields.append(web_field)
-
-	# check if the filter fields exist in Item master
-	or_filters = {}
-	for field in ["show_in_website", "show_variant_in_website"]:
-		if field in item_table_fields:
-			or_filters[field] = 1
-
-	if not web_query_fields or not or_filters:
-		# web fields to map are not present in Item master schema
-		# most likely a fresh installation that doesnt need this patch
-		return
-
-	items = frappe.db.get_all("Item", fields=item_fields, or_filters=or_filters)
-	total_count = len(items)
-
-	for count, item in enumerate(items, start=1):
-		if frappe.db.exists("Website Item", {"item_code": item.item_code}):
-			continue
-
-		# make new website item from item (publish item)
-		website_item = make_website_item(item, save=False)
-		website_item.ranking = item.get("weightage")
-
-		for field in web_fields_to_map:
-			website_item.update({field: item.get(field)})
-
-		website_item.save()
-
-		# move Website Item Group & Website Specification table to Website Item
-		for doctype in ("Website Item Group", "Item Website Specification"):
-			frappe.db.set_value(
-				doctype,
-				{"parenttype": "Item", "parent": item.item_code},  # filters
-				{"parenttype": "Website Item", "parent": website_item.name},  # value dict
-			)
-
-		if count % 20 == 0:  # commit after every 20 items
-			frappe.db.commit()
-
-		frappe.utils.update_progress_bar("Creating Website Items", count, total_count)
diff --git a/erpnext/patches/v13_0/fetch_thumbnail_in_website_items.py b/erpnext/patches/v13_0/fetch_thumbnail_in_website_items.py
deleted file mode 100644
index 9197d86..0000000
--- a/erpnext/patches/v13_0/fetch_thumbnail_in_website_items.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import frappe
-
-
-def execute():
-	if frappe.db.has_column("Item", "thumbnail"):
-		website_item = frappe.qb.DocType("Website Item").as_("wi")
-		item = frappe.qb.DocType("Item")
-
-		frappe.qb.update(website_item).inner_join(item).on(website_item.item_code == item.item_code).set(
-			website_item.thumbnail, item.thumbnail
-		).where(website_item.website_image.notnull() & website_item.thumbnail.isnull()).run()
diff --git a/erpnext/patches/v13_0/make_homepage_products_website_items.py b/erpnext/patches/v13_0/make_homepage_products_website_items.py
deleted file mode 100644
index 50bfd35..0000000
--- a/erpnext/patches/v13_0/make_homepage_products_website_items.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import frappe
-
-
-def execute():
-	homepage = frappe.get_doc("Homepage")
-
-	for row in homepage.products:
-		web_item = frappe.db.get_value("Website Item", {"item_code": row.item_code}, "name")
-		if not web_item:
-			continue
-
-		row.item_code = web_item
-
-	homepage.flags.ignore_mandatory = True
-	homepage.save()
diff --git a/erpnext/patches/v13_0/populate_e_commerce_settings.py b/erpnext/patches/v13_0/populate_e_commerce_settings.py
deleted file mode 100644
index ecf512b..0000000
--- a/erpnext/patches/v13_0/populate_e_commerce_settings.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import frappe
-from frappe.utils import cint
-
-
-def execute():
-	frappe.reload_doc("e_commerce", "doctype", "e_commerce_settings")
-	frappe.reload_doc("portal", "doctype", "website_filter_field")
-	frappe.reload_doc("portal", "doctype", "website_attribute")
-
-	products_settings_fields = [
-		"hide_variants",
-		"products_per_page",
-		"enable_attribute_filters",
-		"enable_field_filters",
-	]
-
-	shopping_cart_settings_fields = [
-		"enabled",
-		"show_attachments",
-		"show_price",
-		"show_stock_availability",
-		"enable_variants",
-		"show_contact_us_button",
-		"show_quantity_in_website",
-		"show_apply_coupon_code_in_website",
-		"allow_items_not_in_stock",
-		"company",
-		"price_list",
-		"default_customer_group",
-		"quotation_series",
-		"enable_checkout",
-		"payment_success_url",
-		"payment_gateway_account",
-		"save_quotations_as_draft",
-	]
-
-	settings = frappe.get_doc("E Commerce Settings")
-
-	def map_into_e_commerce_settings(doctype, fields):
-		singles = frappe.qb.DocType("Singles")
-		query = (
-			frappe.qb.from_(singles)
-			.select(singles["field"], singles.value)
-			.where((singles.doctype == doctype) & (singles["field"].isin(fields)))
-		)
-		data = query.run(as_dict=True)
-
-		# {'enable_attribute_filters': '1', ...}
-		mapper = {row.field: row.value for row in data}
-
-		for key, value in mapper.items():
-			value = cint(value) if (value and value.isdigit()) else value
-			settings.update({key: value})
-
-		settings.save()
-
-	# shift data to E Commerce Settings
-	map_into_e_commerce_settings("Products Settings", products_settings_fields)
-	map_into_e_commerce_settings("Shopping Cart Settings", shopping_cart_settings_fields)
-
-	# move filters and attributes tables to E Commerce Settings from Products Settings
-	for doctype in ("Website Filter Field", "Website Attribute"):
-		frappe.db.set_value(
-			doctype,
-			{"parent": "Products Settings"},
-			{"parenttype": "E Commerce Settings", "parent": "E Commerce Settings"},
-			update_modified=False,
-		)
diff --git a/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py b/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py
deleted file mode 100644
index 35710a9..0000000
--- a/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import click
-import frappe
-
-
-def execute():
-
-	frappe.delete_doc("DocType", "Shopping Cart Settings", ignore_missing=True)
-	frappe.delete_doc("DocType", "Products Settings", ignore_missing=True)
-	frappe.delete_doc("DocType", "Supplier Item Group", ignore_missing=True)
-
-	if frappe.db.get_single_value("E Commerce Settings", "enabled"):
-		notify_users()
-
-
-def notify_users():
-
-	click.secho(
-		"Shopping cart and Product settings are merged into E-commerce settings.\n"
-		"Checkout the documentation to learn more:"
-		"https://docs.erpnext.com/docs/v13/user/manual/en/e_commerce/set_up_e_commerce",
-		fg="yellow",
-	)
-
-	note = frappe.new_doc("Note")
-	note.title = "New E-Commerce Module"
-	note.public = 1
-	note.notify_on_login = 1
-	note.content = """<div class="ql-editor read-mode"><p>You are seeing this message because Shopping Cart is enabled on your site. </p><p><br></p><p>Shopping Cart Settings and Products settings are now merged into "E Commerce Settings". </p><p><br></p><p>You can learn about new and improved E-Commerce features in the official documentation.</p><ol><li data-list="bullet"><span class="ql-ui" contenteditable="false"></span><a href="https://docs.erpnext.com/docs/v13/user/manual/en/e_commerce/set_up_e_commerce" rel="noopener noreferrer">https://docs.erpnext.com/docs/v13/user/manual/en/e_commerce/set_up_e_commerce</a></li></ol><p><br></p></div>"""
-	note.insert(ignore_mandatory=True)
diff --git a/erpnext/patches/v14_0/create_accounting_dimensions_in_sales_order_item.py b/erpnext/patches/v14_0/create_accounting_dimensions_in_sales_order_item.py
new file mode 100644
index 0000000..8f77c35
--- /dev/null
+++ b/erpnext/patches/v14_0/create_accounting_dimensions_in_sales_order_item.py
@@ -0,0 +1,7 @@
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
+	create_accounting_dimensions_for_doctype,
+)
+
+
+def execute():
+	create_accounting_dimensions_for_doctype(doctype="Sales Order Item")
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 a53adf1..9a2a39f 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
@@ -11,6 +11,9 @@
 	asset_depreciation_schedules_map = get_asset_depreciation_schedules_map()
 
 	for asset in assets:
+		if not asset_depreciation_schedules_map.get(asset.name):
+			continue
+
 		depreciation_schedules = asset_depreciation_schedules_map[asset.name]
 
 		for fb_row in asset_finance_books_map[asset.name]:
diff --git a/erpnext/patches/v15_0/delete_ecommerce_doctypes.py b/erpnext/patches/v15_0/delete_ecommerce_doctypes.py
new file mode 100644
index 0000000..af03987
--- /dev/null
+++ b/erpnext/patches/v15_0/delete_ecommerce_doctypes.py
@@ -0,0 +1,30 @@
+import click
+import frappe
+
+
+def execute():
+	if "webshop" in frappe.get_installed_apps():
+		return
+
+	if not frappe.db.table_exists("Website Item"):
+		return
+
+	doctypes = [
+		"E Commerce Settings",
+		"Website Item",
+		"Recommended Items",
+		"Item Review",
+		"Wishlist Item",
+		"Wishlist",
+		"Website Offer",
+		"Website Item Tabbed Section",
+	]
+
+	for doctype in doctypes:
+		frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+	click.secho(
+		"ECommerce is renamed and moved to a separate app"
+		"Please install the app for ECommerce features: https://github.com/frappe/webshop",
+		fg="yellow",
+	)
diff --git a/erpnext/portal/doctype/homepage/homepage.js b/erpnext/portal/doctype/homepage/homepage.js
index 59f808a..6797904 100644
--- a/erpnext/portal/doctype/homepage/homepage.js
+++ b/erpnext/portal/doctype/homepage/homepage.js
@@ -19,12 +19,3 @@
 		});
 	},
 });
-
-frappe.ui.form.on('Homepage Featured Product', {
-	view: function(frm, cdt, cdn) {
-		var child= locals[cdt][cdn];
-		if (child.item_code && child.route) {
-			window.open('/' + child.route, '_blank');
-		}
-	}
-});
diff --git a/erpnext/portal/doctype/homepage/homepage.json b/erpnext/portal/doctype/homepage/homepage.json
index 73f816d..2b891f7 100644
--- a/erpnext/portal/doctype/homepage/homepage.json
+++ b/erpnext/portal/doctype/homepage/homepage.json
@@ -15,10 +15,7 @@
   "description",
   "hero_image",
   "slideshow",
-  "hero_section",
-  "products_section",
-  "products_url",
-  "products"
+  "hero_section"
  ],
  "fields": [
   {
@@ -86,30 +83,11 @@
    "fieldtype": "Link",
    "label": "Homepage Section",
    "options": "Homepage Section"
-  },
-  {
-   "fieldname": "products_section",
-   "fieldtype": "Section Break",
-   "label": "Products"
-  },
-  {
-   "default": "/all-products",
-   "fieldname": "products_url",
-   "fieldtype": "Data",
-   "label": "URL for \"All Products\""
-  },
-  {
-   "description": "Products to be shown on website homepage",
-   "fieldname": "products",
-   "fieldtype": "Table",
-   "label": "Products",
-   "options": "Homepage Featured Product",
-   "width": "40px"
   }
  ],
  "issingle": 1,
  "links": [],
- "modified": "2021-02-18 13:29:29.531639",
+ "modified": "2022-12-19 21:10:29.127277",
  "modified_by": "Administrator",
  "module": "Portal",
  "name": "Homepage",
@@ -138,6 +116,7 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "title_field": "company",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py
index 0d2e360..c0a0c07 100644
--- a/erpnext/portal/doctype/homepage/homepage.py
+++ b/erpnext/portal/doctype/homepage/homepage.py
@@ -12,26 +12,3 @@
 		if not self.description:
 			self.description = frappe._("This is an example website auto-generated from ERPNext")
 		delete_page_cache("home")
-
-	def setup_items(self):
-		for d in frappe.get_all(
-			"Website Item",
-			fields=["name", "item_name", "description", "website_image", "route"],
-			filters={"published": 1},
-			limit=3,
-		):
-
-			doc = frappe.get_doc("Website Item", d.name)
-			if not doc.route:
-				# set missing route
-				doc.save()
-			self.append(
-				"products",
-				dict(
-					item_code=d.name,
-					item_name=d.item_name,
-					description=d.description,
-					image=d.website_image,
-					route=d.route,
-				),
-			)
diff --git a/erpnext/portal/doctype/homepage_featured_product/__init__.py b/erpnext/portal/doctype/homepage_featured_product/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/portal/doctype/homepage_featured_product/__init__.py
+++ /dev/null
diff --git a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json
deleted file mode 100644
index 63789e3..0000000
--- a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json
+++ /dev/null
@@ -1,118 +0,0 @@
-{
- "actions": [],
- "autoname": "hash",
- "creation": "2016-04-22 05:57:06.261401",
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "item_code",
-  "col_break1",
-  "item_name",
-  "view",
-  "section_break_5",
-  "description",
-  "column_break_7",
-  "image",
-  "thumbnail",
-  "route"
- ],
- "fields": [
-  {
-   "bold": 1,
-   "fieldname": "item_code",
-   "fieldtype": "Link",
-   "in_filter": 1,
-   "in_list_view": 1,
-   "label": "Item",
-   "oldfieldname": "item_code",
-   "oldfieldtype": "Link",
-   "options": "Website Item",
-   "print_width": "150px",
-   "reqd": 1,
-   "search_index": 1,
-   "width": "150px"
-  },
-  {
-   "fieldname": "col_break1",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "item_code.item_name",
-   "fetch_if_empty": 1,
-   "fieldname": "item_name",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Item Name",
-   "oldfieldname": "item_name",
-   "oldfieldtype": "Data",
-   "print_hide": 1,
-   "print_width": "150",
-   "read_only": 1,
-   "reqd": 1,
-   "width": "150"
-  },
-  {
-   "fieldname": "view",
-   "fieldtype": "Button",
-   "in_list_view": 1,
-   "label": "View"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "section_break_5",
-   "fieldtype": "Section Break",
-   "label": "Details"
-  },
-  {
-   "fetch_from": "item_code.web_long_description",
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "in_filter": 1,
-   "in_list_view": 1,
-   "label": "Description",
-   "oldfieldname": "description",
-   "oldfieldtype": "Small Text",
-   "print_width": "300px",
-   "width": "300px"
-  },
-  {
-   "fieldname": "column_break_7",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fetch_from": "item_code.website_image",
-   "fetch_if_empty": 1,
-   "fieldname": "image",
-   "fieldtype": "Attach Image",
-   "label": "Image"
-  },
-  {
-   "fetch_from": "item_code.thumbnail",
-   "fieldname": "thumbnail",
-   "fieldtype": "Attach Image",
-   "hidden": 1,
-   "label": "Thumbnail"
-  },
-  {
-   "fetch_from": "item_code.route",
-   "fieldname": "route",
-   "fieldtype": "Small Text",
-   "label": "route",
-   "read_only": 1
-  }
- ],
- "index_web_pages_for_search": 1,
- "istable": 1,
- "links": [],
- "modified": "2021-02-18 13:05:50.669311",
- "modified_by": "Administrator",
- "module": "Portal",
- "name": "Homepage Featured Product",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC"
-}
\ No newline at end of file
diff --git a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py
deleted file mode 100644
index c21461d..0000000
--- a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HomepageFeaturedProduct(Document):
-	pass
diff --git a/erpnext/portal/utils.py b/erpnext/portal/utils.py
index c8b03e6..903d4a6 100644
--- a/erpnext/portal/utils.py
+++ b/erpnext/portal/utils.py
@@ -1,10 +1,4 @@
 import frappe
-from frappe.utils.nestedset import get_root_of
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.e_commerce.shopping_cart.cart import get_debtors_account
 
 
 def set_default_role(doc, method):
@@ -56,26 +50,7 @@
 	party = frappe.new_doc(doctype)
 	fullname = frappe.utils.get_fullname(user)
 
-	if doctype == "Customer":
-		cart_settings = get_shopping_cart_settings()
-
-		if cart_settings.enable_checkout:
-			debtors_account = get_debtors_account(cart_settings)
-		else:
-			debtors_account = ""
-
-		party.update(
-			{
-				"customer_name": fullname,
-				"customer_type": "Individual",
-				"customer_group": cart_settings.default_customer_group,
-				"territory": get_root_of("Territory"),
-			}
-		)
-
-		if debtors_account:
-			party.update({"accounts": [{"company": cart_settings.company, "account": debtors_account}]})
-	else:
+	if not doctype == "Customer":
 		party.update(
 			{
 				"supplier_name": fullname,
diff --git a/erpnext/projects/doctype/task_depends_on/task_depends_on.json b/erpnext/projects/doctype/task_depends_on/task_depends_on.json
index 5102986..3300b7e 100644
--- a/erpnext/projects/doctype/task_depends_on/task_depends_on.json
+++ b/erpnext/projects/doctype/task_depends_on/task_depends_on.json
@@ -24,6 +24,7 @@
   },
   {
    "fetch_from": "task.subject",
+   "fetch_if_empty": 1,
    "fieldname": "subject",
    "fieldtype": "Text",
    "in_list_view": 1,
@@ -31,7 +32,6 @@
    "read_only": 1
   },
   {
-   "fetch_from": "task.project",
    "fieldname": "project",
    "fieldtype": "Text",
    "label": "Project",
@@ -40,7 +40,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2023-10-09 11:34:14.335853",
+ "modified": "2023-10-17 12:45:21.536165",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Task Depends On",
diff --git a/erpnext/public/js/customer_reviews.js b/erpnext/public/js/customer_reviews.js
deleted file mode 100644
index e13ded6..0000000
--- a/erpnext/public/js/customer_reviews.js
+++ /dev/null
@@ -1,138 +0,0 @@
-$(() => {
-	class CustomerReviews {
-		constructor() {
-			this.bind_button_actions();
-			this.start = 0;
-			this.page_length = 10;
-		}
-
-		bind_button_actions() {
-			this.write_review();
-			this.view_more();
-		}
-
-		write_review() {
-			//TODO: make dialog popup on stray page
-			$('.page_content').on('click', '.btn-write-review', (e) => {
-				// Bind action on write a review button
-				const $btn = $(e.currentTarget);
-
-				let d = new frappe.ui.Dialog({
-					title: __("Write a Review"),
-					fields: [
-						{fieldname: "title", fieldtype: "Data", label: "Headline", reqd: 1},
-						{fieldname: "rating", fieldtype: "Rating", label: "Overall Rating", reqd: 1},
-						{fieldtype: "Section Break"},
-						{fieldname: "comment", fieldtype: "Small Text", label: "Your Review"}
-					],
-					primary_action: function() {
-						let data = d.get_values();
-						frappe.call({
-							method: "erpnext.e_commerce.doctype.item_review.item_review.add_item_review",
-							args: {
-								web_item: $btn.attr('data-web-item'),
-								title: data.title,
-								rating: data.rating,
-								comment: data.comment
-							},
-							freeze: true,
-							freeze_message: __("Submitting Review ..."),
-							callback: (r) => {
-								if (!r.exc) {
-									frappe.msgprint({
-										message: __("Thank you for submitting your review"),
-										title: __("Review Submitted"),
-										indicator: "green"
-									});
-									d.hide();
-									location.reload();
-								}
-							}
-						});
-					},
-					primary_action_label: __('Submit')
-				});
-				d.show();
-			});
-		}
-
-		view_more() {
-			$('.page_content').on('click', '.btn-view-more', (e) => {
-				// Bind action on view more button
-				const $btn = $(e.currentTarget);
-				$btn.prop('disabled', true);
-
-				this.start += this.page_length;
-				let me = this;
-
-				frappe.call({
-					method: "erpnext.e_commerce.doctype.item_review.item_review.get_item_reviews",
-					args: {
-						web_item: $btn.attr('data-web-item'),
-						start: me.start,
-						end: me.page_length
-					},
-					callback: (result) => {
-						if (result.message) {
-							let res = result.message;
-							me.get_user_review_html(res.reviews);
-
-							$btn.prop('disabled', false);
-							if (res.total_reviews <= (me.start + me.page_length)) {
-								$btn.hide();
-							}
-
-						}
-					}
-				});
-			});
-
-		}
-
-		get_user_review_html(reviews) {
-			let me = this;
-			let $content = $('.user-reviews');
-
-			reviews.forEach((review) => {
-				$content.append(`
-					<div class="mb-3 review">
-						<div class="d-flex">
-							<p class="mr-4 user-review-title">
-								<span>${__(review.review_title)}</span>
-							</p>
-							<div class="rating">
-								${me.get_review_stars(review.rating)}
-							</div>
-						</div>
-
-						<div class="product-description mb-4">
-							<p>
-								${__(review.comment)}
-							</p>
-						</div>
-						<div class="review-signature mb-2">
-							<span class="reviewer">${__(review.customer)}</span>
-							<span class="indicator grey" style="--text-on-gray: var(--gray-300);"></span>
-							<span class="reviewer">${__(review.published_on)}</span>
-						</div>
-					</div>
-				`);
-			});
-		}
-
-		get_review_stars(rating) {
-			let stars = ``;
-			for (let i = 1; i < 6; i++) {
-				let fill_class = i <= rating ? 'star-click' : '';
-				stars += `
-					<svg class="icon icon-sm ${fill_class}">
-						<use href="#icon-star"></use>
-					</svg>
-				`;
-			}
-			return stars;
-		}
-	}
-
-	new CustomerReviews();
-});
\ No newline at end of file
diff --git a/erpnext/public/js/erpnext-web.bundle.js b/erpnext/public/js/erpnext-web.bundle.js
index cbe899d..45c6a64 100644
--- a/erpnext/public/js/erpnext-web.bundle.js
+++ b/erpnext/public/js/erpnext-web.bundle.js
@@ -1,8 +1 @@
 import "./website_utils";
-import "./wishlist";
-import "./shopping_cart";
-import "./customer_reviews";
-import "../../e_commerce/product_ui/list";
-import "../../e_commerce/product_ui/views";
-import "../../e_commerce/product_ui/grid";
-import "../../e_commerce/product_ui/search";
\ No newline at end of file
diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js
deleted file mode 100644
index d14740c..0000000
--- a/erpnext/public/js/shopping_cart.js
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-
-// shopping cart
-frappe.provide("erpnext.e_commerce.shopping_cart");
-var shopping_cart = erpnext.e_commerce.shopping_cart;
-
-var getParams = function (url) {
-	var params = [];
-	var parser = document.createElement('a');
-	parser.href = url;
-	var query = parser.search.substring(1);
-	var vars = query.split('&');
-	for (var i = 0; i < vars.length; i++) {
-		var pair = vars[i].split('=');
-		params[pair[0]] = decodeURIComponent(pair[1]);
-	}
-	return params;
-};
-
-frappe.ready(function() {
-	var full_name = frappe.session && frappe.session.user_fullname;
-	// update user
-	if(full_name) {
-		$('.navbar li[data-label="User"] a')
-			.html('<i class="fa fa-fixed-width fa fa-user"></i> ' + full_name);
-	}
-	// set coupon code and sales partner code
-
-	var url_args = getParams(window.location.href);
-
-	var referral_coupon_code = url_args['cc'];
-	var referral_sales_partner = url_args['sp'];
-
-	var d = new Date();
-	// expires within 30 minutes
-	d.setTime(d.getTime() + (0.02 * 24 * 60 * 60 * 1000));
-	var expires = "expires="+d.toUTCString();
-	if (referral_coupon_code) {
-		document.cookie = "referral_coupon_code=" + referral_coupon_code + ";" + expires + ";path=/";
-	}
-	if (referral_sales_partner) {
-		document.cookie = "referral_sales_partner=" + referral_sales_partner + ";" + expires + ";path=/";
-	}
-	referral_coupon_code=frappe.get_cookie("referral_coupon_code");
-	referral_sales_partner=frappe.get_cookie("referral_sales_partner");
-
-	if (referral_coupon_code && $(".tot_quotation_discount").val()==undefined ) {
-		$(".txtcoupon").val(referral_coupon_code);
-	}
-	if (referral_sales_partner) {
-		$(".txtreferral_sales_partner").val(referral_sales_partner);
-	}
-
-	// update login
-	shopping_cart.show_shoppingcart_dropdown();
-	shopping_cart.set_cart_count();
-	shopping_cart.show_cart_navbar();
-});
-
-$.extend(shopping_cart, {
-	show_shoppingcart_dropdown: function() {
-		$(".shopping-cart").on('shown.bs.dropdown', function() {
-			if (!$('.shopping-cart-menu .cart-container').length) {
-				return frappe.call({
-					method: 'erpnext.e_commerce.shopping_cart.cart.get_shopping_cart_menu',
-					callback: function(r) {
-						if (r.message) {
-							$('.shopping-cart-menu').html(r.message);
-						}
-					}
-				});
-			}
-		});
-	},
-
-	update_cart: function(opts) {
-		if (frappe.session.user==="Guest") {
-			if (localStorage) {
-				localStorage.setItem("last_visited", window.location.pathname);
-			}
-			frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => {
-				window.location.href = res.message || "/login";
-			});
-		} else {
-			shopping_cart.freeze();
-			return frappe.call({
-				type: "POST",
-				method: "erpnext.e_commerce.shopping_cart.cart.update_cart",
-				args: {
-					item_code: opts.item_code,
-					qty: opts.qty,
-					additional_notes: opts.additional_notes !== undefined ? opts.additional_notes : undefined,
-					with_items: opts.with_items || 0
-				},
-				btn: opts.btn,
-				callback: function(r) {
-					shopping_cart.unfreeze();
-					shopping_cart.set_cart_count(true);
-					if(opts.callback)
-						opts.callback(r);
-				}
-			});
-		}
-	},
-
-	set_cart_count: function(animate=false) {
-		$(".intermediate-empty-cart").remove();
-
-		var cart_count = frappe.get_cookie("cart_count");
-		if(frappe.session.user==="Guest") {
-			cart_count = 0;
-		}
-
-		if(cart_count) {
-			$(".shopping-cart").toggleClass('hidden', false);
-		}
-
-		var $cart = $('.cart-icon');
-		var $badge = $cart.find("#cart-count");
-
-		if(parseInt(cart_count) === 0 || cart_count === undefined) {
-			$cart.css("display", "none");
-			$(".cart-tax-items").hide();
-			$(".btn-place-order").hide();
-			$(".cart-payment-addresses").hide();
-
-			let intermediate_empty_cart_msg = `
-				<div class="text-center w-100 intermediate-empty-cart mt-4 mb-4 text-muted">
-					${ __("Cart is Empty") }
-				</div>
-			`;
-			$(".cart-table").after(intermediate_empty_cart_msg);
-		}
-		else {
-			$cart.css("display", "inline");
-			$("#cart-count").text(cart_count);
-		}
-
-		if(cart_count) {
-			$badge.html(cart_count);
-
-			if (animate) {
-				$cart.addClass("cart-animate");
-				setTimeout(() => {
-					$cart.removeClass("cart-animate");
-				}, 500);
-			}
-		} else {
-			$badge.remove();
-		}
-	},
-
-	shopping_cart_update: function({item_code, qty, cart_dropdown, additional_notes}) {
-		shopping_cart.update_cart({
-			item_code,
-			qty,
-			additional_notes,
-			with_items: 1,
-			btn: this,
-			callback: function(r) {
-				if(!r.exc) {
-					$(".cart-items").html(r.message.items);
-					$(".cart-tax-items").html(r.message.total);
-					$(".payment-summary").html(r.message.taxes_and_totals);
-					shopping_cart.set_cart_count();
-
-					if (cart_dropdown != true) {
-						$(".cart-icon").hide();
-					}
-				}
-			},
-		});
-	},
-
-	show_cart_navbar: function () {
-		frappe.call({
-			method: "erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings.is_cart_enabled",
-			callback: function(r) {
-				$(".shopping-cart").toggleClass('hidden', r.message ? false : true);
-			}
-		});
-	},
-
-	toggle_button_class(button, remove, add) {
-		button.removeClass(remove);
-		button.addClass(add);
-	},
-
-	bind_add_to_cart_action() {
-		$('.page_content').on('click', '.btn-add-to-cart-list', (e) => {
-			const $btn = $(e.currentTarget);
-			$btn.prop('disabled', true);
-
-			if (frappe.session.user==="Guest") {
-				if (localStorage) {
-					localStorage.setItem("last_visited", window.location.pathname);
-				}
-				frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => {
-					window.location.href = res.message || "/login";
-				});
-				return;
-			}
-
-			$btn.addClass('hidden');
-			$btn.closest('.cart-action-container').addClass('d-flex');
-			$btn.parent().find('.go-to-cart').removeClass('hidden');
-			$btn.parent().find('.go-to-cart-grid').removeClass('hidden');
-			$btn.parent().find('.cart-indicator').removeClass('hidden');
-
-			const item_code = $btn.data('item-code');
-			erpnext.e_commerce.shopping_cart.update_cart({
-				item_code,
-				qty: 1
-			});
-
-		});
-	},
-
-	freeze() {
-		if (window.location.pathname !== "/cart") return;
-
-		if (!$('#freeze').length) {
-			let freeze = $('<div id="freeze" class="modal-backdrop fade"></div>')
-				.appendTo("body");
-
-			setTimeout(function() {
-				freeze.addClass("show");
-			}, 1);
-		} else {
-			$("#freeze").addClass("show");
-		}
-	},
-
-	unfreeze() {
-		if ($('#freeze').length) {
-			let freeze = $('#freeze').removeClass("show");
-			setTimeout(function() {
-				freeze.remove();
-			}, 1);
-		}
-	}
-});
diff --git a/erpnext/public/js/wishlist.js b/erpnext/public/js/wishlist.js
deleted file mode 100644
index f6599e9..0000000
--- a/erpnext/public/js/wishlist.js
+++ /dev/null
@@ -1,204 +0,0 @@
-frappe.provide("erpnext.e_commerce.wishlist");
-var wishlist = erpnext.e_commerce.wishlist;
-
-frappe.provide("erpnext.e_commerce.shopping_cart");
-var shopping_cart = erpnext.e_commerce.shopping_cart;
-
-$.extend(wishlist, {
-	set_wishlist_count: function(animate=false) {
-		// set badge count for wishlist icon
-		var wish_count = frappe.get_cookie("wish_count");
-		if (frappe.session.user==="Guest") {
-			wish_count = 0;
-		}
-
-		if (wish_count) {
-			$(".wishlist").toggleClass('hidden', false);
-		}
-
-		var $wishlist = $('.wishlist-icon');
-		var $badge = $wishlist.find("#wish-count");
-
-		if (parseInt(wish_count) === 0 || wish_count === undefined) {
-			$wishlist.css("display", "none");
-		} else {
-			$wishlist.css("display", "inline");
-		}
-		if (wish_count) {
-			$badge.html(wish_count);
-			if (animate) {
-				$wishlist.addClass('cart-animate');
-				setTimeout(() => {
-					$wishlist.removeClass('cart-animate');
-				}, 500);
-			}
-		} else {
-			$badge.remove();
-		}
-	},
-
-	bind_move_to_cart_action: function() {
-		// move item to cart from wishlist
-		$('.page_content').on("click", ".btn-add-to-cart", (e) => {
-			const $move_to_cart_btn = $(e.currentTarget);
-			let item_code = $move_to_cart_btn.data("item-code");
-
-			shopping_cart.shopping_cart_update({
-				item_code,
-				qty: 1,
-				cart_dropdown: true
-			});
-
-			let success_action = function() {
-				const $card_wrapper = $move_to_cart_btn.closest(".wishlist-card");
-				$card_wrapper.addClass("wish-removed");
-			};
-			let args = { item_code: item_code };
-			this.add_remove_from_wishlist("remove", args, success_action, null, true);
-		});
-	},
-
-	bind_remove_action: function() {
-		// remove item from wishlist
-		let me = this;
-
-		$('.page_content').on("click", ".remove-wish", (e) => {
-			const $remove_wish_btn = $(e.currentTarget);
-			let item_code = $remove_wish_btn.data("item-code");
-
-			let success_action = function() {
-				const $card_wrapper = $remove_wish_btn.closest(".wishlist-card");
-				$card_wrapper.addClass("wish-removed");
-				if (frappe.get_cookie("wish_count") == 0) {
-					$(".page_content").empty();
-					me.render_empty_state();
-				}
-			};
-			let args = { item_code: item_code };
-			this.add_remove_from_wishlist("remove", args, success_action);
-		});
-	},
-
-	bind_wishlist_action() {
-		// 'wish'('like') or 'unwish' item in product listing
-		$('.page_content').on('click', '.like-action, .like-action-list', (e) => {
-			const $btn = $(e.currentTarget);
-			this.wishlist_action($btn);
-		});
-	},
-
-	wishlist_action(btn) {
-		const $wish_icon = btn.find('.wish-icon');
-		let me = this;
-
-		if (frappe.session.user==="Guest") {
-			if (localStorage) {
-				localStorage.setItem("last_visited", window.location.pathname);
-			}
-			this.redirect_guest();
-			return;
-		}
-
-		let success_action = function() {
-			erpnext.e_commerce.wishlist.set_wishlist_count(true);
-		};
-
-		if ($wish_icon.hasClass('wished')) {
-			// un-wish item
-			btn.removeClass("like-animate");
-			btn.addClass("like-action-wished");
-			this.toggle_button_class($wish_icon, 'wished', 'not-wished');
-
-			let args = { item_code: btn.data('item-code') };
-			let failure_action = function() {
-				me.toggle_button_class($wish_icon, 'not-wished', 'wished');
-			};
-			this.add_remove_from_wishlist("remove", args, success_action, failure_action);
-		} else {
-			// wish item
-			btn.addClass("like-animate");
-			btn.addClass("like-action-wished");
-			this.toggle_button_class($wish_icon, 'not-wished', 'wished');
-
-			let args = {item_code: btn.data('item-code')};
-			let failure_action = function() {
-				me.toggle_button_class($wish_icon, 'wished', 'not-wished');
-			};
-			this.add_remove_from_wishlist("add", args, success_action, failure_action);
-		}
-	},
-
-	toggle_button_class(button, remove, add) {
-		button.removeClass(remove);
-		button.addClass(add);
-	},
-
-	add_remove_from_wishlist(action, args, success_action, failure_action, async=false) {
-		/*	AJAX call to add or remove Item from Wishlist
-			action: "add" or "remove"
-			args: args for method (item_code, price, formatted_price),
-			success_action: method to execute on successs,
-			failure_action: method to execute on failure,
-			async: make call asynchronously (true/false).	*/
-		if (frappe.session.user==="Guest") {
-			if (localStorage) {
-				localStorage.setItem("last_visited", window.location.pathname);
-			}
-			this.redirect_guest();
-		} else {
-			let method = "erpnext.e_commerce.doctype.wishlist.wishlist.add_to_wishlist";
-			if (action === "remove") {
-				method = "erpnext.e_commerce.doctype.wishlist.wishlist.remove_from_wishlist";
-			}
-
-			frappe.call({
-				async: async,
-				type: "POST",
-				method: method,
-				args: args,
-				callback: function (r) {
-					if (r.exc) {
-						if (failure_action && (typeof failure_action === 'function')) {
-							failure_action();
-						}
-						frappe.msgprint({
-							message: __("Sorry, something went wrong. Please refresh."),
-							indicator: "red", title: __("Note")
-						});
-					} else if (success_action && (typeof success_action === 'function')) {
-						success_action();
-					}
-				}
-			});
-		}
-	},
-
-	redirect_guest() {
-		frappe.call('erpnext.e_commerce.api.get_guest_redirect_on_action').then((res) => {
-			window.location.href = res.message || "/login";
-		});
-	},
-
-	render_empty_state() {
-		$(".page_content").append(`
-			<div class="cart-empty frappe-card">
-				<div class="cart-empty-state">
-					<img src="/assets/erpnext/images/ui-states/cart-empty-state.png" alt="Empty Cart">
-				</div>
-				<div class="cart-empty-message mt-4">${ __('Wishlist is empty !') }</p>
-			</div>
-		`);
-	}
-
-});
-
-frappe.ready(function() {
-	if (window.location.pathname !== "/wishlist") {
-		$(".wishlist").toggleClass('hidden', true);
-		wishlist.set_wishlist_count();
-	} else {
-		wishlist.bind_move_to_cart_action();
-		wishlist.bind_remove_action();
-	}
-
-});
\ No newline at end of file
diff --git a/erpnext/public/scss/erpnext-web.bundle.scss b/erpnext/public/scss/erpnext-web.bundle.scss
index 6ef1892..18d7c6c 100644
--- a/erpnext/public/scss/erpnext-web.bundle.scss
+++ b/erpnext/public/scss/erpnext-web.bundle.scss
@@ -1,2 +1 @@
-@import "./shopping_cart";
 @import "./website";
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
deleted file mode 100644
index 6ae464d..0000000
--- a/erpnext/public/scss/shopping_cart.scss
+++ /dev/null
@@ -1,1381 +0,0 @@
-@import "frappe/public/scss/common/mixins";
-
-:root {
-	--green-info: #38A160;
-	--product-bg-color: white;
-	--body-bg-color:  var(--gray-50);
-}
-
-body.product-page {
-	background: var(--body-bg-color);
-}
-
-.item-breadcrumbs {
-	.breadcrumb-container {
-		a {
-			color: var(--gray-900);
-		}
-	}
-}
-
-.carousel-control {
-	height: 42px;
-	width: 42px;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	background: white;
-	box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.08), 0px 1px 2px 1px rgba(0, 0, 0, 0.06);
-	border-radius: 100px;
-}
-
-.carousel-control-prev,
-.carousel-control-next {
-	opacity: 1;
-	width: 8%;
-
-	@media (max-width: 1200px) {
-		width: 10%;
-	}
-	@media (max-width: 768px) {
-		width: 15%;
-	}
-}
-
-.carousel-body {
-	position: absolute;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
-}
-
-.carousel-content {
-	max-width: 400px;
-	margin-left: 5rem;
-	margin-right: 5rem;
-}
-
-.card {
-	border: none;
-}
-
-.product-category-section {
-	.card:hover {
-		box-shadow: 0px 16px 45px 6px rgba(0, 0, 0, 0.08), 0px 8px 10px -10px rgba(0, 0, 0, 0.04);
-	}
-
-	.card-grid {
-		display: grid;
-		grid-gap: 15px;
-		grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
-	}
-}
-
-.no-image-item {
-	height: 340px;
-	width: 340px;
-	background: var(--gray-100);
-	border-radius: var(--border-radius);
-	font-size: 2rem;
-	color: var(--gray-500);
-	display: flex;
-	align-items: center;
-	justify-content: center;
-}
-
-.item-card-group-section {
-	.card {
-		height: 100%;
-		align-items: center;
-		justify-content: center;
-
-		&:hover {
-			box-shadow: 0px 16px 60px rgba(0, 0, 0, 0.08), 0px 8px 30px -20px rgba(0, 0, 0, 0.04);
-			transition: box-shadow 400ms;
-		}
-	}
-
-	.card:hover, .card:focus-within {
-		.btn-add-to-cart-list {
-			visibility: visible;
-		}
-		.like-action {
-			visibility: visible;
-		}
-		.btn-explore-variants {
-			visibility: visible;
-		}
-	}
-
-
-	.card-img-container {
-		height: 210px;
-		width: 100%;
-	}
-
-	.card-img {
-		max-height: 210px;
-		object-fit: contain;
-		margin-top: 1.25rem;
-	}
-
-	.no-image {
-		@include flex(flex, center, center, null);
-		height: 220px;
-		background: var(--gray-100);
-		width: 100%;
-		border-radius: var(--border-radius) var(--border-radius) 0 0;
-		font-size: 2rem;
-		color: var(--gray-500);
-	}
-
-	.no-image-list {
-		@include flex(flex, center, center, null);
-		height: 150px;
-		background: var(--gray-100);
-		border-radius: var(--border-radius);
-		font-size: 2rem;
-		color: var(--gray-500);
-		margin-top: 15px;
-		margin-bottom: 15px;
-	}
-
-	.card-body-flex {
-		display: flex;
-		flex-direction: column;
-	}
-
-	.product-title {
-		font-size: 14px;
-		color: var(--gray-800);
-		font-weight: 500;
-	}
-
-	.product-description {
-		font-size: 12px;
-		color: var(--text-color);
-		margin: 20px 0;
-		display: -webkit-box;
-		-webkit-line-clamp: 6;
-		-webkit-box-orient: vertical;
-
-		p {
-			margin-bottom: 0.5rem;
-		}
-	}
-
-	.product-category {
-		font-size: 13px;
-		color: var(--text-muted);
-		margin: var(--margin-sm) 0;
-	}
-
-	.product-price {
-		font-size: 18px;
-		font-weight: 600;
-		color: var(--text-color);
-		margin: var(--margin-sm) 0;
-		margin-bottom: auto !important;
-
-		.striked-price {
-			font-weight: 500;
-			font-size: 15px;
-			color: var(--gray-500);
-		}
-	}
-
-	.product-info-green {
-		color: var(--green-info);
-		font-weight: 600;
-	}
-
-	.item-card {
-		padding: var(--padding-sm);
-		min-width: 300px;
-	}
-
-	.wishlist-card {
-		padding: var(--padding-sm);
-		min-width: 260px;
-		.card-body-flex {
-			display: flex;
-			flex-direction: column;
-		}
-	}
-}
-
-#products-list-area, #products-grid-area {
-	padding: 0 5px;
-}
-
-.list-row {
-	background-color: white;
-	padding-bottom: 1rem;
-	padding-top: 1.5rem !important;
-	border-radius: 8px;
-	border-bottom: 1px solid var(--gray-50);
-
-	&:hover, &:focus-within {
-		box-shadow: 0px 16px 60px rgba(0, 0, 0, 0.08), 0px 8px 30px -20px rgba(0, 0, 0, 0.04);
-		transition: box-shadow 400ms;
-
-		.btn-add-to-cart-list {
-			visibility: visible;
-		}
-		.like-action-list {
-			visibility: visible;
-		}
-		.btn-explore-variants {
-			visibility: visible;
-		}
-	}
-
-	.product-code {
-		padding-top: 0 !important;
-	}
-
-	.btn-explore-variants {
-		min-width: 135px;
-		max-height: 30px;
-		float: right;
-		padding: 0.25rem 1rem;
-	}
-}
-
-[data-doctype="Item Group"],
-#page-index {
-	.page-header {
-		font-size: 20px;
-		font-weight: 700;
-		color: var(--text-color);
-	}
-
-	.filters-section {
-		.title-section {
-			border-bottom: 1px solid var(--table-border-color);
-		}
-
-		.filter-title {
-			font-weight: 500;
-		}
-
-		.clear-filters {
-			font-size: 13px;
-		}
-
-		.filter-lookup-input {
-			background-color: white;
-			border: 1px solid var(--gray-300);
-
-			&:focus {
-				border: 1px solid var(--primary);
-			}
-		}
-
-		.filter-label {
-			font-size: 11px;
-			font-weight: 600;
-			color: var(--gray-700);
-			text-transform: uppercase;
-		}
-
-		.filter-block {
-			border-bottom: 1px solid var(--table-border-color);
-		}
-
-		.checkbox {
-			.label-area {
-				font-size: 13px;
-				color: var(--gray-800);
-			}
-		}
-	}
-}
-
-.product-filter {
-	width: 14px !important;
-	height: 14px !important;
-}
-
-.discount-filter {
-	&:before {
-		width: 14px !important;
-		height: 14px !important;
-	}
-}
-
-.list-image {
-	border: none !important;
-	overflow: hidden;
-	max-height: 200px;
-	background-color: white;
-}
-
-.product-container {
-	@include card($padding: var(--padding-md));
-	background-color: var(--product-bg-color) !important;
-	min-height: fit-content;
-
-	.product-details {
-		max-width: 50%;
-
-		.btn-add-to-cart {
-			font-size: 14px;
-		}
-	}
-
-	&.item-main {
-		.product-image {
-			width: 100%;
-		}
-	}
-
-	.expand {
-		max-width: 100% !important; // expand in absence of slideshow
-	}
-
-	@media (max-width: 789px) {
-		.product-details {
-			max-width: 90% !important;
-
-			.btn-add-to-cart {
-				font-size: 14px;
-			}
-		}
-	}
-
-	.btn-add-to-wishlist {
-		svg use {
-			--icon-stroke: #F47A7A;
-		}
-	}
-
-	.btn-view-in-wishlist {
-		svg use {
-			fill: #F47A7A;
-			--icon-stroke: none;
-		}
-	}
-
-	.product-title {
-		font-size: 16px;
-		font-weight: 600;
-		color: var(--text-color);
-		padding: 0 !important;
-	}
-
-	.product-description {
-		font-size: 13px;
-		color: var(--gray-800);
-	}
-
-	.product-image {
-		border-color: var(--table-border-color) !important;
-		padding: 15px;
-
-		@media (max-width: var(--md-width)) {
-			height: 300px;
-			width: 300px;
-		}
-
-		@media (min-width: var(--lg-width)) {
-			height: 350px;
-			width: 350px;
-		}
-
-	 	img {
-			object-fit: contain;
-		}
-	}
-
-	.item-slideshow {
-
-		@media (max-width: var(--md-width)) {
-			max-height: 320px;
-		}
-
-		@media (min-width: var(--lg-width)) {
-			max-height: 430px;
-		}
-
-		overflow: auto;
-	}
-
-	.item-slideshow-image {
-		height: 4rem;
-		width: 6rem;
-		object-fit: contain;
-		padding: 0.5rem;
-		border: 1px solid var(--table-border-color);
-		border-radius: 4px;
-		cursor: pointer;
-
-		&:hover, &.active {
-			border-color: var(--primary);
-		}
-	}
-
-	.item-cart {
-		.product-price {
-			font-size: 22px;
-			color: var(--text-color);
-			font-weight: 600;
-
-			.formatted-price {
-				color: var(--text-muted);
-				font-size: 14px;
-			}
-		}
-
-		.no-stock {
-			font-size: var(--text-base);
-		}
-
-		.offers-heading {
-			font-size: 16px !important;
-			color: var(--text-color);
-			.tag-icon {
-				--icon-stroke: var(--gray-500);
-			}
-		}
-
-		.w-30-40 {
-			width: 30%;
-
-			@media (max-width: 992px) {
-				width: 40%;
-			}
-		}
-	}
-
-	.tab-content {
-		font-size: 14px;
-	}
-}
-
-// Item Recommendations
-.recommended-item-section {
-	padding-right: 0;
-
-	.recommendation-header {
-		font-size: 16px;
-		font-weight: 500
-	}
-
-	.recommendation-container {
-		padding: .5rem;
-		min-height: 0px;
-
-		.r-item-image {
-			min-height: 100px;
-			width: 40%;
-
-			.r-product-image {
-				padding: 2px 15px;
-			}
-
-			.no-image-r-item {
-				display: flex; justify-content: center;
-				background-color: var(--gray-200);
-				align-items: center;
-				color: var(--gray-400);
-				margin-top: .15rem;
-				border-radius: 6px;
-				height: 100%;
-				font-size: 24px;
-			}
-		}
-
-		.r-item-info {
-			font-size: 14px;
-			padding-right: 0;
-			padding-left: 10px;
-			width: 60%;
-
-			a {
-				color: var(--gray-800);
-				font-weight: 400;
-			}
-
-			.item-price {
-				font-size: 15px;
-				font-weight: 600;
-				color: var(--text-color);
-			}
-
-			.striked-item-price {
-				font-weight: 500;
-				color: var(--gray-500);
-			}
-		}
-	}
-}
-
-.product-code {
-	padding: .5rem 0;
-	color: var(--text-muted);
-	font-size: 14px;
-	.product-item-group {
-		padding-right: .25rem;
-		border-right: solid 1px var(--text-muted);
-	}
-
-	.product-item-code {
-		padding-left: .5rem;
-	}
-}
-
-.item-configurator-dialog {
-	.modal-body {
-		padding-bottom: var(--padding-xl);
-
-		.status-area {
-			.alert {
-				padding: var(--padding-xs) var(--padding-sm);
-				font-size: var(--text-sm);
-			}
-		}
-
-		.form-layout {
-			max-height: 50vh;
-			overflow-y: auto;
-		}
-
-		.section-body {
-			.form-column {
-				.form-group {
-					.control-label {
-						font-size: var(--text-md);
-						color: var(--gray-700);
-					}
-
-					.help-box {
-						margin-top: 2px;
-						font-size: var(--text-sm);
-					}
-				}
-			}
-		}
-	}
-}
-
-.item-group-slideshow {
-
-	.carousel-inner.rounded-carousel {
-		border-radius: var(--card-border-radius);
-	}
-}
-
-.sub-category-container {
-	padding-bottom: .5rem;
-	margin-bottom: 1.25rem;
-	border-bottom: 1px solid var(--table-border-color);
-
-	.heading {
-		color: var(--gray-500);
-	}
-}
-
-.scroll-categories {
-	.category-pill {
-		display: inline-block;
-		width: fit-content;
-		padding: 6px 12px;
-		margin-bottom: 8px;
-		background-color: #ecf5fe;
-		font-size: 14px;
-		border-radius: 18px;
-		color: var(--blue-500);
-	}
-}
-
-
-.shopping-badge {
-	position: relative;
-	top: -10px;
-	left: -12px;
-	background: var(--red-600);
-	align-items: center;
-	height: 16px;
-	font-size: 10px;
-	border-radius: 50%;
-}
-
-
-.cart-animate {
-	animation: wiggle 0.5s linear;
-}
-@keyframes wiggle {
-	8%,
-	41% {
-		transform: translateX(-10px);
-	}
-	25%,
-	58% {
-		transform: translate(10px);
-	}
-	75% {
-		transform: translate(-5px);
-	}
-	92% {
-		transform: translate(5px);
-	}
-	0%,
-	100% {
-		transform: translate(0);
-	}
-}
-
-.total-discount {
-	font-size: 14px;
-	color: var(--primary-color) !important;
-}
-
-#page-cart {
-	.shopping-cart-header {
-		font-weight: bold;
-	}
-
-	.cart-container {
-		color: var(--text-color);
-
-		.frappe-card {
-			display: flex;
-			flex-direction: column;
-			justify-content: space-between;
-			height: fit-content;
-		}
-
-		.cart-items-header {
-			font-weight: 600;
-		}
-
-		.cart-table {
-			tr {
-				margin-bottom: 1rem;
-			}
-
-			th, tr, td {
-				border-color: var(--border-color);
-				border-width: 1px;
-			}
-
-			th {
-				font-weight: normal;
-				font-size: 13px;
-				color: var(--text-muted);
-				padding: var(--padding-sm) 0;
-			}
-
-			td {
-				padding: var(--padding-sm) 0;
-				color: var(--text-color);
-			}
-
-			.cart-item-image {
-				width: 20%;
-				min-width: 100px;
-				img {
-					max-height: 112px;
-				}
-			}
-
-			.cart-items {
-				.item-title {
-					width: 80%;
-					font-size: 14px;
-					font-weight: 500;
-					color: var(--text-color);
-				}
-
-				.item-subtitle {
-					color: var(--text-muted);
-					font-size: 13px;
-				}
-
-				.item-subtotal {
-					font-size: 14px;
-					font-weight: 500;
-				}
-
-				.sm-item-subtotal {
-					font-size: 14px;
-					font-weight: 500;
-					display: none;
-
-					@media (max-width: 992px) {
-						display: unset !important;
-					}
-				}
-
-				.item-rate {
-					font-size: 13px;
-					color: var(--text-muted);
-				}
-
-				.free-tag {
-					padding: 4px 8px;
-					border-radius: 4px;
-					background-color: var(--dark-green-50);
-				}
-
-				textarea {
-					width: 80%;
-					height: 60px;
-					font-size: 14px;
-				}
-
-			}
-
-			.cart-tax-items {
-				.item-grand-total {
-					font-size: 16px;
-					font-weight: 700;
-					color: var(--text-color);
-				}
-			}
-
-			.column-sm-view {
-				@media (max-width: 992px) {
-					display: none !important;
-				}
-			}
-
-			.item-column {
-				width: 50%;
-				@media (max-width: 992px) {
-					width: 70%;
-				}
-			}
-
-			.remove-cart-item {
-				border-radius: 6px;
-				border: 1px solid var(--gray-100);
-				width: 28px;
-				height: 28px;
-				font-weight: 300;
-				color: var(--gray-700);
-				background-color: var(--gray-100);
-				float: right;
-				cursor: pointer;
-				margin-top: .25rem;
-				justify-content: center;
-			}
-
-			.remove-cart-item-logo {
-				margin-top: 2px;
-				margin-left: 2.2px;
-				fill: var(--gray-700) !important;
-			}
-		}
-
-		.cart-payment-addresses {
-			hr {
-				border-color: var(--border-color);
-			}
-		}
-
-		.payment-summary {
-			h6 {
-				padding-bottom: 1rem;
-				border-bottom: solid 1px var(--gray-200);
-			}
-
-			table {
-				font-size: 14px;
-				td {
-					padding: 0;
-					padding-top: 0.35rem !important;
-					border: none !important;
-				}
-
-				&.grand-total {
-					border-top: solid 1px var(--gray-200);
-				}
-			}
-
-			.bill-label {
-				color: var(--gray-600);
-			}
-
-			.bill-content {
-				font-weight: 500;
-				&.net-total {
-					font-size: 16px;
-					font-weight: 600;
-				}
-			}
-
-			.btn-coupon-code {
-				font-size: 14px;
-				border: dashed 1px var(--gray-400);
-				box-shadow: none;
-			}
-		}
-
-		.number-spinner {
-			width: 75%;
-			min-width: 105px;
-			.cart-btn {
-				border: none;
-				background: var(--gray-100);
-				box-shadow: none;
-				width: 24px;
-				height: 28px;
-				align-items: center;
-				justify-content: center;
-				display: flex;
-				font-size: 20px;
-				font-weight: 300;
-				color: var(--gray-700);
-			}
-
-			.cart-qty {
-				height: 28px;
-				font-size: 13px;
-				&:disabled {
-					background: var(--gray-100);
-					opacity: 0.65;
-				}
-			}
-		}
-
-		.place-order-container {
-			.btn-place-order {
-				float: right;
-			}
-		}
-	}
-
-	.t-and-c-container {
-		padding: 1.5rem;
-	}
-
-	.t-and-c-terms {
-		font-size: 14px;
-	}
-}
-
-.no-image-cart-item {
-	max-height: 112px;
-	display: flex; justify-content: center;
-	background-color: var(--gray-200);
-	align-items: center;
-	color: var(--gray-400);
-	margin-top: .15rem;
-	border-radius: 6px;
-	height: 100%;
-	font-size: 24px;
-}
-
-.cart-empty.frappe-card {
-	min-height: 76vh;
-	@include flex(flex, center, center, column);
-
-	.cart-empty-message {
-		font-size: 18px;
-		color: var(--text-color);
-		font-weight: bold;
-	}
-}
-
-.address-card {
-	.card-title {
-		font-size: 14px;
-		font-weight: 500;
-	}
-
-	.card-body {
-		max-width: 80%;
-	}
-
-	.card-text {
-		font-size: 13px;
-		color: var(--gray-700);
-	}
-
-	.card-link {
-		font-size: 13px;
-
-		svg use {
-			stroke: var(--primary-color);
-		}
-	}
-
-	.btn-change-address {
-		border: 1px solid var(--primary-color);
-		color: var(--primary-color);
-		box-shadow: none;
-	}
-}
-
-.address-header {
-	margin-top: .15rem;padding: 0;
-}
-
-.btn-new-address {
-	float: right;
-	font-size: 15px !important;
-	color: var(--primary-color) !important;
-}
-
-.btn-new-address:hover, .btn-change-address:hover {
-	color: var(--primary-color) !important;
-}
-
-.modal .address-card {
-	.card-body {
-		padding: var(--padding-sm);
-		border-radius: var(--border-radius);
-		border: 1px solid var(--dark-border-color);
-	}
-}
-
-.cart-indicator {
-	position: absolute;
-	text-align: center;
-	width: 22px;
-	height: 22px;
-	left: calc(100% - 40px);
-	top: 22px;
-
-	border-radius: 66px;
-	box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1);
-	background: white;
-	color: var(--primary-color);
-	font-size: 14px;
-
-	&.list-indicator {
-		position: unset;
-		margin-left: auto;
-	}
-}
-
-
-.like-action {
-	visibility: hidden;
-	text-align: center;
-	position: absolute;
-	cursor: pointer;
-	width: 28px;
-	height: 28px;
-	left: 20px;
-	top: 20px;
-
-	/* White */
-	background: white;
-	box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1);
-	border-radius: 66px;
-
-	&.like-action-wished {
-		visibility: visible !important;
-	}
-
-	@media (max-width: 992px) {
-		visibility: visible !important;
-	}
-}
-
-.like-action-list {
-	visibility: hidden;
-	text-align: center;
-	position: absolute;
-	cursor: pointer;
-	width: 28px;
-	height: 28px;
-	left: 20px;
-	top: 0;
-
-	/* White */
-	background: white;
-	box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1);
-	border-radius: 66px;
-
-	&.like-action-wished {
-		visibility: visible !important;
-	}
-
-	@media (max-width: 992px) {
-		visibility: visible !important;
-	}
-}
-
-.like-action-item-fp {
-	visibility: visible !important;
-	position: unset;
-	float: right;
-}
-
-.like-animate {
-	animation: expand cubic-bezier(0.04, 0.4, 0.5, 0.95) 1.6s forwards 1;
-}
-
-@keyframes expand {
-	30% {
-	  transform: scale(1.3);
-	}
-	50% {
-	  transform: scale(0.8);
-	}
-	70% {
-		transform: scale(1.1);
-	}
-	100% {
-	  transform: scale(1);
-	}
-  }
-
-.not-wished {
-	cursor: pointer;
-	--icon-stroke: #F47A7A !important;
-
-	&:hover {
-		fill: #F47A7A;
-	}
-}
-
-.wished {
-	--icon-stroke: none;
-	fill: #F47A7A !important;
-}
-
-.list-row-checkbox {
-	&:before {
-		display: none;
-	}
-
-	&:checked:before {
-		display: block;
-		z-index: 1;
-	}
-}
-
-#pay-for-order {
-	padding: .5rem 1rem; // Pay button in SO
-}
-
-.btn-explore-variants {
-	visibility: hidden;
-	box-shadow: none;
-	margin: var(--margin-sm) 0;
-	width: 90px;
-	max-height: 50px; // to avoid resizing on window resize
-	flex: none;
-	transition: 0.3s ease;
-
-	color: white;
-	background-color: var(--orange-500);
-	border: 1px solid var(--orange-500);
-	font-size: 13px;
-
-	&:hover {
-		color: white;
-	}
-}
-
-.btn-add-to-cart-list{
-	visibility: hidden;
-	box-shadow: none;
-	margin: var(--margin-sm) 0;
-	// margin-top: auto !important;
-	max-height: 50px; // to avoid resizing on window resize
-	flex: none;
-	transition: 0.3s ease;
-
-	font-size: 13px;
-
-	&:hover {
-		color: white;
-	}
-
-	@media (max-width: 992px) {
-		visibility: visible !important;
-	}
-}
-
-.go-to-cart-grid {
-	max-height: 30px;
-	margin-top: 1rem !important;
-}
-
-.go-to-cart {
-	max-height: 30px;
-	float: right;
-}
-
-.remove-wish {
-	background-color: white;
-	position: absolute;
-	cursor: pointer;
-	top:10px;
-	right: 20px;
-	width: 32px;
-	height: 32px;
-
-	border-radius: 50%;
-	border: 1px solid var(--gray-100);
-	box-shadow: 0px 2px 6px rgba(17, 43, 66, 0.08), 0px 1px 4px rgba(17, 43, 66, 0.1);
-}
-
-.wish-removed {
-	display: none;
-}
-
-.item-website-specification {
-	font-size: .875rem;
-	.product-title {
-		font-size: 18px;
-	}
-
-	.table {
-		width: 70%;
-	}
-
-	td {
-		border: none !important;
-	}
-
-	.spec-label {
-		color: var(--gray-600);
-	}
-
-	.spec-content {
-		color: var(--gray-800);
-	}
-}
-
-.reviews-full-page {
-	padding: 1rem 2rem;
-}
-
-.ratings-reviews-section {
-	border-top: 1px solid #E2E6E9;
-	padding: .5rem 1rem;
-}
-
-.reviews-header {
-	font-size: 20px;
-	font-weight: 600;
-	color: var(--gray-800);
-	display: flex;
-	align-items: center;
-	padding: 0;
-}
-
-.btn-write-review {
-	float: right;
-	padding: .5rem 1rem;
-	font-size: 14px;
-	font-weight: 400;
-	border: none !important;
-	box-shadow: none;
-
-	color: var(--gray-900);
-	background-color: var(--gray-100);
-
-	&:hover {
-		box-shadow: var(--btn-shadow);
-	}
-}
-
-.btn-view-more {
-	font-size: 14px;
-}
-
-.rating-summary-section {
-	display: flex;
-}
-
-.rating-summary-title {
-	margin-top: 0.15rem;
-	font-size: 18px;
-}
-
-.rating-summary-numbers {
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-
-	border-right: solid 1px var(--gray-100);
-}
-
-.user-review-title {
-	margin-top: 0.15rem;
-	font-size: 15px;
-	font-weight: 600;
-}
-
-.rating {
-	--star-fill: var(--gray-300);
-	.star-hover {
-		--star-fill: var(--yellow-100);
-	}
-	.star-click {
-		--star-fill: var(--yellow-300);
-	}
-}
-
-.ratings-pill {
-	background-color: var(--gray-100);
-	padding: .5rem 1rem;
-	border-radius: 66px;
-}
-
-.review {
-	max-width: 80%;
-	line-height: 1.6;
-	padding-bottom: 0.5rem;
-	border-bottom: 1px solid #E2E6E9;
-}
-
-.review-signature {
-	display: flex;
-	font-size: 13px;
-	color: var(--gray-500);
-	font-weight: 400;
-
-	.reviewer {
-		padding-right: 8px;
-		color: var(--gray-600);
-	}
-}
-
-.rating-progress-bar-section {
-	padding-bottom: 2rem;
-
-	.rating-bar-title {
-		margin-left: -15px;
-	}
-
-	.rating-progress-bar {
-		margin-bottom: 4px;
-		height: 7px;
-		margin-top: 6px;
-
-		.progress-bar-cosmetic {
-			background-color: var(--gray-600);
-			border-radius: var(--border-radius);
-		}
-	}
-}
-
-.offer-container {
-	font-size: 14px;
-}
-
-#search-results-container {
-	border: 1px solid var(--gray-200);
-	padding: .25rem 1rem;
-
-	.category-chip {
-		background-color: var(--gray-100);
-		border: none !important;
-		box-shadow: none;
-	}
-
-	.recent-search {
-		padding: .5rem .5rem;
-		border-radius: var(--border-radius);
-
-		&:hover {
-			background-color: var(--gray-100);
-		}
-	}
-}
-
-#search-box {
-	background-color: white;
-	height: 100%;
-	padding-left: 2.5rem;
-	border: 1px solid var(--gray-200);
-}
-
-.search-icon {
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 2.5rem;
-	height: 100%;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	padding-bottom: 1px;
-}
-
-#toggle-view {
-	float: right;
-
-	.btn-primary {
-		background-color: var(--gray-600);
-		box-shadow: 0 0 0 0.2rem var(--gray-400);
-	}
-}
-
-.placeholder-div {
-	height:80%;
-	width: -webkit-fill-available;
-	padding: 50px;
-	text-align: center;
-	background-color: #F9FAFA;
-	border-top-left-radius: calc(0.75rem - 1px);
-	border-top-right-radius: calc(0.75rem - 1px);
-}
-.placeholder {
-	font-size: 72px;
-}
-
-[data-path="cart"] {
-	.modal-backdrop {
-		background-color: var(--gray-50); // lighter backdrop only on cart freeze
-	}
-}
-
-.item-thumb {
-	height: 50px;
-	max-width: 80px;
-	min-width: 80px;
-	object-fit: cover;
-}
-
-.brand-line {
-	color: gray;
-}
-
-.btn-next, .btn-prev {
-	font-size: 14px;
-}
-
-.alert-error {
-	color: #e27a84;
-	background-color: #fff6f7;
-	border-color: #f5c6cb;
-}
-
-.font-md {
-	font-size: 14px !important;
-}
-
-.in-green {
-	color: var(--green-info) !important;
-	font-weight: 500;
-}
-
-.has-stock {
-	font-weight: 400 !important;
-}
-
-.out-of-stock {
-	font-weight: 400;
-	font-size: 14px;
-	line-height: 20px;
-	color: #F47A7A;
-}
-
-.mt-minus-2 {
-	margin-top: -2rem;
-}
-
-.mt-minus-1 {
-	margin-top: -1rem;
-}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 8ff681b..95d2d2c 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -26,7 +26,6 @@
 		self.set_status()
 		self.validate_uom_is_integer("stock_uom", "qty")
 		self.validate_valid_till()
-		self.validate_shopping_cart_items()
 		self.set_customer_name()
 		if self.items:
 			self.with_items = 1
@@ -42,26 +41,6 @@
 		if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date):
 			frappe.throw(_("Valid till date cannot be before transaction date"))
 
-	def validate_shopping_cart_items(self):
-		if self.order_type != "Shopping Cart":
-			return
-
-		for item in self.items:
-			has_web_item = frappe.db.exists("Website Item", {"item_code": item.item_code})
-
-			# If variant is unpublished but template is published: valid
-			template = frappe.get_cached_value("Item", item.item_code, "variant_of")
-			if template and not has_web_item:
-				has_web_item = frappe.db.exists("Website Item", {"item_code": template})
-
-			if not has_web_item:
-				frappe.throw(
-					_("Row #{0}: Item {1} must have a Website Item for Shopping Cart Quotations").format(
-						item.idx, frappe.bold(item.item_code)
-					),
-					title=_("Unpublished Item"),
-				)
-
 	def set_has_alternative_item(self):
 		"""Mark 'Has Alternative Item' for rows."""
 		if not any(row.is_alternative for row in self.get("items")):
@@ -263,8 +242,8 @@
 	return _make_sales_order(source_name, target_doc)
 
 
-def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
-	customer = _make_customer(source_name, ignore_permissions)
+def _make_sales_order(source_name, target_doc=None, customer_group=None, ignore_permissions=False):
+	customer = _make_customer(source_name, ignore_permissions, customer_group)
 	ordered_items = frappe._dict(
 		frappe.db.get_all(
 			"Sales Order Item",
@@ -428,7 +407,7 @@
 	return doclist
 
 
-def _make_customer(source_name, ignore_permissions=False):
+def _make_customer(source_name, ignore_permissions=False, customer_group=None):
 	quotation = frappe.db.get_value(
 		"Quotation", source_name, ["order_type", "party_name", "customer_name"], as_dict=1
 	)
@@ -445,10 +424,7 @@
 				customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions)
 				customer = frappe.get_doc(customer_doclist)
 				customer.flags.ignore_permissions = ignore_permissions
-				if quotation.get("party_name") == "Shopping Cart":
-					customer.customer_group = frappe.db.get_value(
-						"E Commerce Settings", None, "default_customer_group"
-					)
+				customer.customer_group = customer_group
 
 				try:
 					customer.insert()
diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py
index 5623a12..590cd3d 100644
--- a/erpnext/selling/doctype/quotation/test_quotation.py
+++ b/erpnext/selling/doctype/quotation/test_quotation.py
@@ -161,15 +161,6 @@
 
 		make_sales_order(quotation.name)
 
-	def test_shopping_cart_without_website_item(self):
-		if frappe.db.exists("Website Item", {"item_code": "_Test Item Home Desktop 100"}):
-			frappe.get_last_doc("Website Item", {"item_code": "_Test Item Home Desktop 100"}).delete()
-
-		quotation = frappe.copy_doc(test_records[0])
-		quotation.order_type = "Shopping Cart"
-		quotation.valid_till = getdate()
-		self.assertRaises(frappe.ValidationError, quotation.validate)
-
 	def test_create_quotation_with_margin(self):
 		from erpnext.selling.doctype.quotation.quotation import make_sales_order
 		from erpnext.selling.doctype.sales_order.sales_order import (
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index e6f7456..f82047f 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -68,6 +68,7 @@
   "total_weight",
   "column_break_21",
   "weight_uom",
+  "accounting_dimensions_section",
   "warehouse_and_reference",
   "warehouse",
   "target_warehouse",
@@ -889,12 +890,18 @@
    "label": "Production Plan Qty",
    "no_copy": 1,
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2023-07-28 14:56:42.031636",
+ "modified": "2023-10-17 18:18:26.475259",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order Item",
@@ -905,4 +912,4 @@
  "sort_order": "DESC",
  "states": [],
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/item_group/item_group.js b/erpnext/setup/doctype/item_group/item_group.js
index 4b04ac1..d6eb11f 100644
--- a/erpnext/setup/doctype/item_group/item_group.js
+++ b/erpnext/setup/doctype/item_group/item_group.js
@@ -71,20 +71,6 @@
 				frappe.set_route("List", "Item", {"item_group": frm.doc.name});
 			});
 		}
-
-		frappe.model.with_doctype('Website Item', () => {
-			const web_item_meta = frappe.get_meta('Website Item');
-
-			const valid_fields = web_item_meta.fields.filter(df =>
-				['Link', 'Table MultiSelect'].includes(df.fieldtype) && !df.hidden
-			).map(df =>
-				({ label: df.label, value: df.fieldname })
-			);
-
-			frm.get_field("filter_fields").grid.update_docfield_property(
-				'fieldname', 'options', valid_fields
-			);
-		});
 	},
 
 	set_root_readonly: function(frm) {
diff --git a/erpnext/setup/doctype/item_group/item_group.json b/erpnext/setup/doctype/item_group/item_group.json
index e0f5090..dfa5a8e 100644
--- a/erpnext/setup/doctype/item_group/item_group.json
+++ b/erpnext/setup/doctype/item_group/item_group.json
@@ -19,22 +19,9 @@
   "item_group_defaults",
   "sec_break_taxes",
   "taxes",
-  "sb9",
-  "route",
-  "website_title",
-  "description",
-  "show_in_website",
-  "include_descendants",
-  "column_break_16",
-  "weightage",
-  "slideshow",
-  "website_specifications",
-  "website_filters_section",
-  "filter_fields",
-  "filter_attributes",
   "lft",
-  "rgt",
-  "old_parent"
+  "old_parent",
+  "rgt"
  ],
  "fields": [
   {
@@ -107,54 +94,6 @@
    "options": "Item Tax"
   },
   {
-   "fieldname": "sb9",
-   "fieldtype": "Section Break",
-   "label": "Website Settings"
-  },
-  {
-   "default": "0",
-   "description": "Make Item Group visible in website",
-   "fieldname": "show_in_website",
-   "fieldtype": "Check",
-   "label": "Show in Website"
-  },
-  {
-   "depends_on": "show_in_website",
-   "fieldname": "route",
-   "fieldtype": "Data",
-   "label": "Route",
-   "no_copy": 1,
-   "unique": 1
-  },
-  {
-   "depends_on": "show_in_website",
-   "fieldname": "weightage",
-   "fieldtype": "Int",
-   "label": "Weightage"
-  },
-  {
-   "depends_on": "show_in_website",
-   "description": "Show this slideshow at the top of the page",
-   "fieldname": "slideshow",
-   "fieldtype": "Link",
-   "label": "Slideshow",
-   "options": "Website Slideshow"
-  },
-  {
-   "depends_on": "show_in_website",
-   "description": "HTML / Banner that will show on the top of product list.",
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "label": "Description"
-  },
-  {
-   "depends_on": "show_in_website",
-   "fieldname": "website_specifications",
-   "fieldtype": "Table",
-   "label": "Website Specifications",
-   "options": "Item Website Specification"
-  },
-  {
    "fieldname": "lft",
    "fieldtype": "Int",
    "hidden": 1,
@@ -188,43 +127,6 @@
    "options": "Item Group",
    "print_hide": 1,
    "report_hide": 1
-  },
-  {
-   "collapsible": 1,
-   "depends_on": "show_in_website",
-   "fieldname": "website_filters_section",
-   "fieldtype": "Section Break",
-   "label": "Website Filters"
-  },
-  {
-   "fieldname": "filter_fields",
-   "fieldtype": "Table",
-   "label": "Item Fields",
-   "options": "Website Filter Field"
-  },
-  {
-   "fieldname": "filter_attributes",
-   "fieldtype": "Table",
-   "label": "Attributes",
-   "options": "Website Attribute"
-  },
-  {
-   "depends_on": "show_in_website",
-   "fieldname": "website_title",
-   "fieldtype": "Data",
-   "label": "Title"
-  },
-  {
-   "fieldname": "column_break_16",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "0",
-   "depends_on": "show_in_website",
-   "description": "Include Website Items belonging to child Item Groups",
-   "fieldname": "include_descendants",
-   "fieldtype": "Check",
-   "label": "Include Descendants"
   }
  ],
  "icon": "fa fa-sitemap",
@@ -233,7 +135,7 @@
  "is_tree": 1,
  "links": [],
  "max_attachments": 3,
- "modified": "2023-08-28 22:27:48.382985",
+ "modified": "2023-10-12 13:44:13.611287",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Item Group",
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index cc67c69..fe7a241 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -2,39 +2,19 @@
 # License: GNU General Public License v3. See license.txt
 
 import copy
-from urllib.parse import quote
 
 import frappe
 from frappe import _
-from frappe.utils import cint
 from frappe.utils.nestedset import NestedSet
-from frappe.website.utils import clear_cache
-from frappe.website.website_generator import WebsiteGenerator
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import ECommerceSettings
-from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder
 
 
-class ItemGroup(NestedSet, WebsiteGenerator):
-	nsm_parent_field = "parent_item_group"
-	website = frappe._dict(
-		condition_field="show_in_website",
-		template="templates/generators/item_group.html",
-		no_cache=1,
-		no_breadcrumbs=1,
-	)
-
+class ItemGroup(NestedSet):
 	def validate(self):
-		super(ItemGroup, self).validate()
-
 		if not self.parent_item_group and not frappe.flags.in_test:
 			if frappe.db.exists("Item Group", _("All Item Groups")):
 				self.parent_item_group = _("All Item Groups")
-
-		self.make_route()
 		self.validate_item_group_defaults()
 		self.check_item_tax()
-		ECommerceSettings.validate_field_filters(self.filter_fields, enable_field_filters=True)
 
 	def check_item_tax(self):
 		"""Check whether Tax Rate is not entered twice for same Tax Type"""
@@ -53,66 +33,13 @@
 
 	def on_update(self):
 		NestedSet.on_update(self)
-		invalidate_cache_for(self)
 		self.validate_one_root()
 		self.delete_child_item_groups_key()
 
-	def make_route(self):
-		"""Make website route"""
-		if not self.route:
-			self.route = ""
-			if self.parent_item_group:
-				parent_item_group = frappe.get_doc("Item Group", self.parent_item_group)
-
-				# make parent route only if not root
-				if parent_item_group.parent_item_group and parent_item_group.route:
-					self.route = parent_item_group.route + "/"
-
-			self.route += self.scrub(self.item_group_name)
-
-			return self.route
-
 	def on_trash(self):
 		NestedSet.on_trash(self, allow_root_deletion=True)
-		WebsiteGenerator.on_trash(self)
 		self.delete_child_item_groups_key()
 
-	def get_context(self, context):
-		context.show_search = True
-		context.body_class = "product-page"
-		context.page_length = (
-			cint(frappe.db.get_single_value("E Commerce Settings", "products_per_page")) or 6
-		)
-		context.search_link = "/product_search"
-
-		filter_engine = ProductFiltersBuilder(self.name)
-
-		context.field_filters = filter_engine.get_field_filters()
-		context.attribute_filters = filter_engine.get_attribute_filters()
-
-		context.update({"parents": get_parent_item_groups(self.parent_item_group), "title": self.name})
-
-		if self.slideshow:
-			values = {"show_indicators": 1, "show_controls": 0, "rounded": 1, "slider_name": self.slideshow}
-			slideshow = frappe.get_doc("Website Slideshow", self.slideshow)
-			slides = slideshow.get({"doctype": "Website Slideshow Item"})
-			for index, slide in enumerate(slides):
-				values[f"slide_{index + 1}_image"] = slide.image
-				values[f"slide_{index + 1}_title"] = slide.heading
-				values[f"slide_{index + 1}_subtitle"] = slide.description
-				values[f"slide_{index + 1}_theme"] = slide.get("theme") or "Light"
-				values[f"slide_{index + 1}_content_align"] = slide.get("content_align") or "Centre"
-				values[f"slide_{index + 1}_primary_action"] = slide.url
-
-			context.slideshow = values
-
-		context.no_breadcrumbs = False
-		context.title = self.website_title or self.name
-		context.name = self.name
-		context.item_group_name = self.item_group_name
-
-		return context
-
 	def delete_child_item_groups_key(self):
 		frappe.cache().hdel("child_item_groups", self.name)
 
@@ -122,20 +49,6 @@
 		validate_item_default_company_links(self.item_group_defaults)
 
 
-def get_child_groups_for_website(item_group_name, immediate=False, include_self=False):
-	"""Returns child item groups *excluding* passed group."""
-	item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
-	filters = {"lft": [">", item_group.lft], "rgt": ["<", item_group.rgt], "show_in_website": 1}
-
-	if immediate:
-		filters["parent_item_group"] = item_group_name
-
-	if include_self:
-		filters.update({"lft": [">=", item_group.lft], "rgt": ["<=", item_group.rgt]})
-
-	return frappe.get_all("Item Group", filters=filters, fields=["name", "route"], order_by="name")
-
-
 def get_child_item_groups(item_group_name):
 	item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
 
@@ -149,63 +62,6 @@
 	return child_item_groups or {}
 
 
-def get_item_for_list_in_html(context):
-	# add missing absolute link in files
-	# user may forget it during upload
-	if (context.get("website_image") or "").startswith("files/"):
-		context["website_image"] = "/" + quote(context["website_image"])
-
-	products_template = "templates/includes/products_as_list.html"
-
-	return frappe.get_template(products_template).render(context)
-
-
-def get_parent_item_groups(item_group_name, from_item=False):
-	settings = frappe.get_cached_doc("E Commerce Settings")
-
-	if settings.enable_field_filters:
-		base_nav_page = {"name": _("Shop by Category"), "route": "/shop-by-category"}
-	else:
-		base_nav_page = {"name": _("All Products"), "route": "/all-products"}
-
-	if from_item and frappe.request.environ.get("HTTP_REFERER"):
-		# base page after 'Home' will vary on Item page
-		last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1].split("?")[0]
-		if last_page and last_page in ("shop-by-category", "all-products"):
-			base_nav_page_title = " ".join(last_page.split("-")).title()
-			base_nav_page = {"name": _(base_nav_page_title), "route": "/" + last_page}
-
-	base_parents = [
-		{"name": _("Home"), "route": "/"},
-		base_nav_page,
-	]
-
-	if not item_group_name:
-		return base_parents
-
-	item_group = frappe.db.get_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
-	parent_groups = frappe.db.sql(
-		"""select name, route from `tabItem Group`
-		where lft <= %s and rgt >= %s
-		and show_in_website=1
-		order by lft asc""",
-		(item_group.lft, item_group.rgt),
-		as_dict=True,
-	)
-
-	return base_parents + parent_groups
-
-
-def invalidate_cache_for(doc, item_group=None):
-	if not item_group:
-		item_group = doc.name
-
-	for d in get_parent_item_groups(item_group):
-		item_group_name = frappe.db.get_value("Item Group", d.get("name"))
-		if item_group_name:
-			clear_cache(frappe.db.get_value("Item Group", item_group_name, "route"))
-
-
 def get_item_group_defaults(item, company):
 	item = frappe.get_cached_doc("Item", item)
 	item_group = frappe.get_cached_doc("Item Group", item.item_group)
diff --git a/erpnext/setup/setup_wizard/operations/company_setup.py b/erpnext/setup/setup_wizard/operations/company_setup.py
index ace5cca..d4aac5e 100644
--- a/erpnext/setup/setup_wizard/operations/company_setup.py
+++ b/erpnext/setup/setup_wizard/operations/company_setup.py
@@ -33,20 +33,6 @@
 		).insert()
 
 
-def enable_shopping_cart(args):  # nosemgrep
-	# Needs price_lists
-	frappe.get_doc(
-		{
-			"doctype": "E Commerce Settings",
-			"enabled": 1,
-			"company": args.get("company_name"),
-			"price_list": frappe.db.get_value("Price List", {"selling": 1}),
-			"default_customer_group": _("Individual"),
-			"quotation_series": "QTN-",
-		}
-	).insert()
-
-
 def get_fy_details(fy_start_date, fy_end_date):
 	start_year = getdate(fy_start_date).year
 	if start_year == getdate(fy_end_date).year:
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index ae6881b..2205924 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -454,7 +454,6 @@
 
 	set_global_defaults(args)
 	update_stock_settings()
-	update_shopping_cart_settings(args)
 
 	args.update({"set_default": 1})
 	create_bank_account(args)
@@ -529,20 +528,6 @@
 			pass
 
 
-def update_shopping_cart_settings(args):  # nosemgrep
-	shopping_cart = frappe.get_doc("E Commerce Settings")
-	shopping_cart.update(
-		{
-			"enabled": 1,
-			"company": args.company_name,
-			"price_list": frappe.db.get_value("Price List", {"selling": 1}),
-			"default_customer_group": _("Individual"),
-			"quotation_series": "QTN-",
-		}
-	)
-	shopping_cart.update_single(shopping_cart.get_valid_dict())
-
-
 def get_fy_details(fy_start_date, fy_end_date):
 	start_year = getdate(fy_start_date).year
 	if start_year == getdate(fy_end_date).year:
diff --git a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
index 5806fd1..2f9cec4 100644
--- a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
+++ b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
@@ -1,500 +1,500 @@
 {
- "charts": [],
- "content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t</b></span>\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}},{\"id\":\"R3CoYYFXye\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yynbm1J_VO\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Settings</b></span>\",\"col\":12}},{\"id\":\"KDCv2MvSg3\",\"type\":\"card\",\"data\":{\"card_name\":\"Module Settings\",\"col\":4}},{\"id\":\"Q0_bqT7cxQ\",\"type\":\"card\",\"data\":{\"card_name\":\"Email / Notifications\",\"col\":4}},{\"id\":\"UnqK5haBnh\",\"type\":\"card\",\"data\":{\"card_name\":\"Website\",\"col\":4}},{\"id\":\"kp7u1H5hCd\",\"type\":\"card\",\"data\":{\"card_name\":\"Core\",\"col\":4}},{\"id\":\"Ufc3jycgy9\",\"type\":\"card\",\"data\":{\"card_name\":\"Printing\",\"col\":4}},{\"id\":\"89bSNzv3Yh\",\"type\":\"card\",\"data\":{\"card_name\":\"Workflow\",\"col\":4}}]",
- "creation": "2022-01-27 13:14:47.349433",
- "custom_blocks": [],
- "docstatus": 0,
- "doctype": "Workspace",
- "for_user": "",
- "hide_custom": 0,
- "icon": "setting",
- "idx": 0,
- "is_hidden": 0,
- "label": "ERPNext Settings",
- "links": [
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Import Data",
-   "link_count": 0,
-   "link_to": "Data Import",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Export Data",
-   "link_count": 0,
-   "link_to": "Data Export",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Bulk Update",
-   "link_count": 0,
-   "link_to": "Bulk Update",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Download Backups",
-   "link_count": 0,
-   "link_to": "backups",
-   "link_type": "Page",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Deleted Documents",
-   "link_count": 0,
-   "link_to": "Deleted Document",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Email / Notifications",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Email Account",
-   "link_count": 0,
-   "link_to": "Email Account",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Email Domain",
-   "link_count": 0,
-   "link_to": "Email Domain",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Notification",
-   "link_count": 0,
-   "link_to": "Notification",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Email Template",
-   "link_count": 0,
-   "link_to": "Email Template",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Auto Email Report",
-   "link_count": 0,
-   "link_to": "Auto Email Report",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Newsletter",
-   "link_count": 0,
-   "link_to": "Newsletter",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Notification Settings",
-   "link_count": 0,
-   "link_to": "Notification Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Website",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Website Settings",
-   "link_count": 0,
-   "link_to": "Website Settings",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Website Theme",
-   "link_count": 0,
-   "link_to": "Website Theme",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Website Script",
-   "link_count": 0,
-   "link_to": "Website Script",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "About Us Settings",
-   "link_count": 0,
-   "link_to": "About Us Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Contact Us Settings",
-   "link_count": 0,
-   "link_to": "Contact Us Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Printing",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Print Format Builder",
-   "link_count": 0,
-   "link_to": "print-format-builder",
-   "link_type": "Page",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Print Settings",
-   "link_count": 0,
-   "link_to": "Print Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Print Format",
-   "link_count": 0,
-   "link_to": "Print Format",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Print Style",
-   "link_count": 0,
-   "link_to": "Print Style",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Workflow",
-   "link_count": 0,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Workflow",
-   "link_count": 0,
-   "link_to": "Workflow",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Workflow State",
-   "link_count": 0,
-   "link_to": "Workflow State",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Workflow Action",
-   "link_count": 0,
-   "link_to": "Workflow Action",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Core",
-   "link_count": 3,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "System Settings",
-   "link_count": 0,
-   "link_to": "System Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Domain Settings",
-   "link_count": 0,
-   "link_to": "Domain Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Global Defaults",
-   "link_count": 0,
-   "link_to": "Global Defaults",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Module Settings",
-   "link_count": 8,
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Accounts Settings",
-   "link_count": 0,
-   "link_to": "Accounts Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Stock Settings",
-   "link_count": 0,
-   "link_to": "Stock Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Selling Settings",
-   "link_count": 0,
-   "link_to": "Selling Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Buying Settings",
-   "link_count": 0,
-   "link_to": "Buying Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Manufacturing Settings",
-   "link_count": 0,
-   "link_to": "Manufacturing Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "CRM Settings",
-   "link_count": 0,
-   "link_to": "CRM Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Projects Settings",
-   "link_count": 0,
-   "link_to": "Projects Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Support Settings",
-   "link_count": 0,
-   "link_to": "Support Settings",
-   "link_type": "DocType",
-   "onboard": 0,
-   "type": "Link"
-  }
- ],
- "modified": "2023-05-24 14:47:25.356531",
- "modified_by": "Administrator",
- "module": "Setup",
- "name": "ERPNext Settings",
- "number_cards": [],
- "owner": "Administrator",
- "parent_page": "",
- "public": 1,
- "quick_lists": [],
- "restrict_to_domain": "",
- "roles": [],
- "sequence_id": 19.0,
- "shortcuts": [
-  {
-   "color": "Grey",
-   "doc_view": "List",
-   "label": "Print Settings",
-   "link_to": "Print Settings",
-   "type": "DocType"
-  },
-  {
-   "color": "Grey",
-   "doc_view": "List",
-   "label": "System Settings",
-   "link_to": "System Settings",
-   "type": "DocType"
-  },
-  {
-   "icon": "accounting",
-   "label": "Accounts Settings",
-   "link_to": "Accounts Settings",
-   "type": "DocType"
-  },
-  {
-   "color": "Grey",
-   "doc_view": "List",
-   "label": "Global Defaults",
-   "link_to": "Global Defaults",
-   "type": "DocType"
-  },
-  {
-   "icon": "stock",
-   "label": "Stock Settings",
-   "link_to": "Stock Settings",
-   "type": "DocType"
-  },
-  {
-   "icon": "sell",
-   "label": "Selling Settings",
-   "link_to": "Selling Settings",
-   "type": "DocType"
-  },
-  {
-   "icon": "buying",
-   "label": "Buying Settings",
-   "link_to": "Buying Settings",
-   "type": "DocType"
-  }
- ],
- "title": "ERPNext Settings"
-}
\ No newline at end of file
+   "charts": [],
+   "content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t</b></span>\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}},{\"id\":\"R3CoYYFXye\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yynbm1J_VO\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Settings</b></span>\",\"col\":12}},{\"id\":\"KDCv2MvSg3\",\"type\":\"card\",\"data\":{\"card_name\":\"Module Settings\",\"col\":4}},{\"id\":\"Q0_bqT7cxQ\",\"type\":\"card\",\"data\":{\"card_name\":\"Email / Notifications\",\"col\":4}},{\"id\":\"UnqK5haBnh\",\"type\":\"card\",\"data\":{\"card_name\":\"Website\",\"col\":4}},{\"id\":\"kp7u1H5hCd\",\"type\":\"card\",\"data\":{\"card_name\":\"Core\",\"col\":4}},{\"id\":\"Ufc3jycgy9\",\"type\":\"card\",\"data\":{\"card_name\":\"Printing\",\"col\":4}},{\"id\":\"89bSNzv3Yh\",\"type\":\"card\",\"data\":{\"card_name\":\"Workflow\",\"col\":4}}]",
+   "creation": "2022-01-27 13:14:47.349433",
+   "custom_blocks": [],
+   "docstatus": 0,
+   "doctype": "Workspace",
+   "for_user": "",
+   "hide_custom": 0,
+   "icon": "setting",
+   "idx": 0,
+   "is_hidden": 0,
+   "label": "ERPNext Settings",
+   "links": [
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Import Data",
+     "link_count": 0,
+     "link_to": "Data Import",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Export Data",
+     "link_count": 0,
+     "link_to": "Data Export",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Bulk Update",
+     "link_count": 0,
+     "link_to": "Bulk Update",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Download Backups",
+     "link_count": 0,
+     "link_to": "backups",
+     "link_type": "Page",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Deleted Documents",
+     "link_count": 0,
+     "link_to": "Deleted Document",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Email / Notifications",
+     "link_count": 0,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Email Account",
+     "link_count": 0,
+     "link_to": "Email Account",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Email Domain",
+     "link_count": 0,
+     "link_to": "Email Domain",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Notification",
+     "link_count": 0,
+     "link_to": "Notification",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Email Template",
+     "link_count": 0,
+     "link_to": "Email Template",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Auto Email Report",
+     "link_count": 0,
+     "link_to": "Auto Email Report",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Newsletter",
+     "link_count": 0,
+     "link_to": "Newsletter",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Notification Settings",
+     "link_count": 0,
+     "link_to": "Notification Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Website",
+     "link_count": 0,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Website Settings",
+     "link_count": 0,
+     "link_to": "Website Settings",
+     "link_type": "DocType",
+     "onboard": 1,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Website Theme",
+     "link_count": 0,
+     "link_to": "Website Theme",
+     "link_type": "DocType",
+     "onboard": 1,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Website Script",
+     "link_count": 0,
+     "link_to": "Website Script",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "About Us Settings",
+     "link_count": 0,
+     "link_to": "About Us Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Contact Us Settings",
+     "link_count": 0,
+     "link_to": "Contact Us Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Printing",
+     "link_count": 0,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Print Format Builder",
+     "link_count": 0,
+     "link_to": "print-format-builder",
+     "link_type": "Page",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Print Settings",
+     "link_count": 0,
+     "link_to": "Print Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Print Format",
+     "link_count": 0,
+     "link_to": "Print Format",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Print Style",
+     "link_count": 0,
+     "link_to": "Print Style",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Workflow",
+     "link_count": 0,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Workflow",
+     "link_count": 0,
+     "link_to": "Workflow",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Workflow State",
+     "link_count": 0,
+     "link_to": "Workflow State",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Workflow Action",
+     "link_count": 0,
+     "link_to": "Workflow Action",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Core",
+     "link_count": 3,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "System Settings",
+     "link_count": 0,
+     "link_to": "System Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "dependencies": "",
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Domain Settings",
+     "link_count": 0,
+     "link_to": "Domain Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Global Defaults",
+     "link_count": 0,
+     "link_to": "Global Defaults",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Module Settings",
+     "link_count": 8,
+     "onboard": 0,
+     "type": "Card Break"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Accounts Settings",
+     "link_count": 0,
+     "link_to": "Accounts Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Stock Settings",
+     "link_count": 0,
+     "link_to": "Stock Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Selling Settings",
+     "link_count": 0,
+     "link_to": "Selling Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Buying Settings",
+     "link_count": 0,
+     "link_to": "Buying Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Manufacturing Settings",
+     "link_count": 0,
+     "link_to": "Manufacturing Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "CRM Settings",
+     "link_count": 0,
+     "link_to": "CRM Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Projects Settings",
+     "link_count": 0,
+     "link_to": "Projects Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    },
+    {
+     "hidden": 0,
+     "is_query_report": 0,
+     "label": "Support Settings",
+     "link_count": 0,
+     "link_to": "Support Settings",
+     "link_type": "DocType",
+     "onboard": 0,
+     "type": "Link"
+    }
+   ],
+   "modified": "2023-05-24 14:47:25.356531",
+   "modified_by": "Administrator",
+   "module": "Setup",
+   "name": "ERPNext Settings",
+   "number_cards": [],
+   "owner": "Administrator",
+   "parent_page": "",
+   "public": 1,
+   "quick_lists": [],
+   "restrict_to_domain": "",
+   "roles": [],
+   "sequence_id": 19.0,
+   "shortcuts": [
+    {
+     "color": "Grey",
+     "doc_view": "List",
+     "label": "Print Settings",
+     "link_to": "Print Settings",
+     "type": "DocType"
+    },
+    {
+     "color": "Grey",
+     "doc_view": "List",
+     "label": "System Settings",
+     "link_to": "System Settings",
+     "type": "DocType"
+    },
+    {
+     "icon": "accounting",
+     "label": "Accounts Settings",
+     "link_to": "Accounts Settings",
+     "type": "DocType"
+    },
+    {
+     "color": "Grey",
+     "doc_view": "List",
+     "label": "Global Defaults",
+     "link_to": "Global Defaults",
+     "type": "DocType"
+    },
+    {
+     "icon": "stock",
+     "label": "Stock Settings",
+     "link_to": "Stock Settings",
+     "type": "DocType"
+    },
+    {
+     "icon": "sell",
+     "label": "Selling Settings",
+     "link_to": "Selling Settings",
+     "type": "DocType"
+    },
+    {
+     "icon": "buying",
+     "label": "Buying Settings",
+     "link_to": "Buying Settings",
+     "type": "DocType"
+    }
+   ],
+   "title": "ERPNext Settings"
+  }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 4ae9bf5..6e810e5 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -125,36 +125,6 @@
 			erpnext.toggle_naming_series();
 		}
 
-		if (!frm.doc.published_in_website) {
-			frm.add_custom_button(__("Publish in Website"), function() {
-				frappe.call({
-					method: "erpnext.e_commerce.doctype.website_item.website_item.make_website_item",
-					args: {doc: frm.doc},
-					freeze: true,
-					freeze_message: __("Publishing Item ..."),
-					callback: function(result) {
-						frappe.msgprint({
-							message: __("Website Item {0} has been created.",
-								[repl('<a href="/app/website-item/%(item_encoded)s" class="strong">%(item)s</a>', {
-									item_encoded: encodeURIComponent(result.message[0]),
-									item: result.message[1]
-								})]
-							),
-							title: __("Published"),
-							indicator: "green"
-						});
-					}
-				});
-			}, __('Actions'));
-		} else {
-			frm.add_custom_button(__("Website Item"), function() {
-				frappe.db.get_value("Website Item", {item_code: frm.doc.name}, "name", (d) => {
-					if (!d.name) frappe.throw(__("Website Item not found"));
-					frappe.set_route("Form", "Website Item", d.name);
-				});
-			}, __("View"));
-		}
-
 		erpnext.item.edit_prices_button(frm);
 		erpnext.item.toggle_attributes(frm);
 
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 1bcddfa..54491bb 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -117,7 +117,6 @@
   "customer_code",
   "default_item_manufacturer",
   "default_manufacturer_part_no",
-  "published_in_website",
   "total_projected_qty"
  ],
  "fields": [
@@ -816,14 +815,6 @@
    "read_only": 1
   },
   {
-   "default": "0",
-   "depends_on": "published_in_website",
-   "fieldname": "published_in_website",
-   "fieldtype": "Check",
-   "label": "Published in Website",
-   "read_only": 1
-  },
-  {
    "default": "1",
    "fieldname": "grant_commission",
    "fieldtype": "Check",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index aff9587..9e28199 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -32,7 +32,6 @@
 	make_variant_item_code,
 	validate_item_variant_attributes,
 )
-from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for
 from erpnext.stock.doctype.item_default.item_default import ItemDefault
 
 
@@ -122,10 +121,8 @@
 			self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
 
 	def on_update(self):
-		invalidate_cache_for_item(self)
 		self.update_variants()
 		self.update_item_price()
-		self.update_website_item()
 
 	def validate_description(self):
 		"""Clean HTML description if set"""
@@ -248,29 +245,6 @@
 		if self.stock_uom not in uoms_list:
 			self.append("uoms", {"uom": self.stock_uom, "conversion_factor": 1})
 
-	def update_website_item(self):
-		"""Update Website Item if change in Item impacts it."""
-		web_item = frappe.db.exists("Website Item", {"item_code": self.item_code})
-
-		if web_item:
-			changed = {}
-			editable_fields = ["item_name", "item_group", "stock_uom", "brand", "description", "disabled"]
-			doc_before_save = self.get_doc_before_save()
-
-			for field in editable_fields:
-				if doc_before_save.get(field) != self.get(field):
-					if field == "disabled":
-						changed["published"] = not self.get(field)
-					else:
-						changed[field] = self.get(field)
-
-			if not changed:
-				return
-
-			web_item_doc = frappe.get_doc("Website Item", web_item)
-			web_item_doc.update(changed)
-			web_item_doc.save()
-
 	def validate_item_tax_net_rate_range(self):
 		for tax in self.get("taxes"):
 			if flt(tax.maximum_net_rate) < flt(tax.minimum_net_rate):
@@ -454,7 +428,6 @@
 		if merge:
 			self.validate_properties_before_merge(new_name)
 			self.validate_duplicate_product_bundles_before_merge(old_name, new_name)
-			self.validate_duplicate_website_item_before_merge(old_name, new_name)
 			self.delete_old_bins(old_name)
 
 	def after_rename(self, old_name, new_name, merge):
@@ -466,9 +439,6 @@
 				title=_("Note"),
 			)
 
-		if self.published_in_website:
-			invalidate_cache_for_item(self)
-
 		frappe.db.set_value("Item", new_name, "item_code", new_name)
 
 		if merge:
@@ -554,27 +524,6 @@
 			)
 			frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError)
 
-	def validate_duplicate_website_item_before_merge(self, old_name, new_name):
-		"""
-		Block merge if both old and new items have website items against them.
-		This is to avoid duplicate website items after merging.
-		"""
-		web_items = frappe.get_all(
-			"Website Item",
-			filters={"item_code": ["in", [old_name, new_name]]},
-			fields=["item_code", "name"],
-		)
-
-		if len(web_items) <= 1:
-			return
-
-		old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0]
-		web_item_link = get_link_to_form("Website Item", old_web_item)
-		old_name, new_name = frappe.bold(old_name), frappe.bold(new_name)
-
-		msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} into {new_name}"
-		frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError)
-
 	def set_last_purchase_rate(self, new_name):
 		last_purchase_rate = get_last_purchase_details(new_name).get("base_net_rate", 0)
 		frappe.db.set_value("Item", new_name, "last_purchase_rate", last_purchase_rate)
@@ -1151,32 +1100,6 @@
 	return out
 
 
-def invalidate_cache_for_item(doc):
-	"""Invalidate Item Group cache and rebuild ItemVariantsCacheManager."""
-	invalidate_cache_for(doc, doc.item_group)
-
-	if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group:
-		invalidate_cache_for(doc, doc.old_item_group)
-
-	invalidate_item_variants_cache_for_website(doc)
-
-
-def invalidate_item_variants_cache_for_website(doc):
-	"""Rebuild ItemVariantsCacheManager via Item or Website Item."""
-	from erpnext.e_commerce.variant_selector.item_variants_cache import ItemVariantsCacheManager
-
-	item_code = None
-	is_web_item = doc.get("published_in_website") or doc.get("published")
-	if doc.has_variants and is_web_item:
-		item_code = doc.item_code
-	elif doc.variant_of and frappe.db.get_value("Item", doc.variant_of, "published_in_website"):
-		item_code = doc.variant_of
-
-	if item_code:
-		item_cache = ItemVariantsCacheManager(item_code)
-		item_cache.rebuild_cache()
-
-
 def check_stock_uom_with_bin(item, stock_uom):
 	if stock_uom == frappe.db.get_value("Item", item, "stock_uom"):
 		return
diff --git a/erpnext/stock/doctype/item/item_dashboard.py b/erpnext/stock/doctype/item/item_dashboard.py
index 34bb4d1..88ae34f 100644
--- a/erpnext/stock/doctype/item/item_dashboard.py
+++ b/erpnext/stock/doctype/item/item_dashboard.py
@@ -32,6 +32,5 @@
 			{"label": _("Manufacture"), "items": ["Production Plan", "Work Order", "Item Manufacturer"]},
 			{"label": _("Traceability"), "items": ["Serial No", "Batch"]},
 			{"label": _("Stock Movement"), "items": ["Stock Entry", "Stock Reconciliation"]},
-			{"label": _("E-commerce"), "items": ["Website Item"]},
 		],
 	}
diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py
index e77d53a..21c0f18 100644
--- a/erpnext/stock/doctype/price_list/price_list.py
+++ b/erpnext/stock/doctype/price_list/price_list.py
@@ -13,9 +13,6 @@
 		if not cint(self.buying) and not cint(self.selling):
 			throw(_("Price List must be applicable for Buying or Selling"))
 
-		if not self.is_new():
-			self.check_impact_on_shopping_cart()
-
 	def on_update(self):
 		self.set_default_if_missing()
 		self.update_item_price()
@@ -37,19 +34,6 @@
 			(self.currency, cint(self.buying), cint(self.selling), self.name),
 		)
 
-	def check_impact_on_shopping_cart(self):
-		"Check if Price List currency change impacts E Commerce Cart."
-		from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-			validate_cart_settings,
-		)
-
-		doc_before_save = self.get_doc_before_save()
-		currency_changed = self.currency != doc_before_save.currency
-		affects_cart = self.name == frappe.db.get_single_value("E Commerce Settings", "price_list")
-
-		if currency_changed and affects_cart:
-			validate_cart_settings()
-
 	def on_trash(self):
 		self.delete_price_list_details_key()
 
diff --git a/erpnext/templates/generators/item/item.html b/erpnext/templates/generators/item/item.html
deleted file mode 100644
index 358c1c5..0000000
--- a/erpnext/templates/generators/item/item.html
+++ /dev/null
@@ -1,80 +0,0 @@
-{% extends "templates/web.html" %}
-{% from "erpnext/templates/includes/macros.html" import recommended_item_row %}
-
-{% block title %} {{ title }} {% endblock %}
-
-{% block breadcrumbs %}
-<div class="item-breadcrumbs small text-muted">
-	{% include "templates/includes/breadcrumbs.html" %}
-</div>
-{% endblock %}
-
-{% block page_content %}
-<div class="product-container item-main">
-	{% from "erpnext/templates/includes/macros.html" import product_image %}
-	<div class="item-content">
-		<div class="product-page-content" itemscope itemtype="http://schema.org/Product">
-			<!-- Image, Description, Add to Cart -->
-			<div class="row mb-5">
-				{% include "templates/generators/item/item_image.html" %}
-				{% include "templates/generators/item/item_details.html" %}
-			</div>
-		</div>
-	</div>
-</div>
-
-<!-- Additional Info/Reviews, Recommendations -->
-<div class="d-flex">
-	{% set show_recommended_items = recommended_items and shopping_cart.cart_settings.enable_recommendations %}
-	{% set info_col = 'col-9' if show_recommended_items else 'col-12' %}
-
-	{% set padding_top = 'pt-0' if (show_tabs and tabs) else '' %}
-
-	<div class="product-container mt-4 {{ padding_top }} {{ info_col }}">
-		<div class="item-content {{ 'mt-minus-2' if (show_tabs and tabs) else '' }}">
-			<div class="product-page-content">
-				<!-- Product Specifications Table Section -->
-				{% if show_tabs and tabs %}
-					<div class="category-tabs">
-						<!-- tabs -->
-							{{ web_block("Section with Tabs", values=tabs, add_container=0,
-								add_top_padding=0, add_bottom_padding=0)
-							}}
-					</div>
-				{% elif website_specifications %}
-					{% include "templates/generators/item/item_specifications.html"%}
-				{% endif %}
-
-				<!-- Advanced Custom Website Content -->
-				{{ doc.website_content or '' }}
-
-				<!-- Reviews and Comments -->
-				{% if shopping_cart.cart_settings.enable_reviews and not doc.has_variants %}
-					{% include "templates/generators/item/item_reviews.html"%}
-				{% endif %}
-			</div>
-		</div>
-	</div>
-
-	<!-- Recommended Items -->
-	{% if show_recommended_items %}
-		<div class="mt-4 col-3 recommended-item-section">
-			<span class="recommendation-header">Recommended</span>
-			<div class="product-container mt-2 recommendation-container">
-				{% for item in recommended_items %}
-					{{ recommended_item_row(item) }}
-				{% endfor %}
-			</div>
-		</div>
-	{% endif %}
-
-</div>
-{% endblock %}
-
-{% block base_scripts %}
-<!-- js should be loaded in body! -->
-<script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script>
-{{ include_script("frappe-web.bundle.js") }}
-{{ include_script("controls.bundle.js") }}
-{{ include_script("dialog.bundle.js") }}
-{% endblock %}
diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html
deleted file mode 100644
index 9bd3f75..0000000
--- a/erpnext/templates/generators/item/item_add_to_cart.html
+++ /dev/null
@@ -1,180 +0,0 @@
-{% if shopping_cart and shopping_cart.cart_settings.enabled %}
-
-{% set cart_settings = shopping_cart.cart_settings %}
-{% set product_info = shopping_cart.product_info %}
-
-<div class="item-cart row mt-2" data-variant-item-code="{{ item_code }}">
-	<div class="col-md-12">
-		<!-- Price and Availability -->
-		{% if cart_settings.show_price and product_info.price %}
-			{% set price_info = product_info.price %}
-
-			<div class="product-price">
-				<!-- Final Price -->
-				<span itemprop="offers" itemscope itemtype="https://schema.org/Offer">
-					<span itemprop="price" content="{{ price_info.price_list_rate }}">{{ price_info.formatted_price_sales_uom }}</span>
-					<span style="display:none;" itemprop="priceCurrency" content="{{ price_info.currency }}">{{ price_info.currency }}</span>
-				</span>
-
-				<!-- Striked Price and Discount  -->
-				{% if price_info.formatted_mrp %}
-					<small class="formatted-price">
-						<s>MRP {{ price_info.formatted_mrp }}</s>
-					</small>
-					<small class="ml-1 formatted-price in-green">
-						-{{ price_info.get("formatted_discount_percent") or price_info.get("formatted_discount_rate")}}
-					</small>
-				{% endif %}
-
-				<!-- Price per UOM -->
-				<small class="formatted-price ml-2">
-					({{ price_info.formatted_price }} / {{ product_info.uom }})
-				</small>
-			</div>
-		{% else %}
-			{{ _("UOM") }} : {{ product_info.uom }}
-		{% endif %}
-
-		{% if cart_settings.show_stock_availability %}
-		<div class="mt-2">
-			{% if product_info.get("on_backorder") %}
-				<span class="no-stock out-of-stock" style="color: var(--primary-color);">
-					{{ _('Available on backorder') }}
-				</span>
-			{% elif product_info.in_stock == 0 %}
-				<span class="no-stock out-of-stock">
-					{{ _('Out of stock') }}
-				</span>
-			{% elif product_info.in_stock == 1 %}
-				<span class="in-green has-stock">
-					{{ _('In stock') }}
-					{% if product_info.show_stock_qty and product_info.stock_qty %}
-						({{ product_info.stock_qty }})
-					{% endif %}
-				</span>
-			{% endif %}
-		</div>
-		{% endif %}
-
-		<!-- Offers -->
-		{% if doc.offers %}
-			<br>
-			<div class="offers-heading mb-4">
-				<span class="mr-1 tag-icon">
-					<svg class="icon icon-lg"><use href="#icon-tag"></use></svg>
-				</span>
-				<b>Available Offers</b>
-			</div>
-			<div class="offer-container">
-				{% for offer in doc.offers %}
-				<div class="mt-2 d-flex">
-					<div class="mr-2" >
-						<svg width="24" height="24" viewBox="0 0 24 24" stroke="var(--yellow-500)" fill="none" xmlns="http://www.w3.org/2000/svg">
-							<path d="M19 15.6213C19 15.2235 19.158 14.842 19.4393 14.5607L20.9393 13.0607C21.5251 12.4749 21.5251 11.5251 20.9393 10.9393L19.4393 9.43934C19.158 9.15804 19 8.7765 19 8.37868V6.5C19 5.67157 18.3284 5 17.5 5H15.6213C15.2235 5 14.842 4.84196 14.5607 4.56066L13.0607 3.06066C12.4749 2.47487 11.5251 2.47487 10.9393 3.06066L9.43934 4.56066C9.15804 4.84196 8.7765 5 8.37868 5H6.5C5.67157 5 5 5.67157 5 6.5V8.37868C5 8.7765 4.84196 9.15804 4.56066 9.43934L3.06066 10.9393C2.47487 11.5251 2.47487 12.4749 3.06066 13.0607L4.56066 14.5607C4.84196 14.842 5 15.2235 5 15.6213V17.5C5 18.3284 5.67157 19 6.5 19H8.37868C8.7765 19 9.15804 19.158 9.43934 19.4393L10.9393 20.9393C11.5251 21.5251 12.4749 21.5251 13.0607 20.9393L14.5607 19.4393C14.842 19.158 15.2235 19 15.6213 19H17.5C18.3284 19 19 18.3284 19 17.5V15.6213Z" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-							<path d="M15 9L9 15" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-							<path d="M10.5 9.5C10.5 10.0523 10.0523 10.5 9.5 10.5C8.94772 10.5 8.5 10.0523 8.5 9.5C8.5 8.94772 8.94772 8.5 9.5 8.5C10.0523 8.5 10.5 8.94772 10.5 9.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
-							<path d="M15.5 14.5C15.5 15.0523 15.0523 15.5 14.5 15.5C13.9477 15.5 13.5 15.0523 13.5 14.5C13.5 13.9477 13.9477 13.5 14.5 13.5C15.0523 13.5 15.5 13.9477 15.5 14.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
-						</svg>
-					</div>
-					<p class="mr-1 mb-1">
-						{{ _(offer.offer_title) }}:
-						{{ _(offer.offer_subtitle) if offer.offer_subtitle else '' }}
-						<a class="offer-details" href="#"
-							data-offer-title="{{ offer.offer_title }}" data-offer-id="{{ offer.name }}"
-							role="button">
-							{{ _("More") }}
-						</a>
-					</p>
-				</div>
-				{% endfor %}
-			</div>
-		{% endif %}
-
-		<!-- Add to Cart / View in Cart, Contact Us -->
-		<div class="mt-6 mb-5">
-			<div class="mb-4 d-flex">
-				<!-- Add to Cart -->
-				{% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %}
-					<a href="/cart" class="btn btn-light btn-view-in-cart hidden mr-2 font-md"
-						role="button">
-						{{  _("View in Cart") if cart_settings.enable_checkout else _("View in Quote") }}
-					</a>
-					<button
-						data-item-code="{{item_code}}"
-						class="btn btn-primary btn-add-to-cart mr-2 w-30-40"
-					>
-						<span class="mr-2">
-							<svg class="icon icon-md">
-								<use href="#icon-assets"></use>
-							</svg>
-						</span>
-						{{ _("Add to Cart") if cart_settings.enable_checkout else  _("Add to Quote") }}
-					</button>
-				{% endif %}
-
-				<!-- Contact Us -->
-				{% if cart_settings.show_contact_us_button %}
-					{% include "templates/generators/item/item_inquiry.html" %}
-				{% endif %}
-			</div>
-		</div>
-	</div>
-</div>
-
-<script>
-	frappe.ready(() => {
-		$('.page_content').on('click', '.btn-add-to-cart', (e) => {
-			// Bind action on add to cart button
-			const $btn = $(e.currentTarget);
-			$btn.prop('disabled', true);
-			const item_code = $btn.data('item-code');
-			erpnext.e_commerce.shopping_cart.update_cart({
-				item_code,
-				qty: 1,
-				callback(r) {
-					$btn.prop('disabled', false);
-					if (r.message) {
-						$('.btn-add-to-cart, .btn-view-in-cart').toggleClass('hidden');
-					}
-				}
-			});
-		});
-
-		$('.page_content').on('click', '.offer-details', (e) => {
-			// Bind action on More link in Offers
-			const $btn = $(e.currentTarget);
-			$btn.prop('disabled', true);
-
-			var d = new frappe.ui.Dialog({
-				title: __($btn.data('offer-title')),
-				fields: [
-					{
-						fieldname: 'offer_details',
-						fieldtype: 'HTML'
-					},
-					{
-						fieldname: 'section_break',
-						fieldtype: 'Section Break'
-					}
-				]
-			});
-
-			frappe.call({
-				method: 'erpnext.e_commerce.doctype.website_offer.website_offer.get_offer_details',
-				args: {
-					offer_id: $btn.data('offer-id')
-				},
-				callback: (value) => {
-					d.set_value("offer_details", value.message);
-					d.show();
-					$btn.prop('disabled', false);
-				}
-			})
-
-		});
-	});
-
-
-</script>
-
-{% endif %}
diff --git a/erpnext/templates/generators/item/item_configure.html b/erpnext/templates/generators/item/item_configure.html
deleted file mode 100644
index e97a275..0000000
--- a/erpnext/templates/generators/item/item_configure.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% if shopping_cart and shopping_cart.cart_settings.enabled %}
-{% set cart_settings = shopping_cart.cart_settings %}
-
-<div class="mt-5 mb-6">
-	{% if cart_settings.enable_variants | int %}
-	<button class="btn btn-primary-light btn-configure font-md mr-2"
-		data-item-code="{{ doc.item_code }}"
-		data-item-name="{{ doc.web_item_name }}"
-	>
-		{{ _('Select Variant') }}
-	</button>
-	{% endif %}
-	{% if cart_settings.show_contact_us_button %}
-		{% include "templates/generators/item/item_inquiry.html" %}
-	{% endif %}
-</div>
-<script>
-{% include "templates/generators/item/item_configure.js" %}
-</script>
-{% endif %}
diff --git a/erpnext/templates/generators/item/item_configure.js b/erpnext/templates/generators/item/item_configure.js
deleted file mode 100644
index 9beba3f..0000000
--- a/erpnext/templates/generators/item/item_configure.js
+++ /dev/null
@@ -1,343 +0,0 @@
-class ItemConfigure {
-	constructor(item_code, item_name) {
-		this.item_code = item_code;
-		this.item_name = item_name;
-
-		this.get_attributes_and_values()
-			.then(attribute_data => {
-				this.attribute_data = attribute_data;
-				this.show_configure_dialog();
-			});
-	}
-
-	show_configure_dialog() {
-		const fields = this.attribute_data.map(a => {
-			return {
-				fieldtype: 'Select',
-				label: a.attribute,
-				fieldname: a.attribute,
-				options: a.values.map(v => {
-					return {
-						label: v,
-						value: v
-					};
-				}),
-				change: (e) => {
-					this.on_attribute_selection(e);
-				}
-			};
-		});
-
-		this.dialog = new frappe.ui.Dialog({
-			title: __('Select Variant for {0}', [this.item_name]),
-			fields,
-			on_hide: () => {
-				set_continue_configuration();
-			}
-		});
-
-		this.attribute_data.forEach(a => {
-			const field = this.dialog.get_field(a.attribute);
-			const $a = $(`<a href>${__("Clear")}</a>`);
-			$a.on('click', (e) => {
-				e.preventDefault();
-				this.dialog.set_value(a.attribute, '');
-			});
-			field.$wrapper.find('.help-box').append($a);
-		});
-
-		this.append_status_area();
-		this.dialog.show();
-
-		this.dialog.set_values(JSON.parse(localStorage.getItem(this.get_cache_key())));
-
-		$('.btn-configure').prop('disabled', false);
-	}
-
-	on_attribute_selection(e) {
-		if (e) {
-			const changed_fieldname = $(e.target).data('fieldname');
-			this.show_range_input_if_applicable(changed_fieldname);
-		} else {
-			this.show_range_input_for_all_fields();
-		}
-
-		const values = this.dialog.get_values();
-		if (Object.keys(values).length === 0) {
-			this.clear_status();
-			localStorage.removeItem(this.get_cache_key());
-			return;
-		}
-
-		// save state
-		localStorage.setItem(this.get_cache_key(), JSON.stringify(values));
-
-		// show
-		this.set_loading_status();
-
-		this.get_next_attribute_and_values(values)
-			.then(data => {
-				const {
-					valid_options_for_attributes,
-				} = data;
-
-				this.set_item_found_status(data);
-
-				for (let attribute in valid_options_for_attributes) {
-					const valid_options = valid_options_for_attributes[attribute];
-					const options = this.dialog.get_field(attribute).df.options;
-					const new_options = options.map(o => {
-						o.disabled = !valid_options.includes(o.value);
-						return o;
-					});
-
-					this.dialog.set_df_property(attribute, 'options', new_options);
-					this.dialog.get_field(attribute).set_options();
-				}
-			});
-	}
-
-	show_range_input_for_all_fields() {
-		this.dialog.fields.forEach(f => {
-			this.show_range_input_if_applicable(f.fieldname);
-		});
-	}
-
-	show_range_input_if_applicable(fieldname) {
-		const changed_field = this.dialog.get_field(fieldname);
-		const changed_value = changed_field.get_value();
-		if (changed_value && changed_value.includes(' to ')) {
-			// possible range input
-			let numbers = changed_value.split(' to ');
-			numbers = numbers.map(number => parseFloat(number));
-
-			if (!numbers.some(n => isNaN(n))) {
-				numbers.sort((a, b) => a - b);
-				if (changed_field.$input_wrapper.find('.range-selector').length) {
-					return;
-				}
-				const parent = $('<div class="range-selector">')
-					.insertBefore(changed_field.$input_wrapper.find('.help-box'));
-				const control = frappe.ui.form.make_control({
-					df: {
-						fieldtype: 'Int',
-						label: __('Enter value betweeen {0} and {1}', [numbers[0], numbers[1]]),
-						change: () => {
-							const value = control.get_value();
-							if (value < numbers[0] || value > numbers[1]) {
-								control.$wrapper.addClass('was-validated');
-								control.set_description(
-									__('Value must be between {0} and {1}', [numbers[0], numbers[1]]));
-								control.$input[0].setCustomValidity('error');
-							} else {
-								control.$wrapper.removeClass('was-validated');
-								control.set_description('');
-								control.$input[0].setCustomValidity('');
-								this.update_range_values(fieldname, value);
-							}
-						}
-					},
-					render_input: true,
-					parent
-				});
-				control.$wrapper.addClass('mt-3');
-			}
-		}
-	}
-
-	update_range_values(attribute, range_value) {
-		this.range_values = this.range_values || {};
-		this.range_values[attribute] = range_value;
-	}
-
-	show_remaining_optional_attributes() {
-		// show all attributes if remaining
-		// unselected attributes are all optional
-		const unselected_attributes = this.dialog.fields.filter(df => {
-			const value_selected = this.dialog.get_value(df.fieldname);
-			return !value_selected;
-		});
-		const is_optional_attribute = df => {
-			const optional_attributes = this.attribute_data
-				.filter(a => a.optional).map(a => a.attribute);
-			return optional_attributes.includes(df.fieldname);
-		};
-		if (unselected_attributes.every(is_optional_attribute)) {
-			unselected_attributes.forEach(df => {
-				this.dialog.fields_dict[df.fieldname].$wrapper.show();
-			});
-		}
-	}
-
-	set_loading_status() {
-		this.dialog.$status_area.html(`
-			<div class="alert alert-warning d-flex justify-content-between align-items-center" role="alert">
-				${__('Loading...')}
-			</div>
-		`);
-	}
-
-	set_item_found_status(data) {
-		const html = this.get_html_for_item_found(data);
-		this.dialog.$status_area.html(html);
-	}
-
-	clear_status() {
-		this.dialog.$status_area.empty();
-	}
-
-	get_html_for_item_found({ filtered_items_count, filtered_items, exact_match, product_info, available_qty, settings }) {
-		const one_item = exact_match.length === 1
-			? exact_match[0]
-			: filtered_items_count === 1
-				? filtered_items[0]
-				: '';
-
-		let item_add_to_cart = one_item ? `
-			<button data-item-code="${one_item}"
-				class="btn btn-primary btn-add-to-cart w-100"
-				data-action="btn_add_to_cart"
-			>
-				<span class="mr-2">
-					${frappe.utils.icon('assets', 'md')}
-				</span>
-				${__("Add to Cart")}
-			</button>
-		` : '';
-
-		const items_found = filtered_items_count === 1 ?
-			__('{0} item found.', [filtered_items_count]) :
-			__('{0} items found.', [filtered_items_count]);
-
-		/* eslint-disable indent */
-		const item_found_status = exact_match.length === 1
-			? `<div class="alert alert-success d-flex justify-content-between align-items-center" role="alert">
-				<div><div>
-					${one_item}
-					${product_info && product_info.price && !$.isEmptyObject(product_info.price)
-						? '(' + product_info.price.formatted_price_sales_uom + ')'
-						: ''
-					}
-
-					${available_qty === 0 && product_info && product_info?.is_stock_item
-						? '<span class="text-danger">(' + __('Out of Stock') + ')</span>' : ''}
-
-				</div></div>
-				<a href data-action="btn_clear_values" data-item-code="${one_item}">
-					${__('Clear Values')}
-				</a>
-			</div>`
-			: `<div class="alert alert-warning d-flex justify-content-between align-items-center" role="alert">
-					<span>
-						${items_found}
-					</span>
-					<a href data-action="btn_clear_values">
-						${__('Clear values')}
-					</a>
-			</div>`;
-		/* eslint-disable indent */
-
-		if (!product_info?.allow_items_not_in_stock && available_qty === 0
-			&& product_info && product_info?.is_stock_item) {
-			item_add_to_cart = '';
-		}
-
-		return `
-			${item_found_status}
-			${item_add_to_cart}
-		`;
-	}
-
-	btn_add_to_cart(e) {
-		if (frappe.session.user !== 'Guest') {
-			localStorage.removeItem(this.get_cache_key());
-		}
-		const item_code = $(e.currentTarget).data('item-code');
-		const additional_notes = Object.keys(this.range_values || {}).map(attribute => {
-			return `${attribute}: ${this.range_values[attribute]}`;
-		}).join('\n');
-		erpnext.e_commerce.shopping_cart.update_cart({
-			item_code,
-			additional_notes,
-			qty: 1
-		});
-		this.dialog.hide();
-	}
-
-	btn_clear_values() {
-		this.dialog.fields_list.forEach(f => {
-			if (f.df?.options) {
-				f.df.options = f.df.options.map(option => {
-					option.disabled = false;
-					return option;
-				});
-			}
-		});
-		this.dialog.clear();
-		this.dialog.$status_area.empty();
-		this.on_attribute_selection();
-	}
-
-	append_status_area() {
-		this.dialog.$status_area = $('<div class="status-area mt-5">');
-		this.dialog.$wrapper.find('.modal-body').append(this.dialog.$status_area);
-		this.dialog.$wrapper.on('click', '[data-action]', (e) => {
-			e.preventDefault();
-			const $target = $(e.currentTarget);
-			const action = $target.data('action');
-			const method = this[action];
-			method.call(this, e);
-		});
-		this.dialog.$wrapper.addClass('item-configurator-dialog');
-	}
-
-	get_next_attribute_and_values(selected_attributes) {
-		return this.call('erpnext.e_commerce.variant_selector.utils.get_next_attribute_and_values', {
-			item_code: this.item_code,
-			selected_attributes
-		});
-	}
-
-	get_attributes_and_values() {
-		return this.call('erpnext.e_commerce.variant_selector.utils.get_attributes_and_values', {
-			item_code: this.item_code
-		});
-	}
-
-	get_cache_key() {
-		return `configure:${this.item_code}`;
-	}
-
-	call(method, args) {
-		// promisified frappe.call
-		return new Promise((resolve, reject) => {
-			frappe.call(method, args)
-				.then(r => resolve(r.message))
-				.fail(reject);
-		});
-	}
-}
-
-function set_continue_configuration() {
-	const $btn_configure = $('.btn-configure');
-	const { itemCode } = $btn_configure.data();
-
-	if (localStorage.getItem(`configure:${itemCode}`)) {
-		$btn_configure.text(__('Continue Selection'));
-	} else {
-		$btn_configure.text(__('Select Variant'));
-	}
-}
-
-frappe.ready(() => {
-	const $btn_configure = $('.btn-configure');
-	if (!$btn_configure.length) return;
-	const { itemCode, itemName } = $btn_configure.data();
-
-	set_continue_configuration();
-
-	$btn_configure.on('click', () => {
-		$btn_configure.prop('disabled', true);
-		new ItemConfigure(itemCode, itemName);
-	});
-});
diff --git a/erpnext/templates/generators/item/item_details.html b/erpnext/templates/generators/item/item_details.html
deleted file mode 100644
index 028936b..0000000
--- a/erpnext/templates/generators/item/item_details.html
+++ /dev/null
@@ -1,63 +0,0 @@
-{% set width_class = "expand" if not slides else "" %}
-{% set cart_settings = shopping_cart.cart_settings %}
-{% set product_info = shopping_cart.product_info %}
-{% set price_info = product_info.get('price') or {} %}
-
-<div class="col-md-7 product-details {{ width_class }}">
-	<div class="d-flex">
-		<!-- title -->
-		<div class="product-title col-11" itemprop="name">
-			{{ doc.web_item_name }}
-		</div>
-
-		<!-- Wishlist -->
-		{% if cart_settings.enable_wishlist %}
-			<div class="like-action-item-fp like-action {{ 'like-action-wished' if wished else ''}} ml-2"
-				data-item-code="{{ doc.item_code }}">
-				<svg class="icon sm">
-					<use class="{{ 'wished' if wished else 'not-wished' }} wish-icon" href="#icon-heart"></use>
-				</svg>
-			</div>
-		{% endif %}
-	</div>
-
-	<p class="product-code">
-		<span class="product-item-group">
-			{{ _(doc.item_group) }}
-		</span>
-		<span class="product-item-code">
-			{{ _("Item Code") }}:
-		</span>
-		<span itemprop="productID">{{ doc.item_code }}</span>
-	</p>
-	{% if has_variants %}
-		<!-- configure template -->
-		{% include "templates/generators/item/item_configure.html" %}
-	{% else %}
-		<!-- add variant to cart -->
-		{% include "templates/generators/item/item_add_to_cart.html" %}
-	{% endif %}
-	<!-- description -->
-	<div class="product-description" itemprop="description">
-	{% if frappe.utils.strip_html(doc.web_long_description or '') %}
-		{{ doc.web_long_description | safe }}
-	{% elif frappe.utils.strip_html(doc.description or '')  %}
-		{{ doc.description | safe }}
-	{% else %}
-		{{ "" }}
-	{% endif  %}
-	</div>
-</div>
-
-{% block base_scripts %}
-<!-- js should be loaded in body! -->
-<script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script>
-{% endblock %}
-
-<script>
-	$('.page_content').on('click', '.like-action-item-fp', (e) => {
-			// Bind action on wishlist button
-			const $btn = $(e.currentTarget);
-			erpnext.e_commerce.wishlist.wishlist_action($btn);
-		});
-</script>
\ No newline at end of file
diff --git a/erpnext/templates/generators/item/item_image.html b/erpnext/templates/generators/item/item_image.html
deleted file mode 100644
index e1bb3b9..0000000
--- a/erpnext/templates/generators/item/item_image.html
+++ /dev/null
@@ -1,108 +0,0 @@
-{% set column_size = 5 if slides else 4 %}
-<div class="col-md-{{ column_size }} h-100 d-flex mb-4">
-	{% if slides %}
-		<div class="item-slideshow d-flex flex-column mr-3">
-			{% for item in slides %}
-			<img class="item-slideshow-image mb-2 {% if loop.first %}active{% endif %}"
-					src="{{ item.image }}" alt="{{ item.heading }}">
-			{% endfor %}
-		</div>
-		{{ product_image(slides[0].image, 'product-image') }}
-		<!-- Simple image slideshow -->
-		<script>
-			frappe.ready(() => {
-				$('.page_content').on('click', '.item-slideshow-image', (e) => {
-					const $img = $(e.currentTarget);
-					const link = $img.prop('src');
-					const $product_image = $('.product-image');
-					$product_image.find('a').prop('href', link);
-					$product_image.find('img').prop('src', link);
-
-					$('.item-slideshow-image').removeClass('active');
-					$img.addClass('active');
-				});
-			})
-		</script>
-	{% else %}
-		{{ product_image(doc.website_image, alt=doc.website_image_alt or doc.item_name) }}
-	{% endif %}
-
-	<!-- Simple image preview -->
-
-	<div class="image-zoom-view" style="display: none;">
-		<button type="button" class="close" aria-label="Close">
-			<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
-			stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x">
-				<line x1="18" y1="6" x2="6" y2="18"></line>
-				<line x1="6" y1="6" x2="18" y2="18"></line>
-			</svg>
-		</button>
-	</div>
-</div>
-<style>
-	.website-image {
-		cursor: pointer;
-	}
-
-	.image-zoom-view {
-		position: fixed;
-		top: 0;
-		left: 0;
-		right: 0;
-		bottom: 0;
-		height: 100vh;
-		width: 100vw;
-		display: flex;
-		justify-content: center;
-		align-items: center;
-		background: rgba(0, 0, 0, 0.8);
-		z-index: 1080;
-	}
-
-	.image-zoom-view img {
-		max-height: 100%;
-		max-width: 100%;
-	}
-
-	.image-zoom-view button {
-		position: absolute;
-		right: 3rem;
-		top: 2rem;
-	}
-
-	.image-zoom-view svg {
-		color: var(--white);
-	}
-</style>
-<script>
-	frappe.ready(() => {
-		const $zoom_wrapper = $('.image-zoom-view');
-
-		$('.website-image').on('click', (e) => {
-			e.preventDefault();
-			const $img = $(e.target);
-			const src = $img.prop('src');
-			if (!src) return;
-			show_preview(src);
-		});
-
-		$zoom_wrapper.on('click', 'button', hide_preview);
-
-		$(document).on('keydown', (e) => {
-			if (e.key === 'Escape') {
-				hide_preview();
-			}
-		});
-
-		function show_preview(src) {
-			$zoom_wrapper.show();
-			const $img = $(`<img src="${src}">`)
-			$zoom_wrapper.append($img);
-		}
-
-		function hide_preview() {
-			$zoom_wrapper.find('img').remove();
-			$zoom_wrapper.hide();
-		}
-	})
-</script>
diff --git a/erpnext/templates/generators/item/item_inquiry.html b/erpnext/templates/generators/item/item_inquiry.html
deleted file mode 100644
index af636f1..0000000
--- a/erpnext/templates/generators/item/item_inquiry.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% if shopping_cart and shopping_cart.cart_settings.enabled %}
-{% set cart_settings = shopping_cart.cart_settings %}
-	{% if cart_settings.show_contact_us_button | int %}
-		<button class="btn btn-inquiry font-md w-30-40" data-item-code="{{ doc.name }}">
-			{{ _('Contact Us') }}
-		</button>
-	{% endif %}
-<script>
-{% include "templates/generators/item/item_inquiry.js" %}
-</script>
-{% endif %}
diff --git a/erpnext/templates/generators/item/item_inquiry.js b/erpnext/templates/generators/item/item_inquiry.js
deleted file mode 100644
index 0aee996..0000000
--- a/erpnext/templates/generators/item/item_inquiry.js
+++ /dev/null
@@ -1,77 +0,0 @@
-frappe.ready(() => {
-	const d = new frappe.ui.Dialog({
-		title: __('Contact Us'),
-		fields: [
-			{
-				fieldtype: 'Data',
-				label: __('Full Name'),
-				fieldname: 'lead_name',
-				reqd: 1
-			},
-			{
-				fieldtype: 'Data',
-				label: __('Organization Name'),
-				fieldname: 'company_name',
-			},
-			{
-				fieldtype: 'Data',
-				label: __('Email'),
-				fieldname: 'email_id',
-				options: 'Email',
-				reqd: 1
-			},
-			{
-				fieldtype: 'Data',
-				label: __('Phone Number'),
-				fieldname: 'phone',
-				options: 'Phone',
-				reqd: 1
-			},
-			{
-				fieldtype: 'Data',
-				label: __('Subject'),
-				fieldname: 'subject',
-				reqd: 1
-			},
-			{
-				fieldtype: 'Text',
-				label: __('Message'),
-				fieldname: 'message',
-				reqd: 1
-			}
-		],
-		primary_action: send_inquiry,
-		primary_action_label: __('Send')
-	});
-
-	function send_inquiry() {
-		const values = d.get_values();
-		const doc = Object.assign({}, values);
-		delete doc.subject;
-		delete doc.message;
-
-		d.hide();
-
-		frappe.call('erpnext.e_commerce.shopping_cart.cart.create_lead_for_item_inquiry', {
-			lead: doc,
-			subject: values.subject,
-			message: values.message
-		}).then(r => {
-			if (r.message) {
-				d.clear();
-			}
-		});
-	}
-
-	$('.btn-inquiry').click((e) => {
-		const $btn = $(e.target);
-		const item_code = $btn.data('item-code');
-		d.set_value('subject', 'Inquiry about ' + item_code);
-		if (!['Administrator', 'Guest'].includes(frappe.session.user)) {
-			d.set_value('email_id', frappe.session.user);
-			d.set_value('lead_name', frappe.get_cookie('full_name'));
-		}
-
-		d.show();
-	});
-});
diff --git a/erpnext/templates/generators/item/item_reviews.html b/erpnext/templates/generators/item/item_reviews.html
deleted file mode 100644
index c62c6f7..0000000
--- a/erpnext/templates/generators/item/item_reviews.html
+++ /dev/null
@@ -1,88 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import user_review, ratings_summary %}
-
-<div class="mt-4 ratings-reviews-section">
-		<!-- Title and Action -->
-		<div class="w-100 mt-4 mb-2 d-flex">
-			<div class="reviews-header col-9">
-				{{ _("Customer Reviews") }}
-			</div>
-
-			<div class="write-a-review-btn col-3">
-				<!-- Write a Review for legitimate users -->
-				{% if frappe.session.user != "Guest" and user_is_customer %}
-					<button class="btn btn-write-review"
-						data-web-item="{{ doc.name }}">
-						{{ _("Write a Review") }}
-					</button>
-				{% endif %}
-			</div>
-		</div>
-
-		<!-- Summary -->
-		{{ ratings_summary(reviews, reviews_per_rating, average_rating, average_whole_rating, for_summary=True, total_reviews=total_reviews) }}
-
-
-	<!-- Reviews and Comments -->
-	<div class="mt-8">
-		{% if reviews %}
-			{{ user_review(reviews) }}
-
-			{% if total_reviews > 4 %}
-				<div class="mt-6 mb-6"style="color: var(--primary);">
-					<a href="/customer_reviews?web_item={{ doc.name }}">{{ _("View all reviews") }}</a>
-				</div>
-			{% endif %}
-
-		{% else %}
-			<h6 class="text-muted mt-6">
-				{{ _("No Reviews") }}
-			</h6>
-		{% endif %}
-	</div>
-</div>
-
-<script>
-	frappe.ready(() => {
-		$('.page_content').on('click', '.btn-write-review', (e) => {
-			// Bind action on write a review button
-			const $btn = $(e.currentTarget);
-
-			let d = new frappe.ui.Dialog({
-				title: __("Write a Review"),
-				fields: [
-					{fieldname: "title", fieldtype: "Data", label: "Headline", reqd: 1},
-					{fieldname: "rating", fieldtype: "Rating", label: "Overall Rating", reqd: 1},
-					{fieldtype: "Section Break"},
-					{fieldname: "comment", fieldtype: "Small Text", label: "Your Review"}
-				],
-				primary_action: function() {
-					var data = d.get_values();
-					frappe.call({
-						method: "erpnext.e_commerce.doctype.item_review.item_review.add_item_review",
-						args: {
-							web_item: "{{ doc.name }}",
-							title: data.title,
-							rating: data.rating,
-							comment: data.comment
-						},
-						freeze: true,
-						freeze_message: __("Submitting Review ..."),
-						callback: function(r) {
-							if(!r.exc) {
-								frappe.msgprint({
-									message: __("Thank you for the review"),
-									title: __("Review Submitted"),
-									indicator: "green"
-								});
-								d.hide();
-								location.reload();
-							}
-						}
-					});
-				},
-				primary_action_label: __('Submit')
-			});
-			d.show();
-		});
-	});
-</script>
diff --git a/erpnext/templates/generators/item/item_specifications.html b/erpnext/templates/generators/item/item_specifications.html
deleted file mode 100644
index 0814d81..0000000
--- a/erpnext/templates/generators/item/item_specifications.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- Is reused to render within tabs as well as independently -->
-{% if website_specifications %}
-<div class="{{ 'mt-2' if not show_tabs else 'mt-5'}} item-website-specification">
-	<div class="col-md-11">
-		{% if not show_tabs %}
-			<div class="product-title mb-5 mt-4">
-				Product Details
-			</div>
-		{% endif %}
-		<table class="table">
-		{% for d in website_specifications -%}
-			<tr>
-				<td class="spec-label">{{ d.label }}</td>
-				<td class="spec-content">{{ d.description }}</td>
-			</tr>
-		{%- endfor %}
-		</table>
-	</div>
-</div>
-{% endif %}
diff --git a/erpnext/templates/generators/item_group.html b/erpnext/templates/generators/item_group.html
deleted file mode 100644
index 956c3c51..0000000
--- a/erpnext/templates/generators/item_group.html
+++ /dev/null
@@ -1,72 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import field_filter_section, attribute_filter_section, discount_range_filters %}
-{% extends "templates/web.html" %}
-
-{% block header %}
-<div class="mb-6">{{ _(item_group_name) }}</div>
-{% endblock header %}
-
-{% block script %}
-<script type="text/javascript" src="/all-products/index.js"></script>
-{% endblock %}
-
-{% block breadcrumbs %}
-<div class="item-breadcrumbs small text-muted">
-	{% include "templates/includes/breadcrumbs.html" %}
-</div>
-{% endblock %}
-
-{% block page_content %}
-<div class="item-group-content" itemscope itemtype="http://schema.org/Product"
-	data-item-group="{{ name }}">
-	<div class="item-group-slideshow">
-		{% if slideshow %} <!-- slideshow -->
-			{{ web_block(
-				"Hero Slider",
-				values=slideshow,
-				add_container=0,
-				add_top_padding=0,
-				add_bottom_padding=0,
-			) }}
-		{% endif %}
-
-		{% if description %} <!-- description -->
-		<div class="item-group-description text-muted mb-5" itemprop="description">{{ description or ""}}</div>
-		{% endif %}
-	</div>
-	<div class="row">
-		<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
-			<!-- Products Rendered in all-products/index.js-->
-		</div>
-
-		<div class="col-12 order-1 col-md-3 order-md-1">
-			<div class="collapse d-md-block mr-4 filters-section" id="product-filters">
-				<div class="d-flex justify-content-between align-items-center mb-5 title-section">
-					<div class="mb-4 filters-title" > {{ _('Filters') }} </div>
-					<a class="mb-4 clear-filters" href="/{{ doc.route }}">{{ _('Clear All') }}</a>
-				</div>
-				<!-- field filters -->
-				{{ field_filter_section(field_filters) }}
-
-				<!-- attribute filters -->
-				{{ attribute_filter_section(attribute_filters) }}
-
-			</div>
-
-		</div>
-	</div>
-</div>
-
-<script>
-	frappe.ready(() => {
-		$('.btn-prev, .btn-next').click((e) => {
-			const $btn = $(e.target);
-			$btn.prop('disabled', true);
-			const start = $btn.data('start');
-			let query_params = frappe.utils.get_query_params();
-			query_params.start = start;
-			let path = window.location.pathname + '?' + frappe.utils.get_url_from_dict(query_params);
-			window.location.href = path;
-		});
-	});
-</script>
-{% endblock %}
diff --git a/erpnext/templates/includes/cart/address_card.html b/erpnext/templates/includes/cart/address_card.html
deleted file mode 100644
index 830ed64..0000000
--- a/erpnext/templates/includes/cart/address_card.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<div class="card address-card h-100">
-	<div class="btn btn-sm btn-default btn-change-address font-md" style="position: absolute; right: 0; top: 0;">
-		{{ _('Change') }}
-	</div>
-	<div class="card-body p-0">
-		<div class="card-title">{{ address.title }}</div>
-		<div class="card-text mb-2">
-			{{ address.display }}
-		</div>
-		<a href="/addresses?name={{address.name}}" class="card-link">
-			<svg class="icon icon-sm">
-				<use href="#icon-edit"></use>
-			</svg>
-			{{ _('Edit') }}
-		</a>
-	</div>
-</div>
diff --git a/erpnext/templates/includes/cart/address_picker_card.html b/erpnext/templates/includes/cart/address_picker_card.html
deleted file mode 100644
index 646210e..0000000
--- a/erpnext/templates/includes/cart/address_picker_card.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="card address-card h-100">
-	<div class="check" style="position: absolute; right: 15px; top: 15px;">
-		<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg>
-	</div>
-	<div class="card-body">
-		<h5 class="card-title">{{ address.title }}</h5>
-		<p class="card-text text-muted">
-			{{ address.display }}
-		</p>
-		<a href="/addresses?name={{address.name}}" class="card-link">{{ _('Edit') }}</a>
-	</div>
-</div>
diff --git a/erpnext/templates/includes/cart/cart_address.html b/erpnext/templates/includes/cart/cart_address.html
deleted file mode 100644
index a8188ec..0000000
--- a/erpnext/templates/includes/cart/cart_address.html
+++ /dev/null
@@ -1,189 +0,0 @@
-{% from "erpnext/templates/includes/cart/cart_macros.html" import show_address %}
-
-{% if addresses | length == 1%}
-	{% set select_address = True %}
-{% endif %}
-
-<div class="mb-3 frappe-card p-5" data-section="shipping-address">
-	<div class="d-flex">
-		<div class="col-6 address-header"><h6>{{ _("Shipping Address") }}</h6></div>
-		<div class="col-6" style="padding: 0;">
-			<a class="ml-4 btn-new-address" role="button">{{ _("Add a new address") }}</a>
-		</div>
-	</div>
-
-	<hr>
-	{% for address in shipping_addresses %}
-	{% if doc.shipping_address_name == address.name %}
-	<div class="row no-gutters" data-fieldname="shipping_address_name">
-		<div class="w-100 address-container" data-address-name="{{address.name}}" data-address-type="shipping" data-active>
-			{% include "templates/includes/cart/address_card.html" %}
-		</div>
-	</div>
-	{% endif %}
-	{% endfor %}
-</div>
-
-<!-- Billing Address -->
-<div class="checkbox ml-1 mb-2">
-	<label for="input_same_billing">
-		<input type="checkbox" class="product-filter" id="input_same_billing" checked style="width: 14px !important">
-		<span class="label-area font-md">{{ _('Billing Address is same as Shipping Address') }}</span>
-	</label>
-</div>
-
-{% if billing_addresses %}
-	<div class="mb-3 frappe-card p-5" data-section="billing-address">
-		<div class="d-flex">
-			<div class="col-6 address-header"><h6>{{ _("Billing Address") }}</h6></div>
-			<div class="col-6" style="padding: 0;">
-				<a class="ml-4 btn-new-address" role="button">{{ _("Add a new address") }}</a>
-			</div>
-		</div>
-
-		<hr>
-		{% for address in billing_addresses %}
-			{% if doc.customer_address == address.name %}
-			<div class="row no-gutters" data-fieldname="customer_address">
-				<div class="w-100 address-container" data-address-name="{{address.name}}" data-address-type="billing" data-active>
-						{% include "templates/includes/cart/address_card.html" %}
-					</div>
-			</div>
-			{% endif %}
-		{% endfor %}
-	</div>
-{% endif %}
-
-<script>
-frappe.boot = {{ boot }}
-frappe.ready(() => {
-	$(document).on('click', '.address-card', (e) => {
-		const $target = $(e.currentTarget);
-		const $section = $target.closest('[data-section]');
-		$section.find('.address-card').removeClass('active');
-		$target.addClass('active');
-	});
-
-	$('#input_same_billing').change((e) => {
-		const $check = $(e.target);
-		toggle_billing_address_section(!$check.is(':checked'));
-	});
-
-	$('.btn-new-address').click(() => {
-		const d = new frappe.ui.Dialog({
-			title: __('New Address'),
-			fields: [
-				{
-					label: __('Address Title'),
-					fieldname: 'address_title',
-					fieldtype: 'Data',
-					reqd: 1
-				},
-				{
-					label: __('Address Line 1'),
-					fieldname: 'address_line1',
-					fieldtype: 'Data',
-					reqd: 1
-				},
-				{
-					label: __('Address Line 2'),
-					fieldname: 'address_line2',
-					fieldtype: 'Data'
-				},
-				{
-					label: __('City/Town'),
-					fieldname: 'city',
-					fieldtype: 'Data',
-					reqd: 1
-				},
-				{
-					label: __('State'),
-					fieldname: 'state',
-					fieldtype: 'Data'
-				},
-				{
-					label: __('Country'),
-					fieldname: 'country',
-					fieldtype: 'Link',
-					options: 'Country',
-					only_select: true,
-					reqd: 1
-				},
-				{
-					fieldname: "column_break0",
-					fieldtype: "Column Break",
-					width: "50%"
-				},
-				{
-					label: __('Address Type'),
-					fieldname: 'address_type',
-					fieldtype: 'Select',
-					options: [
-						'Billing',
-						'Shipping'
-					],
-					reqd: 1
-				},
-				{
-					label: __('Postal Code'),
-					fieldname: 'pincode',
-					fieldtype: 'Data'
-				},
-				{
-					fieldname: "phone",
-					fieldtype: "Data",
-					label: "Phone",
-					reqd: 1
-				},
-			],
-			primary_action_label: __('Save'),
-			primary_action: (values) => {
-				frappe.call('erpnext.e_commerce.shopping_cart.cart.add_new_address', { doc: values })
-					.then(r => {
-						frappe.call({
-							method: "erpnext.e_commerce.shopping_cart.cart.update_cart_address",
-							args: {
-								address_type: r.message.address_type,
-								address_name: r.message.name
-							},
-							callback: function (r) {
-								d.hide();
-								window.location.reload();
-							}
-						});
-					});
-
-			}
-		})
-
-		d.show();
-	});
-
-	function setup_state() {
-		const shipping_address = $('[data-section="shipping-address"]')
-			.find('[data-address-name][data-active]').attr('data-address-name');
-
-		const billing_address = $('[data-section="billing-address"]')
-			.find('[data-address-name][data-active]').attr('data-address-name');
-
-		$('#input_same_billing').prop('checked', shipping_address === billing_address).trigger('change');
-
-		if (!shipping_address && !billing_address) {
-			$('#input_same_billing').prop('checked', true).trigger('change');
-		}
-
-		if (shipping_address) {
-			$(`[data-section="shipping-address"] [data-address-name="${shipping_address}"] .address-card`).addClass('active');
-		}
-		if (billing_address) {
-			$(`[data-section="billing-address"] [data-address-name="${billing_address}"] .address-card`).addClass('active');
-		}
-	}
-
-	setup_state();
-
-	function toggle_billing_address_section(flag) {
-		$('[data-section="billing-address"]').toggle(flag);
-	}
-});
-</script>
diff --git a/erpnext/templates/includes/cart/cart_address_picker.html b/erpnext/templates/includes/cart/cart_address_picker.html
deleted file mode 100644
index 66a50ec..0000000
--- a/erpnext/templates/includes/cart/cart_address_picker.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div class="mb-3 frappe-card p-5" data-section="shipping-address">
-	<h6>{{ _("Shipping Address") }}</h6>
-</div>
diff --git a/erpnext/templates/includes/cart/cart_dropdown.html b/erpnext/templates/includes/cart/cart_dropdown.html
deleted file mode 100644
index 38ad183..0000000
--- a/erpnext/templates/includes/cart/cart_dropdown.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<div class="cart-dropdown-container">
-	<div id="cart-error" class="alert alert-danger"
-		style="display: none;"></div>
-	<div class="row checkout-btn">
-		<div class="col-sm-12 col-xs-12">
-			<a href="/cart" class="btn btn-block btn-primary">{{ _("Checkout") }}</a>
-		</div>
-	</div>
-	<div class="row cart-items-dropdown cart-item-header text-muted">
-		<div class="col-sm-6 col-xs-6 h6 text-uppercase">
-		{{ _("Item") }}
-		</div>
-		<div class="col-sm-6 col-xs-6 text-right h6 text-uppercase">
-		{{ _("Price") }}
-		</div>
-	</div>
-
-	{% if doc.items %}
-	<div class="row cart-items-dropdown">
-		<div class="col-sm-12 col-xs-12">
-			{% include "templates/includes/cart/cart_items_dropdown.html" %}
-		</div>
-	</div>
-	{% else %}
-	<p>{{ _("Cart is Empty") }}</p>
-	{% endif %}
-</div>
diff --git a/erpnext/templates/includes/cart/cart_items.html b/erpnext/templates/includes/cart/cart_items.html
deleted file mode 100644
index 428b36e..0000000
--- a/erpnext/templates/includes/cart/cart_items.html
+++ /dev/null
@@ -1,113 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import product_image %}
-
-{% macro item_subtotal(item) %}
-	<div>
-		{{ item.get_formatted('amount') }}
-	</div>
-
-	{% if item.is_free_item %}
-		<div class="text-success mt-4">
-			<span class="free-tag">
-				{{ _('FREE') }}
-			</span>
-		</div>
-	{% else %}
-		<span class="item-rate">
-			{{ _('Rate:') }} {{ item.get_formatted('rate') }}
-		</span>
-	{% endif %}
-{% endmacro %}
-
-{% for d in doc.items %}
-	<tr data-name="{{ d.name }}">
-		<td style="width: 60%;">
-			<div class="d-flex">
-				<div class="cart-item-image mr-4">
-					{% if d.thumbnail %}
-						{{ product_image(d.thumbnail, alt="d.web_item_name", no_border=True) }}
-					{% else %}
-						<div class = "no-image-cart-item">
-							{{ frappe.utils.get_abbr(d.web_item_name) or "NA" }}
-						</div>
-					{% endif %}
-				</div>
-
-				<div class="d-flex w-100" style="flex-direction: column;">
-					<div class="item-title mb-1 mr-3">
-						{{ d.get("web_item_name") or d.item_name }}
-					</div>
-					<div class="item-subtitle mr-2">
-						{{ d.item_code }}
-					</div>
-					{%- set variant_of = frappe.db.get_value('Item', d.item_code, 'variant_of') %}
-					{% if variant_of %}
-					<span class="item-subtitle mr-2">
-						{{ _('Variant of') }}
-						<a href="{{frappe.db.get_value('Website Item', {'item_code': variant_of}, 'route') or '#'}}">
-							{{ variant_of }}
-						</a>
-					</span>
-					{% endif %}
-
-					<div class="mt-2 notes">
-						<textarea data-item-code="{{d.item_code}}" class="form-control" rows="2" placeholder="{{ _('Add notes') }}">
-							{{d.additional_notes or ''}}
-						</textarea>
-					</div>
-				</div>
-			</div>
-		</td>
-
-		<!-- Qty column -->
-		<td class="text-right" style="width: 25%;">
-			<div class="d-flex">
-				{% set disabled = 'disabled' if d.is_free_item else '' %}
-				<div class="input-group number-spinner mt-1 mb-4">
-					<span class="input-group-prepend d-sm-inline-block">
-						<button class="btn cart-btn" data-dir="dwn" {{ disabled }}>
-							{{ '–' if not d.is_free_item else ''}}
-						</button>
-					</span>
-
-					<input class="form-control text-center cart-qty" value="{{ d.get_formatted('qty') }}" data-item-code="{{ d.item_code }}"
-						style="max-width: 70px;" {{ disabled }}>
-
-					<span class="input-group-append d-sm-inline-block">
-						<button class="btn cart-btn" data-dir="up" {{ disabled }}>
-							{{ '+' if not d.is_free_item else ''}}
-						</button>
-					</span>
-					</div>
-
-				<div>
-					{% if not d.is_free_item %}
-						<div class="remove-cart-item column-sm-view d-flex" data-item-code="{{ d.item_code }}">
-							<span>
-								<svg class="icon sm remove-cart-item-logo"
-									width="18" height="18" viewBox="0 0 18 18"
-									xmlns="http://www.w3.org/2000/svg" id="icon-close">
-									<path fill-rule="evenodd" clip-rule="evenodd" d="M4.146 11.217a.5.5 0 1 0 .708.708l3.182-3.182 3.181 3.182a.5.5 0 1 0 .708-.708l-3.182-3.18 3.182-3.182a.5.5 0 1 0-.708-.708l-3.18 3.181-3.183-3.182a.5.5 0 0 0-.708.708l3.182 3.182-3.182 3.181z" stroke-width="0"></path>
-								</svg>
-							</span>
-						</div>
-					{% endif %}
-					</div>
-			</div>
-
-
-			<!-- Shown on mobile view, else hidden -->
-			{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-				<div class="text-right sm-item-subtotal">
-					{{ item_subtotal(d) }}
-				</div>
-			{% endif %}
-		</td>
-
-		<!-- Subtotal column -->
-		{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-			<td class="text-right item-subtotal column-sm-view w-100">
-				{{ item_subtotal(d) }}
-			</td>
-		{% endif %}
-	</tr>
-{% endfor %}
diff --git a/erpnext/templates/includes/cart/cart_items_dropdown.html b/erpnext/templates/includes/cart/cart_items_dropdown.html
deleted file mode 100644
index 5d107fc..0000000
--- a/erpnext/templates/includes/cart/cart_items_dropdown.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% from "erpnext/templates/includes/order/order_macros.html" import item_name_and_description_cart %}
-
-{% for d in doc.items %}
-<div class="row cart-dropdown">
-    <div class="col-sm-8 col-xs-8 col-name-description">
-        {{ item_name_and_description_cart(d) }}
-    </div>
-    <div class="col-sm-4 col-xs-4 text-right col-amount">
-        {{ d.get_formatted("amount") }}
-    </div>
-</div>
-{% endfor %}
diff --git a/erpnext/templates/includes/cart/cart_items_total.html b/erpnext/templates/includes/cart/cart_items_total.html
deleted file mode 100644
index c94fde4..0000000
--- a/erpnext/templates/includes/cart/cart_items_total.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- Total at the end of the cart items -->
-<tr>
-	<th></th>
-	<th class="text-left item-grand-total" colspan="1">
-		{{ _("Total") }}
-	</th>
-	<th class="text-left item-grand-total totals" colspan="3">
-		{{ doc.get_formatted("total") }}
-	</th>
-</tr>
\ No newline at end of file
diff --git a/erpnext/templates/includes/cart/cart_macros.html b/erpnext/templates/includes/cart/cart_macros.html
deleted file mode 100644
index fd95dba..0000000
--- a/erpnext/templates/includes/cart/cart_macros.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% macro show_address(address, doc, fieldname, select_address=False) %}
-{% set selected=address.name==doc.get(fieldname) %}
-
-<div class="panel panel-default">
-	<div class="panel-heading">
-		<div class="row">
-			<div class="col-sm-10 address-title"
-				data-address-name="{{ address.name }}">
-                <strong>{{ address.name }}</strong></div>
-			<div class="col-sm-2 text-right">
-                <input type="checkbox"
-                data-fieldname="{{ fieldname }}"
-				data-address-name="{{ address.name}}"
-                    {{ "checked" if selected else "" }}></div>
-		</div>
-	</div>
-	<div class="panel-collapse"
-        data-address-name="{{ address.name }}">
-		<div class="panel-body text-muted small">{{ address.display }}</div>
-	</div>
-</div>
-{% endmacro %}
diff --git a/erpnext/templates/includes/cart/cart_payment_summary.html b/erpnext/templates/includes/cart/cart_payment_summary.html
deleted file mode 100644
index b5655a2..0000000
--- a/erpnext/templates/includes/cart/cart_payment_summary.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!-- Payment -->
-{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-<h6>
-	{{ _("Payment Summary") }}
-</h6>
-{% endif %}
-
-<div class="card h-100">
-	<div class="card-body p-0">
-		{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-			<table class="table w-100">
-				<tr>
-					{% set total_items = frappe.utils.cstr(frappe.utils.flt(doc.total_qty, 0)) %}
-					<td class="bill-label">{{ _("Net Total (") + total_items + _(" Items)") }}</td>
-					<td class="bill-content net-total text-right">{{ doc.get_formatted("net_total") }}</td>
-				</tr>
-
-				<!-- taxes -->
-				{% for d in doc.taxes %}
-					{% if d.base_tax_amount %}
-						<tr>
-							<td class="bill-label">
-								{{ d.description }}
-							</td>
-							<td class="bill-content text-right">
-								{{ d.get_formatted("base_tax_amount") }}
-							</td>
-						</tr>
-					{% endif %}
-				{% endfor %}
-			</table>
-
-			<!-- TODO: Apply Coupon Dialog-->
-			<!-- {% set show_coupon_code = cart_settings.show_apply_coupon_code_in_website and cart_settings.enable_checkout %}
-			{% if show_coupon_code %}
-				<button class="btn btn-coupon-code w-100 text-left">
-					<svg width="24" height="24" viewBox="0 0 24 24" stroke="var(--gray-600)" fill="none" xmlns="http://www.w3.org/2000/svg">
-						<path d="M19 15.6213C19 15.2235 19.158 14.842 19.4393 14.5607L20.9393 13.0607C21.5251 12.4749 21.5251 11.5251 20.9393 10.9393L19.4393 9.43934C19.158 9.15804 19 8.7765 19 8.37868V6.5C19 5.67157 18.3284 5 17.5 5H15.6213C15.2235 5 14.842 4.84196 14.5607 4.56066L13.0607 3.06066C12.4749 2.47487 11.5251 2.47487 10.9393 3.06066L9.43934 4.56066C9.15804 4.84196 8.7765 5 8.37868 5H6.5C5.67157 5 5 5.67157 5 6.5V8.37868C5 8.7765 4.84196 9.15804 4.56066 9.43934L3.06066 10.9393C2.47487 11.5251 2.47487 12.4749 3.06066 13.0607L4.56066 14.5607C4.84196 14.842 5 15.2235 5 15.6213V17.5C5 18.3284 5.67157 19 6.5 19H8.37868C8.7765 19 9.15804 19.158 9.43934 19.4393L10.9393 20.9393C11.5251 21.5251 12.4749 21.5251 13.0607 20.9393L14.5607 19.4393C14.842 19.158 15.2235 19 15.6213 19H17.5C18.3284 19 19 18.3284 19 17.5V15.6213Z" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-						<path d="M15 9L9 15" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
-						<path d="M10.5 9.5C10.5 10.0523 10.0523 10.5 9.5 10.5C8.94772 10.5 8.5 10.0523 8.5 9.5C8.5 8.94772 8.94772 8.5 9.5 8.5C10.0523 8.5 10.5 8.94772 10.5 9.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
-						<path d="M15.5 14.5C15.5 15.0523 15.0523 15.5 14.5 15.5C13.9477 15.5 13.5 15.0523 13.5 14.5C13.5 13.9477 13.9477 13.5 14.5 13.5C15.0523 13.5 15.5 13.9477 15.5 14.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
-					</svg>
-					<span class="ml-2">Apply Coupon</span>
-				</button>
-			{% endif %} -->
-
-			<table class="table w-100 grand-total mt-6">
-				<tr>
-					<td class="bill-content net-total">{{ _("Grand Total") }}</td>
-					<td class="bill-content net-total text-right">{{ doc.get_formatted("grand_total") }}</td>
-				</tr>
-			</table>
-		{% endif %}
-
-		{% if cart_settings.enable_checkout %}
-			<button class="btn btn-primary btn-place-order font-md w-100" type="button">
-				{{ _('Place Order') }}
-			</button>
-		{% else %}
-			<button class="btn btn-primary btn-request-for-quotation font-md w-100" type="button">
-				{{ _('Request for Quote') }}
-			</button>
-		{% endif %}
-	</div>
-</div>
-
-<!-- TODO: Apply Coupon Dialog-->
-<!-- <script>
-	frappe.ready(() => {
-		$('.btn-coupon-code').click((e) => {
-			const $btn = $(e.currentTarget);
-			const d = new frappe.ui.Dialog({
-				title: __('Coupons'),
-				fields: [
-					{
-						fieldname: 'coupons_area',
-						fieldtype: 'HTML'
-					}
-				]
-			});
-			d.show();
-		});
-	});
-</script> -->
\ No newline at end of file
diff --git a/erpnext/templates/includes/navbar/navbar_items.html b/erpnext/templates/includes/navbar/navbar_items.html
deleted file mode 100644
index d7adae5..0000000
--- a/erpnext/templates/includes/navbar/navbar_items.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends 'frappe/templates/includes/navbar/navbar_items.html' %}
-
-{% block navbar_right_extension %}
-	<li class="shopping-cart cart-icon hidden">
-		<a class="nav-link" href="/cart">
-			<svg class="icon icon-lg">
-				<use href="#icon-assets"></use>
-			</svg>
-			<span class="badge badge-primary shopping-badge" id="cart-count"></span>
-		</a>
-	</li>
-	{% if frappe.db.get_single_value("E Commerce Settings", "enable_wishlist") %}
-		<li class="wishlist wishlist-icon hidden">
-			<a class="nav-link" href="/wishlist">
-				<svg class="icon icon-lg">
-					<use href="#icon-heart"></use>
-				</svg>
-				<span class="badge badge-primary shopping-badge" id="wish-count"></span>
-			</a>
-		</li>
-	{% endif %}
-{% endblock %}
diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html
deleted file mode 100644
index d95b289..0000000
--- a/erpnext/templates/includes/order/order_macros.html
+++ /dev/null
@@ -1,52 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import product_image %}
-
-{% macro item_name_and_description(d) %}
-	<div class="row item_name_and_description">
-		<div class="col-xs-4 col-sm-2 order-image-col">
-			<div class="order-image h-100">
-				{% if d.thumbnail or d.image %}
-					{{ product_image(d.thumbnail or d.image, no_border=True) }}
-				{% else %}
-					<div class="no-image-cart-item" style="min-height: 100px;">
-						{{ frappe.utils.get_abbr(d.item_name) or "NA" }}
-					</div>
-				{% endif %}
-			</div>
-		</div>
-		<div class="col-xs-8 col-sm-10">
-			{{ d.item_code }}
-			<div class="text-muted small item-description">
-				{{ html2text(d.description) | truncate(140) }}
-			</div>
-			<span class="text-muted mt-2 d-l-n order-qty">
-				{{ _("Qty ") }}({{ d.get_formatted("qty") }})
-			</span>
-		</div>
-	</div>
-{% endmacro %}
-
-{% macro item_name_and_description_cart(d) %}
-	<div class="row item_name_dropdown">
-		<div class="col-xs-4 col-sm-4 order-image-col">
-			<div class="order-image">
-			 {{ product_image_square(d.thumbnail or d.image) }}
-			</div>
-		</div>
-		<div class="col-xs-8 col-sm-8">
-		   {{ d.item_name|truncate(25) }}
-			<div class="input-group number-spinner">
-				<span class="input-group-btn">
-					<button class="btn btn-light cart-btn" data-dir="dwn">
-						–</button>
-				</span>
-				<input class="form-control text-right cart-qty"
-					value = "{{ d.get_formatted('qty') }}"
-					data-item-code="{{ d.item_code }}">
-				<span class="input-group-btn">
-					<button class="btn btn-light cart-btn" data-dir="up">
-						+</button>
-				</span>
-			</div>
-		</div>
-	</div>
-{% endmacro %}
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js
deleted file mode 100644
index a3979d0..0000000
--- a/erpnext/templates/includes/product_page.js
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-
-frappe.ready(function() {
-	window.item_code = $('[itemscope] [itemprop="productID"]').text().trim();
-	var qty = 0;
-
-	frappe.call({
-		type: "POST",
-		method: "erpnext.e_commerce.shopping_cart.product_info.get_product_info_for_website",
-		args: {
-			item_code: get_item_code()
-		},
-		callback: function(r) {
-			if(r.message) {
-				if(r.message.cart_settings.enabled) {
-					let hide_add_to_cart = !r.message.product_info.price
-						|| (!r.message.product_info.in_stock && !r.message.cart_settings.allow_items_not_in_stock);
-					$(".item-cart, .item-price, .item-stock").toggleClass('hide', hide_add_to_cart);
-				}
-				if(r.message.cart_settings.show_price) {
-					$(".item-price").toggleClass("hide", false);
-				}
-				if(r.message.cart_settings.show_stock_availability) {
-					$(".item-stock").toggleClass("hide", false);
-				}
-				if(r.message.product_info.price) {
-					$(".item-price")
-						.html(r.message.product_info.price.formatted_price_sales_uom + "<div style='font-size: small'>\
-							(" + r.message.product_info.price.formatted_price + " / " + r.message.product_info.uom + ")</div>");
-
-					if(r.message.product_info.in_stock===0) {
-						$(".item-stock").html("<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>");
-					}
-					else if(r.message.product_info.in_stock===1 && r.message.cart_settings.show_stock_availability) {
-						var qty_display = "{{ _("In stock") }}";
-						if (r.message.product_info.show_stock_qty) {
-							qty_display += " ("+r.message.product_info.stock_qty+")";
-						}
-						$(".item-stock").html("<div style='color: green'>\
-							<i class='fa fa-check'></i> "+qty_display+"</div>");
-					}
-
-					if(r.message.product_info.qty) {
-						qty = r.message.product_info.qty;
-						toggle_update_cart(r.message.product_info.qty);
-					} else {
-						toggle_update_cart(0);
-					}
-				}
-			}
-		}
-	})
-
-	$("#item-add-to-cart button").on("click", function() {
-		frappe.provide('erpnext.shopping_cart');
-
-		erpnext.shopping_cart.update_cart({
-			item_code: get_item_code(),
-			qty: $("#item-spinner .cart-qty").val(),
-			callback: function(r) {
-				if(!r.exc) {
-					toggle_update_cart(1);
-					qty = 1;
-				}
-			},
-			btn: this,
-		});
-	});
-
-	$("#item-spinner").on('click', '.number-spinner button', function () {
-		var btn = $(this),
-			input = btn.closest('.number-spinner').find('input'),
-			oldValue = input.val().trim(),
-			newVal = 0;
-
-		if (btn.attr('data-dir') == 'up') {
-			newVal = Number.parseInt(oldValue) + 1;
-		} else if (btn.attr('data-dir') == 'dwn')  {
-			if (Number.parseInt(oldValue) > 1) {
-				newVal = Number.parseInt(oldValue) - 1;
-			}
-			else {
-				newVal = Number.parseInt(oldValue);
-			}
-		}
-		input.val(newVal);
-	});
-
-	$("[itemscope] .item-view-attribute .form-control").on("change", function() {
-		try {
-			var item_code = encodeURIComponent(get_item_code());
-
-		} catch(e) {
-			// unable to find variant
-			// then chose the closest available one
-
-			var attribute = $(this).attr("data-attribute");
-			var attribute_value = $(this).val();
-			var item_code = find_closest_match(attribute, attribute_value);
-
-			if (!item_code) {
-				frappe.msgprint(__("Cannot find a matching Item. Please select some other value for {0}.", [attribute]))
-				throw e;
-			}
-		}
-
-		if (window.location.search == ("?variant=" + item_code) || window.location.search.includes(item_code)) {
-			return;
-		}
-
-		window.location.href = window.location.pathname + "?variant=" + item_code;
-	});
-
-	// change the item image src when alternate images are hovered
-	$(document.body).on('mouseover', '.item-alternative-image', (e) => {
-		const $alternative_image = $(e.currentTarget);
-		const src = $alternative_image.find('img').prop('src');
-		$('.item-image img').prop('src', src);
-	});
-});
-
-var toggle_update_cart = function(qty) {
-	$("#item-add-to-cart").toggle(qty ? false : true);
-	$("#item-update-cart")
-		.toggle(qty ? true : false)
-		.find("input").val(qty);
-	$("#item-spinner").toggle(qty ? false : true);
-}
-
-function get_item_code() {
-	var variant_info = window.variant_info;
-	if(variant_info) {
-		var attributes = get_selected_attributes();
-		var no_of_attributes = Object.keys(attributes).length;
-
-		for(var i in variant_info) {
-			var variant = variant_info[i];
-
-			if (variant.attributes.length < no_of_attributes) {
-				// the case when variant has less attributes than template
-				continue;
-			}
-
-			var match = true;
-			for(var j in variant.attributes) {
-				if(attributes[variant.attributes[j].attribute]
-					!= variant.attributes[j].attribute_value
-				) {
-					match = false;
-					break;
-				}
-			}
-			if(match) {
-				return variant.name;
-			}
-		}
-		throw "Unable to match variant";
-	} else {
-		return window.item_code;
-	}
-}
-
-function find_closest_match(selected_attribute, selected_attribute_value) {
-	// find the closest match keeping the selected attribute in focus and get the item code
-
-	var attributes = get_selected_attributes();
-
-	var previous_match_score = 0;
-	var previous_no_of_attributes = 0;
-	var matched;
-
-	var variant_info = window.variant_info;
-	for(var i in variant_info) {
-		var variant = variant_info[i];
-		var match_score = 0;
-		var has_selected_attribute = false;
-
-		for(var j in variant.attributes) {
-			if(attributes[variant.attributes[j].attribute]===variant.attributes[j].attribute_value) {
-				match_score = match_score + 1;
-
-				if (variant.attributes[j].attribute==selected_attribute && variant.attributes[j].attribute_value==selected_attribute_value) {
-					has_selected_attribute = true;
-				}
-			}
-		}
-
-		if (has_selected_attribute
-			&& ((match_score > previous_match_score) || (match_score==previous_match_score && previous_no_of_attributes < variant.attributes.length))) {
-			previous_match_score = match_score;
-			matched = variant;
-			previous_no_of_attributes = variant.attributes.length;
-
-
-		}
-	}
-
-	if (matched) {
-		for (var j in matched.attributes) {
-			var attr = matched.attributes[j];
-			$('[itemscope]')
-				.find(repl('.item-view-attribute .form-control[data-attribute="%(attribute)s"]', attr))
-				.val(attr.attribute_value);
-		}
-
-		return matched.name;
-	}
-}
-
-function get_selected_attributes() {
-	var attributes = {};
-	$('[itemscope]').find(".item-view-attribute .form-control").each(function() {
-		attributes[$(this).attr('data-attribute')] = $(this).val();
-	});
-	return attributes;
-}
diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html
deleted file mode 100644
index 2b7d9e3..0000000
--- a/erpnext/templates/pages/cart.html
+++ /dev/null
@@ -1,132 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block title %} {{ _("Shopping Cart") }} {% endblock %}
-
-{% block header %}<h3 class="shopping-cart-header mt-2 mb-6">{{ _("Shopping Cart") }}</h1>{% endblock %}
-
-{% block header_actions %}
-{% endblock %}
-
-{% block page_content %}
-
-{% from "templates/includes/macros.html" import item_name_and_description %}
-
-{% if doc.items %}
-<div class="cart-container">
-	<div class="row m-0">
-		<!-- Left section -->
-		<div class="col-md-8">
-			<div class="frappe-card p-5 mb-4">
-				<div id="cart-error" class="alert alert-danger" style="display: none;"></div>
-				<div class="cart-items-header">
-					{{ _('Items') }}
-				</div>
-				<table class="table mt-3 cart-table">
-					<thead>
-						<tr>
-							<th class="item-column">{{ _('Item') }}</th>
-							<th width="20%">{{ _('Quantity') }}</th>
-							{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-								<th width="20" class="text-right column-sm-view">{{ _('Subtotal') }}</th>
-							{% endif %}
-							<th width="10%" class="column-sm-view"></th>
-						</tr>
-					</thead>
-					<tbody class="cart-items">
-						{% include "templates/includes/cart/cart_items.html" %}
-					</tbody>
-
-					{% if cart_settings.enable_checkout or cart_settings.show_price_in_quotation %}
-						<tfoot class="cart-tax-items">
-							{% include "templates/includes/cart/cart_items_total.html" %}
-						</tfoot>
-					{% endif %}
-				</table>
-
-				<div class="row mt-2">
-					<div class="col-3">
-						{% if cart_settings.enable_checkout %}
-							<a class="btn btn-primary-light font-md" href="/orders">
-								{{ _('Past Orders') }}
-							</a>
-						{% else %}
-							<a class="btn btn-primary-light font-md" href="/quotations">
-								{{ _('Past Quotes') }}
-							</a>
-						{% endif %}
-					</div>
-					<div class="col-9">
-						{% if doc.items %}
-						<div class="place-order-container">
-							<a class="btn btn-primary-light mr-2 font-md" href="/all-products">
-								{{ _('Continue Shopping') }}
-							</a>
-						</div>
-						{% endif %}
-					</div>
-				</div>
-			</div>
-
-			<!-- Terms and Conditions -->
-			{% if doc.items %}
-				{% if doc.terms %}
-					<div class="t-and-c-container mt-4 frappe-card">
-						<h5>{{ _("Terms and Conditions") }}</h5>
-						<div class="t-and-c-terms mt-2">
-							{{ doc.terms }}
-						</div>
-					</div>
-				{% endif %}
-		</div>
-
-		<!-- Right section -->
-		<div class="col-md-4">
-			<div class="cart-payment-addresses">
-				<!-- Apply Coupon Code  -->
-				{% set show_coupon_code = cart_settings.show_apply_coupon_code_in_website and cart_settings.enable_checkout %}
-				{% if show_coupon_code == 1%}
-					<div class="mb-3">
-						<div class="row no-gutters">
-							<input type="text" class="txtcoupon form-control mr-3 w-50 font-md" placeholder="Enter Coupon Code" name="txtcouponcode"  ></input>
-							<button class="btn btn-primary btn-sm bt-coupon font-md">{{ _("Apply Coupon Code") }}</button>
-							<input type="hidden" class="txtreferral_sales_partner font-md" placeholder="Enter Sales Partner" name="txtreferral_sales_partner" type="text"></input>
-							</div>
-					</div>
-				{% endif %}
-
-				<div class="mb-3 frappe-card p-5 payment-summary">
-					{% include "templates/includes/cart/cart_payment_summary.html" %}
-				</div>
-
-				{% include "templates/includes/cart/cart_address.html" %}
-			</div>
-		</div>
-		{% endif %}
-	</div>
-</div>
-{% else %}
-<div class="cart-empty frappe-card">
-	<div class="cart-empty-state">
-		<img src="/assets/erpnext/images/ui-states/cart-empty-state.png" alt="Empty State">
-	</div>
-	<div class="cart-empty-message mt-4">{{ _('Your cart is Empty') }}</p>
-	{% if cart_settings.enable_checkout %}
-		<a class="btn btn-outline-primary" href="/orders" style="font-size: 16px;">
-			{{ _('See past orders') }}
-		</a>
-		{% else %}
-		<a class="btn btn-outline-primary" href="/quotations" style="font-size: 16px;">
-			{{ _('See past quotations') }}
-		</a>
-	{% endif %}
-</div>
-{% endif %}
-
-{% endblock %}
-
-{% block base_scripts %}
-<!-- js should be loaded in body! -->
-{{ include_script("frappe-web.bundle.js") }}
-{{ include_script("controls.bundle.js") }}
-{{ include_script("dialog.bundle.js") }}
-{% endblock %}
diff --git a/erpnext/templates/pages/cart.js b/erpnext/templates/pages/cart.js
deleted file mode 100644
index fb2d159..0000000
--- a/erpnext/templates/pages/cart.js
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-
-// JS exclusive to /cart page
-frappe.provide("erpnext.e_commerce.shopping_cart");
-var shopping_cart = erpnext.e_commerce.shopping_cart;
-
-$.extend(shopping_cart, {
-	show_error: function(title, text) {
-		$("#cart-container").html('<div class="msg-box"><h4>' +
-			title + '</h4><p class="text-muted">' + text + '</p></div>');
-	},
-
-	bind_events: function() {
-		shopping_cart.bind_address_picker_dialog();
-		shopping_cart.bind_place_order();
-		shopping_cart.bind_request_quotation();
-		shopping_cart.bind_change_qty();
-		shopping_cart.bind_remove_cart_item();
-		shopping_cart.bind_change_notes();
-		shopping_cart.bind_coupon_code();
-	},
-
-	bind_address_picker_dialog: function() {
-		const d = this.get_update_address_dialog();
-		this.parent.find('.btn-change-address').on('click', (e) => {
-			const type = $(e.currentTarget).parents('.address-container').attr('data-address-type');
-			$(d.get_field('address_picker').wrapper).html(
-				this.get_address_template(type)
-			);
-			d.show();
-		});
-	},
-
-	get_update_address_dialog() {
-		let d = new frappe.ui.Dialog({
-			title: "Select Address",
-			fields: [{
-				'fieldtype': 'HTML',
-				'fieldname': 'address_picker',
-			}],
-			primary_action_label: __('Set Address'),
-			primary_action: () => {
-				const $card = d.$wrapper.find('.address-card.active');
-				const address_type = $card.closest('[data-address-type]').attr('data-address-type');
-				const address_name = $card.closest('[data-address-name]').attr('data-address-name');
-				frappe.call({
-					type: "POST",
-					method: "erpnext.e_commerce.shopping_cart.cart.update_cart_address",
-					freeze: true,
-					args: {
-						address_type,
-						address_name
-					},
-					callback: function(r) {
-						d.hide();
-						if (!r.exc) {
-							$(".cart-tax-items").html(r.message.total);
-							shopping_cart.parent.find(
-								`.address-container[data-address-type="${address_type}"]`
-							).html(r.message.address);
-						}
-					}
-				});
-			}
-		});
-
-		return d;
-	},
-
-	get_address_template(type) {
-		return {
-			shipping: `<div class="mb-3" data-section="shipping-address">
-				<div class="row no-gutters" data-fieldname="shipping_address_name">
-					{% for address in shipping_addresses %}
-						<div class="mr-3 mb-3 w-100" data-address-name="{{address.name}}" data-address-type="shipping"
-							{% if doc.shipping_address_name == address.name %} data-active {% endif %}>
-							{% include "templates/includes/cart/address_picker_card.html" %}
-						</div>
-					{% endfor %}
-				</div>
-			</div>`,
-			billing: `<div class="mb-3" data-section="billing-address">
-				<div class="row no-gutters" data-fieldname="customer_address">
-					{% for address in billing_addresses %}
-						<div class="mr-3 mb-3 w-100" data-address-name="{{address.name}}" data-address-type="billing"
-							{% if doc.shipping_address_name == address.name %} data-active {% endif %}>
-							{% include "templates/includes/cart/address_picker_card.html" %}
-						</div>
-					{% endfor %}
-				</div>
-			</div>`,
-		}[type];
-	},
-
-	bind_place_order: function() {
-		$(".btn-place-order").on("click", function() {
-			shopping_cart.place_order(this);
-		});
-	},
-
-	bind_request_quotation: function() {
-		$('.btn-request-for-quotation').on('click', function() {
-			shopping_cart.request_quotation(this);
-		});
-	},
-
-	bind_change_qty: function() {
-		// bind update button
-		$(".cart-items").on("change", ".cart-qty", function() {
-			var item_code = $(this).attr("data-item-code");
-			var newVal = $(this).val();
-			shopping_cart.shopping_cart_update({item_code, qty: newVal});
-		});
-
-		$(".cart-items").on('click', '.number-spinner button', function () {
-			var btn = $(this),
-				input = btn.closest('.number-spinner').find('input'),
-				oldValue = input.val().trim(),
-				newVal = 0;
-
-			if (btn.attr('data-dir') == 'up') {
-				newVal = parseInt(oldValue) + 1;
-			} else {
-				if (oldValue > 1) {
-					newVal = parseInt(oldValue) - 1;
-				}
-			}
-			input.val(newVal);
-
-			let notes = input.closest("td").siblings().find(".notes").text().trim();
-			var item_code = input.attr("data-item-code");
-			shopping_cart.shopping_cart_update({
-				item_code,
-				qty: newVal,
-				additional_notes: notes
-			});
-		});
-	},
-
-	bind_change_notes: function() {
-		$('.cart-items').on('change', 'textarea', function() {
-			const $textarea = $(this);
-			const item_code = $textarea.attr('data-item-code');
-			const qty = $textarea.closest('tr').find('.cart-qty').val();
-			const notes = $textarea.val();
-			shopping_cart.shopping_cart_update({
-				item_code,
-				qty,
-				additional_notes: notes
-			});
-		});
-	},
-
-	bind_remove_cart_item: function() {
-		$(".cart-items").on("click", ".remove-cart-item", (e) => {
-			const $remove_cart_item_btn = $(e.currentTarget);
-			var item_code = $remove_cart_item_btn.data("item-code");
-
-			shopping_cart.shopping_cart_update({
-				item_code: item_code,
-				qty: 0
-			});
-		});
-	},
-
-	render_tax_row: function($cart_taxes, doc, shipping_rules) {
-		var shipping_selector;
-		if(shipping_rules) {
-			shipping_selector = '<select class="form-control">' + $.map(shipping_rules, function(rule) {
-				return '<option value="' + rule[0] + '">' + rule[1] + '</option>' }).join("\n") +
-			'</select>';
-		}
-
-		var $tax_row = $(repl('<div class="row">\
-			<div class="col-md-9 col-sm-9">\
-				<div class="row">\
-					<div class="col-md-9 col-md-offset-3">' +
-					(shipping_selector || '<p>%(description)s</p>') +
-					'</div>\
-				</div>\
-			</div>\
-			<div class="col-md-3 col-sm-3 text-right">\
-				<p' + (shipping_selector ? ' style="margin-top: 5px;"' : "") + '>%(formatted_tax_amount)s</p>\
-			</div>\
-		</div>', doc)).appendTo($cart_taxes);
-
-		if(shipping_selector) {
-			$tax_row.find('select option').each(function(i, opt) {
-				if($(opt).html() == doc.description) {
-					$(opt).attr("selected", "selected");
-				}
-			});
-			$tax_row.find('select').on("change", function() {
-				shopping_cart.apply_shipping_rule($(this).val(), this);
-			});
-		}
-	},
-
-	apply_shipping_rule: function(rule, btn) {
-		return frappe.call({
-			btn: btn,
-			type: "POST",
-			method: "erpnext.e_commerce.shopping_cart.cart.apply_shipping_rule",
-			args: { shipping_rule: rule },
-			callback: function(r) {
-				if(!r.exc) {
-					shopping_cart.render(r.message);
-				}
-			}
-		});
-	},
-
-	place_order: function(btn) {
-		shopping_cart.freeze();
-
-		return frappe.call({
-			type: "POST",
-			method: "erpnext.e_commerce.shopping_cart.cart.place_order",
-			btn: btn,
-			callback: function(r) {
-				if(r.exc) {
-					shopping_cart.unfreeze();
-					var msg = "";
-					if(r._server_messages) {
-						msg = JSON.parse(r._server_messages || []).join("<br>");
-					}
-
-					$("#cart-error")
-						.empty()
-						.html(msg || frappe._("Something went wrong!"))
-						.toggle(true);
-				} else {
-					$(btn).hide();
-					window.location.href = '/orders/' + encodeURIComponent(r.message);
-				}
-			}
-		});
-	},
-
-	request_quotation: function(btn) {
-		shopping_cart.freeze();
-
-		return frappe.call({
-			type: "POST",
-			method: "erpnext.e_commerce.shopping_cart.cart.request_for_quotation",
-			btn: btn,
-			callback: function(r) {
-				if(r.exc) {
-					shopping_cart.unfreeze();
-					var msg = "";
-					if(r._server_messages) {
-						msg = JSON.parse(r._server_messages || []).join("<br>");
-					}
-
-					$("#cart-error")
-						.empty()
-						.html(msg || frappe._("Something went wrong!"))
-						.toggle(true);
-				} else {
-					$(btn).hide();
-					window.location.href = '/quotations/' + encodeURIComponent(r.message);
-				}
-			}
-		});
-	},
-
-	bind_coupon_code: function() {
-		$(".bt-coupon").on("click", function() {
-			shopping_cart.apply_coupon_code(this);
-		});
-	},
-
-	apply_coupon_code: function(btn) {
-		return frappe.call({
-			type: "POST",
-			method: "erpnext.e_commerce.shopping_cart.cart.apply_coupon_code",
-			btn: btn,
-			args : {
-				applied_code : $('.txtcoupon').val(),
-				applied_referral_sales_partner: $('.txtreferral_sales_partner').val()
-			},
-			callback: function(r) {
-				if (r && r.message){
-					location.reload();
-				}
-			}
-		});
-	}
-});
-
-frappe.ready(function() {
-	if (window.location.pathname === "/cart") {
-		$(".cart-icon").hide();
-	}
-	shopping_cart.parent = $(".cart-container");
-	shopping_cart.bind_events();
-});
-
-function show_terms() {
-	var html = $(".cart-terms").html();
-	frappe.msgprint(html);
-}
diff --git a/erpnext/templates/pages/cart.py b/erpnext/templates/pages/cart.py
deleted file mode 100644
index cadb46f..0000000
--- a/erpnext/templates/pages/cart.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-no_cache = 1
-
-from erpnext.e_commerce.shopping_cart.cart import get_cart_quotation
-
-
-def get_context(context):
-	context.body_class = "product-page"
-	context.update(get_cart_quotation())
diff --git a/erpnext/templates/pages/customer_reviews.html b/erpnext/templates/pages/customer_reviews.html
deleted file mode 100644
index 121bec3..0000000
--- a/erpnext/templates/pages/customer_reviews.html
+++ /dev/null
@@ -1,67 +0,0 @@
-{% extends "templates/web.html" %}
-{% from "erpnext/templates/includes/macros.html" import user_review, ratings_summary %}
-
-{% block title %} {{ _("Customer Reviews") }} {% endblock %}
-
-{% block page_content %}
-<div class="product-container reviews-full-page col-md-12">
-	{% if enable_reviews %}
-		<!-- Title and Action -->
-		<div class="w-100 mb-6 d-flex">
-			<div class="reviews-header col-9">
-				{{ _("Customer Reviews") }}
-			</div>
-
-			<div class="write-a-review-btn col-3">
-				<!-- Write a Review for legitimate users -->
-				{% if frappe.session.user != "Guest" and user_is_customer %}
-					<button class="btn btn-write-review"
-						data-web-item="{{ web_item }}">
-						{{ _("Write a Review") }}
-					</button>
-				{% endif %}
-			</div>
-		</div>
-
-		<!-- Summary -->
-		{{ ratings_summary(reviews, reviews_per_rating, average_rating, average_whole_rating, for_summary=True, total_reviews=total_reviews) }}
-
-
-		<!-- Reviews and Comments -->
-		<div class="mt-8">
-			{% if reviews %}
-				{{ user_review(reviews) }}
-
-				{% if not reviews | len >= total_reviews %}
-					<button class="btn btn-light btn-view-more mr-2 mt-4 mb-4 w-30"
-						data-web-item="{{ web_item }}">
-						{{ _("View More") }}
-					</button>
-				{% endif %}
-
-			{% else %}
-				<h6 class="text-muted mt-6">
-					{{ _("No Reviews") }}
-				</h6>
-			{% endif %}
-		</div>
-	{% else %}
-		<!-- If reviews are disabled -->
-		<div class="text-center">
-			<h3 class="text-muted mt-8">
-				{{ _("No Reviews") }}
-			</h3>
-		</div>
-	{% endif %}
-</div>
-
-{% endblock %}
-
-{% block base_scripts %}
-<!-- js should be loaded in body! -->
-<script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script>
-<script type="text/javascript" src="/assets/js/frappe-web.min.js"></script>
-<script type="text/javascript" src="/assets/js/control.min.js"></script>
-<script type="text/javascript" src="/assets/js/dialog.min.js"></script>
-<script type="text/javascript" src="/assets/js/bootstrap-4-web.min.js"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/customer_reviews.py b/erpnext/templates/pages/customer_reviews.py
deleted file mode 100644
index c1f0c93..0000000
--- a/erpnext/templates/pages/customer_reviews.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.e_commerce.doctype.item_review.item_review import get_item_reviews
-from erpnext.e_commerce.doctype.website_item.website_item import check_if_user_is_customer
-
-
-def get_context(context):
-	context.body_class = "product-page"
-	context.no_cache = 1
-	context.full_page = True
-	context.reviews = None
-
-	if frappe.form_dict and frappe.form_dict.get("web_item"):
-		context.web_item = frappe.form_dict.get("web_item")
-		context.user_is_customer = check_if_user_is_customer()
-		context.enable_reviews = get_shopping_cart_settings().enable_reviews
-
-		if context.enable_reviews:
-			reviews_data = get_item_reviews(context.web_item)
-			context.update(reviews_data)
diff --git a/erpnext/templates/pages/home.html b/erpnext/templates/pages/home.html
index 27d966a..08e0432 100644
--- a/erpnext/templates/pages/home.html
+++ b/erpnext/templates/pages/home.html
@@ -17,9 +17,6 @@
 			<h3 class="d-block d-sm-none">{{ homepage.description }}</h3>
 		</div>
 
-		<div class="container">
-			<a href="{{ explore_link }}" class="mb-5 btn btn-primary">{{ _('Explore') }}</a>
-		</div>
 	</section>
 	{% elif homepage.hero_section_based_on == 'Slideshow' and slideshow %}
 	<section class="hero-section">
@@ -29,26 +26,6 @@
 		{{ render_homepage_section(homepage.hero_section_doc) }}
 	{% endif %}
 
-	{% if homepage.products %}
-	<section class="container section-products my-5">
-		<h3>{{ _('Products') }}</h3>
-
-		<div class="row">
-			{% for item in homepage.products %}
-			<div class="col-md-4 mb-4">
-				<div class="card h-100 justify-content-between">
-					<img class="card-img-top website-image-extra-large" src="{{ item.image }}" loading="lazy" alt="{{ item.item_name }}"></img>
-					<div class="card-body flex-grow-0">
-						<h5 class="card-title">{{ item.item_name }}</h5>
-						<a href="{{ item.route }}" class="card-link">{{ _('More details') }}</a>
-					</div>
-				</div>
-			</div>
-			{% endfor %}
-		</div>
-	</section>
-	{% endif %}
-
 	{% if blogs %}
 	<section class="container my-5">
 		<h3>{{ _('Publications') }}</h3>
diff --git a/erpnext/templates/pages/home.py b/erpnext/templates/pages/home.py
index 47fb89d..751a5b0 100644
--- a/erpnext/templates/pages/home.py
+++ b/erpnext/templates/pages/home.py
@@ -10,11 +10,6 @@
 def get_context(context):
 	homepage = frappe.get_cached_doc("Homepage")
 
-	for item in homepage.products:
-		route = frappe.db.get_value("Website Item", {"item_code": item.item_code}, "route")
-		if route:
-			item.route = "/" + route
-
 	homepage.title = homepage.title or homepage.company
 	context.title = homepage.title
 	context.homepage = homepage
@@ -52,5 +47,3 @@
 	context.metatags = context.metatags or frappe._dict({})
 	context.metatags.image = homepage.hero_image or None
 	context.metatags.description = homepage.description or None
-
-	context.explore_link = "/all-products"
diff --git a/erpnext/templates/pages/order.js b/erpnext/templates/pages/order.js
deleted file mode 100644
index 0574cde..0000000
--- a/erpnext/templates/pages/order.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ready(function(){
-
-	var loyalty_points_input = document.getElementById("loyalty-point-to-redeem");
-	var loyalty_points_status = document.getElementById("loyalty-points-status");
-	if (loyalty_points_input) {
-		loyalty_points_input.onblur = apply_loyalty_points;
-	}
-
-	function apply_loyalty_points() {
-		var loyalty_points = parseInt(loyalty_points_input.value);
-		if (loyalty_points) {
-			frappe.call({
-				method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor",
-				args: {
-					"customer": doc_info.customer
-				},
-				callback: function(r) {
-					if (r) {
-						var message = ""
-						let loyalty_amount = flt(r.message*loyalty_points);
-						if (doc_info.grand_total && doc_info.grand_total < loyalty_amount) {
-							let redeemable_amount = parseInt(doc_info.grand_total/r.message);
-							message = "You can only redeem max " + redeemable_amount + " points in this order.";
-							frappe.msgprint(__(message));
-						} else {
-							message = loyalty_points + " Loyalty Points of amount "+ loyalty_amount + " is applied."
-							frappe.msgprint(__(message));
-							var remaining_amount = flt(doc_info.grand_total) - flt(loyalty_amount);
-							var payment_button = document.getElementById("pay-for-order");
-							payment_button.innerHTML = __("Pay Remaining");
-							payment_button.href = "/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn="+doc_info.doctype_name+"&dt="+doc_info.doctype+"&loyalty_points="+loyalty_points+"&submit_doc=1&order_type=Shopping Cart";
-						}
-						loyalty_points_status.innerHTML = message;
-					}
-				}
-			});
-		}
-	}
-})
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
index 13772d3..d0968bf 100644
--- a/erpnext/templates/pages/order.py
+++ b/erpnext/templates/pages/order.py
@@ -4,8 +4,6 @@
 import frappe
 from frappe import _
 
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import show_attachments
-
 
 def get_context(context):
 	context.no_cache = 1
@@ -14,17 +12,12 @@
 	if hasattr(context.doc, "set_indicator"):
 		context.doc.set_indicator()
 
-	if show_attachments():
-		context.attachments = get_attachments(frappe.form_dict.doctype, frappe.form_dict.name)
-
 	context.parents = frappe.form_dict.parents
 	context.title = frappe.form_dict.name
 	context.payment_ref = frappe.db.get_value(
 		"Payment Request", {"reference_name": frappe.form_dict.name}, "name"
 	)
 
-	context.enabled_checkout = frappe.get_doc("E Commerce Settings").enable_checkout
-
 	default_print_format = frappe.db.get_value(
 		"Property Setter",
 		dict(property="default_print_format", doc_type=frappe.form_dict.doctype),
diff --git a/erpnext/templates/pages/product_search.html b/erpnext/templates/pages/product_search.html
deleted file mode 100644
index 6a5425b..0000000
--- a/erpnext/templates/pages/product_search.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block title %} {{ _("Product Search") }} {% endblock %}
-
-{% block header %}<h2>{{ _("Product Search") }}</h2>{% endblock %}
-
-{% block page_content %}
-<script>{% include "templates/includes/product_list.js" %}</script>
-
-<script>
-frappe.ready(function() {
-	var txt = frappe.utils.get_url_arg("search");
-	$(".search-results").html('{{ _("Search results for") + ": " + html2text(frappe.form_dict.search or "") | e | trim }}');
-	window.search = txt;
-	window.start = 0;
-	window.get_product_list();
-});
-</script>
-
-<div class="product-search-content">
-    <h3 class="search-results">{{ _("Search Results") }}</h3>
-	<div id="search-list" class="row">
-
-	</div>
-	<div style="text-align: center;">
-		<div class="more-btn"
-			style="display: none; text-align: center;">
-            <button class="btn btn-light">{{ _("More...") }}</button>
-		</div>
-	</div>
-</div>
-{% endblock %}
diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py
deleted file mode 100644
index f40fd47..0000000
--- a/erpnext/templates/pages/product_search.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import json
-
-import frappe
-from frappe.utils import cint, cstr
-from redis.commands.search.query import Query
-
-from erpnext.e_commerce.redisearch_utils import (
-	WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE,
-	WEBSITE_ITEM_INDEX,
-	WEBSITE_ITEM_NAME_AUTOCOMPLETE,
-	is_redisearch_enabled,
-)
-from erpnext.e_commerce.shopping_cart.product_info import set_product_info_for_website
-from erpnext.setup.doctype.item_group.item_group import get_item_for_list_in_html
-
-no_cache = 1
-
-
-def get_context(context):
-	context.show_search = True
-
-
-@frappe.whitelist(allow_guest=True)
-def get_product_list(search=None, start=0, limit=12):
-	data = get_product_data(search, start, limit)
-
-	for item in data:
-		set_product_info_for_website(item)
-
-	return [get_item_for_list_in_html(r) for r in data]
-
-
-def get_product_data(search=None, start=0, limit=12):
-	# limit = 12 because we show 12 items in the grid view
-	# base query
-	query = """
-		SELECT
-			web_item_name, item_name, item_code, brand, route,
-			website_image, thumbnail, item_group,
-			description, web_long_description as website_description,
-			website_warehouse, ranking
-		FROM `tabWebsite Item`
-		WHERE published = 1
-		"""
-
-	# search term condition
-	if search:
-		query += """ and (item_name like %(search)s
-				or web_item_name like %(search)s
-				or brand like %(search)s
-				or web_long_description like %(search)s)"""
-		search = "%" + cstr(search) + "%"
-
-	# order by
-	query += """ ORDER BY ranking desc, modified desc limit %s offset %s""" % (
-		cint(limit),
-		cint(start),
-	)
-
-	return frappe.db.sql(query, {"search": search}, as_dict=1)  # nosemgrep
-
-
-@frappe.whitelist(allow_guest=True)
-def search(query):
-	product_results = product_search(query)
-	category_results = get_category_suggestions(query)
-
-	return {
-		"product_results": product_results.get("results") or [],
-		"category_results": category_results.get("results") or [],
-	}
-
-
-@frappe.whitelist(allow_guest=True)
-def product_search(query, limit=10, fuzzy_search=True):
-	search_results = {"from_redisearch": True, "results": []}
-
-	if not is_redisearch_enabled():
-		# Redisearch module not enabled
-		search_results["from_redisearch"] = False
-		search_results["results"] = get_product_data(query, 0, limit)
-		return search_results
-
-	if not query:
-		return search_results
-
-	redis = frappe.cache()
-	query = clean_up_query(query)
-
-	# TODO: Check perf/correctness with Suggestions & Query vs only Query
-	# TODO: Use Levenshtein Distance in Query (max=3)
-	redisearch = redis.ft(WEBSITE_ITEM_INDEX)
-	suggestions = redisearch.sugget(
-		WEBSITE_ITEM_NAME_AUTOCOMPLETE,
-		query,
-		num=limit,
-		fuzzy=fuzzy_search and len(query) > 3,
-	)
-
-	# Build a query
-	query_string = query
-
-	for s in suggestions:
-		query_string += f"|('{clean_up_query(s.string)}')"
-
-	q = Query(query_string)
-	results = redisearch.search(q)
-
-	search_results["results"] = list(map(convert_to_dict, results.docs))
-	search_results["results"] = sorted(
-		search_results["results"], key=lambda k: frappe.utils.cint(k["ranking"]), reverse=True
-	)
-
-	return search_results
-
-
-def clean_up_query(query):
-	return "".join(c for c in query if c.isalnum() or c.isspace())
-
-
-def convert_to_dict(redis_search_doc):
-	return redis_search_doc.__dict__
-
-
-@frappe.whitelist(allow_guest=True)
-def get_category_suggestions(query):
-	search_results = {"results": []}
-
-	if not is_redisearch_enabled():
-		# Redisearch module not enabled, query db
-		categories = frappe.db.get_all(
-			"Item Group",
-			filters={"name": ["like", "%{0}%".format(query)], "show_in_website": 1},
-			fields=["name", "route"],
-		)
-		search_results["results"] = categories
-		return search_results
-
-	if not query:
-		return search_results
-
-	ac = frappe.cache().ft()
-	suggestions = ac.sugget(WEBSITE_ITEM_CATEGORY_AUTOCOMPLETE, query, num=10, with_payloads=True)
-
-	results = [json.loads(s.payload) for s in suggestions]
-
-	search_results["results"] = results
-
-	return search_results
diff --git a/erpnext/templates/pages/wishlist.html b/erpnext/templates/pages/wishlist.html
deleted file mode 100644
index 7a81ded..0000000
--- a/erpnext/templates/pages/wishlist.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "templates/web.html" %}
-
-{% block title %} {{ _("Wishlist") }} {% endblock %}
-
-{% block header %}<h3 class="shopping-cart-header mt-2 mb-6">{{ _("Wishlist") }}</h1>{% endblock %}
-
-{% block page_content %}
-{% if items %}
-	<div class="row">
-		<div class="col-md-12 item-card-group-section">
-			<div class="row products-list">
-					{% from "erpnext/templates/includes/macros.html" import wishlist_card %}
-					{% for item in items %}
-						{{ wishlist_card(item, settings) }}
-					{% endfor %}
-			</div>
-		</div>
-	</div>
-{% else %}
-	<div class="cart-empty frappe-card">
-		<div class="cart-empty-state">
-			<img src="/assets/erpnext/images/ui-states/cart-empty-state.png" alt="Empty Cart">
-		</div>
-		<div class="cart-empty-message mt-4">{{ _('Wishlist is empty!') }}</p>
-	</div>
-{% endif %}
-
-{% endblock %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/wishlist.py b/erpnext/templates/pages/wishlist.py
deleted file mode 100644
index 17607e4..0000000
--- a/erpnext/templates/pages/wishlist.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-import frappe
-
-from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
-	get_shopping_cart_settings,
-)
-from erpnext.e_commerce.shopping_cart.cart import _set_price_list
-from erpnext.utilities.product import get_price
-
-
-def get_context(context):
-	is_guest = frappe.session.user == "Guest"
-
-	settings = get_shopping_cart_settings()
-	items = get_wishlist_items() if not is_guest else []
-	selling_price_list = _set_price_list(settings) if not is_guest else None
-
-	items = set_stock_price_details(items, settings, selling_price_list)
-
-	context.body_class = "product-page"
-	context.items = items
-	context.settings = settings
-	context.no_cache = 1
-
-
-def get_stock_availability(item_code, warehouse):
-	from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
-
-	if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1:
-		warehouses = get_child_warehouses(warehouse)
-	else:
-		warehouses = [warehouse] if warehouse else []
-
-	stock_qty = 0.0
-	for warehouse in warehouses:
-		stock_qty += frappe.utils.flt(
-			frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty")
-		)
-
-	return bool(stock_qty)
-
-
-def get_wishlist_items():
-	if not frappe.db.exists("Wishlist", frappe.session.user):
-		return []
-
-	return frappe.db.get_all(
-		"Wishlist Item",
-		filters={"parent": frappe.session.user},
-		fields=[
-			"web_item_name",
-			"item_code",
-			"item_name",
-			"website_item",
-			"warehouse",
-			"image",
-			"item_group",
-			"route",
-		],
-	)
-
-
-def set_stock_price_details(items, settings, selling_price_list):
-	for item in items:
-		if settings.show_stock_availability:
-			item.available = get_stock_availability(item.item_code, item.get("warehouse"))
-
-		price_details = get_price(
-			item.item_code, selling_price_list, settings.default_customer_group, settings.company
-		)
-
-		if price_details:
-			item.formatted_price = price_details.get("formatted_price")
-			item.formatted_mrp = price_details.get("formatted_mrp")
-			if item.formatted_mrp:
-				item.discount = price_details.get("formatted_discount_percent") or price_details.get(
-					"formatted_discount_rate"
-				)
-
-	return items
diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py
index e967f70..7897c15 100644
--- a/erpnext/utilities/product.py
+++ b/erpnext/utilities/product.py
@@ -2,93 +2,12 @@
 # License: GNU General Public License v3. See license.txt
 
 import frappe
-from frappe.utils import cint, flt, fmt_money, getdate, nowdate
+from frappe.utils import cint, flt, fmt_money
 
 from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item
-from erpnext.stock.doctype.batch.batch import get_batch_qty
-from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
 
 
-def get_web_item_qty_in_stock(item_code, item_warehouse_field, warehouse=None):
-	in_stock, stock_qty = 0, ""
-	template_item_code, is_stock_item = frappe.db.get_value(
-		"Item", item_code, ["variant_of", "is_stock_item"]
-	)
-
-	if not warehouse:
-		warehouse = frappe.db.get_value("Website Item", {"item_code": item_code}, item_warehouse_field)
-
-	if not warehouse and template_item_code and template_item_code != item_code:
-		warehouse = frappe.db.get_value(
-			"Website Item", {"item_code": template_item_code}, item_warehouse_field
-		)
-
-	if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1:
-		warehouses = get_child_warehouses(warehouse)
-	else:
-		warehouses = [warehouse] if warehouse else []
-
-	total_stock = 0.0
-	if warehouses:
-		for warehouse in warehouses:
-			stock_qty = frappe.db.sql(
-				"""
-				select GREATEST(S.actual_qty - S.reserved_qty - S.reserved_qty_for_production - S.reserved_qty_for_sub_contract, 0) / IFNULL(C.conversion_factor, 1)
-				from tabBin S
-				inner join `tabItem` I on S.item_code = I.Item_code
-				left join `tabUOM Conversion Detail` C on I.sales_uom = C.uom and C.parent = I.Item_code
-				where S.item_code=%s and S.warehouse=%s""",
-				(item_code, warehouse),
-			)
-
-			if stock_qty:
-				total_stock += adjust_qty_for_expired_items(item_code, stock_qty, warehouse)
-
-		in_stock = total_stock > 0 and 1 or 0
-
-	return frappe._dict(
-		{"in_stock": in_stock, "stock_qty": total_stock, "is_stock_item": is_stock_item}
-	)
-
-
-def adjust_qty_for_expired_items(item_code, stock_qty, warehouse):
-	batches = frappe.get_all("Batch", filters=[{"item": item_code}], fields=["expiry_date", "name"])
-	expired_batches = get_expired_batches(batches)
-	stock_qty = [list(item) for item in stock_qty]
-
-	for batch in expired_batches:
-		if warehouse:
-			stock_qty[0][0] = max(0, stock_qty[0][0] - get_batch_qty(batch, warehouse))
-		else:
-			stock_qty[0][0] = max(0, stock_qty[0][0] - qty_from_all_warehouses(get_batch_qty(batch)))
-
-		if not stock_qty[0][0]:
-			break
-
-	return stock_qty[0][0] if stock_qty else 0
-
-
-def get_expired_batches(batches):
-	"""
-	:param batches: A list of dict in the form [{'expiry_date': datetime.date(20XX, 1, 1), 'name': 'batch_id'}, ...]
-	"""
-	return [b.name for b in batches if b.expiry_date and b.expiry_date <= getdate(nowdate())]
-
-
-def qty_from_all_warehouses(batch_info):
-	"""
-	:param batch_info: A list of dict in the form [{u'warehouse': u'Stores - I', u'qty': 0.8}, ...]
-	"""
-	qty = 0
-	for batch in batch_info:
-		qty = qty + batch.qty
-
-	return qty
-
-
-def get_price(item_code, price_list, customer_group, company, qty=1):
-	from erpnext.e_commerce.shopping_cart.cart import get_party
-
+def get_price(item_code, price_list, customer_group, company, qty=1, party=None):
 	template_item_code = frappe.db.get_value("Item", item_code, "variant_of")
 
 	if price_list:
@@ -106,7 +25,6 @@
 			)
 
 		if price:
-			party = get_party()
 			pricing_rule_dict = frappe._dict(
 				{
 					"item_code": item_code,
@@ -187,16 +105,62 @@
 			return price_obj
 
 
-def get_non_stock_item_status(item_code, item_warehouse_field):
-	# if item is a product bundle, check if its bundle items are in stock
-	if frappe.db.exists("Product Bundle", item_code):
-		items = frappe.get_doc("Product Bundle", item_code).get_all_children()
-		bundle_warehouse = frappe.db.get_value(
-			"Website Item", {"item_code": item_code}, item_warehouse_field
+def get_item_codes_by_attributes(attribute_filters, template_item_code=None):
+	items = []
+
+	for attribute, values in attribute_filters.items():
+		attribute_values = values
+
+		if not isinstance(attribute_values, list):
+			attribute_values = [attribute_values]
+
+		if not attribute_values:
+			continue
+
+		wheres = []
+		query_values = []
+		for attribute_value in attribute_values:
+			wheres.append("( attribute = %s and attribute_value = %s )")
+			query_values += [attribute, attribute_value]
+
+		attribute_query = " or ".join(wheres)
+
+		if template_item_code:
+			variant_of_query = "AND t2.variant_of = %s"
+			query_values.append(template_item_code)
+		else:
+			variant_of_query = ""
+
+		query = """
+			SELECT
+				t1.parent
+			FROM
+				`tabItem Variant Attribute` t1
+			WHERE
+				1 = 1
+				AND (
+					{attribute_query}
+				)
+				AND EXISTS (
+					SELECT
+						1
+					FROM
+						`tabItem` t2
+					WHERE
+						t2.name = t1.parent
+						{variant_of_query}
+				)
+			GROUP BY
+				t1.parent
+			ORDER BY
+				NULL
+		""".format(
+			attribute_query=attribute_query, variant_of_query=variant_of_query
 		)
-		return all(
-			get_web_item_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock
-			for d in items
-		)
-	else:
-		return 1
+
+		item_codes = set([r[0] for r in frappe.db.sql(query, query_values)])
+		items.append(item_codes)
+
+	res = list(set.intersection(*items))
+
+	return res
diff --git a/erpnext/www/all-products/__init__.py b/erpnext/www/all-products/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/www/all-products/__init__.py
+++ /dev/null
diff --git a/erpnext/www/all-products/index.html b/erpnext/www/all-products/index.html
deleted file mode 100644
index 04fc74c..0000000
--- a/erpnext/www/all-products/index.html
+++ /dev/null
@@ -1,51 +0,0 @@
-{% from "erpnext/templates/includes/macros.html" import attribute_filter_section, field_filter_section, discount_range_filters %}
-{% extends "templates/web.html" %}
-
-{% block title %}{{ _('All Products') }}{% endblock %}
-{% block header %}
-<div class="mb-6">{{ _('All Products') }}</div>
-{% endblock header %}
-
-{% block page_content %}
-<div class="row">
-	<!-- Items section -->
-	<div id="product-listing" class="col-12 order-2 col-md-9 order-md-2 item-card-group-section">
-		<!-- Rendered via JS -->
-	</div>
-
-	<!-- Filters Section -->
-	<div class="col-12 order-1 col-md-3 order-md-1">
-		<div class="collapse d-md-block mr-4 filters-section" id="product-filters">
-			<div class="d-flex justify-content-between align-items-center mb-5 title-section">
-				<div class="mb-4 filters-title" > {{ _('Filters') }} </div>
-				<a class="mb-4 clear-filters" href="/all-products">{{ _('Clear All') }}</a>
-			</div>
-			<!-- field filters -->
-			{% if field_filters %}
-				{{ field_filter_section(field_filters) }}
-			{% endif %}
-
-			<!-- attribute filters -->
-			{% if attribute_filters %}
-				{{ attribute_filter_section(attribute_filters) }}
-			{% endif %}
-		</div>
-
-	</div>
-</div>
-
-<script>
-	frappe.ready(() => {
-		$('.btn-prev, .btn-next').click((e) => {
-			const $btn = $(e.target);
-			$btn.prop('disabled', true);
-			const start = $btn.data('start');
-			let query_params = frappe.utils.get_query_params();
-			query_params.start = start;
-			let path = window.location.pathname + '?' + frappe.utils.get_url_from_dict(query_params);
-			window.location.href = path;
-		});
-	});
-</script>
-
-{% endblock %}
diff --git a/erpnext/www/all-products/index.js b/erpnext/www/all-products/index.js
deleted file mode 100644
index 98a8441..0000000
--- a/erpnext/www/all-products/index.js
+++ /dev/null
@@ -1,27 +0,0 @@
-$(() => {
-	class ProductListing {
-		constructor() {
-			let me = this;
-			let is_item_group_page = $(".item-group-content").data("item-group");
-			this.item_group = is_item_group_page || null;
-
-			let view_type = localStorage.getItem("product_view") || "List View";
-
-			// Render Product Views, Filters & Search
-			new erpnext.ProductView({
-				view_type: view_type,
-				products_section: $('#product-listing'),
-				item_group: me.item_group
-			});
-
-			this.bind_card_actions();
-		}
-
-		bind_card_actions() {
-			erpnext.e_commerce.shopping_cart.bind_add_to_cart_action();
-			erpnext.e_commerce.wishlist.bind_wishlist_action();
-		}
-	}
-
-	new ProductListing();
-});
diff --git a/erpnext/www/all-products/index.py b/erpnext/www/all-products/index.py
deleted file mode 100644
index fbf0dce..0000000
--- a/erpnext/www/all-products/index.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import frappe
-from frappe.utils import cint
-
-from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder
-
-sitemap = 1
-
-
-def get_context(context):
-	# Add homepage as parent
-	context.body_class = "product-page"
-	context.parents = [{"name": frappe._("Home"), "route": "/"}]
-
-	filter_engine = ProductFiltersBuilder()
-	context.field_filters = filter_engine.get_field_filters()
-	context.attribute_filters = filter_engine.get_attribute_filters()
-
-	context.page_length = (
-		cint(frappe.db.get_single_value("E Commerce Settings", "products_per_page")) or 20
-	)
-
-	context.no_cache = 1
diff --git a/erpnext/www/all-products/not_found.html b/erpnext/www/all-products/not_found.html
deleted file mode 100644
index 91989a9..0000000
--- a/erpnext/www/all-products/not_found.html
+++ /dev/null
@@ -1 +0,0 @@
-<div class="d-flex justify-content-center p-3 text-muted">{{ _('No products found') }}</div>
diff --git a/erpnext/www/shop-by-category/__init__.py b/erpnext/www/shop-by-category/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/www/shop-by-category/__init__.py
+++ /dev/null
diff --git a/erpnext/www/shop-by-category/category_card_section.html b/erpnext/www/shop-by-category/category_card_section.html
deleted file mode 100644
index 56cb63a..0000000
--- a/erpnext/www/shop-by-category/category_card_section.html
+++ /dev/null
@@ -1,30 +0,0 @@
-{%- macro card(title, image, type, url=None, text_primary=False) -%}
-<!-- style defined at shop-by-category index -->
-<div class="card category-card" data-type="{{ type }}" data-name="{{ title }}">
-	{% if image %}
-	<img class="card-img-top" src="{{ image }}" alt="{{ title }}" style="height: 80%;">
-	{% else %}
-	<div class="placeholder-div">
-		<span class="placeholder">
-			{{ frappe.utils.get_abbr(title) }}
-		</span>
-	</div>
-	{% endif %}
-	<div class="card-body text-center text-muted">
-		{{ title or '' }}
-	</div>
-	<a href="{{ url or '#' }}" class="stretched-link"></a>
-</div>
-{%- endmacro -%}
-
-<div class="col-12 item-card-group-section">
-	<div class="row products-list product-category-section">
-		{%- for row in data -%}
-			{%- set title = row.name -%}
-			{%- set image = row.get("image") -%}
-			{%- if title -%}
-				{{ card(title, image, type, row.get("route")) }}
-			{%- endif -%}
-		{%- endfor -%}
-	</div>
-</div>
\ No newline at end of file
diff --git a/erpnext/www/shop-by-category/index.html b/erpnext/www/shop-by-category/index.html
deleted file mode 100644
index 04d2d57..0000000
--- a/erpnext/www/shop-by-category/index.html
+++ /dev/null
@@ -1,48 +0,0 @@
-{% extends "templates/web.html" %}
-{% block title %}{{ _('Shop by Category') }}{% endblock %}
-
-{% block head_include %}
-<style>
-	.category-slideshow {
-		margin-bottom: 2rem;
-	}
-	.category-card {
-		height: 300px !important;
-		width: 300px !important;
-		margin: 30px !important;
-	}
-</style>
-{% endblock %}
-
-{% block script %}
-<script type="text/javascript" src="/shop-by-category/index.js"></script>
-{% endblock %}
-
-{% block page_content %}
-<div class="shop-by-category-content">
-	<div class="category-slideshow">
-		{% if slideshow %}
-		<!-- slideshow -->
-			{{ web_block(
-				"Hero Slider",
-				values=slideshow,
-				add_container=0,
-				add_top_padding=0,
-				add_bottom_padding=0,
-			) }}
-		{% endif %}
-	</div>
-	<div class="category-tabs">
-		{% if tabs %}
-		<!-- tabs -->
-			{{ web_block(
-				"Section with Tabs",
-				values=tabs,
-				add_container=0,
-				add_top_padding=0,
-				add_bottom_padding=0
-			) }}
-		{% endif %}
-	</div>
-</div>
-{% endblock %}
\ No newline at end of file
diff --git a/erpnext/www/shop-by-category/index.js b/erpnext/www/shop-by-category/index.js
deleted file mode 100644
index 1b3116f..0000000
--- a/erpnext/www/shop-by-category/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-$(() => {
-	$('.category-card').on('click', (e) => {
-		let category_type = e.currentTarget.dataset.type;
-		let category_name = e.currentTarget.dataset.name;
-
-		if (category_type != "item_group") {
-			let filters = {};
-			filters[category_type] =  [category_name];
-			window.location.href = "/all-products?field_filters=" + JSON.stringify(filters);
-		}
-	});
-});
\ No newline at end of file
diff --git a/erpnext/www/shop-by-category/index.py b/erpnext/www/shop-by-category/index.py
deleted file mode 100644
index 913c183..0000000
--- a/erpnext/www/shop-by-category/index.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import frappe
-from frappe import _
-
-sitemap = 1
-
-
-def get_context(context):
-	context.body_class = "product-page"
-
-	settings = frappe.get_cached_doc("E Commerce Settings")
-	context.categories_enabled = settings.enable_field_filters
-
-	if context.categories_enabled:
-		categories = [row.fieldname for row in settings.filter_fields]
-		context.tabs = get_tabs(categories)
-
-	if settings.slideshow:
-		context.slideshow = get_slideshow(settings.slideshow)
-
-	context.no_cache = 1
-
-
-def get_slideshow(slideshow):
-	values = {"show_indicators": 1, "show_controls": 1, "rounded": 1, "slider_name": "Categories"}
-	slideshow = frappe.get_cached_doc("Website Slideshow", slideshow)
-	slides = slideshow.get({"doctype": "Website Slideshow Item"})
-	for index, slide in enumerate(slides, start=1):
-		values[f"slide_{index}_image"] = slide.image
-		values[f"slide_{index}_title"] = slide.heading
-		values[f"slide_{index}_subtitle"] = slide.description
-		values[f"slide_{index}_theme"] = slide.get("theme") or "Light"
-		values[f"slide_{index}_content_align"] = slide.get("content_align") or "Centre"
-		values[f"slide_{index}_primary_action"] = slide.url
-
-	return values
-
-
-def get_tabs(categories):
-	tab_values = {
-		"title": _("Shop by Category"),
-	}
-
-	categorical_data = get_category_records(categories)
-	for index, tab in enumerate(categorical_data, start=1):
-		tab_values[f"tab_{index + 1}_title"] = frappe.unscrub(tab)
-		# pre-render cards for each tab
-		tab_values[f"tab_{index + 1}_content"] = frappe.render_template(
-			"erpnext/www/shop-by-category/category_card_section.html",
-			{"data": categorical_data[tab], "type": tab},
-		)
-	return tab_values
-
-
-def get_category_records(categories: list):
-	categorical_data = {}
-	website_item_meta = frappe.get_meta("Website Item", cached=True)
-
-	for c in categories:
-		if c == "item_group":
-			categorical_data["item_group"] = frappe.db.get_all(
-				"Item Group",
-				filters={"parent_item_group": "All Item Groups", "show_in_website": 1},
-				fields=["name", "parent_item_group", "is_group", "image", "route"],
-			)
-
-			continue
-
-		field_type = website_item_meta.get_field(c).fieldtype
-
-		if field_type == "Table MultiSelect":
-			child_doc = website_item_meta.get_field(c).options
-			for field in frappe.get_meta(child_doc, cached=True).fields:
-				if field.fieldtype == "Link" and field.reqd:
-					doctype = field.options
-		else:
-			doctype = website_item_meta.get_field(c).options
-
-		fields = ["name"]
-
-		try:
-			meta = frappe.get_meta(doctype, cached=True)
-			if meta.get_field("image"):
-				fields += ["image"]
-
-			data = frappe.db.get_all(doctype, fields=fields)
-			categorical_data[c] = data
-		except BaseException:
-			frappe.throw(_("DocType {} not found").format(doctype))
-			continue
-
-	return categorical_data