diff --git a/care/facility/api/serializers/patient.py b/care/facility/api/serializers/patient.py index 6e9aa27e50..58f1cd7e55 100644 --- a/care/facility/api/serializers/patient.py +++ b/care/facility/api/serializers/patient.py @@ -33,6 +33,7 @@ BLOOD_GROUP_CHOICES, DISEASE_STATUS_CHOICES, DiseaseStatusEnum, + NewDischargeReasonEnum, ) from care.facility.models.patient_consultation import PatientConsultation from care.facility.models.patient_external_test import PatientExternalTest @@ -462,7 +463,7 @@ def save(self, **kwargs): if consultation: consultation.discharge_date = now() - consultation.discharge_reason = "REF" + consultation.new_discharge_reason = NewDischargeReasonEnum.REFERRED consultation.current_bed = None consultation.save() diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index 401d9f3539..216871954b 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -31,8 +31,8 @@ ) from care.facility.models.notification import Notification from care.facility.models.patient_base import ( - DISCHARGE_REASON_CHOICES, SYMPTOM_CHOICES, + NewDischargeReasonEnum, RouteToFacility, SuggestionChoices, ) @@ -111,8 +111,8 @@ class PatientConsultationSerializer(serializers.ModelSerializer): queryset=User.objects.all(), required=False, allow_null=True ) - discharge_reason = serializers.ChoiceField( - choices=DISCHARGE_REASON_CHOICES, read_only=True, required=False + new_discharge_reason = serializers.ChoiceField( + choices=NewDischargeReasonEnum.choices, read_only=True, required=False ) discharge_notes = serializers.CharField(read_only=True) @@ -558,8 +558,8 @@ def validate(self, attrs): class PatientConsultationDischargeSerializer(serializers.ModelSerializer): - discharge_reason = serializers.ChoiceField( - choices=DISCHARGE_REASON_CHOICES, required=True + new_discharge_reason = serializers.ChoiceField( + choices=NewDischargeReasonEnum.choices, required=True ) discharge_notes = serializers.CharField(required=False, allow_blank=True) @@ -596,7 +596,7 @@ def get_discharge_prn_prescription(self, consultation): class Meta: model = PatientConsultation fields = ( - "discharge_reason", + "new_discharge_reason", "referred_to", "referred_to_external", "discharge_notes", @@ -619,11 +619,11 @@ def validate(self, attrs): ], } ) - if attrs.get("discharge_reason") != "EXP": + if attrs.get("new_discharge_reason") != NewDischargeReasonEnum.EXPIRED: attrs.pop("death_datetime", None) attrs.pop("death_confirmed_doctor", None) - if attrs.get("discharge_reason") == "EXP": + if attrs.get("new_discharge_reason") == NewDischargeReasonEnum.EXPIRED: if not attrs.get("death_datetime"): raise ValidationError({"death_datetime": "This field is required"}) if attrs.get("death_datetime") > now(): diff --git a/care/facility/api/serializers/shifting.py b/care/facility/api/serializers/shifting.py index 8951a7691b..4a82b39923 100644 --- a/care/facility/api/serializers/shifting.py +++ b/care/facility/api/serializers/shifting.py @@ -24,6 +24,7 @@ ) from care.facility.models.bed import ConsultationBed from care.facility.models.notification import Notification +from care.facility.models.patient_base import NewDischargeReasonEnum from care.facility.models.patient_consultation import PatientConsultation from care.users.api.serializers.user import UserBaseMinimumSerializer from care.utils.notification_handler import NotificationGenerator @@ -70,9 +71,9 @@ def discharge_patient(patient: PatientRegistration): PatientConsultation.objects.filter(patient=patient).order_by("-id").first() ) if last_consultation: - reason = "REF" + reason = NewDischargeReasonEnum.REFERRED notes = "Patient Shifted to another facility" - last_consultation.discharge_reason = reason + last_consultation.new_discharge_reason = reason last_consultation.discharge_notes = notes last_consultation.discharge_date = current_time last_consultation.current_bed = None diff --git a/care/facility/api/viewsets/patient.py b/care/facility/api/viewsets/patient.py index 982b3d18b8..7608d177fe 100644 --- a/care/facility/api/viewsets/patient.py +++ b/care/facility/api/viewsets/patient.py @@ -49,7 +49,10 @@ from care.facility.models.base import covert_choice_dict from care.facility.models.bed import AssetBed from care.facility.models.notification import Notification -from care.facility.models.patient_base import DISEASE_STATUS_DICT +from care.facility.models.patient_base import ( + DISEASE_STATUS_DICT, + NewDischargeReasonEnum, +) from care.users.models import User from care.utils.cache.cache_allowed_facilities import get_accessible_facilities from care.utils.filters.choicefilter import CareChoiceFilter @@ -181,6 +184,10 @@ def filter_by_bed_type(self, queryset, name, value): field_name="last_consultation__discharge_reason", choices=DISCHARGE_REASON_CHOICES, ) + last_consultation_discharge_reason = filters.ChoiceFilter( + field_name="last_consultation__discharge_reason", + choices=NewDischargeReasonEnum.choices, + ) last_consultation_assigned_to = filters.NumberFilter( field_name="last_consultation__assigned_to" ) diff --git a/care/facility/api/viewsets/shifting.py b/care/facility/api/viewsets/shifting.py index e5e40d1b54..f2f18f57ee 100644 --- a/care/facility/api/viewsets/shifting.py +++ b/care/facility/api/viewsets/shifting.py @@ -28,7 +28,10 @@ ShiftingRequestComment, User, ) -from care.facility.models.patient_base import DISEASE_STATUS_DICT +from care.facility.models.patient_base import ( + DISEASE_STATUS_DICT, + NewDischargeReasonEnum, +) from care.utils.cache.cache_allowed_facilities import get_accessible_facilities from care.utils.filters.choicefilter import CareChoiceFilter from care.utils.queryset.shifting import get_shifting_queryset @@ -155,7 +158,10 @@ def transfer(self, request, *args, **kwargs): # Discharge from all other active consultations PatientConsultation.objects.filter( patient=patient, discharge_date__isnull=True - ).update(discharge_date=localtime(now()), discharge_reason="REF") + ).update( + discharge_date=localtime(now()), + new_discharge_reason=NewDischargeReasonEnum.REFERRED, + ) ConsultationBed.objects.filter( consultation=patient.last_consultation, end_date__isnull=True, diff --git a/care/facility/migrations/0405_auto_20231211_1930.py b/care/facility/migrations/0405_auto_20231211_1930.py new file mode 100644 index 0000000000..eb5ee0445f --- /dev/null +++ b/care/facility/migrations/0405_auto_20231211_1930.py @@ -0,0 +1,42 @@ +# Generated by Django 4.2.6 on 2023-12-11 14:00 + +from django.db import migrations +from django.db.models import Case, Value, When + + +def migrate_to_temp_field(apps, schema_editor): + PatientConsultation = apps.get_model("facility", "PatientConsultation") + mapping = { + "REC": 1, + "REF": 2, + "EXP": 3, + "LAMA": 4, + "": -1, + } + + cases = [When(discharge_reason=k, then=Value(v)) for k, v in mapping.items()] + PatientConsultation.objects.filter(discharge_reason__isnull=False).update( + new_discharge_reason=Case(*cases, default=Value(-1)) + ) + + +def reverse_migration(apps, schema_editor): + PatientConsultation = apps.get_model("facility", "PatientConsultation") + reverse_mapping = {1: "REC", 2: "REF", 3: "EXP", 4: "LAMA", -1: ""} + + cases = [ + When(discharge_reason=k, then=Value(v)) for k, v in reverse_mapping.items() + ] + PatientConsultation.objects.filter(new_discharge_reason__isnull=False).update( + discharge_reason=Case(*cases, default=Value("")) + ) + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0404_merge_20231220_2227"), + ] + + operations = [ + migrations.RunPython(migrate_to_temp_field, reverse_code=reverse_migration), + ] diff --git a/care/facility/models/patient_base.py b/care/facility/models/patient_base.py index e47e461100..cc05c59766 100644 --- a/care/facility/models/patient_base.py +++ b/care/facility/models/patient_base.py @@ -81,7 +81,7 @@ def reverse_choices(choices): ] -class NewDiseaseReasonEnum(IntegerChoices): +class NewDischargeReasonEnum(IntegerChoices): UNKNOWN = -1, _("Unknown") RECOVERED = 1, _("Recovered") REFERRED = 2, _("Referred") @@ -89,7 +89,7 @@ class NewDiseaseReasonEnum(IntegerChoices): LAMA = 4, _("LAMA") -NEW_DISCHARGE_REASON_CHOICES = [(e.value, e.name) for e in NewDiseaseReasonEnum] +NEW_DISCHARGE_REASON_CHOICES = [(e.value, e.name) for e in NewDischargeReasonEnum] class DiseaseStatusEnum(enum.IntEnum): diff --git a/care/facility/tests/test_patient_api.py b/care/facility/tests/test_patient_api.py index da621e6b28..0167300fb4 100644 --- a/care/facility/tests/test_patient_api.py +++ b/care/facility/tests/test_patient_api.py @@ -4,6 +4,7 @@ from rest_framework import status from rest_framework.test import APITestCase +from care.facility.models.patient_base import NewDischargeReasonEnum from care.utils.tests.test_utils import TestUtils @@ -289,7 +290,7 @@ def setUpTestData(cls): suggestion="A", encounter_date=now(), discharge_date=None, # Patient is currently admitted - discharge_reason=None, + new_discharge_reason=None, ) cls.bed = cls.create_bed(cls.facility, cls.location) cls.consultation_bed = cls.create_consultation_bed(cls.consultation, cls.bed) @@ -317,7 +318,9 @@ def test_patient_transfer(self): self.assertEqual(self.patient.facility, self.destination_facility) # Assert the consultation discharge reason and date are set correctly - self.assertEqual(self.consultation.discharge_reason, "REF") + self.assertEqual( + self.consultation.new_discharge_reason, NewDischargeReasonEnum.REFERRED + ) self.assertIsNotNone(self.consultation.discharge_date) def test_transfer_with_active_consultation_same_facility(self): diff --git a/care/facility/tests/test_patient_consultation_api.py b/care/facility/tests/test_patient_consultation_api.py index 37ad1a702b..08f649ed2b 100644 --- a/care/facility/tests/test_patient_consultation_api.py +++ b/care/facility/tests/test_patient_consultation_api.py @@ -8,6 +8,7 @@ ConditionVerificationStatus, ICD11Diagnosis, ) +from care.facility.models.patient_base import NewDischargeReasonEnum from care.facility.models.patient_consultation import ( CATEGORY_CHOICES, PatientConsultation, @@ -113,7 +114,7 @@ def test_discharge_as_recovered_preadmission(self): ) res = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2002-04-01T16:30:00Z", discharge_notes="Discharge as recovered before admission", ) @@ -126,7 +127,7 @@ def test_discharge_as_recovered_future(self): ) res = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2319-04-01T15:30:00Z", discharge_notes="Discharge as recovered in the future", ) @@ -139,7 +140,7 @@ def test_discharge_as_recovered_after_admission(self): ) res = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2020-04-02T15:30:00Z", discharge_notes="Discharge as recovered after admission before future", ) @@ -152,7 +153,7 @@ def test_discharge_as_expired_pre_admission(self): ) res = self.discharge( consultation, - discharge_reason="EXP", + new_discharge_reason=NewDischargeReasonEnum.EXPIRED, death_datetime="2002-04-01T16:30:00Z", discharge_notes="Death before admission", death_confirmed_doctor="Dr. Test", @@ -166,7 +167,7 @@ def test_discharge_as_expired_future(self): ) res = self.discharge( consultation, - discharge_reason="EXP", + new_discharge_reason=NewDischargeReasonEnum.EXPIRED, death_datetime="2319-04-01T15:30:00Z", discharge_notes="Death in the future", death_confirmed_doctor="Dr. Test", @@ -180,7 +181,7 @@ def test_discharge_as_expired_after_admission(self): ) res = self.discharge( consultation, - discharge_reason="EXP", + new_discharge_reason=NewDischargeReasonEnum.EXPIRED, death_datetime="2020-04-02T15:30:00Z", discharge_notes="Death after admission before future", death_confirmed_doctor="Dr. Test", @@ -195,7 +196,7 @@ def test_discharge_as_recovered_with_expired_fields(self): ) res = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2023-04-02T15:30:00Z", discharge_notes="Discharge as recovered with expired fields", death_datetime="2023-04-02T15:30:00Z", @@ -213,7 +214,7 @@ def test_referred_to_external_null(self): ) res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with null referred_to_external", referred_to_external=None, @@ -227,7 +228,7 @@ def test_referred_to_external_empty_string(self): ) res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with empty referred_to_external", referred_to_external="", @@ -241,7 +242,7 @@ def test_referred_to_empty_facility(self): ) res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with empty referred_to_external", referred_to=None, @@ -255,7 +256,7 @@ def test_referred_to_and_external_together(self): ) res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with null referred_to_external", referred_to_external="External Facility", @@ -271,7 +272,7 @@ def test_referred_to_valid_value(self): referred_to_external = "Test Hospital" res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", referred_to_external=referred_to_external, ) @@ -285,7 +286,7 @@ def test_referred_to_external_valid_value(self): referred_to_external = "Test Hospital" res = self.discharge( consultation, - discharge_reason="REF", + new_discharge_reason=NewDischargeReasonEnum.REFERRED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with valid referred_to_external", referred_to_external=referred_to_external, @@ -345,7 +346,7 @@ def test_medico_legal_case(self): # Test Patch after discharge response = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2023-07-01T12:00:00Z", discharge_notes="Discharged with valid referred_to_external", medico_legal_case=False, @@ -367,7 +368,7 @@ def test_update_consultation_after_discharge(self): ) res = self.discharge( consultation, - discharge_reason="REC", + new_discharge_reason=NewDischargeReasonEnum.RECOVERED, discharge_date="2020-04-02T15:30:00Z", discharge_notes="Discharge as recovered after admission before future", ) diff --git a/care/templates/reports/patient_discharge_summary_pdf.html b/care/templates/reports/patient_discharge_summary_pdf.html index 8f8ae45cd0..1fbc572e26 100644 --- a/care/templates/reports/patient_discharge_summary_pdf.html +++ b/care/templates/reports/patient_discharge_summary_pdf.html @@ -848,7 +848,7 @@