""" Analytics admin """ from django.contrib import admin from django.utils.html import format_html from .models import KPI, KPIValue from .kpi_models import KPIReport, KPIReportMonthlyData, KPIReportDepartmentBreakdown, KPIReportSourceBreakdown @admin.register(KPI) class KPIAdmin(admin.ModelAdmin): """KPI admin""" list_display = [ 'name', 'category', 'unit', 'target_value', 'warning_threshold', 'critical_threshold', 'is_active' ] list_filter = ['category', 'is_active'] search_fields = ['name', 'name_ar', 'description'] ordering = ['category', 'name'] fieldsets = ( (None, { 'fields': ('name', 'name_ar', 'description', 'category') }), ('Measurement', { 'fields': ('unit', 'calculation_method') }), ('Thresholds', { 'fields': ('target_value', 'warning_threshold', 'critical_threshold') }), ('Configuration', { 'fields': ('is_active',) }), ('Metadata', { 'fields': ('created_at', 'updated_at') }), ) readonly_fields = ['created_at', 'updated_at'] @admin.register(KPIValue) class KPIValueAdmin(admin.ModelAdmin): """KPI value admin""" list_display = [ 'kpi', 'hospital', 'department', 'value', 'status_badge', 'period_type', 'period_end' ] list_filter = ['status', 'period_type', 'kpi__category', 'hospital', 'period_end'] search_fields = ['kpi__name'] ordering = ['-period_end'] date_hierarchy = 'period_end' fieldsets = ( ('KPI', { 'fields': ('kpi',) }), ('Scope', { 'fields': ('hospital', 'department') }), ('Value', { 'fields': ('value', 'status') }), ('Period', { 'fields': ('period_type', 'period_start', 'period_end') }), ('Metadata', { 'fields': ('metadata', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) readonly_fields = ['created_at', 'updated_at'] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('kpi', 'hospital', 'department') def status_badge(self, obj): """Display status with badge""" colors = { 'on_target': 'success', 'warning': 'warning', 'critical': 'danger', } color = colors.get(obj.status, 'secondary') return format_html( '{}', color, obj.get_status_display() ) status_badge.short_description = 'Status' # Inline for monthly data class KPIReportMonthlyDataInline(admin.TabularInline): model = KPIReportMonthlyData extra = 0 fields = ['month', 'numerator', 'denominator', 'percentage', 'is_below_target'] readonly_fields = ['percentage'] # Inline for department breakdown class KPIReportDepartmentBreakdownInline(admin.TabularInline): model = KPIReportDepartmentBreakdown extra = 0 fields = ['department_category', 'complaint_count', 'resolved_count', 'avg_resolution_days'] # Inline for source breakdown class KPIReportSourceBreakdownInline(admin.TabularInline): model = KPIReportSourceBreakdown extra = 0 fields = ['source_name', 'complaint_count', 'percentage'] @admin.register(KPIReport) class KPIReportAdmin(admin.ModelAdmin): """KPI Report admin""" list_display = [ 'kpi_id', 'indicator_title_short', 'hospital', 'report_period_display', 'overall_result_display', 'status_badge', 'generated_at' ] list_filter = ['report_type', 'status', 'year', 'hospital'] search_fields = ['hospital__name'] ordering = ['-year', '-month', 'report_type'] date_hierarchy = 'report_date' fieldsets = ( ('Report Info', { 'fields': ('report_type', 'hospital', 'year', 'month', 'status') }), ('Results', { 'fields': ('target_percentage', 'total_numerator', 'total_denominator', 'overall_result') }), ('Metadata', { 'fields': ('category', 'kpi_type', 'risk_level', 'dimension', 'data_collection_method', 'data_collection_frequency', 'reporting_frequency', 'collector_name', 'analyzer_name') }), ('Generation', { 'fields': ('generated_by', 'generated_at', 'error_message') }), ) readonly_fields = ['overall_result', 'generated_at', 'error_message'] inlines = [KPIReportMonthlyDataInline, KPIReportDepartmentBreakdownInline, KPIReportSourceBreakdownInline] def indicator_title_short(self, obj): """Shortened indicator title""" title = obj.indicator_title if len(title) > 40: return title[:40] + '...' return title indicator_title_short.short_description = 'Title' def overall_result_display(self, obj): """Display overall result with color""" if obj.overall_result >= obj.target_percentage: color = 'green' else: color = 'red' return format_html( '{}%', color, obj.overall_result ) overall_result_display.short_description = 'Result' def status_badge(self, obj): """Display status with badge""" colors = { 'completed': 'success', 'pending': 'warning', 'generating': 'info', 'failed': 'danger', } color = colors.get(obj.status, 'secondary') return format_html( '{}', color, obj.get_status_display() ) status_badge.short_description = 'Status' actions = ['regenerate_reports'] def regenerate_reports(self, request, queryset): """Regenerate selected reports""" from .kpi_service import KPICalculationService count = 0 for report in queryset: try: KPICalculationService.generate_monthly_report( report_type=report.report_type, hospital=report.hospital, year=report.year, month=report.month, generated_by=request.user ) count += 1 except Exception as e: self.message_user(request, f'Failed to regenerate {report}: {e}', level='ERROR') self.message_user(request, f'{count} report(s) regenerated successfully.') regenerate_reports.short_description = 'Regenerate selected reports'