Skip to content

Commit

Permalink
Merge pull request #2139 from coronasafe/develop
Browse files Browse the repository at this point in the history
Merge Develop to Staging v24.20.0
  • Loading branch information
gigincg authored May 9, 2024
2 parents b375512 + 52985ad commit 3511d11
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 7 deletions.
2 changes: 1 addition & 1 deletion care/facility/api/viewsets/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class PatientFilterSet(filters.FilterSet):
allow_transfer = filters.BooleanFilter(field_name="allow_transfer")
name = filters.CharFilter(field_name="name", lookup_expr="icontains")
patient_no = filters.CharFilter(
field_name="last_consultation__patient_no", lookup_expr="icontains"
field_name="last_consultation__patient_no", lookup_expr="iexact"
)
gender = filters.NumberFilter(field_name="gender")
age = filters.NumberFilter(field_name="age")
Expand Down
6 changes: 4 additions & 2 deletions care/facility/api/viewsets/patient_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ def list(self, request, *args, **kwargs):
raise PermissionDenied()

if settings.CSV_REQUEST_PARAMETER in request.GET:
queryset = self.filter_queryset(self.get_queryset()).values(
*PatientSample.CSV_MAPPING.keys()
queryset = (
self.filter_queryset(self.get_queryset())
.annotate(**PatientSample.CSV_ANNOTATE_FIELDS)
.values(*PatientSample.CSV_MAPPING.keys())
)
return render_to_csv_response(
queryset,
Expand Down
1 change: 1 addition & 0 deletions care/facility/api/viewsets/prescription.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class ConsultationPrescriptionFilter(filters.FilterSet):
dosage_type = MultiSelectFilter()
prescription_type = CareChoiceFilter(choice_dict=inverse_prescription_type)
discontinued = filters.BooleanFilter()
medicine = filters.UUIDFilter(field_name="medicine__external_id")


class ConsultationPrescriptionViewSet(
Expand Down
6 changes: 4 additions & 2 deletions care/facility/api/viewsets/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ def transfer(self, request, *args, **kwargs):

def list(self, request, *args, **kwargs):
if settings.CSV_REQUEST_PARAMETER in request.GET:
queryset = self.filter_queryset(self.get_queryset()).values(
*ShiftingRequest.CSV_MAPPING.keys()
queryset = (
self.filter_queryset(self.get_queryset())
.annotate(**ShiftingRequest.CSV_ANNOTATE_FIELDS)
.values(*ShiftingRequest.CSV_MAPPING.keys())
)
return render_to_csv_response(
queryset,
Expand Down
92 changes: 92 additions & 0 deletions care/facility/migrations/0429_double_pain_scale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Generated by Django 4.2.10 on 2024-03-12 17:48

from math import ceil

from django.core.paginator import Paginator
from django.db import migrations, models

import care.utils.models.validators


def double_pain_scale(apps, schema_editor):
DailyRound = apps.get_model("facility", "DailyRound")

page = Paginator(
DailyRound.objects.only("id", "pain_scale_enhanced")
.exclude(pain_scale_enhanced__exact=[])
.order_by("id"),
2000,
)

for page_num in page.page_range:
records_to_update = []
for daily_round in page.page(page_num):
for obj in daily_round.pain_scale_enhanced:
try:
obj["scale"] *= 2
except KeyError:
pass
records_to_update.append(daily_round)
DailyRound.objects.bulk_update(records_to_update, ["pain_scale_enhanced"])


def halve_pain_scale(apps, schema_editor):
DailyRound = apps.get_model("facility", "DailyRound")
page = Paginator(
DailyRound.objects.only("id", "pain_scale_enhanced")
.exclude(pain_scale_enhanced__exact=[])
.order_by("id"),
2000,
)

for page_num in page.page_range:
records_to_update = []
for daily_round in page.page(page_num):
for obj in daily_round.pain_scale_enhanced:
try:
obj["scale"] = ceil(obj["scale"] / 2)
except KeyError:
pass
records_to_update.append(daily_round)
DailyRound.objects.bulk_update(records_to_update, ["pain_scale_enhanced"])


class Migration(migrations.Migration):
dependencies = [
("facility", "0428_alter_patientmetainfo_occupation"),
]

operations = [
migrations.AlterField(
model_name="dailyround",
name="pain_scale_enhanced",
field=models.JSONField(
default=list,
validators=[
care.utils.models.validators.JSONFieldSchemaValidator(
{
"$schema": "http://json-schema.org/draft-07/schema#",
"items": [
{
"additionalProperties": False,
"properties": {
"description": {"type": "string"},
"region": {"type": "string"},
"scale": {
"maximum": 10,
"minimum": 1,
"type": "number",
},
},
"required": ["region", "scale"],
"type": "object",
}
],
"type": "array",
}
)
],
),
),
migrations.RunPython(double_pain_scale, reverse_code=halve_pain_scale),
]
2 changes: 1 addition & 1 deletion care/facility/models/json_schema/daily_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"type": "object",
"properties": {
"region": {"type": "string"},
"scale": {"type": "number", "minimum": 1, "maximum": 5},
"scale": {"type": "number", "minimum": 1, "maximum": 10},
"description": {"type": "string"},
},
"additionalProperties": False,
Expand Down
42 changes: 41 additions & 1 deletion care/facility/models/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from django.contrib.postgres.aggregates import ArrayAgg
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import JSONField
from django.db.models import Case, F, Func, JSONField, Value, When
from django.db.models.functions import Coalesce, Now
from django.utils import timezone
from simple_history.models import HistoricalRecords

Expand Down Expand Up @@ -773,3 +774,42 @@ class PatientNotesEdit(models.Model):

class Meta:
ordering = ["-edited_date"]


class PatientAgeFunc(Func):
"""
Expression to calculate the age of a patient based on date of birth/year of
birth and death date time.
Eg:
```
PatientSample.objects.annotate(patient_age=PatientAgeFunc())
```
"""

function = "date_part"

def __init__(self) -> None:
super().__init__(
Value("year"),
Func(
Case(
When(patient__death_datetime__isnull=True, then=Now()),
default=F("patient__death_datetime__date"),
),
Coalesce(
"patient__date_of_birth",
Func(
F("patient__year_of_birth"),
Value(1),
Value(1),
function="MAKE_DATE",
output_field=models.DateField(),
),
output_field=models.DateField(),
),
function="age",
),
output_field=models.IntegerField(),
)
5 changes: 5 additions & 0 deletions care/facility/models/patient_sample.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models

from care.facility.models import FacilityBaseModel, PatientRegistration, reverse_choices
from care.facility.models.patient import PatientAgeFunc
from care.users.models import User

SAMPLE_TYPE_CHOICES = [
Expand Down Expand Up @@ -125,6 +126,10 @@ class PatientSample(FacilityBaseModel):
"date_of_result": "Date of Result",
}

CSV_ANNOTATE_FIELDS = {
"patient__age": PatientAgeFunc(),
}

CSV_MAKE_PRETTY = {
"sample_type": (lambda x: REVERSE_SAMPLE_TYPE_CHOICES.get(x, "-")),
"status": (
Expand Down
5 changes: 5 additions & 0 deletions care/facility/models/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from care.facility.models import (
FACILITY_TYPES,
FacilityBaseModel,
PatientAgeFunc,
pretty_boolean,
reverse_choices,
)
Expand Down Expand Up @@ -137,6 +138,10 @@ class ShiftingRequest(FacilityBaseModel):
"reason": "Reason for Shifting",
}

CSV_ANNOTATE_FIELDS = {
"patient__age": PatientAgeFunc(),
}

CSV_MAKE_PRETTY = {
"status": (lambda x: REVERSE_SHIFTING_STATUS_CHOICES.get(x, "-")),
"is_up_shift": pretty_boolean,
Expand Down
36 changes: 36 additions & 0 deletions care/facility/tests/test_prescriptions_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def setUp(self) -> None:
super().setUp()
self.consultation = self.create_consultation(self.patient, self.facility)
self.medicine = MedibaseMedicine.objects.first()
self.medicine2 = MedibaseMedicine.objects.all()[1]

self.normal_prescription_data = {
"medicine": self.medicine.external_id,
Expand All @@ -29,6 +30,14 @@ def setUp(self) -> None:
"dosage_type": "REGULAR",
}

self.normal_prescription_data2 = {
"medicine": self.medicine2.external_id,
"prescription_type": "REGULAR",
"base_dosage": "1 mg",
"frequency": "OD",
"dosage_type": "REGULAR",
}

def test_create_normal_prescription(self):
response = self.client.post(
f"/api/v1/consultation/{self.consultation.external_id}/prescriptions/",
Expand Down Expand Up @@ -113,3 +122,30 @@ def test_create_prn_prescription(self):
prn_prescription_data,
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_medicine_filter_for_prescription(self):
# post 2 prescriptions with different medicines
self.client.post(
f"/api/v1/consultation/{self.consultation.external_id}/prescriptions/",
self.normal_prescription_data,
)
self.client.post(
f"/api/v1/consultation/{self.consultation.external_id}/prescriptions/",
self.normal_prescription_data2,
)

# get all prescriptions without medicine filter
response = self.client.get(
f"/api/v1/consultation/{self.consultation.external_id}/prescriptions/",
)
self.assertEqual(response.data["count"], 2)

# get all prescriptions with medicine filter
response = self.client.get(
f"/api/v1/consultation/{self.consultation.external_id}/prescriptions/?medicine={self.medicine.external_id}",
)

for prescription in response.data["results"]:
self.assertEqual(
prescription["medicine_object"]["name"], self.medicine.name
)
1 change: 1 addition & 0 deletions care/users/api/serializers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ class Meta:
"alt_phone_number",
"user_type",
"last_login",
"gender",
"home_facility_object",
"doctor_qualification",
"doctor_experience_commenced_on",
Expand Down

0 comments on commit 3511d11

Please sign in to comment.