diff --git a/projection/tests.py b/projection/tests.py index 9dba4ae5..452f73b8 100644 --- a/projection/tests.py +++ b/projection/tests.py @@ -535,3 +535,26 @@ def test_cancel_pit_request(self): self.assertRedirects(self.client.post(reverse("projection:cancel-request", args=[2])), reverse("projection:pit-schedule")) + + def test_mark_pit_complete(self): + projectionist = models.Projectionist(user=self.user) + projectionist.save() + level = models.PITLevel.objects.create(name_short="P2", name_long="PIT2", ordering=1) + level.save() + request = models.PitRequest(projectionist=projectionist, level=level, scheduled_for=timezone.now()) + request.save() + + # The user should not have permission to mark a PIT as complete by default + self.assertOk(self.client.get(reverse("projection:pit-complete", args=[1])), 403) + + permission = Permission.objects.get(codename="edit_pits") + self.user.user_permissions.add(permission) + + # Only POST requests are permitted + self.assertOk(self.client.get(reverse("projection:pit-complete", args=[1])), 405) + + self.assertRedirects(self.client.post(reverse("projection:pit-complete", args=[1])), + reverse('projection:pit-schedule')) + + self.assertFalse(models.PitRequest.objects.filter(pk=request.pk).exists()) + self.assertTrue(models.PitInstance.objects.filter(projectionist=projectionist).exists()) diff --git a/projection/urls.py b/projection/urls.py index 201ddd7c..5e5f66c3 100644 --- a/projection/urls.py +++ b/projection/urls.py @@ -24,4 +24,5 @@ url(r'^training/(?P[0-9a-f]+)/update/$', views.pit_request_update, name="edit-request"), url(r'^training/manage/(?P[0-9a-f]+)/$', views.manage_pit_request, name="manage-request"), url(r'^training/(?P[0-9a-f]+)/cancel/$', views.CancelPITRequest.as_view(), name="cancel-request"), + url(r'^training/(?P[0-9a-f]+)/done/$', views.pit_complete, name="pit-complete") ] diff --git a/projection/views.py b/projection/views.py index 048cc94d..943c2fb3 100644 --- a/projection/views.py +++ b/projection/views.py @@ -3,6 +3,7 @@ from crispy_forms.layout import Submit from django.contrib import messages +from django.views.decorators.http import require_POST from django.contrib.auth.decorators import login_required, permission_required from django.db.models import Q from django.conf import settings @@ -15,7 +16,7 @@ from helpers.mixins import HasPermMixin, LoginRequiredMixin from projection.forms import (BulkCreateForm, BulkUpdateForm, DateEntryFormSetBase, ProjectionistForm, ProjectionistUpdateForm, PITRequestForm, PITRequestAdminForm, PITFormset) -from projection.models import PITLevel, Projectionist, PitRequest +from projection.models import PITLevel, Projectionist, PitRequest, PitInstance from emails.generators import GenericEmailGenerator @@ -279,6 +280,24 @@ def pit_schedule(request): return render(request, 'projection_pit_schedule.html', context) +@login_required +@permission_required('projection.edit_pits', raise_exception=True) +@require_POST +def pit_complete(request, id): + """ Mark a PIT as complete """ + pit = get_object_or_404(PitRequest, pk=id) + + # Add the PIT to the user's record automatically + try: + PitInstance.objects.get(projectionist=pit.projectionist, pit_level=pit.level) + except PitInstance.DoesNotExist: + PitInstance.objects.create(projectionist=pit.projectionist, pit_level=pit.level, created_on=pit.scheduled_for) + + pit.delete() + messages.success(request, 'PIT updated successfully!') + return HttpResponseRedirect(reverse('projection:pit-schedule')) + + class CancelPITRequest(LoginRequiredMixin, HasPermMixin, DeleteView): model = PitRequest template_name = "form_cancel_request.html" diff --git a/site_tmpl/projection_pit_schedule.html b/site_tmpl/projection_pit_schedule.html index 7d1e3f7f..2b8b9117 100644 --- a/site_tmpl/projection_pit_schedule.html +++ b/site_tmpl/projection_pit_schedule.html @@ -26,8 +26,14 @@

Approved

{{ request.projectionist }} {{ request.level }} {{ request.scheduled_for }} - Modify - Cancel + +
+ {% csrf_token %} + +
+ Modify + Cancel + {% endfor %}