added form to select correct invoice for sjr application

pull/103/head
mariusrklein 12 months ago
parent c2bfd85eb4
commit 307944bbb7

@ -871,6 +871,15 @@ class GenerateSeminarReportForm(forms.Form):
widget=CheckboxInput(attrs={'style': 'display: inherit'}),
required=False)
class GenerateSjrForm(forms.Form):
def __init__(self, *args, **kwargs):
self.attachments = kwargs.pop('attachments')
super(GenerateSjrForm,self).__init__(*args,**kwargs)
self.fields['invoice'] = forms.ChoiceField(choices=self.attachments, label=_('Invoice'))
class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin):
#inlines = [MemberOnListInline, LJPOnListInline, StatementOnListInline]
@ -966,17 +975,41 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin):
return serve_pdf(fp)
return self.render_seminar_report_options(request, memberlist, GenerateSeminarReportForm())
seminar_report.short_description = _('Generate seminar report')
def render_sjr_options(self, request, memberlist, form):
context = dict(self.admin_site.each_context(request),
title=_('Generate SJR application'),
opts=self.opts,
memberlist=memberlist,
form=form,
object=memberlist)
return render(request, 'admin/generate_sjr_application.html', context=context)
def sjr_application(self, request, memberlist):
if not self.may_view_excursion(request, memberlist):
return self.not_allowed_view(request, memberlist)
context = memberlist.sjr_application_fields()
if hasattr(memberlist, 'statement'):
attachments = [b.proof.path for b in memberlist.statement.bill_set.all() if b.proof]
attachment_names = [f"{b.short_description}: {b.explanation} ({b.amount:.2f}€)" for b in memberlist.statement.bill_set.all() if b.proof]
attachment_paths = [b.proof.path for b in memberlist.statement.bill_set.all() if b.proof]
else:
attachments = []
title = memberlist.ljpproposal.title if hasattr(memberlist, 'ljpproposal') else memberlist.name
return fill_pdf_form(title + "_SJR_Antrag", 'members/sjr_template.pdf', context, attachments)
attachment_names = []
attachment_paths = []
attachments = zip(attachment_paths, attachment_names)
if not self.may_view_excursion(request, memberlist):
return self.not_allowed_view(request, memberlist)
if "apply" in request.POST:
form = GenerateSjrForm(request.POST, attachments=attachments)
if not form.is_valid():
messages.error(request, _('Please select an invoice.'))
return self.render_sjr_options(request, memberlist, form)
selected_attachments = [form.cleaned_data['invoice']]
context = memberlist.sjr_application_fields()
title = memberlist.ljpproposal.title if hasattr(memberlist, 'ljpproposal') else memberlist.name
return fill_pdf_form(title + "_SJR_Antrag", 'members/sjr_template.pdf', context, selected_attachments)
return self.render_sjr_options(request, memberlist, GenerateSjrForm(attachments=attachments))
sjr_application.short_description = _('Generate SJR application')
def finance_overview(self, request, memberlist):

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-19 01:21+0100\n"
"POT-Creation-Date: 2024-12-31 18:13+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -34,174 +34,174 @@ msgstr "Nein"
msgid "All"
msgstr "Alle"
#: members/admin.py:185 members/admin.py:415
#: members/admin.py:185 members/admin.py:414
msgid "Contact information"
msgstr "Kontaktinformationen"
#: members/admin.py:190 members/admin.py:420
#: members/admin.py:190 members/admin.py:419
msgid "Skills"
msgstr "Fähigkeiten"
#: members/admin.py:195 members/admin.py:425
#: members/admin.py:195 members/admin.py:424
msgid "Others"
msgstr "Sonstiges"
#: members/admin.py:201 members/admin.py:430
#: members/admin.py:201 members/admin.py:429
msgid "Organizational"
msgstr "Organisatorisches"
#: members/admin.py:283
#: members/admin.py:282
msgid "Compose new mail to selected members"
msgstr "Neue Nachricht an ausgewählte Teilnehmer*innen verfassen"
#: members/admin.py:289
#: members/admin.py:288
msgid "Echo required"
msgstr "Rückmeldung erforderlich"
#: members/admin.py:291
#: members/admin.py:290
msgid "Successfully requested echo from selected members."
msgstr ""
"Rückmeldungsaufforderung erfolgreich an ausgewählte Teilnehmer*innen "
"verschickt."
#: members/admin.py:292
#: members/admin.py:291
msgid "Request echo from selected members"
msgstr "Rückmeldungsaufforderung an ausgewählte Teilnehmer*innen verschicken"
#: members/admin.py:301
#: members/admin.py:300
#, python-format
msgid "%(name)s does not have a DAV360 email address or is already registered."
msgstr "%(name)s hat keine DAV360 E-Mail Adresse oder ist bereits registriert."
#: members/admin.py:303
#: members/admin.py:302
#, python-format
msgid "Successfully invited %(name)s as user."
msgstr "Erfolgreich %(name)s aufgefordert Zugangsdaten zu wählen."
#: members/admin.py:305
#: members/admin.py:304
msgid "Successfully invited selected members to join as users."
msgstr ""
"Erfolgreich ausgewählte Teilnehmer*innen aufgefordert Zugangsdaten zu wählen."
#: members/admin.py:307
#: members/admin.py:306
msgid "Some members have been invited, others could not be invited."
msgstr ""
"Manche Teilnehmer*innen wurden eingeladen, andere konnten nicht eingeladen "
"werden."
#: members/admin.py:314 members/admin.py:331
#: members/admin.py:313 members/admin.py:330
msgid "Permission denied."
msgstr "Fehlende Berechtigungen."
#: members/admin.py:321 members/admin.py:355
#: members/admin.py:320 members/admin.py:354
#: members/templates/admin/invite_as_user.html:21
msgid "Invite as user"
msgstr "Kompass Zugangsdaten wählen lassen"
#: members/admin.py:326
#: members/admin.py:325
msgid "Invite selected members to join Kompass as users."
msgstr "Ausgewählte Teilnehmer*innen Kompass Zugangsdaten wählen lassen."
#: members/admin.py:337
#: members/admin.py:336
msgid "Member not found."
msgstr "Teilnehmer*in nicht gefunden."
#: members/admin.py:341
#: members/admin.py:340
#, python-format
msgid "%(name)s already has login data."
msgstr "%(name)s hat schon Zugangsdaten."
#: members/admin.py:346
#: members/admin.py:345
#, python-format
msgid "The configured email address for %(name)s is not an internal one."
msgstr "Die für %(name)s eingestellte E-Mail Adresse ist keine DAV360 Adresse."
#: members/admin.py:360
#: members/admin.py:359
#, python-format
msgid "%(name)s already has a pending invitation as user."
msgstr ""
"%(name)s hat bereits eine ausstehende Aufforderung Zugangsdaten zu wählen."
#: members/admin.py:378
#: members/admin.py:377
msgid "activity"
msgstr "Aktivität"
#: members/admin.py:388 members/models.py:56 members/models.py:1572
#: members/admin.py:387 members/models.py:56 members/models.py:1572
msgid "Name"
msgstr "Name"
#: members/admin.py:479
#: members/admin.py:478
msgid "Successfully requested mail confirmation from selected registrations."
msgstr "Aufforderung zur Bestätigung der Email Adresse versendet."
#: members/admin.py:480
#: members/admin.py:479
msgid "Request mail confirmation from selected registrations"
msgstr "Aufforderung zur Bestätigung der Email Adresse versenden"
#: members/admin.py:487 members/admin.py:552
#: members/admin.py:486 members/admin.py:551
#, python-format
msgid "Successfully confirmed %(name)s."
msgstr "Registrierung von %(name)s erfolgreich bestätigt."
#: members/admin.py:491 members/admin.py:555
#: members/admin.py:490 members/admin.py:554
#, python-format
msgid "Can't confirm. %(name)s has unconfirmed email addresses."
msgstr "Bestätigung nicht möglich. %(name)s hat unbestätigte Emailadressen."
#: members/admin.py:496
#: members/admin.py:495
msgid "Successfully confirmed multiple registrations."
msgstr "Erfolgreich mehrere Registrierungen bestätigt."
#: members/admin.py:498
#: members/admin.py:497
msgid ""
"Failed to confirm some registrations because of unconfirmed email addresses."
msgstr ""
"Einige Bestätigungen fehlgeschlagen, weil Emailadressen noch nicht bestätigt "
"sind."
#: members/admin.py:499
#: members/admin.py:498
msgid "Confirm selected registrations"
msgstr "Ausgewählte Registrierungen bestätigen"
#: members/admin.py:522
#: members/admin.py:521
msgid "Demote selected registrations to waiters."
msgstr "Ausgewählte Registrierungen zurück auf die Warteliste setzen."
#: members/admin.py:538
#: members/admin.py:537
msgid "Demote member to waiter"
msgstr "Ausgewählte Registrierung zurück auf die Warteliste setzen."
#: members/admin.py:547
#: members/admin.py:546
#, python-format
msgid "Successfully demoted %(name)s to waiter."
msgstr "%(name)s zurück auf die Warteliste gesetzt."
#: members/admin.py:562 members/models.py:419 members/models.py:822
#: members/admin.py:561 members/models.py:419 members/models.py:822
#: members/models.py:1317
msgid "Group"
msgstr "Gruppe"
#: members/admin.py:577
#: members/admin.py:576
msgid "Pending group invitation for group"
msgstr "Ausstehende Gruppeneinladung für Gruppe"
#: members/admin.py:610
#: members/admin.py:609
#, python-format
msgid "Successfully asked %(name)s to confirm their waiting status."
msgstr "Erfolgreich %(name)s aufgefordert den Wartelistenplatz zu bestätigen."
#: members/admin.py:611
#: members/admin.py:610
msgid "Ask selected waiters to confirm their waiting status"
msgstr "Wartende auffordern den Wartelistenplatz zu bestätigen"
#: members/admin.py:620 members/admin.py:684
#: members/admin.py:619 members/admin.py:683
msgid ""
"An error occurred while trying to invite said members. Please try again."
msgstr ""
"Beim Einladen dieser Personen ist ein Fehler aufgetreten. Bitte versuche es "
"nochmal. "
#: members/admin.py:624 members/admin.py:689
#: members/admin.py:623 members/admin.py:688
msgid ""
"The selected group does not have a contact email. Please first set a contact "
"email and then try again."
@ -209,39 +209,39 @@ msgstr ""
"Die ausgewählte Gruppe hat keine Kontakt E-Mail Adresse. Bitte stelle eine "
"Kontakt E-Mail Adresse ein und versuche es erneut."
#: members/admin.py:632 members/admin.py:696
#: members/admin.py:631 members/admin.py:695
#, python-format
msgid "Successfully invited %(name)s to %(group)s."
msgstr "Erfolgreich %(name)s zu Gruppe %(group)s eingeladen."
#: members/admin.py:636 members/admin.py:702
#: members/admin.py:635 members/admin.py:701
msgid "Select group for invitation"
msgstr "Wähle Gruppe für Einladung aus"
#: members/admin.py:643
#: members/admin.py:642
msgid "Offer waiter a place in a group."
msgstr "Personen auf der Warteliste einen Gruppenplatz anbieten."
#: members/admin.py:719 members/models.py:72
#: members/admin.py:718 members/models.py:72
msgid "name"
msgstr "Name"
#: members/admin.py:720
#: members/admin.py:719
msgid ""
"The group name may only consist of letters, numerals, _, -, :, * and spaces."
msgstr ""
"Der Gruppenname darf nur aus Buchstaben, Zahlen, _, -, :, * oder Leerzeichen "
"bestehen."
#: members/admin.py:749
#: members/admin.py:748
msgid "Difficulty"
msgstr "Schwierigkeit"
#: members/admin.py:752
#: members/admin.py:751
msgid "Tour type"
msgstr "Art der Tour"
#: members/admin.py:755 members/models.py:1048
#: members/admin.py:754 members/models.py:1048
msgid "Means of transportation"
msgstr "Verkehrsmittel"
@ -309,7 +309,11 @@ msgstr "Modus"
msgid "Prepend V32"
msgstr "V32 Formblatt einfügen"
#: members/admin.py:886
#: members/admin.py:880
msgid "Invoice"
msgstr "Beleg"
#: members/admin.py:895
msgid ""
"General information on your excursion. These are partly relevant for the "
"amount of financial compensation (means of transport, travel distance, etc.)."
@ -318,48 +322,53 @@ msgstr ""
"teilweise relevant für die Zuschüsse aus dem Jugendetat (Verkehrsmittel, "
"Fahrstrecke in km)."
#: members/admin.py:916
#: members/admin.py:925
#, python-format
msgid "You are not allowed to view all members on excursion %(name)s."
msgstr ""
"Du hast nicht die nötigen Rechte um alle Teilnehmer*innen der Ausfahrt "
"%(name)s anzusehen."
#: members/admin.py:924
#: members/admin.py:933
msgid "Generate crisis intervention list"
msgstr "Kriseninterventionsliste erstellen"
#: members/admin.py:932
#: members/admin.py:941
msgid "Generate overview"
msgstr "Hinweise für Jugendleiter erstellen"
#: members/admin.py:936 members/admin.py:968
#: members/admin.py:945 members/admin.py:977
#: members/templates/admin/generate_seminar_report.html:21
msgid "Generate seminar report"
msgstr "Landesjugendplan Antrag erstellen"
#: members/admin.py:949
#: members/admin.py:958
msgid "Please select a mode."
msgstr "Bitte wähle einen Modus aus."
#: members/admin.py:954
#: members/admin.py:963
msgid ""
"Full mode is only available, if the seminar report section is filled out."
msgstr ""
"Der vollständiger Modus ist nur verfügbar, wenn der Seminarbericht "
"ausgefüllt ist. "
#: members/admin.py:980
#: members/admin.py:981 members/admin.py:1013
#: members/templates/admin/generate_sjr_application.html:21
msgid "Generate SJR application"
msgstr "SJR Antrag erstellen"
#: members/admin.py:984
#: members/admin.py:1002
msgid "Please select an invoice."
msgstr "Bitte wähle einen Beleg aus."
#: members/admin.py:1017
msgid "No statement found. Please add a statement and then retry."
msgstr ""
"Keine Abrechnung angelegt. Bitte lege eine Abrechnung and und versuche es "
"erneut."
#: members/admin.py:988
#: members/admin.py:1021
msgid ""
"Successfully submited statement. The finance department will notify you as "
"soon as possible."
@ -367,7 +376,7 @@ msgstr ""
"Abrechnung erfolgreich eingericht. Die Finanzabteilung wird sich bei dir so "
"schnell wie möglich melden."
#: members/admin.py:991
#: members/admin.py:1024
#: members/templates/admin/freizeit_finance_overview.html:21
msgid "Finance overview"
msgstr "Kostenübersicht"
@ -972,6 +981,7 @@ msgstr "Fortbildungen"
#: members/templates/admin/demote_to_waiter.html:17
#: members/templates/admin/freizeit_finance_overview.html:17
#: members/templates/admin/generate_seminar_report.html:17
#: members/templates/admin/generate_sjr_application.html:17
#: members/templates/admin/invite_as_user.html:17
#: members/templates/admin/invite_for_group.html:17
#: members/templates/admin/invite_selected_as_user.html:17
@ -996,6 +1006,7 @@ msgstr "Zurück auf die Warteliste setzen"
#: members/templates/admin/demote_to_waiter.html:46
#: members/templates/admin/freizeit_finance_overview.html:154
#: members/templates/admin/generate_seminar_report.html:60
#: members/templates/admin/generate_sjr_application.html:48
#: members/templates/admin/invite_as_user.html:37
#: members/templates/admin/invite_for_group.html:52
#: members/templates/admin/invite_selected_as_user.html:49
@ -1233,9 +1244,28 @@ msgstr ""
"Felder im Formblatt selbst aus und unterschreibe das PDF."
#: members/templates/admin/generate_seminar_report.html:59
#: members/templates/admin/generate_sjr_application.html:47
msgid "Generate"
msgstr "Erstellen"
#: members/templates/admin/generate_sjr_application.html:27
msgid "Here you can generate an allowance application for the SJR."
msgstr "Hier kannst du einen Zuschussantrag für den SJR Heidelberg generieren."
#: members/templates/admin/generate_sjr_application.html:30
msgid ""
"The application needs to be complemented with an invoice from the trip as "
"proof."
msgstr ""
"Für den Zuschussantrag benötigst du eine Rechnung als Beleg, dass die "
"Ausfahrt stattgefunden hat. Bitte wähle hier einen Beleg aus."
#: members/templates/admin/generate_sjr_application.html:41
msgid ""
"Please send this application form to the jdav finance officer via email."
msgstr "Anschließend kannst du das Zuschussformular herunterladen. Sende es "
"bitte per E-Mail an den Finanzwart der jdav."
#: members/templates/admin/invite_as_user.html:27
#, python-format
msgid ""

