""" Admin configuration for SLA & On-Call Management """ from django.contrib import admin from django.utils.html import format_html from django.utils import timezone from datetime import timedelta from .models import ( BusinessHours, SLADefinition, EscalationPolicy, OnCallRotation, OnCallAssignment, SLAInstance, EscalationInstance, NotificationTemplate, ) @admin.register(BusinessHours) class BusinessHoursAdmin(admin.ModelAdmin): list_display = ['name', 'timezone', 'weekday_start', 'weekday_end', 'is_active', 'is_default'] list_filter = ['is_active', 'is_default', 'timezone'] search_fields = ['name', 'description'] ordering = ['name'] fieldsets = ( ('Basic Information', { 'fields': ('name', 'description', 'timezone') }), ('Business Hours', { 'fields': ('weekday_start', 'weekday_end', 'weekend_start', 'weekend_end') }), ('Overrides', { 'fields': ('day_overrides', 'holiday_calendar'), 'classes': ('collapse',) }), ('Status', { 'fields': ('is_active', 'is_default') }), ('Metadata', { 'fields': ('created_by', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(SLADefinition) class SLADefinitionAdmin(admin.ModelAdmin): list_display = [ 'name', 'sla_type', 'target_duration_minutes', 'business_hours_only', 'is_active', 'is_default' ] list_filter = ['sla_type', 'business_hours_only', 'is_active', 'is_default'] search_fields = ['name', 'description'] ordering = ['name'] fieldsets = ( ('Basic Information', { 'fields': ('name', 'description', 'sla_type') }), ('Targeting Criteria', { 'fields': ('incident_categories', 'incident_severities', 'incident_priorities') }), ('SLA Configuration', { 'fields': ('target_duration_minutes', 'business_hours_only', 'business_hours') }), ('Escalation', { 'fields': ('escalation_enabled', 'escalation_threshold_percent') }), ('Status', { 'fields': ('is_active', 'is_default') }), ('Metadata', { 'fields': ('created_by', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(EscalationPolicy) class EscalationPolicyAdmin(admin.ModelAdmin): list_display = [ 'name', 'escalation_type', 'trigger_condition', 'trigger_delay_minutes', 'is_active' ] list_filter = ['escalation_type', 'trigger_condition', 'is_active'] search_fields = ['name', 'description'] ordering = ['name'] fieldsets = ( ('Basic Information', { 'fields': ('name', 'description', 'escalation_type', 'trigger_condition') }), ('Targeting', { 'fields': ('incident_severities', 'incident_categories') }), ('Configuration', { 'fields': ('trigger_delay_minutes', 'escalation_steps') }), ('Notifications', { 'fields': ('notification_channels', 'notification_templates'), 'classes': ('collapse',) }), ('Status', { 'fields': ('is_active', 'is_default') }), ('Metadata', { 'fields': ('created_by', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(OnCallRotation) class OnCallRotationAdmin(admin.ModelAdmin): list_display = [ 'name', 'rotation_type', 'team_name', 'external_system', 'status' ] list_filter = ['rotation_type', 'external_system', 'status'] search_fields = ['name', 'team_name', 'description'] ordering = ['name'] fieldsets = ( ('Basic Information', { 'fields': ('name', 'description', 'rotation_type', 'status') }), ('Team Configuration', { 'fields': ('team_name', 'team_description') }), ('Schedule', { 'fields': ('schedule_config', 'timezone') }), ('External Integration', { 'fields': ('external_system', 'external_system_id', 'integration_config'), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('created_by', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(OnCallAssignment) class OnCallAssignmentAdmin(admin.ModelAdmin): list_display = [ 'user', 'rotation', 'start_time', 'end_time', 'status', 'incidents_handled' ] list_filter = ['status', 'rotation', 'start_time'] search_fields = ['user__username', 'user__email', 'rotation__name'] ordering = ['-start_time'] fieldsets = ( ('Assignment Details', { 'fields': ('rotation', 'user', 'start_time', 'end_time', 'status') }), ('Handoff Information', { 'fields': ('handoff_notes', 'handed_off_from', 'handoff_time'), 'classes': ('collapse',) }), ('Performance', { 'fields': ('incidents_handled', 'response_time_avg') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(SLAInstance) class SLAInstanceAdmin(admin.ModelAdmin): list_display = [ 'incident', 'sla_definition', 'status', 'target_time', 'escalation_triggered', 'time_remaining_display' ] list_filter = ['status', 'escalation_triggered', 'sla_definition__sla_type'] search_fields = ['incident__title', 'sla_definition__name'] ordering = ['-created_at'] fieldsets = ( ('SLA Details', { 'fields': ('sla_definition', 'incident', 'status', 'target_time') }), ('Timing', { 'fields': ('started_at', 'met_at', 'breached_at') }), ('Escalation', { 'fields': ('escalation_policy', 'escalation_triggered', 'escalation_triggered_at', 'escalation_level') }), ('Performance', { 'fields': ('response_time', 'resolution_time') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at', 'started_at'] def time_remaining_display(self, obj): """Display time remaining with color coding""" if obj.status == 'ACTIVE': remaining = obj.time_remaining if remaining > timedelta(hours=1): color = 'green' elif remaining > timedelta(minutes=15): color = 'orange' else: color = 'red' return format_html( '{}', color, str(remaining).split('.')[0] if remaining else 'Expired' ) return '-' time_remaining_display.short_description = 'Time Remaining' @admin.register(EscalationInstance) class EscalationInstanceAdmin(admin.ModelAdmin): list_display = [ 'incident', 'escalation_policy', 'status', 'escalation_level', 'triggered_at', 'current_step' ] list_filter = ['status', 'escalation_level', 'escalation_policy__escalation_type'] search_fields = ['incident__title', 'escalation_policy__name'] ordering = ['-created_at'] fieldsets = ( ('Escalation Details', { 'fields': ('escalation_policy', 'incident', 'sla_instance', 'status') }), ('Progress', { 'fields': ('escalation_level', 'current_step') }), ('Timing', { 'fields': ('triggered_at', 'acknowledged_at', 'resolved_at') }), ('Actions', { 'fields': ('notifications_sent', 'actions_taken'), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(NotificationTemplate) class NotificationTemplateAdmin(admin.ModelAdmin): list_display = [ 'name', 'template_type', 'channel_type', 'is_active', 'is_default' ] list_filter = ['template_type', 'channel_type', 'is_active', 'is_default'] search_fields = ['name', 'subject_template'] ordering = ['template_type', 'channel_type', 'name'] fieldsets = ( ('Basic Information', { 'fields': ('name', 'template_type', 'channel_type') }), ('Template Content', { 'fields': ('subject_template', 'body_template', 'variables') }), ('Status', { 'fields': ('is_active', 'is_default') }), ('Metadata', { 'fields': ('created_by', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at']