From 7a28d1e47675fe0c7b5f5923459cd67def4f0c49 Mon Sep 17 00:00:00 2001
From: Todd Dembrey <todd.dembrey@torchbox.com>
Date: Sat, 15 Sep 2018 16:42:04 +0100
Subject: [PATCH] Allow redirects post determination - fixes an error case but
 safe to keep

---
 opentech/apply/determinations/views.py   | 25 +++++++++++++++++++++++-
 opentech/apply/funds/tests/test_views.py | 21 ++++++++++++++++++++
 opentech/apply/funds/views.py            |  9 ++++-----
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/opentech/apply/determinations/views.py b/opentech/apply/determinations/views.py
index 7be2e9a41..2ed4b742f 100644
--- a/opentech/apply/determinations/views.py
+++ b/opentech/apply/determinations/views.py
@@ -11,11 +11,12 @@ from django.views.generic import DetailView
 from opentech.apply.activity.models import Activity
 from opentech.apply.activity.messaging import messenger, MESSAGES
 from opentech.apply.funds.models import ApplicationSubmission
+from opentech.apply.funds.workflow import DETERMINATION_OUTCOMES
 from opentech.apply.utils.views import CreateOrUpdateView, ViewDispatcher
 from opentech.apply.users.decorators import staff_required
 
 from .forms import ConceptDeterminationForm, ProposalDeterminationForm
-from .models import Determination, DeterminationMessageSettings, NEEDS_MORE_INFO
+from .models import Determination, DeterminationMessageSettings, NEEDS_MORE_INFO, TRANSITION_DETERMINATION
 
 from .utils import can_create_determination, can_edit_determination, has_final_determination, transition_from_outcome
 
@@ -109,6 +110,28 @@ class DeterminationCreateOrUpdateView(CreateOrUpdateView):
 
         return HttpResponseRedirect(self.submission.get_absolute_url())
 
+    @classmethod
+    def should_redirect(cls, request, submission, action):
+        if has_final_determination(submission):
+            determination = submission.determinations.final().first()
+            if determination.outcome == TRANSITION_DETERMINATION[action]:
+                # We want to progress as normal so don't redirect through form
+                return False
+            else:
+                # Add a helpful message to prompt them to select the correct option
+                messages.warning(
+                    request,
+                    _('A determination of "{current}" exists but you tried to progress as "{target}"').format(
+                        current=determination.get_outcome_display(),
+                        target=action,
+                    )
+                )
+
+        if action in DETERMINATION_OUTCOMES:
+            return HttpResponseRedirect(reverse_lazy(
+                'apply:submissions:determinations:form',
+                args=(submission.id,)) + "?action=" + action)
+
 
 @method_decorator(staff_required, name='dispatch')
 class AdminDeterminationDetailView(DetailView):
diff --git a/opentech/apply/funds/tests/test_views.py b/opentech/apply/funds/tests/test_views.py
index 6131353fc..a1614e477 100644
--- a/opentech/apply/funds/tests/test_views.py
+++ b/opentech/apply/funds/tests/test_views.py
@@ -2,6 +2,7 @@ from datetime import datetime, timedelta
 import json
 
 from opentech.apply.activity.models import Activity
+from opentech.apply.determinations.tests.factories import DeterminationFactory
 from opentech.apply.funds.tests.factories import (
     ApplicationSubmissionFactory,
     ApplicationRevisionFactory,
@@ -100,6 +101,26 @@ class TestStaffSubmissionView(BaseSubmissionViewTestCase):
         self.assertEqual(submission.status, 'concept_review_discussion')
         self.assertIsNone(submission.next)
 
+    def test_not_redirected_if_determination_submitted(self):
+        submission = ApplicationSubmissionFactory(lead=self.user)
+        DeterminationFactory(submission=submission, rejected=True, submitted=True)
+
+        self.post_page(submission, {'form-submitted-progress_form': '', 'action': 'rejected'})
+
+        submission = self.refresh(submission)
+        self.assertEqual(submission.status, 'rejected')
+
+    def test_not_redirected_if_wrong_determination_selected(self):
+        submission = ApplicationSubmissionFactory(lead=self.user)
+        DeterminationFactory(submission=submission, accepted=True, submitted=True)
+
+        response = self.post_page(submission, {'form-submitted-progress_form': '', 'action': 'rejected'})
+        self.assertContains(response, 'you tried to progress')
+
+        submission = self.refresh(submission)
+        self.assertNotEqual(submission.status, 'accepted')
+        self.assertNotEqual(submission.status, 'rejected')
+
     def test_cant_access_edit_button_when_applicant_editing(self):
         submission = ApplicationSubmissionFactory(status='more_info')
         response = self.get_page(submission)
diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py
index 8e614ba85..39120dd22 100644
--- a/opentech/apply/funds/views.py
+++ b/opentech/apply/funds/views.py
@@ -21,7 +21,7 @@ from opentech.apply.activity.views import (
     DelegatedViewMixin,
 )
 from opentech.apply.activity.messaging import messenger, MESSAGES
-from opentech.apply.funds.workflow import DETERMINATION_OUTCOMES
+from opentech.apply.determinations.views import DeterminationCreateOrUpdateView
 from opentech.apply.review.views import ReviewContextMixin
 from opentech.apply.users.decorators import staff_required
 from opentech.apply.utils.views import DelegateableView, ViewDispatcher
@@ -80,10 +80,9 @@ class ProgressSubmissionView(DelegatedViewMixin, UpdateView):
     def form_valid(self, form):
         action = form.cleaned_data.get('action')
         # Defer to the determination form for any of the determination transitions
-        if action in DETERMINATION_OUTCOMES:
-            return HttpResponseRedirect(reverse_lazy(
-                'apply:submissions:determinations:form',
-                args=(form.instance.id,)) + "?action=" + action)
+        redirect = DeterminationCreateOrUpdateView.should_redirect(self.request, self.object, action)
+        if redirect:
+            return redirect
 
         self.object.perform_transition(action, self.request.user, request=self.request)
         return super().form_valid(form)
-- 
GitLab