seperate teilnehmerlisten into notizlisten and freizeiten, add migration from old teilnehmerlisten to both new versions

v1-0-stable
Christian Merten 5 years ago
parent bf719601a7
commit 56696edb32

@ -23,7 +23,7 @@ class Message(models.Model):
to_groups = models.ManyToManyField('members.Group',
verbose_name=_('to group'),
blank=True)
to_memberlist = models.ForeignKey('members.MemberList',
to_memberlist = models.ForeignKey('members.Freizeit',
verbose_name=_('to member list'),
blank=True,
null=True)

@ -9,15 +9,16 @@ import unicodedata
from django.http import HttpResponse, HttpResponseRedirect
from wsgiref.util import FileWrapper
from django import forms
from django.contrib import admin
from django.contrib import admin, messages
from django.contrib.admin import DateFieldListFilter
from django.contrib.contenttypes.admin import GenericTabularInline
from django.utils.translation import ugettext_lazy as _
from django.db.models import TextField, ManyToManyField, ForeignKey
from django.forms import Textarea, RadioSelect, TypedChoiceField
from django.shortcuts import render
from .models import (Member, Group, MemberList, MemberOnList, Klettertreff,
KlettertreffAttendee, ActivityCategory)
from .models import (Member, Group, Freizeit, MemberNoteList, NewMemberOnList, Klettertreff,
KlettertreffAttendee, ActivityCategory, OldMemberOnList, MemberList)
from django.conf import settings
#from easy_select2 import apply_select2
@ -103,28 +104,28 @@ class ActivityCategoryAdmin(admin.ModelAdmin):
fields = ['name', 'description']
class MemberListAdminForm(forms.ModelForm):
difficulty = TypedChoiceField(MemberList.difficulty_choices,
class FreizeitAdminForm(forms.ModelForm):
difficulty = TypedChoiceField(Freizeit.difficulty_choices,
#widget=RadioSelect,
coerce=int,
label=_('Difficulty'))
tour_type = TypedChoiceField(MemberList.tour_type_choices,
tour_type = TypedChoiceField(Freizeit.tour_type_choices,
#widget=RadioSelect,
coerce=int,
label=_('Tour type'))
class Meta:
model = MemberList
model = Freizeit
exclude = ['add_member']
def __init__(self, *args, **kwargs):
super(MemberListAdminForm, self).__init__(*args, **kwargs)
super(FreizeitAdminForm, self).__init__(*args, **kwargs)
self.fields['jugendleiter'].queryset = Member.objects.filter(group__name='Jugendleiter')
#self.fields['add_member'].queryset = Member.objects.filter(prename__startswith='F')
class MemberOnListInline(admin.TabularInline):
model = MemberOnList
class MemberOnListInline(GenericTabularInline):
model = NewMemberOnList
extra = 0
#formfield_overrides = {
# TextField: {'widget': Textarea(attrs={'rows': 1,
@ -134,9 +135,144 @@ class MemberOnListInline(admin.TabularInline):
#}
class OldMemberOnListInline(admin.TabularInline):
model = OldMemberOnList
extra = 0
class MemberNoteListAdmin(admin.ModelAdmin):
inlines = [MemberOnListInline]
list_display = ['__str__']
search_fields = ('name',)
actions = ['generate_summary']
def generate_summary(self, request, queryset):
"""Generates a pdf summary of the given NoteMemberLists
"""
for memberlist in queryset:
# unique filename
filename = memberlist.title + "_notes_" + datetime.today().strftime("%d_%m_%Y")
filename = filename.replace(' ', '_').replace('&', '')
# drop umlauts, accents etc.
filename = unicodedata.normalize('NFKD', filename).\
encode('ASCII', 'ignore').decode()
filename_tex = filename + '.tex'
filename_pdf = filename + '.pdf'
# generate table
table = ""
for memberonlist in memberlist.membersonlist.all():
m = memberonlist.member
comment = ". ".join(c for c
in (m.comments,
memberonlist.comments) if
c).replace("..", ".")
line = '{0} {1} & {2} \\\\'.format(
esc_ampersand(m.prename), esc_ampersand(m.lastname),
esc_ampersand(comment) or "---")
table += esc_underscore(line)
# copy template
shutil.copy(media_path('memberlistnote_template.tex'),
media_path(filename_tex))
# read in template
with open(media_path(filename_tex), 'r', encoding='utf-8') as f:
template_content = f.read()
# adapt template
title = esc_all(memberlist.title)
template_content = template_content.replace('MEMBERLIST-TITLE', title)
template_content = template_content.replace('MEMBERLIST-DATE',
datetime.today().strftime('%d.%m.%Y'))
template_content = template_content.replace('TABLE', table)
# write adapted template to file
with open(media_path(filename_tex), 'w', encoding='utf-8') as f:
f.write(template_content)
# compile using pdflatex
oldwd = os.getcwd()
os.chdir(media_dir())
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_path(filename_pdf), 'rb') as pdf:
response = HttpResponse(FileWrapper(pdf))
response['Content-Type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment; filename=' + filename_pdf
return response
generate_summary.short_description = "PDF Übersicht erstellen"
class MemberListAdmin(admin.ModelAdmin):
inlines = [OldMemberOnListInline]
form = FreizeitAdminForm
list_display = ['__str__', 'date']
search_fields = ('name',)
actions = ['migrate_to_freizeit', 'migrate_to_notelist']
#formfield_overrides = {
# ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
# ForeignKey: {'widget': apply_select2(forms.Select)}
#}
class Media:
css = {'all': ('admin/css/tabular_hide_original.css',)}
def __init__(self, *args, **kwargs):
super(MemberListAdmin, self).__init__(*args, **kwargs)
def migrate_to_freizeit(self, request, queryset):
"""Creates 'Freizeiten' from the given memberlists """
for memberlist in queryset:
freizeit = Freizeit(name=memberlist.name,
place=memberlist.place,
destination=memberlist.destination,
date=memberlist.date,
end=memberlist.end,
tour_type=memberlist.tour_type,
difficulty=memberlist.difficulty)
freizeit.save()
freizeit.jugendleiter = memberlist.jugendleiter.all()
freizeit.groups = memberlist.groups.all()
freizeit.activity = memberlist.activity.all()
for memberonlist in memberlist.oldmemberonlist_set.all():
newonlist = NewMemberOnList(member=memberonlist.member,
comments=memberonlist.comments,
memberlist=freizeit)
newonlist.save()
messages.info(request, "Freizeit(en) erfolgreich erstellt.")
migrate_to_freizeit.short_description = "Aus Teilnehmerliste(n) Freizeit(en) erstellen"
def migrate_to_notelist(self, request, queryset):
"""Creates 'MemberNoteList' from the given memberlists """
for memberlist in queryset:
notelist = MemberNoteList(title=memberlist.name,
date=memberlist.date)
notelist.save()
for memberonlist in memberlist.oldmemberonlist_set.all():
newonlist = NewMemberOnList(member=memberonlist.member,
comments=memberonlist.comments,
memberlist=notelist)
newonlist.save()
messages.info(request, "Teilnehmerlist(en) erfolgreich erstellt.")
migrate_to_notelist.short_description = "Aus Teilnehmerliste(n) Notizliste erstellen"
class FreizeitAdmin(admin.ModelAdmin):
inlines = [MemberOnListInline]
form = MemberListAdminForm
form = FreizeitAdminForm
list_display = ['__str__', 'date']
search_fields = ('name',)
actions = ['convert_to_pdf', 'generate_notes']
@ -149,7 +285,7 @@ class MemberListAdmin(admin.ModelAdmin):
css = {'all': ('admin/css/tabular_hide_original.css',)}
def __init__(self, *args, **kwargs):
super(MemberListAdmin, self).__init__(*args, **kwargs)
super(FreizeitAdmin, self).__init__(*args, **kwargs)
def convert_to_pdf(self, request, queryset):
"""Converts a member list to pdf.
@ -167,11 +303,11 @@ class MemberListAdmin(admin.ModelAdmin):
# open temporary file for table
with open(media_path(filename_table), 'w+', encoding='utf-8') as f:
if memberlist.memberonlist_set.count() == 0:
if memberlist.membersonlist.count() == 0:
f.write('{0} & {1} & {2} & {3} \\\\ \n'.format(
'keine Teilnehmer', '-', '-', '-'
))
for memberonlist in memberlist.memberonlist_set.all():
for memberonlist in memberlist.membersonlist.all():
# write table of members in latex compatible format
member = memberonlist.member
# use parents phone number if available
@ -278,7 +414,7 @@ class MemberListAdmin(admin.ModelAdmin):
table = ""
activities = [a.name for a in memberlist.activity.all()]
skills = {a: [] for a in activities}
for memberonlist in memberlist.memberonlist_set.all():
for memberonlist in memberlist.membersonlist.all():
m = memberonlist.member
qualities = []
for activity, value in m.get_skills().items():
@ -440,6 +576,8 @@ class KlettertreffAdmin(admin.ModelAdmin):
admin.site.register(Member, MemberAdmin)
admin.site.register(Group, GroupAdmin)
admin.site.register(Freizeit, FreizeitAdmin)
admin.site.register(MemberNoteList, MemberNoteListAdmin)
admin.site.register(MemberList, MemberListAdmin)
admin.site.register(Klettertreff, KlettertreffAdmin)
admin.site.register(ActivityCategory, ActivityCategoryAdmin)

@ -4,6 +4,8 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.urls import reverse
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from utils import RestrictedFileField
import os
@ -160,14 +162,14 @@ class Member(models.Model):
skills = {}
for kind in ActivityCategory.objects.all():
lists = MemberList.objects.filter(activity=kind,
memberonlist__member=self)
oldmemberonlist__member=self)
skills[kind.name] = sum([l.difficulty * 3 for l in lists
if l.date < datetime.now().date()])
return skills
def get_activities(self):
# get activity overview
return MemberList.objects.filter(memberonlist__member=self)
return MemberList.objects.filter(oldmemberonlist__member=self)
class MemberList(models.Model):
@ -214,7 +216,7 @@ class MemberList(models.Model):
return reverse('admin:members_memberlist_change', args=[str(self.id)])
class MemberOnList(models.Model):
class OldMemberOnList(models.Model):
"""
Connects members to a list of members.
"""
@ -230,6 +232,87 @@ class MemberOnList(models.Model):
verbose_name_plural = _('Members')
class NewMemberOnList(models.Model):
"""
Connects members to a list of members.
"""
member = models.ForeignKey(Member, verbose_name=_('Member'))
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
default=ContentType('members', 'Freizeit').pk)
object_id = models.PositiveIntegerField()
memberlist = GenericForeignKey('content_type', 'object_id')
comments = models.TextField(_('Comment'), default='', blank=True)
def __str__(self):
return str(self.member)
class Meta:
verbose_name = _('Member')
verbose_name_plural = _('Members')
class Freizeit(models.Model):
"""Lets the user create a 'Freizeit' and generate a members overview in pdf format. """
name = models.CharField(verbose_name=_('Activity'), default='',
max_length=50)
place = models.CharField(verbose_name=_('Place'), default='', max_length=50)
destination = models.CharField(verbose_name=_('Destination (optional)'),
default='', max_length=50, blank=True)
date = models.DateField(default=datetime.today, verbose_name=_('Date'))
end = models.DateField(verbose_name=_('End (optional)'), blank=True, default=datetime.today)
# comment = models.TextField(_('Comments'), default='', blank=True)
groups = models.ManyToManyField(Group, verbose_name=_('Groups'))
jugendleiter = models.ManyToManyField(Member)
tour_type_choices = ((GEMEINSCHAFTS_TOUR, 'Gemeinschaftstour'),
(FUEHRUNGS_TOUR, 'Führungstour'),
(AUSBILDUNGS_TOUR, 'Ausbildung'))
# verbose_name is overriden by form, label is set in admin.py
tour_type = models.IntegerField(choices=tour_type_choices)
activity = models.ManyToManyField(ActivityCategory, default=None,
verbose_name=_('Categories'))
difficulty_choices = [(1, _('easy')), (2, _('medium')), (3, _('hard'))]
# verbose_name is overriden by form, label is set in admin.py
difficulty = models.IntegerField(choices=difficulty_choices)
membersonlist = GenericRelation(NewMemberOnList)
def __str__(self):
"""String represenation"""
return self.name
class Meta:
verbose_name = "Freizeit"
verbose_name_plural = "Freizeiten"
def get_tour_type(self):
if self.tour_type == FUEHRUNGS_TOUR:
return "Führungstour"
elif self.tour_type == AUSBILDUNGS_TOUR:
return "Ausbildung"
else:
return "Gemeinschaftstour"
def get_absolute_url(self):
return reverse('admin:members_memberlist_change', args=[str(self.id)])
class MemberNoteList(models.Model):
"""
A member list with a title and a bunch of members to take some notes.
"""
title = models.CharField(verbose_name=_('Title'), default='', max_length=50)
date = models.DateField(default=datetime.today, verbose_name=_('Date'), null=True, blank=True)
membersonlist = GenericRelation(NewMemberOnList)
def __str__(self):
"""String represenation"""
return self.title
class Meta:
verbose_name = "Notizliste"
verbose_name_plural = "Notizlisten"
class Klettertreff(models.Model):
""" This model represents a Klettertreff event.

Loading…
Cancel
Save