from rest_framework import serializers from ..models import ( ExternalSystem, IntegrationEndpoint, DataMapping, IntegrationExecution, WebhookEndpoint, WebhookExecution, IntegrationLog ) class BaseSerializer(serializers.ModelSerializer): """Base serializer with common functionality""" class Meta: fields = ['id'] read_only_fields = ['created_at', 'updated_at'] class ExternalSystemSerializer(serializers.ModelSerializer): """Serializer for ExternalSystem model""" system_type_display = serializers.CharField(source='get_system_type_display', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = ExternalSystem fields = [ 'system_id', 'name', 'description', 'system_type', 'system_type_display', 'base_url', 'api_version', 'authentication_type', 'credentials', 'timeout_seconds', 'retry_attempts', 'status', 'status_display', 'last_health_check', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['system_id', 'last_health_check', 'created_at', 'updated_at'] class IntegrationEndpointSerializer(serializers.ModelSerializer): """Serializer for IntegrationEndpoint model""" system_name = serializers.CharField(source='system.name', read_only=True) method_display = serializers.CharField(source='get_method_display', read_only=True) class Meta: model = IntegrationEndpoint fields = [ 'endpoint_id', 'system', 'system_name', 'name', 'description', 'endpoint_url', 'method', 'method_display', 'headers', 'request_template', 'response_mapping', 'timeout_seconds', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['endpoint_id', 'created_at', 'updated_at'] class DataMappingSerializer(serializers.ModelSerializer): """Serializer for DataMapping model""" endpoint_name = serializers.CharField(source='endpoint.name', read_only=True) mapping_type_display = serializers.CharField(source='get_mapping_type_display', read_only=True) class Meta: model = DataMapping fields = [ 'mapping_id', 'endpoint', 'endpoint_name', 'name', 'description', 'mapping_type', 'mapping_type_display', 'source_field', 'target_field', 'transformation_rules', 'is_required', 'default_value', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['mapping_id', 'created_at', 'updated_at'] class IntegrationExecutionSerializer(serializers.ModelSerializer): """Serializer for IntegrationExecution model""" endpoint_name = serializers.CharField(source='endpoint.name', read_only=True) system_name = serializers.CharField(source='endpoint.system.name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) duration_seconds = serializers.FloatField(read_only=True) class Meta: model = IntegrationExecution fields = [ 'execution_id', 'endpoint', 'endpoint_name', 'system_name', 'start_time', 'end_time', 'duration_seconds', 'status', 'status_display', 'request_data', 'response_data', 'error_message', 'retry_count', 'created_at', 'updated_at' ] read_only_fields = ['execution_id', 'duration_seconds', 'created_at', 'updated_at'] class WebhookEndpointSerializer(serializers.ModelSerializer): """Serializer for WebhookEndpoint model""" class Meta: model = WebhookEndpoint fields = [ 'webhook_id', 'name', 'description', 'url_path', 'secret_key', 'allowed_ips', 'event_types', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['webhook_id', 'created_at', 'updated_at'] class WebhookExecutionSerializer(serializers.ModelSerializer): """Serializer for WebhookExecution model""" webhook_name = serializers.CharField(source='webhook.name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = WebhookExecution fields = [ 'execution_id', 'webhook', 'webhook_name', 'event_type', 'payload', 'headers', 'source_ip', 'status', 'status_display', 'response_data', 'error_message', 'processed_at', 'created_at', 'updated_at' ] read_only_fields = ['execution_id', 'created_at', 'updated_at'] class IntegrationLogSerializer(serializers.ModelSerializer): """Serializer for IntegrationLog model""" level_display = serializers.CharField(source='get_level_display', read_only=True) class Meta: model = IntegrationLog fields = [ 'log_id', 'level', 'level_display', 'message', 'details', 'execution', 'webhook_execution', 'created_at', 'updated_at' ] read_only_fields = ['log_id', 'created_at', 'updated_at'] class IntegrationStatsSerializer(serializers.Serializer): """Serializer for integration statistics""" total_systems = serializers.IntegerField() active_systems = serializers.IntegerField() total_endpoints = serializers.IntegerField() executions_today = serializers.IntegerField() successful_executions = serializers.IntegerField() failed_executions = serializers.IntegerField() avg_response_time = serializers.FloatField() webhook_executions = serializers.IntegerField() system_health = serializers.DictField() execution_trends = serializers.ListField() class SystemTestSerializer(serializers.Serializer): """Serializer for testing external systems""" system_id = serializers.IntegerField() test_endpoint = serializers.CharField(required=False, allow_blank=True) def validate_system_id(self, value): """Validate that the system exists""" try: ExternalSystem.objects.get(id=value) return value except ExternalSystem.DoesNotExist: raise serializers.ValidationError("Invalid system ID.") class EndpointExecuteSerializer(serializers.Serializer): """Serializer for executing integration endpoints""" endpoint_id = serializers.IntegerField() request_data = serializers.JSONField(required=False) override_timeout = serializers.IntegerField(required=False, min_value=1, max_value=300) def validate_endpoint_id(self, value): """Validate that the endpoint exists and is active""" try: endpoint = IntegrationEndpoint.objects.get(id=value) if not endpoint.is_active: raise serializers.ValidationError("Endpoint is not active.") return value except IntegrationEndpoint.DoesNotExist: raise serializers.ValidationError("Invalid endpoint ID.") class WebhookCreateSerializer(serializers.Serializer): """Serializer for creating webhooks""" name = serializers.CharField() description = serializers.CharField(required=False, allow_blank=True) event_types = serializers.ListField( child=serializers.CharField(), min_length=1 ) allowed_ips = serializers.ListField( child=serializers.IPAddressField(), required=False ) def validate_event_types(self, value): """Validate event types""" valid_events = [ 'PATIENT_CREATED', 'PATIENT_UPDATED', 'APPOINTMENT_SCHEDULED', 'LAB_RESULT_AVAILABLE', 'BILLING_INVOICE_CREATED', 'ALERT_TRIGGERED' ] for event in value: if event not in valid_events: raise serializers.ValidationError(f"Invalid event type: {event}") return value class DataSyncSerializer(serializers.Serializer): """Serializer for data synchronization""" system_id = serializers.IntegerField() sync_type = serializers.ChoiceField(choices=['FULL', 'INCREMENTAL']) entity_types = serializers.ListField( child=serializers.CharField(), min_length=1 ) start_date = serializers.DateTimeField(required=False) end_date = serializers.DateTimeField(required=False) def validate_entity_types(self, value): """Validate entity types""" valid_entities = [ 'PATIENTS', 'APPOINTMENTS', 'LAB_RESULTS', 'MEDICATIONS', 'BILLING', 'INVENTORY', 'EMPLOYEES' ] for entity in value: if entity not in valid_entities: raise serializers.ValidationError(f"Invalid entity type: {entity}") return value def validate(self, data): """Validate sync parameters""" if data['sync_type'] == 'INCREMENTAL': if not data.get('start_date'): raise serializers.ValidationError( "Start date is required for incremental sync." ) if data.get('start_date') and data.get('end_date'): if data['end_date'] <= data['start_date']: raise serializers.ValidationError("End date must be after start date.") return data class MappingTestSerializer(serializers.Serializer): """Serializer for testing data mappings""" mapping_id = serializers.IntegerField() test_data = serializers.JSONField() def validate_mapping_id(self, value): """Validate that the mapping exists and is active""" try: mapping = DataMapping.objects.get(id=value) if not mapping.is_active: raise serializers.ValidationError("Data mapping is not active.") return value except DataMapping.DoesNotExist: raise serializers.ValidationError("Invalid mapping ID.") class SystemHealthCheckSerializer(serializers.Serializer): """Serializer for system health checks""" system_ids = serializers.ListField( child=serializers.IntegerField(), required=False ) include_endpoints = serializers.BooleanField(default=True) def validate_system_ids(self, value): """Validate system IDs""" if value: valid_systems = ExternalSystem.objects.filter(id__in=value).count() if valid_systems != len(value): raise serializers.ValidationError("Some system IDs are invalid.") return value class IntegrationConfigSerializer(serializers.Serializer): """Serializer for integration configuration""" system_id = serializers.IntegerField() configuration = serializers.JSONField() test_connection = serializers.BooleanField(default=True) def validate_system_id(self, value): """Validate that the system exists""" try: ExternalSystem.objects.get(id=value) return value except ExternalSystem.DoesNotExist: raise serializers.ValidationError("Invalid system ID.") class BulkExecutionSerializer(serializers.Serializer): """Serializer for bulk endpoint execution""" endpoint_ids = serializers.ListField( child=serializers.IntegerField(), min_length=1, max_length=10 ) request_data = serializers.JSONField(required=False) parallel_execution = serializers.BooleanField(default=True) def validate_endpoint_ids(self, value): """Validate endpoint IDs""" active_endpoints = IntegrationEndpoint.objects.filter( id__in=value, is_active=True ).count() if active_endpoints != len(value): raise serializers.ValidationError("Some endpoint IDs are invalid or inactive.") return value