Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoice status updating improvements #4083

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hypha/apply/activity/adapters/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,4 @@ def get_users_for_groups(groups, user_queryset=None, exact_match=False):
user_queryset = user_queryset.filter(groups__name=groups.pop().name)
return get_users_for_groups(groups, user_queryset=user_queryset)
else:
return user_queryset
return user_queryset if user_queryset is not None else set()
17 changes: 12 additions & 5 deletions hypha/apply/projects/forms/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.core.files.base import ContentFile
from django.db import transaction
from django.db.models.fields.files import FieldFile
from django.forms.widgets import RadioSelect
from django.utils.translation import gettext_lazy as _
from django_file_form.forms import FileFormMixin

Expand Down Expand Up @@ -87,16 +88,22 @@ class ChangeInvoiceStatusForm(forms.ModelForm):
class Meta:
fields = ["status", "comment"]
model = Invoice
widgets = {"status": RadioSelect}

def __init__(self, instance, user, *args, **kwargs):
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
instance = kwargs.pop("instance")
super().__init__(*args, **kwargs, instance=instance)
self.initial["comment"] = ""
status_field = self.fields["status"]

status_field.choices = get_invoice_possible_transition_for_user(
invoice_choices = get_invoice_possible_transition_for_user(
user, invoice=instance
)

self.initial["comment"] = ""
if len(invoice_choices) > 4:
self.fields["status"] = forms.TypedChoiceField(choices=invoice_choices)
else:
self.fields["status"].choices = invoice_choices


class InvoiceBaseForm(forms.ModelForm):
class Meta:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,56 +22,8 @@
<th class="data-block__table-update"></th>
</tr>
</thead>
<tbody>
{% for invoice in object.invoices.not_rejected %}
{% display_invoice_status_for_user user invoice as invoice_status %}
<tr>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Date submitted" %}: </span>{{ invoice.requested_at.date }}</td>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Invoice number" %}: </span>{{ invoice.invoice_number }}</td>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Status" %}: </span>{{ invoice_status }}</td>
<td class="flex flex-wrap justify-center py-4 px-0 gap-2 xl:flex-nowrap">
<a class="data-block__action-icon-link" href="{{ invoice.get_absolute_url }}" >
{% heroicon_micro "eye" aria_hidden=true class="me-1" %}
{% trans "View" %}
</a>
{% can_edit invoice user as user_can_edit_request %}
{% if user_can_edit_request %}
<a class="data-block__action-icon-link" href="{% url "apply:projects:invoice-edit" pk=invoice.project.pk invoice_pk=invoice.pk %}">
{% heroicon_micro "pencil-square" aria_hidden=true class="me-1" %}
{% trans "Edit" %}
</a>
{% endif %}

