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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. from django.core.urlresolvers import resolve
  2. from oscar.services import import_module
  3. shipping_methods = import_module('shipping.repository', ['Repository'])
  4. class ProgressChecker(object):
  5. u"""
  6. Class for testing whether the appropriate steps of the checkout
  7. have been completed.
  8. """
  9. # List of URL names that have to be completed (in this order)
  10. urls_for_steps = ['oscar-checkout-shipping-address',
  11. 'oscar-checkout-shipping-method',
  12. 'oscar-checkout-payment-method',
  13. 'oscar-checkout-preview',
  14. 'oscar-checkout-payment-details',
  15. 'oscar-checkout-submit',]
  16. def are_previous_steps_complete(self, request):
  17. u"""
  18. Checks whether the previous checkout steps have been completed.
  19. This uses the URL-name and the class-level list of required
  20. steps.
  21. """
  22. # Extract the URL name from the path
  23. complete_steps = self._get_completed_steps(request)
  24. try:
  25. url_name = self._get_url_name(request)
  26. current_step_index = self.urls_for_steps.index(url_name)
  27. last_completed_step_index = len(complete_steps) - 1
  28. return current_step_index <= last_completed_step_index + 1
  29. except ValueError:
  30. # Can't find current step index - must be manipulation
  31. return False
  32. except IndexError:
  33. # No complete steps - only allowed to be on first page
  34. return current_step_index == 0
  35. def step_complete(self, request):
  36. u"""Record a checkout step as complete."""
  37. url_name = self._get_url_name(request)
  38. complete_steps = self._get_completed_steps(request)
  39. if not url_name in complete_steps:
  40. # Only add name if this is the first time the step
  41. # has been completed.
  42. complete_steps.append(url_name)
  43. request.session['checkout_complete_steps'] = complete_steps
  44. def get_next_step(self, request):
  45. u"""Returns the next incomplete step of the checkout."""
  46. completed_steps = self._get_completed_steps(request)
  47. if len(completed_steps):
  48. return self.urls_for_steps[len(completed_steps)]
  49. else:
  50. return self.urls_for_steps[0]
  51. def all_steps_complete(self, request):
  52. u"""
  53. Order has been submitted - clear the completed steps from
  54. the session.
  55. """
  56. request.session['checkout_complete_steps'] = []
  57. def _get_url_name(self, request):
  58. return resolve(request.path).url_name
  59. def _get_completed_steps(self, request):
  60. return request.session.get('checkout_complete_steps', [])
  61. class CheckoutSessionData(object):
  62. u"""Class responsible for marshalling all the checkout session data."""
  63. SESSION_KEY = 'checkout_data'
  64. def __init__(self, request):
  65. self.request = request
  66. if self.SESSION_KEY not in self.request.session:
  67. self.request.session[self.SESSION_KEY] = {}
  68. def _check_namespace(self, namespace):
  69. if namespace not in self.request.session[self.SESSION_KEY]:
  70. self.request.session[self.SESSION_KEY][namespace] = {}
  71. def _get(self, namespace, key):
  72. u"""Return session value or None"""
  73. self._check_namespace(namespace)
  74. if key in self.request.session[self.SESSION_KEY][namespace]:
  75. return self.request.session[self.SESSION_KEY][namespace][key]
  76. return None
  77. def _set(self, namespace, key, value):
  78. u"""Set session value"""
  79. self._check_namespace(namespace)
  80. self.request.session[self.SESSION_KEY][namespace][key] = value
  81. self.request.session.modified = True
  82. def _unset(self, namespace, key):
  83. u"""Unset session value"""
  84. self._check_namespace(namespace)
  85. if key in self.request.session[self.SESSION_KEY][namespace]:
  86. del self.request.session[self.SESSION_KEY][namespace][key]
  87. self.request.session.modified = True
  88. def flush(self):
  89. u"""Delete session key"""
  90. self.request.session[self.SESSION_KEY] = {}
  91. # Shipping methods
  92. def ship_to_user_address(self, address):
  93. u"""Set existing shipping address id to session and unset address fields from session"""
  94. self._set('shipping', 'user_address_id', address.id)
  95. self._unset('shipping', 'new_address_fields')
  96. def ship_to_new_address(self, address_fields):
  97. u"""Set new shipping address details to session and unset shipping address id"""
  98. self._set('shipping', 'new_address_fields', address_fields)
  99. self._unset('shipping', 'user_address_id')
  100. def new_address_fields(self):
  101. u"""Get shipping address fields from session"""
  102. return self._get('shipping', 'new_address_fields')
  103. def user_address_id(self):
  104. u"""Get user address id from session"""
  105. return self._get('shipping', 'user_address_id')
  106. def use_shipping_method(self, code):
  107. u"""Set shipping method code to session"""
  108. self._set('shipping', 'method_code', code)
  109. def shipping_method(self):
  110. u"""
  111. Returns the shipping method model based on the
  112. data stored in the session.
  113. """
  114. code = self._get('shipping', 'method_code')
  115. if not code:
  116. return None
  117. repo = shipping_methods.Repository()
  118. return repo.find_by_code(code)
  119. # Payment methods
  120. def pay_by(self, method):
  121. self._set('payment', 'method', method)
  122. def payment_method(self):
  123. return self._get('payment', 'method')