From cc0e22b9f981c420e62b29426bb6c0a6fe67ecec Mon Sep 17 00:00:00 2001
From: Sandeep Chauhan <sandeepsajan0@gmail.com>
Date: Sat, 30 Sep 2023 14:48:21 +0530
Subject: [PATCH] Add payment failed status, and add user roles to statuses,
 and update finance1 to finance (#3585)

Fixes #3567
---
 docs/references/notifications.md              |   4 +-
 .../apply/activity/adapters/activity_feed.py  |   2 +
 hypha/apply/activity/adapters/slack.py        |  10 +-
 hypha/apply/activity/adapters/utils.py        |   7 +-
 hypha/apply/api/v1/tests/test_views.py        |   8 +-
 hypha/apply/projects/forms/payment.py         |  21 ++-
 .../migrations/0080_alter_invoice_status.py   |  34 ++++
 hypha/apply/projects/models/payment.py        |  67 ++++---
 hypha/apply/projects/tables.py                |   2 +-
 .../application_projects/invoice_detail.html  |  29 ++-
 .../application_projects/paf_export.html      |  25 ++-
 .../project_approval_detail.html              |  10 +-
 .../application_projects/project_detail.html  |   8 +-
 .../projects/templatetags/invoice_tools.py    |  34 +++-
 .../projects/templatetags/project_tags.py     | 177 +++++++++++++-----
 hypha/apply/projects/tests/test_forms.py      |  30 +--
 hypha/apply/projects/tests/test_models.py     |  53 +++---
 hypha/apply/projects/utils.py                 |  12 +-
 hypha/apply/projects/views/payment.py         |   4 +-
 .../apply/templates/forms/includes/field.html |   2 +-
 .../src/sass/apply/components/_form.scss      |   4 +
 .../src/sass/apply/components/_icon.scss      |   7 +
 .../sass/apply/components/_simplified.scss    |   5 +
 hypha/templates/includes/sprites.html         |   5 +
 24 files changed, 379 insertions(+), 181 deletions(-)
 create mode 100644 hypha/apply/projects/migrations/0080_alter_invoice_status.py

diff --git a/docs/references/notifications.md b/docs/references/notifications.md
index e421b2986..78f0762a3 100644
--- a/docs/references/notifications.md
+++ b/docs/references/notifications.md
@@ -12,10 +12,10 @@ The types of messages are as follows:
 
 The options for statuses for messages are as follows:
 
-- `APPROVED_BY_FINANCE_1`
+- `APPROVED_BY_FINANCE`
 - `APPROVED_BY_FINANCE_2`
 - `APPROVED_BY_STAFF`
-- `CHANGES_REQUESTED_BY_FINANCE_1`
+- `CHANGES_REQUESTED_BY_FINANCE`
 - `CHANGES_REQUESTED_BY_FINANCE_2`
 - `CONVERTED`
 - `PAID`
diff --git a/hypha/apply/activity/adapters/activity_feed.py b/hypha/apply/activity/adapters/activity_feed.py
index 9a968aeea..bd3e6ca89 100644
--- a/hypha/apply/activity/adapters/activity_feed.py
+++ b/hypha/apply/activity/adapters/activity_feed.py
@@ -50,6 +50,7 @@ class ActivityAdapter(AdapterBase):
             "Lead changed from {old_lead} to {source.lead}"
         ),
         MESSAGES.SEND_FOR_APPROVAL: _("Requested approval"),
+        MESSAGES.APPROVE_PAF: _("PAF assigned to {user}"),
         MESSAGES.APPROVE_PROJECT: _("Approved"),
         MESSAGES.REQUEST_PROJECT_CHANGE: _(
             'Requested changes for acceptance: "{comment}"'
@@ -89,6 +90,7 @@ class ActivityAdapter(AdapterBase):
             MESSAGES.APPROVE_PROJECT,
             MESSAGES.REQUEST_PROJECT_CHANGE,
             MESSAGES.SEND_FOR_APPROVAL,
+            MESSAGES.APPROVE_PAF,
             MESSAGES.NEW_REVIEW,
             MESSAGES.UPDATE_PROJECT_LEAD,
         ]:
diff --git a/hypha/apply/activity/adapters/slack.py b/hypha/apply/activity/adapters/slack.py
index 3c2a1dc69..74d0daaf2 100644
--- a/hypha/apply/activity/adapters/slack.py
+++ b/hypha/apply/activity/adapters/slack.py
@@ -9,12 +9,13 @@ from hypha.apply.activity.adapters.base import AdapterBase
 from hypha.apply.activity.adapters.utils import link_to, reviewers_message
 from hypha.apply.activity.options import MESSAGES
 from hypha.apply.projects.models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
     PAID,
+    PAYMENT_FAILED,
     RESUBMITTED,
     SUBMITTED,
 )
@@ -189,9 +190,10 @@ class SlackAdapter(AdapterBase):
             if related.status in [
                 SUBMITTED,
                 RESUBMITTED,
-                CHANGES_REQUESTED_BY_FINANCE_1,
+                CHANGES_REQUESTED_BY_FINANCE,
                 APPROVED_BY_FINANCE_2,
                 PAID,
+                PAYMENT_FAILED,
             ]:
                 # Notify project lead/staff
                 return recipients
@@ -202,7 +204,7 @@ class SlackAdapter(AdapterBase):
                     for user in User.objects.finances_level_1()
                     if self.slack_id(user)
                 ]
-            if related.status in [APPROVED_BY_FINANCE_1]:
+            if related.status in [APPROVED_BY_FINANCE]:
                 # Notify finance 2
                 return [
                     self.slack_id(user)
diff --git a/hypha/apply/activity/adapters/utils.py b/hypha/apply/activity/adapters/utils.py
index ecaffde8a..98f95af82 100644
--- a/hypha/apply/activity/adapters/utils.py
+++ b/hypha/apply/activity/adapters/utils.py
@@ -7,7 +7,7 @@ from django.utils.translation import gettext as _
 from hypha.apply.activity.options import MESSAGES
 from hypha.apply.projects.models import ProjectSettings
 from hypha.apply.projects.models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     CHANGES_REQUESTED_BY_STAFF,
     DECLINED,
@@ -64,10 +64,7 @@ def is_invoice_public_transition(invoice):
         PAID,
     ]:
         return True
-    if (
-        not settings.INVOICE_EXTENDED_WORKFLOW
-        and invoice.status == APPROVED_BY_FINANCE_1
-    ):
+    if not settings.INVOICE_EXTENDED_WORKFLOW and invoice.status == APPROVED_BY_FINANCE:
         return True
     return False
 
diff --git a/hypha/apply/api/v1/tests/test_views.py b/hypha/apply/api/v1/tests/test_views.py
index f8fe382d7..da222eab5 100644
--- a/hypha/apply/api/v1/tests/test_views.py
+++ b/hypha/apply/api/v1/tests/test_views.py
@@ -5,7 +5,7 @@ from rest_framework.exceptions import ErrorDetail
 from hypha.apply.activity.models import ALL, APPLICANT, Activity
 from hypha.apply.activity.tests.factories import CommentFactory
 from hypha.apply.projects.models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
     SUBMITTED,
@@ -183,7 +183,7 @@ class TestInvoiceDeliverableViewset(TestCase):
     def test_finance2_can_add_deliverables(self):
         user = Finance2Factory()
         project = ProjectFactory()
