Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data Migration to Support New Discharge Reason Field #1773

Merged
merged 8 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion care/facility/api/serializers/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down
16 changes: 8 additions & 8 deletions care/facility/api/serializers/patient_consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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",
Expand All @@ -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():
Expand Down
5 changes: 3 additions & 2 deletions care/facility/api/serializers/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -70,9 +71,9 @@
PatientConsultation.objects.filter(patient=patient).order_by("-id").first()
)
if last_consultation:
reason = "REF"
reason = NewDischargeReasonEnum.REFERRED

Check warning on line 74 in care/facility/api/serializers/shifting.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/shifting.py#L74

Added line #L74 was not covered by tests
notes = "Patient Shifted to another facility"
last_consultation.discharge_reason = reason
last_consultation.new_discharge_reason = reason

Check warning on line 76 in care/facility/api/serializers/shifting.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/shifting.py#L76

Added line #L76 was not covered by tests
last_consultation.discharge_notes = notes
last_consultation.discharge_date = current_time
last_consultation.current_bed = None
Expand Down
9 changes: 8 additions & 1 deletion care/facility/api/viewsets/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
)
Expand Down
10 changes: 8 additions & 2 deletions care/facility/api/viewsets/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
42 changes: 42 additions & 0 deletions care/facility/migrations/0405_auto_20231211_1930.py
Original file line number Diff line number Diff line change
@@ -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),
]
4 changes: 2 additions & 2 deletions care/facility/models/patient_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ def reverse_choices(choices):
]


class NewDiseaseReasonEnum(IntegerChoices):
class NewDischargeReasonEnum(IntegerChoices):
UNKNOWN = -1, _("Unknown")
RECOVERED = 1, _("Recovered")
REFERRED = 2, _("Referred")
EXPIRED = 3, _("Expired")
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):
Expand Down
7 changes: 5 additions & 2 deletions care/facility/tests/test_patient_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down
31 changes: 16 additions & 15 deletions care/facility/tests/test_patient_consultation_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ConditionVerificationStatus,
ICD11Diagnosis,
)
from care.facility.models.patient_base import NewDischargeReasonEnum
from care.facility.models.patient_consultation import (
CATEGORY_CHOICES,
PatientConsultation,
Expand Down Expand Up @@ -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",
)
Expand All @@ -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",
)
Expand All @@ -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",
)
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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,
Expand All @@ -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="",
Expand All @@ -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,
Expand All @@ -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",
Expand All @@ -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,
)
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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",
)
Expand Down
8 changes: 4 additions & 4 deletions care/templates/reports/patient_discharge_summary_pdf.html
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">
<span class="text-sm text-gray-500">Discharge Reason:</span> {{consultation.get_discharge_reason_display}}
</p>
</div>
{% if consultation.discharge_reason == 'REC' %}
{% if consultation.new_discharge_reason == 1 %}
{% if discharge_prescriptions %}
<h4 class="mt-6 font-medium text-gray-500">
Discharge Prescription Medication:
Expand Down Expand Up @@ -962,9 +962,9 @@ <h4 class="mt-6 font-medium text-gray-500">
</table>
</div>
{% endif %}
{% elif consultation.discharge_reason == 'REF' %}
{% elif consultation.discharge_reason == 'EXP' %}
{% elif consultation.discharge_reason == 'LAMA' %}
{% elif consultation.new_discharge_reason == 2 %}
{% elif consultation.new_discharge_reason == 3 %}
{% elif consultation.new_discharge_reason == 4 %}
{% endif %}

<p class="mt-6">
Expand Down
Loading