agdar/psychology/tasks.py
Marwan Alwali 2f1681b18c update
2025-11-11 13:44:48 +03:00

249 lines
7.6 KiB
Python

"""
Celery tasks for psychology app.
Handles automated workflows, notifications, and scheduled tasks.
"""
from celery import shared_task
from django.utils import timezone
from django.db.models import Q
from datetime import timedelta
from .models import (
PsychologyConsultation,
PsychologySession,
PsychologyGoal,
)
from .services import (
PsychologyRiskAssessmentService,
PsychologyGoalTrackingService,
PsychologySessionManagementService,
PsychologyNotificationService,
)
from core.models import User
from notifications.models import Notification
@shared_task
def check_high_risk_patients():
"""
Daily task to check for high-risk patients and send alerts.
Runs every day at 8:00 AM.
"""
from core.models import Tenant
total_alerts = 0
for tenant in Tenant.objects.filter(is_active=True):
high_risk_patients = PsychologyRiskAssessmentService.get_high_risk_patients(str(tenant.id))
if high_risk_patients:
# Get clinical coordinator for this tenant
coordinators = User.objects.filter(
tenant=tenant,
role='CLINICAL_COORDINATOR',
is_active=True
)
for coordinator in coordinators:
Notification.objects.create(
user=coordinator,
notification_type='DAILY_SUMMARY',
title=f"High Risk Patients - Psychology",
message=f"{len(high_risk_patients)} patients with high risk assessments require monitoring.",
)
total_alerts += 1
return {
'task': 'check_high_risk_patients',
'alerts_sent': total_alerts,
'timestamp': timezone.now().isoformat(),
}
@shared_task
def send_unsigned_session_reminders():
"""
Daily task to remind psychologists about unsigned sessions.
Runs every day at 5:00 PM.
"""
psychologists = User.objects.filter(
role__in=['THERAPIST_SENIOR', 'THERAPIST_JUNIOR', 'THERAPIST_ASSISTANT'],
is_active=True
)
total_reminders = 0
for psychologist in psychologists:
# Check if they have psychology sessions
has_psych_sessions = PsychologySession.objects.filter(
provider=psychologist
).exists()
if has_psych_sessions:
count = PsychologyNotificationService.notify_unsigned_sessions(psychologist)
if count > 0:
total_reminders += 1
return {
'task': 'send_unsigned_session_reminders',
'reminders_sent': total_reminders,
'timestamp': timezone.now().isoformat(),
}
@shared_task
def send_overdue_goal_reminders():
"""
Weekly task to remind psychologists about overdue treatment goals.
Runs every Monday at 9:00 AM.
"""
psychologists = User.objects.filter(
role__in=['THERAPIST_SENIOR', 'THERAPIST_JUNIOR', 'THERAPIST_ASSISTANT'],
is_active=True
)
total_reminders = 0
for psychologist in psychologists:
# Check if they have psychology consultations
has_psych_consultations = PsychologyConsultation.objects.filter(
provider=psychologist
).exists()
if has_psych_consultations:
count = PsychologyNotificationService.notify_overdue_goals(psychologist)
if count > 0:
total_reminders += 1
return {
'task': 'send_overdue_goal_reminders',
'reminders_sent': total_reminders,
'timestamp': timezone.now().isoformat(),
}
@shared_task
def generate_weekly_psychology_summary():
"""
Weekly task to generate psychology statistics summary.
Runs every Monday at 8:00 AM.
"""
from .services import PsychologyStatisticsService
from core.models import Tenant
summaries_generated = 0
for tenant in Tenant.objects.filter(is_active=True):
# Get statistics for the past week
stats = PsychologyStatisticsService.get_tenant_statistics(
str(tenant.id),
start_date=timezone.now().date() - timedelta(days=7)
)
# Send to clinical coordinator
coordinators = User.objects.filter(
tenant=tenant,
role='CLINICAL_COORDINATOR',
is_active=True
)
for coordinator in coordinators:
message = f"""
Weekly Psychology Summary:
- Consultations: {stats['total_consultations']}
- Sessions: {stats['total_sessions']}
- Active Patients: {stats['total_active_patients']}
- High Risk Patients: {stats['high_risk_patients']}
- Goals Achieved: {stats['goals_achieved']}
- Average Goal Progress: {stats['average_goal_progress']:.1f}%
""".strip()
Notification.objects.create(
user=coordinator,
notification_type='WEEKLY_SUMMARY',
title=f"Weekly Psychology Summary",
message=message,
)
summaries_generated += 1
return {
'task': 'generate_weekly_psychology_summary',
'summaries_generated': summaries_generated,
'timestamp': timezone.now().isoformat(),
}
@shared_task
def auto_update_goal_status():
"""
Daily task to auto-update goal status based on progress percentage.
Runs every day at 6:00 AM.
"""
goals_updated = 0
# Get all active goals
goals = PsychologyGoal.objects.filter(
status__in=['NOT_STARTED', 'IN_PROGRESS']
)
for goal in goals:
old_status = goal.status
# Update status based on progress
if goal.progress_percentage == 0:
goal.status = 'NOT_STARTED'
elif goal.progress_percentage == 100:
goal.status = 'ACHIEVED'
if not goal.achieved_date:
goal.achieved_date = timezone.now().date()
elif goal.progress_percentage > 0:
goal.status = 'IN_PROGRESS'
# Save if status changed
if old_status != goal.status:
goal.save()
goals_updated += 1
return {
'task': 'auto_update_goal_status',
'goals_updated': goals_updated,
'timestamp': timezone.now().isoformat(),
}
@shared_task
def check_consultation_follow_ups():
"""
Weekly task to check if consultations need follow-up.
Runs every Friday at 10:00 AM.
"""
# Get consultations from 30-45 days ago that don't have follow-up sessions
start_date = timezone.now().date() - timedelta(days=45)
end_date = timezone.now().date() - timedelta(days=30)
consultations_needing_followup = PsychologyConsultation.objects.filter(
consultation_date__gte=start_date,
consultation_date__lte=end_date
).exclude(
patient__psychology_sessions__session_date__gte=end_date
).select_related('patient', 'provider')
notifications_sent = 0
for consultation in consultations_needing_followup:
if consultation.provider:
Notification.objects.create(
user=consultation.provider,
notification_type='REMINDER',
title=f"Follow-up Needed: {consultation.patient.get_full_name()}",
message=f"Consultation from {consultation.consultation_date} may need follow-up session.",
)
notifications_sent += 1
return {
'task': 'check_consultation_follow_ups',
'notifications_sent': notifications_sent,
'consultations_checked': consultations_needing_followup.count(),
'timestamp': timezone.now().isoformat(),
}