from rest_framework import serializers from django.utils.translation import gettext as _ from labs.models import ( CreditTransaction, BillingUserProfile, BillingStripePaymentMethod, ) from labs.billing.consts import ( BILLING_ALLOWED_COUNTRIES, BUY_CREDITS_MIN_QUANTITY, BUY_CREDITS_MAX_QUANTITY, ) from labs.billing.providers.stripe import StripeProvider from labs.user_events import UserEvent, log_user_event class TransactionListSerializer(serializers.ModelSerializer): transaction_type_display = serializers.SerializerMethodField() lab_code = serializers.SerializerMethodField() def get_transaction_type_display(self, obj: CreditTransaction) -> str: return obj.get_transaction_type_display() def get_lab_code(self, obj: CreditTransaction) -> str: return obj.redemption.lab_code if obj.redemption else None class Meta: model = CreditTransaction fields = [ "id", "transaction_type", "transaction_type_display", "paid_credits", "free_credits", "lab_code", "created_at", ] class PaymentCreditsSerializer(serializers.Serializer): quantity = serializers.IntegerField( min_value=BUY_CREDITS_MIN_QUANTITY, max_value=BUY_CREDITS_MAX_QUANTITY, ) class UserProfileUpdateBillingDetailsSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.user = self.context["request"].user self.instance = BillingUserProfile.objects.filter(user=self.user).first() class Meta: model = BillingUserProfile fields = ["country", "city", "state", "postal_code", "line1", "line2"] extra_kwargs = { "country": {"required": True, "allow_blank": False}, "city": {"required": True, "allow_blank": False}, "state": {"required": True, "allow_blank": False}, "postal_code": {"required": True, "allow_blank": False}, "line1": {"required": True, "allow_blank": False}, "line2": {"required": False}, } def validate_country(self, value: str) -> str: if value not in BILLING_ALLOWED_COUNTRIES: raise serializers.ValidationError( _("Sorry, currently we only accept payments from %s") % ", ".join(BILLING_ALLOWED_COUNTRIES) ) return value def validate(self, attrs: dict) -> dict: country = attrs.get("country") state = attrs.get("state") if country == "US": if state.lower() not in ["ca", "california"]: raise serializers.ValidationError( _( "Sorry, currently we only accept payments from California for US users" ) ) return attrs def create(self, validated_data): customer_id = StripeProvider( self.user, self.context["request"], ).get_or_create_stripe_customer() profile = BillingUserProfile.objects.get(user=self.user) return self.update(profile, validated_data) def update(self, instance, validated_data): log_user_event( user=self.user, event_name=UserEvent.EventName.BILLING_UPDATE_PROFILE, event_body={ "country": validated_data["country"], "city": validated_data["city"], "postal_code": validated_data["postal_code"], }, ) return super().update(instance, validated_data) class StripePaymentMethodSerializer(serializers.Serializer): payment_method_id = serializers.CharField(required=True) class CheckoutOrderSerializer(serializers.Serializer): payment_method_id = serializers.CharField(required=True) def validate_payment_method_id(self, value: str) -> str: if not BillingStripePaymentMethod.objects.filter( stripe_pm_id=value, user=self.context["request"].user, ).exists(): raise serializers.ValidationError(_("Payment method not found")) return value