Source code for oscarapi.serializers.basket

import logging
from rest_framework import serializers

from oscarapi.basket import operations

from oscarapi.utils import (
    overridable,
    OscarModelSerializer,
    OscarHyperlinkedModelSerializer,
    DrillDownHyperlinkedIdentityField
)
from oscarapi.serializers.fields import TaxIncludedDecimalField

from django.utils.translation import ugettext as _
from oscar.core.loading import get_model
from decimal import Decimal

logger = logging.getLogger(__name__)

Basket = get_model('basket', 'Basket')
Line = get_model('basket', 'Line')
LineAttribute = get_model('basket', 'LineAttribute')
StockRecord = get_model('partner', 'StockRecord')
Voucher = get_model('voucher', 'Voucher')


[docs]class VoucherSerializer(OscarModelSerializer): class Meta: model = Voucher fields = overridable('OSCARAPI_VOUCHER_FIELDS', default=( 'name', 'code', 'start_datetime', 'end_datetime' ))
class OfferDiscountSerializer(serializers.Serializer): description = serializers.CharField() name = serializers.CharField() amount = serializers.DecimalField( decimal_places=2, max_digits=12, source='discount') class VoucherDiscountSerializer(OfferDiscountSerializer): voucher = VoucherSerializer(required=False)
[docs]class BasketSerializer(serializers.HyperlinkedModelSerializer): lines = serializers.HyperlinkedIdentityField(view_name='basket-lines-list') offer_discounts = OfferDiscountSerializer(many=True, required=False) total_excl_tax = serializers.DecimalField( decimal_places=2, max_digits=12, required=False) total_excl_tax_excl_discounts = serializers.DecimalField( decimal_places=2, max_digits=12, required=False) total_incl_tax = TaxIncludedDecimalField( excl_tax_field='total_excl_tax', decimal_places=2, max_digits=12, required=False) total_incl_tax_excl_discounts = TaxIncludedDecimalField( excl_tax_field='total_excl_tax_excl_discounts', decimal_places=2, max_digits=12, required=False) total_tax = TaxIncludedDecimalField( excl_tax_value=Decimal('0.00'), decimal_places=2, max_digits=12, required=False) currency = serializers.CharField(required=False) voucher_discounts = VoucherDiscountSerializer(many=True, required=False) class Meta: model = Basket fields = overridable('OSCARAPI_BASKET_FIELDS', default=( 'id', 'owner', 'status', 'lines', 'url', 'total_excl_tax', 'total_excl_tax_excl_discounts', 'total_incl_tax', 'total_incl_tax_excl_discounts', 'total_tax', 'currency', 'voucher_discounts', 'offer_discounts', 'is_tax_known')) def get_validation_exclusions(self, instance=None): """ This is needed because oscar declared the owner field as ``null=True``, but ``blank=False``. That means the validator will claim you can not leave this value set to None. """ return super(BasketSerializer, self).get_validation_exclusions( instance) + ['owner']
class LineAttributeSerializer(OscarHyperlinkedModelSerializer): class Meta: model = LineAttribute fields = '__all__'
[docs]class BasketLineSerializer(OscarHyperlinkedModelSerializer): """ This serializer computes the prices of this line by using the basket strategy. """ url = DrillDownHyperlinkedIdentityField( view_name='basket-line-detail', extra_url_kwargs={'basket_pk': 'basket.id'}) attributes = LineAttributeSerializer( many=True, fields=('url', 'option', 'value'), required=False, read_only=True) price_excl_tax = serializers.DecimalField( decimal_places=2, max_digits=12, source='line_price_excl_tax_incl_discounts') price_incl_tax = TaxIncludedDecimalField( decimal_places=2, max_digits=12, excl_tax_field='line_price_excl_tax_incl_discounts', source='line_price_incl_tax_incl_discounts') price_incl_tax_excl_discounts = TaxIncludedDecimalField( decimal_places=2, max_digits=12, excl_tax_field='line_price_excl_tax', source='line_price_incl_tax') price_excl_tax_excl_discounts = serializers.DecimalField( decimal_places=2, max_digits=12, source='line_price_excl_tax') warning = serializers.CharField( read_only=True, required=False, source='get_warning') @property def basket_pk(self): return self.kwargs.get('basket_pk') class Meta: model = Line fields = overridable('OSCARAPI_BASKETLINE_FIELDS', default=( 'url', 'product', 'quantity', 'attributes', 'price_currency', 'price_excl_tax', 'price_incl_tax', 'price_incl_tax_excl_discounts', 'price_excl_tax_excl_discounts', 'is_tax_known', 'warning', 'basket', 'stockrecord', 'date_created' )) def to_representation(self, obj): # This override is needed to reflect offer discounts or strategy # related prices immediately in the response operations.assign_basket_strategy(obj.basket, self.context['request']) # Oscar stores the calculated discount in line._discount_incl_tax or # line._discount_excl_tax when offers are applied. So by just # retrieving the line from the db you will loose this values, that's # why we need to get the line from the in-memory resultset here lines = (x for x in obj.basket.all_lines() if x.id == obj.id) line = next(lines, None) return super(BasketLineSerializer, self).to_representation(line)
class LineSerializer(serializers.HyperlinkedModelSerializer): """ This serializer just shows fields stored in the database for this line. """ attributes = LineAttributeSerializer( many=True, fields=('url', 'option', 'value'), required=False, read_only=True) class Meta: model = Line fields = '__all__' class StockRecordSerializer(serializers.ModelSerializer): class Meta: model = StockRecord fields = '__all__' class VoucherAddSerializer(serializers.Serializer): vouchercode = serializers.CharField(max_length=128, required=True) def validate(self, attrs): # oscar expects this always to be uppercase. attrs['vouchercode'] = attrs['vouchercode'].upper() request = self.context.get('request') try: voucher = Voucher.objects.get(code=attrs.get('vouchercode')) # check expiry date if not voucher.is_active(): message = _("The '%(code)s' voucher has expired") % { 'code': voucher.code } raise serializers.ValidationError(message) # check voucher rules is_available, message = voucher.is_available_to_user(request.user) if not is_available: raise serializers.ValidationError(message) except Voucher.DoesNotExist: raise serializers.ValidationError(_('Voucher code unknown')) # set instance to the voucher so we can use this in the view self.instance = voucher return attrs def create(self, validated_data): return Voucher.objects.create(**validated_data)