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

Medibase Medicines Integration #1369

Merged
merged 30 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9e44786
Adds medibase medicines data
rithviknishad Jun 5, 2023
8c8251b
Merge branch 'master' into medibase
rithviknishad Jun 7, 2023
decb9fa
Merge branch 'master' into medibase
rithviknishad Jun 8, 2023
9be5f26
Adds MedibaseMedicine Table and migrations
rithviknishad Jun 12, 2023
d8d6c78
in-memory search and updated viewsetrs and serializers
rithviknishad Jun 12, 2023
9a3478d
Merge branch 'master' into medibase
rithviknishad Jun 13, 2023
89dcc8f
rebase migrations
rithviknishad Jun 13, 2023
6cff6b8
fix import preventing migration
rithviknishad Jun 13, 2023
f507d3e
set batch_size on medibase population
rithviknishad Jun 13, 2023
bc056b8
noop for medibase population migration
rithviknishad Jun 13, 2023
ac1f456
minor fix
rithviknishad Jun 13, 2023
647068a
cleanup
rithviknishad Jun 14, 2023
2ae96da
sort by word matches first
rithviknishad Jun 14, 2023
8ac3119
adds test for medibase
rithviknishad Jun 15, 2023
d879fa0
fix test casing
rithviknishad Jun 15, 2023
2b04eda
fix discharge summary
rithviknishad Jun 17, 2023
b61908c
Merge branch 'master' into medibase
vigneshhari Jun 17, 2023
fc087d9
merge migrations
rithviknishad Jun 17, 2023
9224ca0
load medicines data management command
rithviknishad Jun 17, 2023
ff772ec
update docs
rithviknishad Jun 17, 2023
5a4e9b0
updated load_dummy_data to call load_medicines_data
rithviknishad Jun 17, 2023
df6f5f2
Merge branch 'master' into medibase
sainak Jun 20, 2023
a00ae14
merge migrations
rithviknishad Jun 22, 2023
b8567d7
Merge branch 'master' into medibase
rithviknishad Jun 28, 2023
078d33c
fresh migrations, drop medibase_id, use name as unique
rithviknishad Jun 28, 2023
c71b799
remove redundant slice operator
sainak Jun 28, 2023
9fec5aa
call load_medicines_data in migration
rithviknishad Jun 28, 2023
66d79bf
Merge branch 'master' into medibase
rithviknishad Jun 30, 2023
e96501b
merge migrations
rithviknishad Jun 30, 2023
103c9a4
Merge branch 'master' into medibase
vigneshhari Jul 5, 2023
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
27 changes: 23 additions & 4 deletions care/facility/api/serializers/prescription.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
from django.shortcuts import get_object_or_404
from rest_framework import serializers

from care.facility.models import MedicineAdministration, Prescription
from care.facility.models import MedibaseMedicine, MedicineAdministration, Prescription
from care.users.api.serializers.user import UserBaseMinimumSerializer


class PrescriptionSerializer(serializers.ModelSerializer):
class MedibaseMedicineSerializer(serializers.ModelSerializer):
id = serializers.UUIDField(source="external_id", read_only=True)

prescribed_by = UserBaseMinimumSerializer(read_only=True)
class Meta:
model = MedibaseMedicine
exclude = ("deleted",)
read_only_fields = (
"external_id",
"created_date",
"modified_date",
)


class PrescriptionSerializer(serializers.ModelSerializer):
id = serializers.UUIDField(source="external_id", read_only=True)
prescribed_by = UserBaseMinimumSerializer(read_only=True)
last_administered_on = serializers.SerializerMethodField()
medicine_object = MedibaseMedicineSerializer(read_only=True, source="medicine")
medicine = serializers.UUIDField(write_only=True)

def get_last_administered_on(self, obj):
last_administration = (
Expand All @@ -28,6 +42,7 @@ class Meta:
"deleted",
)
read_only_fields = (
"medicine_old",
"external_id",
"prescribed_by",
"created_date",
Expand All @@ -37,12 +52,16 @@ class Meta:
)

def validate(self, attrs):
if "medicine" in attrs:
attrs["medicine"] = get_object_or_404(
MedibaseMedicine, external_id=attrs["medicine"]
)

