def test_multi_site(self):
        basket = factories.create_basket(empty=True)
        site1 = factories.SiteFactory()
        site2 = factories.SiteFactory()
        request = HttpRequest()
        request.META['SERVER_PORT'] = 80
        request.META['SERVER_NAME'] = site1.domain
        user = factories.UserFactory()
        add_product(basket, D('12.00'))
        shipping_method = Free()
        shipping_charge = shipping_method.calculate(basket)
        order_total = OrderTotalCalculator().calculate(basket, shipping_charge)

        billing_address = factories.BillingAddressFactory()
        shipping_address = factories.ShippingAddressFactory()
        order_submission_data = {'user': user,
                                 'order_number': '12345',
                                 'basket': basket,
                                 'shipping_method': shipping_method,
                                 'shipping_charge': shipping_charge,
                                 'order_total': order_total,
                                 'billing_address': billing_address,
                                 'shipping_address': shipping_address,
                                 'request': request}
        OrderPlacementMixin().place_order(**order_submission_data)
        order1 = Order.objects.get(number='12345')
        self.assertEqual(order1.site, site1)

        add_product(basket, D('12.00'))
        request.META['SERVER_NAME'] = site2.domain
        order_submission_data['order_number'] = '12346'
        order_submission_data['request'] = request
        OrderPlacementMixin().place_order(**order_submission_data)
        order2 = Order.objects.get(number='12346')
        self.assertEqual(order2.site, site2)
    def test_multiple_payment_events(self):
        basket = factories.create_basket(empty=True)
        user = factories.UserFactory()
        add_product(basket, D('100.00'))
        order_placement = OrderPlacementMixin()
        order_placement.add_payment_event('Gift Card Payment', D('10'))
        order_placement.add_payment_event('Credit Card Payment', D('90'))
        shipping_method = Free()
        shipping_charge = shipping_method.calculate(basket)
        order_total = OrderTotalCalculator().calculate(basket, shipping_charge)

        billing_address = factories.BillingAddressFactory()
        shipping_address = factories.ShippingAddressFactory()
        order_submission_data = {'user': user,
                                 'order_number': '12345',
                                 'basket': basket,
                                 'shipping_method': shipping_method,
                                 'shipping_charge': shipping_charge,
                                 'order_total': order_total,
                                 'billing_address': billing_address,
                                 'shipping_address': shipping_address}
        order_placement.place_order(**order_submission_data)
        order1 = Order.objects.get(number='12345')
        self.assertEqual(order1.payment_events.count(), 2)
        event1 = order1.payment_events.all()[0]
        event2 = order1.payment_events.all()[1]
        self.assertEqual(event1.event_type.name, 'Credit Card Payment')
        self.assertEqual(event1.amount, D('90'))
        self.assertEqual(event1.lines.count(), 1)
        self.assertEqual(event2.event_type.name, 'Gift Card Payment')
        self.assertEqual(event2.amount, D('10'))
        self.assertEqual(event2.lines.count(), 1)
