136 lines
3.3 KiB
Python
136 lines
3.3 KiB
Python
"""
|
|
Projects models - Quality Improvement (QI) projects tracking
|
|
|
|
This module implements QI project management:
|
|
- Project tracking
|
|
- Task management
|
|
- Milestone tracking
|
|
- Outcome measurement
|
|
"""
|
|
from django.db import models
|
|
|
|
from apps.core.models import StatusChoices, TimeStampedModel, UUIDModel
|
|
|
|
|
|
class QIProject(UUIDModel, TimeStampedModel):
|
|
"""
|
|
Quality Improvement Project.
|
|
|
|
Tracks improvement initiatives driven by PX feedback.
|
|
"""
|
|
name = models.CharField(max_length=200)
|
|
name_ar = models.CharField(max_length=200, blank=True)
|
|
description = models.TextField()
|
|
|
|
# Organization
|
|
hospital = models.ForeignKey(
|
|
'organizations.Hospital',
|
|
on_delete=models.CASCADE,
|
|
related_name='qi_projects'
|
|
)
|
|
department = models.ForeignKey(
|
|
'organizations.Department',
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='qi_projects'
|
|
)
|
|
|
|
# Project lead
|
|
project_lead = models.ForeignKey(
|
|
'accounts.User',
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
related_name='led_projects'
|
|
)
|
|
|
|
# Team members
|
|
team_members = models.ManyToManyField(
|
|
'accounts.User',
|
|
blank=True,
|
|
related_name='qi_projects'
|
|
)
|
|
|
|
# Status
|
|
status = models.CharField(
|
|
max_length=20,
|
|
choices=StatusChoices.choices,
|
|
default=StatusChoices.PENDING,
|
|
db_index=True
|
|
)
|
|
|
|
# Dates
|
|
start_date = models.DateField(null=True, blank=True)
|
|
target_completion_date = models.DateField(null=True, blank=True, db_index=True)
|
|
actual_completion_date = models.DateField(null=True, blank=True)
|
|
|
|
# Linked to PX Actions (optional)
|
|
related_actions = models.ManyToManyField(
|
|
'px_action_center.PXAction',
|
|
blank=True,
|
|
related_name='qi_projects'
|
|
)
|
|
|
|
# Outcomes
|
|
outcome_description = models.TextField(blank=True)
|
|
success_metrics = models.JSONField(
|
|
default=dict,
|
|
blank=True,
|
|
help_text="Success metrics and results"
|
|
)
|
|
|
|
# Metadata
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
indexes = [
|
|
models.Index(fields=['hospital', 'status', '-created_at']),
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"{self.name} ({self.status})"
|
|
|
|
|
|
class QIProjectTask(UUIDModel, TimeStampedModel):
|
|
"""
|
|
Task within a QI project.
|
|
"""
|
|
project = models.ForeignKey(
|
|
QIProject,
|
|
on_delete=models.CASCADE,
|
|
related_name='tasks'
|
|
)
|
|
|
|
title = models.CharField(max_length=500)
|
|
description = models.TextField(blank=True)
|
|
|
|
# Assignment
|
|
assigned_to = models.ForeignKey(
|
|
'accounts.User',
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='qi_tasks'
|
|
)
|
|
|
|
# Status
|
|
status = models.CharField(
|
|
max_length=20,
|
|
choices=StatusChoices.choices,
|
|
default=StatusChoices.PENDING
|
|
)
|
|
|
|
# Dates
|
|
due_date = models.DateField(null=True, blank=True)
|
|
completed_date = models.DateField(null=True, blank=True)
|
|
|
|
# Order
|
|
order = models.IntegerField(default=0)
|
|
|
|
class Meta:
|
|
ordering = ['project', 'order']
|
|
|
|
def __str__(self):
|
|
return f"{self.project.name} - {self.title}"
|