kwork-poizonstore/account/serializers.py

111 lines
4.0 KiB
Python

from django.conf import settings
from django.db.models import Q
from djoser import serializers as djoser_serializers
from djoser.conf import settings as djoser_settings
from rest_framework import serializers
from rest_framework.exceptions import AuthenticationFailed
from .models import User, BonusProgramTransaction, BonusType
from .utils import verify_telegram_authentication
class UserSerializer(serializers.ModelSerializer):
name = serializers.CharField(source='first_name')
lastname = serializers.CharField(source='middle_name')
surname = serializers.CharField(source='last_name')
invited_with_orders_count = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('id', 'email', 'phone', 'role', 'name', 'lastname', 'surname',
'balance', 'referral_code', 'is_draft_user', 'invited_with_orders_count')
def get_invited_with_orders_count(self, obj):
return obj.invited_users_with_orders.count()
class BonusProgramTransactionSerializer(serializers.ModelSerializer):
order_id = serializers.StringRelatedField(source='order.id', allow_null=True)
type = serializers.CharField(source='get_type_display')
class Meta:
model = BonusProgramTransaction
fields = ('id', 'type', 'date', 'amount', 'order_id', 'comment', 'was_cancelled')
def non_zero_validator(value):
if value == 0:
raise serializers.ValidationError("Value cannot be zero")
return value
class UserBalanceUpdateSerializer(BonusProgramTransactionSerializer):
amount = serializers.IntegerField(validators=[non_zero_validator])
type = serializers.SerializerMethodField()
class Meta:
model = BonusProgramTransactionSerializer.Meta.model
fields = BonusProgramTransactionSerializer.Meta.fields
read_only_fields = ('id', 'type', 'date')
def get_type(self, instance):
# Deposit or spent depending on value
if instance['amount'] < 0:
return BonusType.OTHER_WITHDRAWAL
elif instance['amount'] > 0:
return BonusType.OTHER_DEPOSIT
class SetInitialPasswordSerializer(djoser_serializers.PasswordSerializer):
def validate(self, attrs):
user = getattr(self, "user", None) or self.context["request"].user
# why assert? There are ValidationError / fail everywhere
assert user is not None
if not user.is_superuser and not user.is_draft_user:
raise serializers.ValidationError("To change password, use /users/change_password endpoint")
return super().validate(attrs)
class UserCreateSerializer(djoser_serializers.UserCreateSerializer):
email = serializers.EmailField(required=True)
class TokenCreateSerializer(serializers.Serializer):
email_or_phone = serializers.CharField()
password = serializers.CharField(required=False, style={"input_type": "password"})
default_error_messages = {
"invalid_credentials": djoser_settings.CONSTANTS.messages.INVALID_CREDENTIALS_ERROR,
"inactive_account": djoser_settings.CONSTANTS.messages.INACTIVE_ACCOUNT_ERROR,
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = None
def validate(self, attrs):
email_or_phone = attrs.get('email_or_phone')
password = attrs.get("password")
user = User.objects.filter(Q(email=email_or_phone) | Q(phone=email_or_phone)).first()
if not user or not user.check_password(password) or not user.is_active:
raise AuthenticationFailed()
self.user = user
return attrs
class TelegramCallbackSerializer(serializers.Serializer):
id = serializers.IntegerField()
first_name = serializers.CharField(allow_null=True)
username = serializers.CharField(allow_null=True)
photo_url = serializers.URLField(allow_null=True)
auth_date = serializers.IntegerField()
hash = serializers.CharField()
def validate(self, attrs):
verify_telegram_authentication(bot_token=settings.TG_BOT_TOKEN, request_data=attrs)
return attrs