From f59a97578c125f84d32ca3e07dd3cbc1d786daff Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Sun, 2 Feb 2025 00:54:02 +0100 Subject: [PATCH] ljp vbk generation --- jdav_web/contrib/media.py | 11 ++++ jdav_web/locale/de/LC_MESSAGES/django.po | 6 +- jdav_web/members/admin.py | 37 +++++++++++- jdav_web/members/excel.py | 49 ++++++++++++++- .../members/locale/de/LC_MESSAGES/django.po | 57 +++++++++++++++--- jdav_web/members/pdf.py | 11 +--- .../templates/admin/generate_seminar_vbk.html | 56 +++++++++++++++++ .../templates/members/LJP_VBK_3-1.xlsx | Bin 0 -> 17651 bytes .../templates/members/LJP_VBK_3-2.xlsx | Bin 0 -> 17648 bytes .../freizeit/change_form_object_tools.html | 7 +++ 10 files changed, 212 insertions(+), 22 deletions(-) create mode 100644 jdav_web/members/templates/admin/generate_seminar_vbk.html create mode 100644 jdav_web/members/templates/members/LJP_VBK_3-1.xlsx create mode 100644 jdav_web/members/templates/members/LJP_VBK_3-2.xlsx diff --git a/jdav_web/contrib/media.py b/jdav_web/contrib/media.py index 4ff27c9..d5e873b 100644 --- a/jdav_web/contrib/media.py +++ b/jdav_web/contrib/media.py @@ -1,9 +1,20 @@ import os from django.conf import settings from django.http import HttpResponse +from django import template +from django.template.loader import get_template from wsgiref.util import FileWrapper +def find_template(template_name): + for engine in template.engines.all(): + for loader in engine.engine.template_loaders: + for origin in loader.get_template_sources(template_name): + if os.path.exists(origin.name): + return origin.name + raise template.TemplateDoesNotExist(f"Could not find template: {template_name}") + + def media_path(fp): return os.path.join(os.path.join(settings.MEDIA_ROOT, "memberlists"), fp) diff --git a/jdav_web/locale/de/LC_MESSAGES/django.po b/jdav_web/locale/de/LC_MESSAGES/django.po index cafea14..4f805db 100644 --- a/jdav_web/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-01 14:54+0100\n" +"POT-Creation-Date: 2025-02-02 00:45+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -260,6 +260,10 @@ msgstr "SJR Antrag erstellen" msgid "Generate seminar report" msgstr "Landesjugendplan Antrag erstellen" +#: templates/admin/members/freizeit/change_form_object_tools.html +msgid "Generate LJP V-BK form" +msgstr "Erzeuge LJP V-BK Formular" + #: templates/admin/members/freizeit/change_form_object_tools.html msgid "Generate overview" msgstr "Hinweise für Jugendleiter*innen erstellen" diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py index 2ca8b50..548bd5f 100644 --- a/jdav_web/members/admin.py +++ b/jdav_web/members/admin.py @@ -29,7 +29,7 @@ from django.forms import Textarea, RadioSelect, TypedChoiceField, CheckboxInput from django.shortcuts import render from django.core.exceptions import PermissionDenied, ValidationError from .pdf import render_tex, fill_pdf_form, merge_pdfs, serve_pdf -from .excel import generate_group_overview +from .excel import generate_group_overview, VBK_3_1, VBK_3_2, generate_ljp_vbk from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin @@ -844,7 +844,7 @@ class GroupAdmin(CommonAdminMixin, admin.ModelAdmin): class ActivityCategoryAdmin(admin.ModelAdmin): - fields = ['name', 'description'] + fields = ['name', 'ljp_category', 'description'] class FreizeitAdminForm(forms.ModelForm): @@ -1045,6 +1045,13 @@ class GenerateSeminarReportForm(forms.Form): widget=CheckboxInput(attrs={'style': 'display: inherit'}), required=False) + +class GenerateVBKForm(forms.Form): + categories = ((VBK_3_1, _('Staff training')), + (VBK_3_2, _('Educational programme'))) + category = forms.ChoiceField(choices=categories, label=_('Category')) + + class GenerateSjrForm(forms.Form): def __init__(self, *args, **kwargs): @@ -1052,7 +1059,6 @@ class GenerateSjrForm(forms.Form): super(GenerateSjrForm,self).__init__(*args,**kwargs) self.fields['invoice'] = forms.ChoiceField(choices=self.attachments, label=_('Invoice')) - class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): @@ -1116,6 +1122,29 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): return render_tex(memberlist.name + "_Notizen", 'members/notes_list.tex', context) notes_list.short_description = _('Generate overview') + def render_seminar_vbk_options(self, request, memberlist, form): + context = dict(self.admin_site.each_context(request), + title=_('Generate LJP V-BK form'), + opts=self.opts, + memberlist=memberlist, + form=form, + object=memberlist) + return render(request, 'admin/generate_seminar_vbk.html', context=context) + + def seminar_vbk(self, request, memberlist): + if not self.may_view_excursion(request, memberlist): + return self.not_allowed_view(request, memberlist) + if "apply" in request.POST: + form = GenerateVBKForm(request.POST) + if not form.is_valid(): + messages.error(request, _('Please select a category.')) + return self.render_seminar_vbk_options(request, memberlist, form) + category = int(form.cleaned_data['category']) + title = memberlist.ljpproposal.title if hasattr(memberlist, 'ljpproposal') else memberlist.name + fp = generate_ljp_vbk(memberlist, category) + return serve_media(fp, 'application/xlsx') + return self.render_seminar_vbk_options(request, memberlist, GenerateVBKForm()) + def render_seminar_report_options(self, request, memberlist, form): context = dict(self.admin_site.each_context(request), title=_('Generate seminar report'), @@ -1233,6 +1262,8 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): def action_view(self, request, object_id): if "sjr_application" in request.POST: return self.sjr_application(request, Freizeit.objects.get(pk=object_id)) + if "seminar_vbk" in request.POST: + return self.seminar_vbk(request, Freizeit.objects.get(pk=object_id)) if "seminar_report" in request.POST: return self.seminar_report(request, Freizeit.objects.get(pk=object_id)) if "notes_list" in request.POST: diff --git a/jdav_web/members/excel.py b/jdav_web/members/excel.py index 6fa8ff7..4b9e83d 100644 --- a/jdav_web/members/excel.py +++ b/jdav_web/members/excel.py @@ -1,8 +1,9 @@ from datetime import datetime import os import xlsxwriter +import openpyxl from django.conf import settings -from contrib.media import media_path +from contrib.media import media_path, find_template from .models import WEEKDAYS def generate_group_overview(all_groups, limit_to_public = True): @@ -67,3 +68,49 @@ def generate_group_overview(all_groups, limit_to_public = True): workbook.close() return filename + + +VBK_3_1, VBK_3_2 = 1, 2 +VBK_TEMPLATES = { + VBK_3_1: 'members/LJP_VBK_3-1.xlsx', + VBK_3_2: 'members/LJP_VBK_3-2.xlsx', +} + + +def generate_ljp_vbk(excursion, mode): + """ + Generate the VBK forms for LJP given an excursion. Returns the filename to the filled excel file. + """ + print(mode, VBK_TEMPLATES, mode in VBK_TEMPLATES) + if not mode in VBK_TEMPLATES: + raise ValueError(f"Invalid mode {mode}.") + template_path = VBK_TEMPLATES[mode] + path = find_template(template_path) + workbook = openpyxl.load_workbook(path) + + sheet = workbook.active + title = excursion.ljpproposal.title if hasattr(excursion, 'ljpproposal') else excursion.name + + sheet['I6'] = settings.SEKTION_IBAN + sheet['I8'] = settings.SEKTION_ACCOUNT_HOLDER + sheet['P3'] = excursion.end.year + sheet['B4'] = f"Sektion {settings.SEKTION}" + sheet['B5'] = settings.SEKTION_STREET + sheet['B6'] = settings.SEKTION_TOWN + sheet['B7'] = settings.RESPONSIBLE_MAIL + sheet['B36'] = f"{settings.SEKTION}, {datetime.today():%d.%m.%Y}" + sheet['F19'] = f"B {excursion.date:%y}-{excursion.pk}" + sheet['D19'] = settings.SEKTION + sheet['G19'] = title + sheet['I19'] = f"von {excursion.date:%d.%m.%y} bis {excursion.end:%d.%m.%y}" + sheet['J19'] = f"{excursion.duration}" + sheet['L19'] = f"{excursion.ljp_participant_count}" + sheet['H19'] = excursion.get_ljp_activity_category() + sheet['M19'] = excursion.place + + if hasattr(excursion, 'statement'): + sheet['Q19'] = f"{excursion.statement.total_theoretic}" + + filename = f"LJP_V-BK_3.{mode}_{title}.xlsx" + workbook.save(media_path(filename)) + return filename diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po index fc719e6..cefb895 100644 --- a/jdav_web/members/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-02 00:32+0100\n" +"POT-Creation-Date: 2025-02-02 00:45+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -351,6 +351,18 @@ msgstr "Modus" msgid "Prepend V32" msgstr "V32 Formblatt einfügen" +#: members/admin.py +msgid "Staff training" +msgstr "Jugendleiter*innenweiterbildung" + +#: members/admin.py +msgid "Educational programme" +msgstr "Themenorientierte Bildungsmaßnahme" + +#: members/admin.py members/models.py +msgid "Category" +msgstr "Kategorie" + #: members/admin.py msgid "Invoice" msgstr "Beleg" @@ -379,6 +391,14 @@ msgstr "Kriseninterventionsliste erstellen" msgid "Generate overview" msgstr "Hinweise für Jugendleiter erstellen" +#: members/admin.py members/templates/admin/generate_seminar_vbk.html +msgid "Generate LJP V-BK form" +msgstr "Erzeuge LJP V-BK Formular" + +#: members/admin.py +msgid "Please select a category." +msgstr "Bitte wähle eine Kategorie aus." + #: members/admin.py members/templates/admin/generate_seminar_report.html msgid "Generate seminar report" msgstr "Landesjugendplan Antrag erstellen" @@ -491,8 +511,7 @@ msgstr "LJP Spielart" #: members/models.py msgid "" "The official category for LJP applications associated with this activity." -msgstr "" -"Die offizielle Spielart für LJP Anträge mit dieser Aktivität." +msgstr "Die offizielle Spielart für LJP Anträge mit dieser Aktivität." #: members/models.py msgid "Description" @@ -1046,10 +1065,6 @@ msgstr "Fortbildungstyp" msgid "Training categories" msgstr "Fortbildungstypen" -#: members/models.py -msgid "Category" -msgstr "Kategorien" - #: members/models.py msgid "Comments" msgstr "Kommentar" @@ -1073,6 +1088,7 @@ msgstr "Fortbildungen" #: members/templates/admin/demote_to_waiter.html #: members/templates/admin/freizeit_finance_overview.html #: members/templates/admin/generate_seminar_report.html +#: members/templates/admin/generate_seminar_vbk.html #: members/templates/admin/generate_sjr_application.html #: members/templates/admin/invite_as_user.html #: members/templates/admin/invite_for_group.html @@ -1098,6 +1114,7 @@ msgstr "Zurück auf die Warteliste setzen" #: members/templates/admin/demote_to_waiter.html #: members/templates/admin/freizeit_finance_overview.html #: members/templates/admin/generate_seminar_report.html +#: members/templates/admin/generate_seminar_vbk.html #: members/templates/admin/generate_sjr_application.html #: members/templates/admin/invite_as_user.html #: members/templates/admin/invite_for_group.html @@ -1389,10 +1406,36 @@ msgstr "" "Felder im Formblatt selbst aus und unterschreibe das PDF." #: members/templates/admin/generate_seminar_report.html +#: members/templates/admin/generate_seminar_vbk.html #: members/templates/admin/generate_sjr_application.html msgid "Generate" msgstr "Erstellen" +#: members/templates/admin/generate_seminar_vbk.html +msgid "" +"Every LJP application needs a V-BK form containing the most important facts " +"about the seminar.\n" +"Here you can automatically generate such a form in Excel format." +msgstr "" +"Jeder LJP Antrag benötigt ein V-BK Formular, das die wichtigsten Randdaten " +"des Seminars enthält. Hier kannst du automatisch ein solches Formular im " +"Excel Format erstellen." + +#: members/templates/admin/generate_seminar_vbk.html +msgid "" +"Your excursion currently has no cost-plan attached, hence the total costs " +"can't be automatically\n" +"calculated and added to the form." +msgstr "" +"Deine Ausfahrt hat zur Zeit keinen Kostenplan. Daher können die Gesamtkosten " +"nicht automatisch berechnet und dem Formular hinzugefügt werden." + +#: members/templates/admin/generate_seminar_vbk.html +msgid "" +"Depending on the type of seminar, please select one of the two options below." +msgstr "" +"Bitte wähle aus, um welche Art von Seminar es sich handelt." + #: members/templates/admin/generate_sjr_application.html members/tests.py msgid "Here you can generate an allowance application for the SJR." msgstr "Hier kannst du einen SJR-Zuschussantrag erstellen." diff --git a/jdav_web/members/pdf.py b/jdav_web/members/pdf.py index ff43d94..9ffb88a 100644 --- a/jdav_web/members/pdf.py +++ b/jdav_web/members/pdf.py @@ -11,19 +11,10 @@ from django.template.loader import get_template from django.conf import settings from django.http import HttpResponse, HttpResponseRedirect from wsgiref.util import FileWrapper -from contrib.media import media_path, media_dir, serve_media, ensure_media_dir +from contrib.media import media_path, media_dir, serve_media, ensure_media_dir, find_template from PIL import Image -def find_template(template_name): - for engine in template.engines.all(): - for loader in engine.engine.template_loaders: - for origin in loader.get_template_sources(template_name): - if os.path.exists(origin.name): - return origin.name - raise template.TemplateDoesNotExist(f"Could not find template: {template_name}") - - def serve_pdf(filename_pdf): return serve_media(filename_pdf, 'application/pdf') diff --git a/jdav_web/members/templates/admin/generate_seminar_vbk.html b/jdav_web/members/templates/admin/generate_seminar_vbk.html new file mode 100644 index 0000000..f028989 --- /dev/null +++ b/jdav_web/members/templates/admin/generate_seminar_vbk.html @@ -0,0 +1,56 @@ +{% extends "admin/base_site.html" %} +{% load i18n admin_urls static %} + +{% block extrahead %} + {{ block.super }} + {{ media }} + + + +{% endblock %} + +{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} invite-waiter +{% endblock %} + +{% block breadcrumbs %} + +{% endblock %} + +{% block content %} + +

