2025-08-12 13:33:25 +03:00

806 lines
24 KiB
Python

"""
Integration app admin configuration.
"""
from django.contrib import admin
from django.utils.html import format_html
from django.urls import reverse
from django.utils.safestring import mark_safe
from decimal import Decimal
from datetime import datetime, timedelta
from .models import (
ExternalSystem, IntegrationEndpoint, DataMapping,
IntegrationExecution, WebhookEndpoint, WebhookExecution,
IntegrationLog
)
class IntegrationEndpointInline(admin.TabularInline):
"""
Inline admin for integration endpoints.
"""
model = IntegrationEndpoint
extra = 0
fields = [
'name', 'endpoint_type', 'direction',
'is_active', 'execution_count', 'success_rate_display'
]
readonly_fields = [
'execution_count', 'success_count', 'failure_count',
'last_executed_at', 'success_rate_display'
]
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
class WebhookEndpointInline(admin.TabularInline):
"""
Inline admin for webhook endpoints.
"""
model = WebhookEndpoint
extra = 0
fields = [
'name', 'url_path', 'authentication_type',
'is_active', 'request_count', 'success_rate_display'
]
readonly_fields = [
'request_count', 'success_count', 'failure_count',
'last_request_at', 'success_rate_display'
]
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
class IntegrationLogInline(admin.TabularInline):
"""
Inline admin for integration logs.
"""
model = IntegrationLog
extra = 0
fields = [
'level', 'category', 'message_short',
'timestamp'
]
readonly_fields = [
'level', 'category', 'message_short', 'timestamp'
]
def message_short(self, obj):
"""Display shortened message."""
return obj.message[:50] + "..." if len(obj.message) > 50 else obj.message
message_short.short_description = 'Message'
@admin.register(ExternalSystem)
class ExternalSystemAdmin(admin.ModelAdmin):
"""
Admin interface for external systems.
"""
list_display = [
'name', 'system_type', 'vendor',
'health_status_display', 'success_rate_display',
'connection_count', 'last_used_at', 'is_active'
]
list_filter = [
'tenant', 'system_type', 'authentication_type',
'is_active', 'is_healthy', 'vendor'
]
search_fields = [
'name', 'description', 'vendor', 'base_url', 'host'
]
readonly_fields = [
'system_id', 'is_healthy', 'last_health_check',
'connection_count', 'success_count', 'failure_count',
'last_used_at', 'created_at', 'updated_at'
]
fieldsets = [
('System Information', {
'fields': [
'system_id', 'tenant', 'name', 'description'
]
}),
('System Type', {
'fields': [
'system_type', 'vendor', 'version'
]
}),
('Connection Details', {
'fields': [
'base_url', 'host', 'port', 'database_name'
]
}),
('Authentication', {
'fields': [
'authentication_type', 'authentication_config'
]
}),
('Configuration', {
'fields': [
'configuration', 'timeout_seconds', 'retry_attempts', 'retry_delay_seconds'
]
}),
('Health Monitoring', {
'fields': [
'is_healthy', 'last_health_check', 'health_check_interval'
]
}),
('System Status', {
'fields': [
'is_active'
]
}),
('Usage Tracking', {
'fields': [
'connection_count', 'success_count', 'failure_count', 'last_used_at'
],
'classes': ['collapse']
}),
('Metadata', {
'fields': [
'created_at', 'updated_at', 'created_by'
],
'classes': ['collapse']
})
]
inlines = [IntegrationEndpointInline, WebhookEndpointInline, IntegrationLogInline]
date_hierarchy = 'last_used_at'
def health_status_display(self, obj):
"""Display health status with color coding."""
if obj.is_healthy:
return format_html('<span style="color: green;">✓ Healthy</span>')
return format_html('<span style="color: red;">✗ Unhealthy</span>')
health_status_display.short_description = 'Health'
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(tenant=request.user.tenant)
return qs.select_related('created_by')
class DataMappingInline(admin.TabularInline):
"""
Inline admin for data mappings.
"""
model = DataMapping
extra = 0
fields = [
'name', 'mapping_type', 'source_field',
'target_field', 'transformation_type', 'is_active'
]
readonly_fields = [
'usage_count', 'success_count', 'failure_count', 'last_used_at'
]
class IntegrationExecutionInline(admin.TabularInline):
"""
Inline admin for integration executions.
"""
model = IntegrationExecution
extra = 0
fields = [
'execution_type', 'status', 'started_at',
'completed_at', 'processing_time_ms'
]
readonly_fields = [
'execution_id', 'started_at', 'completed_at',
'processing_time_ms', 'network_time_ms'
]
@admin.register(IntegrationEndpoint)
class IntegrationEndpointAdmin(admin.ModelAdmin):
"""
Admin interface for integration endpoints.
"""
list_display = [
'name', 'external_system_name', 'endpoint_type',
'direction', 'success_rate_display',
'execution_count', 'last_executed_at', 'is_active'
]
list_filter = [
'external_system__tenant', 'endpoint_type', 'direction',
'method', 'is_active', 'external_system__system_type'
]
search_fields = [
'name', 'description', 'path', 'external_system__name'
]
readonly_fields = [
'endpoint_id', 'execution_count', 'success_count',
'failure_count', 'last_executed_at', 'created_at', 'updated_at'
]
fieldsets = [
('Endpoint Information', {
'fields': [
'endpoint_id', 'external_system', 'name', 'description'
]
}),
('Endpoint Type', {
'fields': [
'endpoint_type', 'direction'
]
}),
('Endpoint Details', {
'fields': [
'path', 'method'
]
}),
('Configuration', {
'fields': [
'headers', 'parameters', 'request_format', 'response_format'
]
}),
('Data Mapping', {
'fields': [
'request_mapping', 'response_mapping'
]
}),
('Validation', {
'fields': [
'request_schema', 'response_schema'
]
}),
('Endpoint Status', {
'fields': [
'is_active'
]
}),
('Usage Tracking', {
'fields': [
'execution_count', 'success_count', 'failure_count', 'last_executed_at'
],
'classes': ['collapse']
}),
('Metadata', {
'fields': [
'created_at', 'updated_at', 'created_by'
],
'classes': ['collapse']
})
]
inlines = [DataMappingInline, IntegrationExecutionInline]
def external_system_name(self, obj):
"""Display external system name."""
return obj.external_system.name
external_system_name.short_description = 'External System'
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(external_system__tenant=request.user.tenant)
return qs.select_related('external_system', 'created_by')
@admin.register(DataMapping)
class DataMappingAdmin(admin.ModelAdmin):
"""
Admin interface for data mappings.
"""
list_display = [
'name', 'endpoint_name', 'mapping_type',
'source_field', 'target_field', 'transformation_type',
'success_rate_display', 'usage_count', 'is_active'
]
list_filter = [
'endpoint__external_system__tenant', 'mapping_type',
'transformation_type', 'is_required', 'is_active'
]
search_fields = [
'name', 'description', 'source_field', 'target_field',
'endpoint__name', 'endpoint__external_system__name'
]
readonly_fields = [
'mapping_id', 'usage_count', 'success_count',
'failure_count', 'last_used_at', 'created_at', 'updated_at'
]
fieldsets = [
('Mapping Information', {
'fields': [
'mapping_id', 'endpoint', 'name', 'description'
]
}),
('Mapping Type', {
'fields': [
'mapping_type'
]
}),
('Source Configuration', {
'fields': [
'source_field', 'source_format', 'source_validation'
]
}),
('Target Configuration', {
'fields': [
'target_field', 'target_format', 'target_validation'
]
}),
('Transformation', {
'fields': [
'transformation_type', 'transformation_config'
]
}),
('Validation Rules', {
'fields': [
'is_required', 'validation_rules', 'default_value'
]
}),
('Mapping Status', {
'fields': [
'is_active'
]
}),
('Usage Tracking', {
'fields': [
'usage_count', 'success_count', 'failure_count', 'last_used_at'
],
'classes': ['collapse']
}),
('Metadata', {
'fields': [
'created_at', 'updated_at', 'created_by'
],
'classes': ['collapse']
})
]
def endpoint_name(self, obj):
"""Display endpoint name."""
return f"{obj.endpoint.external_system.name} - {obj.endpoint.name}"
endpoint_name.short_description = 'Endpoint'
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(endpoint__external_system__tenant=request.user.tenant)
return qs.select_related('endpoint__external_system', 'created_by')
@admin.register(IntegrationExecution)
class IntegrationExecutionAdmin(admin.ModelAdmin):
"""
Admin interface for integration executions.
"""
list_display = [
'endpoint_name', 'execution_type', 'status',
'started_at', 'duration_display',
'processing_time_ms', 'retry_count'
]
list_filter = [
'endpoint__external_system__tenant', 'execution_type',
'status', 'started_at', 'retry_count'
]
search_fields = [
'endpoint__name', 'endpoint__external_system__name',
'external_id', 'correlation_id', 'error_message'
]
readonly_fields = [
'execution_id', 'started_at', 'completed_at',
'processing_time_ms', 'network_time_ms',
'request_size_bytes', 'response_size_bytes'
]
fieldsets = [
('Execution Information', {
'fields': [
'execution_id', 'endpoint', 'execution_type'
]
}),
('Execution Status', {
'fields': [
'status'
]
}),
('Timing', {
'fields': [
'started_at', 'completed_at'
]
}),
('Request/Response', {
'fields': [
'request_data', 'response_data', 'request_size_bytes', 'response_size_bytes'
]
}),
('Performance Metrics', {
'fields': [
'processing_time_ms', 'network_time_ms'
]
}),
('Error Handling', {
'fields': [
'error_message', 'error_details', 'retry_count'
]
}),
('External Tracking', {
'fields': [
'external_id', 'correlation_id'
]
}),
('Metadata', {
'fields': [
'triggered_by', 'metadata'
],
'classes': ['collapse']
})
]
date_hierarchy = 'started_at'
def endpoint_name(self, obj):
"""Display endpoint name."""
return f"{obj.endpoint.external_system.name} - {obj.endpoint.name}"
endpoint_name.short_description = 'Endpoint'
def duration_display(self, obj):
"""Display execution duration."""
duration = obj.duration
if duration:
total_seconds = duration.total_seconds()
if total_seconds >= 60:
minutes = int(total_seconds // 60)
seconds = int(total_seconds % 60)
return f"{minutes}m {seconds}s"
return f"{total_seconds:.1f}s"
return "-"
duration_display.short_description = 'Duration'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(endpoint__external_system__tenant=request.user.tenant)
return qs.select_related('endpoint__external_system', 'triggered_by')
class WebhookExecutionInline(admin.TabularInline):
"""
Inline admin for webhook executions.
"""
model = WebhookExecution
extra = 0
fields = [
'method', 'status', 'received_at',
'processed_at', 'response_status'
]
readonly_fields = [
'execution_id', 'received_at', 'processed_at',
'processing_time_ms', 'payload_size_bytes'
]
@admin.register(WebhookEndpoint)
class WebhookEndpointAdmin(admin.ModelAdmin):
"""
Admin interface for webhook endpoints.
"""
list_display = [
'name', 'external_system_name', 'url_path',
'authentication_type', 'success_rate_display',
'request_count', 'last_request_at', 'is_active'
]
list_filter = [
'external_system__tenant', 'authentication_type',
'is_active', 'external_system__system_type'
]
search_fields = [
'name', 'description', 'url_path', 'external_system__name'
]
readonly_fields = [
'webhook_id', 'request_count', 'success_count',
'failure_count', 'last_request_at', 'created_at', 'updated_at'
]
fieldsets = [
('Webhook Information', {
'fields': [
'webhook_id', 'external_system', 'name', 'description'
]
}),
('Webhook Configuration', {
'fields': [
'url_path', 'allowed_methods'
]
}),
('Authentication', {
'fields': [
'authentication_type', 'authentication_config'
]
}),
('Processing Configuration', {
'fields': [
'data_mapping', 'processing_config'
]
}),
('Rate Limiting', {
'fields': [
'rate_limit_per_minute', 'rate_limit_per_hour'
]
}),
('Webhook Status', {
'fields': [
'is_active'
]
}),
('Usage Tracking', {
'fields': [
'request_count', 'success_count', 'failure_count', 'last_request_at'
],
'classes': ['collapse']
}),
('Metadata', {
'fields': [
'created_at', 'updated_at', 'created_by'
],
'classes': ['collapse']
})
]
inlines = [WebhookExecutionInline]
def external_system_name(self, obj):
"""Display external system name."""
return obj.external_system.name
external_system_name.short_description = 'External System'
def success_rate_display(self, obj):
"""Display success rate with color coding."""
rate = obj.success_rate
if rate >= 95:
color = 'green'
elif rate >= 85:
color = 'orange'
else:
color = 'red'
return format_html(
'<span style="color: {};">{:.1f}%</span>',
color, rate
)
success_rate_display.short_description = 'Success Rate'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(external_system__tenant=request.user.tenant)
return qs.select_related('external_system', 'data_mapping', 'created_by')
@admin.register(WebhookExecution)
class WebhookExecutionAdmin(admin.ModelAdmin):
"""
Admin interface for webhook executions.
"""
list_display = [
'webhook_name', 'method', 'status',
'received_at', 'duration_display',
'response_status', 'client_ip'
]
list_filter = [
'webhook__external_system__tenant', 'method',
'status', 'response_status', 'received_at'
]
search_fields = [
'webhook__name', 'webhook__external_system__name',
'client_ip', 'user_agent', 'external_id', 'correlation_id'
]
readonly_fields = [
'execution_id', 'received_at', 'processed_at',
'processing_time_ms', 'payload_size_bytes'
]
fieldsets = [
('Execution Information', {
'fields': [
'execution_id', 'webhook'
]
}),
('Request Details', {
'fields': [
'method', 'headers', 'query_params', 'payload', 'payload_size_bytes'
]
}),
('Client Information', {
'fields': [
'client_ip', 'user_agent'
]
}),
('Processing', {
'fields': [
'status', 'received_at', 'processed_at', 'processing_time_ms'
]
}),
('Response', {
'fields': [
'response_status', 'response_data'
]
}),
('Error Handling', {
'fields': [
'error_message', 'error_details'
]
}),
('External Tracking', {
'fields': [
'external_id', 'correlation_id'
]
}),
('Metadata', {
'fields': [
'metadata'
],
'classes': ['collapse']
})
]
date_hierarchy = 'received_at'
def webhook_name(self, obj):
"""Display webhook name."""
return f"{obj.webhook.external_system.name} - {obj.webhook.name}"
webhook_name.short_description = 'Webhook'
def duration_display(self, obj):
"""Display processing duration."""
duration = obj.duration
if duration:
total_seconds = duration.total_seconds()
if total_seconds >= 60:
minutes = int(total_seconds // 60)
seconds = int(total_seconds % 60)
return f"{minutes}m {seconds}s"
return f"{total_seconds:.1f}s"
return "-"
duration_display.short_description = 'Duration'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(webhook__external_system__tenant=request.user.tenant)
return qs.select_related('webhook__external_system')
@admin.register(IntegrationLog)
class IntegrationLogAdmin(admin.ModelAdmin):
"""
Admin interface for integration logs.
"""
list_display = [
'system_name', 'level', 'category',
'message_short', 'timestamp'
]
list_filter = [
'external_system__tenant', 'level', 'category',
'timestamp', 'external_system__system_type'
]
search_fields = [
'message', 'external_system__name', 'endpoint__name',
'correlation_id', 'user__username'
]
readonly_fields = [
'log_id', 'timestamp'
]
fieldsets = [
('Log Information', {
'fields': [
'log_id', 'external_system', 'endpoint', 'execution'
]
}),
('Log Details', {
'fields': [
'level', 'category', 'message', 'details'
]
}),
('Context', {
'fields': [
'correlation_id', 'user'
]
}),
('Metadata', {
'fields': [
'timestamp', 'metadata'
],
'classes': ['collapse']
})
]
date_hierarchy = 'timestamp'
def system_name(self, obj):
"""Display system name."""
if obj.external_system:
return obj.external_system.name
return "System"
system_name.short_description = 'System'
def message_short(self, obj):
"""Display shortened message."""
return obj.message[:100] + "..." if len(obj.message) > 100 else obj.message
message_short.short_description = 'Message'
def get_queryset(self, request):
"""Filter by user's tenant."""
qs = super().get_queryset(request)
if hasattr(request.user, 'tenant'):
qs = qs.filter(
models.Q(external_system__tenant=request.user.tenant) |
models.Q(external_system__isnull=True)
)
return qs.select_related('external_system', 'endpoint', 'execution', 'user')
# Customize admin site
admin.site.site_header = "Hospital Management System - Integration"
admin.site.site_title = "Integration Admin"
admin.site.index_title = "Integration Administration"