From 8946d5fda7f63f94803c4903cf5c878290408660 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Tue, 23 May 2023 16:21:36 +0530 Subject: [PATCH 01/17] used prefetch_related method to optimize the query performed to fetch a many to many relationship --- care/users/api/serializers/user.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index e3b0edc0db..ad594f1ceb 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,11 +358,6 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = serializers.SerializerMethodField() - - def get_skills(self, obj): - qs = obj.skills.filter(userskill__deleted=False) - return SkillSerializer(qs, many=True).data class Meta: model = User @@ -382,6 +377,14 @@ class Meta: "skills", ) + def to_representation(self, instance): + representation = super().to_representation(instance) + instance = User.objects.prefetch_related("skills").get(pk=instance.pk) + skills = instance.skills.filter(userskill__deleted=False) + skills_data = SkillSerializer(skills, many=True).data + representation["skills"] = skills_data + return representation + class UserListSerializer(serializers.ModelSerializer): local_body_object = LocalBodySerializer(source="local_body", read_only=True) From 7d410fdb541859ccee1e8e51bdbd1d50d831207f Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:12:51 +0530 Subject: [PATCH 02/17] Revert "add direnv support (#1304)" This reverts commit f6136618821e17278bd46824a0bcd9e3faad1960. --- .envrc | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .envrc diff --git a/.envrc b/.envrc deleted file mode 100644 index f5f5cd5cd5..0000000000 --- a/.envrc +++ /dev/null @@ -1,2 +0,0 @@ -source .venv/bin/activate; unset PS1 -dotenv From 7179fdf297aac1c4a25d0b756e2d5881a1247d4d Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:17:28 +0530 Subject: [PATCH 03/17] Revert "Revert "add direnv support (#1304)"" This reverts commit 7d410fdb541859ccee1e8e51bdbd1d50d831207f. --- .envrc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..f5f5cd5cd5 --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +source .venv/bin/activate; unset PS1 +dotenv From 9cb5f7c0cf3145ddeb1d8de3c1436dac3a34563b Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:18:01 +0530 Subject: [PATCH 04/17] Revert "used prefetch_related method to optimize the query performed to fetch a many to many relationship" This reverts commit 8946d5fda7f63f94803c4903cf5c878290408660. --- care/users/api/serializers/user.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index ad594f1ceb..e3b0edc0db 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,6 +358,11 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) + skills = serializers.SerializerMethodField() + + def get_skills(self, obj): + qs = obj.skills.filter(userskill__deleted=False) + return SkillSerializer(qs, many=True).data class Meta: model = User @@ -377,14 +382,6 @@ class Meta: "skills", ) - def to_representation(self, instance): - representation = super().to_representation(instance) - instance = User.objects.prefetch_related("skills").get(pk=instance.pk) - skills = instance.skills.filter(userskill__deleted=False) - skills_data = SkillSerializer(skills, many=True).data - representation["skills"] = skills_data - return representation - class UserListSerializer(serializers.ModelSerializer): local_body_object = LocalBodySerializer(source="local_body", read_only=True) From 7000a38bafd16e789ccf6ffc5f9a1f41d0c34429 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 02:17:43 +0530 Subject: [PATCH 05/17] used prefetch where we are querying the skills using UserAssigned Serializer --- care/facility/api/viewsets/facility_users.py | 20 ++++++++++++++------ care/users/api/serializers/user.py | 6 +----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index fc8c4ecb86..2fc1e751a5 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,3 +1,5 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Prefetch from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -6,12 +8,14 @@ from care.facility.models.facility import Facility from care.users.api.serializers.user import UserAssignedSerializer -from care.users.models import User +from care.users.models import Skill, User class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role]) + user_type = filters.TypedChoiceFilter( + choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role], + ) class Meta: model = User @@ -21,13 +25,17 @@ class Meta: class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): serializer_class = UserAssignedSerializer filterset_class = UserFilter - queryset = User.objects.all() + queryset = User.objects.all().prefetch_related( + Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) + ) permission_classes = [IsAuthenticated] filter_backends = [filters.DjangoFilterBackend] def get_queryset(self): try: - facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) + facility = Facility.objects.get( + external_id=self.kwargs.get("facility_external_id") + ) return facility.users.filter(deleted=False).order_by("-last_login") - except: + except ObjectDoesNotExist: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index e3b0edc0db..f3d418af3d 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,11 +358,7 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = serializers.SerializerMethodField() - - def get_skills(self, obj): - qs = obj.skills.filter(userskill__deleted=False) - return SkillSerializer(qs, many=True).data + skills = SkillSerializer(many=True, read_only=True) class Meta: model = User From 5fbe14443587c59e4bfe814685dc9298e037e41b Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 03:58:30 +0530 Subject: [PATCH 06/17] made neccessary changes to filter for having admitted but no bed assigned --- care/facility/api/viewsets/patient.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index b875ce635c..d9c87ebd6c 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -147,8 +147,20 @@ def filter_by_category(self, queryset, name, value): field_name="last_consultation__symptoms_onset_date" ) last_consultation_admitted_bed_type_list = MultiSelectFilter( - field_name="last_consultation__current_bed__bed__bed_type" + field_name="last_consultation__current_bed__bed__bed_type", + method="filter_by_bed_type", ) + + def filter_by_bed_type(self, queryset, name, value): + if value == "None": + queryset = queryset.filter(last_consultation__current_bed=None) + else: + queryset = queryset.filter( + last_consultation__current_bed__bed__bed_type=value + ) + + return queryset + last_consultation_admitted_bed_type = CareChoiceFilter( field_name="last_consultation__current_bed__bed__bed_type", choice_dict=REVERSE_BED_TYPES, From 719129eef2984db896131882526c217bdb30cd50 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 19:21:42 +0530 Subject: [PATCH 07/17] Revert "used prefetch where we are querying the skills using UserAssigned Serializer" This reverts commit 7000a38bafd16e789ccf6ffc5f9a1f41d0c34429. --- care/facility/api/viewsets/facility_users.py | 20 ++++++-------------- care/users/api/serializers/user.py | 6 +++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index 2fc1e751a5..fc8c4ecb86 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,5 +1,3 @@ -from django.core.exceptions import ObjectDoesNotExist -from django.db.models import Prefetch from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -8,14 +6,12 @@ from care.facility.models.facility import Facility from care.users.api.serializers.user import UserAssignedSerializer -from care.users.models import Skill, User +from care.users.models import User class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter( - choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role], - ) + user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role]) class Meta: model = User @@ -25,17 +21,13 @@ class Meta: class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): serializer_class = UserAssignedSerializer filterset_class = UserFilter - queryset = User.objects.all().prefetch_related( - Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) - ) + queryset = User.objects.all() permission_classes = [IsAuthenticated] filter_backends = [filters.DjangoFilterBackend] def get_queryset(self): try: - facility = Facility.objects.get( - external_id=self.kwargs.get("facility_external_id") - ) + facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) return facility.users.filter(deleted=False).order_by("-last_login") - except ObjectDoesNotExist: + except: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index f3d418af3d..e3b0edc0db 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,7 +358,11 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = SkillSerializer(many=True, read_only=True) + skills = serializers.SerializerMethodField() + + def get_skills(self, obj): + qs = obj.skills.filter(userskill__deleted=False) + return SkillSerializer(qs, many=True).data class Meta: model = User From f201c9bb0dbc2017f56901fbfcef1dbe1120ed7c Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sun, 28 May 2023 00:15:51 +0530 Subject: [PATCH 08/17] updated the view to handle none option for bed type --- care/facility/api/viewsets/patient.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index d9c87ebd6c..5967fefee5 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -152,14 +152,19 @@ def filter_by_category(self, queryset, name, value): ) def filter_by_bed_type(self, queryset, name, value): - if value == "None": - queryset = queryset.filter(last_consultation__current_bed=None) - else: - queryset = queryset.filter( - last_consultation__current_bed__bed__bed_type=value - ) - - return queryset + values = value.split(",") + union_queryset = PatientRegistration.objects.none() + for val in values: + val.strip() + if val == "8": + union_queryset |= queryset.filter( + last_consultation__current_bed__isnull=True + ) + else: + union_queryset |= queryset.filter( + last_consultation__current_bed__bed__bed_type=val + ) + return union_queryset last_consultation_admitted_bed_type = CareChoiceFilter( field_name="last_consultation__current_bed__bed__bed_type", From b5a5b061608ed571a7c2d9e2b7a46acd1249a2df Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sun, 28 May 2023 21:19:55 +0530 Subject: [PATCH 09/17] changed value 8 into None for None option --- care/facility/api/viewsets/patient.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 5967fefee5..cd41cb5776 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -155,8 +155,8 @@ def filter_by_bed_type(self, queryset, name, value): values = value.split(",") union_queryset = PatientRegistration.objects.none() for val in values: - val.strip() - if val == "8": + val = val.strip() + if val == "None": union_queryset |= queryset.filter( last_consultation__current_bed__isnull=True ) From 6c89ff4f424f50691f008c4285c900d33cab24a2 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Mon, 29 May 2023 16:35:54 +0530 Subject: [PATCH 10/17] made use of Q function to write the filter --- care/facility/api/viewsets/patient.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index cd41cb5776..11b56411aa 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -153,18 +153,16 @@ def filter_by_category(self, queryset, name, value): def filter_by_bed_type(self, queryset, name, value): values = value.split(",") - union_queryset = PatientRegistration.objects.none() + filter_q = Q() + for val in values: val = val.strip() if val == "None": - union_queryset |= queryset.filter( - last_consultation__current_bed__isnull=True - ) + filter_q |= Q(last_consultation__current_bed__isnull=True) else: - union_queryset |= queryset.filter( - last_consultation__current_bed__bed__bed_type=val - ) - return union_queryset + filter_q |= Q(last_consultation__current_bed__bed__bed_type=val) + + return queryset.filter(filter_q) last_consultation_admitted_bed_type = CareChoiceFilter( field_name="last_consultation__current_bed__bed__bed_type", From 883ef24065624d1246a49545922b322fb782ac6b Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Wed, 7 Jun 2023 20:23:00 +0530 Subject: [PATCH 11/17] made use of in lookup --- care/facility/api/viewsets/patient.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 11b56411aa..1565528dd7 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -155,12 +155,12 @@ def filter_by_bed_type(self, queryset, name, value): values = value.split(",") filter_q = Q() - for val in values: - val = val.strip() - if val == "None": - filter_q |= Q(last_consultation__current_bed__isnull=True) - else: - filter_q |= Q(last_consultation__current_bed__bed__bed_type=val) + try: + values.remove("None") + filter_q |= Q(last_consultation__current_bed__isnull=True) + except KeyError: + pass + filter_q |= Q(ast_consultation__current_bed__bed__bed_type__in=values) return queryset.filter(filter_q) From 91e5535760853b17fbbd64c34bb72f1982b1df5f Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Wed, 7 Jun 2023 20:26:41 +0530 Subject: [PATCH 12/17] fix --- care/facility/api/viewsets/patient.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 1565528dd7..02cd697134 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -160,7 +160,9 @@ def filter_by_bed_type(self, queryset, name, value): filter_q |= Q(last_consultation__current_bed__isnull=True) except KeyError: pass - filter_q |= Q(ast_consultation__current_bed__bed__bed_type__in=values) + + if values: + filter_q |= Q(ast_consultation__current_bed__bed__bed_type__in=values) return queryset.filter(filter_q) From 436314cf03104c1b34c4e04f5e3ea22b5ae4a126 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Thu, 15 Jun 2023 01:26:40 +0530 Subject: [PATCH 13/17] added tests and minor fixes in code --- care/facility/api/viewsets/patient.py | 4 +- care/facility/tests/test_patientfilterset.py | 123 +++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 care/facility/tests/test_patientfilterset.py diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 02cd697134..3a64b21e57 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -158,11 +158,11 @@ def filter_by_bed_type(self, queryset, name, value): try: values.remove("None") filter_q |= Q(last_consultation__current_bed__isnull=True) - except KeyError: + except ValueError: pass if values: - filter_q |= Q(ast_consultation__current_bed__bed__bed_type__in=values) + filter_q |= Q(last_consultation__current_bed__bed__bed_type__in=values) return queryset.filter(filter_q) diff --git a/care/facility/tests/test_patientfilterset.py b/care/facility/tests/test_patientfilterset.py new file mode 100644 index 0000000000..a980305c37 --- /dev/null +++ b/care/facility/tests/test_patientfilterset.py @@ -0,0 +1,123 @@ +from django.test import TestCase +from django.utils import timezone + +from care.facility.api.viewsets.patient import PatientFilterSet +from care.facility.models import ( + AssetLocation, + Bed, + ConsultationBed, + Facility, + PatientConsultation, + PatientRegistration, + State, +) +from care.facility.tests.mixins import TestClassMixin + + +class PatientFilterSetTestCase(TestClassMixin, TestCase): + def setUp(self): + super().setUp() + self.creator = self.users[0] + state = State.objects.create(name="Kerala") + + # create patient registrations + + patient_data = {"gender": 1, "age": 30, "is_antenatal": False, "state": state} + + self.patient1 = PatientRegistration.objects.create(**patient_data) + self.patient2 = PatientRegistration.objects.create(**patient_data) + self.patient3 = PatientRegistration.objects.create(**patient_data) + + # Create Facility + sample_data = { + "name": "Hospital X", + "ward": self.creator.ward, + "local_body": self.creator.local_body, + "district": self.creator.district, + "state": self.creator.state, + "facility_type": 1, + "address": "Nearby", + "pincode": 390024, + "features": [], + } + self.facility = Facility.objects.create( + external_id="550e8400-e29b-41d4-a716-446655440000", + created_by=self.creator, + **sample_data, + ) + + # create asset + asset1 = AssetLocation.objects.create( + name="asset1", location_type=1, facility=self.facility + ) + + # create beds + bed1_data = { + "name": "bed 1", + "bed_type": 1, + "location": asset1, + "facility": self.facility, + } + bed2_data = { + "name": "bed 2", + "bed_type": 2, + "location": asset1, + "facility": self.facility, + } + + bed1 = Bed.objects.create(**bed1_data) + bed2 = Bed.objects.create(**bed2_data) + + # create consultations + consultation1 = PatientConsultation.objects.create( + patient=self.patient1, + facility=self.facility, + ) + consultation2 = PatientConsultation.objects.create( + patient=self.patient2, facility=self.facility + ) + consultation3 = PatientConsultation.objects.create( + patient=self.patient3, facility=self.facility + ) + + # consultation beds + consultation_bed1 = ConsultationBed.objects.create( + consultation=consultation1, bed=bed1, start_date=timezone.now() + ) + consultation_bed2 = ConsultationBed.objects.create( + consultation=consultation2, bed=bed2, start_date=timezone.now() + ) + + consultation1.current_bed = consultation_bed1 + consultation1.save(update_fields=["current_bed"]) + consultation2.current_bed = consultation_bed2 + consultation2.save(update_fields=["current_bed"]) + # None for consultation 3 + + self.patient1.last_consultation = consultation1 + self.patient1.save(update_fields=["last_consultation"]) + self.patient2.last_consultation = consultation2 + self.patient2.save(update_fields=["last_consultation"]) + self.patient3.last_consultation = consultation3 + self.patient3.save(update_fields=["last_consultation"]) + + def test_filter_by_bed_type(self): + # Create the filter set instance with the desired queryset + filterset = PatientFilterSet(queryset=PatientRegistration.objects.all()) + + # Apply the filter manually + filtered_queryset = filterset.filter_by_bed_type( + name="last_consultation_admitted_bed_type_list", + value="1,None", + queryset=PatientRegistration.objects.all(), + ) + + # Assert the expected results + self.assertEqual(len(filtered_queryset), 2) + self.assertTrue(self.patient1 in filtered_queryset) + self.assertFalse(self.patient2 in filtered_queryset) + self.assertTrue(self.patient3 in filtered_queryset) + self.assertEqual(filtered_queryset[0].last_consultation.current_bed, None) + self.assertEqual( + filtered_queryset[1].last_consultation.current_bed.bed.bed_type, 1 + ) From e8011e9a4da9242d87e950c6efdbfc3e2ebcad1e Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Thu, 15 Jun 2023 23:07:05 +0530 Subject: [PATCH 14/17] updated the test to make use of testbase --- care/facility/tests/test_patientfilterset.py | 89 +++++++------------- 1 file changed, 29 insertions(+), 60 deletions(-) diff --git a/care/facility/tests/test_patientfilterset.py b/care/facility/tests/test_patientfilterset.py index a980305c37..d843f6ba2e 100644 --- a/care/facility/tests/test_patientfilterset.py +++ b/care/facility/tests/test_patientfilterset.py @@ -6,45 +6,20 @@ AssetLocation, Bed, ConsultationBed, - Facility, - PatientConsultation, PatientRegistration, - State, ) -from care.facility.tests.mixins import TestClassMixin +from care.utils.tests.test_base import TestBase -class PatientFilterSetTestCase(TestClassMixin, TestCase): - def setUp(self): - super().setUp() - self.creator = self.users[0] - state = State.objects.create(name="Kerala") +class PatientFilterSetTestCase(TestBase, TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() - # create patient registrations - - patient_data = {"gender": 1, "age": 30, "is_antenatal": False, "state": state} - - self.patient1 = PatientRegistration.objects.create(**patient_data) - self.patient2 = PatientRegistration.objects.create(**patient_data) - self.patient3 = PatientRegistration.objects.create(**patient_data) - - # Create Facility - sample_data = { - "name": "Hospital X", - "ward": self.creator.ward, - "local_body": self.creator.local_body, - "district": self.creator.district, - "state": self.creator.state, - "facility_type": 1, - "address": "Nearby", - "pincode": 390024, - "features": [], - } - self.facility = Facility.objects.create( - external_id="550e8400-e29b-41d4-a716-446655440000", - created_by=self.creator, - **sample_data, - ) + def test_filter_by_bed_type(self): + patient1 = self.create_patient(name="patient1") + patient2 = self.create_patient(name="patient2") + patient3 = self.create_patient(name="patient3") # create asset asset1 = AssetLocation.objects.create( @@ -68,16 +43,14 @@ def setUp(self): bed1 = Bed.objects.create(**bed1_data) bed2 = Bed.objects.create(**bed2_data) - # create consultations - consultation1 = PatientConsultation.objects.create( - patient=self.patient1, - facility=self.facility, + consultation1 = self.create_consultation( + patient=patient1, facility=self.facility ) - consultation2 = PatientConsultation.objects.create( - patient=self.patient2, facility=self.facility + consultation2 = self.create_consultation( + patient=patient2, facility=self.facility ) - consultation3 = PatientConsultation.objects.create( - patient=self.patient3, facility=self.facility + consultation3 = self.create_consultation( + patient=patient3, facility=self.facility ) # consultation beds @@ -94,30 +67,26 @@ def setUp(self): consultation2.save(update_fields=["current_bed"]) # None for consultation 3 - self.patient1.last_consultation = consultation1 - self.patient1.save(update_fields=["last_consultation"]) - self.patient2.last_consultation = consultation2 - self.patient2.save(update_fields=["last_consultation"]) - self.patient3.last_consultation = consultation3 - self.patient3.save(update_fields=["last_consultation"]) + patient1.last_consultation = consultation1 + patient1.save(update_fields=["last_consultation"]) + patient2.last_consultation = consultation2 + patient2.save(update_fields=["last_consultation"]) + patient3.last_consultation = consultation3 + patient3.save(update_fields=["last_consultation"]) - def test_filter_by_bed_type(self): - # Create the filter set instance with the desired queryset + # Create the filter set instance filterset = PatientFilterSet(queryset=PatientRegistration.objects.all()) - # Apply the filter manually + # filter filtered_queryset = filterset.filter_by_bed_type( name="last_consultation_admitted_bed_type_list", value="1,None", queryset=PatientRegistration.objects.all(), ) - # Assert the expected results - self.assertEqual(len(filtered_queryset), 2) - self.assertTrue(self.patient1 in filtered_queryset) - self.assertFalse(self.patient2 in filtered_queryset) - self.assertTrue(self.patient3 in filtered_queryset) - self.assertEqual(filtered_queryset[0].last_consultation.current_bed, None) - self.assertEqual( - filtered_queryset[1].last_consultation.current_bed.bed.bed_type, 1 - ) + # Assert + self.assertEqual(len(filtered_queryset), 3) # patient, patient1 and patient3 + self.assertTrue(patient1 in filtered_queryset) + self.assertFalse(patient2 in filtered_queryset) + self.assertTrue(patient3 in filtered_queryset) + self.assertTrue(self.patient in filtered_queryset) From 6056779e2eb94eb372fc1265ece09d22c1a8ab66 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Tue, 29 Aug 2023 23:14:54 +0530 Subject: [PATCH 15/17] minor refactor Signed-off-by: Aakash Singh --- care/facility/api/viewsets/patient.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 83af398ae8..b78a7062e2 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -147,11 +147,13 @@ def filter_by_category(self, queryset, name, value): field_name="last_consultation__symptoms_onset_date" ) last_consultation_admitted_bed_type_list = MultiSelectFilter( - field_name="last_consultation__current_bed__bed__bed_type", method="filter_by_bed_type", ) def filter_by_bed_type(self, queryset, name, value): + if not value: + return queryset + values = value.split(",") filter_q = Q() From 536ab303ee70c735f11f16bb7fa5ab3d8ca2a56b Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Tue, 29 Aug 2023 23:15:04 +0530 Subject: [PATCH 16/17] add more tests Signed-off-by: Aakash Singh --- care/facility/tests/test_patientfilterset.py | 30 +++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/care/facility/tests/test_patientfilterset.py b/care/facility/tests/test_patientfilterset.py index d843f6ba2e..be962b791c 100644 --- a/care/facility/tests/test_patientfilterset.py +++ b/care/facility/tests/test_patientfilterset.py @@ -1,4 +1,3 @@ -from django.test import TestCase from django.utils import timezone from care.facility.api.viewsets.patient import PatientFilterSet @@ -11,7 +10,7 @@ from care.utils.tests.test_base import TestBase -class PatientFilterSetTestCase(TestBase, TestCase): +class PatientFilterSetTestCase(TestBase): @classmethod def setUpClass(cls): super().setUpClass() @@ -19,7 +18,7 @@ def setUpClass(cls): def test_filter_by_bed_type(self): patient1 = self.create_patient(name="patient1") patient2 = self.create_patient(name="patient2") - patient3 = self.create_patient(name="patient3") + patient3 = self.patient # create asset asset1 = AssetLocation.objects.create( @@ -83,10 +82,27 @@ def test_filter_by_bed_type(self): value="1,None", queryset=PatientRegistration.objects.all(), ) - - # Assert - self.assertEqual(len(filtered_queryset), 3) # patient, patient1 and patient3 + self.assertEqual(len(filtered_queryset), 2) # patient, patient1 and patient3 self.assertTrue(patient1 in filtered_queryset) self.assertFalse(patient2 in filtered_queryset) self.assertTrue(patient3 in filtered_queryset) - self.assertTrue(self.patient in filtered_queryset) + + filtered_queryset = filterset.filter_by_bed_type( + name="last_consultation_admitted_bed_type_list", + value="None", + queryset=PatientRegistration.objects.all(), + ) + self.assertEqual(len(filtered_queryset), 1) + self.assertFalse(patient1 in filtered_queryset) + self.assertFalse(patient2 in filtered_queryset) + self.assertTrue(patient3 in filtered_queryset) + + filtered_queryset = filterset.filter_by_bed_type( + name="last_consultation_admitted_bed_type_list", + value="2", + queryset=PatientRegistration.objects.all(), + ) + self.assertEqual(len(filtered_queryset), 1) + self.assertFalse(patient1 in filtered_queryset) + self.assertTrue(patient2 in filtered_queryset) + self.assertFalse(patient3 in filtered_queryset) From 61da24eaa9137db5ccca5fcf73615292f9148968 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Wed, 6 Sep 2023 16:36:45 +0530 Subject: [PATCH 17/17] refactor --- care/facility/api/viewsets/patient.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index b78a7062e2..0a502dc06a 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -157,12 +157,9 @@ def filter_by_bed_type(self, queryset, name, value): values = value.split(",") filter_q = Q() - try: - values.remove("None") + if "None" in values: filter_q |= Q(last_consultation__current_bed__isnull=True) - except ValueError: - pass - + values.remove("None") if values: filter_q |= Q(last_consultation__current_bed__bed__bed_type__in=values)