Skip to content

Commit

Permalink
Merge branch 'abdm' of github.com:coronasafe/care into abdm
Browse files Browse the repository at this point in the history
  • Loading branch information
khavinshankar committed Jul 20, 2023
2 parents 54317da + 3bbdb18 commit 025646a
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 57 deletions.
6 changes: 1 addition & 5 deletions care/abdm/api/viewsets/hip.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ def share(self, request, *args, **kwargs):
patient = PatientRegistration.objects.create(
facility=Facility.objects.get(external_id=counter_id),
name=patient_data["name"],
gender=1
if patient_data["gender"] == "M"
else 2
if patient_data["gender"] == "F"
else 3,
gender={ "M": 1, "F": 2 }.get(patient_data["gender"], 3)
is_antenatal=False,
phone_number=patient_data["mobile"],
emergency_phone_number=patient_data["mobile"],
Expand Down
15 changes: 10 additions & 5 deletions care/facility/api/serializers/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
)
from care.facility.models import (
BREATHLESSNESS_CHOICES,
CATEGORY_CHOICES,
FACILITY_TYPES,
SHIFTING_STATUS_CHOICES,
VEHICLE_CHOICES,
Expand Down Expand Up @@ -217,6 +218,7 @@ class ShiftingSerializer(serializers.ModelSerializer):
last_edited_by_object = UserBaseMinimumSerializer(
source="last_edited_by", read_only=True
)
patient_category = ChoiceField(choices=CATEGORY_CHOICES, required=False)
ambulance_driver_name = serializers.CharField(
required=False, allow_null=True, allow_blank=True
)
Expand Down Expand Up @@ -327,8 +329,10 @@ def update(self, instance, validated_data):
new_instance = super().update(instance, validated_data)

patient = new_instance.patient
patient.last_consultation.category = self.initial_data["patient_category"]
patient.last_consultation.save()
patient_category = self.validated_data.pop("patient_category")
if patient.last_consultation and patient_category is not None:
patient.last_consultation.category = patient_category
patient.last_consultation.save(update_fields=["category"])

if (
"status" in validated_data
Expand Down Expand Up @@ -390,9 +394,10 @@ def create(self, validated_data):
patient.allow_transfer = True
patient.save()

if patient.last_consultation:
patient.last_consultation.category = self.initial_data["patient_category"]
patient.last_consultation.save()
patient_category = self.validated_data.pop("patient_category")
if patient.last_consultation and patient_category is not None:
patient.last_consultation.category = patient_category
patient.last_consultation.save(update_fields=["category"])

validated_data["origin_facility"] = patient.facility

Expand Down
11 changes: 9 additions & 2 deletions care/facility/api/viewsets/facility_users.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db.models import Prefetch
from django_filters import rest_framework as filters
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import mixins
Expand All @@ -7,7 +8,7 @@

from care.facility.models.facility import Facility
from care.users.api.serializers.user import UserAssignedSerializer
from care.users.models import User
from care.users.models import Skill, User


class UserFilter(filters.FilterSet):
Expand All @@ -34,6 +35,12 @@ def get_queryset(self):
facility = Facility.objects.get(
external_id=self.kwargs.get("facility_external_id")
)
return facility.users.filter(deleted=False).order_by("-last_login")
queryset = facility.users.filter(deleted=False).order_by("-last_login")
queryset = queryset.prefetch_related(
Prefetch(
"skills", queryset=Skill.objects.filter(userskill__deleted=False)
)
)
return queryset
except Facility.DoesNotExist:
raise ValidationError({"Facility": "Facility not found"})
11 changes: 10 additions & 1 deletion care/facility/api/viewsets/patient_consultation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db.models import Prefetch
from django.db.models.query_utils import Q
from django_filters import rest_framework as filters
from drf_spectacular.utils import extend_schema
Expand All @@ -24,7 +25,7 @@
email_discharge_summary,
generate_and_upload_discharge_summary_task,
)
from care.users.models import User
from care.users.models import Skill, User
from care.utils.cache.cache_allowed_facilities import get_accessible_facilities


Expand Down Expand Up @@ -69,6 +70,14 @@ def get_permissions(self):
return super().get_permissions()

def get_queryset(self):
if self.serializer_class == PatientConsultationSerializer:
self.queryset = self.queryset.prefetch_related(
"assigned_to",
Prefetch(
"assigned_to__skills",
queryset=Skill.objects.filter(userskill__deleted=False),
),
)
if self.request.user.is_superuser:
return self.queryset
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
Expand Down
16 changes: 16 additions & 0 deletions care/facility/migrations/0373_remove_patientconsultation_hba1c.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 4.2.2 on 2023-07-20 13:09

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("facility", "0372_assetavailabilityrecord"),
]

