""" Analytics models - KPIs, metrics, and dashboards This module implements analytics capabilities: - KPI definitions and tracking - Metric aggregation - Dashboard data - Trend analysis """ from django.db import models from apps.core.models import TimeStampedModel, UUIDModel class KPI(UUIDModel, TimeStampedModel): """ KPI (Key Performance Indicator) definition. Defines metrics to track across the system. """ name = models.CharField(max_length=200, unique=True) name_ar = models.CharField(max_length=200, blank=True) description = models.TextField(blank=True) # Category category = models.CharField( max_length=100, choices=[ ('patient_satisfaction', 'Patient Satisfaction'), ('complaint_management', 'Complaint Management'), ('action_management', 'Action Management'), ('sla_compliance', 'SLA Compliance'), ('survey_response', 'Survey Response'), ('operational', 'Operational'), ], db_index=True ) # Measurement unit = models.CharField( max_length=50, help_text="Unit of measurement (%, count, hours, etc.)" ) calculation_method = models.TextField( help_text="Description of how this KPI is calculated" ) # Thresholds target_value = models.DecimalField( max_digits=10, decimal_places=2, null=True, blank=True, help_text="Target value for this KPI" ) warning_threshold = models.DecimalField( max_digits=10, decimal_places=2, null=True, blank=True, help_text="Warning threshold" ) critical_threshold = models.DecimalField( max_digits=10, decimal_places=2, null=True, blank=True, help_text="Critical threshold" ) # Configuration is_active = models.BooleanField(default=True) class Meta: ordering = ['category', 'name'] verbose_name = 'KPI' verbose_name_plural = 'KPIs' def __str__(self): return self.name class KPIValue(UUIDModel, TimeStampedModel): """ KPI value - actual measurement at a point in time. """ kpi = models.ForeignKey( KPI, on_delete=models.CASCADE, related_name='values' ) # Scope hospital = models.ForeignKey( 'organizations.Hospital', on_delete=models.CASCADE, null=True, blank=True, related_name='kpi_values' ) department = models.ForeignKey( 'organizations.Department', on_delete=models.CASCADE, null=True, blank=True, related_name='kpi_values' ) # Value value = models.DecimalField( max_digits=10, decimal_places=2 ) # Time period period_start = models.DateTimeField(db_index=True) period_end = models.DateTimeField(db_index=True) period_type = models.CharField( max_length=20, choices=[ ('hourly', 'Hourly'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), ('quarterly', 'Quarterly'), ('yearly', 'Yearly'), ], default='daily' ) # Status status = models.CharField( max_length=20, choices=[ ('on_target', 'On Target'), ('warning', 'Warning'), ('critical', 'Critical'), ], db_index=True ) # Metadata metadata = models.JSONField( default=dict, blank=True, help_text="Additional calculation details" ) class Meta: ordering = ['-period_end'] indexes = [ models.Index(fields=['kpi', '-period_end']), models.Index(fields=['hospital', 'kpi', '-period_end']), ] def __str__(self): scope = self.hospital.name if self.hospital else "Global" return f"{self.kpi.name} - {scope} - {self.period_end.strftime('%Y-%m-%d')}: {self.value}"