From d1b45e13aabc1387eac83799178baa8bd0cba05f Mon Sep 17 00:00:00 2001 From: Ashesh3 <3626859+Ashesh3@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:37:42 +0530 Subject: [PATCH 1/4] Add validation for patient transfers --- care/facility/api/serializers/patient.py | 26 ++++++++++++++++--- .../api/serializers/patient_consultation.py | 16 ++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/care/facility/api/serializers/patient.py b/care/facility/api/serializers/patient.py index e94fa0d25c..106668e4d0 100644 --- a/care/facility/api/serializers/patient.py +++ b/care/facility/api/serializers/patient.py @@ -3,7 +3,7 @@ from django.conf import settings from django.db import transaction from django.db.models import Q -from django.utils.timezone import make_aware, now +from django.utils.timezone import make_aware from rest_framework import serializers from care.abdm.api.serializers.abhanumber import AbhaNumberSerializer @@ -449,16 +449,32 @@ class PatientTransferSerializer(serializers.ModelSerializer): write_only=True, queryset=Facility.objects.all() ) patient = serializers.UUIDField(source="external_id", read_only=True) + last_consultation_discharge_date = serializers.DateTimeField( + write_only=True, required=True + ) class Meta: model = PatientRegistration - fields = ("facility", "year_of_birth", "patient", "facility_object") + fields = ( + "facility", + "year_of_birth", + "patient", + "facility_object", + "last_consultation_discharge_date", + ) def validate_year_of_birth(self, value): if self.instance and self.instance.year_of_birth != value: raise serializers.ValidationError("Year of birth does not match") return value + def validate_last_consultation_discharge_date(self, value): + if self.instance and self.instance.last_consultation.encounter_date >= value: + raise serializers.ValidationError( + "Discharge date should be after the last encounter date" + ) + return value + def create(self, validated_data): raise NotImplementedError @@ -471,14 +487,16 @@ def update(self, instance, validated_data): ).first() if consultation: - consultation.discharge_date = now() + consultation.discharge_date = validated_data[ + "last_consultation_discharge_date" + ] consultation.new_discharge_reason = NewDischargeReasonEnum.REFERRED consultation.current_bed = None consultation.save() ConsultationBed.objects.filter( consultation=consultation, end_date__isnull=True - ).update(end_date=now()) + ).update(end_date=validated_data["last_consultation_discharge_date"]) instance.save() return instance diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index ad0cd8ece3..b440ccbfcf 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -515,6 +515,22 @@ def validate_encounter_date(self, value): raise ValidationError( {"encounter_date": "This field value cannot be in the future."} ) + + last_consultation = ( + PatientConsultation.objects.filter( + patient=self.validated_data["patient"], discharge_date__isnull=False + ) + .order_by("-encounter_date") + .first() + ) + if last_consultation and value < last_consultation.encounter_date: + raise ValidationError( + { + "encounter_date": [ + "This field value must be greater than the last discharge date." + ] + } + ) return value def validate_patient_no(self, value): From 78ab88350a164a60725f0af4c2c6eee97bb23673 Mon Sep 17 00:00:00 2001 From: Ashesh3 <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:45:56 +0530 Subject: [PATCH 2/4] Move validation --- .../api/serializers/patient_consultation.py | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index b440ccbfcf..607732a63e 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -516,21 +516,6 @@ def validate_encounter_date(self, value): {"encounter_date": "This field value cannot be in the future."} ) - last_consultation = ( - PatientConsultation.objects.filter( - patient=self.validated_data["patient"], discharge_date__isnull=False - ) - .order_by("-encounter_date") - .first() - ) - if last_consultation and value < last_consultation.encounter_date: - raise ValidationError( - { - "encounter_date": [ - "This field value must be greater than the last discharge date." - ] - } - ) return value def validate_patient_no(self, value): @@ -639,6 +624,25 @@ def validate(self, attrs): if not self.instance and "create_diagnoses" not in validated: raise ValidationError({"create_diagnoses": ["This field is required."]}) + last_consultation = ( + PatientConsultation.objects.filter( + patient=validated["patient"], discharge_date__isnull=False + ) + .order_by("-encounter_date") + .first() + ) + if ( + last_consultation + and validated["encounter_date"] <= last_consultation.discharge_date + ): + raise ValidationError( + { + "encounter_date": [ + "This field value must be greater than the last discharge date." + ] + } + ) + return validated From 633bf5924b51a503cd7e55775c80a6005076bddf Mon Sep 17 00:00:00 2001 From: Ashesh3 <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 24 Apr 2024 11:00:26 +0530 Subject: [PATCH 3/4] Fix tests --- .../api/serializers/patient_consultation.py | 35 ++++++++++--------- care/facility/tests/test_patient_api.py | 17 +++++++++ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index 607732a63e..41d323c67f 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -624,24 +624,25 @@ def validate(self, attrs): if not self.instance and "create_diagnoses" not in validated: raise ValidationError({"create_diagnoses": ["This field is required."]}) - last_consultation = ( - PatientConsultation.objects.filter( - patient=validated["patient"], discharge_date__isnull=False - ) - .order_by("-encounter_date") - .first() - ) - if ( - last_consultation - and validated["encounter_date"] <= last_consultation.discharge_date - ): - raise ValidationError( - { - "encounter_date": [ - "This field value must be greater than the last discharge date." - ] - } + if "encounter_date" in validated and "patient" in validated: + last_consultation = ( + PatientConsultation.objects.filter( + patient=validated["patient"], discharge_date__isnull=False + ) + .order_by("-encounter_date") + .first() ) + if ( + last_consultation + and validated["encounter_date"] <= last_consultation.discharge_date + ): + raise ValidationError( + { + "encounter_date": [ + "This field value must be greater than the last discharge date." + ] + } + ) return validated diff --git a/care/facility/tests/test_patient_api.py b/care/facility/tests/test_patient_api.py index d86f7fdd20..ecd9b0305e 100644 --- a/care/facility/tests/test_patient_api.py +++ b/care/facility/tests/test_patient_api.py @@ -465,6 +465,7 @@ def test_patient_transfer(self): { "year_of_birth": 1992, "facility": self.destination_facility.external_id, + "last_consultation_discharge_date": now().isoformat(), }, ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -482,6 +483,22 @@ def test_patient_transfer(self): ) self.assertIsNotNone(self.consultation.discharge_date) + def test_patient_transfer_with_invalid_discharge_date(self): + self.client.force_authenticate(user=self.super_user) + response = self.client.post( + f"/api/v1/patient/{self.patient.external_id}/transfer/", + { + "year_of_birth": 1992, + "facility": self.destination_facility.external_id, + "last_consultation_discharge_date": "2000-01-01T00:00:00Z", # This is before the consultation date + }, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.data["last_consultation_discharge_date"][0], + "Discharge date should be after the last encounter date", + ) + def test_transfer_with_active_consultation_same_facility(self): # Set the patient's facility to allow transfers self.patient.allow_transfer = True From e6ab2d577969db54522b7181bcb9a3dba1bd1717 Mon Sep 17 00:00:00 2001 From: Ashesh3 <3626859+Ashesh3@users.noreply.github.com> Date: Wed, 24 Apr 2024 11:05:03 +0530 Subject: [PATCH 4/4] Fix lint --- care/facility/api/serializers/patient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/care/facility/api/serializers/patient.py b/care/facility/api/serializers/patient.py index b83cc8daf7..9a54d49888 100644 --- a/care/facility/api/serializers/patient.py +++ b/care/facility/api/serializers/patient.py @@ -3,7 +3,7 @@ from django.conf import settings from django.db import transaction from django.db.models import Q -from django.utils.timezone import make_aware +from django.utils.timezone import make_aware, now from rest_framework import serializers from care.abdm.api.serializers.abhanumber import AbhaNumberSerializer