mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-03 04:09:11 +00:00
chore: Drive E-commerce via Website Item
- Removed Shopping Cart Settings - Portal fully driven via E Commerce Settings - All Item listing querying will happen via ProductQuery engine only - Product Listing via Website Items - removed redundant code - Moved all website logic from Item to Website Item
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
# 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
|
||||
import frappe.defaults
|
||||
from frappe import _, throw
|
||||
@@ -11,10 +9,8 @@ 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.e_commerce.doctype.e_commerce_settings.e_commerce_settings import get_shopping_cart_settings
|
||||
from erpnext.accounts.utils import get_account_name
|
||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import (
|
||||
get_shopping_cart_settings,
|
||||
)
|
||||
from erpnext.utilities.product import get_qty_in_stock
|
||||
|
||||
|
||||
@@ -22,7 +18,7 @@ class WebsitePriceListMissingError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
def set_cart_count(quotation=None):
|
||||
if cint(frappe.db.get_singles_value("Shopping Cart Settings", "enabled")):
|
||||
if cint(frappe.db.get_singles_value("E Commerce Settings", "enabled")):
|
||||
if not quotation:
|
||||
quotation = _get_cart_quotation()
|
||||
cart_count = cstr(len(quotation.get("items")))
|
||||
@@ -49,7 +45,7 @@ def get_cart_quotation(doc=None):
|
||||
"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("Shopping Cart Settings")
|
||||
"cart_settings": frappe.get_cached_doc("E Commerce Settings")
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -73,7 +69,7 @@ def get_billing_addresses(party=None):
|
||||
@frappe.whitelist()
|
||||
def place_order():
|
||||
quotation = _get_cart_quotation()
|
||||
cart_settings = frappe.db.get_value("Shopping Cart Settings", None,
|
||||
cart_settings = frappe.db.get_value("E Commerce Settings", None,
|
||||
["company", "allow_items_not_in_stock"], as_dict=1)
|
||||
quotation.company = cart_settings.company
|
||||
|
||||
@@ -263,7 +259,7 @@ def guess_territory():
|
||||
territory = frappe.db.get_value("Territory", geoip_country)
|
||||
|
||||
return territory or \
|
||||
frappe.db.get_value("Shopping Cart Settings", None, "territory") or \
|
||||
frappe.db.get_value("E Commerce Settings", None, "territory") or \
|
||||
get_root_of("Territory")
|
||||
|
||||
def decorate_quotation_doc(doc):
|
||||
@@ -286,7 +282,7 @@ def _get_cart_quotation(party=None):
|
||||
if quotation:
|
||||
qdoc = frappe.get_doc("Quotation", quotation[0].name)
|
||||
else:
|
||||
company = frappe.db.get_value("Shopping Cart Settings", None, ["company"])
|
||||
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-",
|
||||
@@ -341,7 +337,7 @@ def apply_cart_settings(party=None, quotation=None):
|
||||
if not quotation:
|
||||
quotation = _get_cart_quotation(party)
|
||||
|
||||
cart_settings = frappe.get_doc("Shopping Cart Settings")
|
||||
cart_settings = frappe.get_doc("E Commerce Settings")
|
||||
|
||||
set_price_list_and_rate(quotation, cart_settings)
|
||||
|
||||
@@ -418,7 +414,7 @@ def get_party(user=None):
|
||||
party_doctype = contact.links[0].link_doctype
|
||||
party = contact.links[0].link_name
|
||||
|
||||
cart_settings = frappe.get_doc("Shopping Cart Settings")
|
||||
cart_settings = frappe.get_doc("E Commerce Settings")
|
||||
|
||||
debtors_account = ''
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Shopping Cart 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>`
|
||||
);
|
||||
}
|
||||
},
|
||||
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', '');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,212 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-06-19 15:57:32",
|
||||
"description": "Default settings for Shopping Cart",
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"enabled",
|
||||
"store_page_docs",
|
||||
"display_settings",
|
||||
"show_attachments",
|
||||
"show_price",
|
||||
"show_stock_availability",
|
||||
"enable_variants",
|
||||
"column_break_7",
|
||||
"show_contact_us_button",
|
||||
"show_quantity_in_website",
|
||||
"show_apply_coupon_code_in_website",
|
||||
"allow_items_not_in_stock",
|
||||
"section_break_2",
|
||||
"company",
|
||||
"price_list",
|
||||
"column_break_4",
|
||||
"default_customer_group",
|
||||
"quotation_series",
|
||||
"section_break_8",
|
||||
"enable_checkout",
|
||||
"save_quotations_as_draft",
|
||||
"column_break_11",
|
||||
"payment_gateway_account",
|
||||
"payment_success_url"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enabled",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Enable Shopping Cart"
|
||||
},
|
||||
{
|
||||
"fieldname": "display_settings",
|
||||
"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": "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"
|
||||
},
|
||||
{
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "section_break_2",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"mandatory_depends_on": "eval: doc.enabled === 1",
|
||||
"options": "Company",
|
||||
"remember_last_selected_value": 1
|
||||
},
|
||||
{
|
||||
"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_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_customer_group",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Default Customer Group",
|
||||
"mandatory_depends_on": "eval: doc.enabled === 1",
|
||||
"options": "Customer Group"
|
||||
},
|
||||
{
|
||||
"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": "section_break_8",
|
||||
"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_11",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "enable_checkout",
|
||||
"fieldname": "payment_gateway_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Payment Gateway Account",
|
||||
"mandatory_depends_on": "enable_checkout",
|
||||
"options": "Payment Gateway Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_variants",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Variants"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval: doc.enable_checkout == 0",
|
||||
"fieldname": "save_quotations_as_draft",
|
||||
"fieldtype": "Check",
|
||||
"label": "Save Quotations as Draft"
|
||||
},
|
||||
{
|
||||
"depends_on": "doc.enabled",
|
||||
"fieldname": "store_page_docs",
|
||||
"fieldtype": "HTML"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-shopping-cart",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-02 17:34:57.642565",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Shopping Cart",
|
||||
"name": "Shopping Cart Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "Website Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
|
||||
class ShoppingCartSetupError(frappe.ValidationError): pass
|
||||
|
||||
class ShoppingCartSettings(Document):
|
||||
def onload(self):
|
||||
self.get("__onload").quotation_series = frappe.get_meta("Quotation").get_options("naming_series")
|
||||
|
||||
def validate(self):
|
||||
if self.enabled:
|
||||
self.validate_price_list_exchange_rate()
|
||||
|
||||
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 validate_cart_settings(doc=None, method=None):
|
||||
frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate")
|
||||
|
||||
def get_shopping_cart_settings():
|
||||
if not getattr(frappe.local, "shopping_cart_settings", None):
|
||||
frappe.local.shopping_cart_settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
|
||||
|
||||
return frappe.local.shopping_cart_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
|
||||
@@ -1,56 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import (
|
||||
ShoppingCartSetupError,
|
||||
)
|
||||
|
||||
|
||||
class TestShoppingCartSettings(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """)
|
||||
|
||||
def get_cart_settings(self):
|
||||
return frappe.get_doc({"doctype": "Shopping Cart Settings",
|
||||
"company": "_Test Company"})
|
||||
|
||||
# NOTE: Exchangrate API has all enabled currencies that ERPNext supports.
|
||||
# We aren't checking just currency exchange record anymore
|
||||
# while validating price list currency exchange rate to that of company.
|
||||
# The API is being used to fetch the rate which again almost always
|
||||
# gives back a valid value (for valid currencies).
|
||||
# This makes the test obsolete.
|
||||
# Commenting because im not sure if there's a better test we can write
|
||||
|
||||
# def test_exchange_rate_exists(self):
|
||||
# frappe.db.sql("""delete from `tabCurrency Exchange`""")
|
||||
|
||||
# cart_settings = self.get_cart_settings()
|
||||
# cart_settings.price_list = "_Test Price List Rest of the World"
|
||||
# self.assertRaises(ShoppingCartSetupError, cart_settings.validate_price_list_exchange_rate)
|
||||
|
||||
# from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \
|
||||
# currency_exchange_records
|
||||
# frappe.get_doc(currency_exchange_records[0]).insert()
|
||||
# cart_settings.validate_price_list_exchange_rate()
|
||||
|
||||
def test_tax_rule_validation(self):
|
||||
frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0")
|
||||
frappe.db.commit()
|
||||
|
||||
cart_settings = self.get_cart_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")
|
||||
|
||||
test_dependencies = ["Tax Rule"]
|
||||
@@ -1,17 +1,14 @@
|
||||
# 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
|
||||
|
||||
from erpnext.shopping_cart.cart import _get_cart_quotation, _set_price_list
|
||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import (
|
||||
from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import (
|
||||
get_shopping_cart_settings,
|
||||
show_quantity_in_website,
|
||||
show_quantity_in_website
|
||||
)
|
||||
from erpnext.utilities.product import get_non_stock_item_status, get_price, get_qty_in_stock
|
||||
|
||||
from erpnext.utilities.product import get_price, get_qty_in_stock, get_non_stock_item_status
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_product_info_for_website(item_code, skip_quotation_creation=False):
|
||||
|
||||
@@ -10,26 +10,22 @@ class ProductQuery:
|
||||
"""Query engine for product listing
|
||||
|
||||
Attributes:
|
||||
cart_settings (Document): Settings for Cart
|
||||
fields (list): Fields to fetch in query
|
||||
filters (TYPE): Description
|
||||
or_filters (list): Description
|
||||
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
|
||||
filters (list)
|
||||
or_filters (list)
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.settings = frappe.get_doc("E Commerce 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', 'item_code', 'website_image', 'variant_of', 'has_variants',
|
||||
'item_group', 'image', 'web_long_description', 'description', 'route', 'weightage']
|
||||
self.filters = []
|
||||
self.or_filters = [['show_in_website', '=', 1]]
|
||||
if not self.settings.get('hide_variants'):
|
||||
self.or_filters.append(['show_variant_in_website', '=', 1])
|
||||
self.fields = ['wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of',
|
||||
'wi.has_variants', 'wi.item_group', 'wi.image', 'wi.web_long_description', 'wi.description',
|
||||
'wi.route']
|
||||
self.conditions = ""
|
||||
self.or_conditions = ""
|
||||
self.substitutions = []
|
||||
|
||||
def query(self, attributes=None, fields=None, search_term=None, start=0, item_group=None):
|
||||
"""Summary
|
||||
@@ -57,51 +53,14 @@ class ProductQuery:
|
||||
filters=[["Website Item Group", "item_group", "=", item_group]]
|
||||
)
|
||||
|
||||
self.query_fields = (", ").join(self.fields)
|
||||
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,
|
||||
start=start,
|
||||
limit=self.page_length,
|
||||
order_by="weightage desc"
|
||||
)
|
||||
|
||||
items_dict = {item.name: item for item in items}
|
||||
|
||||
all_items.append(set(items_dict.keys()))
|
||||
|
||||
result = [items_dict.get(item) for item in list(set.intersection(*all_items))]
|
||||
result = self.query_items_with_attributes(attributes, start)
|
||||
else:
|
||||
result = frappe.get_all(
|
||||
"Item",
|
||||
fields=self.fields,
|
||||
filters=self.filters,
|
||||
or_filters=self.or_filters,
|
||||
start=start,
|
||||
limit=self.page_length,
|
||||
order_by="weightage desc"
|
||||
)
|
||||
|
||||
# Combine results having context of website item groups into item results
|
||||
if item_group and website_item_groups:
|
||||
items_list = {row.name for row in result}
|
||||
for row in website_item_groups:
|
||||
if row.wig_parent not in items_list:
|
||||
result.append(row)
|
||||
|
||||
result = sorted(result, key=lambda x: x.get("weightage"), reverse=True)
|
||||
result = self.query_items(self.conditions, self.or_conditions,
|
||||
self.substitutions, start=start)
|
||||
|
||||
# add price info in results
|
||||
for item in result:
|
||||
product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get('product_info')
|
||||
if product_info:
|
||||
@@ -109,6 +68,51 @@ class ProductQuery:
|
||||
|
||||
return result
|
||||
|
||||
def query_items(self, conditions, or_conditions, substitutions, start=0):
|
||||
"""Build a query to fetch Website Items based on field filters."""
|
||||
return frappe.db.sql("""
|
||||
select distinct {query_fields}
|
||||
from
|
||||
`tabWebsite Item` wi, `tabItem Variant Attribute` iva
|
||||
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)
|
||||
|
||||
def query_items_with_attributes(self, attributes, start=0):
|
||||
"""Build a query to fetch Website Items based on field & attribute filters."""
|
||||
all_items = []
|
||||
self.conditions += " and iva.parent = wi.item_code"
|
||||
|
||||
for attribute, values in attributes.items():
|
||||
if not isinstance(values, list): values = [values]
|
||||
|
||||
conditions_copy = self.conditions
|
||||
substitutions_copy = self.substitutions.copy()
|
||||
|
||||
conditions_copy += " and iva.attribute = '{0}' and iva.attribute_value in ({1})" \
|
||||
.format(attribute, (", ").join(['%s'] * len(values)))
|
||||
substitutions_copy.extend(values)
|
||||
|
||||
items = self.query_items(conditions_copy, self.or_conditions, substitutions_copy, start=start)
|
||||
|
||||
items_dict = {item.name: item for item in items}
|
||||
# TODO: Replace Variants by their parent templates
|
||||
|
||||
all_items.append(set(items_dict.keys()))
|
||||
|
||||
result = [items_dict.get(item) for item in list(set.intersection(*all_items))]
|
||||
return result
|
||||
|
||||
def build_fields_filters(self, filters):
|
||||
"""Build filters for field values
|
||||
|
||||
@@ -130,10 +134,11 @@ class ProductQuery:
|
||||
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])
|
||||
self.conditions += " and wi.{0} in ({1})".format(field, (', ').join(['%s'] * len(values)))
|
||||
self.substitutions.extend(values)
|
||||
else:
|
||||
# `=` will be faster than `IN` for most cases
|
||||
self.filters.append([field, '=', values])
|
||||
self.conditions += " and wi.{0} = '{1}'".format(field, values)
|
||||
|
||||
def build_search_filters(self, search_term):
|
||||
"""Query search term in specified fields
|
||||
@@ -158,4 +163,5 @@ class ProductQuery:
|
||||
|
||||
# Build or filters for query
|
||||
search = '%{}%'.format(search_term)
|
||||
self.or_filters += [[field, 'like', search] for field in search_fields]
|
||||
for field in search_fields:
|
||||
self.or_conditions += " or {0} like '{1}'".format(field, search)
|
||||
|
||||
@@ -167,7 +167,7 @@ class TestShoppingCart(unittest.TestCase):
|
||||
|
||||
# helper functions
|
||||
def enable_shopping_cart(self):
|
||||
settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
|
||||
settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings")
|
||||
|
||||
settings.update({
|
||||
"enabled": 1,
|
||||
@@ -197,7 +197,7 @@ class TestShoppingCart(unittest.TestCase):
|
||||
frappe.local.shopping_cart_settings = None
|
||||
|
||||
def disable_shopping_cart(self):
|
||||
settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
|
||||
settings = frappe.get_doc("E Commerce Settings", "E Commerce Settings")
|
||||
settings.enabled = 0
|
||||
settings.save()
|
||||
frappe.local.shopping_cart_settings = None
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import (
|
||||
is_cart_enabled,
|
||||
)
|
||||
|
||||
from erpnext.e_commerce.doctype.e_commerce_settings.e_commerce_settings import is_cart_enabled
|
||||
|
||||
def show_cart_count():
|
||||
if (is_cart_enabled() and
|
||||
|
||||
Reference in New Issue
Block a user