from django.contrib.auth import authenticate from drf_extra_fields.fields import Base64ImageField from rest_framework import serializers from store.exceptions import CRMException, InvalidCredentialsException from store.models import User, Checklist, GlobalSettings, Category, PaymentMethod, Promocode, Image class LoginSerializer(serializers.Serializer): login = serializers.CharField(write_only=True, required=False) password = serializers.CharField(trim_whitespace=False, write_only=True, required=False) def validate(self, attrs): email = attrs.get('login') password = attrs.get('password') if not email or not password: raise CRMException('login and password is required') user = authenticate(request=self.context.get('request'), email=email, password=password) # The authenticate call simply returns None for is_active=False # users. (Assuming the default ModelBackend authentication backend.) if not user: raise InvalidCredentialsException() attrs['user'] = user return attrs class UserSerializer(serializers.ModelSerializer): login = serializers.CharField(source='email', required=False) job = serializers.CharField(source='job_title', required=False) name = serializers.CharField(source='first_name', required=False) lastname = serializers.CharField(source='middle_name', required=False) surname = serializers.CharField(source='last_name', required=False) class Meta: model = User fields = ('id', 'login', 'job', 'name', 'lastname', 'surname',) class ImageSerializer(serializers.ModelSerializer): image = Base64ImageField() class Meta: model = Image fields = ('image',) class ImageListSerializer(serializers.ListSerializer): child = ImageSerializer() def to_internal_value(self, data): if isinstance(data, list): data = [{"image": x} for x in data] return super().to_internal_value(data) def to_representation(self, data): images = super().to_representation(data) return [image['image'] for image in images] class ChecklistSerializer(serializers.ModelSerializer): id = serializers.CharField(read_only=True) managerid = serializers.PrimaryKeyRelatedField(source='manager_id', read_only=True, allow_null=True) link = serializers.URLField(source='product_link', required=False) category = serializers.SlugRelatedField(slug_field='slug', queryset=Category.objects.all()) image = ImageListSerializer(source='main_images', required=False) previewimage = serializers.ImageField(source='preview_image_url', read_only=True) promo = serializers.SlugRelatedField(source='promocode', slug_field='name', queryset=Promocode.objects.active(), required=False) currency = serializers.SerializerMethodField('get_yuan_rate') curencycurency2 = serializers.DecimalField(source='price_yuan', required=False, max_digits=10, decimal_places=2) currency3 = serializers.DecimalField(source='price_rub', read_only=True, max_digits=10, decimal_places=2) chinadelivery = serializers.SerializerMethodField('get_delivery_price_CN', read_only=True) chinadelivery2 = serializers.DecimalField(source='delivery_price_CN_RU', read_only=True, max_digits=10, decimal_places=2) fullprice = serializers.DecimalField(source='full_price', read_only=True, max_digits=10, decimal_places=2) realprice = serializers.DecimalField(source='real_price', required=False, allow_null=True, max_digits=10, decimal_places=2) comission = serializers.SerializerMethodField('get_comission', read_only=True) buyername = serializers.CharField(source='buyer_name', required=False, allow_null=True) buyerphone = serializers.CharField(source='buyer_phone', required=False, allow_null=True) tg = serializers.CharField(source='buyer_telegram', required=False, allow_null=True) receivername = serializers.CharField(source='receiver_name', required=False, allow_null=True) reveiverphone = serializers.CharField(source='receiver_phone', required=False, allow_null=True) split = serializers.BooleanField(source='is_split_payment', required=False) paymenttype = serializers.SlugRelatedField(source='payment_method', slug_field='slug', queryset=PaymentMethod.objects.all(), required=False, allow_null=True) paymentproovement = ImageListSerializer(source='payment_proof', required=False, allow_null=True) checkphoto = Base64ImageField(source='receipt', required=False, allow_null=True) trackid = serializers.CharField(source='poizon_tracking', required=False, allow_null=True) cdek_tracking = serializers.CharField(required=False, allow_null=True) delivery = serializers.ChoiceField(choices=Checklist.DeliveryType.CHOICES, required=False, allow_null=True) delivery_display = serializers.CharField(source='get_delivery_display', read_only=True) startDate = serializers.DateTimeField(source='created_at', read_only=True) currentDate = serializers.DateTimeField(source='status_updated_at', read_only=True) def _collect_images_by_fields(self, validated_data): images = {} for k in ('main_images', 'payment_proof'): if k in validated_data: images[k] = validated_data.pop(k) return images def _create_main_images(self, instance, images): if images is None: return img_objs = [Image(image=img['image'], type=Image.DEFAULT) for img in images] img_objs = Image.objects.bulk_create(img_objs) instance.images.set(img_objs) instance.generate_preview(next(iter(img_objs), None)) def _create_payment_proofs(self, instance, images): if images is None: return img_objs = [Image(image=img['image'], type=Image.DOC) for img in images] img_objs = Image.objects.bulk_create(img_objs) instance.payment_proof.set(img_objs) def create(self, validated_data): images = self._collect_images_by_fields(validated_data) instance = super().create(validated_data) self._create_main_images(instance, images.get('main_images')) self._create_payment_proofs(instance, images.get('payment_proof')) return instance def update(self, instance, validated_data): images = self._collect_images_by_fields(validated_data) self._create_main_images(instance, images.get('main_images')) self._create_payment_proofs(instance, images.get('payment_proof')) instance: Checklist = super().update(instance, validated_data) # Invalidate prefetched images delattr(instance, '_images') return instance @staticmethod def get_yuan_rate(obj: Checklist): return GlobalSettings.load().yuan_rate @staticmethod def get_image(obj: Checklist): return obj.images.all() @staticmethod def get_delivery_price_CN(obj: Checklist): return GlobalSettings.load().delivery_price_CN @staticmethod def get_comission(obj: Checklist): return GlobalSettings.load().commission_rub class Meta: model = Checklist fields = ('id', 'status', 'managerid', 'link', 'category', 'subcategory', 'brand', 'model', 'size', 'image', 'previewimage', 'currency', 'curencycurency2', 'currency3', 'chinadelivery', 'chinadelivery2', 'comission', 'promo', 'comment', 'fullprice', 'realprice', 'buyername', 'buyerphone', 'tg', 'receivername', 'reveiverphone', 'split', 'paymenttype', 'paymentproovement', 'checkphoto', 'trackid', 'cdek_tracking', 'cdek_barcode_pdf', 'delivery', 'delivery_display', 'startDate', 'currentDate', ) class AnonymousUserChecklistSerializer(ChecklistSerializer): class Meta: model = ChecklistSerializer.Meta.model fields = ChecklistSerializer.Meta.fields read_only_fields = tuple(set(ChecklistSerializer.Meta.fields) - {'paymentprovement', 'paymenttype', 'buyername', 'buyerphone', 'delivery', 'recievername', 'recieverphone', 'tg'}) class GlobalSettingsYuanRateSerializer(serializers.ModelSerializer): currency = serializers.DecimalField(source='yuan_rate', max_digits=10, decimal_places=2) class Meta: model = GlobalSettings fields = ('currency',) class GlobalSettingsPickupSerializer(serializers.ModelSerializer): pickup = serializers.CharField(source='pickup_address') class Meta: model = GlobalSettings fields = ('pickup',) class GlobalSettingsPriceSerializer(serializers.ModelSerializer): comission = serializers.DecimalField(source='commission_rub', max_digits=10, decimal_places=2) chinadelivery = serializers.DecimalField(source='delivery_price_CN', max_digits=10, decimal_places=2) class Meta: model = GlobalSettings fields = ('comission', 'chinadelivery') class CategorySerializer(serializers.ModelSerializer): category = serializers.CharField(source='slug') chinarush = serializers.DecimalField(source='delivery_price_CN_RU', max_digits=10, decimal_places=2) class Meta: model = Category fields = ('category', 'chinarush') class PaymentMethodSerializer(serializers.ModelSerializer): type = serializers.CharField(source='slug') class Meta: model = PaymentMethod fields = ('type', 'name', 'requisites', 'cardnumber') class PromocodeSerializer(serializers.ModelSerializer): freedelivery = serializers.BooleanField(source='free_delivery') nocomission = serializers.BooleanField(source='no_comission') class Meta: model = Promocode fields = ('id', 'name', 'discount', 'freedelivery', 'nocomission', 'is_active')