806 lines
24 KiB
Python
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"
|
|
|