========
Shipping
========

Shipping can be very complicated.  Depending on the domain, a wide variety of shipping
scenarios are found in the wild.  For instance, calculation of shipping costs can depend on:

* Shipping method (eg standard, courier)
* Shipping address
* Time of day of order (eg if requesting next-day delivery)
* Weight of items in basket
* Customer type (eg business accounts get discounted shipping rates)
* Offers and vouchers that give free or discounted shipping

Further complications can arise such as:

* Only making certain shipping methods available to certain customers
* Tax is only applicable in certain situations
  
Oscar can handle all of these shipping scenarios. 

Shipping in oscar
-----------------

Shipping is handled using "method" objects which represent a means of shipping
an order (eg "standard" or "next-day" delivery).  Each method is essentially a
named calculator that takes a basket and is able to calculate the shipping
costs with and without tax.  

For example, you may model "standard" delivery by having a calculator object
that charges a fixed price for each item in the basket.  The method object
could be configured by passing the fixed price to be used for calculation.

Shipping within checkout
------------------------

Shipping is first encountered by customers within the checkout flow, on the "shipping
method" view.  

It is the responsibility of this class to either:

1. Offer an a set of delivery methods for the customer to choose from, displaying
   the cost of each.
2. If there is only one method available, to construct the appropriate shipping method
   and set it within the checkout session context.

The ``ShippingMethodView`` class handles this behaviour.  Its core
implementation looks up a list of available shipping methods using the
``oscar.shipping.repository.Repository`` class.  If there is only one, then
this is written out to the session and a redirect is issued to the next step of
the checkout.  If more than one, then each available method is displayed so the
customer can choose.

Default behaviour 
-----------------
Oscar ships with a simple model for calculating shipping based on a charge per
order, and a charge per item.  This is the ``OrderAndItemLevelChargeMethod``
class and is configured by setting the two charges used for the calculation.
You can use this model to provide multiple methods - each identified by a code.

The core ``Repository`` class will load all defined
``OrderAndItemLevelChargeMethod`` models and make them available to the
customer.  If none are set, then a `FreeShipping` method object will be
returned.  

Shipping method classes
-----------------------

Each method object must subclass ``ShippingMethod`` from
``oscar.shipping.methods`` which provides the required interface. Note that the interface
does not depend on the many other factors that can affect shipping (eg shipping address).  The
way to handle this is within your "factory" method which returns availables shipping methods. 

Writing your own shipping method
--------------------------------

Simple really - follow these steps:  

1. Subclass ``oscar.shipping.methods.ShippingMethod`` and implement
   the methods ``basket_charge_incl_tax`` and ``basket_charge_excl_tax`` for calculating shipping costs.
2. Override the default ``shipping.repository.Repository`` class and implement your domain logic
   for determining which shipping methods are returned based on the user, basket and shipping address
   passed in.
