from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.settings import api_settings
from salesman.conf import app_settings
from .payment import payment_methods_pool
[docs]class PaymentMethodSerializer(serializers.Serializer):
"""
Serializer to display payment method with error.
"""
identifier = serializers.CharField(read_only=True)
label = serializers.CharField(read_only=True)
error = serializers.CharField(allow_null=True, read_only=True)
def to_representation(self, payment_method):
data = super().to_representation(payment_method)
payment = payment_methods_pool.get_payment(payment_method.identifier)
request = self.context['request']
try:
if 'basket' in self.context:
payment.validate_basket(basket=self.context['basket'], request=request)
if 'order' in self.context:
payment.validate_order(order=self.context['order'], request=request)
except (ValidationError, DjangoValidationError) as e:
error = serializers.as_serializer_error(e)
data['error'] = error[api_settings.NON_FIELD_ERRORS_KEY][0]
return data
[docs]class CheckoutSerializer(serializers.Serializer):
"""
Serializer for processing a basket payment.
"""
url = serializers.CharField(read_only=True)
email = serializers.EmailField(write_only=True)
shipping_address = serializers.CharField(
allow_blank=True, write_only=True, style={'base_template': 'textarea.html'},
)
billing_address = serializers.CharField(
allow_blank=True, write_only=True, style={'base_template': 'textarea.html'},
)
payment_method = serializers.ChoiceField(
choices=payment_methods_pool.get_choices('basket'), write_only=True,
)
# Show payment methods with error on GET.
payment_methods = PaymentMethodSerializer(many=True, read_only=True)
def validate_shipping_address(self, value):
context = self.context.copy()
context['address'] = 'shipping'
return app_settings.SALESMAN_ADDRESS_VALIDATOR(value, context=context)
def validate_billing_address(self, value):
context = self.context.copy()
context['address'] = 'billing'
return app_settings.SALESMAN_ADDRESS_VALIDATOR(value, context=context)
def validate_payment_method(self, value):
basket, request = self.context['basket'], self.context['request']
payment = payment_methods_pool.get_payment(value)
payment.validate_basket(basket, request)
return payment
def save(self):
# Save contact data on basket.
basket, request = self.context['basket'], self.context['request']
basket.extra['email'] = self.validated_data['email']
basket.extra['shipping_address'] = self.validated_data['shipping_address']
basket.extra['billing_address'] = self.validated_data['billing_address']
basket.save(update_fields=['extra'])
# Process the payment.
payment = self.validated_data['payment_method']
url = payment.basket_payment(basket, request)
self.validated_data['url'] = url