Exemple #3
0
    def test_multiple_payment_events(self):
        basket = factories.create_basket(empty=True)
        user = factories.UserFactory()
        add_product(basket, D('100.00'))
        order_placement = OrderPlacementMixin()
        order_placement.add_payment_event('Gift Card Payment', D('10'))
        order_placement.add_payment_event('Credit Card Payment', D('90'))
        shipping_method = Free()
        shipping_charge = shipping_method.calculate(basket)
        order_total = OrderTotalCalculator().calculate(basket, shipping_charge)

        billing_address = factories.BillingAddressFactory()
        shipping_address = factories.ShippingAddressFactory()
        order_submission_data = {
            'user': user,
            'order_number': '12345',
            'basket': basket,
            'shipping_method': shipping_method,
            'shipping_charge': shipping_charge,
            'order_total': order_total,
            'billing_address': billing_address,
            'shipping_address': shipping_address
        }
        order_placement.place_order(**order_submission_data)
        order1 = Order.objects.get(number='12345')
        self.assertEqual(order1.payment_events.count(), 2)
        event1 = order1.payment_events.all()[0]
        event2 = order1.payment_events.all()[1]
        self.assertEqual(event1.event_type.name, 'Credit Card Payment')
        self.assertEqual(event1.amount, D('90'))
        self.assertEqual(event1.lines.count(), 1)
        self.assertEqual(event2.event_type.name, 'Gift Card Payment')
        self.assertEqual(event2.amount, D('10'))
        self.assertEqual(event2.lines.count(), 1)
    def test_multi_site(self):
        basket = factories.create_basket(empty=True)
        site1 = factories.SiteFactory()
        site2 = factories.SiteFactory()
        request = HttpRequest()
        request.META['SERVER_PORT'] = 80
        request.META['SERVER_NAME'] = site1.domain
        user = factories.UserFactory()
        add_product(basket, D('12.00'))
        shipping_method = Free()
        shipping_charge = shipping_method.calculate(basket)
        order_total = OrderTotalCalculator().calculate(basket, shipping_charge)

        billing_address = factories.BillingAddressFactory()
        shipping_address = factories.ShippingAddressFactory()
        order_submission_data = {'user': user,
                                 'order_number': '12345',
                                 'basket': basket,
                                 'shipping_method': shipping_method,
                                 'shipping_charge': shipping_charge,
                                 'order_total': order_total,
                                 'billing_address': billing_address,
                                 'shipping_address': shipping_address,
                                 'request': request}
        OrderPlacementMixin().place_order(**order_submission_data)
        order1 = Order.objects.get(number='12345')
        self.assertEqual(order1.site, site1)

        add_product(basket, D('12.00'))
        request.META['SERVER_NAME'] = site2.domain
        order_submission_data['order_number'] = '12346'
        order_submission_data['request'] = request
        OrderPlacementMixin().place_order(**order_submission_data)
        order2 = Order.objects.get(number='12346')
        self.assertEqual(order2.site, site2)
Exemple #5
0
    def place_order(self,
                    basket,
                    total_incl_tax=None,
                    total_excl_tax=None,
                    user=None,
                    shipping_method=None,
                    shipping_address=None,
                    billing_address=None,
                    order_number=None,
                    status=None,
                    **kwargs):
        """
        Placing an order involves creating all the relevant models based on the
        basket and session data.
        """
        # Only a basket instance is required to place an order - everything else can be set
        # to defaults
        if basket.is_empty:
            raise ValueError(_("Empty baskets cannot be submitted"))
        if not shipping_method:
            shipping_method = Free()
        if total_incl_tax is None or total_excl_tax is None:
            total_incl_tax = basket.total_incl_tax + shipping_method.basket_charge_incl_tax(
            )
            total_excl_tax = basket.total_excl_tax + shipping_method.basket_charge_excl_tax(
            )
        if not order_number:
            generator = OrderNumberGenerator()
            order_number = generator.order_number(basket)
        if not status and hasattr(settings, 'OSCAR_INITIAL_ORDER_STATUS'):
            status = getattr(settings, 'OSCAR_INITIAL_ORDER_STATUS')
        try:
            Order._default_manager.get(number=order_number)
        except Order.DoesNotExist:
            pass
        else:
            raise ValueError(
                _("There is already an order with number %s") % order_number)

        # Ok - everything seems to be in order, let's place the order
        order = self.create_order_model(user, basket, shipping_address,
                                        shipping_method, billing_address,
                                        total_incl_tax, total_excl_tax,
                                        order_number, status, **kwargs)
        for line in basket.all_lines():
            self.create_line_models(order, line)
            self.update_stock_records(line)

        for discount in basket.get_discounts():
            self.create_discount_model(order, discount)
            self.record_discount(discount)

        for voucher in basket.vouchers.all():
            self.record_voucher_usage(order, voucher, user)

        # Send signal for analytics to pick up
        order_placed.send(sender=self, order=order, user=user)

        return order
