members/freizeit: sjr applications

individual-sender-address
Christian Merten 1 year ago
parent 7d9a1bf9a6
commit f2cbac30f6
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -26,7 +26,7 @@ from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\
from django.forms import Textarea, RadioSelect, TypedChoiceField from django.forms import Textarea, RadioSelect, TypedChoiceField
from django.shortcuts import render from django.shortcuts import render
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from .pdf import render_tex from .pdf import render_tex, fill_pdf_form
from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin
@ -669,7 +669,7 @@ class FreizeitAdmin(FilteredMemberFieldMixin, CommonAdminMixin, nested_admin.Nes
list_display = ['__str__', 'date'] list_display = ['__str__', 'date']
search_fields = ('name',) search_fields = ('name',)
ordering = ('-date',) ordering = ('-date',)
actions = ['crisis_intervention_list', 'notes_list', 'seminar_report'] actions = ['crisis_intervention_list', 'notes_list', 'seminar_report', 'sjr_application']
view_on_site = False view_on_site = False
#formfield_overrides = { #formfield_overrides = {
# ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
@ -730,6 +730,17 @@ class FreizeitAdmin(FilteredMemberFieldMixin, CommonAdminMixin, nested_admin.Nes
return render_tex(title + "_Seminarbericht", 'members/seminar_report.tex', context) return render_tex(title + "_Seminarbericht", 'members/seminar_report.tex', context)
seminar_report.short_description = _('Generate seminar report') seminar_report.short_description = _('Generate seminar report')
def sjr_application(self, request, queryset):
# this ensures legacy compatibilty
memberlist = queryset[0]
if not self.may_view_excursion(request, memberlist):
return self.not_allowed_view(request, memberlist)
context = memberlist.sjr_application_fields()
attachments = [b.proof.path for b in memberlist.statement.bill_set.all()]
title = memberlist.ljpproposal.title if hasattr(memberlist, 'ljpproposal') else memberlist.name
return fill_pdf_form(title + "_SJR_Antrag", 'members/sjr_template.pdf', context, attachments)
sjr_application.short_description = _('Generate SJR application')
def get_urls(self): def get_urls(self):
urls = super().get_urls() urls = super().get_urls()
@ -750,6 +761,8 @@ class FreizeitAdmin(FilteredMemberFieldMixin, CommonAdminMixin, nested_admin.Nes
return custom_urls + urls return custom_urls + urls
def action_view(self, request, object_id): 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_report" in request.POST: if "seminar_report" in request.POST:
return self.seminar_report(request, [Freizeit.objects.get(pk=object_id)]) return self.seminar_report(request, [Freizeit.objects.get(pk=object_id)])
if "notes_list" in request.POST: if "notes_list" in request.POST:

@ -973,6 +973,41 @@ class Freizeit(CommonModel):
sks.append(dict(name=activity, skill_avg=skill_avg, skill_min=skill_min, skill_max=skill_max)) sks.append(dict(name=activity, skill_avg=skill_avg, skill_min=skill_min, skill_max=skill_max))
return (people, sks) return (people, sks)
def sjr_application_fields(self):
members = set(map(lambda x: x.member, self.membersonlist.distinct()))
total = len(members)
total_b27_local = len([m for m in members
if m.age <= 27 and settings.SEKTION in m.town])
total_b27_non_local = len([m for m in members
if m.age <= 27 and not settings.SEKTION in m.town])
jls = self.jugendleiter.distinct()
title = self.ljpproposal.title if hasattr(self, 'ljpproposal') else self.name
base = {'Haushaltsjahr': str(datetime.now().year),
'Art / Thema / Titel': title,
'Ort': self.place,
'Datum von': self.date.strftime('%d.%m.%Y'),
'Datum bis': self.end.strftime('%d.%m.%Y'),
'Dauer': str(self.duration).replace('.', ','),
'Teilnehmenden gesamt': str(total),
'bis 27 aus HD': str(total_b27_local),
'bis 27 nicht aus HD': str(total_b27_non_local),
'Verpflegungstage': str(self.duration * self.participant_count).replace('.', ','),
'Betreuer/in': str(len(jls)),
'Ort, Datum': '{p}, {d}'.format(p=settings.SEKTION, d=datetime.now().strftime('%d.%m.%Y'))}
print(members)
for i, m in enumerate(members):
suffix = str(' {}'.format(i + 1))
# indexing starts at zero, but the listing in the pdf starts at 1
if i + 1 == 1:
suffix = ''
elif i + 1 == 12:
suffix = '12'
base['Vor- und Nachname' + suffix] = m.name
base['Anschrift' + suffix] = m.address
base['Alter' + suffix] = str(m.age)
base['Status' + suffix] = str(2)
return base
@staticmethod @staticmethod
def filter_queryset_by_permissions(member, queryset=None): def filter_queryset_by_permissions(member, queryset=None):
if queryset is None: if queryset is None:

@ -4,10 +4,23 @@ import os
import subprocess import subprocess
import time import time
import glob import glob
from io import BytesIO
from pypdf import PdfReader, PdfWriter
from django import template
from django.template.loader import get_template from django.template.loader import get_template
from django.conf import settings from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from wsgiref.util import FileWrapper from wsgiref.util import FileWrapper
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 media_path(fp): def media_path(fp):
@ -58,3 +71,43 @@ def render_tex(name, template_path, context):
response['Content-Disposition'] = 'attachment; filename='+filename_pdf response['Content-Disposition'] = 'attachment; filename='+filename_pdf
return response return response
def fill_pdf_form(name, template_path, fields, attachments=[]):
filename = name + "_" + datetime.today().strftime("%d_%m_%Y")
filename = filename.replace(' ', '_').replace('&', '').replace('/', '_')
# drop umlauts, accents etc.
filename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore').decode()
filename_pdf = filename + '.pdf'
path = find_template(template_path)
if not os.path.exists(media_dir()):
os.makedirs(media_dir())
reader = PdfReader(path)
writer = PdfWriter()
writer.append(reader)
writer.update_page_form_field_values(None, fields, auto_regenerate=False)
for fp in attachments:
try:
img = Image.open(fp)
img_pdf = BytesIO()
img.save(img_pdf, "pdf")
writer.append(img_pdf)
except:
print("Could not add image", fp)
with open(media_path(filename_pdf), 'wb') as output_stream:
writer.write(output_stream)
# provide the user with the resulting pdf file
with open(media_path(filename_pdf), 'rb') as pdf:
response = HttpResponse(FileWrapper(pdf))#, content='application/pdf')
response['Content-Type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment; filename='+filename_pdf
return response

@ -10,6 +10,13 @@
</form> </form>
</li> </li>
<li>
<form method="post" action="{% url 'admin:members_freizeit_action' original.pk %}">
{% csrf_token %}
<input type="submit" name="sjr_application" value="{% trans 'Generate SJR application' %}">
</form>
</li>
<li> <li>
<form method="post" action="{% url 'admin:members_freizeit_action' original.pk %}"> <form method="post" action="{% url 'admin:members_freizeit_action' original.pk %}">
{% csrf_token %} {% csrf_token %}

Loading…
Cancel
Save