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.

utils.py 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import warnings
  2. from django.utils.encoding import force_text
  3. from oscar.core.loading import get_class
  4. Repository = get_class('shipping.repository', 'Repository')
  5. class CheckoutSessionData(object):
  6. """
  7. Class responsible for marshalling all the checkout session data
  8. """
  9. SESSION_KEY = 'checkout_data'
  10. def __init__(self, request):
  11. self.request = request
  12. if self.SESSION_KEY not in self.request.session:
  13. self.request.session[self.SESSION_KEY] = {}
  14. def _check_namespace(self, namespace):
  15. if namespace not in self.request.session[self.SESSION_KEY]:
  16. self.request.session[self.SESSION_KEY][namespace] = {}
  17. def _get(self, namespace, key, default=None):
  18. """
  19. Return session value or None
  20. """
  21. self._check_namespace(namespace)
  22. if key in self.request.session[self.SESSION_KEY][namespace]:
  23. return self.request.session[self.SESSION_KEY][namespace][key]
  24. return default
  25. def _set(self, namespace, key, value):
  26. """
  27. Set session value
  28. """
  29. self._check_namespace(namespace)
  30. self.request.session[self.SESSION_KEY][namespace][key] = value
  31. self.request.session.modified = True
  32. def _unset(self, namespace, key):
  33. """
  34. Unset session value
  35. """
  36. self._check_namespace(namespace)
  37. if key in self.request.session[self.SESSION_KEY][namespace]:
  38. del self.request.session[self.SESSION_KEY][namespace][key]
  39. self.request.session.modified = True
  40. def _flush_namespace(self, namespace):
  41. self.request.session[self.SESSION_KEY][namespace] = {}
  42. self.request.session.modified = True
  43. def flush(self):
  44. """
  45. Delete session key
  46. """
  47. self.request.session[self.SESSION_KEY] = {}
  48. # Guest checkout
  49. def set_guest_email(self, email):
  50. self._set('guest', 'email', email)
  51. def get_guest_email(self):
  52. return self._get('guest', 'email')
  53. # Shipping address
  54. # ================
  55. # Options:
  56. # 1. No shipping required (eg digital products)
  57. # 2. Ship to new address (entered in a form)
  58. # 3. Ship to an addressbook address (address chosen from list)
  59. def reset_shipping_data(self):
  60. self._flush_namespace('shipping')
  61. def ship_to_user_address(self, address):
  62. """
  63. Set existing shipping address id to session and unset address fields
  64. from session
  65. """
  66. self.reset_shipping_data()
  67. self._set('shipping', 'user_address_id', address.id)
  68. def ship_to_new_address(self, address_fields):
  69. """
  70. Set new shipping address details to session and unset shipping address
  71. id
  72. """
  73. self._unset('shipping', 'new_address_fields')
  74. phone_number = address_fields.get('phone_number')
  75. if phone_number:
  76. address_fields = address_fields.copy()
  77. address_fields['phone_number'] = force_text(
  78. address_fields['phone_number'])
  79. self._set('shipping', 'new_address_fields', address_fields)
  80. def new_shipping_address_fields(self):
  81. """
  82. Get shipping address fields from session
  83. """
  84. return self._get('shipping', 'new_address_fields')
  85. def shipping_user_address_id(self):
  86. """
  87. Get user address id from session
  88. """
  89. return self._get('shipping', 'user_address_id')
  90. user_address_id = shipping_user_address_id
  91. def is_shipping_address_set(self):
  92. """
  93. Test whether a shipping address has been stored in the session.
  94. This can be from a new address or re-using an existing address.
  95. """
  96. new_fields = self.new_shipping_address_fields()
  97. has_new_address = new_fields is not None
  98. user_address_id = self.user_address_id()
  99. has_old_address = user_address_id is not None and user_address_id > 0
  100. return has_new_address or has_old_address
  101. # Shipping method
  102. # ===============
  103. def use_free_shipping(self):
  104. """
  105. Set "free shipping" code to session
  106. """
  107. self._set('shipping', 'method_code', '__free__')
  108. def use_shipping_method(self, code):
  109. """
  110. Set shipping method code to session
  111. """
  112. self._set('shipping', 'method_code', code)
  113. def shipping_method_code(self, basket):
  114. """
  115. Returns the shipping method code
  116. """
  117. return self._get('shipping', 'method_code')
  118. def shipping_method(self, basket):
  119. """
  120. Returns the shipping method model based on the
  121. data stored in the session.
  122. """
  123. warnings.warn((
  124. "shipping_method is deprecated as the functionality has "
  125. "been moved to the get_shipping_method from the checkout "
  126. "session mixin"), DeprecationWarning)
  127. code = self.shipping_method_code(basket)
  128. if not code:
  129. return None
  130. return Repository().find_by_code(code, basket)
  131. def is_shipping_method_set(self, basket):
  132. """
  133. Test if a valid shipping method is stored in the session
  134. """
  135. return self.shipping_method_code(basket) is not None
  136. # Billing address fields
  137. # ======================
  138. #
  139. # There are 3 common options:
  140. # 1. Billing address is entered manually through a form
  141. # 2. Billing address is selected from address book
  142. # 3. Billing address is the same as the shipping address
  143. def bill_to_new_address(self, address_fields):
  144. """
  145. Store address fields for a billing address.
  146. """
  147. self._flush_namespace('billing')
  148. self._set('billing', 'new_address_fields', address_fields)
  149. def bill_to_user_address(self, address):
  150. """
  151. Set an address from a user's address book as the billing address
  152. :address: The address object
  153. """
  154. self._flush_namespace('billing')
  155. self._set('billing', 'user_address_id', address.id)
  156. def bill_to_shipping_address(self):
  157. """
  158. Record fact that the billing address is to be the same as
  159. the shipping address.
  160. """
  161. self._flush_namespace('billing')
  162. self._set('billing', 'billing_address_same_as_shipping', True)
  163. # Legacy method name
  164. billing_address_same_as_shipping = bill_to_shipping_address
  165. def is_billing_address_same_as_shipping(self):
  166. return self._get('billing', 'billing_address_same_as_shipping', False)
  167. def billing_user_address_id(self):
  168. """
  169. Return the ID of the user address being used for billing
  170. """
  171. return self._get('billing', 'user_address_id')
  172. def new_billing_address_fields(self):
  173. """
  174. Return fields for a billing address
  175. """
  176. return self._get('billing', 'new_address_fields')
  177. # Payment methods
  178. # ===============
  179. def pay_by(self, method):
  180. self._set('payment', 'method', method)
  181. def payment_method(self):
  182. return self._get('payment', 'method')
  183. # Submission methods
  184. def set_order_number(self, order_number):
  185. self._set('submission', 'order_number', order_number)
  186. def get_order_number(self):
  187. return self._get('submission', 'order_number')
  188. def set_submitted_basket(self, basket):
  189. self._set('submission', 'basket_id', basket.id)
  190. def get_submitted_basket_id(self):
  191. return self._get('submission', 'basket_id')