diff --git a/apps/participation/templates/participation/team_detail.html b/apps/participation/templates/participation/team_detail.html index c4a8ffe..ba808c5 100644 --- a/apps/participation/templates/participation/team_detail.html +++ b/apps/participation/templates/participation/team_detail.html @@ -4,7 +4,6 @@ {% load crispy_forms_filters %} {% block content %} -

{{ team.name }}

@@ -77,7 +76,7 @@ {% if user.registration.participates %} {% if can_validate %}
- {% trans "Your team has at least 3 members and all photo authorizations were given: the team can be validated." %} + {% trans "Your team has at least 4 members and a coach and all photo authorizations were given: the team can be validated." %}
{% csrf_token %} @@ -88,7 +87,7 @@
{% else %}
- {% trans "Your team must be composed of 3 members and each member must upload its photo authorization and confirm its email address." %} + {% trans "Your team must be composed of 4 members and a coach and each member must upload its photo authorization and confirm its email address." %}
{% endif %} {% else %} diff --git a/apps/participation/views.py b/apps/participation/views.py index 9599615..7cceda1 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -171,11 +171,13 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) context["title"] = _("Detail of team {trigram}").format(trigram=self.object.trigram) context["request_validation_form"] = RequestValidationForm(self.request.POST or None) context["validation_form"] = ValidateParticipationForm(self.request.POST or None) - # A team is complete when there are at least 3 members that have sent their photo authorization - # and confirmed their email address - context["can_validate"] = team.students.count() >= 3 and \ + # A team is complete when there are at least 4 members plus a coache that have sent their photo authorization, + # their health sheet, they confirmed their email address and under-18 people sent their parental authorization. + context["can_validate"] = team.students.count() >= 4 and team.coachs.exists() and \ all(r.email_confirmed for r in team.students.all()) and \ - all(r.photo_authorization for r in team.students.all()) + all(r.photo_authorization for r in team.participants.all()) and \ + all(r.health_sheet for r in team.participants.all()) and \ + all(r.parental_authorization for r in team.students.all() if r.under_18) return context diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 5f2ae99..ffe2ac0 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -1,6 +1,7 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later - +from address.forms import AddressField +from address.widgets import AddressWidget from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User @@ -67,7 +68,8 @@ class StudentRegistrationForm(forms.ModelForm): """ class Meta: model = StudentRegistration - fields = ('team', 'student_class', 'school', 'give_contact_to_animath', 'email_confirmed',) + fields = ('team', 'student_class', 'birth_date', 'address', 'phone_number', + 'school', 'give_contact_to_animath', 'email_confirmed',) class PhotoAuthorizationForm(forms.ModelForm): @@ -98,7 +100,8 @@ class CoachRegistrationForm(forms.ModelForm): """ class Meta: model = CoachRegistration - fields = ('team', 'professional_activity', 'give_contact_to_animath', 'email_confirmed',) + fields = ('team', 'birth_date', 'address', 'phone_number', 'professional_activity', + 'give_contact_to_animath', 'email_confirmed',) class VolunteerRegistrationForm(forms.ModelForm): diff --git a/apps/registration/migrations/0002_auto_20201228_2219.py b/apps/registration/migrations/0002_auto_20201228_2219.py new file mode 100644 index 0000000..95e1b8c --- /dev/null +++ b/apps/registration/migrations/0002_auto_20201228_2219.py @@ -0,0 +1,48 @@ +# Generated by Django 3.0.11 on 2020-12-28 21:19 + +import address.models +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import phonenumber_field.modelfields + + +class Migration(migrations.Migration): + + dependencies = [ + ('address', '0003_auto_20200830_1851'), + ('registration', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='participantregistration', + name='address', + field=address.models.AddressField(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.Address', verbose_name='address'), + ), + migrations.AddField( + model_name='participantregistration', + name='birth_date', + field=models.DateField(default=django.utils.timezone.now, verbose_name='birth date'), + ), + migrations.AddField( + model_name='participantregistration', + name='phone_number', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='phone number'), + ), + migrations.AddField( + model_name='studentregistration', + name='responsible_email', + field=models.EmailField(default='', max_length=254, verbose_name='responsible email address'), + ), + migrations.AddField( + model_name='studentregistration', + name='responsible_name', + field=models.CharField(default='', max_length=255, verbose_name='responsible name'), + ), + migrations.AddField( + model_name='studentregistration', + name='responsible_phone', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='responsible phone number'), + ), + ] diff --git a/apps/registration/models.py b/apps/registration/models.py index f096450..61d5b0c 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -1,14 +1,17 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later +from address.models import AddressField from django.contrib.sites.models import Site from django.db import models from django.template import loader from django.urls import reverse_lazy +from django.utils import timezone from django.utils.crypto import get_random_string from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode from django.utils.translation import gettext_lazy as _ +from phonenumber_field.modelfields import PhoneNumberField from polymorphic.models import PolymorphicModel from tfjm.tokens import email_validation_token @@ -114,6 +117,22 @@ class ParticipantRegistration(Registration): verbose_name=_("team"), ) + birth_date = models.DateField( + verbose_name=_("birth date"), + default=timezone.now, + ) + + address = AddressField( + verbose_name=_("address"), + null=True, + default=None, + ) + + phone_number = PhoneNumberField( + verbose_name=_("phone number"), + blank=True, + ) + photo_authorization = models.FileField( verbose_name=_("photo authorization"), upload_to=get_random_photo_filename, @@ -156,6 +175,22 @@ class StudentRegistration(ParticipantRegistration): verbose_name=_("school"), ) + responsible_name = models.CharField( + max_length=255, + verbose_name=_("responsible name"), + default="", + ) + + responsible_phone = PhoneNumberField( + verbose_name=_("responsible phone number"), + blank=True, + ) + + responsible_email = models.EmailField( + verbose_name=_("responsible email address"), + default="", + ) + parental_authorization = models.FileField( verbose_name=_("parental authorization"), upload_to=get_random_parental_filename, diff --git a/apps/registration/templates/registration/signup.html b/apps/registration/templates/registration/signup.html index 82a9431..ee0eba1 100644 --- a/apps/registration/templates/registration/signup.html +++ b/apps/registration/templates/registration/signup.html @@ -4,6 +4,10 @@ {% load i18n %} {% block title %}{% trans "Sign up" %}{% endblock %} +{% block extracss %} + {{ student_registration_form.media }} +{% endblock %} + {% block content %}

