diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json index fc2a56567b7..67b4a3d7f82 100644 --- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.json @@ -6,6 +6,11 @@ "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", @@ -18,15 +23,6 @@ "show_apply_coupon_code_in_website", "show_contact_us_button", "show_attachments", - "guest_display_settings_section", - "hide_price_for_guest", - "redirect_on_action", - "add_ons_section", - "enable_wishlist", - "column_break_22", - "enable_reviews", - "column_break_23", - "enable_recommendations", "section_break_18", "company", "price_list", @@ -42,19 +38,22 @@ "save_quotations_as_draft", "payment_gateway_account", "payment_success_url", - "filter_categories_section", - "enable_field_filters", - "filter_fields", - "enable_attribute_filters", - "filter_attributes", - "shop_by_category_section", - "slideshow", + "add_ons_section", + "enable_wishlist", + "column_break_22", + "enable_reviews", + "column_break_23", + "enable_recommendations", "item_search_settings_section", "redisearch_warning", "search_index_fields", "show_categories_in_search_autocomplete", - "show_brand_line", - "is_redisearch_loaded" + "is_redisearch_loaded", + "shop_by_category_section", + "slideshow", + "guest_display_settings_section", + "hide_price_for_guest", + "redirect_on_action" ], "fields": [ { @@ -309,14 +308,6 @@ "label": "Show Categories in Search Autocomplete", "read_only_depends_on": "eval:!doc.is_redisearch_loaded" }, - { - "default": "0", - "description": "e.g. \"iPhone 12 by Apple\"", - "fieldname": "show_brand_line", - "fieldtype": "Check", - "label": "Show Brand Line", - "read_only_depends_on": "eval:!doc.is_redisearch_loaded" - }, { "default": "0", "fieldname": "is_redisearch_loaded", @@ -379,7 +370,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-08-24 21:10:45.669526", + "modified": "2021-08-31 12:23:06.187619", "modified_by": "Administrator", "module": "E-commerce", "name": "E Commerce Settings", diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py index 38490375a14..c3a34443df2 100644 --- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py @@ -21,7 +21,6 @@ class ECommerceSettings(Document): self.validate_field_filters() self.validate_attribute_filters() self.validate_checkout() - self.validate_brand_check() self.validate_search_index_fields() if self.enabled: @@ -71,10 +70,6 @@ class ECommerceSettings(Document): self.search_index_fields = ','.join(fields) - def validate_brand_check(self): - if self.show_brand_line and not ("brand" in self.search_index_fields): - self.search_index_fields += ",brand" - 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 diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py index 7c661dc7e78..2d71907b2c9 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.py +++ b/erpnext/e_commerce/doctype/website_item/website_item.py @@ -187,12 +187,17 @@ class WebsiteItem(WebsiteGenerator): def get_context(self, context): context.show_search = True - context.search_link = '/search' + 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_variant_context(context) self.set_attribute_context(context) self.set_disabled_attributes(context) @@ -254,11 +259,9 @@ class WebsiteItem(WebsiteGenerator): context[fieldname] = value - if self.slideshow: - if context.variant and context.variant.slideshow: - context.update(get_slideshow(context.variant)) - else: - context.update(get_slideshow(self)) + if self.slideshow and context.variant and context.variant.slideshow: + context.update(get_slideshow(context.variant)) + def set_attribute_context(self, context): if not self.has_variants: diff --git a/erpnext/e_commerce/product_data_engine/filters.py b/erpnext/e_commerce/product_data_engine/filters.py index d9faf81fb63..fc58b44f0ee 100644 --- a/erpnext/e_commerce/product_data_engine/filters.py +++ b/erpnext/e_commerce/product_data_engine/filters.py @@ -135,11 +135,15 @@ class ProductFiltersBuilder: 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 above" + label = f"{discount}% and below" discount_filters.append([discount, label]) return discount_filters \ No newline at end of file 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 index f6ff2d1a5c7..577c11be6bb 100644 --- a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py +++ b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py @@ -226,7 +226,7 @@ class TestProductDataEngine(unittest.TestCase): self.assertEqual(len(discount_filters[0]), 2) self.assertEqual(discount_filters[0][0], 10) - self.assertEqual(discount_filters[0][1], "10% and above") + self.assertEqual(discount_filters[0][1], "10% and below") def test_product_list_with_discount_filters(self): "Test if discount filters are applied correctly." @@ -261,7 +261,7 @@ class TestProductDataEngine(unittest.TestCase): ) items = result.get("items") - # check if only product with 10% and above discount are fetched in the right order + # check if only product with 10% and below discount are fetched in the right order self.assertEqual(len(items), 2) self.assertEqual(items[0].get("item_code"), "Test 13I Laptop") self.assertEqual(items[1].get("item_code"), "Test 12I Laptop") diff --git a/erpnext/e_commerce/product_ui/grid.js b/erpnext/e_commerce/product_ui/grid.js index d0b0e3b7013..51a13b0e0bb 100644 --- a/erpnext/e_commerce/product_ui/grid.js +++ b/erpnext/e_commerce/product_ui/grid.js @@ -143,7 +143,7 @@ erpnext.ProductGrid = class { get_stock_availability(item, settings) { if (settings.show_stock_availability && !item.has_variants && !item.in_stock) { - return `${ __("Out of stock") }`; + return `${ __("Out of stock") }`; } return ``; } @@ -161,7 +161,7 @@ erpnext.ProductGrid = class { return `
diff --git a/erpnext/e_commerce/product_ui/list.js b/erpnext/e_commerce/product_ui/list.js index e5791bb36d5..7056a1af8c3 100644 --- a/erpnext/e_commerce/product_ui/list.js +++ b/erpnext/e_commerce/product_ui/list.js @@ -24,7 +24,7 @@ erpnext.ProductList = class { let title = item.web_item_name || item.item_name || item.item_code || ""; title = title.length > 200 ? title.substr(0, 200) + "..." : title; - html += `
`; + html += `
`; html += me.get_image_html(item, title, me.settings); html += me.get_row_body_html(item, title, me.settings); html += `
`; @@ -86,7 +86,7 @@ erpnext.ProductList = class { `; if (settings.enabled) { - title_html += `
`; + title_html += `
`; title_html += this.get_primary_button(item, settings); title_html += `
`; } @@ -151,9 +151,7 @@ erpnext.ProductList = class { if (item.has_variants) { return ` -
+
${ __('Explore') }
@@ -161,10 +159,10 @@ erpnext.ProductList = class { } else if (settings.enabled && (settings.allow_items_not_in_stock || item.in_stock)) { return `
@@ -174,14 +172,14 @@ erpnext.ProductList = class { ${ __('Add to Cart') }
-
+
1
diff --git a/erpnext/e_commerce/product_ui/search.js b/erpnext/e_commerce/product_ui/search.js index ebe007624a0..9bae1c10bc4 100644 --- a/erpnext/e_commerce/product_ui/search.js +++ b/erpnext/e_commerce/product_ui/search.js @@ -38,39 +38,37 @@ erpnext.ProductSearch = class { let query = e.target.value; if (query.length == 0) { - me.populateResults([]); - me.populateCategoriesList([]); + me.populateResults(null); + me.populateCategoriesList(null); } if (query.length < 3 || !query.length) return; - // Populate recent search chips - me.setRecentSearches(query); - - // Fetch and populate product results frappe.call({ method: "erpnext.templates.pages.product_search.search", args: { query: query }, callback: (data) => { - me.populateResults(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); + } } }); - // Populate categories - if (me.category_container) { - frappe.call({ - method: "erpnext.templates.pages.product_search.get_category_suggestions", - args: { - query: query - }, - callback: (data) => { - me.populateCategoriesList(data); - } - }); - } - this.search_dropdown.removeClass("hidden"); }); } @@ -186,17 +184,16 @@ erpnext.ProductSearch = class { this.attachEventListenersToChips(); } - populateResults(data) { - if (data.length === 0 || data.message.results.length === 0) { + populateResults(product_results) { + if (!product_results || product_results.length === 0) { let empty_html = ``; this.products_container.html(empty_html); return; } let html = ""; - let search_results = data.message.results; - search_results.forEach((res) => { + product_results.forEach((res) => { let thumbnail = res.thumbnail || '/assets/erpnext/images/ui-states/cart-empty-state.png'; html += `