Skip to content

Commit

Permalink
TreatmentPrescription bulk delete endpoint + tests (PLAN-1504) (#1670)
Browse files Browse the repository at this point in the history
  • Loading branch information
lastminutediorama authored Aug 16, 2024
1 parent 3127716 commit 5437242
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/planscape/impacts/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def has_permission(self, request, view):
match view.action:
case "create":
return TreatmentPlanPermission.can_add_scenario(request.user, tx_plan)
case "batch_delete":
return TreatmentPlanPermission.can_remove(request.user, tx_plan)
case _:
return TreatmentPlanPermission.can_view(request.user, tx_plan)

Expand Down
6 changes: 6 additions & 0 deletions src/planscape/impacts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ class Meta:
)


class TreatmentPrescriptionBatchDeleteSerializer(serializers.Serializer):
stand_ids = serializers.ListField(
child=serializers.IntegerField(), allow_empty=False
)


class SummarySerializer(serializers.Serializer):
project_area = serializers.PrimaryKeyRelatedField(
queryset=ProjectArea.objects.all(),
Expand Down
90 changes: 89 additions & 1 deletion src/planscape/impacts/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from collaboration.models import Permissions, Role, UserObjectRole
from collaboration.services import get_content_type
from impacts.models import TreatmentPlan
from impacts.tests.factories import TreatmentPlanFactory, TreatmentPrescriptionFactory
from impacts.tests.factories import (
TreatmentPlanFactory,
TreatmentPrescriptionFactory,
)
from planning.tests.factories import ScenarioFactory
from planscape.tests.factories import UserFactory

Expand Down Expand Up @@ -205,3 +208,88 @@ def test_list_tx_rx(self):
data = response.json()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data["count"], 2)


class TxPrescriptionBatchDeleteTest(APITransactionTestCase):
def setUp(self):
self.tx_plan = TreatmentPlanFactory.create()
self.alt_tx_plan = TreatmentPlanFactory.create()
self.client.force_authenticate(user=self.tx_plan.scenario.user)
self.txrx_owned_list = TreatmentPrescriptionFactory.create_batch(
10, treatment_plan=self.tx_plan
)
# plans for a different user
self.txrx_other_list = TreatmentPrescriptionFactory.create_batch(
10, treatment_plan=self.alt_tx_plan
)

def test_batch_delete_tx_rx(self):
payload = {"stand_ids": [txrx.stand_id for txrx in self.txrx_owned_list]}
response = self.client.post(
reverse(
"api:impacts:tx-prescriptions-delete-prescriptions",
kwargs={"tx_plan_pk": self.tx_plan.pk},
),
data=payload,
format="json",
)
response_data = response.json()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response_data["result"][0], 10)

def test_batch_delete_tx_rx_bad_values(self):
payload = {"stand_ids": [None]}
response = self.client.post(
reverse(
"api:impacts:tx-prescriptions-delete-prescriptions",
kwargs={"tx_plan_pk": self.tx_plan.pk},
),
data=payload,
format="json",
)
response_data = response.json()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_batch_delete_tx_rx_empty_list(self):
payload = {"stand_ids": []}
response = self.client.post(
reverse(
"api:impacts:tx-prescriptions-delete-prescriptions",
kwargs={"tx_plan_pk": self.tx_plan.pk},
),
data=payload,
format="json",
)
response_data = response.json()
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_batch_delete_nonowned_tx_rx(self):
payload = {"stand_ids": [txrx.stand_id for txrx in self.txrx_other_list]}
response = self.client.post(
reverse(
"api:impacts:tx-prescriptions-delete-prescriptions",
kwargs={"tx_plan_pk": self.alt_tx_plan.pk},
),
data=payload,
format="json",
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

# Testing a request to delete various stand_ids for some txrx records don't match the treatment plan id
# current behavior is to only delete items matching the given tx_plan and quietly ignore the rest
def test_batch_delete_mixed_tx_rx(self):
owned_ids = [txrx.stand_id for txrx in self.txrx_owned_list]
other_ids = [txrx.stand_id for txrx in self.txrx_other_list]

payload = {"stand_ids": owned_ids + other_ids}
response = self.client.post(
reverse(
"api:impacts:tx-prescriptions-delete-prescriptions",
kwargs={"tx_plan_pk": self.tx_plan.pk},
),
data=payload,
format="json",
)
response_data = response.json()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response_data["result"][0], 10)
18 changes: 18 additions & 0 deletions src/planscape/impacts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
TreatmentPlanSerializer,
TreatmentPrescriptionSerializer,
TreatmentPrescriptionListSerializer,
TreatmentPrescriptionBatchDeleteSerializer,
UpsertTreamentPrescriptionSerializer,
)
from impacts.services import (
Expand Down Expand Up @@ -191,3 +192,20 @@ def create(self, request, *args, **kwargs):

def perform_create(self, serializer):
return upsert_treatment_prescriptions(**serializer.validated_data)

@action(detail=False, methods=["post"])
def delete_prescriptions(self, request, tx_plan_pk=None):
serializer = TreatmentPrescriptionBatchDeleteSerializer(data=request.data)

if not serializer.is_valid():
return response.Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)

stand_ids = serializer.validated_data.get("stand_ids", [])

delete_result = TreatmentPrescription.objects.filter(
stand_id__in=stand_ids, treatment_plan_id=tx_plan_pk
).delete()

return response.Response({"result": delete_result}, status=status.HTTP_200_OK)

0 comments on commit 5437242

Please sign in to comment.