224 lines
8.3 KiB
Python
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
|