@ -100,12 +100,18 @@ def fill_pdf_form(name, template_path, fields, attachments=[], save_only=False):
for fp in attachments:
try:
img = Image.open(fp)
img_pdf = BytesIO()
img.save(img_pdf, "pdf")
if fp.endswith(".pdf"):
# append pdf directly
img_pdf = PdfReader(fp)
else:
# convert ensures that png files with an alpha channel can be appended
img = Image.open(fp).convert("RGB")
img_pdf = BytesIO()
img.save(img_pdf, "pdf")
writer.append(img_pdf)
except:
except Exception as e:
print("Could not add image", fp)
print(e)
with open(media_path(filename_pdf), 'wb') as output_stream:
writer.write(output_stream)

@ -0,0 +1,52 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static %}
{% block extrahead %}
{{ block.super }}
{{ media }}
<script src="{% static 'admin/js/cancel.js' %}" async></script>
<script type="text/javascript" src="{% static "admin/js/vendor/jquery/jquery.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script>
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} invite-waiter
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
&rsaquo; {% translate 'Generate SJR application' %}
</div>
{% endblock %}
{% block content %}
<p>
{% blocktrans %}Here you can generate an allowance application for the SJR.{% endblocktrans %}
</p>
<p>
{% blocktrans %}The application needs to be complemented with an invoice from the trip as proof.{% endblocktrans %}
</p>
<form action="" method="post">
{% csrf_token %}
<p>
<table>
{{ form }}
</table>
</p>
<p>
{% blocktrans %}Please send this application form to the jdav finance officer via email.{% endblocktrans %}
</p>
<br>
<input type="hidden" name="action" value="sjr_application">
<input type="hidden" name="sjr_application">
<input class="default" style="color: $default-link-color" type="submit" name="apply"
value="{% translate 'Generate' %}">
<a href="#" class="button cancel-link">{% translate "Cancel" %}</a>
</form>
{% endblock %}
Loading…
Cancel
Save