models.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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'), (SUBMITTED, 'Submitted'),
  45. (PROCESSED, 'Processed'), (SHIPPED, 'Shipped'),
  46. (CANCELLED, 'Cancelled'))
  47. #order info
  48. date = models.DateTimeField(auto_now_add=True)
  49. status = models.IntegerField(choices=ORDER_STATUSES, default=INIT)
  50. ip_address = models.IPAddressField(null=True, blank=True)
  51. last_updated = models.DateTimeField(auto_now=True)
  52. user = models.ForeignKey(User, null=True, blank=True)
  53. transaction_id = models.CharField(max_length=20, null=True, blank=True)
  54. cart_id = models.CharField(max_length=50, null=True, blank=True)
  55. objects = managers.OrderManager()
  56. def __unicode__(self):
  57. return u'Order #' + str(self.id)
  58. @property
  59. def get_status(self):
  60. for enum, value in self.ORDER_STATUSES:
  61. if self.status == enum:
  62. return value
  63. @property
  64. def has_items(self):
  65. return self.item_count > 0
  66. @property
  67. def item_count(self):
  68. return self.items.count()
  69. @property
  70. def order_items(self):
  71. return self.items.all()
  72. @property
  73. def subscription_items(self):
  74. """ return only the subscriptions """
  75. for item in self.order_items:
  76. if item.is_subscription:
  77. yield item
  78. @property
  79. def subtotal(self):
  80. total = Decimal('0.00')
  81. for item in self.order_items:
  82. total += item.total
  83. return total
  84. @property
  85. def shipping_total(self):
  86. ship_cost = Decimal(0.0)
  87. for item in self.order_items:
  88. ship_cost = ship_cost + item.shipping_cost
  89. return ship_cost
  90. @property
  91. def total(self):
  92. return self.subtotal + self.shipping_total
  93. @models.permalink
  94. def get_absolute_url(self):
  95. return 'view_order_detail', (), {'order_number': self.pk}
  96. def delete_items(self):
  97. """ delete all orderItems for this order """
  98. OrderItem.objects.filter(order=self).delete()
  99. class OrderPayment(TimeStampedModel):
  100. order = models.OneToOneField(Order)
  101. amazon_payment = models.ForeignKey(
  102. AmazonFPSResponse, related_name='order_payment', blank=True, null=True)
  103. google_payment = models.ForeignKey(
  104. GCNewOrderNotification, related_name='order_payment', blank=True,
  105. null=True)
  106. @property
  107. def is_amazon(self):
  108. if self.amazon_payment:
  109. return True
  110. return False
  111. @property
  112. def is_google(self):
  113. if self.google_payment:
  114. return True
  115. return False
  116. @property
  117. def shipping_state(self):
  118. if self.is_google:
  119. return self.google_payment.fulfillment_order_state
  120. return "N/A"
  121. @property
  122. def payment_state(self):
  123. if self.is_google:
  124. return self.google_payment.financial_order_state
  125. return "N/A"
  126. class OrderItemGiftDetail(TimeStampedModel):
  127. first_name = models.CharField(max_length=30)
  128. last_name = models.CharField(max_length=30)
  129. company = models.CharField(max_length=30, blank=True, null=True)
  130. address1 = models.CharField(max_length=30)
  131. address2 = models.CharField(max_length=30, blank=True, null=True)
  132. city = models.CharField(max_length=30)
  133. region = models.CharField(max_length=30, choices=STATE_CHOICES)
  134. phone = models.CharField(max_length=30)
  135. country = models.CharField(max_length=30, choices=COUNTRIES)
  136. postal_code = models.CharField(max_length=30)
  137. plus_four = models.CharField(max_length=4)
  138. email = models.CharField(max_length=30)
  139. bill_on_renewal = models.CharField(
  140. max_length=10, choices=constants.BILL_CHOICES,
  141. default=constants.CHOOSE)
  142. gift_card_delivery = models.CharField(
  143. max_length=10, choices=constants.GIFT_CARD_DELIVERY_CHOICES,
  144. default=constants.GIFT_CARD_NONE)
  145. message = models.CharField(max_length=72, null=True, blank=True)
  146. class OrderItem(TimeStampedModel):
  147. """ store each Product instance purchased in each order """
  148. product = models.ForeignKey(Item)
  149. quantity = models.IntegerField(default=1)
  150. price = models.DecimalField(max_digits=9, decimal_places=2)
  151. order = models.ForeignKey(Order, related_name='items')
  152. gift_detail = models.OneToOneField(
  153. OrderItemGiftDetail, null=True, blank=True)
  154. account_number = models.CharField(max_length=7, null=True, blank=True)
  155. @property
  156. def is_gift(self):
  157. if self.gift_detail:
  158. return True
  159. return False
  160. @property
  161. def is_subscription(self):
  162. if self.product.is_subscription:
  163. return True
  164. return False
  165. @property
  166. def total(self):
  167. return self.quantity * self.price
  168. @property
  169. def name(self):
  170. return self.product.title
  171. @property
  172. def long_description(self):
  173. return self.product.long_description
  174. @property
  175. def sku(self):
  176. return self.product.sku
  177. def __unicode__(self):
  178. return self.product.title + ' (' + self.product.sku + ')'
  179. @property
  180. def shipping_cost(self):
  181. """ Shipping costs. If there is just one item take the shipping_cost
  182. from the product, if there is more then one, for each item after the
  183. first one, the shipping cost is shipping_cost_multiple for each item
  184. total them together to get the total shipping cost
  185. """
  186. initial_cost = self.product.shipping_cost
  187. if self.quantity == 0:
  188. return 0.0
  189. if self.quantity == 1:
  190. return initial_cost
  191. elif self.quantity > 1:
  192. return (initial_cost + ((self.quantity - 1) *
  193. self.product.shipping_cost_multiple))
  194. @property
  195. def total_plus_shipping(self):
  196. return self.total + self.shipping_cost