From 90849fbb79af5f9bd2ece9990bf3b20b653b20d0 Mon Sep 17 00:00:00 2001
From: Jesse Bickel <jbickel@opentechstrategies.com>
Date: Thu, 25 Jul 2024 12:20:36 -0500
Subject: [PATCH] Distinguish withdrawal permissions

Add distinct withdrawal permissions within stages of workflows. By
default, let the applicant withdraw at any stage. On the submission
page, display the Withdraw button assuming the setting
`ENABLE_SUBMISSION_WITHDRAWAL` is true and the withdrawal permissions
are met.

Issue #3296
---
 .../templates/funds/applicationsubmission_detail.html      | 2 +-
 hypha/apply/funds/templatetags/workflow_tags.py            | 7 +++++++
 hypha/apply/funds/workflow.py                              | 6 +++++-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/hypha/apply/funds/templates/funds/applicationsubmission_detail.html b/hypha/apply/funds/templates/funds/applicationsubmission_detail.html
index d3bf35fc95..167b268ea7 100644
--- a/hypha/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/hypha/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -137,7 +137,7 @@ <h5>{% blocktrans with stage=object.previous.stage %}Your {{ stage }} applicatio
                                         {% trans "Delete" %}
                                     </a>
                                 {% endif %}
-                                {% if ENABLE_SUBMISSION_WITHDRAWAL and request.user.is_applicant %}
+                                {% if request.user|has_withdraw_perm:object %}
                                     <a
                                         class="link link--withdraw-submission is-active"
                                         href="{% url 'funds:submissions:withdraw' object.id %}">
diff --git a/hypha/apply/funds/templatetags/workflow_tags.py b/hypha/apply/funds/templatetags/workflow_tags.py
index 274a1e88b6..91951a22b5 100644
--- a/hypha/apply/funds/templatetags/workflow_tags.py
+++ b/hypha/apply/funds/templatetags/workflow_tags.py
@@ -74,3 +74,10 @@ def display_submission_author(context: dict, revision_author: bool = False) -> s
         return settings.ORG_LONG_NAME  # Likely an edge case but covering bases
 
     return str(author)
+
+
+@register.filter
+def has_withdraw_perm(user, submission):
+    if settings.ENABLE_SUBMISSION_WITHDRAWAL:
+        return check_permission(user, "withdraw", submission)
+    return False
diff --git a/hypha/apply/funds/workflow.py b/hypha/apply/funds/workflow.py
index dc8390e2d5..f238fda96b 100644
--- a/hypha/apply/funds/workflow.py
+++ b/hypha/apply/funds/workflow.py
@@ -181,6 +181,9 @@ def can_review(self, user):
     def can_view(self, user):
         return self.can_do(user, "view")
 
+    def can_withdraw(self, user):
+        return self.can_do(user, "withdraw")
+
 
 staff_can = lambda user: user.is_apply_staff  # NOQA
 
@@ -193,7 +196,7 @@ def can_view(self, user):
 community_can = lambda user: user.is_community_reviewer  # NOQA
 
 
-def make_permissions(edit=None, review=None, view=None):
+def make_permissions(edit=None, review=None, view=None, withdraw=None):
     return {
         "edit": edit or [],
         "review": review or [],
@@ -204,6 +207,7 @@ def make_permissions(edit=None, review=None, view=None):
             reviewer_can,
             partner_can,
         ],
+        "withdraw": withdraw or [applicant_can],
     }