Source code for shuup.campaigns.models.basket_effects

# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. 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.

from django.db import models
from django.utils.translation import ugettext_lazy as _

from shuup.admin.forms.fields import PercentageField
from shuup.campaigns.utils.campaigns import get_total_price_of_products
from shuup.core.fields import MoneyValueField
from shuup.core.models import PolymorphicShuupModel
from shuup.core.pricing import PricingContext


[docs]class BasketDiscountEffect(PolymorphicShuupModel): identifier = None model = None admin_form_class = None campaign = models.ForeignKey( on_delete=models.CASCADE, to="BasketCampaign", related_name="discount_effects", verbose_name=_("campaign") )
[docs] def apply_for_basket(self, order_source): """ Applies the effect based on given `order_source` :return: amount of discount to accumulate for the product :rtype: Price """ raise NotImplementedError("Error! Not implemented: `BasketDiscountEffect` -> `apply_for_basket()`.")
[docs]class BasketDiscountAmount(BasketDiscountEffect): identifier = "discount_amount_effect" name = _("Discount amount value") discount_amount = MoneyValueField( default=None, blank=True, null=True, verbose_name=_("discount amount"), help_text=_("Flat amount of discount.") ) @property def description(self): return _("Give discount amount.") @property def value(self): return self.discount_amount @value.setter def value(self, value): self.discount_amount = value
[docs] def apply_for_basket(self, order_source): return order_source.create_price(self.value)
[docs]class BasketDiscountPercentage(BasketDiscountEffect): identifier = "discount_percentage_effect" name = _("Discount amount percentage") admin_form_class = PercentageField discount_percentage = models.DecimalField( max_digits=6, decimal_places=5, blank=True, null=True, verbose_name=_("discount percentage"), help_text=_("The discount percentage for this campaign."), ) @property def description(self): return _("Give percentage discount.") @property def value(self): return self.discount_percentage @value.setter def value(self, value): self.discount_percentage = value
[docs] def apply_for_basket(self, order_source): total_price_of_products = get_total_price_of_products(order_source, self.campaign) return total_price_of_products * self.value
[docs]class DiscountPercentageFromUndiscounted(BasketDiscountEffect): identifier = "undiscounted_percentage_effect" name = _("Discount amount percentage from undiscounted amount") admin_form_class = PercentageField discount_percentage = models.DecimalField( max_digits=6, decimal_places=5, blank=True, null=True, verbose_name=_("discount percentage"), help_text=_("The discount percentage for this campaign."), ) @property def description(self): return _("Give percentage discount based on undiscounted product prices.") @property def value(self): return self.discount_percentage @value.setter def value(self, value): self.discount_percentage = value
[docs] def apply_for_basket(self, order_source): from shuup.campaigns.models import CatalogCampaign campaign = self.campaign supplier = campaign.supplier if hasattr(campaign, "supplier") and campaign.supplier else None discounted_base_amount = get_total_price_of_products(order_source, campaign) context = PricingContext(order_source.shop, order_source.customer) for line in order_source.get_product_lines(): if supplier and line.supplier != supplier: continue product = line.product if CatalogCampaign.get_matching(context, product.get_shop_instance(order_source.shop)): discounted_base_amount -= line.price return discounted_base_amount * self.value