""" Executive Summary models - AI-powered executive dashboards and reports This module implements: - Executive metrics (KPI snapshots for trending) - Executive reports (AI-generated weekly/monthly summaries) - Predictive insights (AI-detected patterns and risks) - AI recommendations (suggested actions) """ from django.db import models from django.utils.translation import gettext_lazy as _ from apps.core.models import TimeStampedModel, UUIDModel class ExecutiveMetric(UUIDModel, TimeStampedModel): """ Executive Metric - Daily KPI snapshots for trending and analysis. Stores aggregated metrics across all hospitals for executive overview. Used for trend analysis and dashboard display. """ METRIC_TYPES = [ ("complaints_total", _("Total Complaints")), ("complaints_critical", _("Critical Complaints")), ("complaints_overdue", _("Overdue Complaints")), ("complaints_resolution_time", _("Avg Resolution Time (hours)")), ("surveys_total", _("Total Surveys")), ("surveys_satisfaction", _("Satisfaction Rate %")), ("surveys_nps", _("NPS Score")), ("surveys_response_rate", _("Response Rate %")), ("actions_total", _("Total Actions")), ("actions_open", _("Open Actions")), ("actions_overdue", _("Overdue Actions")), ("actions_closed", _("Closed Actions")), ("observations_total", _("Total Observations")), ("observations_critical", _("Critical Observations")), ("inquiries_total", _("Total Inquiries")), ("inquiries_resolved", _("Resolved Inquiries")), ("call_center_total", _("Call Center Interactions")), ("call_center_satisfaction", _("Call Center Satisfaction %")), ("physician_avg_rating", _("Avg Physician Rating")), ] # Date for this metric snapshot metric_date = models.DateField(db_index=True, help_text="Date of this metric snapshot") # Metric type metric_type = models.CharField(max_length=50, choices=METRIC_TYPES, db_index=True) # Metric value metric_value = models.DecimalField(max_digits=10, decimal_places=2) # Variance from previous period variance = models.DecimalField( max_digits=10, decimal_places=2, null=True, blank=True, help_text="Variance from previous period" ) # Variance direction variance_direction = models.CharField( max_length=10, choices=[("up", "Up"), ("down", "Down"), ("neutral", "Neutral")], default="neutral", help_text="Direction of variance", ) # Hospital (null = system-wide aggregate) hospital = models.ForeignKey( "organizations.Hospital", on_delete=models.CASCADE, null=True, blank=True, related_name="executive_metrics" ) # Metadata metadata = models.JSONField(default=dict, blank=True) class Meta: ordering = ["-metric_date", "metric_type"] indexes = [ models.Index(fields=["metric_date", "metric_type"]), models.Index(fields=["hospital", "metric_date"]), ] verbose_name = _("Executive Metric") verbose_name_plural = _("Executive Metrics") def __str__(self): hospital_name = f" - {self.hospital.name}" if self.hospital else " (All)" return f"{self.get_metric_type_display()}: {self.metric_value}{hospital_name} ({self.metric_date})" class ExecutiveReport(UUIDModel, TimeStampedModel): """ Executive Report - AI-generated weekly/monthly narrative summaries. Contains natural language summaries generated by AI analyzing performance data across all hospitals. """ REPORT_TYPES = [ ("weekly", _("Weekly Summary")), ("monthly", _("Monthly Summary")), ("quarterly", _("Quarterly Summary")), ("custom", _("Custom Report")), ] STATUS_CHOICES = [ ("pending", _("Pending")), ("generating", _("Generating")), ("completed", _("Completed")), ("failed", _("Failed")), ] # Report metadata report_type = models.CharField(max_length=20, choices=REPORT_TYPES, db_index=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="pending", db_index=True) # Date range start_date = models.DateField() end_date = models.DateField() # AI-generated narratives (bilingual) narrative_en = models.TextField(blank=True, help_text="English narrative summary") narrative_ar = models.TextField(blank=True, help_text="Arabic narrative summary") # Key highlights highlights_en = models.JSONField(default=list, blank=True, help_text="Key highlights (English)") highlights_ar = models.JSONField(default=list, blank=True, help_text="Key highlights (Arabic)") # Key concerns concerns_en = models.JSONField(default=list, blank=True, help_text="Key concerns (English)") concerns_ar = models.JSONField(default=list, blank=True, help_text="Key concerns (Arabic)") # Summary metrics snapshot metrics_snapshot = models.JSONField(default=dict, blank=True, help_text="Key metrics at report time") # AI metadata ai_model = models.CharField(max_length=100, blank=True, help_text="AI model used for generation") generation_time_ms = models.IntegerField(null=True, blank=True, help_text="Generation time in milliseconds") # PDF report file (if generated) pdf_file = models.FileField( upload_to="executive_reports/pdfs/%Y/%m/", null=True, blank=True, help_text="Generated PDF report" ) # Error message if failed error_message = models.TextField(blank=True, help_text="Error message if generation failed") class Meta: ordering = ["-created_at"] indexes = [ models.Index(fields=["report_type", "-created_at"]), models.Index(fields=["status", "-created_at"]), ] verbose_name = _("Executive Report") verbose_name_plural = _("Executive Reports") def __str__(self): return f"{self.get_report_type_display()} ({self.start_date} to {self.end_date}) - {self.get_status_display()}" class PredictiveInsight(UUIDModel, TimeStampedModel): """ Predictive Insight - AI-detected patterns, anomalies, and early warnings. Automatically generated insights identifying: - Emerging complaint patterns - Declining satisfaction trends - SLA breach risks - Performance anomalies - Resource bottlenecks """ INSIGHT_TYPES = [ ("trend_change", _("Trend Change")), ("anomaly", _("Anomaly Detected")), ("risk_warning", _("Risk Warning")), ("sla_breach_risk", _("SLA Breach Risk")), ("performance_drop", _("Performance Drop")), ("volume_spike", _("Volume Spike")), ("satisfaction_decline", _("Satisfaction Decline")), ("positive_trend", _("Positive Trend")), ] SEVERITY_LEVELS = [ ("low", _("Low")), ("medium", _("Medium")), ("high", _("High")), ("critical", _("Critical")), ] STATUS_CHOICES = [ ("new", _("New")), ("acknowledged", _("Acknowledged")), ("resolved", _("Resolved")), ("dismissed", _("Dismissed")), ] # Insight details insight_type = models.CharField(max_length=30, choices=INSIGHT_TYPES, db_index=True) severity = models.CharField(max_length=10, choices=SEVERITY_LEVELS, default="medium", db_index=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="new", db_index=True) # Title and description (bilingual) title_en = models.CharField(max_length=300) title_ar = models.CharField(max_length=300, blank=True) description_en = models.TextField() description_ar = models.TextField(blank=True) # AI-generated recommendation recommendation_en = models.TextField(blank=True) recommendation_ar = models.TextField(blank=True) # Affected entities hospital = models.ForeignKey( "organizations.Hospital", on_delete=models.SET_NULL, null=True, blank=True, related_name="predictive_insights" ) department = models.ForeignKey( "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="predictive_insights" ) # Metric affected metric_type = models.CharField(max_length=50, blank=True, help_text="Related metric type") # Related entity (for SLA breach predictions, etc.) entity_type = models.CharField( max_length=50, blank=True, help_text="Type of related entity (e.g., complaint, px_action)" ) entity_id = models.CharField(max_length=100, blank=True, help_text="ID of related entity") # Predicted values current_value = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True) predicted_value = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True) confidence_score = models.DecimalField( max_digits=5, decimal_places=2, null=True, blank=True, help_text="AI confidence score (0-100)" ) # Time-related predicted_date = models.DateField(null=True, blank=True, help_text="When this is expected to occur") # Acknowledgement acknowledged_by = models.ForeignKey( "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="acknowledged_insights" ) acknowledged_at = models.DateTimeField(null=True, blank=True) # AI metadata ai_model = models.CharField(max_length=100, blank=True) detection_metadata = models.JSONField(default=dict, blank=True) class Meta: ordering = ["-severity", "-created_at"] indexes = [ models.Index(fields=["status", "severity", "-created_at"]), models.Index(fields=["hospital", "status"]), ] verbose_name = _("Predictive Insight") verbose_name_plural = _("Predictive Insights") def __str__(self): return f"[{self.get_severity_display()}] {self.title_en}" class AIRecommendation(UUIDModel, TimeStampedModel): """ AI Recommendation - Suggested actions based on data analysis. AI-generated recommendations for: - Process improvements - Resource allocation - Training needs - Policy changes - Preventive measures """ CATEGORY_CHOICES = [ ("process_improvement", _("Process Improvement")), ("resource_allocation", _("Resource Allocation")), ("training", _("Training")), ("policy_change", _("Policy Change")), ("preventive_action", _("Preventive Action")), ("performance_optimization", _("Performance Optimization")), ("communication", _("Communication")), ("quality_assurance", _("Quality Assurance")), ] PRIORITY_LEVELS = [ ("low", _("Low")), ("medium", _("Medium")), ("high", _("High")), ("urgent", _("Urgent")), ] STATUS_CHOICES = [ ("new", _("New")), ("under_review", _("Under Review")), ("approved", _("Approved")), ("implemented", _("Implemented")), ("rejected", _("Rejected")), ] # Recommendation details category = models.CharField(max_length=30, choices=CATEGORY_CHOICES, db_index=True) priority = models.CharField(max_length=10, choices=PRIORITY_LEVELS, default="medium", db_index=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="new", db_index=True) # Title and description (bilingual) title_en = models.CharField(max_length=300) title_ar = models.CharField(max_length=300, blank=True) description_en = models.TextField() description_ar = models.TextField(blank=True) # Expected impact expected_impact_en = models.TextField(blank=True, help_text="Expected impact if implemented (English)") expected_impact_ar = models.TextField(blank=True, help_text="Expected impact if implemented (Arabic)") # Related data hospital = models.ForeignKey( "organizations.Hospital", on_delete=models.SET_NULL, null=True, blank=True, related_name="ai_recommend" ) department = models.ForeignKey( "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="ai_recommend" ) # Related insight (if generated from one) related_insight = models.ForeignKey( PredictiveInsight, on_delete=models.SET_NULL, null=True, blank=True, related_name="recommendations" ) # Implementation tracking implemented_by = models.ForeignKey( "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="implemented_recommendations" ) implemented_at = models.DateTimeField(null=True, blank=True) # AI metadata confidence_score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) ai_model = models.CharField(max_length=100, blank=True) generation_metadata = models.JSONField(default=dict, blank=True) class Meta: ordering = ["-priority", "-created_at"] indexes = [ models.Index(fields=["status", "priority", "-created_at"]), models.Index(fields=["hospital", "status"]), ] verbose_name = _("AI Recommendation") verbose_name_plural = _("AI Recommendations") def __str__(self): return f"[{self.get_priority_display()}] {self.title_en}"