HH/apps/integrations/serializers.py

224 lines
8.3 KiB
Python

"""
Integrations serializers
"""
from rest_framework import serializers
from .models import EventMapping, InboundEvent, IntegrationConfig, SurveyTemplateMapping
class InboundEventSerializer(serializers.ModelSerializer):
"""Inbound event serializer"""
class Meta:
model = InboundEvent
fields = [
'id', 'source_system', 'event_code', 'encounter_id', 'patient_identifier',
'payload_json', 'status', 'received_at', 'processed_at',
'error', 'processing_attempts',
'physician_license', 'department_code', 'metadata',
'created_at', 'updated_at'
]
read_only_fields = [
'id', 'status', 'received_at', 'processed_at',
'error', 'processing_attempts', 'metadata',
'created_at', 'updated_at'
]
class InboundEventCreateSerializer(serializers.ModelSerializer):
"""
Serializer for creating inbound events via API.
External systems POST to /api/integrations/events/ with:
{
"source_system": "his",
"event_code": "OPD_VISIT_COMPLETED",
"encounter_id": "ENC123456",
"patient_identifier": "MRN789",
"payload_json": {
"physician_license": "PHY001",
"department_code": "DEPT_OPD",
"timestamp": "2025-12-14T10:30:00Z",
...
}
}
"""
class Meta:
model = InboundEvent
fields = [
'source_system', 'event_code', 'encounter_id',
'patient_identifier', 'payload_json'
]
def create(self, validated_data):
"""
Create event and extract context from payload.
Event will be processed asynchronously by Celery task.
"""
payload = validated_data.get('payload_json', {})
# Extract physician and department from payload
validated_data['physician_license'] = payload.get('physician_license', '')
validated_data['department_code'] = payload.get('department_code', '')
event = InboundEvent.objects.create(**validated_data)
# Queue event for processing (will be implemented in tasks.py)
# from apps.integrations.tasks import process_inbound_event
# process_inbound_event.delay(event.id)
return event
class InboundEventListSerializer(serializers.ModelSerializer):
"""Simplified inbound event serializer for list views"""
class Meta:
model = InboundEvent
fields = [
'id', 'source_system', 'event_code', 'encounter_id',
'status', 'processing_attempts', 'received_at'
]
class EventMappingSerializer(serializers.ModelSerializer):
"""Event mapping serializer"""
integration_name = serializers.CharField(source='integration_config.name', read_only=True)
class Meta:
model = EventMapping
fields = [
'id', 'integration_config', 'integration_name',
'external_event_code', 'internal_event_code',
'field_mappings', 'is_active',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
class SurveyTemplateMappingSerializer(serializers.ModelSerializer):
"""Survey template mapping serializer"""
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
survey_template_name = serializers.CharField(source='survey_template.name', read_only=True)
patient_type_display = serializers.CharField(source='get_patient_type_display', read_only=True)
class Meta:
model = SurveyTemplateMapping
fields = [
'id', 'hospital', 'hospital_name',
'patient_type', 'patient_type_display',
'survey_template', 'survey_template_name',
'is_active',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
class IntegrationConfigSerializer(serializers.ModelSerializer):
"""Integration configuration serializer"""
event_mappings = EventMappingSerializer(many=True, read_only=True)
class Meta:
model = IntegrationConfig
fields = [
'id', 'name', 'source_system', 'description',
'api_url', 'is_active', 'config_json',
'event_mappings', 'last_sync_at',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'last_sync_at', 'created_at', 'updated_at']
extra_kwargs = {
'api_key': {'write_only': True} # Don't expose API key in responses
}
class HISPatientDemographicSerializer(serializers.Serializer):
"""Serializer for HIS patient demographic data"""
Type = serializers.CharField()
PatientID = serializers.CharField()
AdmissionID = serializers.CharField()
HospitalID = serializers.CharField(required=False, allow_blank=True)
HospitalName = serializers.CharField()
PatientType = serializers.CharField(required=False, allow_blank=True)
AdmitDate = serializers.CharField()
DischargeDate = serializers.CharField(required=False, allow_blank=True, allow_null=True)
RegCode = serializers.CharField(required=False, allow_blank=True)
SSN = serializers.CharField(required=False, allow_blank=True)
PatientName = serializers.CharField()
GenderID = serializers.CharField(required=False, allow_blank=True)
Gender = serializers.CharField(required=False, allow_blank=True)
FullAge = serializers.CharField(required=False, allow_blank=True)
PatientNationality = serializers.CharField(required=False, allow_blank=True)
MobileNo = serializers.CharField()
DOB = serializers.CharField(required=False, allow_blank=True)
ConsultantID = serializers.CharField(required=False, allow_blank=True)
PrimaryDoctor = serializers.CharField(required=False, allow_blank=True)
CompanyID = serializers.CharField(required=False, allow_blank=True)
GradeID = serializers.CharField(required=False, allow_blank=True)
CompanyName = serializers.CharField(required=False, allow_blank=True)
GradeName = serializers.CharField(required=False, allow_blank=True)
InsuranceCompanyName = serializers.CharField(required=False, allow_blank=True)
BillType = serializers.CharField(required=False, allow_blank=True)
IsVIP = serializers.CharField(required=False, allow_blank=True)
class HISVisitDataSerializer(serializers.Serializer):
"""Serializer for HIS visit/timeline data"""
Type = serializers.CharField()
BillDate = serializers.CharField()
class HISPatientDataSerializer(serializers.Serializer):
"""
Serializer for real HIS patient data format.
This validates the structure of HIS data received from the simulator
or actual HIS system.
Example structure:
{
"FetchPatientDataTimeStampList": [{...patient demographics...}],
"FetchPatientDataTimeStampVisitDataList": [
{"Type": "Consultation", "BillDate": "05-Jun-2025 11:06"},
...
],
"Code": 200,
"Status": "Success",
"Message": "",
"Message2L": "",
"MobileNo": "",
"ValidateMessage": ""
}
"""
FetchPatientDataTimeStampList = HISPatientDemographicSerializer(many=True)
FetchPatientDataTimeStampVisitDataList = HISVisitDataSerializer(many=True)
Code = serializers.IntegerField()
Status = serializers.CharField()
Message = serializers.CharField(required=False, allow_blank=True)
Message2L = serializers.CharField(required=False, allow_blank=True)
MobileNo = serializers.CharField(required=False, allow_blank=True)
ValidateMessage = serializers.CharField(required=False, allow_blank=True)
def validate(self, data):
"""Validate HIS data structure"""
# Validate status
if data.get('Code') != 200:
raise serializers.ValidationError(
f"HIS returned error code: {data.get('Code')}"
)
if data.get('Status') != 'Success':
raise serializers.ValidationError(
f"HIS status not successful: {data.get('Status')}"
)
# Ensure patient data exists
patient_list = data.get('FetchPatientDataTimeStampList', [])
if not patient_list:
raise serializers.ValidationError(
"No patient data found in FetchPatientDataTimeStampList"
)
return data