HH/apps/complaints/serializers.py
2026-01-15 15:02:42 +03:00

277 lines
11 KiB
Python

"""
Complaints serializers
"""
from rest_framework import serializers
from .models import Complaint, ComplaintAttachment, ComplaintUpdate, Inquiry,ComplaintExplanation
class ComplaintAttachmentSerializer(serializers.ModelSerializer):
"""Complaint attachment serializer"""
uploaded_by_name = serializers.SerializerMethodField()
class Meta:
model = ComplaintAttachment
fields = [
'id', 'complaint', 'file', 'filename', 'file_type', 'file_size',
'uploaded_by', 'uploaded_by_name', 'description',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'file_size', 'created_at', 'updated_at']
def get_uploaded_by_name(self, obj):
"""Get uploader name"""
if obj.uploaded_by:
return obj.uploaded_by.get_full_name()
return None
class ComplaintUpdateSerializer(serializers.ModelSerializer):
"""Complaint update serializer"""
created_by_name = serializers.SerializerMethodField()
class Meta:
model = ComplaintUpdate
fields = [
'id', 'complaint', 'update_type', 'message',
'created_by', 'created_by_name',
'old_status', 'new_status', 'metadata',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_created_by_name(self, obj):
"""Get creator name"""
if obj.created_by:
return obj.created_by.get_full_name()
return None
class ComplaintSerializer(serializers.ModelSerializer):
"""Complaint serializer"""
patient_name = serializers.CharField(source='patient.get_full_name', read_only=True)
patient_mrn = serializers.CharField(source='patient.mrn', read_only=True)
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
department_name = serializers.CharField(source='department.name', read_only=True)
staff_name = serializers.SerializerMethodField()
assigned_to_name = serializers.SerializerMethodField()
created_by_name = serializers.SerializerMethodField()
source_name = serializers.CharField(source='source.name_en', read_only=True)
source_code = serializers.CharField(source='source.code', read_only=True)
attachments = ComplaintAttachmentSerializer(many=True, read_only=True)
updates = ComplaintUpdateSerializer(many=True, read_only=True)
sla_status = serializers.SerializerMethodField()
class Meta:
model = Complaint
fields = [
'id', 'patient', 'patient_name', 'patient_mrn', 'encounter_id',
'hospital', 'hospital_name', 'department', 'department_name',
'staff', 'staff_name',
'title', 'description', 'category', 'subcategory',
'priority', 'severity', 'source', 'source_name', 'source_code', 'status',
'created_by', 'created_by_name',
'assigned_to', 'assigned_to_name', 'assigned_at',
'due_at', 'is_overdue', 'sla_status',
'reminder_sent_at', 'escalated_at',
'resolution', 'resolved_at', 'resolved_by',
'closed_at', 'closed_by',
'resolution_survey', 'resolution_survey_sent_at',
'attachments', 'updates', 'metadata',
'created_at', 'updated_at'
]
read_only_fields = [
'id', 'created_by', 'assigned_at', 'is_overdue',
'reminder_sent_at', 'escalated_at',
'resolved_at', 'closed_at', 'resolution_survey_sent_at',
'created_at', 'updated_at'
]
def create(self, validated_data):
"""
Create complaint with auto-setting of department from AI analysis.
If metadata contains AI analysis with department name,
automatically set the department field by querying the database.
"""
from apps.organizations.models import Department
import logging
logger = logging.getLogger(__name__)
# Extract metadata if present
metadata = validated_data.get('metadata', {})
# Check if department is not already set and AI analysis contains department info
if not validated_data.get('department') and metadata.get('ai_analysis'):
ai_analysis = metadata['ai_analysis']
department_name = ai_analysis.get('department')
# If AI identified a department, try to match it in the database
if department_name:
hospital = validated_data.get('hospital')
if hospital:
try:
# Try exact match first
department = Department.objects.filter(
hospital=hospital,
status='active',
name__iexact=department_name
).first()
# If no exact match, try partial match
if not department:
department = Department.objects.filter(
hospital=hospital,
status='active',
name__icontains=department_name
).first()
if department:
validated_data['department'] = department
logger.info(
f"Auto-set department '{department.name}' from AI analysis "
f"for complaint (matched from '{department_name}')"
)
else:
logger.warning(
f"AI suggested department '{department_name}' but no match found "
f"in hospital '{hospital.name}'"
)
except Exception as e:
logger.error(f"Error auto-setting department: {e}")
# Create the complaint
return super().create(validated_data)
def get_staff_name(self, obj):
"""Get staff name"""
if obj.staff:
return f"{obj.staff.first_name} {obj.staff.last_name}"
return None
def get_assigned_to_name(self, obj):
"""Get assigned user name"""
if obj.assigned_to:
return obj.assigned_to.get_full_name()
return None
def get_created_by_name(self, obj):
"""Get creator name"""
if obj.created_by:
return obj.created_by.get_full_name()
return None
def get_sla_status(self, obj):
"""Get SLA status"""
return obj.sla_status if hasattr(obj, 'sla_status') else 'on_track'
class ComplaintExplanationSerializer(serializers.ModelSerializer):
"""Complaint explanation serializer"""
staff_name = serializers.SerializerMethodField()
requested_by_name = serializers.SerializerMethodField()
attachment_count = serializers.SerializerMethodField()
class Meta:
model = ComplaintExplanation
fields = [
'id', 'complaint', 'staff', 'staff_name',
'explanation', 'token', 'is_used',
'email_sent_at', 'responded_at',
'submitted_via', 'requested_by', 'requested_by_name',
'request_message', 'attachment_count',
'created_at'
]
read_only_fields = ['id', 'email_sent_at', 'responded_at', 'created_at']
def get_staff_name(self, obj):
if obj.staff:
return f"{obj.staff.first_name} {obj.staff.last_name}" if obj.staff.last_name else ""
return ""
def get_requested_by_name(self, obj):
if obj.requested_by:
return obj.requested_by.get_full_name()
return None
def get_attachment_count(self, obj):
return obj.attachments.count()
class ComplaintListSerializer(serializers.ModelSerializer):
"""Simplified complaint serializer for list views"""
patient_name = serializers.CharField(source='patient.get_full_name', read_only=True)
patient_mrn = serializers.CharField(source='patient.mrn', read_only=True)
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
department_name = serializers.CharField(source='department.name', read_only=True)
staff_name = serializers.SerializerMethodField()
assigned_to_name = serializers.SerializerMethodField()
source_name = serializers.CharField(source='source.name_en', read_only=True)
sla_status = serializers.SerializerMethodField()
class Meta:
model = Complaint
fields = [
'id', 'patient_name', 'patient_mrn', 'encounter_id',
'hospital_name', 'department_name', 'staff_name',
'title', 'category', 'subcategory',
'priority', 'severity', 'source_name', 'status',
'assigned_to_name', 'assigned_at',
'due_at', 'is_overdue', 'sla_status',
'resolution', 'resolved_at',
'closed_at',
'created_at', 'updated_at'
]
def get_staff_name(self, obj):
"""Get staff name"""
if obj.staff:
return f"{obj.staff.first_name} {obj.staff.last_name}"
return None
def get_assigned_to_name(self, obj):
"""Get assigned user name"""
if obj.assigned_to:
return obj.assigned_to.get_full_name()
return None
def get_sla_status(self, obj):
"""Get SLA status"""
return obj.sla_status if hasattr(obj, 'sla_status') else 'on_track'
class InquirySerializer(serializers.ModelSerializer):
"""Inquiry serializer"""
patient_name = serializers.CharField(source='patient.get_full_name', read_only=True)
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
department_name = serializers.CharField(source='department.name', read_only=True)
assigned_to_name = serializers.SerializerMethodField()
created_by_name = serializers.SerializerMethodField()
class Meta:
model = Inquiry
fields = [
'id', 'patient', 'patient_name',
'contact_name', 'contact_phone', 'contact_email',
'hospital', 'hospital_name', 'department', 'department_name',
'subject', 'message', 'category', 'source',
'created_by', 'created_by_name',
'assigned_to', 'assigned_to_name',
'response', 'responded_at', 'responded_by',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_by', 'responded_at', 'created_at', 'updated_at']
def get_assigned_to_name(self, obj):
"""Get assigned user name"""
if obj.assigned_to:
return obj.assigned_to.get_full_name()
return None
def get_created_by_name(self, obj):
"""Get creator name"""
if obj.created_by:
return obj.created_by.get_full_name()
return None