+{% blocktrans %}Every LJP application needs a V-BK form containing the most important facts about the seminar. +Here you can automatically generate such a form in Excel format.{% endblocktrans %} +

+{% if not memberlist.statement %} +

+{% blocktrans %}Your excursion currently has no cost-plan attached, hence the total costs can't be automatically +calculated and added to the form.{% endblocktrans %} +

+{% endif %} +

+{% blocktrans %}Depending on the type of seminar, please select one of the two options below.{% endblocktrans %} +

+ +
+ {% csrf_token %} +

+ + {{ form }} +
+

+
+ + + + {% translate "Cancel" %} +
+ +{% endblock %} diff --git a/jdav_web/members/templates/members/LJP_VBK_3-1.xlsx b/jdav_web/members/templates/members/LJP_VBK_3-1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a02224a22f6f3c4de9f0de9f27b46851840656bf GIT binary patch literal 17651 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 Q+Cv8N0)({sg1@!?9|@?4wg3PC literal 0 HcmV?d00001 diff --git a/jdav_web/members/templates/members/LJP_VBK_3-2.xlsx b/jdav_web/members/templates/members/LJP_VBK_3-2.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1b21d3d986d922702d20540d68237edfc7fa789e GIT binary patch literal 17648 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 +
  • +
    + {% csrf_token %} + +
    +
  • +
  • {% csrf_token %}