-        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE)
         deliverable = DeliverableFactory(project=project)
         self.client.force_login(user)
 
@@ -241,7 +241,7 @@ class TestInvoiceDeliverableViewset(TestCase):
     def test_finance1_cant_remove_deliverables_after_finance1_approval(self):
         user = FinanceFactory()
         project = ProjectFactory()
-        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE)
         deliverable = DeliverableFactory(project=project)
         invoice_deliverable = InvoiceDeliverableFactory(deliverable=deliverable)
         invoice.deliverables.add(invoice_deliverable)
@@ -254,7 +254,7 @@ class TestInvoiceDeliverableViewset(TestCase):
     def test_finance2_can_remove_deliverables(self):
         user = Finance2Factory()
         project = ProjectFactory()
-        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(project=project, status=APPROVED_BY_FINANCE)
         deliverable = DeliverableFactory(project=project)
         invoice_deliverable = InvoiceDeliverableFactory(deliverable=deliverable)
         invoice.deliverables.add(invoice_deliverable)
diff --git a/hypha/apply/projects/forms/payment.py b/hypha/apply/projects/forms/payment.py
index ceb6fe68f..8379e92de 100644
--- a/hypha/apply/projects/forms/payment.py
+++ b/hypha/apply/projects/forms/payment.py
@@ -11,15 +11,16 @@ from django_file_form.forms import FileFormMixin
 from hypha.apply.stream_forms.fields import MultiFileField, SingleFileField
 
 from ..models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
     CHANGES_REQUESTED_BY_STAFF,
     DECLINED,
     INVOICE_STATUS_CHOICES,
     PAID,
+    PAYMENT_FAILED,
     RESUBMITTED,
     SUBMITTED,
     Invoice,
@@ -59,27 +60,29 @@ class ChangeInvoiceStatusForm(forms.ModelForm):
             ),
             APPROVED_BY_STAFF: filter_request_choices(
                 [
-                    CHANGES_REQUESTED_BY_FINANCE_1,
-                    APPROVED_BY_FINANCE_1,
+                    CHANGES_REQUESTED_BY_FINANCE,
+                    APPROVED_BY_FINANCE,
                 ],
                 user_choices,
             ),
-            CHANGES_REQUESTED_BY_FINANCE_1: filter_request_choices(
+            CHANGES_REQUESTED_BY_FINANCE: filter_request_choices(
                 [CHANGES_REQUESTED_BY_STAFF, DECLINED], user_choices
             ),
-            APPROVED_BY_FINANCE_1: filter_request_choices([PAID], user_choices),
+            APPROVED_BY_FINANCE: filter_request_choices([PAID], user_choices),
+            PAID: filter_request_choices([PAYMENT_FAILED], user_choices),
+            PAYMENT_FAILED: filter_request_choices([PAID], user_choices),
         }
         if settings.INVOICE_EXTENDED_WORKFLOW:
             possible_status_transitions_lut.update(
                 {
                     CHANGES_REQUESTED_BY_FINANCE_2: filter_request_choices(
                         [
-                            CHANGES_REQUESTED_BY_FINANCE_1,
-                            APPROVED_BY_FINANCE_1,
+                            CHANGES_REQUESTED_BY_FINANCE,
+                            APPROVED_BY_FINANCE,
                         ],
                         user_choices,
                     ),
-                    APPROVED_BY_FINANCE_1: filter_request_choices(
+                    APPROVED_BY_FINANCE: filter_request_choices(
                         [CHANGES_REQUESTED_BY_FINANCE_2, APPROVED_BY_FINANCE_2],
                         user_choices,
                     ),
diff --git a/hypha/apply/projects/migrations/0080_alter_invoice_status.py b/hypha/apply/projects/migrations/0080_alter_invoice_status.py
new file mode 100644
index 000000000..1378fa06a
--- /dev/null
+++ b/hypha/apply/projects/migrations/0080_alter_invoice_status.py
@@ -0,0 +1,34 @@
+# Generated by Django 3.2.20 on 2023-09-19 06:23
+
+from django.db import migrations
+import django_fsm
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("application_projects", "0079_alter_invoice_add_fields"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="invoice",
+            name="status",
+            field=django_fsm.FSMField(
+                choices=[
+                    ("submitted", "Submitted"),
+                    ("resubmitted", "Resubmitted"),
+                    ("changes_requested_staff", "Changes requested by staff"),
+                    ("changes_requested_finance_1", "Changes requested by finance"),
+                    ("changes_requested_finance_2", "Changes requested by finance 2"),
+                    ("approved_by_staff", "Approved by staff"),
+                    ("approved_by_finance_1", "Approved by finance"),
+                    ("approved_by_finance_2", "Approved by finance 2"),
+                    ("paid", "Paid"),
+                    ("payment_failed", "Payment failed"),
+                    ("declined", "Declined"),
+                ],
+                default="submitted",
+                max_length=50,
+            ),
+        ),
+    ]
diff --git a/hypha/apply/projects/models/payment.py b/hypha/apply/projects/models/payment.py
index 952ec3264..c96cccf88 100644
--- a/hypha/apply/projects/models/payment.py
+++ b/hypha/apply/projects/models/payment.py
@@ -18,24 +18,26 @@ from hypha.apply.utils.storage import PrivateStorage
 SUBMITTED = "submitted"
 RESUBMITTED = "resubmitted"
 CHANGES_REQUESTED_BY_STAFF = "changes_requested_staff"
-CHANGES_REQUESTED_BY_FINANCE_1 = "changes_requested_finance_1"
+CHANGES_REQUESTED_BY_FINANCE = "changes_requested_finance_1"
 CHANGES_REQUESTED_BY_FINANCE_2 = "changes_requested_finance_2"
 APPROVED_BY_STAFF = "approved_by_staff"
-APPROVED_BY_FINANCE_1 = "approved_by_finance_1"
+APPROVED_BY_FINANCE = "approved_by_finance_1"
 APPROVED_BY_FINANCE_2 = "approved_by_finance_2"
 PAID = "paid"
+PAYMENT_FAILED = "payment_failed"
 DECLINED = "declined"
 
 INVOICE_STATUS_CHOICES = [
     (SUBMITTED, _("Submitted")),
     (RESUBMITTED, _("Resubmitted")),
-    (CHANGES_REQUESTED_BY_STAFF, _("Changes Requested by Staff")),
-    (CHANGES_REQUESTED_BY_FINANCE_1, _("Changes Requested by Finance 1")),
-    (CHANGES_REQUESTED_BY_FINANCE_2, _("Changes Requested by Finance 2")),
-    (APPROVED_BY_STAFF, _("Approved by Staff")),
-    (APPROVED_BY_FINANCE_1, _("Approved by Finance 1")),
-    (APPROVED_BY_FINANCE_2, _("Approved by Finance 2")),
+    (CHANGES_REQUESTED_BY_STAFF, _("Changes requested by staff")),
+    (CHANGES_REQUESTED_BY_FINANCE, _("Changes requested by finance")),
+    (CHANGES_REQUESTED_BY_FINANCE_2, _("Changes requested by finance 2")),
+    (APPROVED_BY_STAFF, _("Approved by staff")),
+    (APPROVED_BY_FINANCE, _("Approved by finance")),
+    (APPROVED_BY_FINANCE_2, _("Approved by finance 2")),
     (PAID, _("Paid")),
+    (PAYMENT_FAILED, _("Payment failed")),
     (DECLINED, _("Declined")),
 ]
 
@@ -44,26 +46,31 @@ INVOICE_TRANISTION_TO_RESUBMITTED = [
     SUBMITTED,
     RESUBMITTED,
     CHANGES_REQUESTED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
 ]
 
 INVOICE_STATUS_PM_CHOICES = [CHANGES_REQUESTED_BY_STAFF, APPROVED_BY_STAFF, DECLINED]
 INVOICE_STATUS_FINANCE_1_CHOICES = [
-    CHANGES_REQUESTED_BY_FINANCE_1,
-    APPROVED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
+    APPROVED_BY_FINANCE,
+    DECLINED,
     PAID,
+    PAYMENT_FAILED,
 ]
 INVOICE_STATUS_FINANCE_2_CHOICES = []
 if settings.INVOICE_EXTENDED_WORKFLOW:
     INVOICE_STATUS_FINANCE_1_CHOICES = [
-        CHANGES_REQUESTED_BY_FINANCE_1,
-        APPROVED_BY_FINANCE_1,
+        CHANGES_REQUESTED_BY_FINANCE,
+        APPROVED_BY_FINANCE,
+        DECLINED,
     ]
     INVOICE_STATUS_FINANCE_2_CHOICES = [
         CHANGES_REQUESTED_BY_FINANCE_2,
         APPROVED_BY_FINANCE_2,
+        DECLINED,
         PAID,
+        PAYMENT_FAILED,
     ]
 
 
@@ -89,7 +96,7 @@ class InvoiceQueryset(models.QuerySet):
         return self.filter(status=APPROVED_BY_STAFF)
 
     def approved_by_finance_1(self):
-        return self.filter(status=APPROVED_BY_FINANCE_1)
+        return self.filter(status=APPROVED_BY_FINANCE)
 
     def approved_by_finance_2(self):
         return self.filter(status=APPROVED_BY_FINANCE_2)
@@ -97,20 +104,18 @@ class InvoiceQueryset(models.QuerySet):
     def waiting_to_convert(self):
         if settings.INVOICE_EXTENDED_WORKFLOW:
             return self.filter(status=APPROVED_BY_FINANCE_2)
-        return self.filter(status=APPROVED_BY_FINANCE_1)
+        return self.filter(status=APPROVED_BY_FINANCE)
 
     def for_finance_1(self):
         if settings.INVOICE_EXTENDED_WORKFLOW:
             return self.filter(
                 status__in=[APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE_2]
             )
-        return self.filter(status__in=[APPROVED_BY_STAFF, APPROVED_BY_FINANCE_1])
+        return self.filter(status__in=[APPROVED_BY_STAFF, APPROVED_BY_FINANCE])
 
     def for_finance_2(self):
         if settings.INVOICE_EXTENDED_WORKFLOW:
-            return self.filter(
-                status__in=[APPROVED_BY_FINANCE_1, APPROVED_BY_FINANCE_2]
-            )
+            return self.filter(status__in=[APPROVED_BY_FINANCE, APPROVED_BY_FINANCE_2])
         return []
 
     def rejected(self):
@@ -231,7 +236,7 @@ class Invoice(models.Model):
                 return True
 
         if user.is_apply_staff:
-            if self.status in {SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE_1}:
+            if self.status in {SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE}:
                 return True
 
         return False
@@ -248,7 +253,7 @@ class Invoice(models.Model):
         ):
             return False  # Users can't change status
 
-        if self.status in {PAID, DECLINED}:
+        if self.status in {DECLINED}:
             return False
 
         if user.is_contracting:
@@ -260,7 +265,7 @@ class Invoice(models.Model):
                 SUBMITTED,
                 RESUBMITTED,
                 CHANGES_REQUESTED_BY_STAFF,
-                CHANGES_REQUESTED_BY_FINANCE_1,
+                CHANGES_REQUESTED_BY_FINANCE,
             }:
                 return True
 
