""" PX Action Center admin """ from django.contrib import admin from django.utils.html import format_html from .models import PXAction, PXActionAttachment, PXActionLog, PXActionSLAConfig, RoutingRule class PXActionLogInline(admin.TabularInline): """Inline admin for action logs""" model = PXActionLog extra = 1 fields = ['log_type', 'message', 'created_by', 'created_at'] readonly_fields = ['created_at'] ordering = ['-created_at'] class PXActionAttachmentInline(admin.TabularInline): """Inline admin for action attachments""" model = PXActionAttachment extra = 0 fields = ['file', 'filename', 'is_evidence', 'uploaded_by', 'description'] readonly_fields = ['file_size'] @admin.register(PXAction) class PXActionAdmin(admin.ModelAdmin): """PX Action admin""" list_display = [ 'title_preview', 'source_type', 'hospital', 'category', 'severity_badge', 'status_badge', 'sla_indicator', 'assigned_to', 'escalation_level', 'created_at' ] list_filter = [ 'status', 'source_type', 'severity', 'priority', 'category', 'is_overdue', 'requires_approval', 'hospital', 'created_at' ] search_fields = ['title', 'description', 'metadata'] ordering = ['-created_at'] date_hierarchy = 'created_at' inlines = [PXActionLogInline, PXActionAttachmentInline] fieldsets = ( ('Source', { 'fields': ('source_type', 'content_type', 'object_id') }), ('Action Details', { 'fields': ('title', 'description', 'category') }), ('Organization', { 'fields': ('hospital', 'department') }), ('Classification', { 'fields': ('priority', 'severity') }), ('Status & Assignment', { 'fields': ('status', 'assigned_to', 'assigned_at') }), ('SLA Tracking', { 'fields': ('due_at', 'is_overdue', 'reminder_sent_at', 'escalated_at', 'escalation_level') }), ('Approval', { 'fields': ('requires_approval', 'approved_by', 'approved_at') }), ('Closure', { 'fields': ('closed_at', 'closed_by') }), ('Action Plan & Outcome', { 'fields': ('action_plan', 'outcome'), 'classes': ('collapse',) }), ('Metadata', { 'fields': ('metadata', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = [ 'assigned_at', 'reminder_sent_at', 'escalated_at', 'approved_at', 'closed_at', 'created_at', 'updated_at' ] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related( 'hospital', 'department', 'assigned_to', 'approved_by', 'closed_by', 'content_type' ) def title_preview(self, obj): """Show preview of title""" return obj.title[:60] + '...' if len(obj.title) > 60 else obj.title title_preview.short_description = 'Title' def severity_badge(self, obj): """Display severity with color badge""" colors = { 'low': 'info', 'medium': 'warning', 'high': 'danger', 'critical': 'danger', } color = colors.get(obj.severity, 'secondary') return format_html( '{}', color, obj.get_severity_display() ) severity_badge.short_description = 'Severity' def status_badge(self, obj): """Display status with color badge""" colors = { 'open': 'danger', 'in_progress': 'warning', 'pending_approval': 'info', 'approved': 'success', 'closed': 'success', 'cancelled': 'secondary', } color = colors.get(obj.status, 'secondary') return format_html( '{}', color, obj.get_status_display() ) status_badge.short_description = 'Status' def sla_indicator(self, obj): """Display SLA status""" if obj.is_overdue: return format_html( 'OVERDUE (Level {})', obj.escalation_level ) from django.utils import timezone time_remaining = obj.due_at - timezone.now() hours_remaining = time_remaining.total_seconds() / 3600 if hours_remaining < 4: return format_html('DUE SOON') else: return format_html('ON TIME') sla_indicator.short_description = 'SLA' @admin.register(PXActionLog) class PXActionLogAdmin(admin.ModelAdmin): """PX Action log admin""" list_display = ['action', 'log_type', 'message_preview', 'created_by', 'created_at'] list_filter = ['log_type', 'created_at'] search_fields = ['message', 'action__title'] ordering = ['-created_at'] fieldsets = ( (None, { 'fields': ('action', 'log_type', 'message') }), ('Status Change', { 'fields': ('old_status', 'new_status'), 'classes': ('collapse',) }), ('Details', { 'fields': ('created_by', 'metadata') }), ('Metadata', { 'fields': ('created_at', 'updated_at') }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('action', 'created_by') def message_preview(self, obj): """Show preview of message""" return obj.message[:100] + '...' if len(obj.message) > 100 else obj.message message_preview.short_description = 'Message' @admin.register(PXActionAttachment) class PXActionAttachmentAdmin(admin.ModelAdmin): """PX Action attachment admin""" list_display = ['action', 'filename', 'is_evidence', 'file_size', 'uploaded_by', 'created_at'] list_filter = ['is_evidence', 'file_type', 'created_at'] search_fields = ['filename', 'description', 'action__title'] ordering = ['-created_at'] fieldsets = ( (None, { 'fields': ('action', 'file', 'filename', 'file_type', 'file_size') }), ('Details', { 'fields': ('is_evidence', 'uploaded_by', 'description') }), ('Metadata', { 'fields': ('created_at', 'updated_at') }), ) readonly_fields = ['file_size', 'created_at', 'updated_at'] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('action', 'uploaded_by') @admin.register(PXActionSLAConfig) class PXActionSLAConfigAdmin(admin.ModelAdmin): """PX Action SLA configuration admin""" list_display = [ 'name', 'hospital', 'department', 'critical_hours', 'high_hours', 'medium_hours', 'low_hours', 'auto_escalate', 'is_active' ] list_filter = ['is_active', 'auto_escalate', 'hospital'] search_fields = ['name'] ordering = ['hospital', 'name'] fieldsets = ( (None, { 'fields': ('name', 'hospital', 'department') }), ('SLA Durations (hours)', { 'fields': ('critical_hours', 'high_hours', 'medium_hours', 'low_hours') }), ('Reminder Configuration', { 'fields': ('reminder_hours_before',) }), ('Escalation Configuration', { 'fields': ('auto_escalate', 'escalation_delay_hours') }), ('Status', { 'fields': ('is_active',) }), ('Metadata', { 'fields': ('created_at', 'updated_at') }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('hospital', 'department') @admin.register(RoutingRule) class RoutingRuleAdmin(admin.ModelAdmin): """Routing rule admin""" list_display = [ 'name', 'source_type', 'category', 'severity', 'hospital', 'assign_to_role', 'priority', 'is_active' ] list_filter = ['source_type', 'severity', 'is_active', 'hospital'] search_fields = ['name', 'description'] ordering = ['-priority', 'name'] fieldsets = ( (None, { 'fields': ('name', 'description', 'priority') }), ('Conditions', { 'fields': ('source_type', 'category', 'severity', 'hospital', 'department') }), ('Routing Target', { 'fields': ('assign_to_role', 'assign_to_user', 'assign_to_department') }), ('Status', { 'fields': ('is_active',) }), ('Metadata', { 'fields': ('created_at', 'updated_at') }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('hospital', 'department', 'assign_to_user', 'assign_to_department')