from rest_framework import serializers from ..models import ( Message, MessageRecipient, NotificationTemplate, AlertRule, AlertInstance, CommunicationChannel, DeliveryLog ) class BaseSerializer(serializers.ModelSerializer): """Base serializer with common functionality""" class Meta: fields = ['id'] read_only_fields = ['created_at', 'updated_at'] class CommunicationChannelSerializer(serializers.ModelSerializer): """Serializer for CommunicationChannel model""" channel_type_display = serializers.CharField(source='get_channel_type_display', read_only=True) class Meta: model = CommunicationChannel fields = [ 'channel_id', 'name', 'description', 'channel_type', 'channel_type_display', 'configuration', 'is_active', 'is_default', 'priority', 'created_at', 'updated_at' ] read_only_fields = ['channel_id', 'created_at', 'updated_at'] class NotificationTemplateSerializer(serializers.ModelSerializer): """Serializer for NotificationTemplate model""" template_type_display = serializers.CharField(source='get_template_type_display', read_only=True) class Meta: model = NotificationTemplate fields = [ 'template_id', 'name', 'description', 'template_type', 'template_type_display', 'subject_template', 'body_template', 'variables', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['template_id', 'created_at', 'updated_at'] class MessageRecipientSerializer(serializers.ModelSerializer): """Serializer for MessageRecipient model""" recipient_name = serializers.CharField(source='recipient.get_full_name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = MessageRecipient fields = [ 'recipient_id', 'message', 'recipient', 'recipient_name', 'status', 'status_display', 'delivered_at', 'read_at', 'created_at', 'updated_at' ] read_only_fields = ['recipient_id', 'created_at', 'updated_at'] class MessageSerializer(serializers.ModelSerializer): """Serializer for Message model""" sender_name = serializers.CharField(source='sender.get_full_name', read_only=True) message_type_display = serializers.CharField(source='get_message_type_display', read_only=True) priority_display = serializers.CharField(source='get_priority_display', read_only=True) recipients = MessageRecipientSerializer(many=True, read_only=True) recipient_count = serializers.IntegerField(read_only=True) delivered_count = serializers.IntegerField(read_only=True) read_count = serializers.IntegerField(read_only=True) class Meta: model = Message fields = [ 'message_id', 'sender', 'sender_name', 'subject', 'body', 'message_type', 'message_type_display', 'priority', 'priority_display', 'scheduled_at', 'sent_at', 'expires_at', 'is_draft', 'recipients', 'recipient_count', 'delivered_count', 'read_count', 'created_at', 'updated_at' ] read_only_fields = [ 'message_id', 'recipient_count', 'delivered_count', 'read_count', 'created_at', 'updated_at' ] class AlertRuleSerializer(serializers.ModelSerializer): """Serializer for AlertRule model""" rule_type_display = serializers.CharField(source='get_rule_type_display', read_only=True) severity_display = serializers.CharField(source='get_severity_display', read_only=True) class Meta: model = AlertRule fields = [ 'rule_id', 'name', 'description', 'rule_type', 'rule_type_display', 'conditions', 'severity', 'severity_display', 'notification_template', 'recipients', 'is_active', 'cooldown_minutes', 'created_at', 'updated_at' ] read_only_fields = ['rule_id', 'created_at', 'updated_at'] class AlertInstanceSerializer(serializers.ModelSerializer): """Serializer for AlertInstance model""" rule_name = serializers.CharField(source='rule.name', read_only=True) severity_display = serializers.CharField(source='get_severity_display', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = AlertInstance fields = [ 'alert_id', 'rule', 'rule_name', 'title', 'description', 'severity', 'severity_display', 'status', 'status_display', 'triggered_at', 'acknowledged_at', 'resolved_at', 'acknowledged_by', 'resolved_by', 'data', 'created_at', 'updated_at' ] read_only_fields = ['alert_id', 'created_at', 'updated_at'] class DeliveryLogSerializer(serializers.ModelSerializer): """Serializer for DeliveryLog model""" channel_name = serializers.CharField(source='channel.name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = DeliveryLog fields = [ 'log_id', 'message', 'recipient', 'channel', 'channel_name', 'status', 'status_display', 'attempt_count', 'last_attempt_at', 'delivered_at', 'error_message', 'created_at', 'updated_at' ] read_only_fields = ['log_id', 'created_at', 'updated_at'] class CommunicationsStatsSerializer(serializers.Serializer): """Serializer for communications statistics""" total_messages = serializers.IntegerField() messages_today = serializers.IntegerField() pending_messages = serializers.IntegerField() delivered_messages = serializers.IntegerField() failed_messages = serializers.IntegerField() active_alerts = serializers.IntegerField() delivery_rate = serializers.FloatField() message_types = serializers.DictField() channel_usage = serializers.DictField() class MessageCreateSerializer(serializers.Serializer): """Serializer for creating messages""" subject = serializers.CharField() body = serializers.CharField() message_type = serializers.CharField() priority = serializers.CharField(default='NORMAL') recipients = serializers.ListField( child=serializers.IntegerField(), min_length=1 ) scheduled_at = serializers.DateTimeField(required=False) expires_at = serializers.DateTimeField(required=False) is_draft = serializers.BooleanField(default=False) def validate_recipients(self, value): """Validate recipient user IDs""" from django.contrib.auth import get_user_model User = get_user_model() valid_users = User.objects.filter(id__in=value).count() if valid_users != len(value): raise serializers.ValidationError("Some recipient IDs are invalid.") return value def validate(self, data): """Validate message data""" if data.get('scheduled_at') and data.get('expires_at'): if data['expires_at'] <= data['scheduled_at']: raise serializers.ValidationError("Expiry time must be after scheduled time.") return data class BulkMessageSerializer(serializers.Serializer): """Serializer for bulk messaging""" subject = serializers.CharField() body = serializers.CharField() message_type = serializers.CharField() priority = serializers.CharField(default='NORMAL') recipient_groups = serializers.ListField( child=serializers.CharField(), min_length=1 ) template_id = serializers.IntegerField(required=False) template_variables = serializers.JSONField(required=False) def validate_recipient_groups(self, value): """Validate recipient groups""" valid_groups = ['ALL_STAFF', 'DOCTORS', 'NURSES', 'ADMINISTRATORS', 'DEPARTMENT_HEADS'] for group in value: if group not in valid_groups: raise serializers.ValidationError(f"Invalid recipient group: {group}") return value class AlertCreateSerializer(serializers.Serializer): """Serializer for creating alerts""" rule_id = serializers.IntegerField() title = serializers.CharField() description = serializers.CharField() severity = serializers.CharField() data = serializers.JSONField(required=False) def validate_rule_id(self, value): """Validate that the alert rule exists and is active""" try: rule = AlertRule.objects.get(id=value) if not rule.is_active: raise serializers.ValidationError("Alert rule is not active.") return value except AlertRule.DoesNotExist: raise serializers.ValidationError("Invalid alert rule ID.") class AlertAcknowledgeSerializer(serializers.Serializer): """Serializer for acknowledging alerts""" alert_id = serializers.IntegerField() notes = serializers.CharField(required=False, allow_blank=True) def validate_alert_id(self, value): """Validate that the alert exists and can be acknowledged""" try: alert = AlertInstance.objects.get(id=value) if alert.status != 'ACTIVE': raise serializers.ValidationError("Alert is not in active status.") return value except AlertInstance.DoesNotExist: raise serializers.ValidationError("Invalid alert ID.") class AlertResolveSerializer(serializers.Serializer): """Serializer for resolving alerts""" alert_id = serializers.IntegerField() resolution_notes = serializers.CharField() def validate_alert_id(self, value): """Validate that the alert exists and can be resolved""" try: alert = AlertInstance.objects.get(id=value) if alert.status == 'RESOLVED': raise serializers.ValidationError("Alert is already resolved.") return value except AlertInstance.DoesNotExist: raise serializers.ValidationError("Invalid alert ID.") class NotificationSendSerializer(serializers.Serializer): """Serializer for sending notifications""" template_id = serializers.IntegerField() recipients = serializers.ListField( child=serializers.IntegerField(), min_length=1 ) variables = serializers.JSONField(required=False) channel_ids = serializers.ListField( child=serializers.IntegerField(), required=False ) def validate_template_id(self, value): """Validate that the template exists and is active""" try: template = NotificationTemplate.objects.get(id=value) if not template.is_active: raise serializers.ValidationError("Notification template is not active.") return value except NotificationTemplate.DoesNotExist: raise serializers.ValidationError("Invalid template ID.") class ChannelTestSerializer(serializers.Serializer): """Serializer for testing communication channels""" channel_id = serializers.IntegerField() test_message = serializers.CharField(default="Test message from hospital management system") test_recipient = serializers.CharField() def validate_channel_id(self, value): """Validate that the channel exists and is active""" try: channel = CommunicationChannel.objects.get(id=value) if not channel.is_active: raise serializers.ValidationError("Communication channel is not active.") return value except CommunicationChannel.DoesNotExist: raise serializers.ValidationError("Invalid channel ID.")