Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ePD] 'Delete PD' not present in available_actions #3160

Open
wants to merge 6 commits into
base: epd
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/etools/applications/partners/serializers/interventions_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
InterventionPermissions,
PARTNERSHIP_MANAGER_GROUP,
PRC_SECRETARY,
REPRESENTATIVE_OFFICE_GROUP,
SENIOR_MANAGEMENT_GROUP,
)
from etools.applications.partners.serializers.interventions_v2 import (
Expand Down Expand Up @@ -362,6 +363,13 @@ def _is_prc_secretary(self):
profile__country=self.context['request'].user.profile.country
).exists()

def _is_representative_office_manager(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this?

Copy link
Collaborator Author

@roman-karpovich roman-karpovich Jan 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it comes from PartnershipManagerRepPermission (InterventionAmendmentDeleteView.permission_classes) . not sure if we really need this group here

return get_user_model().objects.filter(
pk=self.context['request'].user.pk,
groups__name__in=[REPRESENTATIVE_OFFICE_GROUP],
profile__country=self.context['request'].user.profile.country
).exists()

def _is_overall_approver(self, obj, user):
if not obj.review:
return False
Expand Down Expand Up @@ -395,6 +403,7 @@ def get_available_actions(self, obj):
"export_pdf",
"export_xls",
"amendment_merge",
"delete",
]
available_actions = [
"download_comments",
Expand All @@ -404,6 +413,9 @@ def get_available_actions(self, obj):
]
user = self.context['request'].user

if obj.status == obj.DRAFT and not obj.date_sent_to_partner:
if self._is_management() or self._is_partnership_manager() or self._is_representative_office_manager():
available_actions.append("delete")
# focal point or budget owner
if self._is_unicef_focal_point(obj, user) or obj.budget_owner == user:
# amendments should be deleted instead of moving to cancelled/terminated
Expand Down
56 changes: 56 additions & 0 deletions src/etools/applications/partners/tests/test_v3_interventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,62 @@ def test_with_date_sent_to_partner_reset(self):
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertFalse(self.intervention_qs.exists())

def test_with_date_sent_to_partner(self):
self.intervention.date_sent_to_partner = timezone.now().date()
self.intervention.save()

response = self.forced_auth_req(
"delete",
reverse('pmp_v3:intervention-delete', args=[self.intervention.pk]),
user=self.user,
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("PD has already been sent to Partner.", response.data[0])

def test_with_status_not_draft(self):
self.intervention.status = Intervention.ACTIVE
self.intervention.save()

response = self.forced_auth_req(
"delete",
reverse('pmp_v3:intervention-delete', args=[self.intervention.pk]),
user=self.user,
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("Cannot delete a PD or SSFA that is not Draft", response.data[0])

def test_with_status_not_draft_in_history(self):
pre_save = create_dict_with_relations(self.intervention)
self.intervention.status = Intervention.ACTIVE
self.intervention.save()
create_snapshot(self.intervention, pre_save, self.user)
self.intervention.status = Intervention.DRAFT
self.intervention.save()

response = self.forced_auth_req(
"delete",
reverse('pmp_v3:intervention-delete', args=[self.intervention.pk]),
user=self.user,
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("Cannot delete a PD or SSFA that was manually moved back to Draft", response.data[0])

def test_with_status_sent_to_partner_in_history(self):
pre_save = create_dict_with_relations(self.intervention)
self.intervention.date_sent_to_partner = timezone.now().date()
self.intervention.save()
create_snapshot(self.intervention, pre_save, self.user)
self.intervention.date_sent_to_partner = None
self.intervention.save()

response = self.forced_auth_req(
"delete",
reverse('pmp_v3:intervention-delete', args=[self.intervention.pk]),
user=self.user,
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("PD has already been sent to Partner.", response.data[0])

def test_delete_partner(self):
self.assertTrue(self.intervention_qs.exists())
response = self.forced_auth_req(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_available_actions_management(self):
)
self.assertEqual(pd.status, pd.DRAFT)
available_actions = self.unicef_serializer.get_available_actions(pd)
expected_actions = self.default_actions
expected_actions = self.default_actions + ["delete"]
self.assertEqual(sorted(available_actions), sorted(expected_actions))

def test_available_actions_focal_point_cancel(self):
Expand Down
4 changes: 3 additions & 1 deletion src/etools/applications/partners/views/interventions_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,6 @@ def list(self, request, *args, **kwargs):


class InterventionDeleteView(DestroyAPIView):
# todo: permission_classes are ignored here. see comments in InterventionAmendmentDeleteView.delete
permission_classes = (PartnershipManagerRepPermission,)
queryset = Intervention.objects

Expand All @@ -797,6 +796,9 @@ def delete(self, request, *args, **kwargs):
if intervention.travel_activities.count():
raise ValidationError("Cannot delete a PD or SSFA that has Planned Trips")

if intervention.date_sent_to_partner:
raise ValidationError("PD has already been sent to Partner.")

else:
# get the history of this PD and make sure it wasn't manually moved back to draft before allowing deletion
act = Activity.objects.filter(target_object_id=intervention.id,
Expand Down