""" Django REST Framework API views for psychology app. """ from rest_framework import viewsets, filters, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from django_filters.rest_framework import DjangoFilterBackend from django.db.models import Q, Count, Avg from django.utils import timezone from datetime import timedelta from .models import ( PsychologyConsultation, PsychologyAssessment, PsychologySession, PsychologyGoal, PsychologyProgressReport, ) from .serializers import ( PsychologyConsultationSerializer, PsychologyAssessmentSerializer, PsychologySessionSerializer, PsychologyGoalSerializer, PsychologyProgressReportSerializer, ) class PsychologyConsultationViewSet(viewsets.ModelViewSet): """ API endpoint for psychology consultations. Provides CRUD operations and additional actions for consultations. """ queryset = PsychologyConsultation.objects.all() serializer_class = PsychologyConsultationSerializer permission_classes = [IsAuthenticated] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields = ['patient', 'provider', 'referral_reason', 'suicide_risk', 'homicide_risk', 'tenant'] search_fields = ['patient__first_name_en', 'patient__last_name_en', 'patient__mrn', 'presenting_problem', 'clinical_impressions', 'provisional_diagnosis'] ordering_fields = ['consultation_date', 'created_at'] ordering = ['-consultation_date'] def get_queryset(self): """Filter queryset based on user permissions.""" queryset = super().get_queryset() return queryset.select_related('patient', 'provider', 'tenant', 'appointment') @action(detail=False, methods=['get']) def high_risk(self, request): """Get consultations with high suicide or homicide risk.""" high_risk_consultations = self.get_queryset().filter( Q(suicide_risk__in=['MODERATE', 'HIGH']) | Q(homicide_risk__in=['MODERATE', 'HIGH']) ) serializer = self.get_serializer(high_risk_consultations, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def recent(self, request): """Get consultations from the last 30 days.""" thirty_days_ago = timezone.now().date() - timedelta(days=30) recent_consultations = self.get_queryset().filter( consultation_date__gte=thirty_days_ago ) serializer = self.get_serializer(recent_consultations, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def statistics(self, request): """Get consultation statistics.""" queryset = self.get_queryset() stats = { 'total_consultations': queryset.count(), 'by_referral_reason': dict( queryset.values('referral_reason').annotate(count=Count('id')).values_list('referral_reason', 'count') ), 'high_risk_count': queryset.filter( Q(suicide_risk__in=['MODERATE', 'HIGH']) | Q(homicide_risk__in=['MODERATE', 'HIGH']) ).count(), 'signed_count': queryset.filter(signed_by__isnull=False).count(), 'unsigned_count': queryset.filter(signed_by__isnull=True).count(), } return Response(stats) @action(detail=True, methods=['post']) def sign(self, request, pk=None): """Sign a consultation.""" consultation = self.get_object() if consultation.signed_by: return Response( {'error': 'Consultation already signed'}, status=status.HTTP_400_BAD_REQUEST ) consultation.signed_by = request.user consultation.signed_at = timezone.now() consultation.save() serializer = self.get_serializer(consultation) return Response(serializer.data) class PsychologyAssessmentViewSet(viewsets.ModelViewSet): """ API endpoint for psychology assessments. Provides CRUD operations and additional actions for assessments. """ queryset = PsychologyAssessment.objects.all() serializer_class = PsychologyAssessmentSerializer permission_classes = [IsAuthenticated] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields = ['patient', 'provider', 'assessment_type', 'tenant'] search_fields = ['patient__first_name_en', 'patient__last_name_en', 'patient__mrn', 'reason_for_assessment', 'diagnostic_impressions', 'dsm5_diagnosis'] ordering_fields = ['assessment_date', 'created_at'] ordering = ['-assessment_date'] def get_queryset(self): """Filter queryset based on user permissions.""" queryset = super().get_queryset() return queryset.select_related('patient', 'provider', 'tenant', 'appointment') @action(detail=False, methods=['get']) def by_type(self, request): """Get assessments grouped by type.""" assessment_type = request.query_params.get('type') if assessment_type: assessments = self.get_queryset().filter(assessment_type=assessment_type) else: assessments = self.get_queryset() serializer = self.get_serializer(assessments, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def statistics(self, request): """Get assessment statistics.""" queryset = self.get_queryset() stats = { 'total_assessments': queryset.count(), 'by_type': dict( queryset.values('assessment_type').annotate(count=Count('id')).values_list('assessment_type', 'count') ), 'signed_count': queryset.filter(signed_by__isnull=False).count(), 'unsigned_count': queryset.filter(signed_by__isnull=True).count(), } return Response(stats) class PsychologySessionViewSet(viewsets.ModelViewSet): """ API endpoint for psychology sessions. Provides CRUD operations and additional actions for sessions. """ queryset = PsychologySession.objects.all() serializer_class = PsychologySessionSerializer permission_classes = [IsAuthenticated] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields = ['patient', 'provider', 'session_type', 'therapy_modality', 'current_risk_level', 'tenant'] search_fields = ['patient__first_name_en', 'patient__last_name_en', 'patient__mrn', 'presenting_issues', 'interventions_used', 'clinical_notes'] ordering_fields = ['session_date', 'session_number', 'created_at'] ordering = ['-session_date', '-session_number'] def get_queryset(self): """Filter queryset based on user permissions.""" queryset = super().get_queryset() return queryset.select_related('patient', 'provider', 'tenant', 'appointment') @action(detail=False, methods=['get']) def by_patient(self, request): """Get all sessions for a specific patient.""" patient_id = request.query_params.get('patient_id') if not patient_id: return Response( {'error': 'patient_id parameter required'}, status=status.HTTP_400_BAD_REQUEST ) sessions = self.get_queryset().filter(patient_id=patient_id) serializer = self.get_serializer(sessions, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def high_risk(self, request): """Get sessions with high risk levels.""" high_risk_sessions = self.get_queryset().filter( current_risk_level__in=['MODERATE', 'HIGH'] ) serializer = self.get_serializer(high_risk_sessions, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def statistics(self, request): """Get session statistics.""" queryset = self.get_queryset() stats = { 'total_sessions': queryset.count(), 'by_type': dict( queryset.values('session_type').annotate(count=Count('id')).values_list('session_type', 'count') ), 'by_modality': dict( queryset.values('therapy_modality').annotate(count=Count('id')).values_list('therapy_modality', 'count') ), 'average_duration': queryset.aggregate(avg_duration=Avg('duration_minutes'))['avg_duration'], 'high_risk_count': queryset.filter(current_risk_level__in=['MODERATE', 'HIGH']).count(), 'signed_count': queryset.filter(signed_by__isnull=False).count(), 'unsigned_count': queryset.filter(signed_by__isnull=True).count(), } return Response(stats) @action(detail=False, methods=['get']) def recent(self, request): """Get sessions from the last 30 days.""" thirty_days_ago = timezone.now().date() - timedelta(days=30) recent_sessions = self.get_queryset().filter( session_date__gte=thirty_days_ago ) serializer = self.get_serializer(recent_sessions, many=True) return Response(serializer.data) class PsychologyGoalViewSet(viewsets.ModelViewSet): """ API endpoint for psychology goals. Provides CRUD operations and additional actions for goals. """ queryset = PsychologyGoal.objects.all() serializer_class = PsychologyGoalSerializer permission_classes = [IsAuthenticated] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields = ['patient', 'consultation', 'status'] search_fields = ['patient__first_name_en', 'patient__last_name_en', 'patient__mrn', 'goal_description', 'progress_notes'] ordering_fields = ['target_date', 'progress_percentage', 'created_at'] ordering = ['target_date'] def get_queryset(self): """Filter queryset based on user permissions.""" queryset = super().get_queryset() return queryset.select_related('patient', 'consultation') @action(detail=False, methods=['get']) def active(self, request): """Get active goals (in progress).""" active_goals = self.get_queryset().filter(status='IN_PROGRESS') serializer = self.get_serializer(active_goals, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def achieved(self, request): """Get achieved goals.""" achieved_goals = self.get_queryset().filter(status='ACHIEVED') serializer = self.get_serializer(achieved_goals, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def overdue(self, request): """Get overdue goals.""" today = timezone.now().date() overdue_goals = self.get_queryset().filter( target_date__lt=today, status__in=['NOT_STARTED', 'IN_PROGRESS'] ) serializer = self.get_serializer(overdue_goals, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def statistics(self, request): """Get goal statistics.""" queryset = self.get_queryset() stats = { 'total_goals': queryset.count(), 'by_status': dict( queryset.values('status').annotate(count=Count('id')).values_list('status', 'count') ), 'average_progress': queryset.aggregate(avg_progress=Avg('progress_percentage'))['avg_progress'], 'achieved_count': queryset.filter(status='ACHIEVED').count(), 'in_progress_count': queryset.filter(status='IN_PROGRESS').count(), 'overdue_count': queryset.filter( target_date__lt=timezone.now().date(), status__in=['NOT_STARTED', 'IN_PROGRESS'] ).count(), } return Response(stats) @action(detail=True, methods=['post']) def update_progress(self, request, pk=None): """Update goal progress percentage.""" goal = self.get_object() progress = request.data.get('progress_percentage') if progress is None: return Response( {'error': 'progress_percentage required'}, status=status.HTTP_400_BAD_REQUEST ) try: progress = int(progress) if not 0 <= progress <= 100: raise ValueError except (ValueError, TypeError): return Response( {'error': 'progress_percentage must be between 0 and 100'}, status=status.HTTP_400_BAD_REQUEST ) goal.progress_percentage = progress # Auto-update status based on progress if progress == 0: goal.status = 'NOT_STARTED' elif progress == 100: goal.status = 'ACHIEVED' goal.achieved_date = timezone.now().date() else: goal.status = 'IN_PROGRESS' goal.save() serializer = self.get_serializer(goal) return Response(serializer.data) class PsychologyProgressReportViewSet(viewsets.ModelViewSet): """ API endpoint for psychology progress reports. Provides CRUD operations and additional actions for progress reports. """ queryset = PsychologyProgressReport.objects.all() serializer_class = PsychologyProgressReportSerializer permission_classes = [IsAuthenticated] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields = ['patient', 'provider', 'continue_treatment', 'tenant'] search_fields = ['patient__first_name_en', 'patient__last_name_en', 'patient__mrn', 'presenting_problems_summary', 'overall_progress', 'recommendations'] ordering_fields = ['report_date', 'created_at'] ordering = ['-report_date'] def get_queryset(self): """Filter queryset based on user permissions.""" queryset = super().get_queryset() return queryset.select_related('patient', 'provider', 'tenant') @action(detail=False, methods=['get']) def recent(self, request): """Get reports from the last 90 days.""" ninety_days_ago = timezone.now().date() - timedelta(days=90) recent_reports = self.get_queryset().filter( report_date__gte=ninety_days_ago ) serializer = self.get_serializer(recent_reports, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def discharge_ready(self, request): """Get reports recommending discharge.""" discharge_reports = self.get_queryset().filter(continue_treatment=False) serializer = self.get_serializer(discharge_reports, many=True) return Response(serializer.data) @action(detail=False, methods=['get']) def statistics(self, request): """Get progress report statistics.""" queryset = self.get_queryset() stats = { 'total_reports': queryset.count(), 'continue_treatment_count': queryset.filter(continue_treatment=True).count(), 'discharge_recommended_count': queryset.filter(continue_treatment=False).count(), 'average_attendance_rate': queryset.aggregate( avg_attendance=Avg('sessions_attended') / Avg('sessions_scheduled') * 100 ), 'signed_count': queryset.filter(signed_by__isnull=False).count(), 'unsigned_count': queryset.filter(signed_by__isnull=True).count(), } return Response(stats)