| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- from django.db.models import get_model
-
- from oscar.core.loading import get_class
-
- Repository = get_class('shipping.repository', 'Repository')
- OrderTotalCalculator = get_class(
- 'checkout.calculators', 'OrderTotalCalculator')
- CheckoutSessionData = get_class(
- 'checkout.utils', 'CheckoutSessionData')
- ShippingAddress = get_model('order', 'ShippingAddress')
- UserAddress = get_model('address', 'UserAddress')
-
-
- class CheckoutSessionMixin(object):
- """
- Mixin to provide common functionality shared between checkout views.
- """
-
- def dispatch(self, request, *args, **kwargs):
- # Assign the checkout session manager so it's available in all checkout
- # views.
- self.checkout_session = CheckoutSessionData(request)
- return super(CheckoutSessionMixin, self).dispatch(
- request, *args, **kwargs)
-
- def get_context_data(self, **kwargs):
- """
- Assign common template variables to the context.
- """
- ctx = super(CheckoutSessionMixin, self).get_context_data(**kwargs)
-
- basket = self.request.basket
- shipping_address = self.get_shipping_address(basket)
- shipping_method = self.get_shipping_method(
- basket, shipping_address)
-
- ctx['shipping_address'] = shipping_address
- ctx['shipping_method'] = shipping_method
- if basket and shipping_method:
- ctx['order_total'] = self.get_order_totals(basket, shipping_method)
-
- return ctx
-
- def get_shipping_address(self, basket):
- """
- Return the (unsaved) shipping address for this checkout session.
-
- If the shipping address was entered manually, then we instantiate a
- ``ShippingAddress`` model with the appropriate form data (which is
- saved in the session).
-
- If the shipping address was selected from the user's address book,
- then we convert the ``UserAddress`` to a ``ShippingAddress``.
-
- The ``ShippingAddress`` instance is not saved as sometimes you need a
- shipping address instance before the order is placed. For example, if
- you are submitting fraud information as part of a payment request.
-
- The ``OrderPlacementMixin.create_shipping_address`` method is
- responsible for saving a shipping address when an order is placed.
- """
- if not basket.is_shipping_required():
- return None
-
- addr_data = self.checkout_session.new_shipping_address_fields()
- if addr_data:
- # Load address data into a blank shipping address model
- return ShippingAddress(**addr_data)
- addr_id = self.checkout_session.user_address_id()
- if addr_id:
- try:
- address = UserAddress._default_manager.get(pk=addr_id)
- except UserAddress.DoesNotExist:
- # An address was selected but now it has disappeared. This can
- # happen if the customer flushes their address book midway
- # through checkout. No idea why they would do this but it can
- # happen. Checkouts are highly vulnerable to race conditions
- # like this.
- return None
- else:
- # Copy user address data into a blank shipping address instance
- shipping_addr = ShippingAddress()
- address.populate_alternative_model(shipping_addr)
- return shipping_addr
-
- def get_shipping_method(self, basket, shipping_address=None, **kwargs):
- """
- Return the selected shipping method instance from this checkout session
-
- The shipping address is passed as we need to check that the method
- stored in the session is still valid for the shippinga address.
- """
- code = self.checkout_session.shipping_method_code(basket)
- methods = Repository().get_shipping_methods(
- user=self.request.user, basket=basket,
- shipping_addr=shipping_address, request=self.request)
- for method in methods:
- if method.code == code:
- return method
-
- def get_order_totals(self, basket, shipping_method, **kwargs):
- """
- Returns the total for the order with and without tax (as a tuple)
- """
- return OrderTotalCalculator(self.request).calculate(
- basket, shipping_method, **kwargs)
|