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