""" Appreciation serializers - API serializers for appreciation models """ from rest_framework import serializers from apps.appreciation.models import ( Appreciation, AppreciationBadge, AppreciationCategory, AppreciationStatus, AppreciationVisibility, AppreciationStats, UserBadge, ) class AppreciationCategorySerializer(serializers.ModelSerializer): """Serializer for AppreciationCategory""" class Meta: model = AppreciationCategory fields = [ 'id', 'code', 'name_en', 'name_ar', 'description_en', 'description_ar', 'icon', 'color', 'order', 'is_active', 'hospital', 'created_at', 'updated_at', ] read_only_fields = ['id', 'created_at', 'updated_at'] class AppreciationSerializer(serializers.ModelSerializer): """Serializer for Appreciation""" sender_name = serializers.SerializerMethodField() recipient_name = serializers.SerializerMethodField() recipient_type = serializers.SerializerMethodField() recipient_id = serializers.SerializerMethodField() category_name = serializers.SerializerMethodField() message = serializers.SerializerMethodField() class Meta: model = Appreciation fields = [ 'id', 'sender', 'sender_name', 'recipient', 'recipient_type', 'recipient_id', 'recipient_name', 'hospital', 'department', 'category', 'category_name', 'message_en', 'message_ar', 'message', 'visibility', 'status', 'is_anonymous', 'sent_at', 'acknowledged_at', 'notification_sent', 'notification_sent_at', 'metadata', 'created_at', 'updated_at', ] read_only_fields = [ 'id', 'sender_name', 'recipient_name', 'recipient_type', 'recipient_id', 'category_name', 'message', 'sent_at', 'acknowledged_at', 'notification_sent', 'notification_sent_at', 'created_at', 'updated_at', ] def get_sender_name(self, obj): """Get sender's name""" if obj.is_anonymous: return "Anonymous" if obj.sender: return obj.sender.get_full_name() return "System" def get_recipient_name(self, obj): """Get recipient's name""" try: return str(obj.recipient) except: return "Unknown" def get_recipient_type(self, obj): """Get recipient type (user or physician)""" if obj.recipient_content_type: return obj.recipient_content_type.model return None def get_recipient_id(self, obj): """Get recipient object ID""" return obj.recipient_object_id def get_category_name(self, obj): """Get category name""" if obj.category: return obj.category.name_en return None def get_message(self, obj): """Get message based on language""" # This should use the request's language context # For now, default to English return obj.message_en class AppreciationCreateSerializer(serializers.Serializer): """Serializer for creating Appreciation""" recipient_type = serializers.ChoiceField( choices=['user', 'physician'], write_only=True, help_text="Type of recipient: 'user' or 'physician'" ) recipient_id = serializers.UUIDField(write_only=True) category_id = serializers.UUIDField(required=False, allow_null=True) message_en = serializers.CharField(required=True) message_ar = serializers.CharField(required=False, allow_blank=True) visibility = serializers.ChoiceField( choices=AppreciationVisibility.choices, default=AppreciationVisibility.PRIVATE ) is_anonymous = serializers.BooleanField(default=False) hospital_id = serializers.UUIDField(required=True) department_id = serializers.UUIDField(required=False, allow_null=True) def validate_recipient_id(self, value): """Validate recipient ID""" # Will be validated in validate method return value def validate(self, data): """Validate the entire data""" recipient_type = data.get('recipient_type') recipient_id = data.get('recipient_id') hospital_id = data.get('hospital_id') # Validate recipient exists from django.contrib.contenttypes.models import ContentType if recipient_type == 'user': from apps.accounts.models import User try: user = User.objects.get(id=recipient_id) # Check if user belongs to hospital if user.hospital_id != hospital_id: raise serializers.ValidationError({ 'recipient_id': 'User does not belong to specified hospital' }) except User.DoesNotExist: raise serializers.ValidationError({ 'recipient_id': 'User not found' }) elif recipient_type == 'physician': from apps.organizations.models import Physician try: physician = Physician.objects.get(id=recipient_id) if physician.hospital_id != hospital_id: raise serializers.ValidationError({ 'recipient_id': 'Physician does not belong to specified hospital' }) except Physician.DoesNotExist: raise serializers.ValidationError({ 'recipient_id': 'Physician not found' }) # Validate category if provided category_id = data.get('category_id') if category_id: try: category = AppreciationCategory.objects.get(id=category_id) if category.hospital_id and category.hospital_id != hospital_id: raise serializers.ValidationError({ 'category_id': 'Category does not belong to specified hospital' }) except AppreciationCategory.DoesNotExist: raise serializers.ValidationError({ 'category_id': 'Category not found' }) return data class AppreciationBadgeSerializer(serializers.ModelSerializer): """Serializer for AppreciationBadge""" class Meta: model = AppreciationBadge fields = [ 'id', 'code', 'name_en', 'name_ar', 'description_en', 'description_ar', 'icon', 'color', 'criteria_type', 'criteria_value', 'order', 'is_active', 'hospital', 'created_at', 'updated_at', ] read_only_fields = ['id', 'created_at', 'updated_at'] class UserBadgeSerializer(serializers.ModelSerializer): """Serializer for UserBadge""" recipient_name = serializers.SerializerMethodField() recipient_type = serializers.SerializerMethodField() badge_details = AppreciationBadgeSerializer(source='badge', read_only=True) class Meta: model = UserBadge fields = [ 'id', 'recipient', 'recipient_name', 'recipient_type', 'badge', 'badge_details', 'earned_at', 'appreciation_count', 'metadata', 'created_at', 'updated_at', ] read_only_fields = [ 'id', 'recipient_name', 'recipient_type', 'earned_at', 'created_at', 'updated_at', ] def get_recipient_name(self, obj): """Get recipient's name""" try: return str(obj.recipient) except: return "Unknown" def get_recipient_type(self, obj): """Get recipient type""" if obj.recipient_content_type: return obj.recipient_content_type.model return None class AppreciationStatsSerializer(serializers.ModelSerializer): """Serializer for AppreciationStats""" recipient_name = serializers.SerializerMethodField() recipient_type = serializers.SerializerMethodField() period_display = serializers.SerializerMethodField() class Meta: model = AppreciationStats fields = [ 'id', 'recipient', 'recipient_name', 'recipient_type', 'year', 'month', 'period_display', 'hospital', 'department', 'received_count', 'sent_count', 'acknowledged_count', 'hospital_rank', 'department_rank', 'category_breakdown', 'metadata', 'created_at', 'updated_at', ] read_only_fields = [ 'id', 'recipient_name', 'recipient_type', 'period_display', 'created_at', 'updated_at', ] def get_recipient_name(self, obj): """Get recipient's name""" try: return str(obj.recipient) except: return "Unknown" def get_recipient_type(self, obj): """Get recipient type""" if obj.recipient_content_type: return obj.recipient_content_type.model return None def get_period_display(self, obj): """Get formatted period display""" return f"{obj.year}-{obj.month:02d}" class AppreciationLeaderboardSerializer(serializers.Serializer): """Serializer for appreciation leaderboard""" recipient_type = serializers.CharField() recipient_id = serializers.UUIDField() recipient_name = serializers.CharField() hospital = serializers.CharField() department = serializers.CharField(required=False, allow_null=True) received_count = serializers.IntegerField() rank = serializers.IntegerField() badges = serializers.ListField( child=serializers.DictField(), required=False ) class AppreciationSummarySerializer(serializers.Serializer): """Serializer for appreciation summary statistics""" total_received = serializers.IntegerField() total_sent = serializers.IntegerField() this_month_received = serializers.IntegerField() this_month_sent = serializers.IntegerField() top_category = serializers.DictField(required=False, allow_null=True) badges_earned = serializers.IntegerField() hospital_rank = serializers.IntegerField(required=False, allow_null=True) department_rank = serializers.IntegerField(required=False, allow_null=True)