From 042536dfa8afb1e98e3a9907f5c5a7147b8c20f5 Mon Sep 17 00:00:00 2001 From: cp-Coder Date: Sat, 22 Apr 2023 12:52:57 +0530 Subject: [PATCH] fix(location): added doctor and staff field in location model --- care/facility/api/serializers/asset.py | 12 ++- care/facility/api/viewsets/facility_users.py | 5 +- .../migrations/0389_add_duty_staff.py | 20 ++++ care/facility/models/asset.py | 14 ++- .../facility/tests/test_asset_location_api.py | 93 +++++++++++++++---- 5 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 care/facility/migrations/0389_add_duty_staff.py diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index 57692a8519..784a32d3db 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -28,17 +28,24 @@ StatusChoices, UserDefaultAssetLocation, ) -from care.users.api.serializers.user import UserBaseMinimumSerializer from care.utils.assetintegration.hl7monitor import HL7MonitorAsset from care.utils.assetintegration.onvif import OnvifAsset from care.utils.assetintegration.ventilator import VentilatorAsset +from care.users.api.serializers.user import ( + UserAssignedSerializer, + UserBaseMinimumSerializer, +) from care.utils.queryset.facility import get_facility_queryset from config.serializers import ChoiceField - class AssetLocationSerializer(ModelSerializer): facility = FacilityBareMinimumSerializer(read_only=True) id = UUIDField(source="external_id", read_only=True) + duty_staff_objects = UserAssignedSerializer( + many=True, + read_only=True, + source="duty_staff", + ) def validate(self, data): facility = self.context["facility"] @@ -55,6 +62,7 @@ def validate(self, data): "name": "Asset location with this name and facility already exists." } ) + return data class Meta: diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index 578f326849..44a5dca8d7 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -17,6 +17,7 @@ class UserFilter(filters.FilterSet): choices=[(key, key) for key in User.TYPE_VALUE_MAP], coerce=lambda role: User.TYPE_VALUE_MAP[role], ) + home_facility = filters.CharFilter(field_name="home_facility__external_id") class Meta: model = User @@ -49,5 +50,5 @@ def get_queryset(self): queryset=UserSkill.objects.filter(skill__deleted=False), ), ) - except Facility.DoesNotExist: - raise ValidationError({"Facility": "Facility not found"}) + except Exception as e: + raise ValidationError({"Facility": "Facility not found"}) from e diff --git a/care/facility/migrations/0389_add_duty_staff.py b/care/facility/migrations/0389_add_duty_staff.py new file mode 100644 index 0000000000..59d1f72872 --- /dev/null +++ b/care/facility/migrations/0389_add_duty_staff.py @@ -0,0 +1,20 @@ +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("facility", "0388_goal_goalentry_goalproperty_goalpropertyentry"), + ] + + operations = [ + migrations.AddField( + model_name="assetlocation", + name="duty_staff", + field=models.ManyToManyField( + blank=True, + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/care/facility/models/asset.py b/care/facility/models/asset.py index 353a2d5a84..e15f39896e 100644 --- a/care/facility/models/asset.py +++ b/care/facility/models/asset.py @@ -45,6 +45,10 @@ class RoomType(enum.Enum): facility = models.ForeignKey( Facility, on_delete=models.PROTECT, null=False, blank=False ) + duty_staff = models.ManyToManyField( + User, + blank=True, + ) class AssetType(enum.Enum): @@ -75,7 +79,11 @@ class Asset(BaseModel): choices=AssetTypeChoices, default=AssetType.INTERNAL.value ) asset_class = models.CharField( - choices=AssetClassChoices, default=None, null=True, blank=True, max_length=20 + choices=AssetClassChoices, + default=None, + null=True, + blank=True, + max_length=20, ) status = models.IntegerField(choices=StatusChoices, default=Status.ACTIVE.value) current_location = models.ForeignKey( @@ -86,7 +94,9 @@ class Asset(BaseModel): serial_number = models.CharField(max_length=1024, blank=True, null=True) warranty_details = models.TextField(null=True, blank=True, default="") # Deprecated meta = JSONField( - default=dict, blank=True, validators=[JSONFieldSchemaValidator(ASSET_META)] + default=dict, + blank=True, + validators=[JSONFieldSchemaValidator(ASSET_META)], ) # Vendor Details vendor_name = models.CharField(max_length=1024, blank=True, null=True) diff --git a/care/facility/tests/test_asset_location_api.py b/care/facility/tests/test_asset_location_api.py index 0228a5dcb9..0c7561ed9d 100644 --- a/care/facility/tests/test_asset_location_api.py +++ b/care/facility/tests/test_asset_location_api.py @@ -1,6 +1,10 @@ +""" +Test cases for AssetLocationViewSet +""" from rest_framework import status from rest_framework.test import APITestCase +from care.users.models import User from care.utils.tests.test_utils import TestUtils @@ -15,33 +19,82 @@ def setUpTestData(cls) -> None: cls.asset_location = cls.create_asset_location(cls.facility) cls.user = cls.create_user("staff", cls.district, home_facility=cls.facility) + def get_detail_duty_staff_representation(self, obj=None) -> dict: + """ + Returns duty staff representation + """ + return { + "id": obj.id, + "username": obj.username, + "first_name": obj.first_name, + "last_name": obj.last_name, + "email": obj.email, + "user_type": User.REVERSE_TYPE_MAP[obj.user_type], + } + + def get_base_url(self, asset_id=None) -> str: + """ + Returns base url for AssetLocationViewSet + """ + if asset_id is not None: + return f"/api/v1/facility/{self.facility.external_id}/asset_location/{asset_id}/" + return f"/api/v1/facility/{self.facility.external_id}/asset_location/" + def test_list_asset_locations(self): - response = self.client.get( - f"/api/v1/facility/{self.facility.external_id}/asset_location/" - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertContains(response, self.asset_location.external_id) + """ + Test list asset locations + """ + res = self.client.get(self.get_base_url()) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertContains(res, self.asset_location.external_id) def test_retrieve_asset_location(self): - response = self.client.get( - f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location.external_id}/" - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertContains(response, self.asset_location.external_id) + """ + Test retrieve asset location + """ + res = self.client.get(self.get_base_url(self.asset_location.external_id)) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertContains(res, self.asset_location.external_id) def test_create_asset_location(self): + """ + Test create asset location + """ sample_data = {"name": "Test Asset Location"} - response = self.client.post( - f"/api/v1/facility/{self.facility.external_id}/asset_location/", - sample_data, - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) + res = self.client.post(self.get_base_url(), sample_data) + self.assertEqual(res.status_code, status.HTTP_201_CREATED) def test_update_asset_location(self): + """ + Test update asset location + """ sample_data = {"name": "Updated Test Asset Location"} - response = self.client.patch( - f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location.external_id}/", - sample_data, + res = self.client.patch( + self.get_base_url(self.asset_location.external_id), sample_data + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertEqual(res.data["name"], sample_data["name"]) + + def test_duty_staff_location(self): + """ + Test duty staff location + """ + + # adding doctors + doctor = self.create_user( + username="doctor", + district=self.district, + local_body=self.local_body, + home_facility=self.facility, + user_type=15, + ) + asset = self.create_asset_location(self.facility) + asset.duty_staff.set([doctor]) + asset.save() + res = self.client.get(self.get_base_url(asset.external_id)) + self.assertEqual(res.status_code, status.HTTP_200_OK) + duty_staff_objects = res.json()["duty_staff_objects"] + self.assertEqual(len(duty_staff_objects), 1) + self.assertDictContainsSubset( + self.get_detail_duty_staff_representation(doctor), duty_staff_objects[0] ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data["name"], sample_data["name"])