76 lines
2.1 KiB
Python
76 lines
2.1 KiB
Python
"""
|
|
Physicians models - Physician ratings and performance tracking
|
|
|
|
This module implements physician performance tracking:
|
|
- Monthly rating aggregation from surveys
|
|
- Performance metrics
|
|
- Leaderboards
|
|
"""
|
|
from django.db import models
|
|
|
|
from apps.core.models import TimeStampedModel, UUIDModel
|
|
|
|
|
|
class PhysicianMonthlyRating(UUIDModel, TimeStampedModel):
|
|
"""
|
|
Physician monthly rating - aggregated from survey responses.
|
|
|
|
Calculated monthly from all surveys mentioning this physician.
|
|
"""
|
|
staff = models.ForeignKey(
|
|
'organizations.Staff',
|
|
on_delete=models.CASCADE,
|
|
related_name='monthly_ratings'
|
|
)
|
|
|
|
# Time period
|
|
year = models.IntegerField(db_index=True)
|
|
month = models.IntegerField(db_index=True, help_text="1-12")
|
|
|
|
# Ratings
|
|
average_rating = models.DecimalField(
|
|
max_digits=3,
|
|
decimal_places=2,
|
|
help_text="Average rating (1-5)"
|
|
)
|
|
total_surveys = models.IntegerField(
|
|
help_text="Number of surveys included"
|
|
)
|
|
positive_count = models.IntegerField(default=0)
|
|
neutral_count = models.IntegerField(default=0)
|
|
negative_count = models.IntegerField(default=0)
|
|
|
|
# Breakdown by journey stage
|
|
md_consult_rating = models.DecimalField(
|
|
max_digits=3,
|
|
decimal_places=2,
|
|
null=True,
|
|
blank=True
|
|
)
|
|
|
|
# Ranking
|
|
hospital_rank = models.IntegerField(
|
|
null=True,
|
|
blank=True,
|
|
help_text="Rank within hospital"
|
|
)
|
|
department_rank = models.IntegerField(
|
|
null=True,
|
|
blank=True,
|
|
help_text="Rank within department"
|
|
)
|
|
|
|
# Metadata
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
class Meta:
|
|
ordering = ['-year', '-month', '-average_rating']
|
|
unique_together = [['staff', 'year', 'month']]
|
|
indexes = [
|
|
models.Index(fields=['staff', '-year', '-month']),
|
|
models.Index(fields=['year', 'month', '-average_rating']),
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"{self.staff.get_full_name()} - {self.year}-{self.month:02d}: {self.average_rating}"
|