Source code for oscar.apps.shipping.repository

from decimal import Decimal as D

from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import gettext_lazy as _

from oscar.core.loading import get_classes

(Free, NoShippingRequired,
 TaxExclusiveOfferDiscount, TaxInclusiveOfferDiscount) \
    = get_classes('shipping.methods', ['Free', 'NoShippingRequired',
                                       'TaxExclusiveOfferDiscount', 'TaxInclusiveOfferDiscount'])


[docs]class Repository(object): """ Repository class responsible for returning ShippingMethod objects for a given user, basket etc """ # We default to just free shipping. Customise this class and override this # property to add your own shipping methods. This should be a list of # instantiated shipping methods. methods = (Free(),) # API
[docs] def get_shipping_methods(self, basket, shipping_addr=None, **kwargs): """ Return a list of all applicable shipping method instances for a given basket, address etc. """ if not basket.is_shipping_required(): # Special case! Baskets that don't require shipping get a special # shipping method. return [NoShippingRequired()] methods = self.get_available_shipping_methods( basket=basket, shipping_addr=shipping_addr, **kwargs) if basket.has_shipping_discounts: methods = self.apply_shipping_offers(basket, methods) return methods
[docs] def get_default_shipping_method(self, basket, shipping_addr=None, **kwargs): """ Return a 'default' shipping method to show on the basket page to give the customer an indication of what their order will cost. """ shipping_methods = self.get_shipping_methods( basket, shipping_addr=shipping_addr, **kwargs) if len(shipping_methods) == 0: raise ImproperlyConfigured( _("You need to define some shipping methods")) # Assume first returned method is default return shipping_methods[0]
# Helpers
[docs] def get_available_shipping_methods( self, basket, shipping_addr=None, **kwargs): """ Return a list of all applicable shipping method instances for a given basket, address etc. This method is intended to be overridden. """ return self.methods
[docs] def apply_shipping_offers(self, basket, methods): """ Apply shipping offers to the passed set of methods """ # We default to only applying the first shipping discount. offer = basket.shipping_discounts[0]['offer'] return [self.apply_shipping_offer(basket, method, offer) for method in methods]
[docs] def apply_shipping_offer(self, basket, method, offer): """ Wrap a shipping method with an offer discount wrapper (as long as the shipping charge is non-zero). """ # If the basket has qualified for shipping discount, wrap the shipping # method with a decorating class that applies the offer discount to the # shipping charge. charge = method.calculate(basket) if charge.excl_tax == D('0.00'): # No need to wrap zero shipping charges return method if charge.is_tax_known: return TaxInclusiveOfferDiscount(method, offer) else: # When returning a tax exclusive discount, it is assumed # that this will be used to calculate taxes which will then # be assigned directly to the method instance. return TaxExclusiveOfferDiscount(method, offer)