Source code for oscarapi.serializers.basket

# pylint: disable=W0223
import logging
from decimal import Decimal

from django.utils.translation import gettext as _
from django.contrib.auth import get_user_model
from rest_framework import serializers

from oscar.core.loading import get_model

from oscarapi import settings
from oscarapi.basket import operations
from oscarapi.serializers.fields import (
    DrillDownHyperlinkedIdentityField,
    DrillDownHyperlinkedRelatedField,
)
from oscarapi.serializers.utils import (
    OscarModelSerializer,
    OscarHyperlinkedModelSerializer,
)
from oscarapi.serializers.fields import TaxIncludedDecimalField

logger = logging.getLogger(__name__)

User = get_user_model()
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")
Product = get_model("catalogue", "Product")


[docs]class VoucherSerializer(OscarModelSerializer): class Meta: model = Voucher fields = settings.VOUCHER_FIELDS
class OfferDiscountSerializer( serializers.Serializer ): # pylint: disable=abstract-method 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) owner = serializers.HyperlinkedRelatedField( view_name="user-detail", required=False, allow_null=True, queryset=User.objects.all(), ) class Meta: model = Basket fields = settings.BASKET_FIELDS
class LineAttributeSerializer(OscarHyperlinkedModelSerializer): url = DrillDownHyperlinkedIdentityField( view_name="lineattribute-detail", extra_url_kwargs={"basket_pk": "line.basket.id", "line_pk": "line.id"}, ) line = DrillDownHyperlinkedIdentityField( view_name="basket-line-detail", extra_url_kwargs={"basket_pk": "line.basket.id"} ) 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", read_only=True, ) 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", read_only=True, ) price_incl_tax_excl_discounts = TaxIncludedDecimalField( decimal_places=2, max_digits=12, excl_tax_field="line_price_excl_tax", source="line_price_incl_tax", read_only=True, ) price_excl_tax_excl_discounts = serializers.DecimalField( decimal_places=2, max_digits=12, source="line_price_excl_tax", read_only=True ) warning = serializers.CharField( read_only=True, required=False, source="get_warning" ) stockrecord = DrillDownHyperlinkedRelatedField( view_name="product-stockrecord-detail", extra_url_kwargs={"product_pk": "product_id"}, queryset=StockRecord.objects.all(), ) class Meta: model = Line fields = settings.BASKETLINE_FIELDS def to_representation(self, instance): # This override is needed to reflect offer discounts or strategy # related prices immediately in the response operations.assign_basket_strategy(instance.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 instance.basket.all_lines() if x.id == instance.id) line = next(lines, None) return super(BasketLineSerializer, self).to_representation(line)
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)