""" Standards Section Models - Track compliance standards (CBAHI, MOH, CHI, etc.) """ from django.db import models from django.core.validators import FileExtensionValidator from apps.core.models import TimeStampedModel, UUIDModel, StatusChoices class StandardSource(UUIDModel, TimeStampedModel): """Standard sources like CBAHI, MOH, CHI, JCI, etc.""" name = models.CharField(max_length=100) name_ar = models.CharField(max_length=100, blank=True, verbose_name="Name (Arabic)") code = models.CharField(max_length=50, unique=True, db_index=True) description = models.TextField(blank=True) website = models.URLField(blank=True) is_active = models.BooleanField(default=True, db_index=True) class Meta: ordering = ['name'] verbose_name = 'Standard Source' verbose_name_plural = 'Standard Sources' def __str__(self): return self.name class StandardCategory(UUIDModel, TimeStampedModel): """Group standards by category (Patient Safety, Quality Management, etc.)""" name = models.CharField(max_length=100) name_ar = models.CharField(max_length=100, blank=True, verbose_name="Name (Arabic)") description = models.TextField(blank=True) order = models.PositiveIntegerField(default=0, help_text="Display order") is_active = models.BooleanField(default=True, db_index=True) class Meta: ordering = ['order', 'name'] verbose_name = 'Standard Category' verbose_name_plural = 'Standard Categories' def __str__(self): return self.name class Standard(UUIDModel, TimeStampedModel): """Actual standard requirements""" class ComplianceStatus(models.TextChoices): NOT_ASSESSED = 'not_assessed', 'Not Assessed' MET = 'met', 'Met' PARTIALLY_MET = 'partially_met', 'Partially Met' NOT_MET = 'not_met', 'Not Met' code = models.CharField(max_length=50, db_index=True, help_text="e.g., CBAHI-PS-01") title = models.CharField(max_length=300) title_ar = models.CharField(max_length=300, blank=True, verbose_name="Title (Arabic)") description = models.TextField(help_text="Full description of the standard") # Relationships source = models.ForeignKey( StandardSource, on_delete=models.PROTECT, related_name='standards' ) category = models.ForeignKey( StandardCategory, on_delete=models.PROTECT, related_name='standards' ) department = models.ForeignKey( 'organizations.Department', on_delete=models.SET_NULL, null=True, blank=True, related_name='standards', help_text="Department-specific standard (null if applicable to all)" ) # Dates effective_date = models.DateField(null=True, blank=True, help_text="When standard becomes effective") review_date = models.DateField(null=True, blank=True, help_text="Next review date") is_active = models.BooleanField(default=True, db_index=True) class Meta: ordering = ['source', 'category', 'code'] verbose_name = 'Standard' verbose_name_plural = 'Standards' def __str__(self): return f"{self.code}: {self.title}" class StandardCompliance(UUIDModel, TimeStampedModel): """Track compliance status per department""" class ComplianceStatus(models.TextChoices): NOT_ASSESSED = 'not_assessed', 'Not Assessed' MET = 'met', 'Met' PARTIALLY_MET = 'partially_met', 'Partially Met' NOT_MET = 'not_met', 'Not Met' department = models.ForeignKey( 'organizations.Department', on_delete=models.CASCADE, related_name='compliance_records' ) standard = models.ForeignKey( Standard, on_delete=models.CASCADE, related_name='compliance_records' ) status = models.CharField( max_length=20, choices=ComplianceStatus.choices, default=ComplianceStatus.NOT_ASSESSED, db_index=True ) last_assessed_date = models.DateField(null=True, blank=True, help_text="Date of last assessment") assessor = models.ForeignKey( 'accounts.User', on_delete=models.SET_NULL, null=True, blank=True, related_name='assessments' ) notes = models.TextField(blank=True, help_text="Assessment notes") evidence_summary = models.TextField(blank=True, help_text="Summary of evidence") class Meta: ordering = ['-created_at'] verbose_name = 'Standard Compliance' verbose_name_plural = 'Standard Compliance' unique_together = [['department', 'standard']] def __str__(self): return f"{self.department.name} - {self.standard.code} - {self.status}" class StandardAttachment(UUIDModel, TimeStampedModel): """Proof of compliance - evidence documents""" compliance = models.ForeignKey( StandardCompliance, on_delete=models.CASCADE, related_name='attachments' ) file = models.FileField( upload_to='standards/attachments/%Y/%m/', validators=[FileExtensionValidator(allowed_extensions=['pdf', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'jpeg', 'png', 'zip'])] ) filename = models.CharField(max_length=255, help_text="Original filename") description = models.TextField(blank=True, help_text="Attachment description") uploaded_by = models.ForeignKey( 'accounts.User', on_delete=models.SET_NULL, null=True, blank=True, related_name='uploaded_standards_attachments' ) class Meta: ordering = ['-created_at'] verbose_name = 'Standard Attachment' verbose_name_plural = 'Standard Attachments' def __str__(self): return f"{self.compliance} - {self.filename}"