Skip to content

Commit

Permalink
Allows diagnoses starting with disease code to be available in ICD11 …
Browse files Browse the repository at this point in the history
…Search (#1823)

* allow diagnoses starting with disease code to be searchable

* Add tests

* Fix regex pattern and improve tests

* ensure ICD11 is lazy loaded
  • Loading branch information
rithviknishad authored Jan 17, 2024
1 parent 91ed61a commit e64fc1f
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 11 deletions.
3 changes: 2 additions & 1 deletion care/abdm/utils/fhir.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
from care.facility.models.file_upload import FileUpload
from care.facility.models.icd11_diagnosis import REVERSE_CONDITION_VERIFICATION_STATUSES
from care.facility.models.patient_investigation import InvestigationValue
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id


class Fhir:
Expand Down Expand Up @@ -138,6 +137,8 @@ def _organization(self):
return self._organization_profile

def _condition(self, diagnosis_id, verification_status):
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id

diagnosis = get_icd11_diagnosis_object_by_id(diagnosis_id)
[code, label] = diagnosis.label.split(" ", 1)
condition_profile = Condition(
Expand Down
3 changes: 2 additions & 1 deletion care/facility/api/serializers/consultation_diagnosis.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
ConsultationDiagnosis,
)
from care.facility.models.icd11_diagnosis import ICD11Diagnosis
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id
from care.users.api.serializers.user import UserBaseMinimumSerializer


Expand All @@ -31,6 +30,8 @@ class ConsultationDiagnosisSerializer(serializers.ModelSerializer):
created_by = UserBaseMinimumSerializer(read_only=True)

def get_diagnosis_object(self, obj):
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id

return get_icd11_diagnosis_object_by_id(obj.diagnosis_id, as_dict=True)

class Meta:
Expand Down
5 changes: 2 additions & 3 deletions care/facility/api/viewsets/icd.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ class ICDViewSet(ViewSet):
def list(self, request):
from care.facility.static_data.icd11 import ICDDiseases

queryset = ICDDiseases
queryset = ICDDiseases.where(has_code=True)
if request.GET.get("query", False):
query = request.GET.get("query")
queryset = queryset.where(
label=queryset.re_match(r".*" + query + r".*", IGNORECASE),
is_leaf=True,
label=queryset.re_match(r".*" + query + r".*", IGNORECASE)
) # can accept regex from FE if needed.
return Response(serailize_data(queryset[0:100]))
3 changes: 2 additions & 1 deletion care/facility/models/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
REVERSE_ROUTE_TO_FACILITY_CHOICES,
)
from care.facility.models.patient_consultation import PatientConsultation
from care.facility.static_data.icd11 import get_icd11_diagnoses_objects_by_ids
from care.users.models import GENDER_CHOICES, REVERSE_GENDER_CHOICES, User
from care.utils.models.base import BaseManager, BaseModel
from care.utils.models.validators import mobile_or_landline_number_validator
Expand Down Expand Up @@ -539,6 +538,8 @@ def format_as_time(time):
return time.strftime("%H:%M")

def format_diagnoses(diagnosis_ids):
from care.facility.static_data.icd11 import get_icd11_diagnoses_objects_by_ids

diagnoses = get_icd11_diagnoses_objects_by_ids(diagnosis_ids)
return ", ".join([diagnosis["label"] for diagnosis in diagnoses])

Expand Down
9 changes: 6 additions & 3 deletions care/facility/static_data/icd11.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import contextlib
import re

from django.db import connection
from littletable import Table

from care.facility.models.icd11_diagnosis import ICD11Diagnosis

DISEASE_CODE_PATTERN = r"^(?:[A-Z]+\d|\d+[A-Z])[A-Z\d.]*\s"


def fetch_from_db():
# This is a hack to prevent the migration from failing when the table does not exist
Expand All @@ -14,11 +17,11 @@ def fetch_from_db():
{
"id": str(diagnosis["id"]),
"label": diagnosis["label"],
"is_leaf": diagnosis["is_leaf"],
"has_code": bool(re.match(DISEASE_CODE_PATTERN, diagnosis["label"])),
"chapter": diagnosis["meta_chapter_short"],
}
for diagnosis in ICD11Diagnosis.objects.filter().values(
"id", "label", "is_leaf", "meta_chapter_short"
for diagnosis in ICD11Diagnosis.objects.values(
"id", "label", "meta_chapter_short"
)
]
return []
Expand Down
42 changes: 42 additions & 0 deletions care/facility/tests/test_icd11_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from rest_framework.test import APITestCase

from care.utils.tests.test_utils import TestUtils


class TestICD11Api(TestUtils, APITestCase):
@classmethod
def setUpTestData(cls) -> None:
cls.state = cls.create_state()
cls.district = cls.create_district(cls.state)
cls.local_body = cls.create_local_body(cls.district)
cls.super_user = cls.create_super_user("su", cls.district)
cls.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body)
cls.user = cls.create_user(
"icd11_doctor", cls.district, home_facility=cls.facility
)

def search_icd11(self, query):
return self.client.get("/api/v1/icd/", {"query": query})

def test_search_no_disease_code(self):
res = self.search_icd11("14 Diseases of the skin")
self.assertNotContains(res, "14 Diseases of the skin")

res = self.search_icd11("Acute effects of ionizing radiation on the skin")
self.assertNotContains(res, "Acute effects of ionizing radiation on the skin")

def test_search_with_disease_code(self):
res = self.search_icd11("aCuTe radiodermatitis following radiotherapy")
self.assertContains(res, "EL60 Acute radiodermatitis following radiotherapy")

res = self.search_icd11("cutaneous insect bite reactions")
self.assertContains(res, "EK50.0 Cutaneous insect bite reactions")

res = self.search_icd11("Haemorrhage of anus and rectum")
self.assertContains(res, "ME24.A1 Haemorrhage of anus and rectum")

res = self.search_icd11("ME24.A1")
self.assertContains(res, "ME24.A1 Haemorrhage of anus and rectum")

res = self.search_icd11("1A00 Cholera")
self.assertContains(res, "1A00 Cholera")
3 changes: 2 additions & 1 deletion care/facility/utils/reports/discharge_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
ACTIVE_CONDITION_VERIFICATION_STATUSES,
ConditionVerificationStatus,
)
from care.facility.static_data.icd11 import get_icd11_diagnoses_objects_by_ids
from care.hcx.models.policy import Policy

logger = logging.getLogger(__name__)
Expand All @@ -50,6 +49,8 @@ def clear_lock(consultation_ext_id: str):


def get_diagnoses_data(consultation: PatientConsultation):
from care.facility.static_data.icd11 import get_icd11_diagnoses_objects_by_ids

entries = (
consultation.diagnoses.filter(
verification_status__in=ACTIVE_CONDITION_VERIFICATION_STATUSES
Expand Down
3 changes: 2 additions & 1 deletion care/hcx/api/viewsets/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from care.facility.models.file_upload import FileUpload
from care.facility.models.icd11_diagnosis import ConditionVerificationStatus
from care.facility.models.patient_consultation import PatientConsultation
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id
from care.facility.utils.reports.discharge_summary import (
generate_discharge_report_signed_url,
)
Expand Down Expand Up @@ -106,6 +105,8 @@ def check_eligibility(self, request):
@extend_schema(tags=["hcx"], request=MakeClaimSerializer())
@action(detail=False, methods=["post"])
def make_claim(self, request):
from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id

data = request.data

serializer = MakeClaimSerializer(data=data)
Expand Down

0 comments on commit e64fc1f

Please sign in to comment.