248 lines
8.8 KiB
Python
248 lines
8.8 KiB
Python
"""
|
|
Journeys views and viewsets
|
|
"""
|
|
from rest_framework import status, viewsets
|
|
from rest_framework.decorators import action
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
|
|
from apps.accounts.permissions import IsPXAdminOrHospitalAdmin
|
|
from apps.core.services import AuditService
|
|
|
|
from .models import (
|
|
PatientJourneyInstance,
|
|
PatientJourneyStageInstance,
|
|
PatientJourneyStageTemplate,
|
|
PatientJourneyTemplate,
|
|
)
|
|
from .serializers import (
|
|
PatientJourneyInstanceListSerializer,
|
|
PatientJourneyInstanceSerializer,
|
|
PatientJourneyStageInstanceSerializer,
|
|
PatientJourneyStageTemplateSerializer,
|
|
PatientJourneyTemplateSerializer,
|
|
)
|
|
|
|
|
|
class PatientJourneyTemplateViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
ViewSet for Journey Templates.
|
|
|
|
Permissions:
|
|
- PX Admins and Hospital Admins can manage templates
|
|
- Others can view templates
|
|
"""
|
|
queryset = PatientJourneyTemplate.objects.all()
|
|
serializer_class = PatientJourneyTemplateSerializer
|
|
permission_classes = [IsAuthenticated]
|
|
filterset_fields = ['journey_type', 'hospital', 'is_active', 'is_default', 'hospital__organization']
|
|
search_fields = ['name', 'name_ar', 'description']
|
|
ordering_fields = ['name', 'created_at']
|
|
ordering = ['hospital', 'journey_type', 'name']
|
|
|
|
def get_queryset(self):
|
|
"""Filter templates based on user role"""
|
|
queryset = super().get_queryset().select_related('hospital').prefetch_related('stages')
|
|
user = self.request.user
|
|
|
|
# PX Admins see all templates
|
|
if user.is_px_admin():
|
|
return queryset
|
|
|
|
# Hospital Admins see templates for their hospital
|
|
if user.is_hospital_admin() and user.hospital:
|
|
return queryset.filter(hospital=user.hospital)
|
|
|
|
# Others see templates for their hospital
|
|
if user.hospital:
|
|
return queryset.filter(hospital=user.hospital)
|
|
|
|
return queryset.none()
|
|
|
|
|
|
class PatientJourneyStageTemplateViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
ViewSet for Journey Stage Templates.
|
|
|
|
Permissions:
|
|
- PX Admins and Hospital Admins can manage stage templates
|
|
"""
|
|
queryset = PatientJourneyStageTemplate.objects.all()
|
|
serializer_class = PatientJourneyStageTemplateSerializer
|
|
permission_classes = [IsAuthenticated, IsPXAdminOrHospitalAdmin]
|
|
filterset_fields = ['journey_template', 'is_active', 'auto_send_survey']
|
|
search_fields = ['name', 'name_ar', 'code', 'trigger_event_code']
|
|
ordering_fields = ['order', 'name']
|
|
ordering = ['journey_template', 'order']
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset().select_related('journey_template', 'survey_template')
|
|
user = self.request.user
|
|
|
|
# PX Admins see all stage templates
|
|
if user.is_px_admin():
|
|
return queryset
|
|
|
|
# Hospital Admins see stage templates for their hospital
|
|
if user.is_hospital_admin() and user.hospital:
|
|
return queryset.filter(journey_template__hospital=user.hospital)
|
|
|
|
return queryset.none()
|
|
|
|
|
|
class PatientJourneyInstanceViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
ViewSet for Journey Instances.
|
|
|
|
Permissions:
|
|
- All authenticated users can view journey instances
|
|
- PX Admins and Hospital Admins can create/manage instances
|
|
"""
|
|
queryset = PatientJourneyInstance.objects.all()
|
|
permission_classes = [IsAuthenticated]
|
|
filterset_fields = [
|
|
'journey_template', 'journey_template__journey_type',
|
|
'patient', 'hospital', 'department', 'status',
|
|
'hospital__organization'
|
|
]
|
|
search_fields = ['encounter_id', 'patient__mrn', 'patient__first_name', 'patient__last_name']
|
|
ordering_fields = ['started_at', 'completed_at']
|
|
ordering = ['-started_at']
|
|
|
|
def get_serializer_class(self):
|
|
"""Use simplified serializer for list view"""
|
|
if self.action == 'list':
|
|
return PatientJourneyInstanceListSerializer
|
|
return PatientJourneyInstanceSerializer
|
|
|
|
def get_queryset(self):
|
|
"""Filter journey instances based on user role"""
|
|
queryset = super().get_queryset().select_related(
|
|
'journey_template', 'patient', 'hospital', 'department'
|
|
).prefetch_related('stage_instances__stage_template')
|
|
|
|
user = self.request.user
|
|
|
|
# PX Admins see all journey instances
|
|
if user.is_px_admin():
|
|
return queryset
|
|
|
|
# Hospital Admins see instances for their hospital
|
|
if user.is_hospital_admin() and user.hospital:
|
|
return queryset.filter(hospital=user.hospital)
|
|
|
|
# Department Managers see instances for their department
|
|
if user.is_department_manager() and user.department:
|
|
return queryset.filter(department=user.department)
|
|
|
|
# Others see instances for their hospital
|
|
if user.hospital:
|
|
return queryset.filter(hospital=user.hospital)
|
|
|
|
return queryset.none()
|
|
|
|
def perform_create(self, serializer):
|
|
"""
|
|
Create journey instance and initialize stage instances.
|
|
|
|
When a journey instance is created, automatically create
|
|
stage instances for all stages in the template.
|
|
"""
|
|
journey_instance = serializer.save()
|
|
|
|
# Create stage instances for all stages in the template
|
|
for stage_template in journey_instance.journey_template.stages.filter(is_active=True):
|
|
PatientJourneyStageInstance.objects.create(
|
|
journey_instance=journey_instance,
|
|
stage_template=stage_template
|
|
)
|
|
|
|
# Log journey creation
|
|
AuditService.log_from_request(
|
|
event_type='journey_started',
|
|
description=f"Journey started for encounter {journey_instance.encounter_id}",
|
|
request=self.request,
|
|
content_object=journey_instance,
|
|
metadata={
|
|
'journey_type': journey_instance.journey_template.journey_type,
|
|
'patient_mrn': journey_instance.patient.mrn
|
|
}
|
|
)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def progress(self, request, pk=None):
|
|
"""Get journey progress summary"""
|
|
journey = self.get_object()
|
|
|
|
stages = journey.stage_instances.select_related('stage_template').order_by('stage_template__order')
|
|
|
|
progress_data = {
|
|
'journey_id': str(journey.id),
|
|
'encounter_id': journey.encounter_id,
|
|
'patient': journey.patient.get_full_name(),
|
|
'journey_type': journey.journey_template.journey_type,
|
|
'status': journey.status,
|
|
'completion_percentage': journey.get_completion_percentage(),
|
|
'is_complete': journey.is_complete(),
|
|
'started_at': journey.started_at,
|
|
'completed_at': journey.completed_at,
|
|
'stages': [
|
|
{
|
|
'name': stage.stage_template.name,
|
|
'order': stage.stage_template.order,
|
|
'status': stage.status,
|
|
'completed_at': stage.completed_at,
|
|
'survey_sent': stage.survey_sent_at is not None,
|
|
}
|
|
for stage in stages
|
|
]
|
|
}
|
|
|
|
return Response(progress_data)
|
|
|
|
|
|
class PatientJourneyStageInstanceViewSet(viewsets.ReadOnlyModelViewSet):
|
|
"""
|
|
ViewSet for Journey Stage Instances (read-only).
|
|
|
|
Stage instances are created automatically and updated via event processing.
|
|
Manual updates should be done through the admin interface.
|
|
"""
|
|
queryset = PatientJourneyStageInstance.objects.all()
|
|
serializer_class = PatientJourneyStageInstanceSerializer
|
|
permission_classes = [IsAuthenticated]
|
|
filterset_fields = ['journey_instance', 'stage_template', 'status']
|
|
search_fields = ['journey_instance__encounter_id', 'stage_template__name']
|
|
ordering_fields = ['completed_at', 'created_at']
|
|
ordering = ['journey_instance', 'stage_template__order']
|
|
|
|
def get_queryset(self):
|
|
"""Filter stage instances based on user role"""
|
|
queryset = super().get_queryset().select_related(
|
|
'journey_instance',
|
|
'stage_template',
|
|
'physician',
|
|
'department',
|
|
'survey_instance'
|
|
)
|
|
|
|
user = self.request.user
|
|
|
|
# PX Admins see all stage instances
|
|
if user.is_px_admin():
|
|
return queryset
|
|
|
|
# Hospital Admins see instances for their hospital
|
|
if user.is_hospital_admin() and user.hospital:
|
|
return queryset.filter(journey_instance__hospital=user.hospital)
|
|
|
|
# Department Managers see instances for their department
|
|
if user.is_department_manager() and user.department:
|
|
return queryset.filter(journey_instance__department=user.department)
|
|
|
|
# Others see instances for their hospital
|
|
if user.hospital:
|
|
return queryset.filter(journey_instance__hospital=user.hospital)
|
|
|
|
return queryset.none()
|