Refactors flags and discount classes to be DRYer.

This commit is contained in:
Christopher Neugebauer 2016-09-04 11:30:29 +10:00
parent 7e39339ed9
commit 1333fcdea1

View file

@ -9,7 +9,75 @@ from django.utils.translation import ugettext_lazy as _
from model_utils.managers import InheritanceManager from model_utils.managers import InheritanceManager
# Product Modifiers # Condition Types
class TimeOrStockLimitCondition(models.Model):
''' Attributes for a condition that is limited by timespan or a count of
purchased or reserved items.
Attributes:
start_time (Optional[datetime]): When the condition should start being
true.
end_time (Optional[datetime]): When the condition should stop being
true.
limit (Optional[int]): How many items may fall under the condition
the condition until it stops being false -- for all users.
'''
class Meta:
abstract = True
start_time = models.DateTimeField(
null=True,
blank=True,
verbose_name=_("Start time"),
help_text=_("When the condition should start being true"),
)
end_time = models.DateTimeField(
null=True,
blank=True,
verbose_name=_("End time"),
help_text=_("When the condition should stop being true."),
)
limit = models.PositiveIntegerField(
null=True,
blank=True,
verbose_name=_("Limit"),
help_text=_(
"How many times this condition may be applied for all users."
),
)
class VoucherCondition(models.Model):
''' A condition is met when a voucher code is in the current cart. '''
class Meta:
abstract = True
voucher = models.OneToOneField(
inventory.Voucher,
on_delete=models.CASCADE,
verbose_name=_("Voucher"),
db_index=True,
)
class IncludedProductCondition(models.Model):
class Meta:
abstract = True
enabling_products = models.ManyToManyField(
inventory.Product,
verbose_name=_("Including product"),
help_text=_("If one of these products are purchased, this condition "
"is met."),
)
# Discounts
@python_2_unicode_compatible @python_2_unicode_compatible
class DiscountBase(models.Model): class DiscountBase(models.Model):
@ -154,7 +222,7 @@ class DiscountForCategory(models.Model):
quantity = models.PositiveIntegerField() quantity = models.PositiveIntegerField()
class TimeOrStockLimitDiscount(DiscountBase): class TimeOrStockLimitDiscount(TimeOrStockLimitCondition, DiscountBase):
''' Discounts that are generally available, but are limited by timespan or ''' Discounts that are generally available, but are limited by timespan or
usage count. This is for e.g. Early Bird discounts. usage count. This is for e.g. Early Bird discounts.
@ -175,27 +243,8 @@ class TimeOrStockLimitDiscount(DiscountBase):
verbose_name = _("discount (time/stock limit)") verbose_name = _("discount (time/stock limit)")
verbose_name_plural = _("discounts (time/stock limit)") verbose_name_plural = _("discounts (time/stock limit)")
start_time = models.DateTimeField(
null=True,
blank=True,
verbose_name=_("Start time"),
help_text=_("This discount will only be available after this time."),
)
end_time = models.DateTimeField(
null=True,
blank=True,
verbose_name=_("End time"),
help_text=_("This discount will only be available before this time."),
)
limit = models.PositiveIntegerField(
null=True,
blank=True,
verbose_name=_("Limit"),
help_text=_("This discount may only be applied this many times."),
)
class VoucherDiscount(VoucherCondition, DiscountBase):
class VoucherDiscount(DiscountBase):
''' Discounts that are enabled when a voucher code is in the current ''' Discounts that are enabled when a voucher code is in the current
cart. These are normally configured in the Admin page at the same time as cart. These are normally configured in the Admin page at the same time as
creating a Voucher object. creating a Voucher object.
@ -210,15 +259,8 @@ class VoucherDiscount(DiscountBase):
verbose_name = _("discount (enabled by voucher)") verbose_name = _("discount (enabled by voucher)")
verbose_name_plural = _("discounts (enabled by voucher)") verbose_name_plural = _("discounts (enabled by voucher)")
voucher = models.OneToOneField(
inventory.Voucher,
on_delete=models.CASCADE,
verbose_name=_("Voucher"),
db_index=True,
)
class IncludedProductDiscount(IncludedProductCondition, DiscountBase):
class IncludedProductDiscount(DiscountBase):
''' Discounts that are enabled because another product has been purchased. ''' Discounts that are enabled because another product has been purchased.
e.g. A conference ticket includes a free t-shirt. e.g. A conference ticket includes a free t-shirt.
@ -233,13 +275,6 @@ class IncludedProductDiscount(DiscountBase):
verbose_name = _("discount (product inclusions)") verbose_name = _("discount (product inclusions)")
verbose_name_plural = _("discounts (product inclusions)") verbose_name_plural = _("discounts (product inclusions)")
enabling_products = models.ManyToManyField(
inventory.Product,
verbose_name=_("Including product"),
help_text=_("If one of these products are purchased, the discounts "
"below will be enabled."),
)
class RoleDiscount(object): class RoleDiscount(object):
''' Discounts that are enabled because the active user has a specific ''' Discounts that are enabled because the active user has a specific
@ -330,7 +365,7 @@ class FlagBase(models.Model):
) )
class TimeOrStockLimitFlag(FlagBase): class TimeOrStockLimitFlag(TimeOrStockLimitCondition, FlagBase):
''' Product groupings that can be used to enable a product during a ''' Product groupings that can be used to enable a product during a
specific date range, or when fewer than a limit of products have been specific date range, or when fewer than a limit of products have been
sold. sold.
@ -352,28 +387,9 @@ class TimeOrStockLimitFlag(FlagBase):
verbose_name = _("flag (time/stock limit)") verbose_name = _("flag (time/stock limit)")
verbose_name_plural = _("flags (time/stock limit)") verbose_name_plural = _("flags (time/stock limit)")
start_time = models.DateTimeField(
null=True,
blank=True,
help_text=_("Products included in this condition will only be "
"available after this time."),
)
end_time = models.DateTimeField(
null=True,
blank=True,
help_text=_("Products included in this condition will only be "
"available before this time."),
)
limit = models.PositiveIntegerField(
null=True,
blank=True,
help_text=_("The number of items under this grouping that can be "
"purchased."),
)
@python_2_unicode_compatible @python_2_unicode_compatible
class ProductFlag(FlagBase): class ProductFlag(IncludedProductCondition, FlagBase):
''' The condition is met because a specific product is purchased. ''' The condition is met because a specific product is purchased.
Attributes: Attributes:
@ -389,12 +405,6 @@ class ProductFlag(FlagBase):
def __str__(self): def __str__(self):
return "Enabled by products: " + str(self.enabling_products.all()) return "Enabled by products: " + str(self.enabling_products.all())
enabling_products = models.ManyToManyField(
inventory.Product,
help_text=_("If one of these products are purchased, this condition "
"is met."),
)
@python_2_unicode_compatible @python_2_unicode_compatible
class CategoryFlag(FlagBase): class CategoryFlag(FlagBase):
@ -422,7 +432,7 @@ class CategoryFlag(FlagBase):
@python_2_unicode_compatible @python_2_unicode_compatible
class VoucherFlag(FlagBase): class VoucherFlag(VoucherCondition, FlagBase):
''' The condition is met because a Voucher is present. This is for e.g. ''' The condition is met because a Voucher is present. This is for e.g.
enabling sponsor tickets. ''' enabling sponsor tickets. '''
@ -434,8 +444,6 @@ class VoucherFlag(FlagBase):
def __str__(self): def __str__(self):
return "Enabled by voucher: %s" % self.voucher return "Enabled by voucher: %s" % self.voucher
voucher = models.OneToOneField(inventory.Voucher)
# @python_2_unicode_compatible # @python_2_unicode_compatible
class RoleFlag(object): class RoleFlag(object):