Merge branch 'master' into branch 'changelog'

This commit is contained in:
2020-11-03 09:52:52 +01:00
18 changed files with 387 additions and 33 deletions

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-10-15 15:38
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0033_auto_20200925_1543'),
]
operations = [
migrations.AddField(
model_name='participant',
name='dav_member',
field=models.BooleanField(default=True, help_text='In Ausnahmefällen nehmen wir auch Nichtmitglieder mit.', verbose_name='DAV Mitglied'),
),
migrations.AlterField(
model_name='participant',
name='dav_number',
field=models.CharField(blank=True, max_length=62, validators=[django.core.validators.RegexValidator('^([0-9]{1,10}/[0-9]{2,10}/)?[0-9]{1,10}(\\*[0-9]{1,10})?(\\*[0-9]{4}\\*[0-9]{4})?([* ][0-9]{8})?$', 'Ungültiges Format.')], verbose_name='DAV Mitgliedsnummer'),
),
]

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
@@ -32,8 +33,11 @@ class Participant(models.Model):
email_address = models.EmailField(verbose_name=_('E-Mail-Adresse'))
phone_number = models.CharField(max_length=254,
verbose_name=_('Telefonnummer'))
dav_member = models.BooleanField(default=True,
verbose_name=_('DAV Mitglied'),
help_text=_('In Ausnahmefällen nehmen wir auch Nichtmitglieder mit.'))
dav_number = models.CharField(max_length=62,
validators=[DAVNumberValidator],
blank=True, validators=[DAVNumberValidator],
verbose_name=_('DAV Mitgliedsnummer'))
emergency_contact = models.TextField(blank=True,
verbose_name=_('Notfall-Kontakt'),
@@ -69,25 +73,38 @@ class Participant(models.Model):
text = """{fullname}
{address}, {postal_code} {city}
DAV Mitglied: {dav_info}
Notfallkontakt:
{emergency_contact}
Anmerkung:
{note}
"""
if not self.dav_member:
dav_info = _('Nein')
else:
dav_info = self.dav_number
return text.format(
fullname=self.get_full_name(),
address=self.address,
postal_code=self.postal_code,
city=self.city,
dav_info=dav_info,
emergency_contact=self.emergency_contact,
note=self.note,
)
def clean(self):
if self.dav_member and not self.dav_number:
raise ValidationError({'dav_number': _('Bei DAV Mitgliedern brauchen wir die Mitgliedsnummer.')})
def save(self, **kwargs):
if not self.purge_at and self.event:
self.purge_at = self.__class__.calc_purge_at(self.event)
self.full_clean()
super(Participant, self).save(**kwargs)
@staticmethod

View File

@@ -223,11 +223,38 @@
</div>
</div>
<hr />
<div class="pull-right text-info" style="margin-right: 1em;"
title="Sobald du im Kasten 'Anmeldungen' bei einzelnen Personen auf das Plus-Symbol geklickt hast, oder jemanden mit dem Formular unter 'weiteren Teilnehmer hinzufügen' eingetragen hast, erscheinen diese Personen weiter unten als Teilnehmer (graue Kästen).
Diese Teilnehmerliste muss zum Zeitpunkt der Tour wirklich stimmen, da wir sie im Falle eines Unfalls brauchen!
Das rote oder grüne Sparschweinchensymbol am rechten Rand eines Teilnehmerkastens zeigt dir, ob die Geschäftstelle bereits den Teilnehmerbeitrag erhalten bzw. zugeordnet hat.
Wenn mehr Teilnehmer eingetragen sind, als in der Teilnehmerzahl der Ausschreibung angegeben, werden die entsprechenden Teilnehmer in gelben Kästen dargestellt.
Wichtig: das System verschickt keine Zu- oder Absagen an die Teilnehmer!
Das musst du selbst per E-Mail oder telefonisch machen.
">
{% bootstrap_icon 'question-sign' %}
</div>
<h4>{% trans 'Teilnehmer' %}</h4>
<div class="panel-group" id="form-accordion-participants" role="tablist" aria-multiselectable="true">
{% if registrations_support %}
<div class="panel panel-info">
<div id="headingRegistrations" class="panel-heading" role="tab">
<div class="pull-right text-info" title="Unter Anmeldungen siehst du, wer gerne mit auf deine Tour möchte.
- Wenn du jemanden davon mitnehmen möchtest, schicke ihm per E-Mail eine Zusage und klicke dann auf das Plus-Symbol.
Die Person wird dann automatisch auf die Teilnehmerliste übernommen.
- Wenn du jemanden nicht mitnehmen möchtest, schicke ihm per E-Mail eine Absage und klicke dann auf das Minus-Symbol.
Nach einem Klick auf Plus oder Minus werden die entsprechenden Zeilen ausgegraut.
Wichtig: das System verschickt keine Zu- oder Absagen an die Teilnehmer!
Das musst du selbst (per E-Mail oder telefonisch) machen.
">
{% bootstrap_icon 'question-sign' %}
</div>
<h5 class="panel-title">
<a role="button" href="#collapseRegistrations"
data-toggle="collapse"
@@ -236,14 +263,25 @@
</a>
</h5>
</div>
<div id="collapseRegistrations" class="panel-collapse collapse {% if registrations %}in{% endif %}"
<div id="collapseRegistrations" class="panel-collapse collapse {% if registrations_pending %}in{% endif %}"
role="tabpanel" aria-labelledby="headingRegistrations">
<div class="panel-body">
{% for registration in registrations %}
{% for registration in registrations_all %}
<form action="" method="post" class="form-inline">
{% csrf_token %}
<input type="hidden" name="registration" value="{{ registration.id }}">
{% if has_permission_update_participants %}
{% if registration.answered %}
<button disabled="disabled"
class="btn btn-link no-padding" title="Anmeldung wurde bereits bearbeitet">
<span class="text-muted">{% bootstrap_icon 'plus-sign' %}</span>
</button>
&nbsp;
<button disabled="disabled"
class="btn btn-link no-padding" title="Anmeldung wurde bereits bearbeitet">
<span class="text-muted">{% bootstrap_icon 'minus-sign' %}</span>
</button>
&nbsp;
{% elif has_permission_update_participants %}
<button type="submit" name="action" value="accept_registration"
class="btn btn-link no-padding" title="zur Teilnehmerliste hinzufügen">
<span class="text-success">{% bootstrap_icon 'plus-sign' %}</span>
@@ -256,6 +294,7 @@
&nbsp;
{% endif %}
{% if registration.answered %}
<s>
<span class="text-muted">
{% endif %}
{{ registration.get_full_name }}
@@ -270,12 +309,19 @@
<span title="{{ registration.get_info }}">
{% bootstrap_icon 'info-sign' %}
</span>
&nbsp;
{% if registration.answered %}
</span>
</s>
&nbsp;
<span class="text-info" title="Bei dieser Anmeldung hast du bereits auf Plus oder Minus geklickt.
Leider speichert das System hier nicht, welchen der beiden Knöpfe du gewählt hast, aber bei Plus sollte die Person ja weiter unten als Teilnehmer gelistet sein.">
{% bootstrap_icon 'question-sign' %}
</span>
{% endif %}
</form>
{% empty %}
{% trans 'Keine unbearbeiteten Anmeldungen vorhanden' %}
{% trans 'Keine Anmeldungen vorhanden' %}
{% endfor %}
</div>
</div>
@@ -284,6 +330,14 @@
{% if has_permission_update_participants %}
<div class="panel panel-info">
<div id="headingAddParticipant" class="panel-heading" role="tab">
<div class="pull-right text-info" title="Wenn du jemanden in die Teilnehmerliste aufnehmen möchtest,
der nicht unter 'Anmeldungen' steht, klicke auf 'weiteren Teilnehmer hinzufügen' um das Teilnehmerformular aufzuklappen.
Über das Formular kannst du dann die Teilnehmerdaten eintragen und speichern.
Wichtig: das System verschickt keine Bestätigung an dich oder den neuen Teilnehmer.
">
{% bootstrap_icon 'question-sign' %}
</div>
<h5 class="panel-title">
<a role="button" href="#collapseAddParticipant"
data-toggle="collapse"
@@ -401,6 +455,10 @@
{% else %}
<div class="panel panel-info">
<div class="panel-body">
<div class="pull-right text-info" title="Sobald du im Kasten 'Anmeldungen' bei einzelnen Personen auf das Plus-Symbol geklickt hast, oder jemanden mit dem Formular unter 'weiteren Teilnehmer hinzufügen' eingetragen hast, erscheinen diese Personen hier als Teilnehmer.
">
{% bootstrap_icon 'question-sign' %}
</div>
<span class="text-info">{% trans 'Es wurden noch keine Teilnehmer hinzugefügt.' %}</span>
</div>
</div>

View File

@@ -29,9 +29,12 @@
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="col-sm-3">
{% bootstrap_field form.dav_number %}
</div>
<div class="col-sm-3">
{% bootstrap_field form.dav_member %}
</div>
<div class="col-sm-6">
{% bootstrap_field form.emergency_contact %}
</div>

View File

@@ -121,7 +121,11 @@ class ActionTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
'user': user.get_full_name(),
})
html = message.replace('\'', '&#39;')
self.assertInHTML(html, content)
# Sometimes this test fail, and we cannot see the tested content, so we create our own Exception
try:
self.assertInHTML(html, content)
except AssertionError:
raise AssertionError('Not in HTML:\n{}\n-----\n{}\n'.format(html, content))
self.assertRegex(content, r'alert-success')
def setUp(self):

View File

@@ -230,9 +230,11 @@ class EventRegistrationsView(EventPermissionMixin, generic.DetailView):
registrations_support = hasattr(event, 'registrations')
context['registrations_support'] = registrations_support
if registrations_support:
registrations = event.registrations.filter(answered=False)
# registrations = event.registrations.all()
context['registrations'] = registrations
registrations_all = event.registrations.all()
registrations_pending = registrations_all.filter(answered=False)
context['registrations_pending'] = registrations_pending
context['registrations_all'] = registrations_all
context['registrations'] = registrations_all
return context
@@ -279,6 +281,7 @@ class EventRegistrationsView(EventPermissionMixin, generic.DetailView):
'city': registration.city,
'email_address': registration.email_address,
'phone_number': registration.phone_number,
'dav_member': registration.dav_member,
'dav_number': registration.dav_number,
'emergency_contact': registration.emergency_contact,
'experience': registration.experience,