270 lines
12 KiB
Python
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
|
|
|