text: from decimal import Decimal as D
  
  from django.utils.translation import ugettext_lazy as _
  
  from oscar.apps.shipping.base import Base
  
  
  class Free(Base):
      code = 'free-shipping'
      name = _('Free shipping')
      is_tax_known = True
      charge_incl_tax = charge_excl_tax = D('0.00')
  
  
  class NoShippingRequired(Free):
      """
      This is a special shipping method that indicates that no shipping is
      actually required (eg for digital goods).
      """
      code = 'no-shipping-required'
      name = _('No shipping required')
  
  
  class FixedPrice(Base):
      code = 'fixed-price-shipping'
      name = _('Fixed price shipping')
  
      def __init__(self, charge_excl_tax, charge_incl_tax=None):
          self.charge_excl_tax = charge_excl_tax
          if charge_incl_tax is not None:
              self.charge_incl_tax = charge_incl_tax
              self.is_tax_known = True
  
  
  class OfferDiscount(Base):
      """
      Wrapper class that applies a discount to an existing shipping method's
      charges
      """
  
      def __init__(self, method, offer):
          self.method = method
          self.offer = offer
  
      @property
      def is_discounted(self):
          # We check to see if the discount is non-zero.  It is possible to have
          # zero shipping already in which case this the offer does not lead to
          # any further discount.
          return self.discount > 0
  
      @property
      def discount(self):
          return self.get_discount()['discount']
  
      @property
      def code(self):
          return self.method.code
  
      @property
      def name(self):
          return self.method.name
  
      @property
      def description(self):
          return self.method.description
  
      def get_discount(self):
          # Return a 'discount' dictionary in the same form as that used by the
          # OfferApplications class
          return {
              'offer': self.offer,
              'result': None,
              'name': self.offer.name,
              'description': '',
              'voucher': self.offer.get_voucher(),
              'freq': 1,
              'discount': self.effective_discount}
  
      @property
      def charge_incl_tax_before_discount(self):
          return self.method.charge_incl_tax
  
      @property
      def charge_excl_tax_before_discount(self):
          return self.method.charge_excl_tax
  
      # Property for is_tax_known
  
      def _get_is_tax_known(self):
          return self.method.is_tax_known
  
      def _set_is_tax_known(self, value):
          self.method.is_tax_known = value
  
      is_tax_known = property(_get_is_tax_known, _set_is_tax_known)
  
      @property
      def effective_discount(self):
          """
          The discount value.
          """
          raise NotImplemented()
  
      @property
      def charge_excl_tax(self):
          raise NotImplemented()
  
  
  class TaxExclusiveOfferDiscount(OfferDiscount):
  
      @property
      def effective_discount(self):
          parent_charge = self.method.charge_excl_tax
          return self.offer.shipping_discount(parent_charge)
  
      @property
      def charge_excl_tax(self):
          parent_charge = self.method.charge_excl_tax
          discount = self.offer.shipping_discount(parent_charge)
          return parent_charge - discount
  
  
  class TaxInclusiveOfferDiscount(OfferDiscount):
  
      @property
      def effective_discount(self):
          parent_charge = self.method.charge_incl_tax
          return self.offer.shipping_discount(parent_charge)
  
      @property
      def charge_incl_tax(self):
          parent_charge = self.method.charge_incl_tax
          discount = self.offer.shipping_discount(parent_charge)
          return parent_charge - discount
  
      @property
      def charge_excl_tax(self):
          # Adjust tax exclusive rate using the ratio of the two tax inclusive
          # charges.
          parent_charge_excl_tax = self.method.charge_excl_tax
          parent_charge_incl_tax = self.method.charge_incl_tax
          charge_incl_tax = self.charge_incl_tax
          if parent_charge_incl_tax == 0:
              return D('0.00')
          charge = parent_charge_excl_tax * (charge_incl_tax /
                                             parent_charge_incl_tax)
          return charge.quantize(D('0.01'))
  