You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

abstract_models.py 2.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from decimal import Decimal, ROUND_UP
  2. from django.db import models
  3. from django.utils.translation import ugettext as _
  4. ABSOLUTE_DISCOUNT, PERCENTAGE_DISCOUNT, FINAL_PRICE = "Absolute", "Percentage", "Final price"
  5. class AbstractDiscountOffer(models.Model):
  6. u"""
  7. A fixed-discount offer (eg get 10% off all fiction books)
  8. """
  9. name = models.CharField(max_length=128)
  10. description = models.TextField(blank=True, null=True)
  11. start_date = models.DateField()
  12. end_date = models.DateField()
  13. products = models.ManyToManyField('product.Item')
  14. TYPE_CHOICES = (
  15. (ABSOLUTE_DISCOUNT, _("An absolute amount of discount off the site price")),
  16. (PERCENTAGE_DISCOUNT, _("A percentage discount off the site price")),
  17. (FINAL_PRICE, _("Sets the site price")),
  18. )
  19. discount_type = models.CharField(_("Discount type"), max_length=128, choices=TYPE_CHOICES, default=PERCENTAGE_DISCOUNT)
  20. discount_value = models.DecimalField(decimal_places=2, max_digits=12,
  21. help_text="""For percentage values, enter integers less than 100 (eg '25' for a 25% discount)""")
  22. date_created = models.DateTimeField(auto_now_add=True)
  23. class Meta:
  24. ordering = ['-date_created']
  25. abstract = True
  26. def __unicode__(self):
  27. return self.name
  28. def is_active(self, test_date=None):
  29. u"""
  30. Tests whether this offer is currently active or not.
  31. """
  32. if not test_date:
  33. test_date = datetime.date.today()
  34. return self.start_date <= test_date and test_date < self.end_date
  35. def num_products(self):
  36. return self.products.count()
  37. def apply(self):
  38. u"""
  39. Applies this offer to its linked products.
  40. The default behaviour of this method is to always
  41. apply this offer, even if it makes the product more expensive.
  42. This behaviour can of course customised by subclassing.
  43. """
  44. for product in self.products.all():
  45. self._apply_discount_to_product(product)
  46. def _apply_discount_to_product(self, product):
  47. u"""
  48. Applies this offer to an individual product
  49. """
  50. if product.has_stockrecord:
  51. discount_price = self._get_discount_price(product)
  52. product.stockrecord.set_discount_price(discount_price)
  53. def _get_discount_price(self, product):
  54. u"""
  55. Returns the discounted price
  56. """
  57. current_price = product.stockrecord.price_excl_tax
  58. if self.discount_type == ABSOLUTE_DISCOUNT:
  59. price = max(Decimal('0.00'), current_price - self.discount_value)
  60. elif self.discount_type == PERCENTAGE_DISCOUNT:
  61. price = current_price * (1 - self.discount_value/100)
  62. else:
  63. price = self.discount_value
  64. return price.quantize(Decimal('.01'))