@@ -269,11 +274,21 @@ class Invoice(models.Model):
                 if self.status in {APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE_2}:
                     return True
             else:
-                if self.status in {APPROVED_BY_STAFF, APPROVED_BY_FINANCE_1}:
+                if self.status in {
+                    APPROVED_BY_STAFF,
+                    APPROVED_BY_FINANCE,
+                    PAID,
+                    PAYMENT_FAILED,
+                }:
                     return True
 
         if user.is_finance_level_2:
-            if self.status in {APPROVED_BY_FINANCE_1, APPROVED_BY_FINANCE_2}:
+            if self.status in {
+                APPROVED_BY_FINANCE,
+                APPROVED_BY_FINANCE_2,
+                PAID,
+                PAYMENT_FAILED,
+            }:
                 return True
 
         return False
@@ -284,7 +299,7 @@ class Invoice(models.Model):
         ):
             return False
         if user.is_apply_staff:
-            if self.status in {SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE_1}:
+            if self.status in {SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE}:
                 return True
         if user.is_finance_level_1:
             if self.status in {APPROVED_BY_STAFF}:
@@ -294,7 +309,7 @@ class Invoice(models.Model):
             ]:
                 return True
         if user.is_finance_level_2:
-            if self.status in {APPROVED_BY_FINANCE_1}:
+            if self.status in {APPROVED_BY_FINANCE}:
                 return True
         return False
 
diff --git a/hypha/apply/projects/tables.py b/hypha/apply/projects/tables.py
index 97e177d3f..117d6db83 100644
--- a/hypha/apply/projects/tables.py
+++ b/hypha/apply/projects/tables.py
@@ -8,7 +8,7 @@ from .models import Invoice, Project, Report
 
 
 class BaseInvoiceTable(tables.Table):