Exemple #6
0
    def place_order(self, basket, total_incl_tax=None, total_excl_tax=None,
                    user=None, shipping_method=None, shipping_address=None,
                    billing_address=None, order_number=None, status=None, **kwargs):
        """
        Placing an order involves creating all the relevant models based on the
        basket and session data.
        """
        # Only a basket instance is required to place an order - everything else can be set
        # to defaults
        if basket.is_empty:
            raise ValueError(_("Empty baskets cannot be submitted"))
        if not shipping_method:
            shipping_method = Free()
        if total_incl_tax is None or total_excl_tax is None:
            total_incl_tax = basket.total_incl_tax + shipping_method.basket_charge_incl_tax()
            total_excl_tax = basket.total_excl_tax + shipping_method.basket_charge_excl_tax()
        if not order_number:
            generator = OrderNumberGenerator()
            order_number = generator.order_number(basket)
        if not status and hasattr(settings, 'OSCAR_INITIAL_ORDER_STATUS'):
            status = getattr(settings, 'OSCAR_INITIAL_ORDER_STATUS')
        try:
            Order._default_manager.get(number=order_number)
        except Order.DoesNotExist:
            pass
        else:
            raise ValueError(_("There is already an order with number %s") % order_number)

        # Ok - everything seems to be in order, let's place the order
        order = self.create_order_model(
            user, basket, shipping_address, shipping_method, billing_address,
            total_incl_tax, total_excl_tax, order_number, status, **kwargs)
        for line in basket.all_lines():
            self.create_line_models(order, line)
            self.update_stock_records(line)

        for application in basket.offer_applications:
            # Trigger any deferred benefits from offers and capture the
            # resulting message
            application['message'] = application['offer'].apply_deferred_benefit(basket)
            # Record offer application results
            if application['result'].affects_shipping:
                # Skip zero shipping discounts
                if shipping_method.discount <= D('0.00'):
                    continue
                # If a shipping offer, we need to grab the actual discount off
                # the shipping method instance, which should be wrapped in an
                # OfferDiscount instance.
                application['discount'] = shipping_method.discount
            self.create_discount_model(order, application)
            self.record_discount(application)

        for voucher in basket.vouchers.all():
            self.record_voucher_usage(order, voucher, user)

        # Send signal for analytics to pick up
        order_placed.send(sender=self, order=order, user=user)

        return order
Exemple #7
0
    def place_order(self, basket, total_incl_tax=None, total_excl_tax=None,
                    user=None, shipping_method=None, shipping_address=None,
                    billing_address=None, order_number=None, status=None, **kwargs):
        """
        Placing an order involves creating all the relevant models based on the
        basket and session data.
        """
        # Only a basket instance is required to place an order - everything else can be set
        # to defaults
        if basket.is_empty:
            raise ValueError(_("Empty baskets cannot be submitted"))
        if not shipping_method:
            shipping_method = Free()
        if total_incl_tax is None or total_excl_tax is None:
            total_incl_tax = basket.total_incl_tax + shipping_method.basket_charge_incl_tax()
            total_excl_tax = basket.total_excl_tax + shipping_method.basket_charge_excl_tax()
        if not order_number:
            generator = OrderNumberGenerator()
            order_number = generator.order_number(basket)
        if not status and hasattr(settings, 'OSCAR_INITIAL_ORDER_STATUS'):
            status = getattr(settings, 'OSCAR_INITIAL_ORDER_STATUS')
        try:
            Order._default_manager.get(number=order_number)
        except Order.DoesNotExist:
            pass
        else:
            raise ValueError(_("There is already an order with number %s") % order_number)

        # Ok - everything seems to be in order, let's place the order
        order = self.create_order_model(user, basket, shipping_address,
                                        shipping_method, billing_address, total_incl_tax,
                                        total_excl_tax, order_number, status, **kwargs)
        for line in basket.all_lines():
            self.create_line_models(order, line)
            self.update_stock_records(line)

        # Record discounts (including any on the shipping method)
        for discount in basket.get_discounts():
            self.create_discount_model(order, discount)
            self.record_discount(discount)
        if shipping_method.is_discounted:
            discount = shipping_method.get_discount()
            self.create_discount_model(order, discount,
                                       is_shipping_discount=True)
            self.record_discount(discount)

        for voucher in basket.vouchers.all():
            self.record_voucher_usage(order, voucher, user)

        # Send signal for analytics to pick up
        order_placed.send(sender=self, order=order, user=user)

        return order
Exemple #8
0
class Repository(CoreRepository):
    """
    This class is included so that there is a choice of shipping methods.
    Oscar's default behaviour is to only have one which means you can't test
    the shipping features of PayFast.
    """
    methods = [Free(), FixedPrice(D('10.00'), D('10.00'))]
