diff --git a/fet2020/finance/admin.py b/fet2020/finance/admin.py index d64b6052..425be9d2 100644 --- a/fet2020/finance/admin.py +++ b/fet2020/finance/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin, messages +from django.http import HttpResponseRedirect from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import ngettext @@ -12,6 +13,7 @@ from .forms import ( WirefAdminForm, ) from .models import BankData, Bill, Resolution, Wiref +from .utils import generate_pdf class BillInline(admin.TabularInline): @@ -76,7 +78,12 @@ class BillAdmin(admin.ModelAdmin): ordering = ["-id"] search_fields = ["purpose"] - readonly_fields = ["get_bankdata_name", "get_bankdata_iban", "get_bankdata_bic", "get_qrcode"] + readonly_fields = [ + "get_bankdata_name", + "get_bankdata_iban", + "get_bankdata_bic", + "get_qrcode", + ] fieldsets = ( ( None, @@ -351,6 +358,7 @@ class WirefAdmin(admin.ModelAdmin): def change_view(self, request, object_id, form_url="", extra_context=None): extra_context = extra_context or {} extra_context["help_text"] = "Fette Schriften sind Pflichtfelder." + extra_context["generate_pdf"] = True return super().change_view( request, object_id, @@ -358,6 +366,31 @@ class WirefAdmin(admin.ModelAdmin): extra_context=extra_context, ) + def response_change(self, request, obj): + if "_generate_pdf" in request.POST: + if generate_pdf(obj) is True: + self.message_user( + request, + "Neues Wiref Formular wurde generiert.", + messages.SUCCESS, + ) + else: + self.message_user( + request, + "Das PDF File wurde nicht generiert, weil der Status nicht offen ist.", + messages.WARNING, + ) + return HttpResponseRedirect(".") + return super().response_change(request, obj) + + def save_model(self, request, obj, form, change): + # set status to submitted, if a file exists and status is opened. + get_status_open = obj.status == Wiref.Status.OPENED + get_exist_file = obj.file_field != "" + if get_exist_file and get_status_open and "_generate_pdf" not in request.POST: + obj.status = Wiref.Status.SUBMITTED + super().save_model(request, obj, form, change) + @admin.display(description="Gesamtsumme (EUR)") def total(self, obj): total = 0 diff --git a/fet2020/finance/static/Vorlage.pdf b/fet2020/finance/static/Vorlage.pdf new file mode 100644 index 00000000..0a61b2c3 Binary files /dev/null and b/fet2020/finance/static/Vorlage.pdf differ diff --git a/fet2020/finance/utils.py b/fet2020/finance/utils.py new file mode 100644 index 00000000..7975aae5 --- /dev/null +++ b/fet2020/finance/utils.py @@ -0,0 +1,94 @@ +import datetime +import io +import os + +import fitz +from django.core.files import File + +from .models import Bill, Wiref + + +def generate_pdf(wiref): + if wiref is not None and wiref.status == Wiref.Status.OPENED: + bills = Bill.objects.filter(wiref=wiref).order_by("date") + + data = {} + for count, elem in enumerate(bills): + data.update( + { + f"Datum.{count}": str(elem.date.strftime("%d.%m.%Y")), + f"Aussteller.{count}": elem.invoice, + f"Verwendungszweck.{count}": elem.purpose, + # replace decimal separator from '.' to ',' + f"Betrag.{count}": str(elem.amount).replace(".", ","), + } + ) + + # get budget year + today = datetime.date.today() + if today.month < 7: + budget_year = f"{today.year - 1}-{today.year}" + else: + budget_year = f"{today.year}-{today.year + 1}" + + # get total of all bills of wiref form + total = 0 + for elem in bills: + total += elem.amount + + data.update( + { + "Laufende Nummer": str(wiref.wiref_id), + "Budgetjahr": budget_year, + # replace decimal separator from '.' to ',' + "Summe": str(total).replace(".", ","), + } + ) + + pdf_path = os.path.join(os.path.dirname(__file__), "static/Vorlage.pdf") + with fitz.open(pdf_path) as doc: + for page in doc: + widgets = page.widgets() + for widget in widgets: + if widget.field_name in data: + # removing '\r' is important for textbox in pdf file + widget.field_value = data[widget.field_name].replace("\r", "") + fontsize = widget.text_fontsize + + # update font size if there are more than one newlines in string + count = widget.field_value.count("\n") + 1 + if count > 1: + fontsize = 0.7 * widget.rect.height / count + + if ( + widget.text_fontsize == 0 + or fontsize < widget.text_fontsize + ): + widget.text_fontsize = fontsize + + # get max length of one line of multi-line text + max_len = 0 + for elem in widget.field_value.split("\n"): + length = fitz.get_text_length(elem) + if length > max_len: + max_len = length + + # update fontsize if length of text is longer than rectangle width + if max_len > widget.rect.width: + fontsize = widget.rect.width / max_len * 10 + + if ( + widget.text_fontsize == 0 + or fontsize < widget.text_fontsize + ): + widget.text_fontsize = fontsize + + widget.update() + + dist = doc.tobytes() + wiref_name = f"{wiref.wiref_id}.pdf" + wiref.file_field.save(wiref_name, File(io.BytesIO(dist), wiref_name)) + + return True + + return False diff --git a/fet2020/templates/admin/submit_line.html b/fet2020/templates/admin/submit_line.html index b697100e..1549624f 100644 --- a/fet2020/templates/admin/submit_line.html +++ b/fet2020/templates/admin/submit_line.html @@ -6,5 +6,6 @@ {% url opts|admin_urlname:'changelist' as changelist_url %} {% translate 'Close' %} {% endif %} + {% if generate_pdf %}{% endif %} {{ block.super }} {% endblock %}