diff --git a/hypha/apply/projects/templates/application_projects/includes/invoices.html b/hypha/apply/projects/templates/application_projects/includes/invoices.html index 13022b741d..57eb54d0af 100644 --- a/hypha/apply/projects/templates/application_projects/includes/invoices.html +++ b/hypha/apply/projects/templates/application_projects/includes/invoices.html @@ -22,53 +22,32 @@ - - {% for invoice in object.invoices.not_rejected %} - {% invoice_htmx_triggers invoice as htmx_trig %} - - {% trans "Date submitted" %}: - {% trans "Invoice number" %}: - {% trans "Status" %}: - - - {% endfor %} - - - {% else %} -

{% trans "No active invoices yet." %}

- {% endif %} + + {% include "application_projects/partials/invoice_status.html" with invoices=object.invoices.not_rejected rejected=False %} + + + {% else %} +

{% trans "No active invoices yet." %}

+ {% endif %} - {% if object.invoices.rejected %} -

- {% trans "Show rejected" %} -

+ {% if object.invoices.rejected %} +

+ {% trans "Show rejected" %} +

- - - - - - - - - - - {% for invoice in object.invoices.rejected %} - {% display_invoice_status_for_user user invoice as invoice_status %} - - - - - - - {% endfor %} - - - {% endif %} - - + + + + + + + + + + + {% include "application_projects/partials/invoice_status.html" with invoices=object.invoices.rejected rejected=True %} + + + {% endif %} + + diff --git a/hypha/apply/projects/templates/application_projects/partials/invoice_status.html b/hypha/apply/projects/templates/application_projects/partials/invoice_status.html index 1cce3b714a..69feec1ee2 100644 --- a/hypha/apply/projects/templates/application_projects/partials/invoice_status.html +++ b/hypha/apply/projects/templates/application_projects/partials/invoice_status.html @@ -1,33 +1,39 @@ {% load i18n invoice_tools heroicons %} -{% display_invoice_status_for_user user invoice as invoice_status %} -{% trans "Date submitted" %}: {{ invoice.requested_at.date }} -{% trans "Invoice number" %}: {{ invoice.invoice_number }} -{% trans "Status" %}: {{ invoice_status }} - - - {% heroicon_micro "eye" aria_hidden=true class="me-1" %} - {% trans "View" %} - - {% can_edit invoice user as user_can_edit_request %} - {% if user_can_edit_request %} - - {% heroicon_micro "pencil-square" aria_hidden=true class="me-1" %} - {% trans "Edit" %} - - {% endif %} +{% for invoice in invoices %} + + {% display_invoice_status_for_user user invoice as invoice_status %} + {% trans "Date submitted" %}: {{ invoice.requested_at.date }} + {% trans "Invoice number" %}: {{ invoice.invoice_number }} + {% trans "Status" %}: {{ invoice_status }} + + + {% heroicon_micro "eye" aria_hidden=true class="me-1" %} + {% trans "View" %} + + {% if not rejected %} + {% can_edit invoice user as user_can_edit_request %} + {% if user_can_edit_request %} + + {% heroicon_micro "pencil-square" aria_hidden=true class="me-1" %} + {% trans "Edit" %} + + {% endif %} - {% can_delete invoice user as user_can_delete_request %} - {% if user.is_applicant and user_can_delete_request %} - - {% heroicon_micro "trash" aria_hidden=true class="me-1" %} - {% trans "Delete" %} - - {% endif %} - {% can_change_status invoice user as can_change_invoice_status %} - {% if can_change_invoice_status %} - - {% endif %} - \ No newline at end of file + {% can_delete invoice user as user_can_delete_request %} + {% if user.is_applicant and user_can_delete_request %} + + {% heroicon_micro "trash" aria_hidden=true class="me-1" %} + {% trans "Delete" %} + + {% endif %} + {% can_change_status invoice user as can_change_invoice_status %} + {% if can_change_invoice_status %} + + {% endif %} + {% endif %} + + +{% endfor %} \ No newline at end of file diff --git a/hypha/apply/projects/urls.py b/hypha/apply/projects/urls.py index fbb9c68543..9001905616 100644 --- a/hypha/apply/projects/urls.py +++ b/hypha/apply/projects/urls.py @@ -104,6 +104,18 @@ VendorPrivateMediaView.as_view(), name="vendor-documents", ), + path( + "partial/invoice-status/", + partial_get_invoice_status, + {"rejected": False}, + name="partial-invoice-status", + ), + path( + "partial/rejected-invoice-status/", + partial_get_invoice_status, + {"rejected": True}, + name="partial-rejected-invoice-status", + ), path( "invoices//", include( @@ -132,11 +144,6 @@ InvoicePrivateMedia.as_view(), name="invoice-supporting-document", ), - path( - "partial/invoice-status/", - partial_get_invoice_status, - name="partial-invoice-status", - ), ] ), ), diff --git a/hypha/apply/projects/views/payment.py b/hypha/apply/projects/views/payment.py index 67c7b9c90c..9d235e6fd1 100644 --- a/hypha/apply/projects/views/payment.py +++ b/hypha/apply/projects/views/payment.py @@ -63,6 +63,7 @@ APPROVED_BY_STAFF, CHANGES_REQUESTED_BY_FINANCE, CHANGES_REQUESTED_BY_STAFF, + DECLINED, INVOICE_TRANISTION_TO_RESUBMITTED, Invoice, ) @@ -100,29 +101,26 @@ class ChangeInvoiceStatusView(DelegatedViewMixin, InvoiceAccessMixin, UpdateView template = "application_projects/includes/update_invoice_form.html" def dispatch(self, request, *args, **kwargs): - self.object = get_object_or_404(Invoice, id=kwargs.get("invoice_pk")) + self.object: Invoice = get_object_or_404(Invoice, id=kwargs.get("invoice_pk")) return super().dispatch(request, *args, **kwargs) - def get(self, *args, **kwargs): - form_instance = self.form_class(instance=self.object, user=self.request.user) - form_instance.name = self.context_name + def get_context_data(self, **kwargs): + if not (form := kwargs.get("form")): + form = self.form_class(instance=self.object, user=self.request.user) - return render( - self.request, - self.template, - context={ - "form": form_instance, - "form_id": f"{form_instance.name}-{self.object.id}", - "invoice_status": display_invoice_status_for_user( - self.request.user, self.object - ), - "value": _("Update status"), - "object": self.object, - }, - ) + form.name = self.context_name - def get_context_data(self, **kwargs): - return super().get_context_data(**kwargs) + extras = { + "form": form, + "form_id": f"{form.name}-{self.object.id}", + "invoice_status": display_invoice_status_for_user( + self.request.user, self.object + ), + "value": _("Update status"), + "object": self.object, + } + + return {**kwargs, **extras} def form_valid(self, form): old_status = self.object.status @@ -131,7 +129,7 @@ def form_valid(self, form): invoice_status_change = _( "

Invoice status updated to: {status}.

" ).format(status=self.object.get_status_display()) - comment = f"

{self.object.comment}.

" + comment = f"

{self.object.comment}

" message = invoice_status_change + comment @@ -173,37 +171,29 @@ def form_valid(self, form): return response + def get(self, *args, **kwargs): + form_instance = self.form_class(instance=self.object, user=self.request.user) + form_instance.name = self.context_name + + return render(self.request, self.template, self.get_context_data()) + def post(self, *args, **kwargs): - form = ChangeInvoiceStatusForm( + form = self.form_class( self.request.POST, instance=self.object, user=self.request.user ) if form.is_valid(): self.form_valid(form) + htmx_headers = {"invoicesUpdated": None, "showMessage": "Invoice updated."} + if self.object.status == DECLINED: + htmx_headers.update({"rejectedInvoicesUpdated": None}) return HttpResponse( - status=204, - headers={ - "HX-Trigger": json.dumps( - { - f"invoiceUpdated-{self.object.id}": None, - "showMessage": "Invoice updated.", - } - ) - }, + status=204, headers={"HX-Trigger": json.dumps(htmx_headers)} ) - # TODO: get_context_data method to not duplicate code return render( self.request, self.template, - context={ - "form": form, - "form_id": f"{form.name}-{self.object.id}", - "invoice_status": display_invoice_status_for_user( - self.request.user, self.object - ), - "value": _("Update status"), - "object": self.object, - }, + self.get_context_data(form=form), status=400, ) diff --git a/hypha/apply/projects/views/project_partials.py b/hypha/apply/projects/views/project_partials.py index 517425e478..00a34bb62b 100644 --- a/hypha/apply/projects/views/project_partials.py +++ b/hypha/apply/projects/views/project_partials.py @@ -107,10 +107,15 @@ def get_invoices_status_counts(request): @login_required -def partial_get_invoice_status(request, pk, invoice_pk): - invoice = get_object_or_404(Invoice, pk=invoice_pk) +def partial_get_invoice_status(request, pk: int, rejected: bool): + invoices = get_object_or_404(Project, pk=pk).invoices + return render( request, "application_projects/partials/invoice_status.html", - context={"invoice": invoice, "user": request.user}, + context={ + "invoices": invoices.rejected if rejected else invoices.not_rejected, + "user": request.user, + "rejected": rejected, + }, )