From 67c76af8f729d1b24afa9868f39bfd06dbfa8235 Mon Sep 17 00:00:00 2001 From: cp-Coder Date: Sat, 22 Apr 2023 12:52:57 +0530 Subject: [PATCH 1/3] 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 | 60 +++++++++++++++++-- 5 files changed, 100 insertions(+), 11 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 d52c46fe34..49c59101b9 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -28,18 +28,25 @@ 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 from config.validators import MiddlewareDomainAddressValidator - 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_middleware_address(self, value): value = (value or "").strip() @@ -65,6 +72,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 bbdf39f957..f634b01eee 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, + ) middleware_address = models.CharField( null=True, blank=True, default=None, max_length=200 @@ -79,7 +83,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( @@ -90,7 +98,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 b859823c1b..4badaa91e7 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,12 +19,34 @@ 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( @@ -75,3 +101,27 @@ def test_create_asset_location_invalid_middleware(self): self.assertEqual( response.data["middleware_address"][0].code, "invalid_domain_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] + ) From 55fe1e8e4e525ad3442c7804efb17b33b7ff80b0 Mon Sep 17 00:00:00 2001 From: Abhiuday Date: Mon, 2 Oct 2023 19:16:33 +0530 Subject: [PATCH 2/3] fix(asset): fixed linting --- care/facility/api/serializers/asset.py | 15 ++++++++++++--- care/facility/api/viewsets/facility_users.py | 4 ++-- .../migrations/0393_merge_20231020_1752.py | 12 ++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 care/facility/migrations/0393_merge_20231020_1752.py diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index 49c59101b9..bde7d15af3 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -28,17 +28,18 @@ StatusChoices, UserDefaultAssetLocation, ) -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.assetintegration.hl7monitor import HL7MonitorAsset +from care.utils.assetintegration.onvif import OnvifAsset +from care.utils.assetintegration.ventilator import VentilatorAsset from care.utils.queryset.facility import get_facility_queryset from config.serializers import ChoiceField from config.validators import MiddlewareDomainAddressValidator + class AssetLocationSerializer(ModelSerializer): facility = FacilityBareMinimumSerializer(read_only=True) id = UUIDField(source="external_id", read_only=True) @@ -73,6 +74,14 @@ def validate(self, data): } ) + if "duty_staff" in data: + duty_staffs_objects = len(data["duty_staff"]) + print("duty: ", duty_staffs_objects) + if duty_staffs_objects > 3: + raise ValidationError( + {"duty_staff": "Only 3 duty staffs can be assigned"} + ) + return data class Meta: diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index 44a5dca8d7..1636963026 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -50,5 +50,5 @@ def get_queryset(self): queryset=UserSkill.objects.filter(skill__deleted=False), ), ) - except Exception as e: - raise ValidationError({"Facility": "Facility not found"}) from e + except Facility.DoesNotExist: + raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/facility/migrations/0393_merge_20231020_1752.py b/care/facility/migrations/0393_merge_20231020_1752.py new file mode 100644 index 0000000000..24ea3a04cf --- /dev/null +++ b/care/facility/migrations/0393_merge_20231020_1752.py @@ -0,0 +1,12 @@ +# Generated by Django 4.2.5 on 2023-10-20 12:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0389_add_duty_staff"), + ("facility", "0392_alter_dailyround_consciousness_level"), + ] + + operations = [] From 8b9d4d16f843ed7e6d06b7ed3dda41582f5e52ed Mon Sep 17 00:00:00 2001 From: Abhiuday Date: Mon, 23 Oct 2023 19:35:11 +0530 Subject: [PATCH 3/3] fix(asset): removed unnecessary print statements --- care/facility/api/serializers/asset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index bde7d15af3..8d2fde211d 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -76,7 +76,6 @@ def validate(self, data): if "duty_staff" in data: duty_staffs_objects = len(data["duty_staff"]) - print("duty: ", duty_staffs_objects) if duty_staffs_objects > 3: raise ValidationError( {"duty_staff": "Only 3 duty staffs can be assigned"}