Exemple #9
0
def create_order(number=None, basket=None, user=None, shipping_address=None, shipping_method=None,
        billing_address=None, total_incl_tax=None, total_excl_tax=None, **kwargs):
    """
    Helper method for creating an order for testing
    """
    if not basket:
        basket = Basket.objects.create()
        basket.add_product(create_product(price=D('10.00')))
    if not basket.id:
        basket.save()
    if shipping_method is None:
        shipping_method = Free()
    if total_incl_tax is None or total_excl_tax is None:
        calc = OrderTotalCalculator()
        total_incl_tax = calc.order_total_incl_tax(basket, shipping_method)
        total_excl_tax = calc.order_total_excl_tax(basket, shipping_method)
    order = OrderCreator().place_order(
            order_number=number,
            user=user,
            basket=basket,
            shipping_address=shipping_address,
            shipping_method=shipping_method,
            billing_address=billing_address,
            total_incl_tax=total_incl_tax,
            total_excl_tax=total_excl_tax,
            **kwargs
            )
    return order
 def setUp(self):
     self.non_discount_methods = [
         Free(),
         FixedPrice(D('10.00'), D('10.00')),
         OrderAndItemCharges(price_per_order=D('5.00'),
                             price_per_item=D('1.00'))
     ]
Exemple #11
0
    def get_shipping_method(self, basket=None):
        method = self.checkout_session.shipping_method(basket)

        # We default to using free shipping
        if not method:
            method = Free()

        return method
Exemple #12
0
 def test_saves_shipping_code(self):
     add_product(self.basket, D('12.00'))
     free_method = Free()
     order = place_order(self.creator,
                         basket=self.basket,
                         order_number='1234',
                         shipping_method=free_method)
     self.assertEqual(order.shipping_code, free_method.code)
Exemple #13
0
    def place_order(self, basket, total,  # noqa (too complex (12))
                    user=None, shipping_method=None, shipping_address=None,
                    billing_address=None, order_number=None, status=None,
                    **kwargs):
        """
        Placing an order involves creating all the relevant models based on the
        basket and session data.
        """
        if basket.is_empty:
            raise ValueError(_("Empty baskets cannot be submitted"))
        if not shipping_method:
            shipping_method = Free()
        if not order_number:
            generator = OrderNumberGenerator()
            order_number = generator.order_number(basket)
        if not status and hasattr(settings, 'OSCAR_INITIAL_ORDER_STATUS'):
            status = getattr(settings, 'OSCAR_INITIAL_ORDER_STATUS')
        try:
            Order._default_manager.get(number=order_number)
        except Order.DoesNotExist:
            pass
        else:
            raise ValueError(_("There is already an order with number %s")
                             % order_number)

        # Ok - everything seems to be in order, let's place the order
        order = self.create_order_model(
            user, basket, shipping_address, shipping_method, billing_address,
            total, order_number, status, **kwargs)
        for line in basket.all_lines():
            self.create_line_models(order, line)
            self.update_stock_records(line)

        for application in basket.offer_applications:
            # Trigger any deferred benefits from offers and capture the
            # resulting message
            application['message'] \
                = application['offer'].apply_deferred_benefit(basket)
            # Record offer application results
            if application['result'].affects_shipping:
                # Skip zero shipping discounts
                if shipping_method.discount <= D('0.00'):
                    continue
                # If a shipping offer, we need to grab the actual discount off
                # the shipping method instance, which should be wrapped in an
                # OfferDiscount instance.
                application['discount'] = shipping_method.discount
            self.create_discount_model(order, application)
            self.record_discount(application)

        for voucher in basket.vouchers.all():
            self.record_voucher_usage(order, voucher, user)

        # Send signal for analytics to pick up
        order_placed.send(sender=self, order=order, user=user)

        return order
def place_order(creator, **kwargs):
    """
    Helper function to place an order without the boilerplate
    """
    if 'shipping_method' not in kwargs:
        kwargs['shipping_method'] = Free()
    if 'total' not in kwargs:
        kwargs['total'] = calculators.OrderTotalCalculator().calculate(
            basket=kwargs['basket'], shipping_method=kwargs['shipping_method'])
    return creator.place_order(**kwargs)
Exemple #15
0
    def get_shipping_method(self, basket, shipping_address=None, **kwargs):
        """
        Return the shipping method used
        """
        if not basket.is_shipping_required():
            return NoShippingRequired()

        method = Free()

        return method
