Skip to content

Commit

Permalink
Merge branch 'develop' into updating-feature-to-arrayfield-in-facilit…
Browse files Browse the repository at this point in the history
…y-model
  • Loading branch information
vigneshhari authored Aug 21, 2024
2 parents 8c5b4a6 + 5cada26 commit fe4994f
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 129 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ default_stages: [commit]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.6.0
hooks:
- id: no-commit-to-branch
args: [--branch, develop, --branch, staging, --branch, production]
Expand All @@ -23,13 +23,13 @@ repos:
additional_dependencies: ["isort[pyproject]"]

- repo: https://github.com/psf/black
rev: 24.4.0
rev: 24.4.2
hooks:
- id: black
args: ["--config=pyproject.toml"]

- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
rev: 7.1.0
hooks:
- id: flake8
args: ["--config=.flake8"]
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Open Healthcare Network
Copyright (c) 2024 Open Healthcare Network

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
26 changes: 26 additions & 0 deletions care/facility/api/serializers/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,32 @@ def update(self, instance: Asset, validated_data):
return updated_instance


class AssetPublicSerializer(ModelSerializer):
id = UUIDField(source="external_id", read_only=True)
status = ChoiceField(choices=StatusChoices, read_only=True)
asset_type = ChoiceField(choices=AssetTypeChoices)
location_object = AssetLocationSerializer(source="current_location", read_only=True)

class Meta:
model = Asset
fields = (
"id",
"name",
"location_object",
"serial_number",
"warranty_details",
"warranty_amc_end_of_validity",
"asset_type",
"asset_class",
"vendor_name",
"support_name",
"support_email",
"support_phone",
"is_working",
"status",
)


class AssetConfigSerializer(ModelSerializer):
id = UUIDField(source="external_id")
type = CharField(source="asset_class")
Expand Down
235 changes: 119 additions & 116 deletions care/facility/api/serializers/patient_consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
UserBaseMinimumSerializer,
)
from care.users.models import User
from care.utils.lock import Lock
from care.utils.notification_handler import NotificationGenerator
from care.utils.queryset.facility import get_home_facility_queryset
from care.utils.serializer.external_id_field import ExternalIdSerializerField
Expand Down Expand Up @@ -191,6 +192,9 @@ def get_discharge_prn_prescription(self, consultation):
dosage_type=PrescriptionDosageType.PRN.value,
).values()

def _lock_key(self, patient_id):
return f"patient_consultation__patient_registration__{patient_id}"

