members/groups: factored out xlsxwriter recipe

pull/118/head
mariusrklein 11 months ago
parent fc94079365
commit c352457587

@ -7,7 +7,6 @@ import time
import unicodedata import unicodedata
import random import random
import string import string
import xlsxwriter
from functools import partial, update_wrapper from functools import partial, update_wrapper
from django.forms.models import BaseInlineFormSet from django.forms.models import BaseInlineFormSet
@ -21,6 +20,7 @@ from django import forms
from django.contrib import admin, messages from django.contrib import admin, messages
from django.contrib.admin import DateFieldListFilter from django.contrib.admin import DateFieldListFilter
from django.contrib.contenttypes.admin import GenericTabularInline from django.contrib.contenttypes.admin import GenericTabularInline
from contrib.media import serve_media, ensure_media_dir
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\ from django.db.models import TextField, ManyToManyField, ForeignKey, Count,\
@ -29,7 +29,7 @@ from django.forms import Textarea, RadioSelect, TypedChoiceField, CheckboxInput
from django.shortcuts import render from django.shortcuts import render
from django.core.exceptions import PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied, ValidationError
from .pdf import render_tex, fill_pdf_form, merge_pdfs, serve_pdf from .pdf import render_tex, fill_pdf_form, merge_pdfs, serve_pdf
from .models import WEEKDAYS from .excel import generate_group_overview
from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin
@ -829,64 +829,9 @@ class GroupAdmin(CommonAdminMixin, admin.ModelAdmin):
_("You are not allowed to create a group overview.")) _("You are not allowed to create a group overview."))
return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name))) return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name)))
if not os.path.exists(media_dir()): ensure_media_dir()
os.makedirs(media_dir()) filename = generate_group_overview(all_groups=self.model.objects.all())
response = serve_media(filename=filename, content_type='application/xlsx')
today = f"{datetime.today():%d.%m.%Y}"
filename = f"gruppenuebersicht_jdav_{settings.SEKTION}_{today}.xlsx"
workbook = xlsxwriter.Workbook(media_path(filename))
default = workbook.add_format({'text_wrap' : True, 'border': 1})
bold = workbook.add_format({'bold': True, 'border': 1})
title = workbook.add_format({'bold': True, 'font_size': 16, 'align': 'center'})
right = workbook.add_format({'bold': True, 'align': 'right'})
worksheet = workbook.add_worksheet()
worksheet.merge_range(0, 0, 0, 6, f"Gruppenübersicht JDAV {settings.SEKTION}", title)
row = 1
worksheet.write(row, 0, "Gruppe", bold)
worksheet.write(row, 1, "Wochentag", bold)
worksheet.write(row, 2, "Uhrzeit", bold)
worksheet.write(row, 3, "Altersgruppe", bold)
worksheet.write(row, 4, "TN", bold)
worksheet.write(row, 5, "JL", bold)
worksheet.write(row, 6, "Jugendleiter*innen", bold)
for group in self.model.objects.all():
# only official youth groups are on the website
if not group.show_website:
continue
row = row + 1
wd = f"{WEEKDAYS[group.weekday][1]}" if group.weekday else 'kein Wochentag'
times = f"{group.start_time:%H:%M} - {group.end_time:%H:%M}" if group.start_time and group.end_time else 'keine Zeiten'
yl_count = len([member for member in group.member_set.all() if member in group.leiters.all()])
tn_count = group.member_set.count() - yl_count
members = f"JG {group.year_from} - {group.year_to}"
leaders = f"{', '.join([yl.name for yl in group.leiters.all()])}"
worksheet.write(row, 0, group.name, default)
worksheet.write(row, 1, wd, default)
worksheet.write(row, 2, times, default)
worksheet.write(row, 3, members, default)
worksheet.write(row, 4, tn_count, default)
worksheet.write(row, 5, yl_count, default)
worksheet.write(row, 6, leaders, default)
worksheet.write(row+2, 6, f"Stand: {today}", right)
# set column width
worksheet.set_column_pixels(0, 0, 100)
worksheet.set_column_pixels(1, 1, 80)
worksheet.set_column_pixels(2, 2, 90)
worksheet.set_column_pixels(3, 3, 120)
worksheet.set_column_pixels(4, 4, 20)
worksheet.set_column_pixels(5, 5, 20)
worksheet.set_column_pixels(6, 6, 140)
workbook.close()
with open(media_path(filename), 'rb') as xls:
response = HttpResponse(FileWrapper(xls))
response['Content-Type'] = 'application/xlsx'
response['Content-Disposition'] = 'attachment; filename='+filename
return response return response

@ -0,0 +1,69 @@
from datetime import datetime
import os
import xlsxwriter
from django.conf import settings
from contrib.media import media_path
from .models import WEEKDAYS
def generate_group_overview(all_groups, limit_to_public = True):
"""
Creates an Excel Sheet with an overview of all the groups, their dates, times, age range and
number of members, etc.
arguments:
limit_to_public (optional, default is True): If False, all groups are returned in the overview,
including technical ones. If True, only groups with the flag "show_on_website" are returned.
"""
today = f"{datetime.today():%d.%m.%Y}"
filename = f"gruppenuebersicht_jdav_{settings.SEKTION}_{today}.xlsx"
workbook = xlsxwriter.Workbook(media_path(filename))
default = workbook.add_format({'text_wrap' : True, 'border': 1})
bold = workbook.add_format({'bold': True, 'border': 1})
title = workbook.add_format({'bold': True, 'font_size': 16, 'align': 'center'})
right = workbook.add_format({'bold': True, 'align': 'right'})
worksheet = workbook.add_worksheet()
worksheet.merge_range(0, 0, 0, 6, f"Gruppenübersicht JDAV {settings.SEKTION}", title)
row = 1
worksheet.write(row, 0, "Gruppe", bold)
worksheet.write(row, 1, "Wochentag", bold)
worksheet.write(row, 2, "Uhrzeit", bold)
worksheet.write(row, 3, "Altersgruppe", bold)
worksheet.write(row, 4, "TN", bold)
worksheet.write(row, 5, "JL", bold)
worksheet.write(row, 6, "Jugendleiter*innen", bold)
for group in all_groups:
# choose if only official youth groups on the website are shown
if limit_to_public and not group.show_website:
continue
row = row + 1
wd = f"{WEEKDAYS[group.weekday][1]}" if group.weekday else 'kein Wochentag'
times = f"{group.start_time:%H:%M} - {group.end_time:%H:%M}" if group.start_time and group.end_time else 'keine Zeiten'
yl_count = len([member for member in group.member_set.all() if member in group.leiters.all()])
tn_count = group.member_set.count() - yl_count
members = f"JG {group.year_from} - {group.year_to}"
leaders = f"{', '.join([yl.name for yl in group.leiters.all()])}"
worksheet.write(row, 0, group.name, default)
worksheet.write(row, 1, wd, default)
worksheet.write(row, 2, times, default)
worksheet.write(row, 3, members, default)
worksheet.write(row, 4, tn_count, default)
worksheet.write(row, 5, yl_count, default)
worksheet.write(row, 6, leaders, default)
worksheet.write(row+2, 6, f"Stand: {today}", right)
# set column width
worksheet.set_column_pixels(0, 0, 100)
worksheet.set_column_pixels(1, 1, 80)
worksheet.set_column_pixels(2, 2, 90)
worksheet.set_column_pixels(3, 3, 120)
worksheet.set_column_pixels(4, 4, 20)
worksheet.set_column_pixels(5, 5, 20)
worksheet.set_column_pixels(6, 6, 140)
workbook.close()
return filename
Loading…
Cancel
Save