if attrs.get("is_prn"):
if not attrs.get("indicator"):
raise serializers.ValidationError(
{"indicator": "Indicator should be set for PRN prescriptions."}
)

else:
if not attrs.get("frequency"):
raise serializers.ValidationError(
Expand Down
39 changes: 38 additions & 1 deletion care/facility/api/viewsets/prescription.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from re import IGNORECASE

from django.shortcuts import get_object_or_404
from django_filters import rest_framework as filters
from rest_framework import mixins, status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from rest_framework.viewsets import GenericViewSet, ViewSet

from care.facility.api.serializers.prescription import (
MedicineAdministrationSerializer,
Expand Down Expand Up @@ -126,3 +128,38 @@ def administer(self, request, *args, **kwargs):
# administered_obj = MedicineAdministration.objects.get(external_id=request.query_params.get("id", None))
# administered_obj.delete()
# return Response({"success": True}, status=status.HTTP_200_OK)


class MedibaseViewSet(ViewSet):
# permission_classes = (IsAuthenticated,)

def serailize_data(self, objects):
result = []
for object in objects:
if type(object) == tuple:
object = object[0]
result.append(
{
"id": object.external_id,
"name": object.name,
"type": object.type,
"generic": object.generic,
"company": object.company,
"contents": object.contents,
"cims_class": object.cims_class,
"atc_classification": object.atc_classification,
}
)
return result

def list(self, request):
from care.facility.static_data.medibase import MedibaseMedicineTable

queryset = MedibaseMedicineTable

if request.GET.get("query", False):
query = request.GET.get("query").strip().lower()
queryset = queryset.where(
searchable=queryset.re_match(r".*" + query + r".*", IGNORECASE)
)
return Response(self.serailize_data(queryset[0:15]))
77 changes: 77 additions & 0 deletions care/facility/migrations/0361_auto_20230608_1851.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Generated by Django 2.2.11 on 2023-06-08 13:21

import uuid

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("facility", "0360_auto_20230608_1750"),
]

operations = [
migrations.CreateModel(
name="MedibaseMedicine",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"external_id",
models.UUIDField(db_index=True, default=uuid.uuid4, unique=True),
),
(
"created_date",
models.DateTimeField(auto_now_add=True, db_index=True, null=True),
),
(
"modified_date",
models.DateTimeField(auto_now=True, db_index=True, null=True),
),
("deleted", models.BooleanField(db_index=True, default=False)),
(
"medibase_id",
models.CharField(db_index=True, max_length=32, unique=True),
),
("name", models.CharField(db_index=True, max_length=255)),
(
"type",
models.CharField(
choices=[("BRAND", "brand"), ("GENERIC", "generic")],
db_index=True,
max_length=16,
),
),
(
"generic",
models.CharField(
blank=True, db_index=True, max_length=255, null=True
),
),
(
"company",
models.CharField(
blank=True, db_index=True, max_length=255, null=True
),
),
("contents", models.TextField(blank=True, null=True)),
("cims_class", models.CharField(blank=True, max_length=255, null=True)),
("atc_classification", models.TextField(blank=True, null=True)),
],
options={
"abstract": False,
},
),
migrations.RenameField(
model_name="prescription",
old_name="medicine",
new_name="medicine_old",
),
]
27 changes: 27 additions & 0 deletions care/facility/migrations/0362_auto_20230608_1852.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 2.2.11 on 2023-06-08 13:22

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("facility", "0361_auto_20230608_1851"),
]

operations = [
migrations.AddField(
model_name="prescription",
name="medicine",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="facility.MedibaseMedicine",
),
),
migrations.AlterField(
model_name="prescription",
name="medicine_old",
field=models.CharField(max_length=1023, null=True),
),
]
45 changes: 45 additions & 0 deletions care/facility/migrations/0363_auto_20230608_1852.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 2.2.11 on 2023-06-08 13:22

import json

from django.db import migrations


def fetch_data():
with open("data/medibase.json", "r") as json_file:
return json.load(json_file)


medibase_objects = fetch_data()


class Migration(migrations.Migration):
def populate_medibase_medicines(apps, schema_editor):
MedibaseMedicine = apps.get_model("facility", "MedibaseMedicine")
MedibaseMedicine.objects.all().delete()
MedibaseMedicine.objects.bulk_create(
[
MedibaseMedicine(
medibase_id=medicine["_id"]["$oid"],
name=medicine["name"],
type=medicine["type"],
company=medicine.get("company"),
contents=medicine.get("contents"),
cims_class=medicine.get("cims_class"),
atc_classification=medicine.get("atc_classification"),
generic=medicine.get("generic"),
)
for medicine in medibase_objects
],
batch_size=1000,
)

