2025-08-12 13:33:25 +03:00

270 lines
12 KiB
Python

from rest_framework import serializers
from ..models import (
OperatingRoom, ORBlock, SurgicalCase, SurgicalNote,
EquipmentUsage, SurgicalNoteTemplate
)
class BaseSerializer(serializers.ModelSerializer):
"""Base serializer with common functionality"""
class Meta:
fields = ['id']
read_only_fields = ['created_at', 'updated_at']
class OperatingRoomSerializer(serializers.ModelSerializer):
"""Serializer for OperatingRoom model"""
room_type_display = serializers.CharField(source='get_room_type_display', read_only=True)
status_display = serializers.CharField(source='get_status_display', read_only=True)
current_utilization = serializers.FloatField(read_only=True)
class Meta:
model = OperatingRoom
fields = [
'room_id', 'room_number', 'name', 'room_type', 'room_type_display',
'floor', 'building', 'capacity', 'length', 'width', 'height',
'status', 'status_display', 'equipment_list', 'capabilities',
'special_features', 'ventilation_type', 'lighting_type',
'temperature_range', 'humidity_range', 'last_cleaned',
'next_maintenance', 'is_active', 'current_utilization',
'created_at', 'updated_at'
]
read_only_fields = ['room_id', 'current_utilization', 'created_at', 'updated_at']
class ORBlockSerializer(serializers.ModelSerializer):
"""Serializer for ORBlock model"""
operating_room_number = serializers.CharField(source='operating_room.room_number', read_only=True)
primary_surgeon_name = serializers.CharField(source='primary_surgeon.get_full_name', read_only=True)
utilization_percentage = serializers.FloatField(read_only=True)
class Meta:
model = ORBlock
fields = [
'block_id', 'operating_room', 'operating_room_number', 'date',
'start_time', 'end_time', 'primary_surgeon', 'primary_surgeon_name',
'block_type', 'specialty', 'allocated_minutes', 'used_minutes',
'utilization_percentage', 'is_emergency_block', 'notes',
'created_at', 'updated_at'
]
read_only_fields = ['block_id', 'utilization_percentage', 'created_at', 'updated_at']
class SurgicalCaseSerializer(serializers.ModelSerializer):
"""Serializer for SurgicalCase model"""
patient_name = serializers.CharField(source='patient.get_full_name', read_only=True)
patient_mrn = serializers.CharField(source='patient.mrn', read_only=True)
primary_surgeon_name = serializers.CharField(source='primary_surgeon.get_full_name', read_only=True)
operating_room_number = serializers.CharField(source='operating_room.room_number', read_only=True)
status_display = serializers.CharField(source='get_status_display', read_only=True)
priority_display = serializers.CharField(source='get_priority_display', read_only=True)
case_type_display = serializers.CharField(source='get_case_type_display', read_only=True)
duration_minutes = serializers.IntegerField(read_only=True)
class Meta:
model = SurgicalCase
fields = [
'case_id', 'case_number', 'patient', 'patient_name', 'patient_mrn',
'primary_surgeon', 'primary_surgeon_name', 'assisting_surgeons',
'anesthesiologist', 'scrub_nurse', 'circulating_nurse',
'operating_room', 'operating_room_number', 'or_block',
'scheduled_date', 'scheduled_start_time', 'scheduled_end_time',
'actual_start_time', 'actual_end_time', 'duration_minutes',
'procedure_name', 'procedure_codes', 'case_type', 'case_type_display',
'priority', 'priority_display', 'status', 'status_display',
'anesthesia_type', 'position', 'special_equipment',
'estimated_blood_loss', 'complications', 'postop_destination',
'notes', 'created_at', 'updated_at'
]
read_only_fields = ['case_id', 'case_number', 'duration_minutes', 'created_at', 'updated_at']
class SurgicalNoteTemplateSerializer(serializers.ModelSerializer):
"""Serializer for SurgicalNoteTemplate model"""
class Meta:
model = SurgicalNoteTemplate
fields = [
'template_id', 'name', 'description', 'procedure_type', 'specialty',
'template_content', 'sections', 'required_fields', 'is_active',
'created_by', 'created_at', 'updated_at'
]
read_only_fields = ['template_id', 'created_at', 'updated_at']
class SurgicalNoteSerializer(serializers.ModelSerializer):
"""Serializer for SurgicalNote model"""
surgical_case_number = serializers.CharField(source='surgical_case.case_number', read_only=True)
patient_name = serializers.CharField(source='surgical_case.patient.get_full_name', read_only=True)
surgeon_name = serializers.CharField(source='surgeon.get_full_name', read_only=True)
note_type_display = serializers.CharField(source='get_note_type_display', read_only=True)
class Meta:
model = SurgicalNote
fields = [
'note_id', 'surgical_case', 'surgical_case_number', 'patient_name',
'template', 'surgeon', 'surgeon_name', 'note_type', 'note_type_display',
'preoperative_diagnosis', 'postoperative_diagnosis', 'procedure_performed',
'indications', 'findings', 'technique', 'complications',
'estimated_blood_loss', 'specimens', 'implants', 'drains',
'closure', 'postoperative_plan', 'dictated_date', 'transcribed_date',
'signed_date', 'is_signed', 'electronic_signature',
'created_at', 'updated_at'
]
read_only_fields = ['note_id', 'created_at', 'updated_at']
class EquipmentUsageSerializer(serializers.ModelSerializer):
"""Serializer for EquipmentUsage model"""
surgical_case_number = serializers.CharField(source='surgical_case.case_number', read_only=True)
used_by_name = serializers.CharField(source='used_by.get_full_name', read_only=True)
class Meta:
model = EquipmentUsage
fields = [
'usage_id', 'surgical_case', 'surgical_case_number', 'equipment_name',
'equipment_id', 'serial_number', 'start_time', 'end_time',
'duration_minutes', 'used_by', 'used_by_name', 'status',
'maintenance_required', 'issues_reported', 'notes',
'created_at', 'updated_at'
]
read_only_fields = ['usage_id', 'duration_minutes', 'created_at', 'updated_at']
class ORStatsSerializer(serializers.Serializer):
"""Serializer for operating room statistics"""
total_cases = serializers.IntegerField()
cases_today = serializers.IntegerField()
emergency_cases = serializers.IntegerField()
completed_cases = serializers.IntegerField()
cancelled_cases = serializers.IntegerField()
average_duration = serializers.FloatField()
room_utilization = serializers.DictField()
surgeon_productivity = serializers.ListField()
case_types = serializers.DictField()
status_breakdown = serializers.DictField()
class CaseSchedulingSerializer(serializers.Serializer):
"""Serializer for scheduling surgical cases"""
patient_id = serializers.IntegerField()
primary_surgeon_id = serializers.IntegerField()
operating_room_id = serializers.IntegerField()
scheduled_date = serializers.DateField()
scheduled_start_time = serializers.TimeField()
estimated_duration = serializers.IntegerField()
procedure_name = serializers.CharField()
procedure_codes = serializers.CharField()
case_type = serializers.CharField()
priority = serializers.CharField()
anesthesia_type = serializers.CharField()
special_equipment = serializers.CharField(required=False, allow_blank=True)
notes = serializers.CharField(required=False, allow_blank=True)
def validate_estimated_duration(self, value):
"""Validate estimated duration"""
if value <= 0:
raise serializers.ValidationError("Estimated duration must be greater than 0.")
if value > 720: # 12 hours
raise serializers.ValidationError("Estimated duration cannot exceed 12 hours.")
return value
class CaseStartSerializer(serializers.Serializer):
"""Serializer for starting surgical cases"""
case_id = serializers.IntegerField()
anesthesiologist_id = serializers.IntegerField(required=False)
scrub_nurse_id = serializers.IntegerField(required=False)
circulating_nurse_id = serializers.IntegerField(required=False)
position = serializers.CharField(required=False, allow_blank=True)
notes = serializers.CharField(required=False, allow_blank=True)
def validate_case_id(self, value):
"""Validate that the case exists and can be started"""
try:
case = SurgicalCase.objects.get(id=value)
if case.status not in ['SCHEDULED', 'PATIENT_IN_ROOM']:
raise serializers.ValidationError(
"Case cannot be started with current status."
)
return value
except SurgicalCase.DoesNotExist:
raise serializers.ValidationError("Invalid case ID.")
class CaseCompletionSerializer(serializers.Serializer):
"""Serializer for completing surgical cases"""
case_id = serializers.IntegerField()
estimated_blood_loss = serializers.IntegerField(required=False)
complications = serializers.CharField(required=False, allow_blank=True)
postop_destination = serializers.CharField(required=False, allow_blank=True)
notes = serializers.CharField(required=False, allow_blank=True)
def validate_case_id(self, value):
"""Validate that the case exists and can be completed"""
try:
case = SurgicalCase.objects.get(id=value)
if case.status != 'IN_PROGRESS':
raise serializers.ValidationError(
"Case must be in progress to complete."
)
return value
except SurgicalCase.DoesNotExist:
raise serializers.ValidationError("Invalid case ID.")
class SurgicalNoteDictationSerializer(serializers.Serializer):
"""Serializer for dictating surgical notes"""
case_id = serializers.IntegerField()
template_id = serializers.IntegerField(required=False)
note_type = serializers.CharField()
preoperative_diagnosis = serializers.CharField()
postoperative_diagnosis = serializers.CharField()
procedure_performed = serializers.CharField()
indications = serializers.CharField()
findings = serializers.CharField()
technique = serializers.CharField()
complications = serializers.CharField(required=False, allow_blank=True)
estimated_blood_loss = serializers.IntegerField(required=False)
specimens = serializers.CharField(required=False, allow_blank=True)
implants = serializers.CharField(required=False, allow_blank=True)
drains = serializers.CharField(required=False, allow_blank=True)
closure = serializers.CharField()
postoperative_plan = serializers.CharField()
def validate_case_id(self, value):
"""Validate that the case exists and can have notes"""
try:
case = SurgicalCase.objects.get(id=value)
if case.status not in ['IN_PROGRESS', 'COMPLETED']:
raise serializers.ValidationError(
"Case must be in progress or completed to create notes."
)
return value
except SurgicalCase.DoesNotExist:
raise serializers.ValidationError("Invalid case ID.")
class EquipmentTrackingSerializer(serializers.Serializer):
"""Serializer for tracking equipment usage"""
case_id = serializers.IntegerField()
equipment_name = serializers.CharField()
equipment_id = serializers.CharField()
serial_number = serializers.CharField(required=False, allow_blank=True)
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField(required=False)
maintenance_required = serializers.BooleanField(default=False)
issues_reported = serializers.CharField(required=False, allow_blank=True)
notes = serializers.CharField(required=False, allow_blank=True)
def validate(self, data):
"""Validate equipment tracking data"""
if data.get('end_time') and data.get('start_time'):
if data['end_time'] <= data['start_time']:
raise serializers.ValidationError(
"End time must be after start time."
)
return data