fix: Items Query, Sub categories, Review Button

- Include Item Variant table in query only if attributes are involved
- Render sub categories of they exist, even without items
- 'Write a Review' provision only if user is a customer
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py
index f47b722..98d680b 100644
--- a/erpnext/e_commerce/doctype/website_item/website_item.py
+++ b/erpnext/e_commerce/doctype/website_item/website_item.py
@@ -433,15 +433,16 @@
 		user = frappe.session.user
 
 	contact_name = get_contact_name(user)
-	party = None
+	customer = 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
+		for link in contact.links:
+			if link.link_doctype == "Customer":
+				customer = link.link_name
+				break
 
-	return True if party else False
+	return True if customer else False
 
 @frappe.whitelist(allow_guest=True)
 def get_product_filter_data():
diff --git a/erpnext/e_commerce/product_query.py b/erpnext/e_commerce/product_query.py
index 9e675e5..608e9d9 100644
--- a/erpnext/e_commerce/product_query.py
+++ b/erpnext/e_commerce/product_query.py
@@ -104,27 +104,24 @@
 		elif not frappe.db.get_value("Item", item.item_code, "is_stock_item"):
 			item.in_stock = "green" # non-stock item will always be available
 
-	def query_items(self, conditions, or_conditions, substitutions, start=0):
+	def query_items(self, conditions, or_conditions, substitutions, start=0, with_attributes=False):
 		"""Build a query to fetch Website Items based on field filters."""
 		self.query_fields = (", ").join(self.fields)
 
-		return frappe.db.sql("""
-			select distinct {query_fields}
+		attribute_table = ", `tabItem Variant Attribute` iva" if with_attributes else ""
+
+		return frappe.db.sql(f"""
+			select distinct {self.query_fields}
 			from
-				`tabWebsite Item` wi, `tabItem Variant Attribute` iva
+				`tabWebsite Item` wi {attribute_table}
 			where
 				wi.published = 1
 				{conditions}
 				{or_conditions}
-			limit {limit} offset {start}
-		""".format(
-				query_fields=self.query_fields,
-				conditions=conditions,
-				or_conditions=or_conditions,
-				limit=self.page_length,
-				start=start),
-			tuple(substitutions),
-			as_dict=1)
+			limit {self.page_length} offset {start}
+		""",
+		tuple(substitutions),
+		as_dict=1)
 
 	def query_items_with_attributes(self, attributes, start=0):
 		"""Build a query to fetch Website Items based on field & attribute filters."""
@@ -142,7 +139,8 @@
 				.format(attribute, (", ").join(['%s'] * len(values)))
 			substitutions_copy.extend(values)
 
-			items = self.query_items(conditions_copy, self.or_conditions, substitutions_copy, start=start)
+			items = self.query_items(conditions_copy, self.or_conditions, substitutions_copy,
+				start=start, with_attributes=True)
 
 			items_dict = {item.name: item for item in items}
 			# TODO: Replace Variants by their parent templates
diff --git a/erpnext/e_commerce/product_view.js b/erpnext/e_commerce/product_view.js
index 5fcd0a0..372e722 100644
--- a/erpnext/e_commerce/product_view.js
+++ b/erpnext/e_commerce/product_view.js
@@ -32,18 +32,17 @@
 			method: 'erpnext.e_commerce.doctype.website_item.website_item.get_product_filter_data',
 			args: args,
 			callback: function(result) {
-				if (!result.exc && result) {
-					if (!result.message || !result.message[0].length) {
-						console.log("no items");
+				if (!result.exc && result && result.message) {
+					if (me.item_group && result.message[3].length) {
+						me.render_item_sub_categories(result.message[3]);
+					}
+
+					if (!result.message[0].length) {
 						// if result has no items or result is empty
 						me.render_no_products_section();
 					} else {
-						console.log("there are items");
 						me.render_filters(result.message[1]);
 
-						if (me.item_group) {
-							me.render_item_sub_categories(result.message[3]);
-						}
 						// Render views
 						me.render_list_view(result.message[0], result.message[2]);
 						me.render_grid_view(result.message[0], result.message[2]);