"""
PX Action Center admin
"""
from django.contrib import admin
from django.utils.html import format_html, mark_safe
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 mark_safe('DUE SOON')
else:
return mark_safe('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")