233 lines
11 KiB
Python
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.")
|
|
|