Merge pull request #63 from Schlabonski/activity-categories

activity categories and members' skills
v1-0-stable
Christian Merten 9 years ago committed by GitHub
commit 4f09175863

@ -1,3 +1,4 @@
from django.core import mail
from django.core.mail import EmailMessage
@ -13,8 +14,10 @@ def send(subject, content, sender, recipients, reply_to=None,
kwargs = {"reply_to": [reply_to]}
else:
kwargs = {}
with mail.get_connection() as connection:
for recipient in recipients:
email = EmailMessage(subject, content, sender, [recipient], **kwargs)
email = EmailMessage(subject, content, sender, [recipient],
connection=connection, **kwargs)
if attachments is not None:
for attach in attachments:
email.attach_file(attach)

@ -0,0 +1,58 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{booktabs}
\usepackage{tabularx}
\usepackage{ragged2e}
\usepackage{amssymb}
\usepackage{cmbright}
\usepackage{graphicx}
\usepackage{textpos}
\usepackage[colorlinks]{hyperref}
\usepackage{float}
\usepackage[margin=1cm]{geometry}
\renewcommand{\arraystretch}{1.5}
\newcolumntype{Y}{>{\RaggedRight\arraybackslash}X}
\begin{document}
% HEADLINE
{\noindent\LARGE\textsc{Teilnehmerliste \\Sektionsveranstaltung}}\\
\textit{Erstellt: MEMBERLIST-DATE}\\
% DESCRIPTION TABLE
\begin{table}[H]
\begin{tabular}{ll}
\large Aktivität: & ACTIVITY \\
\large Gruppe: & GROUP \\
\large Ziel: & DESTINATION \\
\large Stützpunkt: & PLACE \\
\large Zeitraum: & TIME-PERIOD \\
\end{tabular}
\end{table}
\begin{table}[H]
\begin{tabularx}{\textwidth}{@{} l l Y @{}}
\toprule
\textbf{Name} & \textbf{Fähigkeiten (max. 100)} & \textbf{Kommentare} \\
\midrule
TABLE
\bottomrule
\end{tabularx}
\end{table}
\noindent\large Fähigkeiten der Gruppe\\
\begin{table}[H]
\begin{tabular*}{1\linewidth}{@{\extracolsep{\fill}}llll}
\toprule
\textbf{Name} & \textbf{Durchschnitt} & \textbf{Minimum} & \textbf{Maximum} \\
\midrule
TABLE-QUALITIES
\bottomrule
\end{tabular*}
\end{table}
\vspace{1cm}
\end{document}

@ -12,11 +12,11 @@ from django.contrib import admin
from django.contrib.admin import DateFieldListFilter
from django.utils.translation import ugettext_lazy as translate
from django.db.models import TextField, ManyToManyField
from django.forms import Textarea
from django.forms import Textarea, RadioSelect, TypedChoiceField
from django.shortcuts import render
from .models import (Member, Group, MemberList, MemberOnList, Klettertreff,
KlettertreffAttendee)
KlettertreffAttendee, ActivityCategory)
# Register your models here.
@ -28,18 +28,35 @@ class MemberAdmin(admin.ModelAdmin):
formfield_overrides = {
ManyToManyField: {'widget': forms.CheckboxSelectMultiple}
}
change_form_template = "members/change_member.html"
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['qualities'] =\
Member.objects.get(pk=object_id).get_skills()
return super(MemberAdmin, self).change_view(request, object_id,
form_url=form_url,
extra_context=extra_context)
class GroupAdmin(admin.ModelAdmin):
fields = ['name', 'min_age']
list_display = ('name', 'min_age')
class ActivityCategoryAdmin(admin.ModelAdmin):
fields = ['name', 'description']
class MemberListAdminForm(forms.ModelForm):
difficulty = TypedChoiceField(MemberList.difficulty_choices,
widget=RadioSelect,
coerce=int)
class Meta:
model = MemberList
exclude = ['add_member']
def __init__(self, *args, **kwargs):
super(MemberListAdminForm, self).__init__(*args, **kwargs)
self.fields['jugendleiter'].queryset = Member.objects.filter(group__name='Jugendleiter')
@ -55,11 +72,12 @@ class MemberOnListInline(admin.StackedInline):
'cols': 40})},
}
class MemberListAdmin(admin.ModelAdmin):
inlines = [MemberOnListInline]
form = MemberListAdminForm
list_display = ['__str__', 'date']
actions = ['convert_to_pdf']
actions = ['convert_to_pdf', 'generate_notes']
formfield_overrides = {
ManyToManyField: {'widget': forms.CheckboxSelectMultiple}
}
@ -69,7 +87,6 @@ class MemberListAdmin(admin.ModelAdmin):
def convert_to_pdf(self, request, queryset):
"""Converts a member list to pdf.
"""
for memberlist in queryset:
# create a unique filename
@ -155,6 +172,102 @@ class MemberListAdmin(admin.ModelAdmin):
return response
def generate_notes(self, request, queryset):
"""Generates a short note for the jugendleiter"""
for memberlist in queryset:
# unique filename
filename = memberlist.name + "_note_" +\
datetime.today().strftime("%d_%m_%Y")
filename = filename.replace(' ', '_')
filename_tex = filename + '.tex'
filename_pdf = filename + '.pdf'
# generate table
table = ""
activities = [a.name for a in memberlist.activity.all()]
skills = {a: [] for a in activities}
for memberonlist in memberlist.memberonlist_set.all():
m = memberonlist.member
qualities = []
for activity, value in m.get_skills().items():
if activity not in activities:
continue
skills[activity].append(value)
qualities.append("\\textit{%s:} %s" % (activity, value))
comment = ". ".join(c for c
in (m.comments,
memberonlist.comments) if
c).replace("..", ".")
line = '{0} {1} & {2} & {3} \\\\'.format(
m.prename, m.lastname,
", ".join(qualities), comment or "---",
)
table += line
table_qualities = ""
for activity in activities:
line = '{0} & {1} & {2} & {3} \\\\ \n'.format(
activity,
sum(skills[activity]) / len(skills[activity]),
min(skills[activity]),
max(skills[activity])
)
table_qualities += line
# copy template
shutil.copy('media/memberlists/membernote_template.tex',
'media/memberlists/' + filename_tex)
# read in template
with open('media/memberlists/' + filename_tex, 'r') as f:
template_content = f.read()
# adapt template
template_content = template_content.replace('ACTIVITY', memberlist.name)
groups = ', '.join(g.name for g in memberlist.groups.all())
template_content = template_content.replace('GROUP', groups)
template_content = template_content.replace('DESTINATION', memberlist.destination)
template_content = template_content.replace('PLACE', memberlist.place)
template_content = template_content.replace('MEMBERLIST-DATE',
datetime.today().strftime('%d.%m.%Y'))
time_period = memberlist.date.strftime('%d.%m.%Y')
if memberlist.end != memberlist.date:
time_period += " - " + memberlist.end.strftime('%d.%m.%Y')
template_content = template_content.replace('TIME-PERIOD', time_period)
jugendleiter = ', '.join(j.name for j in memberlist.jugendleiter.all())
template_content = template_content.replace('JUGENDLEITER', jugendleiter)
template_content = template_content.replace('TABLE-QUALITIES',
table_qualities)
template_content = template_content.replace('TABLE', table)
# write adapted template to file
with open('media/memberlists/' + filename_tex, 'w') as f:
f.write(template_content)
# compile using pdflatex
oldwd = os.getcwd()
os.chdir('media/memberlists')
subprocess.call(['pdflatex', filename_tex])
time.sleep(1)
# do some cleanup
for f in glob.glob('*.log'):
os.remove(f)
for f in glob.glob('*.aux'):
os.remove(f)
os.remove(filename_tex)
os.chdir(oldwd)
# provide the user with the resulting pdf file
with open('media/memberlists/'+filename_pdf, 'rb') as pdf:
response = HttpResponse(FileWrapper(pdf))
response['Content-Type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment; filename=' + filename_pdf
return response
class KlettertreffAdminForm(forms.ModelForm):
class Meta:
@ -217,3 +330,4 @@ admin.site.register(Member, MemberAdmin)
admin.site.register(Group, GroupAdmin)
admin.site.register(MemberList, MemberListAdmin)
admin.site.register(Klettertreff, KlettertreffAdmin)
admin.site.register(ActivityCategory, ActivityCategoryAdmin)

@ -7,6 +7,22 @@ from django.utils import timezone
from multiselectfield import MultiSelectField
class ActivityCategory(models.Model):
"""
Describes one kind of activity
"""
name = models.CharField(max_length=20, verbose_name=_('Name'))
description = models.TextField(_('Description'))
def __str__(self):
return self.name
class Meta:
verbose_name = _('Activity')
verbose_name_plural = _('Activities')
class Group(models.Model):
"""
Represents one group of the association
@ -85,6 +101,16 @@ class Member(models.Model):
verbose_name = _('member')
verbose_name_plural = _('members')
def get_skills(self):
# get skills by summing up all the activities taken part in
skills = {}
for kind in ActivityCategory.objects.all():
lists = MemberList.objects.filter(activity=kind,
memberonlist__member=self)
skills[kind.name] = sum([l.difficulty * 3 for l in lists
if l.date < datetime.now().date()])
return skills
class MemberList(models.Model):
"""Lets the user create a list of members in pdf format. """
@ -101,6 +127,10 @@ class MemberList(models.Model):
tour_type_choices = (('Gemeinschaftstour','Gemeinschaftstour'), ('Führungstour', 'Führungstour'),
('Ausbildung', 'Ausbildung'))
tour_type = MultiSelectField(choices=tour_type_choices, default='', max_choices=1)
activity = models.ManyToManyField(ActivityCategory, default=None)
difficulty_choices = [(1, _('easy')), (2, _('medium')), (3, _('hard'))]
difficulty = models.IntegerField(verbose_name=_('Difficulty'),
choices=difficulty_choices)
def __str__(self):
@ -157,7 +187,6 @@ class Klettertreff(models.Model):
return True
return False
get_jugendleiter.short_description = _('Jugendleiter')
class Meta:

@ -0,0 +1,20 @@
{% extends "admin/change_form.html" %}
{% load i18n %}
{% load static %}
{% block after_field_sets %}
<p><b>{% trans "Qualities:" %}</b></p>
<table style="width:100%">
<tr>
<th>{% trans "Activity" %}</th>
<th>{% trans "Skill level" %}</th>
</tr>
{% for key, value in qualities.items %}
<tr>
<td>{{ key }}</td>
<td><progress value="{{ value }}" max="100"></progress></td>
</tr>
{% endfor %}
</table>
{% endblock %}
Loading…
Cancel
Save