{% can_delete invoice user as user_can_delete_request %}
{% if user.is_applicant and user_can_delete_request %}
<a class="data-block__action-icon-link text-red-500" href="{% url 'apply:projects:invoice-delete' pk=invoice.project.pk invoice_pk=invoice.pk %}">
{% heroicon_micro "trash" aria_hidden=true class="me-1" %}
{% trans "Delete" %}
</a>
{% endif %}
{% can_change_status invoice user as can_change_invoice_status %}
{% if can_change_invoice_status %}
<a
data-fancybox
data-src="#change-invoice-status-{{ invoice.id }}"
id="update_invoice_status-{{ invoice.id }}"
class="data-block__button button button--primary"
href="#"
>
{% trans "Update Status" %}
</a>
<div class="modal" id="change-invoice-status-{{ invoice.id }}">
{% get_invoice_form invoice user as invoice_form %}
{% get_invoice_form_id invoice_form invoice as invoice_form_id %}
<h4 class="modal__project-header-bar">{% trans "Update Invoice status" %}</h4>
<p>{% trans "Current status" %}: {{ invoice_status }}</p>
{% trans "Update Status" as update %}
{% include 'funds/includes/delegated_form_base.html' with form=invoice_form value=update action=invoice.get_absolute_url form_id=invoice_form_id %}
</div>
{% endif %}
</td>
</tr>
{% endfor %}
<tbody hx-get="{% url 'apply:projects:partial-invoices-status' pk=object.pk %}" hx-trigger="invoicesUpdated from:body">
{% include "application_projects/partials/invoice_status_table.html" with invoices=object.invoices.not_rejected rejected=False %}
</tbody>
</table>
{% else %}
Expand All @@ -87,26 +39,13 @@ <h4 class="modal__project-header-bar">{% trans "Update Invoice status" %}</h4>
<thead>
<tr>
<th class="data-block__table-date">{% trans "Date submitted" %}</th>
<th class="data-block__table-amount">{% trans "Invoice number" %}</th>
<th class="data-block__table-amount">{% trans "Invoice No." %}</th>
<th class="data-block__table-status">{% trans "Status" %}</th>
<th class="data-block__table-update"></th>
</tr>
</thead>
<tbody>
{% for invoice in object.invoices.rejected %}
{% display_invoice_status_for_user user invoice as invoice_status %}
<tr>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Date submitted" %}: </span>{{ invoice.requested_at.date }}</td>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Invoice number" %}: </span>{{ invoice.invoice_number }}</td>
<td class="py-4 px-2.5"><span class="data-block__mobile-label">{% trans "Status" %}: </span>{{ invoice_status }}</td>
<td class="flex justify-end py-4 px-0">
<a class="data-block__action-icon-link" href="{{ invoice.get_absolute_url }}" >
{% heroicon_mini "eye" size=16 aria_hidden=true class="me-1" %}
{% trans "View" %}
</a>
</td>
</tr>
{% endfor %}
<tbody id="rejected-invoice-table" hx-get="{% url 'apply:projects:partial-rejected-invoices-status' pk=object.pk %}" hx-trigger="rejectedInvoicesUpdated from:body">
{% include "application_projects/partials/invoice_status_table.html" with invoices=object.invoices.rejected rejected=True %}
</tbody>
</table>
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% load i18n %}

{% modal_title %}Update Invoice Status{% endmodal_title %}

<form class="p-4"
method="POST"
action="{{ request.path }}"
hx-post="{{ request.path }}"
>
<p class="mt-0 text-fg-muted">{% trans "Current status" %}: {{ invoice_status }}</p>

{% include 'funds/includes/dialog_form_base.html' with form=form value=value form_id=form_id %}
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,7 @@
{% endif %}
{% endblock %}

{% block actions %}
{{ block.super }}
{% can_change_status object user as user_can_change_status %}
<a
{% if user_can_change_status %}
data-fancybox
data-src="#change-status"
{% endif %}
id="update_invoice_status"
class="button button--bottom-space button--primary button--full-width{% if not user_can_change_status %} button--tooltip-disabled{% endif %}"
href="#"
>
{% trans "Update Invoice Status" %}
</a>
{% if user_can_change_status %}
<div class="modal" id="change-status">
<h4 class="modal__project-header-bar">{% trans "Update Invoice status" %}</h4>
<p>{% trans "Current status" %}: {{ object.status_display }}</p>
{% trans "Update Status" as update %}
{% include 'funds/includes/delegated_form_base.html' with form=change_invoice_status value=update %}
</div>
{% endif %}
{% endblock %}

