auction.models.bases: 125 total statements, 97.2% covered

Generated: Mon 2013-04-29 18:13 CST

Source file: /home/slam/workspace/django-auction/auction/models/bases.py

Stats: 105 executed, 3 missed, 17 excluded, 67 ignored

  1. from decimal import Decimal
  2. from django.db import models
  3. from polymorphic.polymorphic_model import PolymorphicModel
  4. from django.utils.translation import ugettext_lazy as _
  5. from django.contrib.auth.models import User
  6. from django.contrib.contenttypes.models import ContentType
  7. from django.contrib.contenttypes import generic
  8. from auction.utils.loader import get_model_string
  9. from south.modelsinspector import add_introspection_rules
  10. from django.conf import settings
  11. add_introspection_rules([], ["^auction\.models\.bases\.CurrencyField"])
  12. class CurrencyField(models.DecimalField):
  13. __metaclass__ = models.SubfieldBase
  14. def to_python(self, value):
  15. try:
  16. return super(CurrencyField, self).to_python(value=value).quantize(Decimal("0.01"))
  17. except AttributeError:
  18. return None
  19. class BaseAuction(PolymorphicModel):
  20. name = models.CharField(max_length=255, verbose_name=_('Auction name'))
  21. slug = models.SlugField(unique=True, verbose_name=_('Slug'))
  22. start_date = models.DateTimeField(verbose_name=_('Start date'))
  23. end_date = models.DateTimeField(verbose_name=_('End date'))
  24. active = models.BooleanField(default=False, verbose_name=_('Active'))
  25. total_bids = models.IntegerField(default=0, verbose_name=_('Total bids'))
  26. date_added = models.DateTimeField(auto_now_add=True, verbose_name=_('Date added'))
  27. last_modified = models.DateTimeField(auto_now=True, verbose_name=_('Last modified'))
  28. class Meta:
  29. abstract = True
  30. app_label = 'auction'
  31. verbose_name = _('Auction')
  32. verbose_name_plural = _('Auctions')
  33. def __unicode__(self):
  34. return self.name
  35. class BaseBidBasket(models.Model):
  36. """
  37. This models functions similarly to a shopping cart, except it expects a logged in user.
  38. """
  39. user = models.OneToOneField(User, related_name="%(app_label)s_%(class)s_related", verbose_name=_('User'))
  40. date_added = models.DateTimeField(auto_now_add=True, verbose_name=_('Date added'))
  41. last_modified = models.DateTimeField(auto_now=True, verbose_name=_('Last modified'))
  42. class Meta:
  43. abstract = True
  44. app_label = 'auction'
  45. verbose_name = _('Bid basket')
  46. verbose_name_plural = _('Bid baskets')
  47. def add_bid(self, lot, amount):
  48. from auction.models import BidItem
  49. self.save()
  50. if not lot.is_biddable:
  51. return False
  52. try:
  53. amount = Decimal(amount)
  54. except Exception, e:
  55. amount = Decimal('0')
  56. from auction.models.lot import Lot
  57. item,created = BidItem.objects.get_or_create(bid_basket=self,
  58. content_type=ContentType.objects.get_for_model(Lot),
  59. lot_id=lot.pk)
  60. if item:
  61. item.amount=amount
  62. item.save()
  63. return item
  64. def update_bid(self, bid_basket_item_id, amount):
  65. """
  66. Update amount of bid. Delete bid if amount is 0.
  67. """
  68. try:
  69. amount = Decimal(amount)
  70. except Exception, e:
  71. amount = Decimal('0')
  72. bid_basket_item = self.bids.get(pk=bid_basket_item_id)
  73. if not bid_basket_item.is_locked():
  74. if amount == 0:
  75. bid_basket_item.delete()
  76. else:
  77. bid_basket_item.amount = amount
  78. bid_basket_item.save()
  79. self.save()
  80. return bid_basket_item
  81. def delete_bid(self, bid_basket_item_id):
  82. """
  83. Delete a single item from bid basket.
  84. """
  85. bid_basket_item = self.bids.get(pk=bid_basket_item_id)
  86. if not bid_basket_item.is_locked():
  87. bid_basket_item.delete()
  88. return bid_basket_item
  89. def empty(self):
  90. """
  91. Remove all bids from bid basket.
  92. """
  93. if self.pk:
  94. bids = self.bids.all()
  95. for bid in bids:
  96. if not bid.is_locked():
  97. bid.delete()
  98. @property
  99. def bids(self):
  100. """
  101. Used as accessor for abstract related (BaseBidItem.bid_items).
  102. If you override BaseBidItem and use a label other than "auction"
  103. you will also need to set AUCTION_BIDBASKET_BIDS_RELATED_NAME.
  104. Example: foo_biditem_related
  105. (where your label is "foo" and your model is "BidItem")
  106. """
  107. bids = getattr(settings, 'AUCTION_BIDBASKET_BIDS_RELATED_NAME',
  108. 'auction_biditem_related')
  109. return getattr(self, bids)
  110. @property
  111. def total_bids(self):
  112. """
  113. Returns total bids in basket.
  114. """
  115. return len(self.bids.all())
  116. class BaseAuctionLot(PolymorphicModel):
  117. name = models.CharField(max_length=255, verbose_name=_('Lot name'))
  118. slug = models.SlugField(verbose_name=_('Slug'))
  119. active = models.BooleanField(default=False, verbose_name=_('Active'))
  120. is_biddable = models.BooleanField(default=False, verbose_name=_('Is biddable?'))
  121. content_type = models.ForeignKey(ContentType, verbose_name=_('Content type'))
  122. object_id = models.PositiveIntegerField(verbose_name=_('Object ID'))
  123. content_object = generic.GenericForeignKey('content_type', 'object_id')
  124. date_added = models.DateTimeField(auto_now_add=True, verbose_name=_('Date added'))
  125. last_modified = models.DateTimeField(auto_now=True, verbose_name=_('Last modified'))
  126. class Meta:
  127. abstract = True
  128. app_label = 'auction'
  129. verbose_name = _('Auction lot')
  130. verbose_name_plural = _('Auction lots')
  131. def __unicode__(self):
  132. return self.name
  133. @property
  134. def is_locked(self):
  135. """
  136. This property is meant to be overwritten with your own logic. Bid baskets
  137. check this method to find out if a bid can be manipulated.
  138. """
  139. import auction.utils.generic
  140. now = auction.utils.generic.get_current_time()
  141. if self.content_object.end_date <= now:
  142. return True
  143. return False
  144. class BaseBidItem(models.Model):
  145. """
  146. This is a holder for total number of bids and a pointer to
  147. item being bid on.
  148. """
  149. bid_basket = models.ForeignKey(get_model_string("BidBasket"), related_name="%(app_label)s_%(class)s_related", verbose_name=_('Bid basket'))
  150. content_type = models.ForeignKey(ContentType, related_name="%(app_label)s_%(class)s_related", verbose_name=_('Content type'))
  151. lot_id = models.PositiveIntegerField(verbose_name=_('Lot ID'))
  152. lot_object = generic.GenericForeignKey('content_type', 'lot_id')
  153. amount = CurrencyField(max_digits=100, decimal_places=2, null=True, blank=True, verbose_name=_('Amount'))
  154. class Meta:
  155. abstract = True
  156. app_label = 'auction'
  157. verbose_name = _('Bid item')
  158. verbose_name_plural = _('Bid items')
  159. def is_locked(self):
  160. return self.lot.is_locked
  161. @property
  162. def lot(self):
  163. return self.lot_object