feat(members/excursion): add basic approval status

pull/136/head
Christian Merten 10 months ago
parent 9d1351197a
commit 7cae13fc1d
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -1066,10 +1066,10 @@ def decorate_download(fun):
class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin):
#inlines = [MemberOnListInline, LJPOnListInline, StatementOnListInline] #inlines = [MemberOnListInline, LJPOnListInline, StatementOnListInline]
form = FreizeitAdminForm form = FreizeitAdminForm
list_display = ['__str__', 'date', 'place'] list_display = ['__str__', 'date', 'place', 'approved']
search_fields = ('name',) search_fields = ('name',)
ordering = ('-date',) ordering = ('-date',)
list_filter = ['groups'] list_filter = ['groups', 'approved']
view_on_site = False view_on_site = False
fieldsets = ( fieldsets = (
(None, { (None, {
@ -1078,11 +1078,24 @@ class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin):
'tour_type', 'tour_approach', 'kilometers_traveled', 'activity', 'difficulty'), 'tour_type', 'tour_approach', 'kilometers_traveled', 'activity', 'difficulty'),
'description': _('General information on your excursion. These are partly relevant for the amount of financial compensation (means of transport, travel distance, etc.).') 'description': _('General information on your excursion. These are partly relevant for the amount of financial compensation (means of transport, travel distance, etc.).')
}), }),
(_('Approval'), {
'fields': ('approved', 'approval_comments'),
'description': _('Information on the approval status of this excursion. Everything here is not editable by standard users.')
}),
) )
#formfield_overrides = { #formfield_overrides = {
# ManyToManyField: {'widget': forms.CheckboxSelectMultiple}, # ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
# ForeignKey: {'widget': apply_select2(forms.Select)} # ForeignKey: {'widget': apply_select2(forms.Select)}
#} #}
field_view_permissions = {
'approved': 'members.view_approval_excursion',
'approval_comments': 'members.view_approval_excursion',
}
field_change_permissions = {
'approved': 'members.manage_approval_excursion',
'approval_comments': 'members.manage_approval_excursion',
}
def get_inlines(self, request, obj=None): def get_inlines(self, request, obj=None):
if obj: if obj:

@ -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: 2025-02-06 00:32+0100\n" "POT-Creation-Date: 2025-02-08 00:12+0100\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"
@ -339,11 +339,11 @@ msgstr "Übersicht erstellen"
msgid "Invoice" msgid "Invoice"
msgstr "Beleg" msgstr "Beleg"
#: members/admin.py #: members/admin.py members/tests.py
msgid "Excursion not found." msgid "Excursion not found."
msgstr "Ausfahrt nicht gefunden." msgstr "Ausfahrt nicht gefunden."
#: members/admin.py #: members/admin.py members/tests.py
msgid "" msgid ""
"This excursion does not have a LJP proposal. Please add one and try again." "This excursion does not have a LJP proposal. Please add one and try again."
msgstr "" msgstr ""
@ -360,6 +360,19 @@ msgstr ""
"Fahrstrecke in km)." "Fahrstrecke in km)."
#: members/admin.py #: members/admin.py
msgid "Approval"
msgstr "Genehmigung"
#: members/admin.py
msgid ""
"Information on the approval status of this excursion. Everything here is not "
"editable by standard users."
msgstr ""
"Informationen zum Genehmigungszustand der Ausfahrt. Die Felder hier sind "
"nicht sichtbar für Standardbenutzer*innen, nur der Genehmigungszustand wird "
"in der Übersicht alle Ausfahrten angezeigt."
#: members/admin.py members/tests.py
#, 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 ""
@ -885,6 +898,22 @@ msgstr "mittel"
msgid "hard" msgid "hard"
msgstr "schwer" msgstr "schwer"
#: members/models.py
msgid "Approved"
msgstr "Genehmigt"
#: members/models.py
msgid ""
"Choose no in case of rejection or yes in case of approval. Leave empty, if "
"not yet decided."
msgstr ""
"Wähle Ja bei Genehmigung, Nein bei Ablehung und Unbekannt, falls noch keine "
"Entscheidung getroffen wurde."
#: members/models.py
msgid "Approval comments"
msgstr "Kommentare oder Auflagen zur Genehmigung"
#: members/models.py members/templates/admin/freizeit_finance_overview.html #: members/models.py members/templates/admin/freizeit_finance_overview.html
msgid "Excursion" msgid "Excursion"
msgstr "Ausfahrt" msgstr "Ausfahrt"
@ -1401,7 +1430,7 @@ msgstr ""
"notwendig. Aus den Informationen, die du in der Ausfahrt angegeben hast, " "notwendig. Aus den Informationen, die du in der Ausfahrt angegeben hast, "
"kann automatisch ein solcher Antrag erstellt werden." "kann automatisch ein solcher Antrag erstellt werden."
#: members/templates/admin/generate_seminar_report.html #: members/templates/admin/generate_seminar_report.html members/tests.py
msgid "A seminar report consists of multiple components:" msgid "A seminar report consists of multiple components:"
msgstr "Ein LJP Antrag besteht aus verschiedenen Komponenten:" msgstr "Ein LJP Antrag besteht aus verschiedenen Komponenten:"
@ -1979,25 +2008,6 @@ msgstr ""
"Danke %(prename)s für dein Interesse auf der Warteliste zu bleiben.\n" "Danke %(prename)s für dein Interesse auf der Warteliste zu bleiben.\n"
"Dein Platz wurde bestätigt." "Dein Platz wurde bestätigt."
#: members/tests.py
msgid "You may also choose to include the V32 attachment."
msgstr ""
"Ein LJP Antrag benötigt immer ein Formblatt (in unserem Fall V32-1 "
"Themenorientierte Bildungsmaßnahmen). Dieses kannst du automatisch "
"vorausfüllen lassen und dem Antrag hinzufügen. Bitte fülle die verbleibenden "
"Felder im Formblatt selbst aus und unterschreibe das PDF."
#: members/tests.py
msgid "Please select a mode."
msgstr "Bitte wähle einen Modus aus."
#: members/tests.py
msgid ""
"Full mode is only available, if the seminar report section is filled out."
msgstr ""
"Der vollständiger Modus ist nur verfügbar, wenn der Seminarbericht "
"ausgefüllt ist. "
#: members/tests.py #: members/tests.py
msgid "This field is required." msgid "This field is required."
msgstr "" msgstr ""
@ -2040,6 +2050,22 @@ msgstr "Optionale zusätzliche E-Mailadresse"
msgid "Invalid emergency contacts" msgid "Invalid emergency contacts"
msgstr "Ungültige Notfallkontakte" msgstr "Ungültige Notfallkontakte"
#~ msgid "You may also choose to include the V32 attachment."
#~ msgstr ""
#~ "Ein LJP Antrag benötigt immer ein Formblatt (in unserem Fall V32-1 "
#~ "Themenorientierte Bildungsmaßnahmen). Dieses kannst du automatisch "
#~ "vorausfüllen lassen und dem Antrag hinzufügen. Bitte fülle die "
#~ "verbleibenden Felder im Formblatt selbst aus und unterschreibe das PDF."
#~ msgid "Please select a mode."
#~ msgstr "Bitte wähle einen Modus aus."
#~ msgid ""
#~ "Full mode is only available, if the seminar report section is filled out."
#~ msgstr ""
#~ "Der vollständiger Modus ist nur verfügbar, wenn der Seminarbericht "
#~ "ausgefüllt ist. "
#~ msgid "Generate LJP V-BK form" #~ msgid "Generate LJP V-BK form"
#~ msgstr "Erzeuge LJP V-BK Formular" #~ msgstr "Erzeuge LJP V-BK Formular"

