Skip to content

Commit 73b2275

Browse files
committed
added first implementation of the patients-without-episodes server side APIs
1 parent 2ed5780 commit 73b2275

File tree

3 files changed

+82
-3
lines changed

3 files changed

+82
-3
lines changed

tmh_registry/registry/api/serializers.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,3 +670,45 @@ def get_discharge(self, obj):
670670
# Return the discharge date if available, otherwise None
671671
discharge = getattr(obj, 'discharge', None)
672672
return discharge.date if discharge else None
673+
674+
675+
class UnlinkedPatientSerializer(ModelSerializer):
676+
full_name = CharField()
677+
id = CharField()
678+
hospital_id = SerializerMethodField()
679+
patient_hospital_id = SerializerMethodField()
680+
681+
class Meta:
682+
model = Patient
683+
fields = ['id', 'full_name', 'hospital_id', 'patient_hospital_id']
684+
685+
def get_hospital_id(self, obj):
686+
request = self.context.get('request')
687+
if not request:
688+
return None
689+
690+
try:
691+
medical_personnel = request.user.medical_personnel
692+
preferred_hospital = medical_personnel.preferred_hospital.hospital
693+
except Exception:
694+
return None
695+
696+
return preferred_hospital.id
697+
698+
def get_patient_hospital_id(self, obj):
699+
request = self.context.get('request')
700+
if not request:
701+
return None
702+
703+
try:
704+
medical_personnel = request.user.medical_personnel
705+
preferred_hospital = medical_personnel.preferred_hospital.hospital
706+
except Exception:
707+
return None
708+
709+
mapping = PatientHospitalMapping.objects.filter(
710+
patient=obj,
711+
hospital=preferred_hospital
712+
).first()
713+
714+
return mapping.patient_hospital_id if mapping else None

tmh_registry/registry/api/viewsets.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.core.exceptions import ObjectDoesNotExist
2-
from django.db.models import CharField, Q, Count, Max
2+
from django.db.models import CharField, Q, Count, Max, OuterRef, Exists
33
from django.db.models.functions import Cast
44
from django.utils.decorators import method_decorator
55
from django_filters import ( # pylint: disable=E0401
@@ -41,7 +41,7 @@
4141
PatientHospitalMappingWriteSerializer,
4242
PreferredHospitalReadSerializer,
4343
ReadPatientSerializer,
44-
SurgeonEpisodeSummarySerializer, OwnedEpisodeSerializer,
44+
SurgeonEpisodeSummarySerializer, OwnedEpisodeSerializer, UnlinkedPatientSerializer,
4545
)
4646
from ...users.models import MedicalPersonnel
4747

@@ -365,3 +365,39 @@ def get_serializer_class(self):
365365
return FollowUpWriteSerializer
366366

367367
raise NotImplementedError
368+
369+
370+
class UnlinkedPatientsViewSet(viewsets.ReadOnlyModelViewSet):
371+
serializer_class = UnlinkedPatientSerializer
372+
permission_classes = [IsAuthenticated]
373+
pagination_class = None
374+
375+
def get_queryset(self):
376+
user = self.request.user
377+
378+
try:
379+
medical_personnel = user.medical_personnel
380+
preferred_hospital = medical_personnel.preferred_hospital.hospital
381+
except (MedicalPersonnel.DoesNotExist, PreferredHospital.DoesNotExist):
382+
return Patient.objects.none()
383+
384+
# Subquery: check if any Episode exists for a given patient in the preferred hospital
385+
has_episode_subquery = Episode.objects.filter(
386+
patient_hospital_mapping__patient=OuterRef('pk'),
387+
patient_hospital_mapping__hospital=preferred_hospital
388+
)
389+
390+
patients = Patient.objects.filter(
391+
hospital_mappings__hospital=preferred_hospital
392+
).annotate(
393+
has_episode=Exists(has_episode_subquery)
394+
).filter(
395+
has_episode=False
396+
).distinct().prefetch_related('hospital_mappings')
397+
398+
return patients
399+
400+
def get_serializer_context(self):
401+
context = super().get_serializer_context()
402+
context['request'] = self.request
403+
return context

tmh_registry/registry/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
PatientViewSet,
1111
PreferredHospitalViewSet,
1212
SurgeonEpisodeSummaryViewSet,
13-
OwnedEpisodesViewSet,
13+
OwnedEpisodesViewSet, UnlinkedPatientsViewSet,
1414
)
1515

1616
router = DefaultRouter()
@@ -23,6 +23,7 @@
2323
router.register(r"preferred-hospital", PreferredHospitalViewSet, basename='preferred-hospital')
2424
router.register(r'surgeon-episode-summary', SurgeonEpisodeSummaryViewSet, basename='surgeon-episode-summary')
2525
router.register(r"owned-episodes", OwnedEpisodesViewSet, basename='owned-episodes')
26+
router.register(r'unlinked-patients', UnlinkedPatientsViewSet, basename='unlinked-patients')
2627

2728

2829
urlpatterns = [

0 commit comments

Comments
 (0)