members: add training data for Member, set blank flags on multiple fields

pull/5/head
Christian Merten 3 years ago
parent 9222b2869a
commit d0ede5d0c1
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -38,6 +38,7 @@ JET_SIDE_MENU_ITEMS = [
{'name': 'freizeit', 'permissions': ['members.view_freizeit']}, {'name': 'freizeit', 'permissions': ['members.view_freizeit']},
{'name': 'klettertreff', 'permissions': ['members.view_klettertreff']}, {'name': 'klettertreff', 'permissions': ['members.view_klettertreff']},
{'name': 'activitycategory', 'permissions': ['members.view_activitycategory']}, {'name': 'activitycategory', 'permissions': ['members.view_activitycategory']},
{'name': 'trainingcategory', 'permissions': ['members.view_trainingcategory']},
{'name': 'memberunconfirmedproxy', 'permissions': ['members.view_memberunconfirmedproxy']}, {'name': 'memberunconfirmedproxy', 'permissions': ['members.view_memberunconfirmedproxy']},
{'name': 'memberwaitinglist', 'permissions': ['members.view_memberwaitinglist']}, {'name': 'memberwaitinglist', 'permissions': ['members.view_memberwaitinglist']},
]}, ]},

@ -32,7 +32,7 @@ import nested_admin
from .models import (Member, Group, Freizeit, MemberNoteList, NewMemberOnList, Klettertreff, from .models import (Member, Group, Freizeit, MemberNoteList, NewMemberOnList, Klettertreff,
MemberWaitingList, LJPProposal, Intervention, PermissionMember, MemberWaitingList, LJPProposal, Intervention, PermissionMember,
PermissionGroup, PermissionGroup, MemberTraining, TrainingCategory,
KlettertreffAttendee, ActivityCategory, OldMemberOnList, MemberList, KlettertreffAttendee, ActivityCategory, OldMemberOnList, MemberList,
annotate_activity_score, RegistrationPassword, MemberUnconfirmedProxy) annotate_activity_score, RegistrationPassword, MemberUnconfirmedProxy)
from finance.models import Statement, Bill from finance.models import Statement, Bill
@ -91,6 +91,20 @@ class PermissionOnMemberInline(admin.StackedInline):
can_delete = False can_delete = False
class TrainingOnMemberInline(admin.TabularInline):
model = MemberTraining
formfield_overrides = {
TextField: {'widget': Textarea(attrs={'rows': 1, 'cols': 40})}
}
ordering = ("date",)
extra = 0
class TrainingCategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'permission_needed')
ordering = ('name', )
class RegistrationFilter(admin.SimpleListFilter): class RegistrationFilter(admin.SimpleListFilter):
title = _('Registration complete') title = _('Registration complete')
parameter_name = 'registered' parameter_name = 'registered'
@ -148,7 +162,7 @@ class MemberAdmin(admin.ModelAdmin):
search_fields = ('prename', 'lastname', 'email') search_fields = ('prename', 'lastname', 'email')
list_filter = ('group', 'gets_newsletter', RegistrationFilter, 'active') list_filter = ('group', 'gets_newsletter', RegistrationFilter, 'active')
list_display_links = None list_display_links = None
inlines = [PermissionOnMemberInline] inlines = [TrainingOnMemberInline, PermissionOnMemberInline]
#formfield_overrides = { #formfield_overrides = {
# ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
# ForeignKey: {'widget': apply_select2(forms.Select)} # ForeignKey: {'widget': apply_select2(forms.Select)}
@ -892,6 +906,7 @@ admin.site.register(Freizeit, FreizeitAdmin)
admin.site.register(MemberNoteList, MemberNoteListAdmin) admin.site.register(MemberNoteList, MemberNoteListAdmin)
admin.site.register(Klettertreff, KlettertreffAdmin) admin.site.register(Klettertreff, KlettertreffAdmin)
admin.site.register(ActivityCategory, ActivityCategoryAdmin) admin.site.register(ActivityCategory, ActivityCategoryAdmin)
admin.site.register(TrainingCategory, TrainingCategoryAdmin)
def media_path(fp): def media_path(fp):

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-01 04:45-0500\n" "POT-Creation-Date: 2023-04-01 05:46-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,155 +18,155 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: members/admin.py:95 members/models.py:199 #: members/admin.py:108 members/models.py:199
msgid "Registration complete" msgid "Registration complete"
msgstr "Anmeldung vollständig" msgstr "Anmeldung vollständig"
#: members/admin.py:101 #: members/admin.py:114
msgid "True" msgid "True"
msgstr "Ja" msgstr "Ja"
#: members/admin.py:102 #: members/admin.py:115
msgid "False" msgid "False"
msgstr "Nein" msgstr "Nein"
#: members/admin.py:103 #: members/admin.py:116
msgid "All" msgid "All"
msgstr "Alle" msgstr "Alle"
#: members/admin.py:233 #: members/admin.py:246
#, python-format #, python-format
msgid "You are not allowed to view %(name)s." msgid "You are not allowed to view %(name)s."
msgstr "Du hast nicht die notwendigen Rechte um %(name)s anzuschauen." msgstr "Du hast nicht die notwendigen Rechte um %(name)s anzuschauen."
#: members/admin.py:240 #: members/admin.py:253
msgid "Compose new mail to selected members" msgid "Compose new mail to selected members"
msgstr "Neue Nachricht an ausgewählte Teilnehmer verfassen" msgstr "Neue Nachricht an ausgewählte Teilnehmer verfassen"
#: members/admin.py:246 #: members/admin.py:259
msgid "Echo required" msgid "Echo required"
msgstr "Rückmeldung erforderlich" msgstr "Rückmeldung erforderlich"
#: members/admin.py:251 #: members/admin.py:264
msgid "Successfully requested echo from selected members." msgid "Successfully requested echo from selected members."
msgstr "" msgstr ""
"Rückmeldungsaufforderung erfolgreich an ausgewählte Teilnehmer verschickt." "Rückmeldungsaufforderung erfolgreich an ausgewählte Teilnehmer verschickt."
#: members/admin.py:252 #: members/admin.py:265
msgid "Request echo from selected members" msgid "Request echo from selected members"
msgstr "Rückmeldungsaufforderung an ausgewählte Teilnehmer verschicken" msgstr "Rückmeldungsaufforderung an ausgewählte Teilnehmer verschicken"
#: members/admin.py:269 #: members/admin.py:282
msgid "activity" msgid "activity"
msgstr "Aktivität" msgstr "Aktivität"
#: members/admin.py:279 members/models.py:36 #: members/admin.py:292 members/models.py:36 members/models.py:1085
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
#: members/admin.py:308 #: members/admin.py:321
msgid "Successfully requested mail confirmation from selected registrations." msgid "Successfully requested mail confirmation from selected registrations."
msgstr "Aufforderung zur Bestätigung der Email Adresse versendet." msgstr "Aufforderung zur Bestätigung der Email Adresse versendet."
#: members/admin.py:309 #: members/admin.py:322
msgid "Request mail confirmation from selected registrations" msgid "Request mail confirmation from selected registrations"
msgstr "Aufforderung zur Bestätigung der Email Adresse versenden" msgstr "Aufforderung zur Bestätigung der Email Adresse versenden"
#: members/admin.py:316 members/admin.py:354 #: members/admin.py:329 members/admin.py:367
#, python-format #, python-format
msgid "Successfully confirmed %(name)s." msgid "Successfully confirmed %(name)s."
msgstr "Registrierung von %(name)s erfolgreich bestätigt." msgstr "Registrierung von %(name)s erfolgreich bestätigt."
#: members/admin.py:320 members/admin.py:357 #: members/admin.py:333 members/admin.py:370
#, python-format #, python-format
msgid "Can't confirm. %(name)s has unconfirmed email addresses." msgid "Can't confirm. %(name)s has unconfirmed email addresses."
msgstr "Bestätigung nicht möglich. %(name)s hat unbestätigte Emailadressen." msgstr "Bestätigung nicht möglich. %(name)s hat unbestätigte Emailadressen."
#: members/admin.py:325 #: members/admin.py:338
msgid "Successfully confirmed multiple registrations." msgid "Successfully confirmed multiple registrations."
msgstr "Erfolgreich mehrere Registrierungen bestätigt." msgstr "Erfolgreich mehrere Registrierungen bestätigt."
#: members/admin.py:327 #: members/admin.py:340
msgid "" msgid ""
"Failed to confirm some registrations because of unconfirmed email addresses." "Failed to confirm some registrations because of unconfirmed email addresses."
msgstr "" msgstr ""
"Einige Bestätigungen fehlgeschlagen, weil Emailadressen noch nicht bestätigt " "Einige Bestätigungen fehlgeschlagen, weil Emailadressen noch nicht bestätigt "
"sind." "sind."
#: members/admin.py:328 #: members/admin.py:341
msgid "Confirm selected registrations" msgid "Confirm selected registrations"
msgstr "Ausgewählte Registrierungen bestätigen" msgstr "Ausgewählte Registrierungen bestätigen"
#: members/admin.py:348 #: members/admin.py:361
#, python-format #, python-format
msgid "Successfully demoted %(name)s to waiter." msgid "Successfully demoted %(name)s to waiter."
msgstr "%(name)s zurück auf die Warteliste gesetzt." msgstr "%(name)s zurück auf die Warteliste gesetzt."
#: members/admin.py:349 #: members/admin.py:362
msgid "Demote selected registrations to waiters." msgid "Demote selected registrations to waiters."
msgstr "Ausgewählte Registrierungen zurück auf die Warteliste setzen." msgstr "Ausgewählte Registrierungen zurück auf die Warteliste setzen."
#: members/admin.py:364 members/models.py:294 members/models.py:843 #: members/admin.py:377 members/models.py:294 members/models.py:842
msgid "Group" msgid "Group"
msgstr "Gruppe" msgstr "Gruppe"
#: members/admin.py:384 #: members/admin.py:397
#, python-format #, python-format
msgid "Successfully asked %(name)s to confirm their waiting status." msgid "Successfully asked %(name)s to confirm their waiting status."
msgstr "Erfolgreich %(name)s aufgefordert den Wartelistenplatz zu bestätigen." msgstr "Erfolgreich %(name)s aufgefordert den Wartelistenplatz zu bestätigen."
#: members/admin.py:385 #: members/admin.py:398
msgid "Ask selected waiters to confirm their waiting status" msgid "Ask selected waiters to confirm their waiting status"
msgstr "Wartende auffordern den Wartelistenplatz zu bestätigen" msgstr "Wartende auffordern den Wartelistenplatz zu bestätigen"
#: members/admin.py:394 members/admin.py:450 #: members/admin.py:407 members/admin.py:463
msgid "" msgid ""
"An error occurred while trying to invite said members. Please try again." "An error occurred while trying to invite said members. Please try again."
msgstr "" msgstr ""
"Beim Einladen dieser Personen ist ein Fehler aufgetreten. Bitte versuche es " "Beim Einladen dieser Personen ist ein Fehler aufgetreten. Bitte versuche es "
"nochmal. " "nochmal. "
#: members/admin.py:402 members/admin.py:457 #: members/admin.py:415 members/admin.py:470
#, python-format #, python-format
msgid "Successfully invited %(name)s to %(group)s." msgid "Successfully invited %(name)s to %(group)s."
msgstr "Erfolgreich %(name)s zu Gruppe %(group)s eingeladen." msgstr "Erfolgreich %(name)s zu Gruppe %(group)s eingeladen."
#: members/admin.py:406 members/admin.py:462 #: members/admin.py:419 members/admin.py:475
msgid "Select group for invitation" msgid "Select group for invitation"
msgstr "Wähle Gruppe für Einladung aus" msgstr "Wähle Gruppe für Einladung aus"
#: members/admin.py:413 #: members/admin.py:426
msgid "Offer waiter a place in a group." msgid "Offer waiter a place in a group."
msgstr "Personen auf der Warteliste einen Gruppenplatz anbieten." msgstr "Personen auf der Warteliste einen Gruppenplatz anbieten."
#: members/admin.py:502 #: members/admin.py:515
msgid "Difficulty" msgid "Difficulty"
msgstr "Schwierigkeit" msgstr "Schwierigkeit"
#: members/admin.py:505 #: members/admin.py:518
msgid "Tour type" msgid "Tour type"
msgstr "Art der Tour" msgstr "Art der Tour"
#: members/admin.py:508 members/models.py:694 #: members/admin.py:521 members/models.py:693
msgid "Means of transportation" msgid "Means of transportation"
msgstr "Verkehrsmittel" msgstr "Verkehrsmittel"
#: members/admin.py:760 #: members/admin.py:773
#, python-format #, python-format
msgid "You are not allowed to view all members on excursion %(name)s." msgid "You are not allowed to view all members on excursion %(name)s."
msgstr "" msgstr ""
"Du hast nicht die nötigen Rechte um alle Teilnehmer:innen der Freizeit " "Du hast nicht die nötigen Rechte um alle Teilnehmer:innen der Freizeit "
"%(name)s anzusehen." "%(name)s anzusehen."
#: members/admin.py:770 #: members/admin.py:783
msgid "Generate crisis intervention list" msgid "Generate crisis intervention list"
msgstr "Kriseninterventionsliste erstellen" msgstr "Kriseninterventionsliste erstellen"
#: members/admin.py:780 #: members/admin.py:793
msgid "Generate overview" msgid "Generate overview"
msgstr "Hinweise für Jugendleiter erstellen" msgstr "Hinweise für Jugendleiter erstellen"
#: members/admin.py:790 #: members/admin.py:803
msgid "Generate seminar report" msgid "Generate seminar report"
msgstr "Seminarbericht erstellen" msgstr "Seminarbericht erstellen"
@ -178,7 +178,7 @@ msgstr "Teilnehmer"
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: members/models.py:43 members/models.py:575 members/models.py:674 #: members/models.py:43 members/models.py:574 members/models.py:673
#: members/templates/members/change_member.html:17 #: members/templates/members/change_member.html:17
msgid "Activity" msgid "Activity"
msgstr "Aktivität" msgstr "Aktivität"
@ -404,219 +404,256 @@ msgstr "Letzte Wartebestätigung"
msgid "Invited for group" msgid "Invited for group"
msgstr "Einladung zu Gruppe austehend" msgstr "Einladung zu Gruppe austehend"
#: members/models.py:498 #: members/models.py:497
msgid "Waiter" msgid "Waiter"
msgstr "Wartende Person" msgstr "Wartende Person"
#: members/models.py:499 #: members/models.py:498
msgid "Waiters" msgid "Waiters"
msgstr "Warteliste" msgstr "Warteliste"
#: members/models.py:516 #: members/models.py:515
msgid "Waiting status confirmed" msgid "Waiting status confirmed"
msgstr "Wartelistenplatz bestätigt" msgstr "Wartelistenplatz bestätigt"
#: members/models.py:520 #: members/models.py:519
msgid "Waiting confirmation needed" msgid "Waiting confirmation needed"
msgstr "Wartelistenplatzbestätigung erforderlich" msgstr "Wartelistenplatzbestätigung erforderlich"
#: members/models.py:561 #: members/models.py:560
msgid "Good news" msgid "Good news"
msgstr "Gute Neuigkeiten" msgstr "Gute Neuigkeiten"
#: members/models.py:577 members/models.py:676 #: members/models.py:576 members/models.py:675
msgid "Place" msgid "Place"
msgstr "Ort" msgstr "Ort"
#: members/models.py:578 members/models.py:677 #: members/models.py:577 members/models.py:676
msgid "Destination (optional)" msgid "Destination (optional)"
msgstr "Ziel (optional)" msgstr "Ziel (optional)"
#: members/models.py:580 members/models.py:821 members/models.py:839 #: members/models.py:579 members/models.py:820 members/models.py:838
#: members/models.py:1100
msgid "Date" msgid "Date"
msgstr "Datum" msgstr "Datum"
#: members/models.py:581 members/models.py:680 #: members/models.py:580 members/models.py:679
msgid "End (optional)" msgid "End (optional)"
msgstr "Ende" msgstr "Ende"
#: members/models.py:583 members/models.py:682 #: members/models.py:582 members/models.py:681
msgid "Groups" msgid "Groups"
msgstr "Gruppen" msgstr "Gruppen"
#: members/models.py:591 members/models.py:698 #: members/models.py:590 members/models.py:697
msgid "Categories" msgid "Categories"
msgstr "Kategorien" msgstr "Kategorien"
#: members/models.py:592 members/models.py:699 #: members/models.py:591 members/models.py:698
msgid "easy" msgid "easy"
msgstr "leicht" msgstr "leicht"
#: members/models.py:592 members/models.py:699 #: members/models.py:591 members/models.py:698
msgid "medium" msgid "medium"
msgstr "mittel" msgstr "mittel"
#: members/models.py:592 members/models.py:699 #: members/models.py:591 members/models.py:698
msgid "hard" msgid "hard"
msgstr "schwer" msgstr "schwer"
#: members/models.py:601 #: members/models.py:600
msgid "Memberlist" msgid "Memberlist"
msgstr "Teilnehmerliste" msgstr "Teilnehmerliste"
#: members/models.py:602 #: members/models.py:601
msgid "Memberlists" msgid "Memberlists"
msgstr "Teilnehmerlisten" msgstr "Teilnehmerlisten"
#: members/models.py:620 members/models.py:628 members/models.py:636 #: members/models.py:619 members/models.py:627 members/models.py:635
#: members/models.py:647 members/models.py:874 members/models.py:881 #: members/models.py:646 members/models.py:873 members/models.py:880
msgid "Member" msgid "Member"
msgstr "Teilnehmer" msgstr "Teilnehmer"
#: members/models.py:622 members/models.py:641 #: members/models.py:621 members/models.py:640
msgid "Comment" msgid "Comment"
msgstr "Kommentar" msgstr "Kommentar"
#: members/models.py:629 members/models.py:648 members/models.py:882 #: members/models.py:628 members/models.py:647 members/models.py:881
msgid "Members" msgid "Members"
msgstr "Teilnehmer" msgstr "Teilnehmer"
#: members/models.py:679 #: members/models.py:678
msgid "Begin" msgid "Begin"
msgstr "Anfang" msgstr "Anfang"
#: members/models.py:695 #: members/models.py:694
msgid "Kilometers traveled" msgid "Kilometers traveled"
msgstr "Fahrstrecke in Kilometer" msgstr "Fahrstrecke in Kilometer"
#: members/models.py:820 members/models.py:896 #: members/models.py:819 members/models.py:895 members/models.py:1099
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
#: members/models.py:840 #: members/models.py:839
msgid "Location" msgid "Location"
msgstr "Ort" msgstr "Ort"
#: members/models.py:841 #: members/models.py:840
msgid "Topic" msgid "Topic"
msgstr "Thema" msgstr "Thema"
#: members/models.py:865 #: members/models.py:864
msgid "Jugendleiter" msgid "Jugendleiter"
msgstr "Jugendleiter" msgstr "Jugendleiter"
#: members/models.py:868 #: members/models.py:867
msgid "Klettertreff" msgid "Klettertreff"
msgstr "Klettertreff" msgstr "Klettertreff"
#: members/models.py:869 #: members/models.py:868
msgid "Klettertreffs" msgid "Klettertreffs"
msgstr "Klettertreffs" msgstr "Klettertreffs"
#: members/models.py:887 #: members/models.py:886
msgid "Password" msgid "Password"
msgstr "Passwort" msgstr "Passwort"
#: members/models.py:890 #: members/models.py:889
msgid "registration password" msgid "registration password"
msgstr "Registrierungspassort" msgstr "Registrierungspassort"
#: members/models.py:891 #: members/models.py:890
msgid "registration passwords" msgid "registration passwords"
msgstr "Registrierungspasswörter" msgstr "Registrierungspasswörter"
#: members/models.py:898 #: members/models.py:897
msgid "Alpinistic goals" msgid "Alpinistic goals"
msgstr "Alpintechnische Ziele" msgstr "Alpintechnische Ziele"
#: members/models.py:899 #: members/models.py:898
msgid "Pedagogic goals" msgid "Pedagogic goals"
msgstr "Pädagogische Ziele" msgstr "Pädagogische Ziele"
#: members/models.py:900 #: members/models.py:899
msgid "Content and methods" msgid "Content and methods"
msgstr "Inhalte und Methoden" msgstr "Inhalte und Methoden"
#: members/models.py:901 #: members/models.py:900
msgid "Evaluation" msgid "Evaluation"
msgstr "Wertung" msgstr "Wertung"
#: members/models.py:902 #: members/models.py:901
msgid "Experiences and possible improvements" msgid "Experiences and possible improvements"
msgstr "Erfahrungen und Verbesserungsvorschläge" msgstr "Erfahrungen und Verbesserungsvorschläge"
#: members/models.py:905 #: members/models.py:904
msgid "Excursion" msgid "Excursion"
msgstr "Freizeit" msgstr "Freizeit"
#: members/models.py:911 members/models.py:926 #: members/models.py:910 members/models.py:925
msgid "LJP Proposal" msgid "LJP Proposal"
msgstr "Seminarbericht" msgstr "Seminarbericht"
#: members/models.py:912 #: members/models.py:911
msgid "LJP Proposals" msgid "LJP Proposals"
msgstr "Seminarberichte" msgstr "Seminarberichte"
#: members/models.py:919 #: members/models.py:918
msgid "Starting time" msgid "Starting time"
msgstr "Zeitpunkt" msgstr "Zeitpunkt"
#: members/models.py:920 #: members/models.py:919
msgid "Duration in hours" msgid "Duration in hours"
msgstr "Dauer in Stunden" msgstr "Dauer in Stunden"
#: members/models.py:923 #: members/models.py:922
msgid "Activity and method" msgid "Activity and method"
msgstr "Art der Aktion inkl. Methode" msgstr "Art der Aktion inkl. Methode"
#: members/models.py:931 #: members/models.py:930
msgid "Intervention" msgid "Intervention"
msgstr "Aktion" msgstr "Aktion"
#: members/models.py:932 #: members/models.py:931
msgid "Interventions" msgid "Interventions"
msgstr "Aktionen" msgstr "Aktionen"
#: members/models.py:1028 members/models.py:1058 #: members/models.py:1027 members/models.py:1057
msgid "May list members" msgid "May list members"
msgstr "Darf folgende Teilnehmer:innen listen" msgstr "Darf folgende Teilnehmer:innen listen"
#: members/models.py:1030 members/models.py:1060 #: members/models.py:1029 members/models.py:1059
msgid "May view members" msgid "May view members"
msgstr "Darf folgende Teilnehmer:innen anzeigen" msgstr "Darf folgende Teilnehmer:innen anzeigen"
#: members/models.py:1032 members/models.py:1062 #: members/models.py:1031 members/models.py:1061
msgid "May change members" msgid "May change members"
msgstr "Darf folgende Teilnehmer:innen ändern" msgstr "Darf folgende Teilnehmer:innen ändern"
#: members/models.py:1034 members/models.py:1064 #: members/models.py:1033 members/models.py:1063
msgid "May delete members" msgid "May delete members"
msgstr "Darf folgende Teilnehmer:innen löschen" msgstr "Darf folgende Teilnehmer:innen löschen"
#: members/models.py:1038 members/models.py:1068 #: members/models.py:1037 members/models.py:1067
msgid "May list members of groups" msgid "May list members of groups"
msgstr "Darf Teilnehmer:innen folgender Gruppen listen" msgstr "Darf Teilnehmer:innen folgender Gruppen listen"
#: members/models.py:1040 members/models.py:1070 #: members/models.py:1039 members/models.py:1069
msgid "May view members of groups" msgid "May view members of groups"
msgstr "Darf Teilnehmer:innen folgender Gruppen anzeigen" msgstr "Darf Teilnehmer:innen folgender Gruppen anzeigen"
#: members/models.py:1042 members/models.py:1072 #: members/models.py:1041 members/models.py:1071
msgid "May change members of groups" msgid "May change members of groups"
msgstr "Darf Teilnehmer:innen folgender Gruppen ändern" msgstr "Darf Teilnehmer:innen folgender Gruppen ändern"
#: members/models.py:1044 members/models.py:1074 #: members/models.py:1043 members/models.py:1073
msgid "May delete members of groups" msgid "May delete members of groups"
msgstr "Darf Teilnehmer:innen folgender Gruppen löschen" msgstr "Darf Teilnehmer:innen folgender Gruppen löschen"
#: members/models.py:1047 members/models.py:1048 members/models.py:1051 #: members/models.py:1046 members/models.py:1047 members/models.py:1050
msgid "Permissions" msgid "Permissions"
msgstr "Berechtigungen" msgstr "Berechtigungen"
#: members/models.py:1077 members/models.py:1078 members/models.py:1081 #: members/models.py:1076 members/models.py:1077 members/models.py:1080
msgid "Group permissions" msgid "Group permissions"
msgstr "Gruppenberechtigungen" msgstr "Gruppenberechtigungen"
#: members/models.py:1086
msgid "Permission needed"
msgstr "Freigabe erforderlich"
#: members/models.py:1089
msgid "Training category"
msgstr "Fortbildungstyp"
#: members/models.py:1090
msgid "Training categories"
msgstr "Fortbildungstypen"
#: members/models.py:1101
msgid "Category"
msgstr "Kategorien"
#: members/models.py:1102
msgid "Comments"
msgstr "Kommentar"
#: members/models.py:1103
msgid "Participated"
msgstr "Teilgenommmen"
#: members/models.py:1104
msgid "Passed"
msgstr "Bestanden"
#: members/models.py:1107
msgid "Training"
msgstr "Fortbildung"
#: members/models.py:1108
msgid "Trainings"
msgstr "Fortbildungen"
#: members/templates/admin/invite_for_group.html:17 #: members/templates/admin/invite_for_group.html:17
#: members/templates/admin/invite_selected_for_group.html:17 #: members/templates/admin/invite_selected_for_group.html:17
msgid "Home" msgid "Home"