{% trans "Sign up" %}

diff --git a/apps/registration/templates/registration/update_user.html b/apps/registration/templates/registration/update_user.html index 7e282d5..05533b8 100644 --- a/apps/registration/templates/registration/update_user.html +++ b/apps/registration/templates/registration/update_user.html @@ -2,6 +2,10 @@ {% load crispy_forms_filters i18n %} +{% block extracss %} + {{ registration_form.media }} +{% endblock %} + {% block content %}
diff --git a/requirements.txt b/requirements.txt index f1e2197..c2f695e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Django~=3.0 +django-address~=0.2 django-bootstrap-datepicker-plus~=3.0 django-cas-server~=1.2 django-crispy-forms~=1.9 @@ -6,14 +7,16 @@ django-extensions~=3.0 django-filter~=2.3 django-haystack~=3.0 django-mailer~=2.0 +django-phonenumber-field~=5.0.0 django-polymorphic~=3.0 django-tables2~=2.3 djangorestframework~=3.12 django-rest-polymorphic~=0.1 gunicorn~=20.0 matrix-nio~=0.15 +phonenumbers~=8.9.10 psycopg2-binary~=2.8 ptpython~=3.0 python-magic~=0.4 sympasoap~=1.0 -whoosh~=2.7 \ No newline at end of file +whoosh~=2.7 diff --git a/tfjm/settings.py b/tfjm/settings.py index 3fbdcb0..75f98ca 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -53,11 +53,13 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'django.forms', + 'address', 'bootstrap_datepicker_plus', 'crispy_forms', 'django_tables2', 'haystack', 'logs', + 'phonenumber_field', 'polymorphic', 'rest_framework', 'rest_framework.authtoken', @@ -225,3 +227,9 @@ if os.getenv("TFJM_STAGE", "dev") == "prod": # pragma: no cover from .settings_prod import * # noqa: F401,F403 else: from .settings_dev import * # noqa: F401,F403 + +# Custom phone number format +PHONENUMBER_DB_FORMAT = 'NATIONAL' +PHONENUMBER_DEFAULT_REGION = 'FR' + +GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") diff --git a/tox.ini b/tox.ini index 38be163..d3cd380 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,7 @@ sitepackages = False deps = coverage Django~=3.1 + django-address~=0.2 django-bootstrap-datepicker-plus~=3.0 django-crispy-forms~=1.9 django-filter~=2.3