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

233 lines
11 KiB
Python

from rest_framework import serializers
from ..models import LabTest, LabOrder, Specimen, LabResult, QualityControl, ReferenceRange
class BaseSerializer(serializers.ModelSerializer):
"""Base serializer with common functionality"""
class Meta:
fields = ['id']
read_only_fields = ['created_at', 'updated_at']
class LabTestSerializer(serializers.ModelSerializer):
"""Serializer for LabTest model"""
category_display = serializers.CharField(source='get_category_display', read_only=True)
specimen_type_display = serializers.CharField(source='get_specimen_type_display', read_only=True)
class Meta:
model = LabTest
fields = [
'test_id', 'code', 'name', 'description', 'category', 'category_display',
'specimen_type', 'specimen_type_display', 'specimen_volume',
'collection_instructions', 'processing_instructions', 'methodology',
'turnaround_time_hours', 'critical_value_low', 'critical_value_high',
'units', 'reference_range_text', 'interpretation_notes',
'requires_fasting', 'temperature_requirements', 'stability_hours',
'cost', 'cpt_code', 'loinc_code', 'is_active', 'created_at', 'updated_at'
]
read_only_fields = ['test_id', 'created_at', 'updated_at']
class LabOrderSerializer(serializers.ModelSerializer):
"""Serializer for LabOrder model"""
patient_name = serializers.CharField(source='patient.get_full_name', read_only=True)
patient_mrn = serializers.CharField(source='patient.mrn', read_only=True)
ordering_provider_name = serializers.CharField(source='ordering_provider.get_full_name', 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)
class Meta:
model = LabOrder
fields = [
'order_id', 'order_number', 'patient', 'patient_name', 'patient_mrn',
'encounter', 'ordering_provider', 'ordering_provider_name',
'order_date', 'collection_scheduled_date', 'collection_date',
'collected_by', 'status', 'status_display', 'priority', 'priority_display',
'clinical_info', 'diagnosis_codes', 'fasting_required', 'special_instructions',
'collection_location', 'external_order_id', 'insurance_authorization',
'estimated_cost', 'notes', 'created_at', 'updated_at'
]
read_only_fields = ['order_id', 'order_number', 'created_at', 'updated_at']
class SpecimenSerializer(serializers.ModelSerializer):
"""Serializer for Specimen model"""
lab_order_number = serializers.CharField(source='lab_order.order_number', read_only=True)
patient_name = serializers.CharField(source='lab_order.patient.get_full_name', read_only=True)
specimen_type_display = serializers.CharField(source='get_specimen_type_display', read_only=True)
status_display = serializers.CharField(source='get_status_display', read_only=True)
collected_by_name = serializers.CharField(source='collected_by.get_full_name', read_only=True)
received_by_name = serializers.CharField(source='received_by.get_full_name', read_only=True)
class Meta:
model = Specimen
fields = [
'specimen_id', 'specimen_number', 'lab_order', 'lab_order_number',
'patient_name', 'specimen_type', 'specimen_type_display',
'collection_date', 'collection_time', 'collected_by', 'collected_by_name',
'collection_site', 'collection_method', 'container_type',
'volume_collected', 'received_date', 'received_by', 'received_by_name',
'processing_started_date', 'processed_by', 'status', 'status_display',
'rejection_reason', 'rejected_by', 'rejected_date', 'storage_location',
'temperature_log', 'chain_of_custody', 'comments', 'created_at', 'updated_at'
]
read_only_fields = ['specimen_id', 'specimen_number', 'created_at', 'updated_at']
class ReferenceRangeSerializer(serializers.ModelSerializer):
"""Serializer for ReferenceRange model"""
lab_test_name = serializers.CharField(source='lab_test.name', read_only=True)
class Meta:
model = ReferenceRange
fields = [
'range_id', 'lab_test', 'lab_test_name', 'age_min', 'age_max',
'gender', 'reference_low', 'reference_high', 'critical_low',
'critical_high', 'units', 'population', 'methodology',
'effective_date', 'expiration_date', 'is_active',
'created_at', 'updated_at'
]
read_only_fields = ['range_id', 'created_at', 'updated_at']
class LabResultSerializer(serializers.ModelSerializer):
"""Serializer for LabResult model"""
lab_order_number = serializers.CharField(source='lab_order.order_number', read_only=True)
patient_name = serializers.CharField(source='lab_order.patient.get_full_name', read_only=True)
test_name = serializers.CharField(source='lab_test.name', read_only=True)
specimen_number = serializers.CharField(source='specimen.specimen_number', read_only=True)
status_display = serializers.CharField(source='get_status_display', read_only=True)
result_status_display = serializers.CharField(source='get_result_status_display', read_only=True)
performed_by_name = serializers.CharField(source='performed_by.get_full_name', read_only=True)
verified_by_name = serializers.CharField(source='verified_by.get_full_name', read_only=True)
is_critical = serializers.BooleanField(read_only=True)
is_abnormal = serializers.BooleanField(read_only=True)
class Meta:
model = LabResult
fields = [
'result_id', 'lab_order', 'lab_order_number', 'patient_name',
'lab_test', 'test_name', 'specimen', 'specimen_number',
'result_value', 'result_text', 'units', 'reference_range',
'abnormal_flag', 'critical_flag', 'status', 'status_display',
'result_status', 'result_status_display', 'performed_date',
'performed_by', 'performed_by_name', 'verified_date',
'verified_by', 'verified_by_name', 'instrument_id',
'method_used', 'dilution_factor', 'quality_control_passed',
'comments', 'interpretation', 'is_critical', 'is_abnormal',
'created_at', 'updated_at'
]
read_only_fields = [
'result_id', 'is_critical', 'is_abnormal', 'created_at', 'updated_at'
]
class QualityControlSerializer(serializers.ModelSerializer):
"""Serializer for QualityControl model"""
lab_test_name = serializers.CharField(source='lab_test.name', read_only=True)
control_type_display = serializers.CharField(source='get_control_type_display', read_only=True)
status_display = serializers.CharField(source='get_status_display', read_only=True)
performed_by_name = serializers.CharField(source='performed_by.get_full_name', read_only=True)
class Meta:
model = QualityControl
fields = [
'qc_id', 'lab_test', 'lab_test_name', 'control_type', 'control_type_display',
'control_lot', 'control_level', 'expected_value', 'acceptable_range_low',
'acceptable_range_high', 'measured_value', 'run_date', 'performed_by',
'performed_by_name', 'instrument_id', 'status', 'status_display',
'deviation_reason', 'corrective_action', 'comments',
'created_at', 'updated_at'
]
read_only_fields = ['qc_id', 'created_at', 'updated_at']
class LabStatsSerializer(serializers.Serializer):
"""Serializer for laboratory statistics"""
total_orders = serializers.IntegerField()
pending_orders = serializers.IntegerField()
completed_today = serializers.IntegerField()
specimens_collected = serializers.IntegerField()
results_pending = serializers.IntegerField()
critical_results = serializers.IntegerField()
turnaround_time_avg = serializers.FloatField()
qc_pass_rate = serializers.FloatField()
order_types = serializers.DictField()
status_breakdown = serializers.DictField()
class SpecimenCollectionSerializer(serializers.Serializer):
"""Serializer for specimen collection"""
order_id = serializers.IntegerField()
specimen_type = serializers.CharField()
collection_site = serializers.CharField()
collection_method = serializers.CharField()
container_type = serializers.CharField()
volume_collected = serializers.DecimalField(max_digits=8, decimal_places=2)
comments = serializers.CharField(required=False, allow_blank=True)
def validate_order_id(self, value):
"""Validate that the order exists and can have specimens collected"""
try:
order = LabOrder.objects.get(id=value)
if order.status not in ['PENDING', 'SCHEDULED']:
raise serializers.ValidationError(
"Cannot collect specimen for order with current status."
)
return value
except LabOrder.DoesNotExist:
raise serializers.ValidationError("Invalid order ID.")
class ResultEntrySerializer(serializers.Serializer):
"""Serializer for entering lab results"""
specimen_id = serializers.IntegerField()
lab_test_id = serializers.IntegerField()
result_value = serializers.CharField(required=False, allow_blank=True)
result_text = serializers.CharField(required=False, allow_blank=True)
abnormal_flag = serializers.CharField(required=False, allow_blank=True)
critical_flag = serializers.BooleanField(default=False)
instrument_id = serializers.CharField(required=False, allow_blank=True)
method_used = serializers.CharField(required=False, allow_blank=True)
comments = serializers.CharField(required=False, allow_blank=True)
def validate(self, data):
"""Validate that either result_value or result_text is provided"""
if not data.get('result_value') and not data.get('result_text'):
raise serializers.ValidationError(
"Either result_value or result_text must be provided."
)
return data
def validate_specimen_id(self, value):
"""Validate that the specimen exists and is ready for results"""
try:
specimen = Specimen.objects.get(id=value)
if specimen.status != 'PROCESSING':
raise serializers.ValidationError(
"Specimen must be in processing status to enter results."
)
return value
except Specimen.DoesNotExist:
raise serializers.ValidationError("Invalid specimen ID.")
class ResultVerificationSerializer(serializers.Serializer):
"""Serializer for verifying lab results"""
result_id = serializers.IntegerField()
verification_comments = serializers.CharField(required=False, allow_blank=True)
def validate_result_id(self, value):
"""Validate that the result exists and can be verified"""
try:
result = LabResult.objects.get(id=value)
if result.status != 'PENDING_VERIFICATION':
raise serializers.ValidationError(
"Result must be pending verification to verify."
)
return value
except LabResult.DoesNotExist:
raise serializers.ValidationError("Invalid result ID.")