From 1615f1652cd61a55b08963e8f80c3c3c963eacd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Wed, 23 Oct 2024 15:17:50 +0200 Subject: [PATCH] feat: add admin invoice download --- weblate_web/invoices/admin.py | 20 ++++++++++++++++++++ weblate_web/invoices/views.py | 21 ++++++++++++++++++++- weblate_web/urls.py | 10 ++++++++-- weblate_web/views.py | 2 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/weblate_web/invoices/admin.py b/weblate_web/invoices/admin.py index cf83ccbdc1..381a4437d9 100644 --- a/weblate_web/invoices/admin.py +++ b/weblate_web/invoices/admin.py @@ -17,10 +17,18 @@ # along with this program. If not, see . # +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from django.contrib import admin +from django.urls import reverse from .models import Discount, Invoice, InvoiceItem +if TYPE_CHECKING: + from django.http.request import HttpRequest + @admin.register(Discount) class DiscountAdmin(admin.ModelAdmin): @@ -30,6 +38,7 @@ class DiscountAdmin(admin.ModelAdmin): class InvoiceItemAdmin(admin.TabularInline): model = InvoiceItem + min_num = 1 @admin.register(Invoice) @@ -43,3 +52,14 @@ class InvoiceAdmin(admin.ModelAdmin): "number", ) inlines = (InvoiceItemAdmin,) + + def save_related( + self, request: HttpRequest, form: Any, formsets: Any, change: Any + ) -> None: + super().save_related( + request=request, form=form, formsets=formsets, change=change + ) + form.instance.generate_files() + + def view_on_site(self, obj): + return reverse("invoice-pdf", kwargs={"pk": obj.pk}) diff --git a/weblate_web/invoices/views.py b/weblate_web/invoices/views.py index 60f00ef0ef..64c146fbc4 100644 --- a/weblate_web/invoices/views.py +++ b/weblate_web/invoices/views.py @@ -1 +1,20 @@ -# Create your views here. +from django.contrib.auth.decorators import login_required, user_passes_test +from django.http import FileResponse +from django.shortcuts import get_object_or_404 + +from weblate_web.views import AuthenticatedHttpRequest + +from .models import Invoice + + +@login_required +@user_passes_test(lambda u: u.is_superuser) +def download_invoice(request: AuthenticatedHttpRequest, pk: int): + invoice = get_object_or_404(Invoice, pk=pk) + + return FileResponse( + invoice.path.open("rb"), + as_attachment=True, + filename=invoice.filename, + content_type="application/pdf", + ) diff --git a/weblate_web/urls.py b/weblate_web/urls.py index 32ec504e4a..93a1e490bd 100644 --- a/weblate_web/urls.py +++ b/weblate_web/urls.py @@ -31,6 +31,7 @@ from django.views.decorators.cache import cache_page from django.views.generic import RedirectView, TemplateView +from weblate_web.invoices.views import download_invoice from weblate_web.models import Post from weblate_web.views import ( AddDiscoveryView, @@ -54,7 +55,7 @@ api_user, disable_repeat, donate_pay, - download_invoice, + download_payment_invoice, fetch_vat, not_found, process_payment, @@ -201,7 +202,11 @@ def lastmod(self, item): r"^donate/edit/(?P[0-9]+)/$", EditLinkView.as_view(), name="donate-edit" ), re_path(r"^donate/pay/(?P[0-9]+)/$", donate_pay, name="donate-pay"), - re_path(r"^user/invoice/" + UUID + "/$", download_invoice, name="user-invoice"), + re_path( + r"^user/invoice/" + UUID + "/$", + download_payment_invoice, + name="user-invoice", + ), re_path( r"^donate/disable/(?P[0-9]+)/$", disable_repeat, name="donate-disable" ), @@ -285,6 +290,7 @@ def lastmod(self, item): CompleteView.as_view(), name="payment-complete", ), + path("invoice//pdf/", download_invoice, name="invoice-pdf"), # FOSDEM short link re_path( r"^FOSDEM/|fosdem/$", diff --git a/weblate_web/views.py b/weblate_web/views.py index 652500b7a9..8694ae23f8 100644 --- a/weblate_web/views.py +++ b/weblate_web/views.py @@ -546,7 +546,7 @@ def process_payment(request): @login_required -def download_invoice(request, pk): +def download_payment_invoice(request, pk): # Allow downloading own invoices of pending ones (for proforma invoices) payment = get_object_or_404(Payment, pk=pk)