@ -0,0 +1,93 @@
# Generated by Django 4.0.1 on 2023-04-01 06:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('members', '0003_adapt_to_clubdesk_contact_fields'),
]
operations = [
migrations.CreateModel(
name='TrainingCategory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50, verbose_name='Name')),
('permission_needed', models.BooleanField(verbose_name='Permission needed')),
],
options={
'verbose_name': 'Training category',
'verbose_name_plural': 'Training categories',
},
),
migrations.AlterField(
model_name='member',
name='allergies',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Allergies'),
),
migrations.AlterField(
model_name='member',
name='climbing_badge',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Climbing badge'),
),
migrations.AlterField(
model_name='member',
name='dav_badge_no',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='DAV badge number'),
),
migrations.AlterField(
model_name='member',
name='legal_guardians',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Legal guardians'),
),
migrations.AlterField(
model_name='member',
name='medication',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='Medication'),
),
migrations.AlterField(
model_name='member',
name='rock_experience',
field=models.CharField(blank=True, default='', max_length=50, verbose_name='Rock experience'),
),
migrations.AlterField(
model_name='member',
name='swimming_badge',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='Swimming badge'),
),
migrations.AlterField(
model_name='member',
name='tetanus_vaccination',
field=models.CharField(blank=True, default='', max_length=50, verbose_name='Tetanus vaccination'),
),
migrations.AlterField(
model_name='member',
name='birth_date',
field=models.DateField(blank=True, null=True, verbose_name='birth date'),
),
migrations.CreateModel(
name='MemberTraining',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(blank=True, null=True, verbose_name='Date')),
('title', models.CharField(max_length=30, verbose_name='Title')),
('comments', models.TextField(blank=True, verbose_name='Comments')),
('participated', models.BooleanField(verbose_name='Participated')),
('passed', models.BooleanField(verbose_name='Passed')),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='traininigs', to='members.member')),
('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='members.trainingcategory', verbose_name='Category')),
],
options={
'verbose_name': 'Training',
'verbose_name_plural': 'Trainings',
},
),
migrations.AlterField(
model_name='memberwaitinglist',
name='birth_date',
field=models.DateField(blank=True, null=True, verbose_name='birth date'),
),
]