operations = [
migrations.RemoveField(
model_name="patientconsultation",
name="HBA1C",
),
]
6 changes: 0 additions & 6 deletions care/facility/models/patient_consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,6 @@ class PatientConsultation(PatientBaseModel, PatientRelatedPermissionMixin):
verbose_name="Patient's Weight in KG",
validators=[MinValueValidator(0)],
)
HBA1C = models.FloatField(
default=None,
null=True,
verbose_name="HBA1C parameter for reference to current blood sugar levels",
validators=[MinValueValidator(0)],
)

# ICU Information

Expand Down
2 changes: 1 addition & 1 deletion care/facility/models/patient_icmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def is_symptomatic(self):
def symptomatic_international_traveller(
self,
):
return (
return bool(
self.patient.countries_travelled
and len(self.patient.countries_travelled) != 0
and (
Expand Down
37 changes: 21 additions & 16 deletions care/facility/tasks/asset_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,23 @@ def check_asset_status():
middleware_status_cache = {}

for asset in assets:
# Skipping if asset class or local IP address is not present
if not asset.asset_class or not asset.meta.get("local_ip_address", None):
continue
try:
# Fetching middleware hostname
hostname = asset.meta.get(
"middleware_hostname",
asset.current_location.facility.middleware_address,
)
result: Any = {}
result: Any = None

# Checking if middleware status is already cached
if hostname in middleware_status_cache:
result = middleware_status_cache[hostname]
else:
try:
# Creating an instance of the asset class
asset_class: BaseAssetIntegration = AssetClasses[
asset.asset_class
].value(
Expand All @@ -45,42 +49,43 @@ def check_asset_status():
"middleware_hostname": hostname,
}
)
# Fetching the status of the device
result = asset_class.api_get(asset_class.get_url("devices/status"))
middleware_status_cache[hostname] = result
except Exception:
logger.exception("Error in Asset Status Check - Fetching Status")
middleware_status_cache[hostname] = None
continue
logger.warn(f"Middleware {hostname} is down", exc_info=True)

# If no status is returned, setting default status as down
if not result:
continue
result = [{"time": timezone.now().isoformat(), "status": []}]

new_status = None
middleware_status_cache[hostname] = result

# Setting new status as down by default
new_status = AvailabilityStatus.DOWN
for status_record in result:
if asset.meta.get("local_ip_address") in status_record.get(
"status", {}
):
new_status = status_record["status"][
asset_status = status_record["status"][
asset.meta.get("local_ip_address")
]
else:
new_status = "not_monitored"
asset_status = "down"

# Fetching the last record of the asset
last_record = (
AssetAvailabilityRecord.objects.filter(asset=asset)
.order_by("-timestamp")
.first()
)

if new_status == "up":
# Setting new status based on the status returned by the device
if asset_status == "up":
new_status = AvailabilityStatus.OPERATIONAL
elif new_status == "down":
new_status = AvailabilityStatus.DOWN
elif new_status == "maintenance":
elif asset_status == "maintenance":
new_status = AvailabilityStatus.UNDER_MAINTENANCE
else:
new_status = AvailabilityStatus.NOT_MONITORED

# Creating a new record if the status has changed
if not last_record or (
datetime.fromisoformat(status_record.get("time"))
> last_record.timestamp
Expand All @@ -93,4 +98,4 @@ def check_asset_status():
)

except Exception:
logger.exception("Error in Asset Status Check")
logger.error("Error in Asset Status Check", exc_info=True)
47 changes: 47 additions & 0 deletions care/facility/tests/test_facilityuser_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.test import TestCase
from rest_framework import status

from care.facility.api.viewsets.facility_users import FacilityUserViewSet
from care.facility.models.facility import Facility
from care.facility.tests.mixins import TestClassMixin
from care.users.models import Skill


class FacilityUserTest(TestClassMixin, TestCase):
def setUp(self):
super().setUp()
self.creator = self.users[0]

sample_data = {
"name": "Hospital X",
"ward": self.creator.ward,
"local_body": self.creator.local_body,
"district": self.creator.district,
"state": self.creator.state,
"facility_type": 1,
"address": "Nearby",
"pincode": 390024,
"features": [],
}
self.facility = Facility.objects.create(
external_id="550e8400-e29b-41d4-a716-446655440000",
created_by=self.creator,
**sample_data,
)

self.skill1 = Skill.objects.create(name="Skill 1")
self.skill2 = Skill.objects.create(name="Skill 2")

self.users[0].skills.add(self.skill1, self.skill2)

def test_get_queryset_with_prefetching(self):
response = self.new_request(
(f"/api/v1/facility/{self.facility.external_id}/get_users/",),
{"get": "list"},
FacilityUserViewSet,
self.users[0],
{"facility_external_id": self.facility.external_id},
)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNumQueries(2)
50 changes: 45 additions & 5 deletions care/facility/tests/test_patient_consultation_api.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
import datetime

from django.test import TestCase
from django.utils.timezone import make_aware
from rest_framework import status
from rest_framework.test import APIRequestFactory, APITestCase

from care.facility.api.viewsets.facility_users import FacilityUserViewSet
from care.facility.api.viewsets.patient_consultation import PatientConsultationViewSet
from care.facility.models.facility import Facility
from care.facility.models.patient_consultation import (
CATEGORY_CHOICES,
PatientConsultation,
)
from care.facility.tests.mixins import TestClassMixin
from care.users.models import Skill
from care.utils.tests.test_base import TestBase


class FacilityUserTest(TestClassMixin, TestCase):
def setUp(self):
super().setUp()
self.creator = self.users[0]

sample_data = {
"name": "Hospital X",
"ward": self.creator.ward,
"local_body": self.creator.local_body,
"district": self.creator.district,
"state": self.creator.state,
"facility_type": 1,
"address": "Nearby",
"pincode": 390024,
"features": [],
}
self.facility = Facility.objects.create(
external_id="550e8400-e29b-41d4-a716-446655440000",
created_by=self.creator,
**sample_data,
)

self.skill1 = Skill.objects.create(name="Skill 1")
self.skill2 = Skill.objects.create(name="Skill 2")

self.users[0].skills.add(self.skill1, self.skill2)

def test_get_queryset_with_prefetching(self):
response = self.new_request(
(f"/api/v1/facility/{self.facility.external_id}/get_users/",),
{"get": "list"},
FacilityUserViewSet,
self.users[0],
{"facility_external_id": self.facility.external_id},
)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNumQueries(2)


class TestPatientConsultation(TestBase, TestClassMixin, APITestCase):
default_data = {
"symptoms": [1],
Expand All @@ -31,11 +75,7 @@ def setUp(self):
)

def create_admission_consultation(self, patient=None, **kwargs):
patient = (
self.create_patient(facility_id=self.facility.id)
if not patient
else patient
)
patient = patient or self.create_patient(facility_id=self.facility.id)
data = self.default_data.copy()
kwargs.update(
{
Expand Down
14 changes: 4 additions & 10 deletions care/facility/utils/summarisation/facility_capacity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@


def facility_capacity_summary():
capacity_objects = FacilityCapacity.objects.all().select_related(
"facility",
"facility__state",
"facility__district",
"facility__local_body",
)
capacity_objects = FacilityCapacity.objects.all()
capacity_summary = {}
current_date = localtime(now()).replace(hour=0, minute=0, second=0, microsecond=0)

Expand Down Expand Up @@ -106,11 +101,10 @@ def facility_capacity_summary():
capacity_summary[facility_obj.id]["inventory"] = temp_inventory_summary_obj

for capacity_object in capacity_objects:
facility_id = capacity_object.facility.id
facility_id = capacity_object.facility_id
if facility_id not in capacity_summary:
capacity_summary[facility_id] = FacilitySerializer(
capacity_object.facility
).data
# This facility is either deleted or not active
continue
if "availability" not in capacity_summary[facility_id]:
capacity_summary[facility_id]["availability"] = []
capacity_summary[facility_id]["availability"].append(
Expand Down
Loading

0 comments on commit 025646a

Please sign in to comment.