HH/apps/appreciation/serializers.py
2026-01-01 16:44:42 +03:00

362 lines
11 KiB
Python

"""
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)