dependencies = [
("facility", "0362_auto_20230608_1852"),
]

operations = [
migrations.RunPython(
populate_medibase_medicines, reverse_code=migrations.RunPython.noop
),
]
62 changes: 61 additions & 1 deletion care/facility/models/prescription.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,60 @@ def generate_choices(enum_class):
return [(tag.name, tag.value) for tag in enum_class]


class MedibaseMedicineType(enum.Enum):
BRAND = "brand"
GENERIC = "generic"


class MedibaseMedicine(BaseModel):
medibase_id = models.CharField(
max_length=32,
db_index=True,
unique=True,
)
name = models.CharField(
max_length=255,
blank=False,
null=False,
db_index=True,
)
type = models.CharField(
max_length=16,
choices=generate_choices(MedibaseMedicineType),
blank=False,
null=False,
db_index=True,
)
generic = models.CharField(
max_length=255,
null=True,
blank=True,
db_index=True,
)
company = models.CharField(
max_length=255,
blank=True,
null=True,
db_index=True,
)
contents = models.TextField(
blank=True,
null=True,
)
cims_class = models.CharField(
max_length=255,
blank=True,
null=True,
)
atc_classification = models.TextField(
blank=True,
null=True,
)

def __str__(self):
return self.name + " - " + self.type


class Prescription(BaseModel):
consultation = models.ForeignKey(
PatientConsultation,
Expand All @@ -49,7 +103,13 @@ class Prescription(BaseModel):
choices=generate_choices(PrescriptionType),
)

medicine = models.CharField(max_length=1023, blank=False, null=False)
medicine = models.ForeignKey(
MedibaseMedicine,
on_delete=models.PROTECT,
null=True,
blank=False,
)
medicine_old = models.CharField(max_length=1023, blank=False, null=True)
route = models.CharField(
max_length=100,
choices=[(tag.name, tag.value) for tag in Routes],
Expand Down
29 changes: 29 additions & 0 deletions care/facility/static_data/medibase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from littletable import Table

from care.facility.models.prescription import MedibaseMedicine

MedibaseMedicineTable = Table("MedibaseMedicine")

medibase_objects = MedibaseMedicine.objects.all()

for obj in medibase_objects:
MedibaseMedicineTable.insert(
{
"id": obj.id,
"external_id": obj.external_id,
"medibase_id": obj.medibase_id,
"name": obj.name,
"type": obj.type,
"generic": obj.generic or "",
"company": obj.company or "",
"contents": obj.contents or "",
"cims_class": obj.cims_class or "",
"atc_classification": obj.atc_classification or "",
"searchable": f"{obj.name} {obj.generic} {obj.company}",
}
)

# MedibaseMedicineTable.insert_many(medibase_objects)

MedibaseMedicineTable.create_index("id", unique=True)
MedibaseMedicineTable.create_search_index("searchable")
4 changes: 3 additions & 1 deletion config/api_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
)
from care.facility.api.viewsets.bed import (
AssetBedViewSet,
PatientAssetBedViewSet,
BedViewSet,
ConsultationBedViewSet,
PatientAssetBedViewSet,
)
from care.facility.api.viewsets.daily_round import DailyRoundsViewSet
from care.facility.api.viewsets.facility import AllFacilityViewSet, FacilityViewSet
Expand Down Expand Up @@ -53,6 +53,7 @@
from care.facility.api.viewsets.patient_search import PatientScopedSearchViewSet
from care.facility.api.viewsets.prescription import (
ConsultationPrescriptionViewSet,
MedibaseViewSet,
MedicineAdministrationViewSet,
)
from care.facility.api.viewsets.prescription_supplier import (
Expand Down Expand Up @@ -202,6 +203,7 @@
consultation_nested_router.register(
r"prescription_administration", MedicineAdministrationViewSet
)
router.register("medibase", MedibaseViewSet, basename="medibase")

# HCX
router.register("hcx/policy", PolicyViewSet)
Expand Down
Loading