218 lines
6.2 KiB
Python
218 lines
6.2 KiB
Python
"""
|
|
PX Sources models - Manages origins of patient feedback
|
|
|
|
This module implements the PX Source management system that:
|
|
- Tracks sources of patient feedback (Complaints and Inquiries)
|
|
- Supports bilingual naming (English/Arabic)
|
|
- Enables status management
|
|
"""
|
|
from django.db import models
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from apps.core.models import UUIDModel, TimeStampedModel
|
|
|
|
|
|
class PXSource(UUIDModel, TimeStampedModel):
|
|
"""
|
|
PX Source model for managing feedback origins.
|
|
|
|
Simple model with bilingual naming and active status management.
|
|
"""
|
|
|
|
# Bilingual names
|
|
name_en = models.CharField(
|
|
max_length=200,
|
|
help_text="Source name in English"
|
|
)
|
|
name_ar = models.CharField(
|
|
max_length=200,
|
|
blank=True,
|
|
help_text="Source name in Arabic"
|
|
)
|
|
|
|
# Description
|
|
description = models.TextField(
|
|
blank=True,
|
|
help_text="Detailed description"
|
|
)
|
|
|
|
# Status
|
|
is_active = models.BooleanField(
|
|
default=True,
|
|
db_index=True,
|
|
help_text="Whether this source is active for selection"
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ['name_en']
|
|
verbose_name = 'PX Source'
|
|
verbose_name_plural = 'PX Sources'
|
|
indexes = [
|
|
models.Index(fields=['is_active', 'name_en']),
|
|
]
|
|
|
|
def __str__(self):
|
|
return self.name_en
|
|
|
|
def get_localized_name(self, language='en'):
|
|
"""Get localized name based on language"""
|
|
if language == 'ar' and self.name_ar:
|
|
return self.name_ar
|
|
return self.name_en
|
|
|
|
def get_localized_description(self):
|
|
"""Get localized description"""
|
|
return self.description
|
|
|
|
def activate(self):
|
|
"""Activate this source"""
|
|
if not self.is_active:
|
|
self.is_active = True
|
|
self.save(update_fields=['is_active'])
|
|
|
|
def deactivate(self):
|
|
"""Deactivate this source"""
|
|
if self.is_active:
|
|
self.is_active = False
|
|
self.save(update_fields=['is_active'])
|
|
|
|
@classmethod
|
|
def get_active_sources(cls):
|
|
"""
|
|
Get all active sources.
|
|
|
|
Returns:
|
|
QuerySet of active PXSource objects
|
|
"""
|
|
return cls.objects.filter(is_active=True).order_by('name_en')
|
|
|
|
|
|
class SourceUser(UUIDModel, TimeStampedModel):
|
|
"""
|
|
Links users to PX Sources for management.
|
|
|
|
A user can be a source manager for a specific PX Source,
|
|
allowing them to create complaints and inquiries from that source.
|
|
"""
|
|
user = models.OneToOneField(
|
|
'accounts.User',
|
|
on_delete=models.CASCADE,
|
|
related_name='source_user_profile',
|
|
help_text="User who manages this source"
|
|
)
|
|
source = models.ForeignKey(
|
|
PXSource,
|
|
on_delete=models.CASCADE,
|
|
related_name='source_users',
|
|
help_text="Source managed by this user"
|
|
)
|
|
|
|
# Status
|
|
is_active = models.BooleanField(
|
|
default=True,
|
|
db_index=True,
|
|
help_text="Whether this source user is active"
|
|
)
|
|
|
|
# Permissions
|
|
can_create_complaints = models.BooleanField(
|
|
default=True,
|
|
help_text="User can create complaints from this source"
|
|
)
|
|
can_create_inquiries = models.BooleanField(
|
|
default=True,
|
|
help_text="User can create inquiries from this source"
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ['source__name_en']
|
|
verbose_name = 'Source User'
|
|
verbose_name_plural = 'Source Users'
|
|
indexes = [
|
|
models.Index(fields=['user', 'is_active']),
|
|
models.Index(fields=['source', 'is_active']),
|
|
]
|
|
unique_together = [['user', 'source']]
|
|
|
|
def __str__(self):
|
|
return f"{self.user.email} - {self.source.name_en}"
|
|
|
|
def activate(self):
|
|
"""Activate this source user"""
|
|
if not self.is_active:
|
|
self.is_active = True
|
|
self.save(update_fields=['is_active'])
|
|
|
|
def deactivate(self):
|
|
"""Deactivate this source user"""
|
|
if self.is_active:
|
|
self.is_active = False
|
|
self.save(update_fields=['is_active'])
|
|
|
|
@classmethod
|
|
def get_active_source_user(cls, user):
|
|
"""
|
|
Get active source user for a user.
|
|
|
|
Returns:
|
|
SourceUser object or None
|
|
"""
|
|
return cls.objects.filter(user=user, is_active=True).first()
|
|
|
|
|
|
class SourceUsage(UUIDModel, TimeStampedModel):
|
|
"""
|
|
Tracks usage of sources across the system.
|
|
|
|
This model can be used to analyze which sources are most commonly used,
|
|
track trends, and generate reports.
|
|
"""
|
|
source = models.ForeignKey(
|
|
PXSource,
|
|
on_delete=models.CASCADE,
|
|
related_name='usage_records'
|
|
)
|
|
|
|
# Related object (could be Complaint, Inquiry, or other feedback types)
|
|
content_type = models.ForeignKey(
|
|
'contenttypes.ContentType',
|
|
on_delete=models.CASCADE,
|
|
help_text="Type of related object"
|
|
)
|
|
object_id = models.UUIDField(help_text="ID of related object")
|
|
|
|
# Hospital context (optional)
|
|
hospital = models.ForeignKey(
|
|
'organizations.Hospital',
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='source_usage_records',
|
|
help_text="Hospital where this source was used"
|
|
)
|
|
|
|
# User who selected this source (optional)
|
|
user = models.ForeignKey(
|
|
'accounts.User',
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='source_usage_records',
|
|
help_text="User who selected this source"
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = 'Source Usage'
|
|
verbose_name_plural = 'Source Usages'
|
|
indexes = [
|
|
models.Index(fields=['source', '-created_at']),
|
|
models.Index(fields=['content_type', 'object_id']),
|
|
models.Index(fields=['hospital', '-created_at']),
|
|
models.Index(fields=['created_at']),
|
|
]
|
|
unique_together = [['content_type', 'object_id']]
|
|
|
|
def __str__(self):
|
|
return f"{self.source} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
|