From 832d3e16a94504f4c9cde27f6c0c24c8197980ec Mon Sep 17 00:00:00 2001
From: Shrikrishna Singh <krishnasingh.ss30@gmail.com>
Date: Tue, 8 Feb 2022 14:24:13 +0530
Subject: [PATCH] Fix permissions to add deliverables

---
 hypha/apply/api/v1/permissions.py              | 16 ++++++++++++++--
 hypha/apply/api/v1/projects/views.py           |  4 ++--
 hypha/apply/projects/models/payment.py         | 14 ++++++++++++++
 .../includes/deliverables_block.html           | 18 +++++++++++-------
 .../projects/templatetags/invoice_tools.py     |  5 +++++
 5 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/hypha/apply/api/v1/permissions.py b/hypha/apply/api/v1/permissions.py
index 0ead51633..188a6ada9 100644
--- a/hypha/apply/api/v1/permissions.py
+++ b/hypha/apply/api/v1/permissions.py
@@ -20,7 +20,19 @@ class IsApplyStaffUser(permissions.BasePermission):
 
 class IsFinance1User(permissions.BasePermission):
     def has_permission(self, request, view):
-        return request.user.is_finance_level_1
+        invoice = view.get_invoice_object()
+        return request.user.is_finance_level_1 and invoice.can_user_edit_deliverables(request.user)
 
     def has_object_permission(self, request, view, obj):
-        return request.user.is_finance_level_1
+        invoice = view.get_invoice_object()
+        return request.user.is_finance_level_1 and invoice.can_user_edit_deliverables(request.user)
+
+
+class IsFinance2User(permissions.BasePermission):
+    def has_permission(self, request, view):
+        invoice = view.get_invoice_object()
+        return request.user.is_finance_level_2 and invoice.can_user_edit_deliverables(request.user)
+
+    def has_object_permission(self, request, view, obj):
+        invoice = view.get_invoice_object()
+        return request.user.is_finance_level_2 and invoice.can_user_edit_deliverables(request.user)
diff --git a/hypha/apply/api/v1/projects/views.py b/hypha/apply/api/v1/projects/views.py
index 084260d4e..ae6ad88b5 100644
--- a/hypha/apply/api/v1/projects/views.py
+++ b/hypha/apply/api/v1/projects/views.py
@@ -9,7 +9,7 @@ from hypha.apply.projects.models.payment import Invoice, InvoiceDeliverable
 from hypha.apply.projects.models.project import Deliverable
 
 from ..mixin import InvoiceNestedMixin, ProjectNestedMixin
-from ..permissions import IsApplyStaffUser, IsFinance1User
+from ..permissions import IsApplyStaffUser, IsFinance1User, IsFinance2User
 from .serializers import (
     DeliverableSerializer,
     InvoiceDeliverableListSerializer,
@@ -25,7 +25,7 @@ class DeliverableViewSet(
     viewsets.GenericViewSet
 ):
     permission_classes = (
-        permissions.IsAuthenticated, IsApplyStaffUser | IsFinance1User,
+        permissions.IsAuthenticated, IsApplyStaffUser | IsFinance1User | IsFinance2User
     )
     serializer_class = InvoiceDeliverableListSerializer
     pagination_class = None
diff --git a/hypha/apply/projects/models/payment.py b/hypha/apply/projects/models/payment.py
index c2f5d52b7..d873b1890 100644
--- a/hypha/apply/projects/models/payment.py
+++ b/hypha/apply/projects/models/payment.py
@@ -231,6 +231,20 @@ class Invoice(models.Model):
             return True
         return False
 
+    def can_user_edit_deliverables(self, user):
+        if not (user.is_apply_staff or user.is_finance_level_1 or user.is_finance_level_2):
+            return False
+        if user.is_apply_staff:
+            if self.status in {SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE_1}:
+                return True
+        if user.is_finance_level_1:
+            if self.status in {APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE_2}:
+                return True
+        if user.is_finance_level_2:
+            if self.status in {APPROVED_BY_FINANCE_1}:
+                return True
+        return False
+
     @property
     def value(self):
         return self.paid_value or self.amount
diff --git a/hypha/apply/projects/templates/application_projects/includes/deliverables_block.html b/hypha/apply/projects/templates/application_projects/includes/deliverables_block.html
index ab39e81b9..d1df43682 100644
--- a/hypha/apply/projects/templates/application_projects/includes/deliverables_block.html
+++ b/hypha/apply/projects/templates/application_projects/includes/deliverables_block.html
@@ -1,5 +1,6 @@
-{% load i18n %}
+{% load i18n invoice_tools %}
 <div class="sidebar__inner">
+    {% can_edit_deliverables invoice user as user_can_edit_deliverables %}
     <h5>{% trans "Choose deliverables" %}</h5>
     <form id="add-deliverables", action="" data-projectid="{{ project.id }}" data-invoiceid="{{ invoice.id }}">
         <div class="select-deliverables">
@@ -11,22 +12,25 @@
             </select>
         </div>
         <br>
-        <div class="available-to-invoice">
-            <b>{% trans "Available to invoice:" %} </b>
-        </div>
-        <br>
+        {% if user_can_edit_deliverables %}
+            <div class="available-to-invoice">
+                <b>{% trans "Available to invoice:" %} </b>
+            </div>
+            <br>
+        {% endif %}
+
         <div class="quantity">
             <b><label for="quantity">{% trans "Quantity:" %}</label></b>
             <input type="number" id="quantity" name="quantity" min="1">
         </div>
         <br>
-        <input type="submit" value="Add Deliverable">
+        <input type="submit" value="Add Deliverable" {% if not user_can_edit_deliverables %}disabled{% endif %}>
     </form>
     <br>
     <div id="list-deliverables">
         <div class="deliverables">
             {% for deliverable in invoice.deliverables.all %}
-                <b>{{ deliverable.deliverable.name }} ({{ deliverable.quantity }} {{ CURRENCY_SYMBOL }}{{deliverable.deliverable.unit_price}})</b><a href="{% url "api:v1:remove-deliverables" pk=deliverable.pk invoice_pk=invoice.pk project_pk=project.pk %}"> {% trans "Remove" %}</a>
+                <b>{{ deliverable.deliverable.name }} ({{ deliverable.quantity }} {{ CURRENCY_SYMBOL }}{{deliverable.deliverable.unit_price}})</b>{% if user_can_edit_deliverables %}<a href="{% url "api:v1:remove-deliverables" pk=deliverable.pk invoice_pk=invoice.pk project_pk=project.pk %}"> {% trans "Remove" %}</a>{% endif %}<br>
             {% endfor %}
         </div>
         {% if invoice.deliverables_total_amount.total %}
diff --git a/hypha/apply/projects/templatetags/invoice_tools.py b/hypha/apply/projects/templatetags/invoice_tools.py
index e416add71..84745c623 100644
--- a/hypha/apply/projects/templatetags/invoice_tools.py
+++ b/hypha/apply/projects/templatetags/invoice_tools.py
@@ -44,3 +44,8 @@ def can_complete_required_checks(invoice, user):
 @register.simple_tag
 def can_view_required_checks(invoice, user):
     return invoice.can_user_view_required_checks(user)
+
+
+@register.simple_tag
+def can_edit_deliverables(invoice, user):
+    return invoice.can_user_edit_deliverables(user)
-- 
GitLab