{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/fancybox.css' %}">
{% endblock %}

{% block extra_js %}
{{ block.super }}
<script src="{% static 'js/jquery.fancybox.min.js' %}"></script>
<script src="{% static 'js/fancybox-global.js' %}"></script>
<script src="{% static 'js/deliverables.js' %}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -28,47 +28,9 @@
{% endif %}
<p class="card__text"><b>{% trans "Fund" %}:</b> {{ object.project.submission.page }}</p>
</div>
<div class="flex card card--solid" x-data="{ collapsed: true }">
<div class="flex-none">
<p><b>{% trans "Status" %}: </b></p>
</div>
<div class="ps-2">
{% extract_status latest_activity user as latest_activity_status %}
{% 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">{% trans "View comment" %}</a>
{% endif %}
</p>
{% for activity in activities %}
{% extract_status activity user as activity_status %}
{% 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">{% trans "View comment" %}</a>
{% endif %}
</p>
{% endfor %}
</div>
<button
type="button"
class="flex-1 font-bold transition-opacity text-light-blue text-end hover:opacity-70"
x-on:click="collapsed = ! collapsed"
>
<span x-show="collapsed">
{% trans "Show" %}
{% heroicon_mini "arrow-down" class="inline align-text-bottom" aria_hidden=true %}
</span>
<span x-show="!collapsed">
{% trans "Hide" %}
{% heroicon_mini "arrow-up" class="inline align-text-bottom" aria_hidden=true %}
</span>

</button>
<div hx-get="{% url 'apply:projects:partial-invoice-status' pk=object.project.pk invoice_pk=object.pk %}" hx-trigger="load, invoicesUpdated from:body" class="flex card card--solid" x-data="{ collapsed: true }">
<div class="flex-none content-center min-h-10"><div class="h-4 min-w-96 bg-gray-400 rounded-full animate-pulse"></div></div>
<div class="ps-2"></div>
</div>

<div class="card card--solid">
Expand All @@ -90,34 +52,8 @@ <h5 class="card__heading">{% trans "Supporting Documents" %}</h5>
<aside class="sidebar">
{% block deliverables %}
{% endblock %}
<div class="sticky js-actions-sidebar sidebar__inner sidebar__inner--light-blue sidebar__inner--actions top-8" data-testid="sidebar-primary-actions">
<h5>{% trans "Actions to take" %}</h5>
{% block actions %}
{% can_edit object user as user_can_edit_request %}
{% if user.is_apply_staff or user.is_applicant %}
<a
{% if not user_can_edit_request %}
data-tooltip="{% trans "Only editable when 'Submitted' or you have been requested to make changes" %}"
{% endif %}
class="button button--bottom-space button--primary button--full-width{% if not user_can_edit_request %} button--tooltip-disabled{% endif %}"
href={% if user_can_edit_request %}
"{% url "apply:projects:invoice-edit" pk=object.project.pk invoice_pk=object.pk %}"
{% else %}
"#"
{% endif %}
>
{% trans "Edit Invoice" %}
</a>
{% endif %}
{% can_delete object user as user_can_delete_request %}
{% if user_can_delete_request %}
<a
class="button button--bottom-space button--primary button--full-width"
href="{% url 'apply:projects:invoice-delete' pk=object.project.pk invoice_pk=object.pk %}">
{% trans "Delete Invoice" %}
</a>
{% endif %}
{% endblock %}
<div hx-get="{% url 'apply:projects:partial-invoice-detail-actions' pk=object.project.pk invoice_pk=object.pk %}" hx-trigger="invoicesUpdated from:body" class="sticky js-actions-sidebar sidebar__inner sidebar__inner--light-blue sidebar__inner--actions top-8" data-testid="sidebar-primary-actions">
{% include "application_projects/partials/invoice_detail_actions.html" %}
</div>
</aside>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{% load i18n invoice_tools %}

<h5>{% trans "Actions to take" %}</h5>
{% can_edit object user as user_can_edit_request %}
{% if user.is_apply_staff or user.is_applicant %}
<a
{% if not user_can_edit_request %}
data-tooltip="{% trans "Only editable when 'Submitted' or you have been requested to make changes" %}"
{% endif %}
class="button button--bottom-space button--primary button--full-width{% if not user_can_edit_request %} button--tooltip-disabled{% endif %}"
href={% if user_can_edit_request %}
"{% url "apply:projects:invoice-edit" pk=object.project.pk invoice_pk=object.pk %}"
{% else %}
"#"
{% endif %}
>
{% trans "Edit Invoice" %}
</a>
{% endif %}
{% can_delete object user as user_can_delete_request %}
{% if user_can_delete_request %}
<a
class="button button--bottom-space button--primary button--full-width"
href="{% url 'apply:projects:invoice-delete' pk=object.project.pk invoice_pk=object.pk %}">
{% trans "Delete Invoice" %}
</a>
{% endif %}

{% if user.is_org_faculty %}
{% can_change_status object user as user_can_change_status %}
{% if user_can_change_status %}
<button class="button button--bottom-space button--primary button--full-width" hx-get="{% url 'apply:projects:invoice-update' pk=object.project.pk invoice_pk=object.pk %}" hx-target="#htmx-modal">
{% trans "Update Status" %}
</button>
<div class="modal" id="change-status">
<h4 class="modal__project-header-bar">{% trans "Update Invoice status" %}</h4>
<p>{% trans "Current status" %}: {{ object.status_display }}</p>
{% trans "Update Status" as update %}
{% include 'funds/includes/delegated_form_base.html' with form=change_invoice_status value=update %}
</div>
{% else %}
<button class="button button--bottom-space button--primary button--full-width" disabled>
{% trans "Update Status" %}
</button>
{% endif %}
{% endif %}
Loading
Loading