class Meta:
model = PatientConsultation
read_only_fields = TIMESTAMP_FIELDS + (
Expand Down Expand Up @@ -353,149 +357,146 @@ def create(self, validated_data):

create_diagnosis = validated_data.pop("create_diagnoses")
create_symptoms = validated_data.pop("create_symptoms")
action = -1
review_interval = -1
if "action" in validated_data:
action = validated_data.pop("action")
if "review_interval" in validated_data:
review_interval = validated_data.pop("review_interval")

action = validated_data.pop("action", -1)
review_interval = validated_data.get("review_interval", -1)

# Authorisation Check

allowed_facilities = get_home_facility_queryset(self.context["request"].user)
user = self.context["request"].user
allowed_facilities = get_home_facility_queryset(user)
if not allowed_facilities.filter(
id=self.validated_data["patient"].facility.id
id=self.validated_data["patient"].facility_id
).exists():
raise ValidationError(
{"facility": "Consultation creates are only allowed in home facility"}
)

# End Authorisation Checks

if validated_data["patient"].last_consultation:
with (
Lock(self._lock_key(validated_data["patient"].id)),
transaction.atomic(),
):
patient = validated_data["patient"]
if patient.last_consultation:
if patient.last_consultation.assigned_to == user:
raise ValidationError(
{
"Permission Denied": "Only Facility Staff can create consultation for a Patient"
},
)

if not patient.last_consultation.discharge_date:
raise ValidationError(
{"consultation": "Exists please Edit Existing Consultation"}
)

if "is_kasp" in validated_data:
if validated_data["is_kasp"]:
validated_data["kasp_enabled_date"] = now()

bed = validated_data.pop("bed", None)

# Coercing facility as the patient's facility
validated_data["facility_id"] = patient.facility_id

consultation: PatientConsultation = super().create(validated_data)
consultation.created_by = user
consultation.last_edited_by = user
consultation.previous_consultation = patient.last_consultation
last_consultation = patient.last_consultation
if (
self.context["request"].user
== validated_data["patient"].last_consultation.assigned_to
last_consultation
and consultation.suggestion == SuggestionChoices.A
and last_consultation.suggestion == SuggestionChoices.A
and last_consultation.discharge_date
and last_consultation.discharge_date + timedelta(days=30)
> consultation.encounter_date
):
raise ValidationError(
{
"Permission Denied": "Only Facility Staff can create consultation for a Patient"
},
)
consultation.is_readmission = True

diagnosis = ConsultationDiagnosis.objects.bulk_create(
[
ConsultationDiagnosis(
consultation=consultation,
diagnosis_id=obj["diagnosis"].id,
is_principal=obj["is_principal"],
verification_status=obj["verification_status"],
created_by=user,
)
for obj in create_diagnosis
]
)

if validated_data["patient"].last_consultation:
if not validated_data["patient"].last_consultation.discharge_date:
raise ValidationError(
{"consultation": "Exists please Edit Existing Consultation"}
symptoms = EncounterSymptom.objects.bulk_create(
EncounterSymptom(
consultation=consultation,
symptom=obj.get("symptom"),
onset_date=obj.get("onset_date"),
cure_date=obj.get("cure_date"),
clinical_impression_status=obj.get("clinical_impression_status"),
other_symptom=obj.get("other_symptom") or "",
created_by=user,
)
for obj in create_symptoms
)

if "is_kasp" in validated_data:
if validated_data["is_kasp"]:
validated_data["kasp_enabled_date"] = localtime(now())

bed = validated_data.pop("bed", None)

validated_data["facility_id"] = validated_data[
"patient"
].facility_id # Coercing facility as the patient's facility
consultation = super().create(validated_data)
consultation.created_by = self.context["request"].user
consultation.last_edited_by = self.context["request"].user
patient = consultation.patient
consultation.previous_consultation = patient.last_consultation
last_consultation = patient.last_consultation
if (
last_consultation
and consultation.suggestion == SuggestionChoices.A
and last_consultation.suggestion == SuggestionChoices.A
and last_consultation.discharge_date
and last_consultation.discharge_date + timedelta(days=30)
> consultation.encounter_date
):
consultation.is_readmission = True
consultation.save()

diagnosis = ConsultationDiagnosis.objects.bulk_create(
[
ConsultationDiagnosis(
if bed and consultation.suggestion == SuggestionChoices.A:
consultation_bed = ConsultationBed(
bed=bed,
consultation=consultation,
diagnosis_id=obj["diagnosis"].id,
is_principal=obj["is_principal"],
verification_status=obj["verification_status"],
created_by=self.context["request"].user,
start_date=consultation.created_date,
)
for obj in create_diagnosis
]
)
consultation_bed.save()
consultation.current_bed = consultation_bed

symptoms = EncounterSymptom.objects.bulk_create(
EncounterSymptom(
consultation=consultation,
symptom=obj.get("symptom"),
onset_date=obj.get("onset_date"),
cure_date=obj.get("cure_date"),
clinical_impression_status=obj.get("clinical_impression_status"),
other_symptom=obj.get("other_symptom") or "",
created_by=self.context["request"].user,
)
for obj in create_symptoms
)
if consultation.suggestion == SuggestionChoices.OP:
consultation.discharge_date = now()
patient.is_active = False
patient.allow_transfer = True
else:
patient.is_active = True
patient.last_consultation = consultation

if bed and consultation.suggestion == SuggestionChoices.A:
consultation_bed = ConsultationBed(
bed=bed,
consultation=consultation,
start_date=consultation.created_date,
)
consultation_bed.save()
consultation.current_bed = consultation_bed
consultation.save(update_fields=["current_bed"])
if action != -1:
patient.action = action

if consultation.suggestion == SuggestionChoices.OP:
consultation.discharge_date = localtime(now())
consultation.save()
patient.is_active = False
patient.allow_transfer = True
else:
patient.is_active = True
patient.last_consultation = consultation

if action != -1:
patient.action = action
consultation.review_interval = review_interval
if review_interval > 0:
patient.review_time = localtime(now()) + timedelta(minutes=review_interval)
else:
patient.review_time = None
if review_interval > 0:
patient.review_time = now() + timedelta(minutes=review_interval)
else:
patient.review_time = None

patient.save()
NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_CREATED,
caused_by=self.context["request"].user,
caused_object=consultation,
facility=patient.facility,
).generate()
consultation.save()
patient.save()

create_consultation_events(
consultation.id,
(consultation, *diagnosis, *symptoms),
consultation.created_by.id,
consultation.created_date,
)
create_consultation_events(
consultation.id,
(consultation, *diagnosis, *symptoms),
consultation.created_by.id,
consultation.created_date,
)

if consultation.assigned_to:
NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_ASSIGNMENT,
caused_by=self.context["request"].user,
event=Notification.Event.PATIENT_CONSULTATION_CREATED,
caused_by=user,
caused_object=consultation,
facility=consultation.patient.facility,
notification_mediums=[
Notification.Medium.SYSTEM,
Notification.Medium.WHATSAPP,
],
facility=patient.facility,
).generate()

return consultation
if consultation.assigned_to:
NotificationGenerator(
event=Notification.Event.PATIENT_CONSULTATION_ASSIGNMENT,
caused_by=user,
caused_object=consultation,
facility=consultation.patient.facility,
notification_mediums=[
Notification.Medium.SYSTEM,
Notification.Medium.WHATSAPP,
],
).generate()

return consultation

def validate_create_diagnoses(self, value):
# Reject if create_diagnoses is present for edits
Expand Down Expand Up @@ -555,7 +556,9 @@ def validate_create_symptoms(self, value):
if item in counter:
# Reject if duplicate symptoms are provided
raise ValidationError("Duplicate symptoms are not allowed")
counter.add(item)
if not obj.get("cure_date"):
# skip duplicate symptom check for ones that has cure date
counter.add(item)

current_time = now()
for obj in value:
Expand Down
5 changes: 3 additions & 2 deletions care/facility/api/viewsets/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from care.facility.api.serializers.asset import (
AssetConfigSerializer,
AssetLocationSerializer,
AssetPublicSerializer,
AssetSerializer,
AssetServiceSerializer,
AssetTransactionSerializer,
Expand Down Expand Up @@ -187,7 +188,7 @@ def filter_is_permanent(self, queryset, _, value):

class AssetPublicViewSet(GenericViewSet):
queryset = Asset.objects.all()
serializer_class = AssetSerializer
serializer_class = AssetPublicSerializer
lookup_field = "external_id"

def retrieve(self, request, *args, **kwargs):
Expand All @@ -205,7 +206,7 @@ def retrieve(self, request, *args, **kwargs):

class AssetPublicQRViewSet(GenericViewSet):
queryset = Asset.objects.all()
serializer_class = AssetSerializer
serializer_class = AssetPublicSerializer
lookup_field = "qr_code_id"

def retrieve(self, request, *args, **kwargs):
Expand Down
5 changes: 5 additions & 0 deletions care/facility/api/viewsets/patient_consultation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db import transaction
from django.db.models import Prefetch
from django.db.models.query_utils import Q
from django.shortcuts import get_object_or_404, render
Expand Down Expand Up @@ -109,6 +110,10 @@ def get_queryset(self):
applied_filters |= Q(facility=self.request.user.home_facility)
return self.queryset.filter(applied_filters)

@transaction.non_atomic_requests
def create(self, request, *args, **kwargs) -> Response:
return super().create(request, *args, **kwargs)

@extend_schema(tags=["consultation"])
@action(detail=True, methods=["POST"])
def discharge_patient(self, request, *args, **kwargs):
Expand Down
Loading

0 comments on commit fe4994f

Please sign in to comment.