add automatically generation of wiref pdf
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ngettext
|
from django.utils.translation import ngettext
|
||||||
@@ -12,6 +13,7 @@ from .forms import (
|
|||||||
WirefAdminForm,
|
WirefAdminForm,
|
||||||
)
|
)
|
||||||
from .models import BankData, Bill, Resolution, Wiref
|
from .models import BankData, Bill, Resolution, Wiref
|
||||||
|
from .utils import generate_pdf
|
||||||
|
|
||||||
|
|
||||||
class BillInline(admin.TabularInline):
|
class BillInline(admin.TabularInline):
|
||||||
@@ -76,7 +78,12 @@ class BillAdmin(admin.ModelAdmin):
|
|||||||
ordering = ["-id"]
|
ordering = ["-id"]
|
||||||
search_fields = ["purpose"]
|
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 = (
|
fieldsets = (
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
@@ -351,6 +358,7 @@ class WirefAdmin(admin.ModelAdmin):
|
|||||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||||
extra_context = extra_context or {}
|
extra_context = extra_context or {}
|
||||||
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
|
||||||
|
extra_context["generate_pdf"] = True
|
||||||
return super().change_view(
|
return super().change_view(
|
||||||
request,
|
request,
|
||||||
object_id,
|
object_id,
|
||||||
@@ -358,6 +366,31 @@ class WirefAdmin(admin.ModelAdmin):
|
|||||||
extra_context=extra_context,
|
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)")
|
@admin.display(description="Gesamtsumme (EUR)")
|
||||||
def total(self, obj):
|
def total(self, obj):
|
||||||
total = 0
|
total = 0
|
||||||
|
|||||||
BIN
fet2020/finance/static/Vorlage.pdf
Normal file
BIN
fet2020/finance/static/Vorlage.pdf
Normal file
Binary file not shown.
94
fet2020/finance/utils.py
Normal file
94
fet2020/finance/utils.py
Normal file
@@ -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
|
||||||
@@ -6,5 +6,6 @@
|
|||||||
{% url opts|admin_urlname:'changelist' as changelist_url %}
|
{% url opts|admin_urlname:'changelist' as changelist_url %}
|
||||||
<a href="{% add_preserved_filters changelist_url %}" class="closelink">{% translate 'Close' %}</a>
|
<a href="{% add_preserved_filters changelist_url %}" class="closelink">{% translate 'Close' %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if generate_pdf %}<input type="submit" value="PDF File generieren" class="default" name="_generate_pdf">{% endif %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user