Skip to content

Commit

Permalink
Support for deleting a location (#1812)
Browse files Browse the repository at this point in the history
* Support for deleting a location

* add tests

* refactor

* link patient to consultation bed

* restrict deletion if beds are linked to location

* restrict for linked assets

* add tests and update restrictions

* add destroy permissions in permissions mixin instead of viewset

* refactor to use reverse relation

* filter soft deletes

Co-authored-by: Rithvik Nishad <rithvikn2001@gmail.com>

* include soft deleted asset in tests

---------

Co-authored-by: Rithvik Nishad <rithvikn2001@gmail.com>
Co-authored-by: Aakash Singh <mail@singhaakash.dev>
  • Loading branch information
3 people authored Feb 10, 2024
1 parent 307a7c5 commit 29b1569
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 1 deletion.
10 changes: 10 additions & 0 deletions care/facility/api/viewsets/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class AssetLocationViewSet(
CreateModelMixin,
UpdateModelMixin,
GenericViewSet,
DestroyModelMixin,
):
queryset = (
AssetLocation.objects.all().select_related("facility").order_by("-created_date")
Expand Down Expand Up @@ -118,6 +119,15 @@ def get_facility(self):
def perform_create(self, serializer):
serializer.save(facility=self.get_facility())

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.bed_set.filter(deleted=False).count():
raise ValidationError("Cannot delete a Location with associated Beds")
if instance.asset_set.filter(deleted=False).count():
raise ValidationError("Cannot delete a Location with associated Assets")

return super().destroy(request, *args, **kwargs)


class AssetFilter(filters.FilterSet):
facility = filters.UUIDFilter(field_name="current_location__facility__external_id")
Expand Down
3 changes: 3 additions & 0 deletions care/facility/models/mixins/permissions/facility.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,6 @@ def has_object_write_permission(self, request):

def has_object_update_permission(self, request):
return self.has_object_write_permission(request)

def has_object_destroy_permission(self, request):
return self.has_object_write_permission(request)
34 changes: 34 additions & 0 deletions care/facility/tests/test_asset_location_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ def setUpTestData(cls) -> None:
cls.super_user = cls.create_super_user("su", cls.district)
cls.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body)
cls.asset_location = cls.create_asset_location(cls.facility)
cls.asset_location_with_linked_bed = cls.create_asset_location(cls.facility)
cls.asset_location_with_linked_asset = cls.create_asset_location(cls.facility)
cls.asset = cls.create_asset(cls.asset_location_with_linked_asset)
cls.bed = cls.create_bed(cls.facility, cls.asset_location_with_linked_bed)
cls.patient = cls.create_patient(cls.district, cls.facility)
cls.consultation = cls.create_consultation(cls.patient, cls.facility)
cls.consultation_bed = cls.create_consultation_bed(cls.consultation, cls.bed)
cls.user = cls.create_user("staff", cls.district, home_facility=cls.facility)
cls.deleted_asset = cls.create_asset(cls.asset_location)
cls.deleted_asset.deleted = True
cls.deleted_asset.save()

def test_list_asset_locations(self):
response = self.client.get(
Expand Down Expand Up @@ -78,3 +88,27 @@ def test_create_asset_location_invalid_middleware(self):
self.assertEqual(
response.data["middleware_address"][0].code, "invalid_domain_name"
)

def test_delete_asset_location_with_beds(self):
response = self.client.delete(
f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location_with_linked_bed.external_id}/",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.data[0], "Cannot delete a Location with associated Beds"
)

def test_delete_asset_location_with_linked_assets(self):
response = self.client.delete(
f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location_with_linked_asset.external_id}/",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.data[0], "Cannot delete a Location with associated Assets"
)

def test_delete_asset_location_with_no_assets_and_beds(self):
response = self.client.delete(
f"/api/v1/facility/{self.facility.external_id}/asset_location/{self.asset_location.external_id}/",
)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
2 changes: 1 addition & 1 deletion care/utils/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def create_asset(cls, location: AssetLocation, **kwargs) -> Asset:
"current_location": location,
"asset_type": 50,
"warranty_amc_end_of_validity": make_aware(datetime(2030, 4, 1)).date(),
"qr_code_id": "3dcee5fa-8fb8-4b07-be12-8e0d0baf6692",
"qr_code_id": uuid.uuid4(),
}
data.update(kwargs)
return Asset.objects.create(**data)
Expand Down

0 comments on commit 29b1569

Please sign in to comment.