""" 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(), }