362 lines
11 KiB
Python
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)
|