@ -80,7 +80,7 @@ class Person(models.Model):
verbose_name=_("Parents' Email")) verbose_name=_("Parents' Email"))
cc_email_parents = models.BooleanField(default=True, verbose_name=_('Also send mails to parents')) cc_email_parents = models.BooleanField(default=True, verbose_name=_('Also send mails to parents'))
birth_date = models.DateField(_('birth date'), null=True) # to determine the age birth_date = models.DateField(_('birth date'), null=True, blank=True) # to determine the age
comments = models.TextField(_('comments'), default='', blank=True) comments = models.TextField(_('comments'), default='', blank=True)
@ -173,15 +173,15 @@ class Member(Person):
civil_status = models.CharField(_('Civil status'), max_length=30, default='', blank=True) civil_status = models.CharField(_('Civil status'), max_length=30, default='', blank=True)
has_key = models.BooleanField(_('Has key'), default=False) has_key = models.BooleanField(_('Has key'), default=False)
has_free_ticket_gym = models.BooleanField(_('Has a free ticket for the climbing gym'), default=False) has_free_ticket_gym = models.BooleanField(_('Has a free ticket for the climbing gym'), default=False)
dav_badge_no = models.CharField(max_length=20, verbose_name=_('DAV badge number'), default='') dav_badge_no = models.CharField(max_length=20, verbose_name=_('DAV badge number'), default='', blank=True)
swimming_badge = models.CharField(max_length=20, verbose_name=_('Swimming badge'), default='') swimming_badge = models.CharField(max_length=20, verbose_name=_('Swimming badge'), default='', blank=True)
climbing_badge = models.CharField(max_length=100, verbose_name=_('Climbing badge'), default='') climbing_badge = models.CharField(max_length=100, verbose_name=_('Climbing badge'), default='', blank=True)
rock_experience = models.CharField(max_length=50, verbose_name=_('Rock experience'), default='') rock_experience = models.CharField(max_length=50, verbose_name=_('Rock experience'), default='', blank=True)
allergies = models.CharField(max_length=100, verbose_name=_('Allergies'), default='') allergies = models.CharField(max_length=100, verbose_name=_('Allergies'), default='', blank=True)
medication = models.CharField(max_length=100, verbose_name=_('Medication'), default='') medication = models.CharField(max_length=100, verbose_name=_('Medication'), default='', blank=True)
tetanus_vaccination = models.CharField(max_length=50, verbose_name=_('Tetanus vaccination'), default='') tetanus_vaccination = models.CharField(max_length=50, verbose_name=_('Tetanus vaccination'), default='', blank=True)
photos_may_be_taken = models.BooleanField(verbose_name=_('Photos may be taken'), default=False) photos_may_be_taken = models.BooleanField(verbose_name=_('Photos may be taken'), default=False)
legal_guardians = models.CharField(max_length=100, verbose_name=_('Legal guardians'), default='') legal_guardians = models.CharField(max_length=100, verbose_name=_('Legal guardians'), default='', blank=True)
phone_number_private = models.CharField(max_length=100, verbose_name=_('phone number private'), default='', blank=True) phone_number_private = models.CharField(max_length=100, verbose_name=_('phone number private'), default='', blank=True)
phone_number_mobile = models.CharField(max_length=100, verbose_name=_('phone number mobile'), default='', blank=True) phone_number_mobile = models.CharField(max_length=100, verbose_name=_('phone number mobile'), default='', blank=True)
@ -493,7 +493,6 @@ class MemberWaitingList(Person):
default=None, default=None,
verbose_name=_('Invited for group'), verbose_name=_('Invited for group'),
on_delete=models.SET_NULL) on_delete=models.SET_NULL)
class Meta: class Meta:
verbose_name = _('Waiter') verbose_name = _('Waiter')
verbose_name_plural = _('Waiters') verbose_name_plural = _('Waiters')
@ -1081,6 +1080,34 @@ class PermissionGroup(models.Model):
return str(_('Group permissions')) return str(_('Group permissions'))
class TrainingCategory(models.Model):
"""Represents a type of training, e.g. Grundausbildung, Fortbildung, Aufbaumodul, etc."""
name = models.CharField(verbose_name=_('Name'), max_length=50)
permission_needed = models.BooleanField(verbose_name=_('Permission needed'))
class Meta:
verbose_name = _('Training category')
verbose_name_plural = _('Training categories')
def __str__(self):
return self.name
class MemberTraining(models.Model):
"""Represents a training planned or attended by a member."""
member = models.ForeignKey(Member, on_delete=models.CASCADE, related_name='traininigs')
title = models.CharField(verbose_name=_('Title'), max_length=30)
date = models.DateField(verbose_name=_('Date'), null=True, blank=True)
category = models.ForeignKey(TrainingCategory, on_delete=models.PROTECT, verbose_name=_('Category'))
comments = models.TextField(verbose_name=_('Comments'), blank=True)
participated = models.BooleanField(verbose_name=_('Participated'))
passed = models.BooleanField(verbose_name=_('Passed'))
class Meta:
verbose_name = _('Training')
verbose_name_plural = _('Trainings')
def import_from_csv(path): def import_from_csv(path):
with open(path, encoding='ISO-8859-1') as csvfile: with open(path, encoding='ISO-8859-1') as csvfile:
reader = csv.DictReader(csvfile, delimiter=';') reader = csv.DictReader(csvfile, delimiter=';')
@ -1095,11 +1122,41 @@ def import_from_csv(path):
def transform_row(row): def transform_row(row):
kwargs = dict([ transform_field(k, v) for k, v in row.items() if k in CLUBDESK_TO_KOMPASS ]) kwargs = dict([ transform_field(k, v) for k, v in row.items() if k in CLUBDESK_TO_KOMPASS ])
kwargs_without_group = { k : v for k, v in kwargs.items() if k != 'group' } kwargs_filtered = { k : v for k, v in kwargs.items() if k not in ['group', 'last_training', 'has_fundamental_training', 'special_training'] }
mem = Member(**kwargs_without_group) mem = Member(**kwargs_filtered)
mem.save() mem.save()
mem.group.set(kwargs['group']) mem.group.set(kwargs['group'])
if kwargs['has_fundamental_training']:
try:
ga_cat = TrainingCategory.objects.get(name='Grundausbildung')
except TrainingCategory.DoesNotExist:
ga_cat = TrainingCategory(name='Grundausbildung', permission_needed=True)
ga_cat.save()
ga_training = MemberTraining(member=mem, title='Grundausbildung', date=None, category=ga_cat,
participated=True, passed=True)
ga_training.save()
if kwargs['last_training'] is not None:
try:
cat = TrainingCategory.objects.get(name='Fortbildung')
except TrainingCategory.DoesNotExist:
cat = TrainingCategory(name='Fortbildung', permission_needed=False)
cat.save()
training = MemberTraining(member=mem, title='Unbekannt', date=kwargs['last_training'], category=cat,
participated=True, passed=True)
training.save()
if kwargs['special_training'] != '':
try:
cat = TrainingCategory.objects.get(name='Sonstiges')
except TrainingCategory.DoesNotExist:
cat = TrainingCategory(name='Sonstiges', permission_needed=False)
cat.save()
training = MemberTraining(member=mem, title=kwargs['special_training'], date=None, category=cat,
participated=True, passed=True)
training.save()
for row in rows: for row in rows:
transform_row(row) transform_row(row)
@ -1155,9 +1212,9 @@ CLUBDESK_TO_KOMPASS = {
'IBAN': 'iban', 'IBAN': 'iban',
'Vorlage Führungszeugnis': ('good_conduct_certificate_presented_date', parse_date), 'Vorlage Führungszeugnis': ('good_conduct_certificate_presented_date', parse_date),
'Vorlage Führungszeugnis notwendig': ('good_conduct_certificate_presentation_needed', parse_boolean), 'Vorlage Führungszeugnis notwendig': ('good_conduct_certificate_presentation_needed', parse_boolean),
# 'Letzte Fortbildung': '', 'Letzte Fortbildung': ('last_training', parse_date),
# 'Grundausbildung': '', 'Grundausbildung': ('has_fundamental_training', parse_boolean),
# 'Besondere Ausbildung': '', 'Besondere Ausbildung': 'special_training',
'[Gruppen]' : ('group', parse_group), '[Gruppen]' : ('group', parse_group),
'Schlüssel': ('has_key', parse_boolean), 'Schlüssel': ('has_key', parse_boolean),
'Freikarte': ('has_free_ticket_gym', parse_boolean), 'Freikarte': ('has_free_ticket_gym', parse_boolean),

Loading…
Cancel
Save