""" 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