Source code for shuup.core.utils.price_display

# This file is part of Shuup.
#
# Copyright (c) 2012-2017, Shoop Commerce Ltd. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
"""
Utilities for displaying prices correctly.

Contents:

  * Class `PriceDisplayOptions` for storing the display options.

  * Helper function `render_price_property` for rendering prices
    correctly from Python code.

  * Various filter classes for implementing Jinja2 filters.
"""

import django_jinja.library
import jinja2

from shuup.core.pricing import PriceDisplayOptions, Priceful
from shuup.core.templatetags.shuup_common import money, percent
from shuup.core.utils import context_cache

from .prices import convert_taxness


[docs]def render_price_property(request, item, priceful, property_name='price'): """ Render price property of a Priceful object. :type request: django.http.HttpRequest :type item: shuup.core.taxing.TaxableItem :type priceful: shuup.core.pricing.Priceful :type propert_name: str :rtype: str """ options = PriceDisplayOptions.from_context({'request': request}) if options.hide_prices: return "" new_priceful = convert_taxness( request, item, priceful, options.include_taxes) price_value = getattr(new_priceful, property_name) return money(price_value)
class _ContextObject(object): def __init__(self, name, property_name=None): self.name = name self.property_name = (property_name or name) self._register() class _ContextFilter(_ContextObject): def _register(self): django_jinja.library.filter( name=self.name, fn=jinja2.contextfilter(self)) @property def cache_identifier(self): return "price_filter_%s" % self.name class _ContextFunction(_ContextObject): def _register(self): django_jinja.library.global_function( name=self.name, fn=jinja2.contextfunction(self))
[docs]class PriceDisplayFilter(_ContextFilter): def __call__(self, context, item, quantity=1, include_taxes=None, allow_cache=True): key, val = context_cache.get_cached_value( identifier=self.cache_identifier, item=item, context=context.get('request', context), quantity=quantity, include_taxes=include_taxes, name=self.name, allow_cache=allow_cache) if val is not None: return val options = PriceDisplayOptions.from_context(context) if options.hide_prices: context_cache.set_cached_value(key, "") return "" if include_taxes is None: include_taxes = options.include_taxes request = context.get('request') orig_priceful = _get_priceful(request, item, quantity) if not orig_priceful: context_cache.set_cached_value(key, "") return "" priceful = convert_taxness(request, item, orig_priceful, include_taxes) price_value = getattr(priceful, self.property_name) val = money(price_value) context_cache.set_cached_value(key, val) return val
[docs]class PricePropertyFilter(_ContextFilter): def __call__(self, context, item, quantity=1, allow_cache=True): key, val = context_cache.get_cached_value( identifier=self.cache_identifier, item=item, context=context.get('request', context), quantity=quantity, name=self.name, allow_cache=allow_cache) if val is not None: return val priceful = _get_priceful(context.get('request'), item, quantity) if not priceful: context_cache.set_cached_value(key, "") return "" price = getattr(priceful, self.property_name) context_cache.set_cached_value(key, price) return price
[docs]class PricePercentPropertyFilter(_ContextFilter): def __call__(self, context, item, quantity=1, allow_cache=True): key, val = context_cache.get_cached_value( identifier=self.cache_identifier, item=item, context=context.get('request', context), quantity=quantity, name=self.name, allow_cache=allow_cache) if val is not None: return val priceful = _get_priceful(context.get('request'), item, quantity) if not priceful: context_cache.set_cached_value(key, "") return "" val = percent(getattr(priceful, self.property_name)) context_cache.set_cached_value(key, val) return val
[docs]class TotalPriceDisplayFilter(_ContextFilter): def __call__(self, context, source, include_taxes=None): """ :type source: shuup.core.order_creator.OrderSource| shuup.core.models.Order """ options = PriceDisplayOptions.from_context(context) if options.hide_prices: return "" if include_taxes is None: include_taxes = options.include_taxes try: if include_taxes is None: total = source.total_price elif include_taxes: total = source.taxful_total_price else: total = source.taxless_total_price except TypeError: total = source.total_price return money(total)
[docs]class PriceRangeDisplayFilter(_ContextFilter): def __call__(self, context, product, quantity=1, allow_cache=True): """ :type product: shuup.core.models.Product """ key, val = context_cache.get_cached_value( identifier=self.cache_identifier, item=product, context=context.get('request', context), quantity=quantity, name=self.name, allow_cache=allow_cache) if val is not None: return val options = PriceDisplayOptions.from_context(context) if options.hide_prices: val = ("", "") context_cache.set_cached_value(key, val) return val request = context.get('request') priced_children = product.get_priced_children(request, quantity) priced_products = priced_children if priced_children else [ (product, _get_priceful(request, product, quantity))] def get_formatted_price(priced_product): (prod, price_info) = priced_product if not price_info: return "" pf = convert_taxness(request, prod, price_info, options.include_taxes) price = money(pf.price) return price min_max = (priced_products[0], priced_products[-1]) prices = tuple(get_formatted_price(x) for x in min_max) context_cache.set_cached_value(key, prices) return prices
def _get_priceful(request, item, quantity): """ Get priceful from given item. If item has `get_price_info` method, it will be called with given `request` and `quantity` as arguments, otherwise the item itself should implement the `Priceful` interface. :type request: django.http.HttpRequest :type item: shuup.core.taxing.TaxableItem :type quantity: numbers.Number :rtype: shuup.core.pricing.Priceful|None """ if hasattr(item, 'get_price_info'): if hasattr(item, 'is_variation_parent'): if item.is_variation_parent(): return item.get_cheapest_child_price_info(request, quantity) return item.get_price_info(request, quantity=quantity) if hasattr(item, 'get_total_cost'): return item.get_total_cost(request.basket) assert isinstance(item, Priceful) return item