| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseBadRequest
- from django.contrib import messages
- from django.core.urlresolvers import reverse
-
- from oscar.core.loading import import_module
- basket_factory = import_module('basket.factory', ['BasketFactory'])
- checkout_calculators = import_module('checkout.calculators', ['OrderTotalCalculator'])
- order_models = import_module('order.models', ['Order', 'ShippingAddress'])
- checkout_utils = import_module('checkout.utils', ['ProgressChecker', 'CheckoutSessionData'])
- address_models = import_module('address.models', ['UserAddress'])
-
- def prev_steps_must_be_complete(view_fn):
- u"""
- Decorator fn for checking that previous steps of the checkout
- are complete.
-
- The completed steps (identified by URL-names) are stored in the session.
- If this fails, then we redirect to the next uncompleted step.
- """
- def _view_wrapper(self, request, *args, **kwargs):
- checker = checkout_utils.ProgressChecker()
- if not checker.are_previous_steps_complete(request):
- messages.error(request, "You must complete this step of the checkout first")
- url_name = checker.get_next_step(request)
- return HttpResponseRedirect(reverse(url_name))
- return view_fn(self, request, *args, **kwargs)
- return _view_wrapper
-
- def basket_required(view_fn):
- def _view_wrapper(self, request, *args, **kwargs):
- basket = basket_factory.BasketFactory().get_open_basket(request)
- if not basket:
- messages.error(request, "You must add some products to your basket before checking out")
- return HttpResponseRedirect(reverse('oscar-basket'))
- return view_fn(self, request, *args, **kwargs)
- return _view_wrapper
-
- def mark_step_as_complete(request):
- u"""
- Convenience function for marking a checkout page
- as complete.
- """
- checkout_utils.ProgressChecker().step_complete(request)
-
- def mark_step_as_complete(request):
- u"""
- Convenience function for marking a checkout page
- as complete.
- """
- checkout_utils.ProgressChecker().step_complete(request)
-
- def get_next_step(request):
- return checkout_utils.ProgressChecker().get_next_step(request)
-
-
- class CheckoutView(object):
- u"""
- Top-level superclass for all checkout view classes
- """
-
- def __init__(self, template_file=None):
- if template_file:
- self.template_file = template_file
-
- @basket_required
- @prev_steps_must_be_complete
- def __call__(self, request):
- u"""
- We forward request handling to the appropriate method
- based on the HTTP method.
- """
-
- # Set up the instance variables that are needed to place an order
- self.request = request
- self.co_data = checkout_utils.CheckoutSessionData(request)
- self.basket = basket_factory.BasketFactory().get_open_basket(self.request)
-
- # Set up template context that is available to every view
- method = self.co_data.shipping_method()
- if method:
- method.set_basket(self.basket)
-
- self.context = {'basket': self.basket,
- 'order_total': self.get_order_total(method),
- 'shipping_addr': self.get_shipping_address()}
- self.set_shipping_context(method)
- self.set_payment_context()
-
- if request.method == 'POST':
- response = self.handle_POST()
- elif request.method == 'GET':
- response = self.handle_GET()
- else:
- response = HttpResponseBadRequest()
- return response
-
- def set_shipping_context(self, method):
- if method:
- self.context['method'] = method
- self.context['shipping_total_excl_tax'] = method.basket_charge_excl_tax()
- self.context['shipping_total_incl_tax'] = method.basket_charge_incl_tax()
-
- def set_payment_context(self):
- method = self.co_data.payment_method()
- if method:
- self.context['payment_method'] = method
-
- def handle_GET(self):
- u"""
- Default behaviour is to set step as complete and redirect
- to the next step.
- """
- return self.get_success_response()
-
- def get_order_total(self, shipping_method):
- calc = checkout_calculators.OrderTotalCalculator(self.request)
- return calc.order_total_incl_tax(self.basket, shipping_method)
-
- def get_shipping_address(self):
- # Load address data into a blank address model
- addr_data = self.co_data.new_address_fields()
- if addr_data:
- return order_models.ShippingAddress(**addr_data)
- addr_id = self.co_data.user_address_id()
- if addr_id:
- try:
- return address_models.UserAddress._default_manager.get(pk=addr_id)
- except address_models.UserAddress.DoesNotExist:
- # This can happen if you reset all your tables and you still have
- # session data that refers to addresses that no longer exist
- pass
- return None
-
- def get_success_response(self):
- u"""
- Returns the appropriate redirect response if a checkout
- step has been successfully passed.
- """
- mark_step_as_complete(self.request)
- return HttpResponseRedirect(reverse(get_next_step(self.request)))
-
- def handle_POST(self):
- pass
|