shoop.core.pricing package¶
Submodules¶
shoop.core.pricing.default_pricing module¶
-
class
shoop.core.pricing.default_pricing.
DefaultPricingContext
(**kwargs)[source]¶ Bases:
shoop.core.pricing.PricingContext
-
REQUIRED_VALUES
= ['shop']¶
-
shop
= None¶
-
-
class
shoop.core.pricing.default_pricing.
DefaultPricingModule
[source]¶ Bases:
shoop.core.pricing.PricingModule
-
identifier
= 'default_pricing'¶
-
name
= <django.utils.functional.lazy.<locals>.__proxy__ object>¶
-
pricing_context_class
¶ alias of
DefaultPricingContext
-
Module contents¶
Shoop modular product pricing functionality.
The pricing module in use is declared by the
SHOOP_PRICING_MODULE
setting. The
default is a pricing module that always prices everything to be free.
The base distribution contains shoop.simple_pricing
, which is an
useful pricing module for many cases.
To acquire an instance of the current pricing module, use
get_pricing_module
.
In brief, a pricing module is able to price a product based on a
context; what exactly a context contains is determined by the module
in question. You can construct a context from a request by calling the
module’s get_context_from_request
method, or
for more advanced uses, when you do not have access to an HTTP request,
get_context_from_data
.
After you have acquired the module and a context, you can calculate
prices for a product with the module’s
get_price_info
method.
(Product
objects contain the
convenience methods
get_price_info
,
get_price
,
and get_base_price
which do these steps for you.)
If you have multiple products, it will likely be more efficient –
depending on the implementation of the module – to use the
get_price_infos
method.
TODO: document the concepts of base price and the pricing steps API. TODO: caching.
-
class
shoop.core.pricing.
Price
¶ Bases:
shoop.utils.money.Money
Money amount with taxful/taxless info.
Taxful and taxless prices cannot be mixed in comparison or in calculations, i.e. operations like
x < y
orx + y
for two Pricesx
andy
withx.includes_tax != y.includes_tax
will raise anUnitMixupError
.In addition to
includes_tax
info, Prices are Money and know theirvalue
andcurrency
. To get the bare Money amount of aPrice
, use theamount
property.-
includes_tax
= None¶
-
-
class
shoop.core.pricing.
Priceful
¶ Bases:
object
Mixin to define price properties based on other price properties.
You must provide at least
quantity
(Decimal
)
and both
or both
You may also provide
tax_amount
(Money
)
to get various tax related properties.
Provided
base_unit_price
,discount_amount
,price
,base_price
, andtax_amount
must have compatible units (i.e. same taxness and currency).- Invariants:
price = base_unit_price * quantity - discount_amount
discount_amount = base_price - price
discount_rate = 1 - (price / base_price)
discount_percentage = 100 * discount_rate
unit_discount_amount = discount_amount / quantity
taxful_price = taxless_price + tax_amount
tax_rate = (taxful_price.amount / taxless_price.amount) - 1
tax_percentage = 100 * tax_rate
-
base_price
¶ Total price for the specified quantity excluding discount.
Return type: shoop.core.pricing.Price
-
base_unit_price
¶ Undiscounted unit price.
Note: If quantity is 0, will return
base_price
.Return type: shoop.core.pricing.Price
-
discount_amount
¶ Amount of discount for the total quantity.
Return type: shoop.core.pricing.Price
-
discount_percentage
¶ Discount percentage, 100 meaning totally discounted.
See
discount_rate
.Return type: decimal.Decimal
-
discount_rate
¶ Discount rate, 1 meaning totally discounted.
Note: Could be negative, when base price is smaller than effective price. Could also be greater than 1, when effective price is negative.
If base price is 0, will return 0.
Return type: decimal.Decimal
-
discounted_unit_price
¶ Unit price with discount.
If quantity is 0, will return
base_unit_price - discount_amount
.Return type: shoop.core.pricing.Price
-
is_discounted
¶ Check if there is a discount in effect.
Returns: True, iff price < base price.
-
price
¶ Total price for the specified quantity with discount.
Return type: shoop.core.pricing.Price
-
tax_percentage
¶ Return type: decimal.Decimal
-
tax_rate
¶ Return type: decimal.Decimal
-
taxful_base_price
¶ Taxful
base_price
-
taxful_base_unit_price
¶ Taxful
base_unit_price
-
taxful_discount_amount
¶ Taxful
discount_amount
-
taxful_discounted_unit_price
¶ Taxful
discounted_unit_price
-
taxful_price
¶ Return type: TaxfulPrice
-
taxful_unit_discount_amount
¶ Taxful
unit_discount_amount
-
taxless_base_price
¶ Taxless
base_price
-
taxless_base_unit_price
¶ Taxless
base_unit_price
-
taxless_discount_amount
¶ Taxless
discount_amount
-
taxless_discounted_unit_price
¶ Taxless
discounted_unit_price
-
taxless_price
¶ Return type: TaxlessPrice
-
taxless_unit_discount_amount
¶ Taxless
unit_discount_amount
-
unit_discount_amount
¶ Discount amount per unit.
If quantity is 0, will return
discount_amount
.Return type: shoop.core.pricing.Price
-
class
shoop.core.pricing.
PriceInfo
(price, base_price, quantity, expires_on=None)¶ Bases:
shoop.core.pricing.Priceful
Object for passing around pricing data of an item.
Initialize PriceInfo with prices and other parameters.
Prices can be taxful or taxless, but their types must match.
Parameters: - price (Price) – Effective price for the specified quantity.
- base_price (Price) – Base price for the specified quantity. Discounts are calculated based on this.
- quantity (numbers.Number) – Quantity that the given price is for. Unit price is
calculated by
discounted_unit_price = price / quantity
. Note: Quantity could be non-integral (i.e. decimal). - expires_on (numbers.Number|None) – Timestamp, comparable to values returned by
time.time
, determining the point in time when the prices are no longer valid, or None if no expire time is set (which could mean indefinitely, but in reality, it just means undefined).
-
base_price
= None¶
-
price
= None¶
-
quantity
= None¶
-
class
shoop.core.pricing.
PricingContext
(**kwargs)¶ Bases:
shoop.core.pricing.PricingContextable
Context for pricing.
-
REQUIRED_VALUES
= ()¶
-
cache_key
¶
-
-
class
shoop.core.pricing.
PricingContextable
¶ Bases:
object
Object that is or can be converted to a pricing context.
Currently there exists two kind of
PricingContextable
objects:PricingContext`(and its subclasses) and `HttpRequest
.Note
Expression
isinstance(request, PricingContextable)
will return True for arequest
which isHttpRequest
, becauseHttpRequest
is registered as a subclass of this abstract base class.This abstract base class is just a helper to allow writing simpler type specifiers, since we want to allow passing
HttpRequest
as a pricing context even though it is not aPricingContext
.
-
class
shoop.core.pricing.
PricingModule
¶ Bases:
object
-
get_context
(context)[source]¶ Create pricing context from pricing contextable object.
Return type: PricingContext
-
get_context_from_data
(**context_data)[source]¶ Create pricing context from keyword arguments.
Return type: PricingContext
-
get_context_from_request
(request)[source]¶ Create pricing context from HTTP request.
This base class implementation does not use
request
at all.Return type: PricingContext
-
get_price_info
(context, product, quantity=1)[source]¶ Get price info of product for given quantity.
Parameters: product (shoop.core.models.Product|int) – Product
object or id ofProduct
Return type: PriceInfo
-
get_price_infos
(context, products, quantity=1)[source]¶ Get PriceInfo objects for a bunch of products.
Returns a dict with product id as key and PriceInfo as value.
May be faster than doing
get_price_info
for each product separately, since inheriting class may override this.Parameters: products (Iterable[shoop.core.models.Product|int]) – List of product objects or id’s Return type: dict[int,PriceInfo]
-
get_pricing_steps
(context, product)[source]¶ Get context-specific list pricing steps for the given product.
Returns a list of PriceInfos
[pi0, pi1, pi2, ...]
where each PriceInfo object is at the border unit price change: unit price for0 <= quantity < pi1.quantity1
ispi0.discounted_unit_price
, and unit price forpi1.quantity <= quantity < pi2.quantity
ispi1.discounted_unit_price
, and so on.If there are “no steps”, the return value will be a list of single PriceInfo object with the constant price, i.e.
[price_info]
.Parameters: product (shoop.core.models.Product|int) – Product or product id Return type: list[PriceInfo]
-
get_pricing_steps_for_products
(context, products)[source]¶ Get pricing steps for a bunch of products.
Returns a dict with product id as key and step data (as list of PriceInfos) as values.
May be faster than doing
get_pricing_steps
for each product separately, since inheriting class may override this.Parameters: products (Iterable[shoop.core.models.Product|int]) – List of product objects or id’s Return type: dict[int,list[PriceInfo]]
-
identifier
= None¶
-
name
= None¶
-
pricing_context_class
¶ alias of
PricingContext
-
-
class
shoop.core.pricing.
TaxfulPrice
¶ Bases:
shoop.core.pricing.Price
Price which includes taxes.
Check the base class,
Price
, for more info.-
includes_tax
= True¶
-
-
class
shoop.core.pricing.
TaxlessPrice
¶ Bases:
shoop.core.pricing.Price
Price which does not include taxes.
Check the base class,
Price
, for more info.-
includes_tax
= False¶
-
-
shoop.core.pricing.
get_pricing_module
()¶ Return type: shoop.core.pricing.PricingModule