Files
backend/core/apps/api/serializers/ad/ad.py
A'zamov Samandar f5766aa319 update
2025-12-06 21:50:28 +05:00

149 lines
4.7 KiB
Python

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)