Address, responsible and phone number were missing. Use Google Maps API to query the address, to ensure to have valid addresses

This commit is contained in:
Yohann D'ANELLO 2020-12-28 23:59:21 +01:00
parent 95fec7c0da
commit 72753edf64
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
10 changed files with 118 additions and 11 deletions

View File

@ -4,7 +4,6 @@
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% block content %} {% block content %}
<div class="card bg-light shadow"> <div class="card bg-light shadow">
<div class="card-header text-center"> <div class="card-header text-center">
<h4>{{ team.name }}</h4> <h4>{{ team.name }}</h4>
@ -77,7 +76,7 @@
{% if user.registration.participates %} {% if user.registration.participates %}
{% if can_validate %} {% if can_validate %}
<div class="alert alert-info"> <div class="alert alert-info">
{% 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." %}
<div class="text-center"> <div class="text-center">
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
@ -88,7 +87,7 @@
</div> </div>
{% else %} {% else %}
<div class="alert alert-warning"> <div class="alert alert-warning">
{% 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." %}
</div> </div>
{% endif %} {% endif %}
{% else %} {% else %}

View File

@ -171,11 +171,13 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
context["title"] = _("Detail of team {trigram}").format(trigram=self.object.trigram) context["title"] = _("Detail of team {trigram}").format(trigram=self.object.trigram)
context["request_validation_form"] = RequestValidationForm(self.request.POST or None) context["request_validation_form"] = RequestValidationForm(self.request.POST or None)
context["validation_form"] = ValidateParticipationForm(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 # A team is complete when there are at least 4 members plus a coache that have sent their photo authorization,
# and confirmed their email address # their health sheet, they confirmed their email address and under-18 people sent their parental authorization.
context["can_validate"] = team.students.count() >= 3 and \ 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.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 return context

View File

@ -1,6 +1,7 @@
# Copyright (C) 2020 by Animath # Copyright (C) 2020 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from address.forms import AddressField
from address.widgets import AddressWidget
from django import forms from django import forms
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -67,7 +68,8 @@ class StudentRegistrationForm(forms.ModelForm):
""" """
class Meta: class Meta:
model = StudentRegistration 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): class PhotoAuthorizationForm(forms.ModelForm):
@ -98,7 +100,8 @@ class CoachRegistrationForm(forms.ModelForm):
""" """
class Meta: class Meta:
model = CoachRegistration 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): class VolunteerRegistrationForm(forms.ModelForm):

View File

@ -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'),
),
]

View File

@ -1,14 +1,17 @@
# Copyright (C) 2020 by Animath # Copyright (C) 2020 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from address.models import AddressField
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.db import models from django.db import models
from django.template import loader from django.template import loader
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
from tfjm.tokens import email_validation_token from tfjm.tokens import email_validation_token
@ -114,6 +117,22 @@ class ParticipantRegistration(Registration):
verbose_name=_("team"), 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( photo_authorization = models.FileField(
verbose_name=_("photo authorization"), verbose_name=_("photo authorization"),
upload_to=get_random_photo_filename, upload_to=get_random_photo_filename,
@ -156,6 +175,22 @@ class StudentRegistration(ParticipantRegistration):
verbose_name=_("school"), 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( parental_authorization = models.FileField(
verbose_name=_("parental authorization"), verbose_name=_("parental authorization"),
upload_to=get_random_parental_filename, upload_to=get_random_parental_filename,

View File

@ -4,6 +4,10 @@
{% load i18n %} {% load i18n %}
{% block title %}{% trans "Sign up" %}{% endblock %} {% block title %}{% trans "Sign up" %}{% endblock %}
{% block extracss %}
{{ student_registration_form.media }}
{% endblock %}
{% block content %} {% block content %}
<h2>{% trans "Sign up" %}</h2> <h2>{% trans "Sign up" %}</h2>

View File

@ -2,6 +2,10 @@
{% load crispy_forms_filters i18n %} {% load crispy_forms_filters i18n %}
{% block extracss %}
{{ registration_form.media }}
{% endblock %}
{% block content %} {% block content %}
<form method="post"> <form method="post">
<div id="form-content"> <div id="form-content">

View File

@ -1,4 +1,5 @@
Django~=3.0 Django~=3.0
django-address~=0.2
django-bootstrap-datepicker-plus~=3.0 django-bootstrap-datepicker-plus~=3.0
django-cas-server~=1.2 django-cas-server~=1.2
django-crispy-forms~=1.9 django-crispy-forms~=1.9
@ -6,14 +7,16 @@ django-extensions~=3.0
django-filter~=2.3 django-filter~=2.3
django-haystack~=3.0 django-haystack~=3.0
django-mailer~=2.0 django-mailer~=2.0
django-phonenumber-field~=5.0.0
django-polymorphic~=3.0 django-polymorphic~=3.0
django-tables2~=2.3 django-tables2~=2.3
djangorestframework~=3.12 djangorestframework~=3.12
django-rest-polymorphic~=0.1 django-rest-polymorphic~=0.1
gunicorn~=20.0 gunicorn~=20.0
matrix-nio~=0.15 matrix-nio~=0.15
phonenumbers~=8.9.10
psycopg2-binary~=2.8 psycopg2-binary~=2.8
ptpython~=3.0 ptpython~=3.0
python-magic~=0.4 python-magic~=0.4
sympasoap~=1.0 sympasoap~=1.0
whoosh~=2.7 whoosh~=2.7

View File

@ -53,11 +53,13 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.forms', 'django.forms',
'address',
'bootstrap_datepicker_plus', 'bootstrap_datepicker_plus',
'crispy_forms', 'crispy_forms',
'django_tables2', 'django_tables2',
'haystack', 'haystack',
'logs', 'logs',
'phonenumber_field',
'polymorphic', 'polymorphic',
'rest_framework', 'rest_framework',
'rest_framework.authtoken', 'rest_framework.authtoken',
@ -225,3 +227,9 @@ if os.getenv("TFJM_STAGE", "dev") == "prod": # pragma: no cover
from .settings_prod import * # noqa: F401,F403 from .settings_prod import * # noqa: F401,F403
else: else:
from .settings_dev import * # noqa: F401,F403 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")

View File

@ -11,6 +11,7 @@ sitepackages = False
deps = deps =
coverage coverage
Django~=3.1 Django~=3.1
django-address~=0.2
django-bootstrap-datepicker-plus~=3.0 django-bootstrap-datepicker-plus~=3.0
django-crispy-forms~=1.9 django-crispy-forms~=1.9
django-filter~=2.3 django-filter~=2.3