models.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. from decimal import Decimal
  2. from django.contrib.localflavor.us.us_states import STATE_CHOICES
  3. from django.db import models
  4. from django.contrib.auth.models import User
  5. from django_countries.countries import COUNTRIES
  6. from billing.models import GCNewOrderNotification, AmazonFPSResponse
  7. from catalog.models import Item
  8. from pbp_core.models import TimeStampedModel
  9. from . import constants
  10. from . import managers
  11. class BaseOrderInfo(TimeStampedModel):
  12. """ base class for storing customer order information """
  13. class Meta:
  14. abstract = True
  15. # contact info
  16. email = models.EmailField(max_length=50, null=True, blank=True)
  17. phone = models.CharField(max_length=20, null=True, blank=True)
  18. # shipping information
  19. shipping_name = models.CharField(max_length=50, null=True, blank=True)
  20. shipping_address_1 = models.CharField(max_length=50, null=True, blank=True)
  21. shipping_address_2 = models.CharField(max_length=50, null=True, blank=True)
  22. shipping_city = models.CharField(max_length=50, null=True, blank=True)
  23. shipping_state = models.CharField(max_length=2, null=True, blank=True)
  24. shipping_country = models.CharField(max_length=50, null=True, blank=True)
  25. shipping_zip = models.CharField(max_length=10, null=True, blank=True)
  26. # billing information
  27. billing_name = models.CharField(max_length=50, null=True, blank=True)
  28. billing_address_1 = models.CharField(max_length=50, null=True, blank=True)
  29. billing_address_2 = models.CharField(max_length=50, null=True, blank=True)
  30. billing_city = models.CharField(max_length=50, null=True, blank=True)
  31. billing_state = models.CharField(max_length=2, null=True, blank=True)
  32. billing_country = models.CharField(max_length=50, null=True, blank=True)
  33. billing_zip = models.CharField(max_length=10, null=True, blank=True)
  34. class Order(BaseOrderInfo):
  35. """ model class for storing a customer order instance """
  36. # each individual status
  37. INIT = 0
  38. SUBMITTED = 1
  39. PROCESSED = 2
  40. SHIPPED = 3
  41. CANCELLED = 4
  42. # set of possible order statuses
  43. ORDER_STATUSES = (
  44. (INIT, "Initialized"),
  45. (SUBMITTED, "Submitted"),
  46. (PROCESSED, "Processed"),
  47. (SHIPPED, "Shipped"),
  48. (CANCELLED, "Cancelled"),
  49. )
  50. # order info
  51. date = models.DateTimeField(auto_now_add=True)
  52. status = models.IntegerField(choices=ORDER_STATUSES, default=INIT)
  53. ip_address = models.IPAddressField(null=True, blank=True)
  54. last_updated = models.DateTimeField(auto_now=True)
  55. user = models.ForeignKey(User, null=True, blank=True)
  56. transaction_id = models.CharField(max_length=20, null=True, blank=True)
  57. cart_id = models.CharField(max_length=50, null=True, blank=True)
  58. objects = managers.OrderManager()
  59. def __unicode__(self):
  60. return u"Order #" + str(self.id)
  61. @property
  62. def get_status(self):
  63. for enum, value in self.ORDER_STATUSES:
  64. if self.status == enum:
  65. return value
  66. @property
  67. def has_items(self):
  68. return self.item_count > 0
  69. @property
  70. def item_count(self):
  71. return self.items.count()
  72. @property
  73. def order_items(self):
  74. return self.items.all()
  75. @property
  76. def subscription_items(self):
  77. """ return only the subscriptions """
  78. for item in self.order_items:
  79. if item.is_subscription:
  80. yield item
  81. @property
  82. def subtotal(self):
  83. total = Decimal("0.00")
  84. for item in self.order_items:
  85. total += item.total
  86. return total
  87. @property
  88. def shipping_total(self):
  89. ship_cost = Decimal(0.0)
  90. for item in self.order_items:
  91. ship_cost = ship_cost + item.shipping_cost
  92. return ship_cost
  93. @property
  94. def total(self):
  95. return self.subtotal + self.shipping_total
  96. @models.permalink
  97. def get_absolute_url(self):
  98. return "view_order_detail", (), {"order_number": self.pk}
  99. def delete_items(self):
  100. """ delete all orderItems for this order """
  101. OrderItem.objects.filter(order=self).delete()
  102. class OrderPayment(TimeStampedModel):
  103. order = models.OneToOneField(Order)
  104. amazon_payment = models.ForeignKey(
  105. AmazonFPSResponse, related_name="order_payment", blank=True, null=True
  106. )
  107. google_payment = models.ForeignKey(
  108. GCNewOrderNotification, related_name="order_payment", blank=True, null=True
  109. )
  110. @property
  111. def is_amazon(self):
  112. if self.amazon_payment:
  113. return True
  114. return False
  115. @property
  116. def is_google(self):
  117. if self.google_payment:
  118. return True
  119. return False
  120. @property
  121. def shipping_state(self):
  122. if self.is_google:
  123. return self.google_payment.fulfillment_order_state
  124. return "N/A"
  125. @property
  126. def payment_state(self):
  127. if self.is_google:
  128. return self.google_payment.financial_order_state
  129. return "N/A"
  130. class OrderItemGiftDetail(TimeStampedModel):
  131. first_name = models.CharField(max_length=30)
  132. last_name = models.CharField(max_length=30)
  133. company = models.CharField(max_length=30, blank=True, null=True)
  134. address1 = models.CharField(max_length=30)
  135. address2 = models.CharField(max_length=30, blank=True, null=True)
  136. city = models.CharField(max_length=30)
  137. region = models.CharField(max_length=30, choices=STATE_CHOICES)
  138. phone = models.CharField(max_length=30)
  139. country = models.CharField(max_length=30, choices=COUNTRIES)
  140. postal_code = models.CharField(max_length=30)
  141. plus_four = models.CharField(max_length=4)
  142. email = models.CharField(max_length=30)
  143. bill_on_renewal = models.CharField(
  144. max_length=10, choices=constants.BILL_CHOICES, default=constants.CHOOSE
  145. )
  146. gift_card_delivery = models.CharField(
  147. max_length=10,
  148. choices=constants.GIFT_CARD_DELIVERY_CHOICES,
  149. default=constants.GIFT_CARD_NONE,
  150. )
  151. message = models.CharField(max_length=72, null=True, blank=True)
  152. class OrderItem(TimeStampedModel):
  153. """ store each Product instance purchased in each order """
  154. product = models.ForeignKey(Item)
  155. quantity = models.IntegerField(default=1)
  156. price = models.DecimalField(max_digits=9, decimal_places=2)
  157. order = models.ForeignKey(Order, related_name="items")
  158. gift_detail = models.OneToOneField(OrderItemGiftDetail, null=True, blank=True)
  159. account_number = models.CharField(max_length=7, null=True, blank=True)
  160. @property
  161. def is_gift(self):
  162. if self.gift_detail:
  163. return True
  164. return False
  165. @property
  166. def is_subscription(self):
  167. if self.product.is_subscription:
  168. return True
  169. return False
  170. @property
  171. def total(self):
  172. return self.quantity * self.price
  173. @property
  174. def name(self):
  175. return self.product.title
  176. @property
  177. def long_description(self):
  178. return self.product.long_description
  179. @property
  180. def sku(self):
  181. return self.product.sku
  182. def __unicode__(self):
  183. return self.product.title + " (" + self.product.sku + ")"
  184. @property
  185. def shipping_cost(self):
  186. """ Shipping costs. If there is just one item take the shipping_cost
  187. from the product, if there is more then one, for each item after the
  188. first one, the shipping cost is shipping_cost_multiple for each item
  189. total them together to get the total shipping cost
  190. """
  191. initial_cost = self.product.shipping_cost
  192. if self.quantity == 0:
  193. return 0.0
  194. if self.quantity == 1:
  195. return initial_cost
  196. elif self.quantity > 1:
  197. return initial_cost + (
  198. (self.quantity - 1) * self.product.shipping_cost_multiple
  199. )
  200. @property
  201. def total_plus_shipping(self):
  202. return self.total + self.shipping_cost