from rest_framework import serializers from django.db.models import Avg from core.apps.accounts.choices import AccountType from core.apps.api.models import AdModel, AdVariantModel, CategoryModel, AdImageModel, AdOptionModel from core.apps.accounts.models import UserLike from core.apps.api.choices import AdVariantType from core.apps.api.serializers.common.color import ListColorSerializer from core.apps.api.serializers.common.size import ListSizeSerializer class AdOptionSerializer(serializers.ModelSerializer): class Meta: model = AdOptionModel fields = ["id", "name", "value"] read_only_fields = ["id"] class CategorySerializer(serializers.ModelSerializer): class Meta: model = CategoryModel fields = ["id", "name"] read_only_fields = ["id"] class AdImageSerializer(serializers.ModelSerializer): class Meta: model = AdImageModel fields = ["id", "image", "ad_variant", "is_primary", "order"] read_only_fields = ["id"] def to_representation(self, instance): data = super().to_representation(instance) if not instance.ad_variant: data.pop("ad_variant", None) return data class AdVariantSerializer(serializers.ModelSerializer): color = ListColorSerializer() size = ListSizeSerializer() class Meta: model = AdVariantModel fields = ["id", "size", "color", "is_available", "price", "stock_quantity"] read_only_fields = ["id", "color_name"] class AdListSerializer(serializers.ModelSerializer): is_liked = serializers.SerializerMethodField() rating = serializers.SerializerMethodField() reviews_count = serializers.SerializerMethodField() class Meta: model = AdModel fields = ["id", "name", "price", "image", "discount", "is_liked", "rating", "reviews_count", "is_available"] read_only_fields = fields def get_rating(self, obj): """Get average rating from feedbacks""" avg = obj.feedbacks.aggregate(avg=Avg("star"))["avg"] return round(avg, 1) if avg else 0 def get_reviews_count(self, obj): """Get total count of feedbacks""" return obj.feedbacks.count() def get_is_liked(self, obj): """Check if current user liked this ad""" request = self.context.get("request") if not request or not request.user.is_authenticated: return False return UserLike.objects.filter(user=request.user, ad=obj).exists() class AdDetailSerializer(AdListSerializer): variants = AdVariantSerializer(many=True, read_only=True) images = AdImageSerializer(many=True, read_only=True) colors = serializers.SerializerMethodField() sizes = serializers.SerializerMethodField() creator = serializers.SerializerMethodField() options = AdOptionSerializer(many=True, read_only=True) category = CategorySerializer(read_only=True) class Meta(AdListSerializer.Meta): fields = AdListSerializer.Meta.fields + [ "description", "images", "variants", "colors", "sizes", "creator", "options", "category", "ad_type", "physical_product", ] def get_colors(self, obj): """Get unique colors from variants""" return list(obj.variants.values_list("color", flat=True).distinct()) def get_sizes(self, obj): """Get unique sizes from variants""" return list(obj.variants.values_list("size", flat=True).distinct()) def get_creator(self, obj): """Get creator information""" user = obj.user request = self.context.get("request") avatar_url = None if user.avatar and request: avatar_url = request.build_absolute_uri(user.avatar.url) if user.account_type == AccountType.BUSINESS: username = user.business.name if hasattr(user, "business") else user.username else: username = f"{user.first_name} {user.last_name}".strip() or user.username return { "id": user.id, "username": username, "avatar": avatar_url, "account_type": user.account_type, "joined_at": user.date_joined, } class AdCreateSerializer(serializers.ModelSerializer): class Meta: model = AdModel fields = [ "name", "ad_type", "category", "ad_category_type", "discount", "is_available", "physical_product", "plan", "tags", "image", "description", ] def create(self, validated_data): validated_data["user"] = self.context["request"].user return super().create(validated_data)