-    vendor_document_number = tables.LinkColumn(
+    invoice_number = tables.LinkColumn(
         "funds:projects:invoice-detail",
         verbose_name=_("Invoice Number"),
         args=[tables.utils.A("project__pk"), tables.utils.A("pk")],
diff --git a/hypha/apply/projects/templates/application_projects/invoice_detail.html b/hypha/apply/projects/templates/application_projects/invoice_detail.html
index 01ad8ead4..edf5fa4d9 100644
--- a/hypha/apply/projects/templates/application_projects/invoice_detail.html
+++ b/hypha/apply/projects/templates/application_projects/invoice_detail.html
@@ -19,9 +19,8 @@
             <div class="card card--solid">
                 <p class="card__text"><b>{% trans "Invoice number" %}:</b> {{ object.invoice_number }}</p>
                 {% is_vendor_setup request as show_vendor_information %}
-                {% if show_vendor_information %}
-                    <p class="card__text"><b>{% trans "Vendor" %}:</b> {{ object.project.vendor.name }}</p>
-                {% endif %}
+                <p class="card__text"><b>{% trans "Vendor" %}:</b>
+                    {% if show_vendor_information %}{{ object.project.vendor.name }}{% else %}{{ object.project.user }}{% endif %}</p>
                 <p class="card__text"><b>{% trans "Lead" %}:</b> {{ object.project.lead }}</p>
                 <p class="card__text"><b>{% trans "Fund" %}:</b> {{ object.project.submission.page }}</p>
             </div>
@@ -29,18 +28,32 @@
                 <div class="flex-none">
                     <p><b>{% trans "Status" %}: </b></p>
                 </div>
-                <div class="flex-1 pl-2">
+                <div class="pl-2">
                     {% extract_status latest_activity user as latest_activity_status %}
-                    <p>{{ latest_activity_status }} ({{ latest_activity.user }})</p>
+                    {% get_comment_for_invoice_action object latest_activity as latest_activity_comment %}
+                    <p>{{ latest_activity_status }} {% if user.is_applicant and latest_activity.user != user %} ({{ ORG_SHORT_NAME }}){% else %}({{ latest_activity.user }}){% endif %}
+                        <span class="text-gray-400">{{ latest_activity.timestamp }}</span>
+                        {% if latest_activity_comment %}
+                            <svg class="icon icon--request-changes"><use xlink:href="#request-changes"></use></svg>
+                            <a href="{% url 'apply:projects:detail' pk=object.project.id %}#communications#{{ latest_activity_comment.id }}" class="font-bold" target="_blank">View comment</a>
+                        {% endif %}
+                    </p>
                     {% for activity in activities %}
                         {% extract_status activity user as activity_status %}
-                        <p x-show="!collapsed">{{ activity_status }} ({{ activity.user }})</p>
+                        {% get_comment_for_invoice_action object activity as activity_comment %}
+                        <p x-show="!collapsed">{{ activity_status }} {% if user.is_applicant and activity.user != user %} ({{ ORG_SHORT_NAME }}){% else %}({{ activity.user }}){% endif %}
+                            <span class="text-gray-400">{{ activity.timestamp }}</span>
+                            {% if activity_comment %}
+                                <svg class="icon icon--request-changes"><use xlink:href="#request-changes"></use></svg>
+                                <a href="{% url 'apply:projects:detail' pk=object.project.id %}#communications#{{ activity_comment.id }}" class="font-bold" target="_blank">View comment</a>
+                            {% endif %}
+                        </p>
                     {% endfor %}
                 </div>
                 <div class="flex-1 text-right" x-on:click="collapsed = ! collapsed" role="button">
-                    <p class="font-bold text-light-blue" x-show="collapsed">{% trans "View status history" %}
+                    <p class="font-bold text-light-blue" x-show="collapsed">{% trans "View" %}
                         <svg class="icon icon--arrow-down top-1"  aria-hidden=true><use xlink:href="#arrow-down"></use></svg></p>
-                    <p class="font-bold text-light-blue" x-show="!collapsed">{% trans "Hide status history" %}
+                    <p class="font-bold text-light-blue" x-show="!collapsed">{% trans "Hide" %}
                         <svg class="icon icon--arrow-up top-1" aria-hidden=true><use xlink:href="#arrow-up"></use></svg></p>
 
                 </div>
diff --git a/hypha/apply/projects/templates/application_projects/paf_export.html b/hypha/apply/projects/templates/application_projects/paf_export.html
index 56a23d796..c5b3c55c1 100644
--- a/hypha/apply/projects/templates/application_projects/paf_export.html
+++ b/hypha/apply/projects/templates/application_projects/paf_export.html
@@ -39,7 +39,6 @@
                 .title {
                     text-align: center;
                     font-size: 22px;
-                    font-weight: bold;
                 }
                 p {
                     font-size: 16px;
@@ -62,37 +61,35 @@
     </head>
     <body>
         <div>
-            {%block page_header%}
-                <h1 class="title"> {{ org_name }}(Project Approval Form | <a href="{{ project_link }}">{{ title }}</a>)</h1>
-            {%endblock%}
 
             {%block content%}
                 <table id="page-width">
 <!--            Project details in table format -->
                     <tr>
-                        <td class="align-left">
-                            <b>Project Title</b>
+                        <td rowspan="4" align="left" class="align-left">
+                            <p class="title"> <b>{{ org_name|upper }}</b> PROJECT APPROVAL FORM</p>
                         </td>
                         <td align="right" class="align-right">
-                            <b>Project ID</b>
+                            <b>Project Title</b>
                         </td>
                     </tr>
                     <tr>
-                        <td>
-                            {{ title }}
+                        <td align="right" class="align-right">
+                            <a href="{{ project_link }}">{{ title }}</a>
                         </td>
+                    </tr>
+                    <tr>
                         <td align="right" class="align-right">
-                            {{ id }}
+                            <b>Project ID</b>
                         </td>
                     </tr>
-                    <tr></tr>
-
                     <tr>
-                        <td class="align-left">
-                            <b>Contractor: </b> {{ contractor_name|default:"None" }}
+                        <td align="right" class="align-right">
+                            {{ id }}
                         </td>
                     </tr>
                 </table>
+                <br>
 <!--            PAF fields data in paragraph format-->
                 {% for field_name, field_value in paf_data.items %}
                     <p><b>{{ field_name }}</b></p>
diff --git a/hypha/apply/projects/templates/application_projects/project_approval_detail.html b/hypha/apply/projects/templates/application_projects/project_approval_detail.html
index 3521fa187..f2f5eb89c 100644
--- a/hypha/apply/projects/templates/application_projects/project_approval_detail.html
+++ b/hypha/apply/projects/templates/application_projects/project_approval_detail.html
@@ -32,7 +32,7 @@
         <div class="wrapper wrapper--large wrapper--tabs">
             <div class="wrapper wrapper--sidebar">
                 <article class="wrapper--sidebar--inner">
-                    <h4>{% trans "Project Information" %}</h4>
+                    <h4 class="mb-2">{% trans "Project Information" %}</h4>
                     <div class="card card--solid">
 
                         {% if object.output_answers %}
@@ -49,7 +49,7 @@
                         {% endif %}
                     </div>
 
-                    <h4>{% trans "Approvals" %}</h4>
+                    <h4 class="mb-2">{% trans "Approvals" %}</h4>
                     <div class="card card--solid">
                         {% for approval in project.paf_approvals.all %}
                             {% if approval.approved %}
@@ -60,7 +60,7 @@
                         {% endfor %}
                     </div>
 
-                    <h4>{% trans "Review" %}</h4>
+                    <h4 class="mb-2">{% trans "Review" %}</h4>
                     <div class="card card--solid">
                         <p class="font-bold mb-0 mt-0">{% trans "Submission lead" %}</p>
                         <p class="mt-2 mb-0">{{ project.submission.lead }}</p>
@@ -87,7 +87,7 @@
                         {% endfor %}
                     </div>
 
-                    <h4>{% trans "Supporting Documents" %}</h4>
+                    <h4 class="mb-2">{% trans "Supporting Documents" %}</h4>
                     <div class="card card--solid">
                         <p><a href="{% url 'apply:submissions:simplified' pk=object.submission_id %}">{% trans "Submission" %}</a></p>
                         {% for packet_file in object.packet_files.all %}
@@ -125,7 +125,7 @@
                                 {% if user != project.lead %}
                                     <a data-fancybox
                                        data-src="#change-assigned-paf-approvers"
-                                       class="button button--bottom-space button--primary button--full-width"
+                                       class="button button--bottom-space button--white button--full-width"
                                        href="#">
                                         {% trans "Change approver" %}
                                     </a>
diff --git a/hypha/apply/projects/templates/application_projects/project_detail.html b/hypha/apply/projects/templates/application_projects/project_detail.html
index e56632367..73183c690 100644
--- a/hypha/apply/projects/templates/application_projects/project_detail.html
+++ b/hypha/apply/projects/templates/application_projects/project_detail.html
@@ -149,13 +149,15 @@
                         {% user_next_step_on_project object user request=request as next_step %}
                         {% if next_step %}
                             {% if mobile %}
-                                <a class="js-actions-toggle button button--white button--full-width button--actions">{% trans "Next Step" %}</a>
+                                <a class="js-actions-toggle button button--white button--full-width button--actions">{{ next_step.heading }}</a>
                             {% endif %}
 
                             <div class="js-actions-sidebar sidebar__inner sidebar__inner--actions {% if mobile %}sidebar__inner--mobile{% endif %}">
 
-                                <h5>{% trans "Next Step" %}</h5>
-                                <p>{{ next_step }}</p>
+                                <h5><svg class="icon icon--side-arrow"><use xlink:href="#side-arrow"></use></svg>
+                                    {{ next_step.heading }}
+                                </h5>
+                                <p>{{ next_step.text }}</p>
                                 {% user_next_step_instructions object user as instructions %}
                                 {% if instructions %}
                                     <div class="sidebar__inner--actions--instructions">
diff --git a/hypha/apply/projects/templatetags/invoice_tools.py b/hypha/apply/projects/templatetags/invoice_tools.py
index 49bdcbb43..a808740e7 100644
--- a/hypha/apply/projects/templatetags/invoice_tools.py
+++ b/hypha/apply/projects/templatetags/invoice_tools.py
@@ -1,7 +1,11 @@
 import decimal
+from datetime import timedelta
 
 from django import template
+from django.conf import settings
+from django.utils.translation import gettext_lazy as _
 
+from hypha.apply.activity.models import Activity
 from hypha.apply.activity.templatetags.activity_tags import display_for
 from hypha.apply.projects.models.project import (
     CLOSING,
@@ -92,9 +96,24 @@ def get_invoice_form_id(form, invoice):
 def extract_status(activity, user):
     if activity and user:
         invoice_activity_message = display_for(activity, user)
-        return invoice_activity_message.replace(
+        invoice_status = invoice_activity_message.replace(
             "Updated Invoice status to: ", ""
         ).replace(".", "")
+        if " by " not in str(invoice_status) and not user.is_applicant:
+            if activity.user.is_apply_staff:
+                user_role = "staff"
+            elif (
+                activity.user.is_finance_level_2 and settings.INVOICE_EXTENDED_WORKFLOW
+            ):
+                user_role = "finance2"
+            elif activity.user.is_finance:
+                user_role = "finance"
+            else:
+                user_role = "vendor"
+            return _("{status} by {user_role}").format(
+                status=invoice_status, user_role=user_role
+            )
+        return invoice_status
     return ""
 
 
@@ -103,3 +122,16 @@ def display_invoice_status_for_user(user, invoice):
     if user.is_apply_staff or user.is_contracting or user.is_finance:
         return invoice.status_display
     return get_invoice_public_status(invoice_status=invoice.status)
+
+
+@register.simple_tag
+def get_comment_for_invoice_action(invoice, action):
+    if action and invoice:
+        return Activity.comments.filter(
+            timestamp__range=(
+                action.timestamp - timedelta(minutes=1),
+                action.timestamp + timedelta(minutes=1),
+            ),
+            related_content_type__model="invoice",
+            related_object_id=invoice.id,
+        ).first()
diff --git a/hypha/apply/projects/templatetags/project_tags.py b/hypha/apply/projects/templatetags/project_tags.py
index e68e10b29..5432966ef 100644
--- a/hypha/apply/projects/templatetags/project_tags.py
+++ b/hypha/apply/projects/templatetags/project_tags.py
@@ -32,24 +32,45 @@ def user_next_step_on_project(project, user, request=None):
     if project.status == DRAFT:
         if user.is_apply_staff:
             if not project.user_has_updated_details:
-                return _("Fill in the Approval Form(PAF)")
+                return {
+                    "heading": _("To do"),
+                    "text": _("Fill in the Approval Form(PAF)"),
+                }
             if project.paf_approvals.exists():
-                return _("Resubmit project documents for approval")
-            return _("Submit project documents for approval")
+                return {
+                    "heading": _("To do"),
+                    "text": _("Resubmit project documents for approval"),
+                }
+            return {
+                "heading": _("To do"),
+                "text": _("Submit project documents for approval"),
+            }
         elif user.is_applicant:
-            return _(
-                "Awaiting project documents to be created and approved by {org_short_name} internally. "
-                "Please check back when the project has moved to contracting stage."
-            ).format(org_short_name=settings.ORG_SHORT_NAME)
+            return {
+                "heading": _("Waiting for"),
+                "text": _(
+                    "Awaiting project documents to be created and approved by {org_short_name} internally. "
+                    "Please check back when the project has moved to contracting stage."
+                ).format(org_short_name=settings.ORG_SHORT_NAME),
+            }
         if project.paf_approvals.exists():
-            return _("Changes requested. Awaiting documents to be resubmitted.")
-        return _("Awaiting approval form to be created.")
+            return {
+                "heading": _("Waiting for"),
+                "text": _("Changes requested. Awaiting documents to be resubmitted."),
+            }
+        return {
+            "heading": _("Waiting for"),
+            "text": _("Awaiting approval form to be created."),
+        }
     elif project.status == INTERNAL_APPROVAL:
         if user.is_applicant:
-            return _(
-                "Awaiting project documents to be created and approved by {org_short_name} internally. "
-                "Please check back when the project has moved to contracting stage."
-            ).format(org_short_name=settings.ORG_SHORT_NAME)
+            return {
+                "heading": _("Waiting for"),
+                "text": _(
+                    "Awaiting project documents to be created and approved by {org_short_name} internally. "
+                    "Please check back when the project has moved to contracting stage."
+                ).format(org_short_name=settings.ORG_SHORT_NAME),
+            }
 
         if request:
             project_settings = ProjectSettings.for_request(request=request)
@@ -59,12 +80,20 @@ def user_next_step_on_project(project, user, request=None):
                 ).first()
                 if latest_unapproved_approval:
                     if latest_unapproved_approval.user:
-                        return _("Awaiting approval. Assigned to {approver}").format(
-                            approver=latest_unapproved_approval.user
-                        )
-                    return _("Awaiting {reviewer_role} to assign an approver").format(
-                        reviewer_role=latest_unapproved_approval.paf_reviewer_role.label
-                    )
+                        return {
+                            "heading": _("Waiting for"),
+                            "text": _(
+                                "Awaiting approval. Assigned to {approver}"
+                            ).format(approver=latest_unapproved_approval.user),
+                        }
+                    return {
+                        "heading": _("Waiting for"),
+                        "text": _(
+                            "Awaiting {reviewer_role} to assign an approver"
+                        ).format(
+                            reviewer_role=latest_unapproved_approval.paf_reviewer_role.label
+                        ),
+                    }
             else:
                 matched_roles = PAFReviewersRole.objects.annotate(
                     roles_count=Count("user_roles")
@@ -72,57 +101,109 @@ def user_next_step_on_project(project, user, request=None):
                 for group in user.groups.all():
                     matched_roles = matched_roles.filter(user_roles__id=group.id)
                 if not matched_roles:
-                    return _("Awaiting PAF approval form to be approved")
+                    return {
+                        "heading": _("Waiting for"),
+                        "text": _("Awaiting PAF approval form to be approved"),
+                    }
                 else:
                     matched_unapproved_approval = project.paf_approvals.filter(
                         approved=False, paf_reviewer_role__in=matched_roles
                     )
                     if not matched_unapproved_approval.exists():
-                        return _("Awaiting approval from other approvers teams")
+                        return {
+                            "heading": _("Waiting for"),
+                            "text": _("Awaiting approval from other approvers teams"),
+                        }
                     else:
                         if matched_unapproved_approval.first().user:
-                            return _(
-                                "Awaiting approval. Assigned to {approver}"
-                            ).format(approver=matched_unapproved_approval.first().user)
-                        return _(
-                            "Awaiting {reviewer_role} to assign an approver"
-                        ).format(
-                            reviewer_role=matched_unapproved_approval.first().paf_reviewer_role.label
-                        )
-
-        return _("Awaiting project approval from assigned approvers")
+                            return {
+                                "heading": _("Waiting for"),
+                                "text": _(
+                                    "Awaiting approval. Assigned to {approver}"
+                                ).format(
+                                    approver=matched_unapproved_approval.first().user
+                                ),
+                            }
+                        return {
+                            "heading": _("Waiting for"),
+                            "text": _(
+                                "Awaiting {reviewer_role} to assign an approver"
+                            ).format(
+                                reviewer_role=matched_unapproved_approval.first().paf_reviewer_role.label
+                            ),
+                        }
+
+        return {
+            "heading": _("Waiting for"),
+            "text": _("Awaiting project approval from assigned approvers"),
+        }
     elif project.status == CONTRACTING:
         if not project.contracts.exists():
             if user.is_applicant:
-                return _("Awaiting signed contract from {org_short_name}").format(
-                    org_short_name=settings.ORG_SHORT_NAME
-                )
-            return _("Awaiting signed contract from Contracting team")
+                return {
+                    "heading": _("Waiting for"),
+                    "text": _("Awaiting signed contract from {org_short_name}").format(
+                        org_short_name=settings.ORG_SHORT_NAME
+                    ),
+                }
+            return {
+                "heading": _("Waiting for"),
+                "text": _("Awaiting signed contract from Contracting team"),
+            }
         else:
             contract = project.contracts.order_by("-created_at").first()
             if not contract.signed_by_applicant:
                 if user.is_applicant:
-                    return _("Awaiting contract documents to be submitted by you.")
-                return _("Awaiting countersigned contract from Vendor")
+                    return {
+                        "heading": _("To do"),
+                        "text": _(
+                            "Awaiting contract documents to be submitted by you."
+                        ),
+                    }
+                return {
+                    "heading": _("Waiting for"),
+                    "text": _("Awaiting countersigned contract from Vendor"),
+                }
             elif not project.submitted_contract_documents:
                 if user.is_applicant:
-                    return _("Awaiting contract documents submission by you")
-                return _("Awaiting contract documents submission from Vendor")
+                    return {
+                        "heading": _("To do"),
+                        "text": _("Awaiting contract documents submission by you"),
+                    }
+                return {
+                    "heading": _("Waiting for"),
+                    "text": _("Awaiting contract documents submission from Vendor"),
+                }
             else:
                 if user.is_apply_staff:
-                    return _(
-                        "Review the contract for all relevant details and approve."
-                    )
+                    return {
+                        "heading": _("To do"),
+                        "text": _(
+                            "Review the contract for all relevant details and approve."
+                        ),
+                    }
                 if user.is_applicant:
-                    return _("Awaiting contract approval from {org_short_name}").format(
-                        org_short_name=settings.ORG_SHORT_NAME
-                    )
-                return _("Awaiting contract approval from Staff")
+                    return {
+                        "heading": _("Waiting for"),
+                        "text": _(
+                            "Awaiting contract approval from {org_short_name}"
+                        ).format(org_short_name=settings.ORG_SHORT_NAME),
+                    }
+                return {
+                    "heading": _("Waiting for"),
+                    "text": _("Awaiting contract approval from Staff"),
+                }
     elif project.status == INVOICING_AND_REPORTING:
         if user.is_applicant and not project.invoices.exists():
-            return _("Add invoices")
+            return {
+                "heading": _("To do"),
+                "text": _("Add invoices"),
+            }
         elif user.is_apply_staff or user.is_finance:
-            return _("Review invoice and take action")
+            return {
+                "heading": _("To do"),
+                "text": _("Review invoice and take action"),
+            }
     return False
 
 
diff --git a/hypha/apply/projects/tests/test_forms.py b/hypha/apply/projects/tests/test_forms.py
index a1d85c869..0c9ff6274 100644
--- a/hypha/apply/projects/tests/test_forms.py
+++ b/hypha/apply/projects/tests/test_forms.py
@@ -28,10 +28,10 @@ from ..forms.project import (
     UploadContractForm,
 )
 from ..models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
     CHANGES_REQUESTED_BY_STAFF,
     DECLINED,
@@ -176,7 +176,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
@@ -190,7 +190,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
@@ -204,7 +204,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
@@ -212,7 +212,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
         self.assertEqual(expected, actual)
 
     def test_staff_choices_with_changes_requested_by_finance1_status(self):
-        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE)
         user = StaffFactory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -226,7 +226,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
         self.assertEqual(expected, actual)
 
     def test_finance1_choices_with_changes_requested_by_finance1_status(self):
-        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE)
         user = FinanceFactory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -240,7 +240,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
         self.assertEqual(expected, actual)
 
     def test_finance2_choices_with_changes_requested_by_finance1_status(self):
-        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE)
         user = Finance2Factory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -254,7 +254,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
         self.assertEqual(expected, actual)
 
     def test_staff_choices_with_approved_by_finance1_status(self):
-        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE)
         user = StaffFactory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -269,7 +269,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
     def test_finance1_choices_with_approved_by_finance1_status_with_extended_flow(self):
-        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE)
         user = FinanceFactory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -284,7 +284,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=False)
     def test_finance1_choices_with_approved_by_finance1_status(self):
