261 lines
9.2 KiB
Python
261 lines
9.2 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()
|
|
PatientType = serializers.CharField(required=False, allow_blank=True)
|
|
AdmissionID = serializers.CharField(required=False, allow_blank=True)
|
|
PatientID = serializers.CharField(required=False, allow_blank=True)
|
|
RegCode = serializers.CharField(required=False, allow_blank=True)
|
|
SSN = serializers.CharField(required=False, allow_blank=True)
|
|
MobileNo = serializers.CharField(required=False, allow_blank=True)
|
|
|
|
|
|
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...}],
|
|
"FetchPatientDataTimeStampVisitEDDataList": [...],
|
|
"FetchPatientDataTimeStampVisitIPDataList": [...],
|
|
"FetchPatientDataTimeStampVisitOPDataList": [...],
|
|
"Code": 200,
|
|
"Status": "Success",
|
|
"Message": "",
|
|
"Message2L": "",
|
|
"MobileNo": "",
|
|
"ValidateMessage": ""
|
|
}
|
|
"""
|
|
|
|
FetchPatientDataTimeStampList = HISPatientDemographicSerializer(many=True)
|
|
FetchPatientDataTimeStampVisitEDDataList = HISVisitDataSerializer(many=True, required=False)
|
|
FetchPatientDataTimeStampVisitIPDataList = HISVisitDataSerializer(many=True, required=False)
|
|
FetchPatientDataTimeStampVisitOPDataList = HISVisitDataSerializer(many=True, required=False)
|
|
FetchPatientDataTimeStampVisitDataList = HISVisitDataSerializer(many=True, required=False)
|
|
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
|