Exemple #16
0
 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.
     """
     methods = [Free(), FixedPrice(D('10.00'), D('10.00'))]
     return methods
Exemple #17
0
 def get_shipping_method(self, basket=None):
     method = self.checkout_session.shipping_method()
     if method:
         if not basket:
             basket = self.request.basket
         method.set_basket(basket)
     else:
         # We default to using free shipping
         method = Free()
     return method
Exemple #18
0
class TestPlacingOrderForDigitalGoods(TestCase):
    def setUp(self):
        self.creator = OrderCreator()
        self.basket = factories.create_basket(empty=True)
        self.shipping_method = Free()
        self.shipping_method.set_basket(self.basket)

    def test_does_not_allocate_stock(self):
        ProductClass.objects.create(name="Digital", track_stock=False)
        product = factories.create_product(product_class="Digital")
        record = factories.create_stockrecord(product, num_in_stock=None)
        self.assertTrue(record.num_allocated is None)

        add_product(self.basket, D('12.00'), product=product)
        place_order(self.creator, basket=self.basket, order_number='1234')

        product = Product.objects.get(id=product.id)
        stockrecord = product.stockrecords.all()[0]
        self.assertTrue(stockrecord.num_in_stock is None)
        self.assertTrue(stockrecord.num_allocated is None)
 def perform_action(self):
     basket = Mock()
     basket.id = 1
     basket.total_incl_tax = D('200')
     basket.all_lines = Mock(return_value=[])
     basket.offer_discounts = []
     basket.voucher_discounts = []
     basket.shipping_discounts = []
     methods = [Free()]
     url_str = get_paypal_url(basket, methods)
     self.url = URL.from_string(url_str)
    def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
        """
        Return a list of all applicable shipping method objects
        for a given basket.

        We default to returning the Method models that have been defined but
        this behaviour can easily be overridden by subclassing this class
        and overriding this method.
        """
        methods = [Free()]
        return self.prime_methods(basket, methods)
class TestPlacingOrderForDigitalGoods(TestCase):

    def setUp(self):
        self.creator = OrderCreator()
        self.basket = factories.create_basket(empty=True)
        self.shipping_method = Free()
        self.shipping_method.set_basket(self.basket)

    def test_does_not_allocate_stock(self):
        ProductClass.objects.create(
            name="Digital", track_stock=False)
        product = factories.create_product(product_class="Digital")
        record = factories.create_stockrecord(product, num_in_stock=None)
        self.assertTrue(record.num_allocated is None)

        add_product(self.basket, D('12.00'), product=product)
        place_order(self.creator, basket=self.basket, order_number='1234')

        product = Product.objects.get(id=product.id)
        stockrecord = product.stockrecords.all()[0]
        self.assertTrue(stockrecord.num_in_stock is None)
        self.assertTrue(stockrecord.num_allocated is None)
Exemple #22
0
class FreeTest(TestCase):
    def setUp(self):
        self.method = Free()

    def test_shipping_is_free_for_empty_basket(self):
        basket = Basket()
        self.method.set_basket(basket)
        self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
        self.assertEquals(D('0.00'), self.method.basket_charge_excl_tax())

    def test_shipping_is_free_for_nonempty_basket(self):
        basket = Basket()
        basket.add_product(create_product())
        self.method.set_basket(basket)
        self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
        self.assertEquals(D('0.00'), self.method.basket_charge_excl_tax())
class FreeTest(TestCase):
    def setUp(self):
        self.method = Free()

    def test_shipping_is_free_for_empty_basket(self):
        basket = Basket()
        self.method.set_basket(basket)
        self.assertEquals(D("0.00"), self.method.basket_charge_incl_tax())
        self.assertEquals(D("0.00"), self.method.basket_charge_excl_tax())

    def test_shipping_is_free_for_nonempty_basket(self):
        basket = Basket()
        basket.add_product(create_product())
        self.method.set_basket(basket)
        self.assertEquals(D("0.00"), self.method.basket_charge_incl_tax())
        self.assertEquals(D("0.00"), self.method.basket_charge_excl_tax())
Exemple #24
0
class Repository(CoreRepository):
    """
    This class is included so that there is a choice of shipping methods.
    Oscar's default behaviour is to only have one which means you can't test
    the shipping features of PayPal.
    """
    methods = [Free(), FixedPrice(D('10.00'))]

    def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
        return self.prime_methods(basket, self.methods)

    def find_by_code(self, code, basket):
        for method in self.methods:
            if code == method.code:
                return self.prime_method(basket, method)
Exemple #25
0
    def test_zero_shipping_discount_is_not_created(self):
        add_product(self.basket, D('12.00'))
        offer = self.apply_20percent_shipping_offer()

        shipping = Free()
        shipping = Repository().apply_shipping_offer(self.basket, shipping,
                                                     offer)

        place_order(self.creator,
                    basket=self.basket,
                    order_number='1234',
                    shipping_method=shipping)
        order = Order.objects.get(number='1234')

        # No shipping discount
        self.assertEqual(0, len(order.shipping_discounts))
        self.assertEqual(D('0.00'), order.shipping_incl_tax)
        self.assertEqual(D('12.00'), order.total_incl_tax)
Exemple #26
0
from oscar.apps.shipping.methods import Free, NoShippingRequired
from oscar.apps.shipping.repository import Repository as CoreRepository

# Dummy shipping methods
free1 = Free()
free1.code = 'free1'
free1.description = 'Ship by van'

free2 = Free()
free2.code = 'free2'
free2.description = 'Ship by boat'


class Repository(CoreRepository):

    methods = {free1.code: free1, free2.code: free2}

    def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
        methods = self.methods.values()
        return self.add_basket_to_methods(basket, methods)

    def find_by_code(self, code):
        if code == NoShippingRequired.code:
            return NoShippingRequired()
        return self.methods.get(code, None)
 def setUp(self):
     self.creator = OrderCreator()
     self.basket = factories.create_basket(empty=True)
     self.shipping_method = Free()
     self.shipping_method.set_basket(self.basket)
Exemple #28
0
 def setUp(self):
     self.method = Free()
Exemple #29
0
class Repository(CoreRepository):
    methods = [Free(), FixedPrice(D('10.00'), D('10.00'))]
class StubRepository(Repository):
    """ Custom shipping methods """
    methods = (FixedPrice(D('5.00'), D('5.00')), Free())
 def setUp(self):
     self.creator = OrderCreator()
     self.basket = factories.create_basket(empty=True)
     self.shipping_method = Free()
     self.shipping_method.set_basket(self.basket)
 def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
     methods = [Free(), FixedPrice(D('10.00')), FixedPrice(D('20.00'))]
     return self.prime_methods(basket, methods)
Exemple #33
0
from oscar.apps.shipping.methods import Free
from oscar.apps.shipping.repository import Repository as CoreRepository

# Dummy shipping methods
free1 = Free()
free1.code = 'free1'
free1.description = 'Ship by van'

free2 = Free()
free2.code = 'free2'
free2.description = 'Ship by boat'

class Repository(CoreRepository):

    methods = {
        free1.code: free1,
        free2.code: free2
    }

    def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
        methods = self.methods.values()
        return self.add_basket_to_methods(basket, methods)

    def find_by_code(self, code):
        return self.methods.get(code, None)
 def setUp(self):
     self.method = Free()
 def get_methods(self):
     return [Free(), FixedPrice(D('10.00'), D('10.00'))]
 def setUp(self):
     self.basket = create_mock_basket()
     self.methods = [Free()]
Exemple #37
0
class Repository(object):
    """
    Repository class responsible for returning ShippingMethod
    objects for a given user, basket etc
    """
    methods = (Free(), )

    def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
        """
        Return a list of all applicable shipping method objects
        for a given basket.

        We default to returning the Method models that have been defined but
        this behaviour can easily be overridden by subclassing this class
        and overriding this method.
        """
        return self.prime_methods(basket, self.methods)

    def get_default_shipping_method(self,
                                    user,
                                    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.
        """
        methods = self.get_shipping_methods(user, basket, shipping_addr,
                                            **kwargs)
        if len(methods) == 0:
            raise ImproperlyConfigured(
                _("You need to define some shipping methods"))

        # Choose the cheapest method by default
        return min(methods, key=lambda method: method.basket_charge_incl_tax())

    def prime_methods(self, basket, methods):
        """
        Prime a list of shipping method instances

        This involves injecting the basket instance into each and adding any
        discount wrappers.
        """
        return [self.prime_method(basket, method) for method in methods]

    def prime_method(self, basket, method):
        """
        Prime an individual method instance
        """
        method.set_basket(basket)
        # If the basket has a shipping offer, wrap the shipping method with a
        # decorating class that applies the offer discount to the shipping
        # charge.
        if basket.offer_applications.shipping_discounts:
            # We assume there is only one shipping discount available
            discount = basket.offer_applications.shipping_discounts[0]
            if method.basket_charge_incl_tax > D('0.00'):
                return OfferDiscount(method, discount['offer'])
        return method

    def find_by_code(self, code, basket):
        """
        Return the appropriate Method object for the given code
        """
        for method in self.methods:
            if method.code == code:
                return self.prime_method(basket, method)

        # Check for NoShippingRequired as that is a special case
        if code == NoShippingRequired.code:
            return self.prime_method(basket, NoShippingRequired())