-        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE)
         user = FinanceFactory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -296,7 +296,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
     def test_finance2_choices_with_approved_by_finance1_status(self):
-        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        invoice = InvoiceFactory(status=APPROVED_BY_FINANCE)
         user = Finance2Factory()
         form = ChangeInvoiceStatusForm(instance=invoice, user=user)
 
@@ -317,7 +317,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
@@ -332,7 +332,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
@@ -347,7 +347,7 @@ class TestChangeInvoiceStatusFormForm(TestCase):
 
         expected = set(
             filter_request_choices(
-                [CHANGES_REQUESTED_BY_FINANCE_1, APPROVED_BY_FINANCE_1],
+                [CHANGES_REQUESTED_BY_FINANCE, APPROVED_BY_FINANCE],
                 invoice_status_user_choices(user),
             )
         )
diff --git a/hypha/apply/projects/tests/test_models.py b/hypha/apply/projects/tests/test_models.py
index 4a2199dec..df84018b9 100644
--- a/hypha/apply/projects/tests/test_models.py
+++ b/hypha/apply/projects/tests/test_models.py
@@ -13,10 +13,10 @@ from hypha.apply.users.tests.factories import (
 )
 
 from ..models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
     CHANGES_REQUESTED_BY_STAFF,
     DECLINED,