@ -0,0 +1,27 @@
# Generated by Django 4.0.1 on 2025-02-07 23:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('members', '0035_ljp_application_rework'),
]
operations = [
migrations.AddField(
model_name='freizeit',
name='approval_comments',
field=models.TextField(blank=True, default='', verbose_name='Approval comments'),
),
migrations.AddField(
model_name='freizeit',
name='approved',
field=models.BooleanField(default=None, help_text='Choose no in case of rejection or yes in case of approval. Leave empty, if not yet decided.', null=True, verbose_name='Approved'),
),
migrations.AlterModelOptions(
name='freizeit',
options={'default_permissions': ('add_global', 'change_global', 'view_global', 'delete_global', 'list_global', 'view'), 'permissions': (('manage_approval_excursion', 'Can edit the approval status of excursions.'), ('view_approval_excursion', 'Can view the approval status of excursions.')), 'verbose_name': 'Excursion', 'verbose_name_plural': 'Excursions'},
),
]

@ -1091,6 +1091,14 @@ class Freizeit(CommonModel):
difficulty = models.IntegerField(choices=difficulty_choices) difficulty = models.IntegerField(choices=difficulty_choices)
membersonlist = GenericRelation(NewMemberOnList) membersonlist = GenericRelation(NewMemberOnList)
# approval: None means no decision taken, False means rejected
approved = models.BooleanField(verbose_name=_('Approved'),
null=True,
default=None,
help_text=_('Choose no in case of rejection or yes in case of approval. Leave empty, if not yet decided.'))
approval_comments = models.TextField(verbose_name=_('Approval comments'),
blank=True, default='')
def __str__(self): def __str__(self):
"""String represenation""" """String represenation"""
return self.name return self.name
@ -1098,6 +1106,10 @@ class Freizeit(CommonModel):
class Meta(CommonModel.Meta): class Meta(CommonModel.Meta):
verbose_name = _('Excursion') verbose_name = _('Excursion')
verbose_name_plural = _('Excursions') verbose_name_plural = _('Excursions')
permissions = (
('manage_approval_excursion', 'Can edit the approval status of excursions.'),
('view_approval_excursion', 'Can view the approval status of excursions.'),
)
rules_permissions = { rules_permissions = {
'add_obj': has_global_perm('members.add_global_freizeit'), 'add_obj': has_global_perm('members.add_global_freizeit'),
'view_obj': is_leader | has_global_perm('members.view_global_freizeit'), 'view_obj': is_leader | has_global_perm('members.view_global_freizeit'),

Loading…
Cancel
Save