diff --git a/hypha/apply/determinations/templates/determinations/includes/determination_button.html b/hypha/apply/determinations/templates/determinations/includes/determination_button.html index 2e275ed5bc7d9d22a6687112147bcf96f7fa6d8e..a528358dcd36ec424d2d43faf524bfb3099147ab 100644 --- a/hypha/apply/determinations/templates/determinations/includes/determination_button.html +++ b/hypha/apply/determinations/templates/determinations/includes/determination_button.html @@ -1,6 +1,14 @@ {% load determination_tags workflow_tags %} {% if request.user|show_determination_button:submission %} - <a target="_blank" href="{% url 'apply:submissions:determinations:form' submission_pk=submission.id %}" class="button button--primary button--full-width"> - {% if submission.determination.is_draft %}Update draft{% else %}Add Determination{% endif %} + <a target="_blank" href="{% url 'apply:submissions:determinations:form' submission_pk=submission.id %}" class="button button--primary button--full-width {{ class }}"> + {% if submission.determinations.last.is_draft %} + {% if draft_text %} + {{ draft_text }} + {% else %} + Update draft + {% endif %} + {% else %} + Add determination + {% endif %} </a> {% endif %} diff --git a/hypha/apply/funds/models/submissions.py b/hypha/apply/funds/models/submissions.py index 00b8fbea422f10f766da0de6114c6c2cf04817a9..538274ec6590d6959db452d39045d03c77adfed3 100644 --- a/hypha/apply/funds/models/submissions.py +++ b/hypha/apply/funds/models/submissions.py @@ -702,6 +702,10 @@ class ApplicationSubmission( def __repr__(self): return f'<{self.__class__.__name__}: {self.user}, {self.round}, {self.page}>' + @property + def ready_for_determination(self): + return self.status in PHASES_MAPPING['ready-for-determination']['statuses'] + @property def accepted_for_funding(self): accepted = self.status in PHASES_MAPPING['accepted']['statuses'] diff --git a/hypha/apply/funds/templates/funds/includes/actions.html b/hypha/apply/funds/templates/funds/includes/actions.html index fef520d40b0baaa27c542576c4650e9e76ff4beb..3aca979d6edbe386d02ac6d4625dcb9f3975bfb3 100644 --- a/hypha/apply/funds/templates/funds/includes/actions.html +++ b/hypha/apply/funds/templates/funds/includes/actions.html @@ -14,6 +14,10 @@ <a data-fancybox data-src="#screen-application" class="button button--bottom-space button--primary button--full-width {% if screening_form.should_show %}is-not-disabled{% else %}is-disabled{% endif %}" href="#">Screen application</a> +{% if object.ready_for_determination %} + {% include 'determinations/includes/determination_button.html' with submission=object class="button--bottom-space" draft_text="Complete draft determination" %} +{% endif %} + <a data-fancybox data-src="#update-status" class="button button--primary button--full-width {% if progress_form.should_show %}is-not-disabled{% else %}is-disabled{% endif %}" href="#">Update status</a> diff --git a/hypha/apply/funds/tests/test_views.py b/hypha/apply/funds/tests/test_views.py index dd09926fded0ac68663849e69c168ab2ba9e1ea5..9b3734a115d58011a930aa63426490f989c3640b 100644 --- a/hypha/apply/funds/tests/test_views.py +++ b/hypha/apply/funds/tests/test_views.py @@ -1,5 +1,7 @@ +import re from datetime import timedelta +from bs4 import BeautifulSoup from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied from django.http import Http404 @@ -207,6 +209,48 @@ class TestStaffSubmissionView(BaseSubmissionViewTestCase): self.assertTrue(hasattr(submission, 'project')) self.assertEquals(submission.project.id, project.id) + def test_can_see_add_determination_primary_action(self): + def assert_add_determination_displayed(submission, button_text): + response = self.get_page(submission) + # Ignore whitespace (including line breaks) in button text + pattern = re.compile(rf'\s*{button_text}\s*') + buttons = BeautifulSoup(response.content, 'html5lib').find(class_='js-actions-sidebar').find_all('a', class_='button--primary', text=pattern) + self.assertEqual(len(buttons), 1) + + submission = ApplicationSubmissionFactory(status='determination') + + # Phase: ready-for-determination, no determination + # "Add determination" should be displayed + assert_add_determination_displayed(submission, 'Add determination') + + # Phase: ready-for-determination, draft determination + # "Complete draft determination" should be displayed + DeterminationFactory(submission=submission, author=self.user, accepted=True, submitted=False) + assert_add_determination_displayed(submission, 'Complete draft determination') + + def test_cant_see_add_determination_primary_action(self): + def assert_add_determination_not_displayed(submission, button_text): + response = self.get_page(submission) + # Ignore whitespace (including line breaks) in button text + pattern = re.compile(rf'\s*{button_text}\s*') + buttons = BeautifulSoup(response.content, 'html5lib').find(class_='js-actions-sidebar').find_all('a', class_='button--primary', text=pattern) + self.assertEqual(len(buttons), 0) + + submission = ApplicationSubmissionFactory() + + # Phase: received / in_discussion + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + + # Phase: accepted + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + submission.perform_transition('accepted', self.user) + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + class TestReviewersUpdateView(BaseSubmissionViewTestCase): user_factory = StaffFactory @@ -335,6 +379,38 @@ class TestReviewersUpdateView(BaseSubmissionViewTestCase): self.assertCountEqual(submission.reviewers.all(), [reviewer, self.reviewers[1]]) +class TestReviewerSubmissionView(BaseSubmissionViewTestCase): + user_factory = ReviewerFactory + + @classmethod + def setUpTestData(cls): + super().setUpTestData() + cls.applicant = ApplicantFactory() + + def test_cant_see_add_determination_primary_action(self): + def assert_add_determination_not_displayed(submission, button_text): + response = self.get_page(submission) + # Ignore whitespace (including line breaks) in button text + pattern = re.compile(rf'\s*{button_text}\s*') + buttons = BeautifulSoup(response.content, 'html5lib').find_all('a', class_='button--primary', text=pattern) + self.assertEqual(len(buttons), 0) + + submission = ApplicationSubmissionFactory(status='determination', user=self.applicant, reviewers=[self.user]) + + # Phase: ready-for-determination, no determination + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + + # Phase: ready-for-determination, draft determination + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + DeterminationFactory(submission=submission, accepted=True, submitted=False) + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + + class TestApplicantSubmissionView(BaseSubmissionViewTestCase): user_factory = ApplicantFactory @@ -428,6 +504,29 @@ class TestApplicantSubmissionView(BaseSubmissionViewTestCase): response = self.get_page(self.submission) self.assertNotContains(response, 'Screening Status') + def test_cant_see_add_determination_primary_action(self): + def assert_add_determination_not_displayed(submission, button_text): + response = self.get_page(submission) + # Ignore whitespace (including line breaks) in button text + pattern = re.compile(rf'\s*{button_text}\s*') + buttons = BeautifulSoup(response.content, 'html5lib').find_all('a', class_='button--primary', text=pattern) + self.assertEqual(len(buttons), 0) + + submission = ApplicationSubmissionFactory(status='determination', user=self.user) + + # Phase: ready-for-determination, no determination + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + + # Phase: ready-for-determination, draft determination + # "Add determination" should not be displayed + # "Complete draft determination" should not be displayed + DeterminationFactory(submission=submission, accepted=True, submitted=False) + assert_add_determination_not_displayed(submission, 'Add determination') + assert_add_determination_not_displayed(submission, 'Complete draft determination') + class TestRevisionsView(BaseSubmissionViewTestCase): user_factory = ApplicantFactory