@@ -24,6 +24,7 @@ from ..models.payment import (
     INVOICE_STATUS_FINANCE_2_CHOICES,
     INVOICE_STATUS_PM_CHOICES,
     PAID,
+    PAYMENT_FAILED,
     RESUBMITTED,
     SUBMITTED,
     Invoice,
@@ -162,7 +163,7 @@ class TestInvoiceModel(TestCase):
             SUBMITTED,
             RESUBMITTED,
             CHANGES_REQUESTED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
         ]
         user = StaffFactory()
         for status in statuses:
@@ -172,7 +173,7 @@ class TestInvoiceModel(TestCase):
     def test_staff_cant_change_status(self):
         statuses = [
             APPROVED_BY_STAFF,
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
             CHANGES_REQUESTED_BY_FINANCE_2,
             DECLINED,
@@ -193,7 +194,7 @@ class TestInvoiceModel(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=False)
     def test_finance1_can_change_status(self):
-        statuses = [APPROVED_BY_STAFF, APPROVED_BY_FINANCE_1]
+        statuses = [APPROVED_BY_STAFF, APPROVED_BY_FINANCE, PAID, PAYMENT_FAILED]
         user = FinanceFactory()
         for status in statuses:
             invoice = InvoiceFactory(status=status)
@@ -202,10 +203,10 @@ class TestInvoiceModel(TestCase):
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
     def test_finance1_cant_change_status_with_extended_flow(self):
         statuses = [
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
             CHANGES_REQUESTED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             DECLINED,
             PAID,
             RESUBMITTED,
@@ -220,9 +221,8 @@ class TestInvoiceModel(TestCase):
     def test_finance1_cant_change_status(self):
         statuses = [
             CHANGES_REQUESTED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             DECLINED,
-            PAID,
             RESUBMITTED,
             SUBMITTED,
         ]
@@ -233,7 +233,7 @@ class TestInvoiceModel(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
     def test_finance2_can_change_status_with_extended_flow(self):
-        statuses = [APPROVED_BY_FINANCE_1, APPROVED_BY_FINANCE_2]
+        statuses = [APPROVED_BY_FINANCE, APPROVED_BY_FINANCE_2, PAID, PAYMENT_FAILED]
         user = Finance2Factory()
         for status in statuses:
             invoice = InvoiceFactory(status=status)
@@ -243,11 +243,10 @@ class TestInvoiceModel(TestCase):
     def test_finance2_cant_change_status(self):
         statuses = [
             APPROVED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             CHANGES_REQUESTED_BY_FINANCE_2,
             CHANGES_REQUESTED_BY_STAFF,
             DECLINED,
-            PAID,
             RESUBMITTED,
             SUBMITTED,
         ]
@@ -265,10 +264,10 @@ class TestInvoiceModel(TestCase):
 
     def test_applicant_cant_edit_invoice(self):
         statuses = [
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
             APPROVED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             CHANGES_REQUESTED_BY_FINANCE_2,
             DECLINED,
             PAID,
@@ -279,7 +278,7 @@ class TestInvoiceModel(TestCase):
             self.assertFalse(invoice.can_user_edit(user))
 
     def test_staff_can_edit_invoice(self):
-        statuses = [SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE_1]
+        statuses = [SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE]
         user = StaffFactory()
         for status in statuses:
             invoice = InvoiceFactory(status=status)
@@ -287,7 +286,7 @@ class TestInvoiceModel(TestCase):
 
     def test_staff_cant_edit_invoice(self):
         statuses = [
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
             APPROVED_BY_STAFF,
             CHANGES_REQUESTED_BY_FINANCE_2,
@@ -306,8 +305,8 @@ class TestInvoiceModel(TestCase):
             RESUBMITTED,
             CHANGES_REQUESTED_BY_STAFF,
             APPROVED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
-            APPROVED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
+            APPROVED_BY_FINANCE,
             CHANGES_REQUESTED_BY_FINANCE_2,
             APPROVED_BY_FINANCE_2,
             DECLINED,
@@ -319,7 +318,7 @@ class TestInvoiceModel(TestCase):
             self.assertFalse(invoice.can_user_edit_deliverables(user))
 
     def test_staff_can_edit_deliverables(self):
-        statuses = [SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE_1]
+        statuses = [SUBMITTED, RESUBMITTED, CHANGES_REQUESTED_BY_FINANCE]
         user = StaffFactory()
         for status in statuses:
             invoice = InvoiceFactory(status=status)
@@ -327,7 +326,7 @@ class TestInvoiceModel(TestCase):
 
     def test_staff_cant_edit_deliverables(self):
         statuses = [
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
             APPROVED_BY_STAFF,
             CHANGES_REQUESTED_BY_FINANCE_2,
@@ -358,9 +357,9 @@ class TestInvoiceModel(TestCase):
 
     def test_finance1_cant_edit_deliverables(self):
         statuses = [
-            APPROVED_BY_FINANCE_1,
+            APPROVED_BY_FINANCE,
             APPROVED_BY_FINANCE_2,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             CHANGES_REQUESTED_BY_STAFF,
             DECLINED,
             PAID,
@@ -374,7 +373,7 @@ class TestInvoiceModel(TestCase):
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
     def test_finance2_can_edit_deliverables(self):
-        statuses = [APPROVED_BY_FINANCE_1]
+        statuses = [APPROVED_BY_FINANCE]
         user = Finance2Factory()
         for status in statuses:
             invoice = InvoiceFactory(status=status)
@@ -385,7 +384,7 @@ class TestInvoiceModel(TestCase):
         statuses = [
             APPROVED_BY_FINANCE_2,
             APPROVED_BY_STAFF,
-            CHANGES_REQUESTED_BY_FINANCE_1,
+            CHANGES_REQUESTED_BY_FINANCE,
             CHANGES_REQUESTED_BY_FINANCE_2,
             CHANGES_REQUESTED_BY_STAFF,
             DECLINED,
@@ -412,7 +411,7 @@ class TestInvoiceQueryset(TestCase):
     def test_in_progress(self):
         InvoiceFactory(status=SUBMITTED)
         InvoiceFactory(status=APPROVED_BY_STAFF)
-        InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE_1)
+        InvoiceFactory(status=CHANGES_REQUESTED_BY_FINANCE)
         InvoiceFactory(status=DECLINED)
         self.assertEqual(Invoice.objects.in_progress().count(), 3)
 
@@ -421,7 +420,7 @@ class TestInvoiceQueryset(TestCase):
         self.assertEqual(Invoice.objects.approved_by_staff().count(), 1)
 
     def test_approved_by_finance_1(self):
-        InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        InvoiceFactory(status=APPROVED_BY_FINANCE)
         self.assertEqual(Invoice.objects.approved_by_finance_1().count(), 1)
 
     @override_settings(INVOICE_EXTENDED_WORKFLOW=True)
@@ -434,7 +433,7 @@ class TestInvoiceQueryset(TestCase):
     @override_settings(INVOICE_EXTENDED_WORKFLOW=False)
     def test_for_finance_1(self):
         InvoiceFactory(status=APPROVED_BY_STAFF)
-        InvoiceFactory(status=APPROVED_BY_FINANCE_1)
+        InvoiceFactory(status=APPROVED_BY_FINANCE)
         InvoiceFactory(status=SUBMITTED)
         self.assertEqual(Invoice.objects.for_finance_1().count(), 2)
 
diff --git a/hypha/apply/projects/utils.py b/hypha/apply/projects/utils.py
index aab11ecce..b367f0ea5 100644
--- a/hypha/apply/projects/utils.py
+++ b/hypha/apply/projects/utils.py
@@ -3,10 +3,10 @@ from django.utils.translation import gettext_lazy as _
 
 from .models import Deliverable, Project
 from .models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_FINANCE_2,
     APPROVED_BY_STAFF,
-    CHANGES_REQUESTED_BY_FINANCE_1,
+    CHANGES_REQUESTED_BY_FINANCE,
     CHANGES_REQUESTED_BY_FINANCE_2,
     CHANGES_REQUESTED_BY_STAFF,
     DECLINED,
@@ -120,13 +120,13 @@ def get_paf_status_display(paf_status):
 def get_invoice_public_status(invoice_status):
     if (
         invoice_status
-        in [SUBMITTED, RESUBMITTED, APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE_1]
+        in [SUBMITTED, RESUBMITTED, APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE]
     ) or (
-        invoice_status in [APPROVED_BY_FINANCE_1, CHANGES_REQUESTED_BY_FINANCE_2]
+        invoice_status in [APPROVED_BY_FINANCE, CHANGES_REQUESTED_BY_FINANCE_2]
         and settings.INVOICE_EXTENDED_WORKFLOW
     ):
-        return _("Pending Approval")
-    if (invoice_status == APPROVED_BY_FINANCE_1) or (
+        return _("Pending approval")
+    if (invoice_status == APPROVED_BY_FINANCE) or (
         invoice_status == APPROVED_BY_FINANCE_2 and settings.INVOICE_EXTENDED_WORKFLOW
     ):
         return _("Approved")
diff --git a/hypha/apply/projects/views/payment.py b/hypha/apply/projects/views/payment.py
index a29fda248..7a3f934ad 100644
--- a/hypha/apply/projects/views/payment.py
+++ b/hypha/apply/projects/views/payment.py
@@ -21,7 +21,7 @@ from hypha.apply.utils.views import DelegateableView, DelegatedViewMixin, ViewDi
 from ..filters import InvoiceListFilter
 from ..forms import ChangeInvoiceStatusForm, CreateInvoiceForm, EditInvoiceForm
 from ..models.payment import (
-    APPROVED_BY_FINANCE_1,
+    APPROVED_BY_FINANCE,
     APPROVED_BY_STAFF,
     INVOICE_TRANISTION_TO_RESUBMITTED,
     Invoice,
@@ -82,7 +82,7 @@ class ChangeInvoiceStatusView(DelegatedViewMixin, InvoiceAccessMixin, UpdateView
         ) or (
             settings.INVOICE_EXTENDED_WORKFLOW
             and self.request.user.is_finance_level_1
-            and self.object.status == APPROVED_BY_FINANCE_1
+            and self.object.status == APPROVED_BY_FINANCE
         ):
             messenger(
                 MESSAGES.APPROVE_INVOICE,
diff --git a/hypha/apply/templates/forms/includes/field.html b/hypha/apply/templates/forms/includes/field.html
index acd603362..9a943ba70 100644
--- a/hypha/apply/templates/forms/includes/field.html
+++ b/hypha/apply/templates/forms/includes/field.html
@@ -4,7 +4,7 @@
 
     <div class="form__group {{ field.id_for_label }} form__group--{{ widget_type }} {% if widget_type == 'checkbox_input' %} form__group--checkbox{% endif %}{% if widget_type == 'clearable_file_input' or widget_type == 'multi_file_input' or widget_type == 'single_file_field_widget' or widget_type == 'multi_file_field_widget' %} form__group--file{% endif %}{% if field.help_text %} form__group--wrap{% endif %}{% if field.errors %} form__error{% endif %}{% if is_application and field.field.group_number > 1 %} field-group field-group-{{ field.field.group_number }}{% endif %}{% if is_application and field.field.grouper_for %} form-fields-grouper{% endif %}"{% if is_application and field.field.grouper_for %}data-grouper-for="{{ field.field.grouper_for }}" data-toggle-on="{{ field.field.choices.0.0 }}" data-toggle-off="{{ field.field.choices.1.0 }}"{% endif %}{% if is_application and field.field.group_number > 1 %} data-hidden="{% if not show_all_group_fields and not field.field.visible %}true{% else %}false{% endif %}" data-required="{{ field.field.required_when_visible }}"{% endif %}{% if field.field.word_limit %} data-word-limit="{{ field.field.word_limit }}"{% endif %}>
         {% if widget_type == 'clearable_file_input' or widget_type == 'multi_file_input' or widget_type == 'single_file_field_widget' or widget_type == 'multi_file_field_widget'%}
-            <span class="form__question">{{ field.label }}</span>
+            <span class="form__question form__file-label">{{ field.label }}</span>
             <label for="{{ field.id_for_label }}" class="form__question form__question--{{ field_type }} {{ widget_type }}" {% if field.field.required %}required{% endif %}>
                 <span>{% trans "Upload" %}</span>
                 {% if field.field.required %}
diff --git a/hypha/static_src/src/sass/apply/components/_form.scss b/hypha/static_src/src/sass/apply/components/_form.scss
index e38d4ee12..c29c801be 100644
--- a/hypha/static_src/src/sass/apply/components/_form.scss
+++ b/hypha/static_src/src/sass/apply/components/_form.scss
@@ -134,6 +134,10 @@
         // stylelint-enable selector-class-pattern
     }
 
+    &__file-label {
+        padding-bottom: 0.5rem;
+    }
+
     &__file-list {
         ul {
             margin: 0.5rem 0;
diff --git a/hypha/static_src/src/sass/apply/components/_icon.scss b/hypha/static_src/src/sass/apply/components/_icon.scss
index 5cee7bc02..dcc3730de 100644
--- a/hypha/static_src/src/sass/apply/components/_icon.scss
+++ b/hypha/static_src/src/sass/apply/components/_icon.scss
@@ -164,6 +164,13 @@
         stroke: $color--light-blue;
     }
 
+    &--side-arrow {
+        position: relative;
+        align-self: center;
+        width: 8px;
+        height: 30px;
+    }
+
     &--arrow-up-short-bar {
         position: relative;
         align-self: center;
diff --git a/hypha/static_src/src/sass/apply/components/_simplified.scss b/hypha/static_src/src/sass/apply/components/_simplified.scss
index d68bc7418..76161b522 100644
--- a/hypha/static_src/src/sass/apply/components/_simplified.scss
+++ b/hypha/static_src/src/sass/apply/components/_simplified.scss
@@ -154,7 +154,12 @@
     }
 
     &__paf_answers {
+        section {
+            margin: 0 0 1.5rem;
+        }
+
         h4 {
+            margin: 0;
             font-size: 16px;
         }
     }
diff --git a/hypha/templates/includes/sprites.html b/hypha/templates/includes/sprites.html
index 159e4efee..108705131 100644
--- a/hypha/templates/includes/sprites.html
+++ b/hypha/templates/includes/sprites.html
@@ -254,6 +254,11 @@
         <path d="M1 8L8 2L15 8" stroke-width="2"/>
     </svg>
 
+    <symbol id="side-arrow" viewBox="0 0 8 12" fill="none" >
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 6L0 0L0 12L8 6Z" fill="#0D7DB0"/>
+    </symbol>
+
+
 
 
     <symbol id="wifi" viewBox="0 0 69 42">
-- 
GitLab