feat: add ProductQuery engine
This commit is contained in:
parent
d0437cfb59
commit
293f483cb4
89
erpnext/shopping_cart/product_query.py
Normal file
89
erpnext/shopping_cart/product_query.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
class ProductQuery:
|
||||||
|
"""Query engine for product listing
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
cart_settings (Document): Settings for Cart
|
||||||
|
fields (list): Fields to fetch in query
|
||||||
|
filters (list)
|
||||||
|
or_filters (list)
|
||||||
|
page_length (Int): Length of page for the query
|
||||||
|
settings (Document): Products Settings DocType
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.settings = frappe.get_doc("Products Settings")
|
||||||
|
self.cart_settings = frappe.get_doc("Shopping Cart Settings")
|
||||||
|
self.page_length = self.settings.products_per_page or 20
|
||||||
|
self.fields = ['name', 'item_name', 'website_image', 'variant_of', 'has_variants', 'item_group', 'image', 'web_long_description', 'description', 'route']
|
||||||
|
self.filters = [['show_in_website', '=', 1]]
|
||||||
|
self.or_filters = []
|
||||||
|
|
||||||
|
def query(self, attributes=None, fields=None, search_term=None, start=0):
|
||||||
|
if fields: self.build_fields_filters(fields)
|
||||||
|
if search_term: self.build_search_filters(search_term)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
if attributes:
|
||||||
|
all_items = []
|
||||||
|
for attribute, values in attributes.items():
|
||||||
|
if not isinstance(values, list):
|
||||||
|
values = [values]
|
||||||
|
|
||||||
|
items = frappe.get_all(
|
||||||
|
"Item",
|
||||||
|
fields=self.fields,
|
||||||
|
filters=[
|
||||||
|
*self.filters,
|
||||||
|
["Item Variant Attribute", "attribute", "=", attribute],`
|
||||||
|
["Item Variant Attribute", "attribute_value", "in", values],
|
||||||
|
],
|
||||||
|
or_filters=self.or_filters,
|
||||||
|
limit=self.page_length
|
||||||
|
)
|
||||||
|
|
||||||
|
items_dict = {item.name: item for item in items}
|
||||||
|
|
||||||
|
all_items.append(set(items.keys()))
|
||||||
|
|
||||||
|
result = [items_dict.get(item) for item in list(set.intersection(*all_items))]
|
||||||
|
else:
|
||||||
|
result = frappe.get_all("Item", fields=self.fields, filters=self.filters, or_filters=self.or_filters, limit=self.page_length)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def build_fields_filters(self, filters):
|
||||||
|
for field, values in filters.items():
|
||||||
|
if not values:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(values, list):
|
||||||
|
self.filters.append([field, 'IN', values])
|
||||||
|
else:
|
||||||
|
self.filters.append([field, '=', values])
|
||||||
|
|
||||||
|
def build_search_filters(self, search_term):
|
||||||
|
# Default fields to search from
|
||||||
|
default_fields = {'name', 'item_name', 'description', 'item_group'}
|
||||||
|
|
||||||
|
# Get meta search fields
|
||||||
|
meta = frappe.get_meta("Item")
|
||||||
|
meta_fields = set(meta.get_search_fields())
|
||||||
|
|
||||||
|
# Join the meta fields and default fields set
|
||||||
|
search_fields = default_fields.union(meta_fields)
|
||||||
|
try:
|
||||||
|
if frappe.db.count('Item', cache=True) > 50000:
|
||||||
|
search_fields.remove('description')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Build or filters for query
|
||||||
|
search = '%{}%'.format(search_term)
|
||||||
|
self.or_filters += [[field, 'like', search] for field in search_fields]
|
@ -1,6 +1,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from erpnext.portal.product_configurator.utils import (get_products_for_website, get_product_settings,
|
from erpnext.portal.product_configurator.utils import (get_products_for_website, get_product_settings,
|
||||||
get_field_filter_data, get_attribute_filter_data)
|
get_field_filter_data, get_attribute_filter_data)
|
||||||
|
from erpnext.shopping_cart.product_query import ProductQuery
|
||||||
|
|
||||||
sitemap = 1
|
sitemap = 1
|
||||||
|
|
||||||
@ -12,10 +13,14 @@ def get_context(context):
|
|||||||
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
|
||||||
else:
|
else:
|
||||||
search = field_filters = attribute_filters = None
|
search = field_filters = attribute_filters = None
|
||||||
|
|
||||||
context.items = get_products_for_website(field_filters, attribute_filters, search)
|
# items = get_products_for_website(field_filters, attribute_filters, search)
|
||||||
|
|
||||||
|
engine = ProductQuery()
|
||||||
|
items = engine.query(attribute_filters, field_filters, search)
|
||||||
|
|
||||||
product_settings = get_product_settings()
|
product_settings = get_product_settings()
|
||||||
|
context.items = items
|
||||||
context.field_filters = get_field_filter_data() \
|
context.field_filters = get_field_filter_data() \
|
||||||
if product_settings.enable_field_filters else []
|
if product_settings.enable_field_filters else []
|
||||||
|
|
||||||
@ -23,6 +28,7 @@ def get_context(context):
|
|||||||
if product_settings.enable_attribute_filters else []
|
if product_settings.enable_attribute_filters else []
|
||||||
|
|
||||||
context.product_settings = product_settings
|
context.product_settings = product_settings
|
||||||
|
context.body_class = "product-page"
|
||||||
context.page_length = product_settings.products_per_page
|
context.page_length = product_settings.products_per_page
|
||||||
|
|
||||||
context.no_cache = 1
|
context.no_cache = 1
|
||||||
|
Loading…
Reference in New Issue
Block a user