From 9f7b7a951787d7b5f8c6ff97cb64f88de3afee55 Mon Sep 17 00:00:00 2001
From: Christian Merten
Date: Sat, 20 Sep 2025 00:19:40 +0200
Subject: [PATCH] feat(members/admin): button to (re)request registration form
---
jdav_web/contrib/admin.py | 20 ++
jdav_web/members/admin.py | 19 +-
.../members/locale/de/LC_MESSAGES/django.po | 193 +++++++++++-------
jdav_web/members/models.py | 5 +
.../admin/request_registration_form.html | 40 ++++
.../admin/request_registratoin_form.html | 48 +++++
jdav_web/members/tests/basic.py | 22 ++
jdav_web/members/views.py | 3 +-
.../change_form_object_tools.html | 5 +
9 files changed, 273 insertions(+), 82 deletions(-)
create mode 100644 jdav_web/members/templates/admin/request_registration_form.html
create mode 100644 jdav_web/members/templates/admin/request_registratoin_form.html
diff --git a/jdav_web/contrib/admin.py b/jdav_web/contrib/admin.py
index 4346029..96a3838 100644
--- a/jdav_web/contrib/admin.py
+++ b/jdav_web/contrib/admin.py
@@ -12,6 +12,26 @@ import rules.contrib.admin
from rules.permissions import perm_exists
+def decorate_admin_view(model, perm=None):
+ """
+ Decorator for wrapping admin views.
+ """
+ def decorator(fun):
+ def aux(self, request, object_id):
+ try:
+ obj = model.objects.get(pk=object_id)
+ except model.DoesNotExist:
+ messages.error(request, _('%(modelname)s not found.') % {'modelname': self.opts.verbose_name})
+ return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name)))
+ permitted = self.has_change_permission(request, obj) if not perm else request.user.has_perm(perm)
+ if not permitted:
+ messages.error(request, _('Insufficient permissions.'))
+ return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name)))
+ return fun(self, request, obj)
+ return aux
+ return decorator
+
+
class FieldPermissionsAdminMixin:
field_change_permissions = {}
field_view_permissions = {}
diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py
index ae42295..3c290c0 100644
--- a/jdav_web/members/admin.py
+++ b/jdav_web/members/admin.py
@@ -32,7 +32,7 @@ from .pdf import render_tex, fill_pdf_form, merge_pdfs, serve_pdf, render_docx
from .excel import generate_group_overview, generate_ljp_vbk
from .models import WEEKDAYS
-from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin
+from contrib.admin import CommonAdminInlineMixin, CommonAdminMixin, decorate_admin_view
import nested_admin
@@ -513,6 +513,11 @@ class MemberUnconfirmedAdmin(CommonAdminMixin, admin.ModelAdmin):
wrap(self.demote_to_waiter_view),
name="%s_%s_demote" % (self.opts.app_label, self.opts.model_name),
),
+ path(
+ "/request_registration_form/",
+ wrap(self.request_registration_form_view),
+ name="%s_%s_request_registration_form" % (self.opts.app_label, self.opts.model_name),
+ ),
]
return custom_urls + urls
@@ -545,6 +550,18 @@ class MemberUnconfirmedAdmin(CommonAdminMixin, admin.ModelAdmin):
member.demote_to_waiter()
messages.success(request, _("Successfully demoted %(name)s to waiter.") % {'name': member.name})
+ @decorate_admin_view(MemberUnconfirmedProxy)
+ def request_registration_form_view(self, request, member):
+ if "apply" in request.POST:
+ member.request_registration_form()
+ messages.success(request, _("Requested registration form for %(name)s.") % {'name': member.name})
+ return HttpResponseRedirect(reverse('admin:members_memberunconfirmedproxy_change', args=(member.pk,)))
+ context = dict(self.admin_site.each_context(request),
+ title=_('Request upload registration form'),
+ opts=self.opts,
+ member=member)
+ return render(request, 'admin/request_registration_form.html', context=context)
+
def response_change(self, request, member):
if "_confirm" in request.POST:
if member.confirm():
diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po
index d231df7..6f709e8 100644
--- a/jdav_web/members/locale/de/LC_MESSAGES/django.po
+++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-07-25 18:44+0200\n"
+"POT-Creation-Date: 2025-09-19 21:35+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -18,22 +18,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: members/admin.py members/models.py
-msgid "Registration complete"
-msgstr "Anmeldung vollständig"
-
-#: members/admin.py
-msgid "True"
-msgstr "Ja"
-
-#: members/admin.py
-msgid "False"
-msgstr "Nein"
-
-#: members/admin.py members/tests.py
-msgid "All"
-msgstr "Alle"
-
#: members/admin.py
msgid "The entered IBAN is not valid."
msgstr "Die eingegebene IBAN ist ungültig."
@@ -82,18 +66,18 @@ msgstr "%(name)s hat keine DAV360 E-Mail Adresse oder ist bereits registriert."
msgid "Successfully invited %(name)s as user."
msgstr "Erfolgreich %(name)s aufgefordert Zugangsdaten zu wählen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Successfully invited selected members to join as users."
msgstr ""
"Erfolgreich ausgewählte Teilnehmer*innen aufgefordert Zugangsdaten zu wählen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Some members have been invited, others could not be invited."
msgstr ""
"Manche Teilnehmer*innen wurden eingeladen, andere konnten nicht eingeladen "
"werden."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Permission denied."
msgstr "Fehlende Berechtigungen."
@@ -105,21 +89,21 @@ msgstr "Kompass Zugangsdaten wählen lassen"
msgid "Invite selected members to join Kompass as users."
msgstr "Ausgewählte Teilnehmer*innen Kompass Zugangsdaten wählen lassen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Member not found."
msgstr "Teilnehmer*in nicht gefunden."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
#, python-format
msgid "%(name)s already has login data."
msgstr "%(name)s hat schon Zugangsdaten."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
#, python-format
msgid "The configured email address for %(name)s is not an internal one."
msgstr "Die für %(name)s eingestellte E-Mail Adresse ist keine DAV360 Adresse."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
#, python-format
msgid "%(name)s already has a pending invitation as user."
msgstr ""
@@ -143,7 +127,7 @@ msgid "Unconfirm selected members."
msgstr ""
"Ausgewählte Teilnehmer*innen zu unbestätigten Registrierungen zurücksetzen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Successfully requested mail confirmation from selected registrations."
msgstr "Aufforderung zur Bestätigung der Email Adresse versendet."
@@ -151,7 +135,7 @@ msgstr "Aufforderung zur Bestätigung der Email Adresse versendet."
msgid "Request mail confirmation from selected registrations"
msgstr "Aufforderung zur Bestätigung der Email Adresse versenden"
-#: members/admin.py
+#: members/admin.py members/tests/basic.py
msgid ""
"Successfully re-requested missing mail confirmations from selected "
"registrations."
@@ -175,11 +159,11 @@ msgstr "Registrierung von %(name)s erfolgreich bestätigt."
msgid "Can't confirm. %(name)s has unconfirmed email addresses."
msgstr "Bestätigung nicht möglich. %(name)s hat unbestätigte Emailadressen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Successfully confirmed multiple registrations."
msgstr "Erfolgreich mehrere Registrierungen bestätigt."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid ""
"Failed to confirm some registrations because of unconfirmed email addresses."
msgstr ""
@@ -194,7 +178,7 @@ msgstr "Ausgewählte Registrierungen bestätigen"
msgid "Demote selected registrations to waiters."
msgstr "Ausgewählte Registrierungen zurück auf die Warteliste setzen."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Demote member to waiter"
msgstr "Ausgewählte Registrierung zurück auf die Warteliste setzen."
@@ -203,6 +187,15 @@ msgstr "Ausgewählte Registrierung zurück auf die Warteliste setzen."
msgid "Successfully demoted %(name)s to waiter."
msgstr "%(name)s zurück auf die Warteliste gesetzt."
+#: members/admin.py
+#, python-format
+msgid "Requested registration form for %(name)s."
+msgstr "Anmeldeformular für %(name)s angefragt."
+
+#: members/admin.py
+msgid "Request upload registration form"
+msgstr "Anmeldeformular anfragen"
+
#: members/admin.py members/models.py
msgid "Group"
msgstr "Gruppe"
@@ -257,7 +250,7 @@ msgstr ""
msgid "Offer waiter a place in a group."
msgstr "Personen auf der Warteliste einen Gruppenplatz anbieten."
-#: members/admin.py
+#: members/admin.py members/tests/basic.py
msgid "A waiter with this ID does not exist."
msgstr "Es existiert keine wartende Person mit dieser ID."
@@ -379,11 +372,11 @@ msgstr "Übersicht erstellen"
msgid "Invoice"
msgstr "Beleg"
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Excursion not found."
msgstr "Ausfahrt nicht gefunden."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid ""
"This excursion does not have a LJP proposal. Please add one and try again."
msgstr ""
@@ -412,7 +405,7 @@ msgstr ""
"nicht sichtbar für Standardbenutzer*innen, nur der Genehmigungszustand wird "
"in der Übersicht alle Ausfahrten angezeigt."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
#, python-format
msgid "You are not allowed to view all members on excursion %(name)s."
msgstr ""
@@ -435,17 +428,17 @@ msgstr "Landesjugendplan Antrag erstellen"
msgid "Generate SJR application"
msgstr "SJR Antrag erstellen"
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "Please select an invoice."
msgstr "Bitte wähle einen Beleg aus."
-#: members/admin.py members/tests.py
+#: members/admin.py members/tests/basic.py
msgid "No statement found. Please add a statement and then retry."
msgstr ""
"Keine Abrechnung angelegt. Bitte lege eine Abrechnung and und versuche es "
"erneut."
-#: members/admin.py
+#: members/admin.py members/tests/basic.py
msgid ""
"The configured recipients of the allowance don't match the regulations. "
"Please correct this and try again."
@@ -453,7 +446,7 @@ msgstr ""
"Die ausgewählten Empfänger*innen der Aufwandsentschädigung stimmen nicht mit "
"den Richtlinien überein. Bitte korrigiere das und versuche es erneut. "
-#: members/admin.py
+#: members/admin.py members/tests/basic.py
msgid ""
"The excursion is configured to claim LJP contributions. In that case, for "
"all bills, a proof must be uploaded. Please correct this and try again."
@@ -474,15 +467,6 @@ msgstr ""
msgid "Finance overview"
msgstr "Kostenübersicht"
-#: members/admin.py
-msgid "Inform youth leaders about sending of crisis intervention list."
-msgstr ""
-"Informiere Jugendleiter:innen über Versand der Kriseninterventionsliste."
-
-#: members/admin.py
-msgid "Send crisis intervention list."
-msgstr "Kriseninterventionsliste verschicken"
-
#: members/apps.py
msgid "member administration"
msgstr "Teilnehmer*innenverwaltung"
@@ -781,6 +765,10 @@ msgstr ""
msgid "Good conduct certificate valid"
msgstr "Führungszeugnis gültig"
+#: members/models.py
+msgid "Registration complete"
+msgstr "Anmeldung vollständig"
+
#: members/models.py
msgid "member"
msgstr "Teilnehmer*in"
@@ -846,15 +834,15 @@ msgstr "Gruppeneinladung"
msgid "Invitations to groups"
msgstr "Gruppeneinladungen"
-#: members/models.py
+#: members/models.py members/tests/basic.py
msgid "Rejected"
msgstr "Abgelehnt"
-#: members/models.py
+#: members/models.py members/tests/basic.py
msgid "Expired"
msgstr "Abgelaufen"
-#: members/models.py
+#: members/models.py members/tests/basic.py
msgid "Undecided"
msgstr "Ausstehend"
@@ -1021,6 +1009,7 @@ msgid "Excursions"
msgstr "Ausfahrten"
#: members/models.py
+#, python-format
msgid "Crisis intervention list for %(excursion)s from %(start)s to %(end)s"
msgstr "Kriseninterventionsliste für %(excursion)s vom %(start)s bis %(end)s"
@@ -1213,11 +1202,11 @@ msgstr "Darf Teilnehmer*innen folgender Gruppen ändern"
msgid "May delete members of groups"
msgstr "Darf Teilnehmer*innen folgender Gruppen löschen"
-#: members/models.py
+#: members/models.py members/tests/basic.py
msgid "Permissions"
msgstr "Berechtigungen"
-#: members/models.py
+#: members/models.py members/tests/basic.py
msgid "Group permissions"
msgstr "Gruppenberechtigungen"
@@ -1266,19 +1255,25 @@ msgstr "Fortbildungen"
#: members/templates/admin/invite_for_group_text.html
#: members/templates/admin/invite_selected_as_user.html
#: members/templates/admin/invite_selected_for_group.html
+#: members/templates/admin/request_registration_form.html
+#: members/templates/admin/request_registratoin_form.html
msgid "Home"
msgstr "Start"
#: members/templates/admin/demote_to_waiter.html
+#: members/templates/admin/request_registration_form.html
+#: members/templates/admin/request_registratoin_form.html
msgid "Demote to waiter"
msgstr "Zurück auf die Warteliste setzen"
#: members/templates/admin/demote_to_waiter.html
+#: members/templates/admin/request_registratoin_form.html
msgid ""
"Do you want to demote the following unconfirmed registrations to waiters?"
msgstr "Möchtest du die folgenden Personen zurück auf die Warteliste setzen?"
#: members/templates/admin/demote_to_waiter.html
+#: members/templates/admin/request_registratoin_form.html
msgid "Demote"
msgstr "Zurück auf die Warteliste setzen"
@@ -1289,6 +1284,8 @@ msgstr "Zurück auf die Warteliste setzen"
#: members/templates/admin/invite_for_group.html
#: members/templates/admin/invite_selected_as_user.html
#: members/templates/admin/invite_selected_for_group.html
+#: members/templates/admin/request_registration_form.html
+#: members/templates/admin/request_registratoin_form.html
msgid "Cancel"
msgstr "Abbrechen"
@@ -1515,7 +1512,8 @@ msgstr ""
msgid "Summary"
msgstr "Zusammenfassung"
-#: members/templates/admin/freizeit_finance_overview.html members/tests.py
+#: members/templates/admin/freizeit_finance_overview.html
+#: members/tests/basic.py
msgid "This is the estimated cost and contribution summary:"
msgstr "Das ist die geschätzte Kosten- und Zuschussübersicht."
@@ -1611,7 +1609,7 @@ msgstr ""
"notwendig. Aus den Informationen, die du in der Ausfahrt angegeben hast, "
"kann automatisch ein solcher Antrag erstellt werden."
-#: members/templates/admin/generate_seminar_report.html members/tests.py
+#: members/templates/admin/generate_seminar_report.html members/tests/basic.py
msgid "A seminar report consists of multiple components:"
msgstr "Ein LJP Antrag besteht aus verschiedenen Komponenten:"
@@ -1646,7 +1644,7 @@ msgstr ""
"Eine Kosten- und Teilnehmendenübersicht. Dies ist nicht notwendig für den "
"eigentlichen Bericht, muss aber langfristig aufbewahrt werden."
-#: members/templates/admin/generate_sjr_application.html members/tests.py
+#: members/templates/admin/generate_sjr_application.html members/tests/basic.py
msgid "Here you can generate an allowance application for the SJR."
msgstr "Hier kannst du einen SJR-Zuschussantrag erstellen."
@@ -1683,7 +1681,8 @@ msgstr ""
#: members/templates/admin/invite_as_user.html
#: members/templates/admin/invite_for_group.html
#: members/templates/admin/invite_selected_as_user.html
-#: members/templates/admin/invite_selected_for_group.html members/tests.py
+#: members/templates/admin/invite_selected_for_group.html
+#: members/tests/basic.py
msgid "Invite"
msgstr "Einladen"
@@ -1794,6 +1793,18 @@ msgstr "Anzahl Personen:"
msgid "thereof leaders:"
msgstr "davon Leitung:"
+#: members/templates/admin/request_registration_form.html
+msgid "Request registration form"
+msgstr "Anmeldeformular anfragen"
+
+#: members/templates/admin/request_registration_form.html
+msgid "Do you want to ask %(member)s to upload their registration form?"
+msgstr "Möchtest du %(member)s auffordern das Anmeldeformular hochzuladen?"
+
+#: members/templates/admin/request_registration_form.html
+msgid "Warning: %(member)s has already uploaded a registration form."
+msgstr "Warnung: %(member)s hat bereits ein Anmeldeformular hochgeladen."
+
#: members/templates/members/change_member.html
msgid "Participations:"
msgstr "Ausfahrtteilnahmen:"
@@ -1815,11 +1826,12 @@ msgid "Confirm invitation"
msgstr "Teilnahme bestätigen"
#: members/templates/members/confirm_invalid.html
-#: members/templates/members/reject_invalid.html members/tests.py
+#: members/templates/members/reject_invalid.html members/tests/basic.py
+#: members/tests/views.py
msgid "This invitation is invalid or expired."
msgstr "Diese Einladung ist ungültig oder abgelaufen."
-#: members/templates/members/confirm_invitation.html
+#: members/templates/members/confirm_invitation.html members/tests/views.py
msgid "Confirm trial group meeting invitation"
msgstr "Teilnahme bestätigen"
@@ -1841,7 +1853,7 @@ msgstr ""
msgid "Confirm trial group meeting"
msgstr "Teilnahme bestätigen"
-#: members/templates/members/confirm_success.html
+#: members/templates/members/confirm_success.html members/tests/views.py
msgid "Invitation confirmed"
msgstr "Teilnahme bestätigt"
@@ -1874,7 +1886,7 @@ msgstr ""
msgid "Echo"
msgstr "Rückmeldung"
-#: members/templates/members/echo.html members/tests.py
+#: members/templates/members/echo.html members/tests/basic.py
msgid ""
"Here is your current data. Please check if it is up to date and change "
"accordingly."
@@ -1882,7 +1894,7 @@ msgstr ""
"Hier siehst du deine aktuellen Daten. Bitte überprüfe alles und passe es bei "
"Bedarf an."
-#: members/templates/members/echo_failed.html members/tests.py
+#: members/templates/members/echo_failed.html members/tests/basic.py
msgid "Echo failed"
msgstr "Rückmeldung fehlgeschlagen"
@@ -1903,7 +1915,7 @@ msgstr "Wenn du denkst, dass das ein Fehler ist, "
msgid "contact us."
msgstr "kontaktiere uns."
-#: members/templates/members/echo_password.html members/tests.py
+#: members/templates/members/echo_password.html members/tests/basic.py
msgid ""
"Thanks for echoing back. Please enter the password, which you can find in "
"the email we sent you.\n"
@@ -1925,7 +1937,7 @@ msgstr "Rückmeldung erfolgreich"
msgid "Thank you"
msgstr "Danke"
-#: members/templates/members/echo_success.html members/tests.py
+#: members/templates/members/echo_success.html members/tests/basic.py
msgid "Your data was successfully updated."
msgstr "Deine Daten wurden erfolgreich aktualisiert."
@@ -1936,7 +1948,7 @@ msgstr ""
"Jugendleiter nach einem korrekten Passwort."
#: members/templates/members/invited_registration_failed.html
-#: members/templates/members/register_failed.html
+#: members/templates/members/register_failed.html members/tests/basic.py
msgid "Registration failed"
msgstr "Registrierung fehlgeschlagen"
@@ -1952,7 +1964,7 @@ msgstr "Registrierung fehlgeschlagen"
msgid "Registration"
msgstr "Registrierung"
-#: members/templates/members/leave_waitinglist.html members/tests.py
+#: members/templates/members/leave_waitinglist.html members/tests/basic.py
msgid "Leave waitinglist"
msgstr "Warteliste verlassen"
@@ -1969,7 +1981,8 @@ msgstr ""
msgid "Yes, leave the waitinglist"
msgstr "Ja, Warteliste verlassen"
-#: members/templates/members/leave_waitinglist_success.html members/tests.py
+#: members/templates/members/leave_waitinglist_success.html
+#: members/tests/basic.py
msgid "Left waitinglist"
msgstr "Warteliste verlassen"
@@ -1984,16 +1997,19 @@ msgstr ""
"einem späteren Zeitpunkt wieder auf die Warteliste setzen lassen möchtest "
"kannst du das auf unserer Webseite machen.\n"
-#: members/templates/members/mail_confirmation_invalid.html members/tests.py
+#: members/templates/members/mail_confirmation_invalid.html
+#: members/tests/basic.py
msgid "Mail confirmation failed"
msgstr "Emailbestätigung fehlgeschlagen"
#: members/templates/members/mail_confirmation_invalid.html
-#: members/templates/members/waiting_confirmation_invalid.html members/tests.py
+#: members/templates/members/waiting_confirmation_invalid.html
+#: members/tests/basic.py
msgid "The supplied link is invalid."
msgstr "Der verwendete Link ist ungültig."
-#: members/templates/members/mail_confirmation_success.html members/tests.py
+#: members/templates/members/mail_confirmation_success.html
+#: members/tests/basic.py
msgid "Mail confirmed"
msgstr "Emailadresse bestätigt"
@@ -2066,7 +2082,7 @@ msgstr "Registrieren"
msgid "Here you can register for group"
msgstr "Hier kannst du dich registrieren für die Gruppe"
-#: members/templates/members/register_failed.html members/tests.py
+#: members/templates/members/register_failed.html members/tests/basic.py
msgid "Something went wrong while processing your registration."
msgstr "Etwas ist schief gelaufen, bei der Verarbeitung deiner Registrierung."
@@ -2129,7 +2145,7 @@ msgid "Registration for waiting list."
msgstr "Registrierung für die Warteliste."
#: members/templates/members/register_waiting_list_success.html
-#: members/tests.py
+#: members/tests/basic.py
msgid "Your registration for the waiting list was successful."
msgstr "Du wurdest auf die Warteliste gesetzt."
@@ -2227,7 +2243,8 @@ msgstr ""
"zustimmst, unterschreibe bitte das Formular und lade hier einen Scan oder "
"ein Bild hoch."
-#: members/templates/members/upload_registration_form.html members/tests.py
+#: members/templates/members/upload_registration_form.html
+#: members/tests/basic.py
msgid ""
"If you are not an adult yet, please let someone responsible for you sign the "
"agreement."
@@ -2240,7 +2257,7 @@ msgid "Upload"
msgstr "Hochladen"
#: members/templates/members/upload_registration_form_invalid.html
-#: members/tests.py
+#: members/tests/basic.py
msgid "The supplied key for uploading a registration form is invalid."
msgstr "Der verwendete Link zum Hochladen eines Anmeldeformulars ist ungültig."
@@ -2249,7 +2266,7 @@ msgid "Thank you for uploading the registration form."
msgstr "Danke für das Hochladen des Anmeldeformulars."
#: members/templates/members/upload_registration_form_success.html
-#: members/tests.py
+#: members/tests/basic.py
msgid "Our team will process your registration shortly."
msgstr ""
"Unser Jugendleiter*innenteam wird deine Registrierung so schnell wie möglich "
@@ -2267,11 +2284,13 @@ msgstr ""
"Leider hast du deinen Wartelistenplatz nicht rechtzeitig bestätigt und hast "
"somit deinen Platz verloren. Du kannst"
-#: members/templates/members/waiting_confirmation_invalid.html members/tests.py
+#: members/templates/members/waiting_confirmation_invalid.html
+#: members/tests/basic.py
msgid "rejoin the waiting list"
msgstr "der Warteliste erneut beitreten"
-#: members/templates/members/waiting_confirmation_success.html members/tests.py
+#: members/templates/members/waiting_confirmation_success.html
+#: members/tests/basic.py
msgid "Waiting confirmed"
msgstr "Wartelistenplatz bestätigt"
@@ -2293,19 +2312,19 @@ msgstr ""
"Danke %(prename)s für dein Interesse auf der Warteliste zu bleiben.\n"
"Dein Platz wurde bestätigt."
-#: members/tests.py
+#: members/tests/basic.py
msgid "This field is required."
msgstr ""
-#: members/tests.py members/views.py
+#: members/tests/basic.py members/views.py
msgid "The entered password is wrong."
msgstr "Das eingegebene Passwort ist falsch."
-#: members/tests.py members/views.py
+#: members/tests/basic.py members/views.py
msgid "invalid"
msgstr "ungültig"
-#: members/tests.py members/views.py
+#: members/tests/basic.py members/views.py
msgid "expired"
msgstr "abgelaufen"
@@ -2335,6 +2354,22 @@ msgstr "Optionale zusätzliche E-Mailadresse"
msgid "Invalid emergency contacts"
msgstr "Ungültige Notfallkontakte"
+#~ msgid "True"
+#~ msgstr "Ja"
+
+#~ msgid "False"
+#~ msgstr "Nein"
+
+#~ msgid "All"
+#~ msgstr "Alle"
+
+#~ msgid "Inform youth leaders about sending of crisis intervention list."
+#~ msgstr ""
+#~ "Informiere Jugendleiter:innen über Versand der Kriseninterventionsliste."
+
+#~ msgid "Send crisis intervention list."
+#~ msgstr "Kriseninterventionsliste verschicken"
+
#~ msgid "You may also choose to include the V32 attachment."
#~ msgstr ""
#~ "Ein LJP Antrag benötigt immer ein Formblatt (in unserem Fall V32-1 "
diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py
index 3daeb4c..4c59373 100644
--- a/jdav_web/members/models.py
+++ b/jdav_web/members/models.py
@@ -595,6 +595,11 @@ class Member(Person):
settings.UPLOAD_REGISTRATION_FORM_TEXT.format(name=self.prename,
link=link))
+ def request_registration_form(self):
+ """Ask the member to upload a registration form via email."""
+ self.generate_upload_registration_form_key()
+ self.send_upload_registration_form_link()
+
def notify_jugendleiters_about_confirmed_mail(self):
group = ", ".join([g.name for g in self.group.all()])
# notify jugendleiters of group of registration
diff --git a/jdav_web/members/templates/admin/request_registration_form.html b/jdav_web/members/templates/admin/request_registration_form.html
new file mode 100644
index 0000000..be44696
--- /dev/null
+++ b/jdav_web/members/templates/admin/request_registration_form.html
@@ -0,0 +1,40 @@
+{% extends "admin/base_site.html" %}
+{% load i18n admin_urls static %}
+
+{% block extrahead %}
+ {{ block.super }}
+ {{ media }}
+
+
+
+{% endblock %}
+
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} invite-waiter
+{% endblock %}
+
+{% block breadcrumbs %}
+
+{% endblock %}
+
+{% block content %}
+{% translate "Request registration form" %}
+
+{% blocktrans %}Do you want to ask {{ member }} to upload their registration form?{% endblocktrans %}
+
+
+{% if member.registration_form %}
+{% blocktrans %}Warning: {{ member }} has already uploaded a registration form.{% endblocktrans %}
+{% endif %}
+
+
+
+{% endblock %}
diff --git a/jdav_web/members/templates/admin/request_registratoin_form.html b/jdav_web/members/templates/admin/request_registratoin_form.html
new file mode 100644
index 0000000..661ddef
--- /dev/null
+++ b/jdav_web/members/templates/admin/request_registratoin_form.html
@@ -0,0 +1,48 @@
+{% extends "admin/base_site.html" %}
+{% load i18n admin_urls static %}
+
+{% block extrahead %}
+ {{ block.super }}
+ {{ media }}
+
+
+
+{% endblock %}
+
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} invite-waiter
+{% endblock %}
+
+{% block breadcrumbs %}
+
+{% endblock %}
+
+{% block content %}
+{% translate "Demote to waiter" %}
+
+{% trans "Do you want to demote the following unconfirmed registrations to waiters?" %}
+
+
+
+ {% for member in queryset %}
+ -
+ {{ member }}
+
+ {% endfor %}
+
+
+
+
+{% endblock %}
diff --git a/jdav_web/members/tests/basic.py b/jdav_web/members/tests/basic.py
index 2448bbf..fca89c6 100644
--- a/jdav_web/members/tests/basic.py
+++ b/jdav_web/members/tests/basic.py
@@ -1423,6 +1423,28 @@ class MemberUnconfirmedAdminTestCase(AdminTestCase):
qs = self.admin.get_queryset(request)
self.assertQuerysetEqual(qs, MemberUnconfirmedProxy.objects.none(), ordered=False)
+ def test_request_registration_form_invalid(self):
+ c = self._login('standard')
+ url = reverse('admin:members_memberunconfirmedproxy_request_registration_form', args=(124,))
+ response = c.get(url)
+ self.assertEqual(response.status_code, HTTPStatus.FOUND)
+
+ def test_request_registration_form_insuficient_permission(self):
+ c = self._login('standard')
+ url = reverse('admin:members_memberunconfirmedproxy_request_registration_form', args=(self.reg.pk,))
+ response = c.get(url, follow=True)
+ self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)
+
+ def test_request_registration_form(self):
+ c = self._login('superuser')
+ url = reverse('admin:members_memberunconfirmedproxy_request_registration_form', args=(self.reg.pk,))
+ response = c.get(url)
+ self.assertEqual(response.status_code, HTTPStatus.OK)
+ self.assertContains(response, _('Request registration form'))
+
+ response = c.post(url, data={'apply': ''})
+ self.assertEqual(response.status_code, HTTPStatus.FOUND)
+
def test_demote_to_waiter(self):
c = self._login('superuser')
url = reverse('admin:members_memberunconfirmedproxy_demote', args=(self.reg.pk,))
diff --git a/jdav_web/members/views.py b/jdav_web/members/views.py
index 4987b17..9938b81 100644
--- a/jdav_web/members/views.py
+++ b/jdav_web/members/views.py
@@ -183,8 +183,7 @@ def echo(request):
member.save()
if not member.registration_form:
# If the member does not have a registration form, forward them to the upload page.
- member.generate_upload_registration_form_key()
- member.send_upload_registration_form_link()
+ member.request_registration_form()
return HttpResponseRedirect(reverse('members:upload_registration_form') + "?key=" + member.upload_registration_form_key)
else:
return render_echo_success(request, member.prename)
diff --git a/jdav_web/templates/admin/members/memberunconfirmedproxy/change_form_object_tools.html b/jdav_web/templates/admin/members/memberunconfirmedproxy/change_form_object_tools.html
index c3fbe46..b39d39a 100644
--- a/jdav_web/templates/admin/members/memberunconfirmedproxy/change_form_object_tools.html
+++ b/jdav_web/templates/admin/members/memberunconfirmedproxy/change_form_object_tools.html
@@ -3,6 +3,11 @@
{% block object-tools-items %}
+
+ {% url opts|admin_urlname:'request_registration_form' original.pk|admin_urlquote as request_url %}
+ {% trans 'Request registration form' %}
+
+
{% url opts|admin_urlname:'demote' original.pk|admin_urlquote as demote_url %}
{% trans 'Demote to waiter' %}