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.

availability.py 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. from django.utils.translation import ugettext_lazy as _
  2. class Base(object):
  3. """
  4. Simple base availability class which defaults to everything being
  5. unavailable.
  6. """
  7. # Standard properties
  8. code = ''
  9. message = ''
  10. lead_time = None
  11. dispatch_date = None
  12. @property
  13. def short_message(self):
  14. """
  15. A shorter version of the availability message, suitable for showing on
  16. browsing pages.
  17. """
  18. return self.message
  19. @property
  20. def is_available_to_buy(self):
  21. """
  22. Test if this product is available to be bought.
  23. """
  24. # We test a purchase of a single item
  25. return self.is_purchase_permitted(1)[0]
  26. def is_purchase_permitted(self, quantity):
  27. """
  28. Test whether a proposed purchase is allowed
  29. Should return a boolean and a reason
  30. """
  31. return False, _("Unavailable")
  32. # Common availability policies
  33. class Unavailable(Base):
  34. """
  35. Policy for when a product is unavailable
  36. """
  37. code = 'unavailable'
  38. message = _("Unavailable")
  39. class Available(Base):
  40. """
  41. For when a product is always available, irrespective of stock level.
  42. This might be appropriate for a digital product.
  43. """
  44. code = 'available'
  45. message = _("Available")
  46. def is_purchase_permitted(self, quantity):
  47. return True, ""
  48. class StockRequired(Base):
  49. """
  50. Enforce a given stock number
  51. """
  52. CODE_IN_STOCK = 'instock'
  53. CODE_OUT_OF_STOCK = 'outofstock'
  54. def __init__(self, num_available):
  55. self.num_available = num_available
  56. def is_purchase_permitted(self, quantity):
  57. if self.num_available == 0:
  58. return False, _("No stock available")
  59. if quantity > self.num_available:
  60. msg = _("A maximum of %(max)d can be bought") % {
  61. 'max': self.num_available}
  62. return False, msg
  63. return True, ""
  64. @property
  65. def code(self):
  66. if self.num_available > 0:
  67. return self.CODE_IN_STOCK
  68. return self.CODE_OUT_OF_STOCK
  69. @property
  70. def short_message(self):
  71. if self.num_available > 0:
  72. return _("In stock")
  73. return _("Not available")
  74. @property
  75. def message(self):
  76. if self.num_available > 0:
  77. return _("In stock (%d available)") % self.num_available
  78. return _("Not available")
  79. class DelegateToStockRecord(Base):
  80. """
  81. An availability class which delegates all calls to the
  82. stockrecord itself. This will exercise the deprecate methods on the
  83. stockrecord that call "partner wrapper" classes.
  84. """
  85. def __init__(self, product, stockrecord=None, user=None):
  86. self.product = product
  87. self.stockrecord = stockrecord
  88. self.user = user
  89. @property
  90. def is_available_to_buy(self):
  91. if self.stockrecord is None:
  92. return False
  93. if not self.product.get_product_class().track_stock:
  94. return True
  95. return self.stockrecord.is_available_to_buy
  96. def is_purchase_permitted(self, quantity):
  97. return self.stockrecord.is_purchase_permitted(
  98. self.user, quantity, self.product)
  99. @property
  100. def code(self):
  101. return self.stockrecord.availability_code
  102. @property
  103. def message(self):
  104. return self.stockrecord.availability
  105. @property
  106. def lead_time(self):
  107. return self.stockrecord.lead_time
  108. @property
  109. def dispatch_date(self):
  110. return self.stockrecord.dispatch_date