Moved Portal and Shopping Cart to Shopping Cart app, and some minor fixes
diff --git a/erpnext/selling/doctype/lead/lead.js b/erpnext/selling/doctype/lead/lead.js
index 4ab1067..41f679e 100644
--- a/erpnext/selling/doctype/lead/lead.js
+++ b/erpnext/selling/doctype/lead/lead.js
@@ -14,12 +14,12 @@
onload: function() {
if(cur_frm.fields_dict.lead_owner.df.options.match(/^Profile/)) {
cur_frm.fields_dict.lead_owner.get_query = function(doc,cdt,cdn) {
- return { query:"core.doctype.profile.profile.profile_query" } }
+ return { query:"webnotes.core.doctype.profile.profile.profile_query" } }
}
if(cur_frm.fields_dict.contact_by.df.options.match(/^Profile/)) {
cur_frm.fields_dict.contact_by.get_query = function(doc,cdt,cdn) {
- return { query:"core.doctype.profile.profile.profile_query" } }
+ return { query:"webnotes.core.doctype.profile.profile.profile_query" } }
}
if(in_list(user_roles,'System Manager')) {
diff --git a/erpnext/selling/doctype/sales_order/templates/__init__.py b/erpnext/selling/doctype/sales_order/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/sales_order/templates/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/sales_order/templates/pages/__init__.py b/erpnext/selling/doctype/sales_order/templates/pages/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/sales_order/templates/pages/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/sales_order/templates/pages/order.html b/erpnext/selling/doctype/sales_order/templates/pages/order.html
deleted file mode 100644
index 45867ea..0000000
--- a/erpnext/selling/doctype/sales_order/templates/pages/order.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "templates/sale.html" %}
-
-{% block status -%}
- {% if doc.status %}{{ doc.status }}{% endif %}
-{%- endblock %}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/templates/pages/order.py b/erpnext/selling/doctype/sales_order/templates/pages/order.py
deleted file mode 100644
index e172c09..0000000
--- a/erpnext/selling/doctype/sales_order/templates/pages/order.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import webnotes
-from webnotes import _
-
-no_cache = True
-
-def get_context():
- from erpnext.templates.utils import get_transaction_context
- context = get_transaction_context("Sales Order", webnotes.form_dict.name)
- modify_status(context.get("doc"))
- context.update({
- "parent_link": "orders",
- "parent_title": "My Orders"
- })
- return context
-
-def modify_status(doc):
- doc.status = []
- if 0 < doc.per_billed < 100:
- doc.status.append(("label-warning", "icon-ok", _("Partially Billed")))
- elif doc.per_billed == 100:
- doc.status.append(("label-success", "icon-ok", _("Billed")))
-
- if 0 < doc.per_delivered < 100:
- doc.status.append(("label-warning", "icon-truck", _("Partially Delivered")))
- elif doc.per_delivered == 100:
- doc.status.append(("label-success", "icon-truck", _("Delivered")))
- doc.status = " " + " ".join(('<span class="label %s"><i class="icon-fixed-width %s"></i> %s</span>' % s
- for s in doc.status))
diff --git a/erpnext/selling/doctype/sales_order/templates/pages/orders.html b/erpnext/selling/doctype/sales_order/templates/pages/orders.html
deleted file mode 100644
index 0467f34..0000000
--- a/erpnext/selling/doctype/sales_order/templates/pages/orders.html
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "templates/sales_transactions.html" %}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/templates/pages/orders.py b/erpnext/selling/doctype/sales_order/templates/pages/orders.py
deleted file mode 100644
index 5d28d5b..0000000
--- a/erpnext/selling/doctype/sales_order/templates/pages/orders.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import webnotes
-
-no_cache = True
-
-def get_context():
- from erpnext.templates.utils import get_currency_context
- context = get_currency_context()
- context.update({
- "title": "My Orders",
- "method": "selling.doctype.sales_order.templates.pages.orders.get_orders",
- "icon": "icon-list",
- "empty_list_message": "No Orders Yet",
- "page": "order",
- })
- return context
-
-@webnotes.whitelist()
-def get_orders(start=0):
- from erpnext.templates.utils import get_transaction_list
- from erpnext.selling.doctype.sales_order.templates.pages.order import modify_status
- orders = get_transaction_list("Sales Order", start, ["per_billed", "per_delivered"])
- for d in orders:
- modify_status(d)
-
- return orders
-
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_price_list/__init__.py b/erpnext/selling/doctype/shopping_cart_price_list/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/shopping_cart_price_list/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.py b/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.py
deleted file mode 100644
index e5468e5..0000000
--- a/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, Web Notes 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 webnotes
-
-class DocType:
- def __init__(self, d, dl):
- self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.txt b/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.txt
deleted file mode 100644
index 7cd61f7..0000000
--- a/erpnext/selling/doctype/shopping_cart_price_list/shopping_cart_price_list.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-[
- {
- "creation": "2013-06-20 16:00:18",
- "docstatus": 0,
- "modified": "2013-12-20 19:21:47",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "doctype": "DocType",
- "istable": 1,
- "module": "Selling",
- "name": "__common__"
- },
- {
- "doctype": "DocField",
- "fieldname": "selling_price_list",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Price List",
- "name": "__common__",
- "options": "Price List",
- "parent": "Shopping Cart Price List",
- "parentfield": "fields",
- "parenttype": "DocType",
- "permlevel": 0,
- "reqd": 1
- },
- {
- "doctype": "DocType",
- "name": "Shopping Cart Price List"
- },
- {
- "doctype": "DocField"
- }
-]
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_settings/__init__.py b/erpnext/selling/doctype/shopping_cart_settings/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/shopping_cart_settings/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.js
deleted file mode 100644
index 7505dc2..0000000
--- a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-
-$.extend(cur_frm.cscript, {
- onload: function() {
- if(cur_frm.doc.__quotation_series) {
- cur_frm.fields_dict.quotation_series.df.options = cur_frm.doc.__quotation_series;
- }
- }
-});
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.py
deleted file mode 100644
index 923936e..0000000
--- a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# Copyright (c) 2013, Web Notes 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 webnotes
-from webnotes import _, msgprint
-from webnotes.utils import comma_and
-from webnotes.model.controller import DocListController
-
-class ShoppingCartSetupError(webnotes.ValidationError): pass
-
-class DocType(DocListController):
- def onload(self):
- self.doc.fields["__quotation_series"] = webnotes.get_doctype("Quotation").get_options("naming_series")
-
- def validate(self):
- if self.doc.enabled:
- self.validate_price_lists()
- self.validate_tax_masters()
- self.validate_exchange_rates_exist()
-
- def on_update(self):
- webnotes.conn.set_default("shopping_cart_enabled", self.doc.fields.get("enabled") or 0)
- webnotes.conn.set_default("shopping_cart_quotation_series", self.doc.fields.get("quotation_series"))
-
- def validate_overlapping_territories(self, parentfield, fieldname):
- # for displaying message
- doctype = self.meta.get_field(parentfield).options
-
- # specify atleast one entry in the table
- self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError)
-
- territory_name_map = self.get_territory_name_map(parentfield, fieldname)
- for territory, names in territory_name_map.items():
- if len(names) > 1:
- msgprint(_("Error for") + " " + _(doctype) + ": " + comma_and(names) +
- " " + _("have a common territory") + ": " + territory,
- raise_exception=ShoppingCartSetupError)
-
- return territory_name_map
-
- def validate_price_lists(self):
- territory_name_map = self.validate_overlapping_territories("price_lists",
- "selling_price_list")
-
- # validate that a Shopping Cart Price List exists for the root territory
- # as a catch all!
- from erpnext.setup.utils import get_root_of
- root_territory = get_root_of("Territory")
-
- if root_territory not in territory_name_map.keys():
- msgprint(_("Please specify a Price List which is valid for Territory") +
- ": " + root_territory, raise_exception=ShoppingCartSetupError)
-
- def validate_tax_masters(self):
- self.validate_overlapping_territories("sales_taxes_and_charges_masters",
- "sales_taxes_and_charges_master")
-
- def get_territory_name_map(self, parentfield, fieldname):
- territory_name_map = {}
-
- # entries in table
- names = [doc.fields.get(fieldname) for doc in self.doclist.get({"parentfield": parentfield})]
-
- if names:
- # for condition in territory check
- parenttype = self.meta.get_field(fieldname, parentfield=parentfield).options
-
- # to validate territory overlap
- # make a map of territory: [list of names]
- # if list against each territory has more than one element, raise exception
- territory_name = webnotes.conn.sql("""select `territory`, `parent`
- from `tabApplicable Territory`
- where `parenttype`=%s and `parent` in (%s)""" %
- ("%s", ", ".join(["%s"]*len(names))), tuple([parenttype] + names))
-
- for territory, name in territory_name:
- territory_name_map.setdefault(territory, []).append(name)
-
- if len(territory_name_map[territory]) > 1:
- territory_name_map[territory].sort(key=lambda val: names.index(val))
-
- return territory_name_map
-
- def validate_exchange_rates_exist(self):
- """check if exchange rates exist for all Price List currencies (to company's currency)"""
- company_currency = webnotes.conn.get_value("Company", self.doc.company, "default_currency")
- if not company_currency:
- msgprint(_("Please specify currency in Company") + ": " + self.doc.company,
- raise_exception=ShoppingCartSetupError)
-
- price_list_currency_map = webnotes.conn.get_values("Price List",
- [d.selling_price_list for d in self.doclist.get({"parentfield": "price_lists"})],
- "currency")
-
- # check if all price lists have a currency
- for price_list, currency in price_list_currency_map.items():
- if not currency:
- webnotes.throw("%s: %s" % (_("Currency is missing for Price List"), price_list))
-
- expected_to_exist = [currency + "-" + company_currency
- for currency in price_list_currency_map.values()
- if currency != company_currency]
-
- if expected_to_exist:
- exists = webnotes.conn.sql_list("""select name from `tabCurrency Exchange`
- where name in (%s)""" % (", ".join(["%s"]*len(expected_to_exist)),),
- tuple(expected_to_exist))
-
- missing = list(set(expected_to_exist).difference(exists))
-
- if missing:
- msgprint(_("Missing Currency Exchange Rates for" + ": " + comma_and(missing)),
- raise_exception=ShoppingCartSetupError)
-
- def get_name_from_territory(self, territory, parentfield, fieldname):
- name = None
- territory_name_map = self.get_territory_name_map(parentfield, fieldname)
-
- if territory_name_map.get(territory):
- name = territory_name_map.get(territory)
- else:
- territory_ancestry = self.get_territory_ancestry(territory)
- for ancestor in territory_ancestry:
- if territory_name_map.get(ancestor):
- name = territory_name_map.get(ancestor)
- break
-
- return name
-
- def get_price_list(self, billing_territory):
- price_list = self.get_name_from_territory(billing_territory, "price_lists", "selling_price_list")
- return price_list and price_list[0] or None
-
- 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 get_territory_ancestry(self, territory):
- from erpnext.setup.utils import get_ancestors_of
-
- if not hasattr(self, "_territory_ancestry"):
- self._territory_ancestry = {}
-
- if not self._territory_ancestry.get(territory):
- self._territory_ancestry[territory] = get_ancestors_of("Territory", territory)
-
- return self._territory_ancestry[territory]
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.txt b/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.txt
deleted file mode 100644
index f52cc60..0000000
--- a/erpnext/selling/doctype/shopping_cart_settings/shopping_cart_settings.txt
+++ /dev/null
@@ -1,129 +0,0 @@
-[
- {
- "creation": "2013-06-19 15:57:32",
- "docstatus": 0,
- "modified": "2013-12-20 19:21:47",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "description": "Default settings for Shopping Cart",
- "doctype": "DocType",
- "icon": "icon-shopping-cart",
- "issingle": 1,
- "module": "Selling",
- "name": "__common__"
- },
- {
- "doctype": "DocField",
- "name": "__common__",
- "parent": "Shopping Cart Settings",
- "parentfield": "fields",
- "parenttype": "DocType",
- "permlevel": 0
- },
- {
- "create": 1,
- "doctype": "DocPerm",
- "email": 1,
- "name": "__common__",
- "parent": "Shopping Cart Settings",
- "parentfield": "permissions",
- "parenttype": "DocType",
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "role": "Website Manager",
- "write": 1
- },
- {
- "doctype": "DocType",
- "name": "Shopping Cart Settings"
- },
- {
- "doctype": "DocField",
- "fieldname": "enabled",
- "fieldtype": "Check",
- "label": "Enable Shopping Cart"
- },
- {
- "doctype": "DocField",
- "fieldname": "section_break_2",
- "fieldtype": "Section Break"
- },
- {
- "doctype": "DocField",
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "reqd": 1
- },
- {
- "description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
- "doctype": "DocField",
- "fieldname": "default_territory",
- "fieldtype": "Link",
- "label": "Default Territory",
- "options": "Territory",
- "reqd": 1
- },
- {
- "doctype": "DocField",
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
- {
- "description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
- "doctype": "DocField",
- "fieldname": "default_customer_group",
- "fieldtype": "Link",
- "label": "Default Customer Group",
- "options": "Customer Group",
- "reqd": 1
- },
- {
- "doctype": "DocField",
- "fieldname": "quotation_series",
- "fieldtype": "Select",
- "label": "Quotation Series",
- "reqd": 1
- },
- {
- "doctype": "DocField",
- "fieldname": "section_break_6",
- "fieldtype": "Section Break"
- },
- {
- "doctype": "DocField",
- "fieldname": "price_lists",
- "fieldtype": "Table",
- "label": "Shopping Cart Price Lists",
- "options": "Shopping Cart Price List",
- "reqd": 0
- },
- {
- "doctype": "DocField",
- "fieldname": "shipping_rules",
- "fieldtype": "Table",
- "label": "Shopping Cart Shipping Rules",
- "options": "Shopping Cart Shipping Rule",
- "reqd": 0
- },
- {
- "doctype": "DocField",
- "fieldname": "column_break_10",
- "fieldtype": "Column Break"
- },
- {
- "doctype": "DocField",
- "fieldname": "sales_taxes_and_charges_masters",
- "fieldtype": "Table",
- "label": "Shopping Cart Taxes and Charges Masters",
- "options": "Shopping Cart Taxes and Charges Master",
- "reqd": 0
- },
- {
- "doctype": "DocPerm"
- }
-]
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/selling/doctype/shopping_cart_settings/test_shopping_cart_settings.py
deleted file mode 100644
index be67f6f..0000000
--- a/erpnext/selling/doctype/shopping_cart_settings/test_shopping_cart_settings.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (c) 2013, Web Notes 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 webnotes
-import unittest
-from erpnext.selling.doctype.shopping_cart_settings.shopping_cart_settings import ShoppingCartSetupError
-
-class TestShoppingCartSettings(unittest.TestCase):
- def setUp(self):
- webnotes.conn.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """)
- webnotes.conn.sql("""delete from `tabShopping Cart Price List`""")
- webnotes.conn.sql("""delete from `tabShopping Cart Taxes and Charges Master`""")
- webnotes.conn.sql("""delete from `tabShopping Cart Shipping Rule`""")
-
- def get_cart_settings(self):
- return webnotes.bean({"doctype": "Shopping Cart Settings",
- "company": "_Test Company"})
-
- def test_price_list_territory_overlap(self):
- cart_settings = self.get_cart_settings()
-
- def _add_price_list(price_list):
- cart_settings.doclist.append({
- "doctype": "Shopping Cart Price List",
- "parentfield": "price_lists",
- "selling_price_list": price_list
- })
-
- for price_list in ("_Test Price List Rest of the World", "_Test Price List India",
- "_Test Price List"):
- _add_price_list(price_list)
-
- controller = cart_settings.make_controller()
- controller.validate_overlapping_territories("price_lists", "selling_price_list")
-
- _add_price_list("_Test Price List 2")
-
- controller = cart_settings.make_controller()
- self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
- "price_lists", "selling_price_list")
-
- return cart_settings
-
- def test_taxes_territory_overlap(self):
- cart_settings = self.get_cart_settings()
-
- def _add_tax_master(tax_master):
- cart_settings.doclist.append({
- "doctype": "Shopping Cart Taxes and Charges Master",
- "parentfield": "sales_taxes_and_charges_masters",
- "sales_taxes_and_charges_master": tax_master
- })
-
- for tax_master in ("_Test Sales Taxes and Charges Master", "_Test India Tax Master"):
- _add_tax_master(tax_master)
-
- controller = cart_settings.make_controller()
- controller.validate_overlapping_territories("sales_taxes_and_charges_masters",
- "sales_taxes_and_charges_master")
-
- _add_tax_master("_Test Sales Taxes and Charges Master 2")
-
- controller = cart_settings.make_controller()
- self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
- "sales_taxes_and_charges_masters", "sales_taxes_and_charges_master")
-
- def test_exchange_rate_exists(self):
- webnotes.conn.sql("""delete from `tabCurrency Exchange`""")
-
- cart_settings = self.test_price_list_territory_overlap()
- controller = cart_settings.make_controller()
- self.assertRaises(ShoppingCartSetupError, controller.validate_exchange_rates_exist)
-
- from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \
- currency_exchange_records
- webnotes.bean(currency_exchange_records[0]).insert()
- controller.validate_exchange_rates_exist()
-
diff --git a/erpnext/selling/doctype/shopping_cart_shipping_rule/__init__.py b/erpnext/selling/doctype/shopping_cart_shipping_rule/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/shopping_cart_shipping_rule/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py b/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py
deleted file mode 100644
index e5468e5..0000000
--- a/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, Web Notes 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 webnotes
-
-class DocType:
- def __init__(self, d, dl):
- self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.txt b/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.txt
deleted file mode 100644
index 91b41c2..0000000
--- a/erpnext/selling/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-[
- {
- "creation": "2013-07-03 13:15:34",
- "docstatus": 0,
- "modified": "2013-12-20 19:21:47",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "doctype": "DocType",
- "istable": 1,
- "module": "Selling",
- "name": "__common__"
- },
- {
- "doctype": "DocField",
- "fieldname": "shipping_rule",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Shipping Rule",
- "name": "__common__",
- "options": "Shipping Rule",
- "parent": "Shopping Cart Shipping Rule",
- "parentfield": "fields",
- "parenttype": "DocType",
- "permlevel": 0,
- "reqd": 1
- },
- {
- "doctype": "DocType",
- "name": "Shopping Cart Shipping Rule"
- },
- {
- "doctype": "DocField"
- }
-]
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/__init__.py b/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py b/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py
deleted file mode 100644
index e5468e5..0000000
--- a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, Web Notes 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 webnotes
-
-class DocType:
- def __init__(self, d, dl):
- self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.txt b/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.txt
deleted file mode 100644
index ba44199..0000000
--- a/erpnext/selling/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-[
- {
- "creation": "2013-06-20 16:57:03",
- "docstatus": 0,
- "modified": "2013-12-20 19:21:47",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "doctype": "DocType",
- "istable": 1,
- "module": "Selling",
- "name": "__common__"
- },
- {
- "doctype": "DocField",
- "fieldname": "sales_taxes_and_charges_master",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Tax Master",
- "name": "__common__",
- "options": "Sales Taxes and Charges Master",
- "parent": "Shopping Cart Taxes and Charges Master",
- "parentfield": "fields",
- "parenttype": "DocType",
- "permlevel": 0,
- "reqd": 1
- },
- {
- "doctype": "DocType",
- "name": "Shopping Cart Taxes and Charges Master"
- },
- {
- "doctype": "DocField"
- }
-]
\ No newline at end of file
diff --git a/erpnext/selling/page/selling_home/selling_home.js b/erpnext/selling/page/selling_home/selling_home.js
index a64ed48..54b4edc 100644
--- a/erpnext/selling/page/selling_home/selling_home.js
+++ b/erpnext/selling/page/selling_home/selling_home.js
@@ -66,12 +66,6 @@
"description": wn._("Settings for Selling Module")
},
{
- "route":"Form/Shopping Cart Settings",
- "label":wn._("Shopping Cart Settings"),
- "description":wn._("Setup of Shopping Cart."),
- doctype:"Shopping Cart Settings"
- },
- {
label: wn._("Sales Taxes and Charges Master"),
description: wn._("Sales taxes template."),
doctype:"Sales Taxes and Charges Master"
diff --git a/erpnext/selling/utils/__init__.py b/erpnext/selling/utils.py
similarity index 99%
rename from erpnext/selling/utils/__init__.py
rename to erpnext/selling/utils.py
index c73d76e..7949e47 100644
--- a/erpnext/selling/utils/__init__.py
+++ b/erpnext/selling/utils.py
@@ -207,4 +207,4 @@
if out.get("warehouse"):
out["actual_qty"] = get_available_qty(opts.item_code, out.get("warehouse")).get("actual_qty")
- return out
+ return out
\ No newline at end of file
diff --git a/erpnext/selling/utils/cart.py b/erpnext/selling/utils/cart.py
deleted file mode 100644
index f23a571..0000000
--- a/erpnext/selling/utils/cart.py
+++ /dev/null
@@ -1,462 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import webnotes, json
-from webnotes import msgprint, _
-import webnotes.defaults
-from webnotes.utils import flt, get_fullname, fmt_money, cstr
-
-class WebsitePriceListMissingError(webnotes.ValidationError): pass
-
-def set_cart_count(quotation=None):
- if not quotation:
- quotation = _get_cart_quotation()
- cart_count = cstr(len(quotation.doclist.get({"parentfield": "quotation_details"})))
- webnotes._response.set_cookie("cart_count", cart_count)
-
-@webnotes.whitelist()
-def get_cart_quotation(doclist=None):
- party = get_lead_or_customer()
-
- if not doclist:
- quotation = _get_cart_quotation(party)
- doclist = quotation.doclist
- set_cart_count(quotation)
-
- return {
- "doclist": decorate_quotation_doclist(doclist),
- "addresses": [{"name": address.name, "display": address.display}
- for address in get_address_docs(party)],
- "shipping_rules": get_applicable_shipping_rules(party)
- }
-
-@webnotes.whitelist()
-def place_order():
- quotation = _get_cart_quotation()
- controller = quotation.make_controller()
- for fieldname in ["customer_address", "shipping_address_name"]:
- if not quotation.doc.fields.get(fieldname):
- msgprint(_("Please select a") + " " + _(controller.meta.get_label(fieldname)), raise_exception=True)
-
- quotation.ignore_permissions = True
- quotation.submit()
-
- from erpnext.selling.doctype.quotation.quotation import _make_sales_order
- sales_order = webnotes.bean(_make_sales_order(quotation.doc.name, ignore_permissions=True))
- sales_order.ignore_permissions = True
- sales_order.insert()
- sales_order.submit()
- webnotes._response.set_cookie("cart_count", "")
-
- return sales_order.doc.name
-
-@webnotes.whitelist()
-def update_cart(item_code, qty, with_doclist=0):
- quotation = _get_cart_quotation()
-
- qty = flt(qty)
- if qty == 0:
- quotation.set_doclist(quotation.doclist.get({"item_code": ["!=", item_code]}))
- if not quotation.doclist.get({"parentfield": "quotation_details"}) and \
- not quotation.doc.fields.get("__islocal"):
- quotation.__delete = True
-
- else:
- quotation_items = quotation.doclist.get({"item_code": item_code})
- if not quotation_items:
- quotation.doclist.append({
- "doctype": "Quotation Item",
- "parentfield": "quotation_details",
- "item_code": item_code,
- "qty": qty
- })
- else:
- quotation_items[0].qty = qty
-
- apply_cart_settings(quotation=quotation)
-
- if hasattr(quotation, "__delete"):
- webnotes.delete_doc("Quotation", quotation.doc.name, ignore_permissions=True)
- quotation = _get_cart_quotation()
- else:
- quotation.ignore_permissions = True
- quotation.save()
-
- set_cart_count(quotation)
-
- if with_doclist:
- return get_cart_quotation(quotation.doclist)
- else:
- return quotation.doc.name
-
-@webnotes.whitelist()
-def update_cart_address(address_fieldname, address_name):
- from erpnext.utilities.transaction_base import get_address_display
-
- quotation = _get_cart_quotation()
- address_display = get_address_display(webnotes.doc("Address", address_name).fields)
-
- if address_fieldname == "shipping_address_name":
- quotation.doc.shipping_address_name = address_name
- quotation.doc.shipping_address = address_display
-
- if not quotation.doc.customer_address:
- address_fieldname == "customer_address"
-
- if address_fieldname == "customer_address":
- quotation.doc.customer_address = address_name
- quotation.doc.address_display = address_display
-
-
- apply_cart_settings(quotation=quotation)
-
- quotation.ignore_permissions = True
- quotation.save()
-
- return get_cart_quotation(quotation.doclist)
-
-@webnotes.whitelist()
-def get_addresses():
- return [d.fields for d in get_address_docs()]
-
-@webnotes.whitelist()
-def save_address(fields, address_fieldname=None):
- party = get_lead_or_customer()
- fields = json.loads(fields)
-
- if fields.get("name"):
- bean = webnotes.bean("Address", fields.get("name"))
- else:
- bean = webnotes.bean({"doctype": "Address", "__islocal": 1})
-
- bean.doc.fields.update(fields)
-
- party_fieldname = party.doctype.lower()
- bean.doc.fields.update({
- party_fieldname: party.name,
- (party_fieldname + "_name"): party.fields[party_fieldname + "_name"]
- })
- bean.ignore_permissions = True
- bean.save()
-
- if address_fieldname:
- update_cart_address(address_fieldname, bean.doc.name)
-
- return bean.doc.name
-
-def get_address_docs(party=None):
- from webnotes.model.doclist import objectify
- from erpnext.utilities.transaction_base import get_address_display
-
- if not party:
- party = get_lead_or_customer()
-
- address_docs = objectify(webnotes.conn.sql("""select * from `tabAddress`
- where `%s`=%s order by name""" % (party.doctype.lower(), "%s"), party.name,
- as_dict=True, update={"doctype": "Address"}))
-
- for address in address_docs:
- address.display = get_address_display(address.fields)
- address.display = (address.display).replace("\n", "<br>\n")
-
- return address_docs
-
-def get_lead_or_customer():
- customer = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user}, "customer")
- if customer:
- return webnotes.doc("Customer", customer)
-
- lead = webnotes.conn.get_value("Lead", {"email_id": webnotes.session.user})
- if lead:
- return webnotes.doc("Lead", lead)
- else:
- lead_bean = webnotes.bean({
- "doctype": "Lead",
- "email_id": webnotes.session.user,
- "lead_name": get_fullname(webnotes.session.user),
- "territory": guess_territory(),
- "status": "Open" # TODO: set something better???
- })
-
- if webnotes.session.user != "Guest":
- lead_bean.ignore_permissions = True
- lead_bean.insert()
-
- return lead_bean.doc
-
-def guess_territory():
- territory = None
- geoip_country = webnotes.session.get("session_country")
- if geoip_country:
- territory = webnotes.conn.get_value("Territory", geoip_country)
-
- return territory or \
- webnotes.conn.get_value("Shopping Cart Settings", None, "territory") or \
- "All Territories"
-
-def decorate_quotation_doclist(doclist):
- for d in doclist:
- if d.item_code:
- d.fields.update(webnotes.conn.get_value("Item", d.item_code,
- ["website_image", "description", "page_name"], as_dict=True))
- d.formatted_rate = fmt_money(d.export_rate, currency=doclist[0].currency)
- d.formatted_amount = fmt_money(d.export_amount, currency=doclist[0].currency)
- elif d.charge_type:
- d.formatted_tax_amount = fmt_money(d.tax_amount / doclist[0].conversion_rate,
- currency=doclist[0].currency)
-
- doclist[0].formatted_grand_total_export = fmt_money(doclist[0].grand_total_export,
- currency=doclist[0].currency)
-
- return [d.fields for d in doclist]
-
-def _get_cart_quotation(party=None):
- if not party:
- party = get_lead_or_customer()
-
- quotation = webnotes.conn.get_value("Quotation",
- {party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0})
-
- if quotation:
- qbean = webnotes.bean("Quotation", quotation)
- else:
- qbean = webnotes.bean({
- "doctype": "Quotation",
- "naming_series": webnotes.defaults.get_user_default("shopping_cart_quotation_series") or "QTN-CART-",
- "quotation_to": party.doctype,
- "company": webnotes.defaults.get_user_default("company"),
- "order_type": "Shopping Cart",
- "status": "Draft",
- "docstatus": 0,
- "__islocal": 1,
- (party.doctype.lower()): party.name
- })
-
- if party.doctype == "Customer":
- qbean.doc.contact_person = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
- "customer": party.name})
- qbean.run_method("set_contact_fields")
-
- qbean.run_method("onload_post_render")
- apply_cart_settings(party, qbean)
-
- return qbean
-
-def update_party(fullname, company_name=None, mobile_no=None, phone=None):
- party = get_lead_or_customer()
-
- if party.doctype == "Lead":
- party.company_name = company_name
- party.lead_name = fullname
- party.mobile_no = mobile_no
- party.phone = phone
- else:
- party.customer_name = company_name or fullname
- party.customer_type == "Company" if company_name else "Individual"
-
- contact_name = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
- "customer": party.name})
- contact = webnotes.bean("Contact", contact_name)
- contact.doc.first_name = fullname
- contact.doc.last_name = None
- contact.doc.customer_name = party.customer_name
- contact.doc.mobile_no = mobile_no
- contact.doc.phone = phone
- contact.ignore_permissions = True
- contact.save()
-
- party_bean = webnotes.bean(party.fields)
- party_bean.ignore_permissions = True
- party_bean.save()
-
- qbean = _get_cart_quotation(party)
- if not qbean.doc.fields.get("__islocal"):
- qbean.doc.customer_name = company_name or fullname
- qbean.run_method("set_contact_fields")
- qbean.ignore_permissions = True
- qbean.save()
-
-def apply_cart_settings(party=None, quotation=None):
- if not party:
- party = get_lead_or_customer()
- if not quotation:
- quotation = _get_cart_quotation(party)
-
- cart_settings = webnotes.get_obj("Shopping Cart Settings")
-
- billing_territory = get_address_territory(quotation.doc.customer_address) or \
- party.territory or "All Territories"
-
- set_price_list_and_rate(quotation, cart_settings, billing_territory)
-
- quotation.run_method("calculate_taxes_and_totals")
-
- set_taxes(quotation, cart_settings, billing_territory)
-
- _apply_shipping_rule(party, quotation, cart_settings)
-
-def set_price_list_and_rate(quotation, cart_settings, billing_territory):
- """set price list based on billing territory"""
- quotation.doc.selling_price_list = cart_settings.get_price_list(billing_territory)
-
- # reset values
- quotation.doc.price_list_currency = quotation.doc.currency = \
- quotation.doc.plc_conversion_rate = quotation.doc.conversion_rate = None
- for item in quotation.doclist.get({"parentfield": "quotation_details"}):
- item.ref_rate = item.adj_rate = item.export_rate = item.export_amount = None
-
- # refetch values
- quotation.run_method("set_price_list_and_item_details")
-
- # set it in cookies for using in product page
- webnotes.local._response.set_cookie("selling_price_list", quotation.doc.selling_price_list)
-
-def set_taxes(quotation, cart_settings, billing_territory):
- """set taxes based on billing territory"""
- quotation.doc.charge = cart_settings.get_tax_master(billing_territory)
-
- # clear table
- quotation.set_doclist(quotation.doclist.get({"parentfield": ["!=", "other_charges"]}))
-
- # append taxes
- controller = quotation.make_controller()
- controller.append_taxes_from_master("other_charges", "charge")
- quotation.set_doclist(controller.doclist)
-
-@webnotes.whitelist()
-def apply_shipping_rule(shipping_rule):
- quotation = _get_cart_quotation()
-
- quotation.doc.shipping_rule = shipping_rule
-
- apply_cart_settings(quotation=quotation)
-
- quotation.ignore_permissions = True
- quotation.save()
-
- return get_cart_quotation(quotation.doclist)
-
-def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
- shipping_rules = get_shipping_rules(party, quotation, cart_settings)
-
- if not shipping_rules:
- return
-
- elif quotation.doc.shipping_rule not in shipping_rules:
- quotation.doc.shipping_rule = shipping_rules[0]
-
- 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(party, quotation)
-
- if shipping_rules:
- rule_label_map = webnotes.conn.get_values("Shipping Rule", shipping_rules, "label")
- # we need this in sorted order as per the position of the rule in the settings page
- return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
-
-def get_shipping_rules(party=None, quotation=None, cart_settings=None):
- if not party:
- party = get_lead_or_customer()
- if not quotation:
- quotation = _get_cart_quotation()
- if not cart_settings:
- cart_settings = webnotes.get_obj("Shopping Cart Settings")
-
- # set shipping rule based on shipping territory
- shipping_territory = get_address_territory(quotation.doc.shipping_address_name) or \
- party.territory
-
- shipping_rules = cart_settings.get_shipping_rules(shipping_territory)
-
- 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 = webnotes.conn.get_value("Address", address_name,
- ["city", "state", "country"])
- for value in address_fields:
- territory = webnotes.conn.get_value("Territory", value)
- if territory:
- break
-
- return territory
-
-import unittest
-test_dependencies = ["Item", "Price List", "Contact", "Shopping Cart Settings"]
-
-class TestCart(unittest.TestCase):
- def tearDown(self):
- return
-
- cart_settings = webnotes.bean("Shopping Cart Settings")
- cart_settings.ignore_permissions = True
- cart_settings.doc.enabled = 0
- cart_settings.save()
-
- def enable_shopping_cart(self):
- return
- if not webnotes.conn.get_value("Shopping Cart Settings", None, "enabled"):
- cart_settings = webnotes.bean("Shopping Cart Settings")
- cart_settings.ignore_permissions = True
- cart_settings.doc.enabled = 1
- cart_settings.save()
-
- def test_get_lead_or_customer(self):
- webnotes.session.user = "test@example.com"
- party1 = get_lead_or_customer()
- party2 = get_lead_or_customer()
- self.assertEquals(party1.name, party2.name)
- self.assertEquals(party1.doctype, "Lead")
-
- webnotes.session.user = "test_contact_customer@example.com"
- party = get_lead_or_customer()
- self.assertEquals(party.name, "_Test Customer")
-
- def test_add_to_cart(self):
- self.enable_shopping_cart()
- webnotes.session.user = "test@example.com"
-
- update_cart("_Test Item", 1)
-
- quotation = _get_cart_quotation()
- quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
- self.assertTrue(quotation_items)
- self.assertEquals(quotation_items[0].qty, 1)
-
- return quotation
-
- def test_update_cart(self):
- self.test_add_to_cart()
-
- update_cart("_Test Item", 5)
-
- quotation = _get_cart_quotation()
- quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
- self.assertTrue(quotation_items)
- self.assertEquals(quotation_items[0].qty, 5)
-
- return quotation
-
- def test_remove_from_cart(self):
- quotation0 = self.test_add_to_cart()
-
- update_cart("_Test Item", 0)
-
- quotation = _get_cart_quotation()
- self.assertEquals(quotation0.doc.name, quotation.doc.name)
-
- quotation_items = quotation.doclist.get({"parentfield": "quotation_details", "item_code": "_Test Item"})
- self.assertEquals(quotation_items, [])
-
- def test_place_order(self):
- quotation = self.test_update_cart()
- sales_order_name = place_order()
- sales_order = webnotes.bean("Sales Order", sales_order_name)
- self.assertEquals(sales_order.doclist.getone({"item_code": "_Test Item"}).prevdoc_docname, quotation.doc.name)
-
\ No newline at end of file
diff --git a/erpnext/selling/utils/product.py b/erpnext/selling/utils/product.py
deleted file mode 100644
index 98b7d6a..0000000
--- a/erpnext/selling/utils/product.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import webnotes
-from webnotes.utils import cstr, cint, fmt_money
-from webnotes.webutils import delete_page_cache
-from erpnext.selling.utils.cart import _get_cart_quotation
-
-@webnotes.whitelist(allow_guest=True)
-def get_product_info(item_code):
- """get product price / stock info"""
- if not cint(webnotes.conn.get_default("shopping_cart_enabled")):
- return {}
-
- cart_quotation = _get_cart_quotation()
-
- price_list = webnotes.local.request.cookies.get("selling_price_list")
-
- warehouse = webnotes.conn.get_value("Item", item_code, "website_warehouse")
- if warehouse:
- in_stock = webnotes.conn.sql("""select actual_qty from tabBin where
- item_code=%s and warehouse=%s""", (item_code, warehouse))
- if in_stock:
- in_stock = in_stock[0][0] > 0 and 1 or 0
- else:
- in_stock = -1
-
- price = price_list and webnotes.conn.sql("""select ref_rate, currency from
- `tabItem Price` where item_code=%s and price_list=%s""",
- (item_code, price_list), as_dict=1) or []
-
- price = price and price[0] or None
- qty = 0
-
- if price:
- price["formatted_price"] = fmt_money(price["ref_rate"], currency=price["currency"])
-
- price["currency"] = not cint(webnotes.conn.get_default("hide_currency_symbol")) \
- and (webnotes.conn.get_value("Currency", price.currency, "symbol") or price.currency) \
- or ""
-
- if webnotes.session.user != "Guest":
- item = cart_quotation.doclist.get({"item_code": item_code})
- if item:
- qty = item[0].qty
-
- return {
- "price": price,
- "stock": in_stock,
- "uom": webnotes.conn.get_value("Item", item_code, "stock_uom"),
- "qty": qty
- }
-
-@webnotes.whitelist(allow_guest=True)
-def get_product_list(search=None, start=0, limit=10):
- # base query
- query = """select name, item_name, page_name, website_image, item_group,
- web_long_description as website_description
- from `tabItem` where docstatus = 0 and show_in_website = 1 """
-
- # search term condition
- if search:
- query += """and (web_long_description like %(search)s or
- item_name like %(search)s or name like %(search)s)"""
- search = "%" + cstr(search) + "%"
-
- # order by
- query += """order by weightage desc, modified desc limit %s, %s""" % (start, limit)
-
- data = webnotes.conn.sql(query, {
- "search": search,
- }, as_dict=1)
-
- return [get_item_for_list_in_html(r) for r in data]
-
-
-def get_product_list_for_group(product_group=None, start=0, limit=10):
- child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(product_group)])
-
- # base query
- query = """select name, item_name, page_name, website_image, item_group,
- web_long_description as website_description
- from `tabItem` where docstatus = 0 and show_in_website = 1
- and (item_group in (%s)
- or name in (select parent from `tabWebsite Item Group` where item_group in (%s))) """ % (child_groups, child_groups)
-
- query += """order by weightage desc, modified desc limit %s, %s""" % (start, limit)
-
- data = webnotes.conn.sql(query, {"product_group": product_group}, as_dict=1)
-
- return [get_item_for_list_in_html(r) for r in data]
-
-def get_child_groups(item_group_name):
- item_group = webnotes.doc("Item Group", item_group_name)
- return webnotes.conn.sql("""select name
- from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s
- and show_in_website = 1""", item_group.fields)
-
-def get_group_item_count(item_group):
- child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(item_group)])
- return webnotes.conn.sql("""select count(*) from `tabItem`
- where docstatus = 0 and show_in_website = 1
- and (item_group in (%s)
- or name in (select parent from `tabWebsite Item Group`
- where item_group in (%s))) """ % (child_groups, child_groups))[0][0]
-
-def get_item_for_list_in_html(context):
- return webnotes.get_template("templates/includes/product_in_grid.html").render(context)
-
-def scrub_item_for_list(r):
- if not r.website_description:
- r.website_description = "No description given"
- if len(r.website_description.split(" ")) > 24:
- r.website_description = " ".join(r.website_description.split(" ")[:24]) + "..."
-
-def get_parent_item_groups(item_group_name):
- item_group = webnotes.doc("Item Group", item_group_name)
- return webnotes.conn.sql("""select name, page_name from `tabItem Group`
- where lft <= %s and rgt >= %s
- and ifnull(show_in_website,0)=1
- order by lft asc""", (item_group.lft, item_group.rgt), as_dict=True)
-
-def invalidate_cache_for(item_group):
- for i in get_parent_item_groups(item_group):
- if i.page_name:
- delete_page_cache(i.page_name)
\ No newline at end of file