diff --git a/apps/participation/templates/participation/team_detail.html b/apps/participation/templates/participation/team_detail.html
index 6d0505b..1e947d2 100644
--- a/apps/participation/templates/participation/team_detail.html
+++ b/apps/participation/templates/participation/team_detail.html
@@ -74,6 +74,19 @@
{% endfor %}
+
{% trans "Vaccine sheets:" %}
+
+ {% for student in team.students.all %}
+ {% if student.under_18 %}
+ {% if student.vaccine_sheet %}
+ {{ student }}{% if not forloop.last %},{% endif %}
+ {% else %}
+ {{ student }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+
{% trans "Parental authorizations:" %}
{% for student in team.students.all %}
diff --git a/apps/participation/tests.py b/apps/participation/tests.py
index 57a3abe..4fd57e6 100644
--- a/apps/participation/tests.py
+++ b/apps/participation/tests.py
@@ -230,6 +230,7 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/mai-linh",
health_sheet="authorization/health/mai-linh",
+ vaccine_sheet="authorization/vaccine/mai-linh",
parental_authorization="authorization/parental/mai-linh",
)
@@ -251,6 +252,7 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/emmy",
health_sheet="authorization/health/emmy",
+ vaccine_sheet="authorization/vaccine/emmy",
parental_authorization="authorization/parental/emmy",
)
@@ -272,11 +274,13 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/tfjm",
health_sheet="authorization/health/tfjm",
+ vaccine_sheet="authorization/health/tfjm",
parental_authorization="authorization/parental/tfjm",
)
self.coach.registration.team = self.team
self.coach.registration.health_sheet = "authorization/health/coach"
+ self.coach.registration.vaccine_sheet = "authorization/vaccine/coach"
self.coach.registration.photo_authorization = "authorization/photo/coach"
self.coach.registration.email_confirmed = True
self.coach.registration.save()
@@ -305,6 +309,7 @@ class TestStudentParticipation(TestCase):
self.user.registration.photo_authorization = "authorization/photo/ananas"
self.user.registration.health_sheet = "authorization/health/ananas"
+ self.user.registration.vaccine_sheet = "authorization/health/ananas"
self.user.registration.parental_authorization = "authorization/parental/ananas"
self.user.registration.save()
diff --git a/apps/participation/views.py b/apps/participation/views.py
index 622b8f5..f4e900d 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -180,6 +180,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
context["validation_form"] = ValidateParticipationForm(self.request.POST or None)
# A team is complete when there are at least 4 members plus a coache that have sent their authorizations,
# their health sheet, they confirmed their email address and under-18 people sent their parental authorization.
+ # TODO: Add vaccine sheets
context["can_validate"] = team.students.count() >= 4 and team.coaches.exists() and \
team.participation.tournament and \
all(r.photo_authorization for r in team.participants.all()) and \
@@ -414,6 +415,12 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
zf.write("media/" + participant.health_sheet.name,
_("Health sheet of {participant}.{ext}").format(participant=str(participant), ext=ext))
+ if isinstance(participant, StudentRegistration) and participant.vaccine_sheet:
+ mime_type = magic.from_file("media/" + participant.vaccine_sheet.name)
+ ext = mime_type.split("/")[1].replace("jpeg", "jpg")
+ zf.write("media/" + participant.vaccine_sheet.name,
+ _("Vaccine sheet of {participant}.{ext}").format(participant=str(participant), ext=ext))
+
if team.motivation_letter:
mime_type = magic.from_file("media/" + team.motivation_letter.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
diff --git a/apps/registration/forms.py b/apps/registration/forms.py
index a79ec76..ae67080 100644
--- a/apps/registration/forms.py
+++ b/apps/registration/forms.py
@@ -146,6 +146,28 @@ class HealthSheetForm(forms.ModelForm):
fields = ('health_sheet',)
+class VaccineSheetForm(forms.ModelForm):
+ """
+ Form to send a vaccine sheet.
+ """
+ def clean_vaccine_sheet(self):
+ if "vaccine_sheet" in self.files:
+ file = self.files["vaccine_sheet"]
+ if file.size > 2e6:
+ raise ValidationError(_("The uploaded file size must be under 2 Mo."))
+ if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]:
+ raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
+ return self.cleaned_data["vaccine_sheet"]
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fields["vaccine_sheet"].widget = FileInput()
+
+ class Meta:
+ model = StudentRegistration
+ fields = ('vaccine_sheet',)
+
+
class ParentalAuthorizationForm(forms.ModelForm):
"""
Form to send a parental authorization.
diff --git a/apps/registration/migrations/0005_studentregistration_vaccine_sheet.py b/apps/registration/migrations/0005_studentregistration_vaccine_sheet.py
new file mode 100644
index 0000000..518464e
--- /dev/null
+++ b/apps/registration/migrations/0005_studentregistration_vaccine_sheet.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2.18 on 2023-02-19 23:38
+
+from django.db import migrations, models
+import registration.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('registration', '0004_volunteer_admin'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='studentregistration',
+ name='vaccine_sheet',
+ field=models.FileField(blank=True, default='', upload_to=registration.models.get_random_vaccine_filename, verbose_name='vaccine sheet'),
+ ),
+ ]
diff --git a/apps/registration/models.py b/apps/registration/models.py
index 8c688c2..a837079 100644
--- a/apps/registration/models.py
+++ b/apps/registration/models.py
@@ -108,6 +108,10 @@ def get_random_health_filename(instance, filename):
return "authorization/health/" + get_random_string(64)
+def get_random_vaccine_filename(instance, filename):
+ return "authorization/vaccine/" + get_random_string(64)
+
+
def get_random_parental_filename(instance, filename):
return "authorization/parental/" + get_random_string(64)
@@ -242,6 +246,13 @@ class StudentRegistration(ParticipantRegistration):
default="",
)
+ vaccine_sheet = models.FileField(
+ verbose_name=_("vaccine sheet"),
+ upload_to=get_random_vaccine_filename,
+ blank=True,
+ default="",
+ )
+
@property
def type(self):
return _("student")
diff --git a/apps/registration/templates/registration/upload_vaccine_sheet.html b/apps/registration/templates/registration/upload_vaccine_sheet.html
new file mode 100644
index 0000000..e97ad94
--- /dev/null
+++ b/apps/registration/templates/registration/upload_vaccine_sheet.html
@@ -0,0 +1,15 @@
+{% extends "base.html" %}
+
+{% load i18n static crispy_forms_filters %}
+
+{% block content %}
+ {% trans "Back to the user detail" %}
+
+
+{% endblock %}
diff --git a/apps/registration/templates/registration/user_detail.html b/apps/registration/templates/registration/user_detail.html
index 8dc7e5d..54af4b2 100644
--- a/apps/registration/templates/registration/user_detail.html
+++ b/apps/registration/templates/registration/user_detail.html
@@ -79,6 +79,16 @@
{% endif %}
+ {% trans "Vaccine sheet:" %}
+
+ {% if user_object.registration.vaccine_sheet %}
+ {% trans "Download" %}
+ {% endif %}
+ {% if user_object.registration.team and not user_object.registration.team.participation.valid %}
+
+ {% endif %}
+
+
{% trans "Parental authorization:" %}
{% if user_object.registration.parental_authorization %}
@@ -171,6 +181,11 @@
{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk as modal_action %}
{% include "base_modal.html" with modal_id="uploadHealthSheet" modal_enctype="multipart/form-data" %}
+ {% trans "Upload vaccine sheet" as modal_title %}
+ {% trans "Upload" as modal_button %}
+ {% url "registration:upload_user_vaccine_sheet" pk=user_object.registration.pk as modal_action %}
+ {% include "base_modal.html" with modal_id="uploadVaccineSheet" modal_enctype="multipart/form-data" %}
+
{% trans "Upload parental authorization" as modal_title %}
{% trans "Upload" as modal_button %}
{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %}
diff --git a/apps/registration/urls.py b/apps/registration/urls.py
index 457614a..caaf9e1 100644
--- a/apps/registration/urls.py
+++ b/apps/registration/urls.py
@@ -7,7 +7,7 @@ from .views import AddOrganizerView, AdultPhotoAuthorizationTemplateView, ChildP
InstructionsTemplateView, MyAccountDetailView, ParentalAuthorizationTemplateView, PaymentUpdateView, \
ResetAdminView, SignupView, UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, \
UserUpdateView, UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
- UserValidateView, UserValidationEmailSentView
+ UserUploadVaccineSheetView, UserValidateView, UserValidationEmailSentView
app_name = "registration"
@@ -32,6 +32,8 @@ urlpatterns = [
path("instructions-template/", InstructionsTemplateView.as_view(), name="instructions_template"),
path("user//upload-health-sheet/", UserUploadHealthSheetView.as_view(),
name="upload_user_health_sheet"),
+ path("user//upload-vaccine-sheet/", UserUploadVaccineSheetView.as_view(),
+ name="upload_user_vaccine_sheet"),
path("user//upload-parental-authorization/", UserUploadParentalAuthorizationView.as_view(),
name="upload_user_parental_authorization"),
path("update-payment//", PaymentUpdateView.as_view(), name="update_payment"),
diff --git a/apps/registration/views.py b/apps/registration/views.py
index f6d89dc..0d048bf 100644
--- a/apps/registration/views.py
+++ b/apps/registration/views.py
@@ -29,7 +29,7 @@ from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
from .forms import AddOrganizerForm, CoachRegistrationForm, HealthSheetForm, \
ParentalAuthorizationForm, PaymentForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \
- VolunteerRegistrationForm
+ VaccineSheetForm, VolunteerRegistrationForm
from .models import ParticipantRegistration, Payment, Registration, StudentRegistration
from .tables import RegistrationTable
@@ -344,6 +344,27 @@ class UserUploadHealthSheetView(UserRegistrationMixin, UpdateView):
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
+class UserUploadVaccineSheetView(UserRegistrationMixin, UpdateView):
+ """
+ A participant can send its vaccine sheet.
+ """
+ model = StudentRegistration
+ form_class = VaccineSheetForm
+ template_name = "registration/upload_vaccine_sheet.html"
+ extra_context = dict(title=_("Upload vaccine sheet"))
+
+ @transaction.atomic
+ def form_valid(self, form):
+ old_instance = StudentRegistration.objects.get(pk=self.object.pk)
+ if old_instance.vaccine_sheet:
+ old_instance.vaccine_sheet.delete()
+ old_instance.save()
+ return super().form_valid(form)
+
+ def get_success_url(self):
+ return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
+
+
class UserUploadParentalAuthorizationView(UserRegistrationMixin, UpdateView):
"""
A participant can send its parental authorization.
@@ -484,6 +505,29 @@ class HealthSheetView(LoginRequiredMixin, View):
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
+class VaccineSheetView(LoginRequiredMixin, View):
+ """
+ Display the sent health sheet.
+ """
+ def get(self, request, *args, **kwargs):
+ filename = kwargs["filename"]
+ path = f"media/authorization/vaccine/{filename}"
+ if not os.path.exists(path):
+ raise Http404
+ student = StudentRegistration.objects.get(vaccine_sheet__endswith=filename)
+ user = request.user
+ if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
+ and student.team.participation.tournament in user.registration.organized_tournaments.all()):
+ raise PermissionDenied
+ # Guess mime type of the file
+ mime = Magic(mime=True)
+ mime_type = mime.from_file(path)
+ ext = mime_type.split("/")[1].replace("jpeg", "jpg")
+ # Replace file name
+ true_file_name = _("Vaccine sheet of {student}.{ext}").format(student=str(student), ext=ext)
+ return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
+
+
class ParentalAuthorizationView(LoginRequiredMixin, View):
"""
Display the sent parental authorization.
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 4fa6039..2573a9d 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-02-20 00:20+0100\n"
+"POT-Creation-Date: 2023-02-20 00:37+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello \n"
"Language-Team: LANGUAGE \n"
@@ -100,83 +100,84 @@ msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
#: apps/participation/admin.py:19 apps/participation/models.py:318
-#: apps/participation/tables.py:44 apps/registration/models.py:353
+#: apps/participation/tables.py:44 apps/registration/models.py:364
msgid "valid"
msgstr "valide"
-#: apps/participation/forms.py:29
+#: apps/participation/forms.py:28
msgid "This name is already used."
msgstr "Ce nom est déjà utilisé."
-#: apps/participation/forms.py:36 apps/participation/models.py:40
+#: apps/participation/forms.py:35 apps/participation/models.py:40
msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules."
-#: apps/participation/forms.py:39
+#: apps/participation/forms.py:38
msgid "This trigram is already used."
msgstr "Ce trigramme est déjà utilisé."
-#: apps/participation/forms.py:54
+#: apps/participation/forms.py:53
msgid "No team was found with this access code."
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
-#: apps/participation/forms.py:83 apps/participation/forms.py:281
+#: apps/participation/forms.py:82 apps/participation/forms.py:280
#: apps/registration/forms.py:113 apps/registration/forms.py:135
-#: apps/registration/forms.py:157 apps/registration/forms.py:202
+#: apps/registration/forms.py:157 apps/registration/forms.py:179
+#: apps/registration/forms.py:224
msgid "The uploaded file size must be under 2 Mo."
msgstr "Le fichier envoyé doit peser moins de 2 Mo."
-#: apps/participation/forms.py:85 apps/registration/forms.py:115
+#: apps/participation/forms.py:84 apps/registration/forms.py:115
#: apps/registration/forms.py:137 apps/registration/forms.py:159
-#: apps/registration/forms.py:204
+#: apps/registration/forms.py:181 apps/registration/forms.py:226
msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG."
-#: apps/participation/forms.py:103
+#: apps/participation/forms.py:102
msgid "I engage myself to participate to the whole TFJM²."
msgstr "Je m'engage à participer à l'intégralité du TFJM²."
-#: apps/participation/forms.py:118
+#: apps/participation/forms.py:117
msgid "Message to address to the team:"
msgstr "Message à adresser à l'équipe :"
-#: apps/participation/forms.py:154
+#: apps/participation/forms.py:153
msgid "The uploaded file size must be under 5 Mo."
msgstr "Le fichier envoyé doit peser moins de 5 Mo."
-#: apps/participation/forms.py:156 apps/participation/forms.py:283
+#: apps/participation/forms.py:155 apps/participation/forms.py:282
msgid "The uploaded file must be a PDF file."
msgstr "Le fichier envoyé doit être au format PDF."
-#: apps/participation/forms.py:160
+#: apps/participation/forms.py:159
msgid "The PDF file must not have more than 30 pages."
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
-#: apps/participation/forms.py:197
+#: apps/participation/forms.py:196
msgid "CSV file:"
msgstr "Tableur au format CSV :"
-#: apps/participation/forms.py:214
+#: apps/participation/forms.py:213
msgid ""
"This file contains non-UTF-8 content. Please send your sheet as a CSV file."
msgstr ""
"Ce fichier contient des éléments non-UTF-8. Merci d'envoyer votre tableur au "
"format CSV."
-#: apps/participation/forms.py:239
+#: apps/participation/forms.py:238
msgid "The following note is higher of the maximum expected value:"
msgstr "La note suivante est supérieure au maximum attendu :"
-#: apps/participation/forms.py:247
+#: apps/participation/forms.py:246
msgid "The following user was not found:"
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
-#: apps/participation/forms.py:264
+#: apps/participation/forms.py:263
msgid "The defender, the opponent and the reporter must be different."
msgstr ""
"Læ défenseur⋅se, l'opposant⋅e et læ rapporteur⋅e doivent être différent⋅es."
-#: apps/participation/forms.py:268
+#: apps/participation/forms.py:267
msgid "This defender did not work on this problem."
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
@@ -211,7 +212,7 @@ msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})"
#: apps/participation/models.py:125 apps/participation/models.py:303
-#: apps/registration/models.py:123
+#: apps/registration/models.py:127
msgid "team"
msgstr "équipe"
@@ -597,14 +598,14 @@ msgstr "Rejoindre"
#: apps/participation/templates/participation/pool_detail.html:55
#: apps/participation/templates/participation/pool_detail.html:74
#: apps/participation/templates/participation/pool_detail.html:79
-#: apps/participation/templates/participation/team_detail.html:113
-#: apps/participation/templates/participation/team_detail.html:177
+#: apps/participation/templates/participation/team_detail.html:126
+#: apps/participation/templates/participation/team_detail.html:190
#: apps/participation/templates/participation/tournament_form.html:12
#: apps/participation/templates/participation/update_team.html:12
#: apps/registration/templates/registration/payment_form.html:49
#: apps/registration/templates/registration/update_user.html:16
-#: apps/registration/templates/registration/user_detail.html:155
-#: apps/registration/templates/registration/user_detail.html:187
+#: apps/registration/templates/registration/user_detail.html:165
+#: apps/registration/templates/registration/user_detail.html:202
msgid "Update"
msgstr "Modifier"
@@ -661,7 +662,7 @@ msgstr "Envoyer une solution"
#: apps/participation/templates/participation/participation_detail.html:59
#: apps/participation/templates/participation/passage_detail.html:114
#: apps/participation/templates/participation/pool_detail.html:84
-#: apps/participation/templates/participation/team_detail.html:172
+#: apps/participation/templates/participation/team_detail.html:185
#: apps/participation/templates/participation/upload_motivation_letter.html:13
#: apps/participation/templates/participation/upload_notes.html:12
#: apps/participation/templates/participation/upload_solution.html:11
@@ -669,10 +670,12 @@ msgstr "Envoyer une solution"
#: apps/registration/templates/registration/upload_health_sheet.html:17
#: apps/registration/templates/registration/upload_parental_authorization.html:17
#: apps/registration/templates/registration/upload_photo_authorization.html:18
-#: apps/registration/templates/registration/user_detail.html:165
-#: apps/registration/templates/registration/user_detail.html:170
+#: apps/registration/templates/registration/upload_vaccine_sheet.html:13
#: apps/registration/templates/registration/user_detail.html:175
#: apps/registration/templates/registration/user_detail.html:180
+#: apps/registration/templates/registration/user_detail.html:185
+#: apps/registration/templates/registration/user_detail.html:190
+#: apps/registration/templates/registration/user_detail.html:195
msgid "Upload"
msgstr "Téléverser"
@@ -852,7 +855,8 @@ msgstr "Autorisations de droit à l'image :"
#: apps/participation/templates/participation/team_detail.html:58
#: apps/participation/templates/participation/team_detail.html:71
#: apps/participation/templates/participation/team_detail.html:84
-#: apps/participation/templates/participation/team_detail.html:96
+#: apps/participation/templates/participation/team_detail.html:97
+#: apps/participation/templates/participation/team_detail.html:109
msgid "Not uploaded yet"
msgstr "Pas encore envoyée"
@@ -861,44 +865,50 @@ msgid "Health sheets:"
msgstr "Fiches sanitaires :"
#: apps/participation/templates/participation/team_detail.html:77
+msgid "Vaccine sheets:"
+msgstr "Carnets de vaccination :"
+
+#: apps/participation/templates/participation/team_detail.html:90
msgid "Parental authorizations:"
msgstr "Autorisations parentales :"
-#: apps/participation/templates/participation/team_detail.html:91
+#: apps/participation/templates/participation/team_detail.html:104
msgid "Motivation letter:"
msgstr "Lettre de motivation :"
-#: apps/participation/templates/participation/team_detail.html:94
+#: apps/participation/templates/participation/team_detail.html:107
#: apps/registration/templates/registration/upload_health_sheet.html:12
#: apps/registration/templates/registration/upload_parental_authorization.html:12
#: apps/registration/templates/registration/user_detail.html:62
#: apps/registration/templates/registration/user_detail.html:75
#: apps/registration/templates/registration/user_detail.html:85
+#: apps/registration/templates/registration/user_detail.html:95
msgid "Download"
msgstr "Télécharger"
-#: apps/participation/templates/participation/team_detail.html:99
+#: apps/participation/templates/participation/team_detail.html:112
#: apps/registration/templates/registration/user_detail.html:65
#: apps/registration/templates/registration/user_detail.html:78
#: apps/registration/templates/registration/user_detail.html:88
+#: apps/registration/templates/registration/user_detail.html:98
msgid "Replace"
msgstr "Remplacer"
-#: apps/participation/templates/participation/team_detail.html:107
+#: apps/participation/templates/participation/team_detail.html:120
msgid "Download all submitted authorizations"
msgstr "Télécharger toutes les autorisations soumises"
-#: apps/participation/templates/participation/team_detail.html:115
-#: apps/participation/templates/participation/team_detail.html:182
+#: apps/participation/templates/participation/team_detail.html:128
+#: apps/participation/templates/participation/team_detail.html:195
#: apps/participation/templates/participation/team_leave.html:11
msgid "Leave"
msgstr "Quitter"
-#: apps/participation/templates/participation/team_detail.html:125
+#: apps/participation/templates/participation/team_detail.html:138
msgid "Access to team participation"
msgstr "Accéder à la participation de l'équipe"
-#: apps/participation/templates/participation/team_detail.html:132
+#: apps/participation/templates/participation/team_detail.html:145
msgid ""
"Your team has at least 4 members and a coach and all authorizations were "
"given: the team can be validated."
@@ -906,11 +916,11 @@ msgstr ""
"Votre équipe contient au moins 4 personnes et un⋅e encadrant⋅e et toutes les "
"autorisations ont été données : l'équipe peut être validée."
-#: apps/participation/templates/participation/team_detail.html:137
+#: apps/participation/templates/participation/team_detail.html:150
msgid "Submit my team to validation"
msgstr "Soumettre mon équipe à validation"
-#: apps/participation/templates/participation/team_detail.html:143
+#: apps/participation/templates/participation/team_detail.html:156
msgid ""
"Your team must be composed of 4 members and a coach and each member must "
"upload their authorizations and confirm its email address."
@@ -918,15 +928,15 @@ msgstr ""
"Votre équipe doit être composée d'au moins 4 membres et un⋅e encadrant⋅e et "
"chaque membre doit envoyer ses autorisations et confirmé son adresse e-mail."
-#: apps/participation/templates/participation/team_detail.html:148
+#: apps/participation/templates/participation/team_detail.html:161
msgid "This team didn't ask for validation yet."
msgstr "L'équipe n'a pas encore demandé à être validée."
-#: apps/participation/templates/participation/team_detail.html:154
+#: apps/participation/templates/participation/team_detail.html:167
msgid "Your validation is pending."
msgstr "Votre validation est en attente."
-#: apps/participation/templates/participation/team_detail.html:158
+#: apps/participation/templates/participation/team_detail.html:171
msgid ""
"The team requested to be validated. You may now control the authorizations "
"and confirm that they can participate."
@@ -934,25 +944,25 @@ msgstr ""
"L'équipe a demandé à être validée. Vous pouvez désormais contrôler les "
"différentes autorisations et confirmer qu'elle peut participer."
-#: apps/participation/templates/participation/team_detail.html:164
+#: apps/participation/templates/participation/team_detail.html:177
msgid "Validate"
msgstr "Valider"
-#: apps/participation/templates/participation/team_detail.html:165
+#: apps/participation/templates/participation/team_detail.html:178
msgid "Invalidate"
msgstr "Invalider"
-#: apps/participation/templates/participation/team_detail.html:171
-#: apps/participation/views.py:332
+#: apps/participation/templates/participation/team_detail.html:184
+#: apps/participation/views.py:333
msgid "Upload motivation letter"
msgstr "Envoyer la lettre de motivation"
-#: apps/participation/templates/participation/team_detail.html:176
+#: apps/participation/templates/participation/team_detail.html:189
msgid "Update team"
msgstr "Modifier l'équipe"
-#: apps/participation/templates/participation/team_detail.html:181
-#: apps/participation/views.py:435
+#: apps/participation/templates/participation/team_detail.html:194
+#: apps/participation/views.py:442
msgid "Leave team"
msgstr "Quitter l'équipe"
@@ -1082,12 +1092,12 @@ msgstr "Vous êtes déjà dans une équipe."
msgid "Join team"
msgstr "Rejoindre une équipe"
-#: apps/participation/views.py:151 apps/participation/views.py:441
-#: apps/participation/views.py:475
+#: apps/participation/views.py:151 apps/participation/views.py:448
+#: apps/participation/views.py:482
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
-#: apps/participation/views.py:152 apps/participation/views.py:476
+#: apps/participation/views.py:152 apps/participation/views.py:483
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
@@ -1096,17 +1106,17 @@ msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
msgid "Detail of team {trigram}"
msgstr "Détails de l'équipe {trigram}"
-#: apps/participation/views.py:214
+#: apps/participation/views.py:215
msgid "You don't participate, so you can't request the validation of the team."
msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe."
-#: apps/participation/views.py:217
+#: apps/participation/views.py:218
msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
-#: apps/participation/views.py:220
+#: apps/participation/views.py:221
msgid ""
"The team can't be validated: missing email address confirmations, "
"authorizations, people, motivation letter or the tournament is not set."
@@ -1115,74 +1125,79 @@ msgstr ""
"d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre "
"de motivation, soit le tournoi n'a pas été choisi."
-#: apps/participation/views.py:242
+#: apps/participation/views.py:243
msgid "You are not an organizer of the tournament."
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi."
-#: apps/participation/views.py:245
+#: apps/participation/views.py:246
msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente."
-#: apps/participation/views.py:275
+#: apps/participation/views.py:276
msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non."
-#: apps/participation/views.py:310
+#: apps/participation/views.py:311
#, python-brace-format
msgid "Update team {trigram}"
msgstr "Mise à jour de l'équipe {trigram}"
-#: apps/participation/views.py:371 apps/participation/views.py:421
+#: apps/participation/views.py:372 apps/participation/views.py:428
#, python-brace-format
msgid "Motivation letter of {team}.{ext}"
msgstr "Lettre de motivation de {team}.{ext}"
-#: apps/participation/views.py:402
+#: apps/participation/views.py:403
#, python-brace-format
msgid "Photo authorization of {participant}.{ext}"
msgstr "Autorisation de droit à l'image de {participant}.{ext}"
-#: apps/participation/views.py:408
+#: apps/participation/views.py:409
#, python-brace-format
msgid "Parental authorization of {participant}.{ext}"
msgstr "Autorisation parentale de {participant}.{ext}"
-#: apps/participation/views.py:415
+#: apps/participation/views.py:416
#, python-brace-format
msgid "Health sheet of {participant}.{ext}"
msgstr "Fiche sanitaire de {participant}.{ext}"
-#: apps/participation/views.py:425
+#: apps/participation/views.py:422
+#, python-brace-format
+msgid "Vaccine sheet of {participant}.{ext}"
+msgstr "Carnet de vaccination de {participant}.{ext}"
+
+#: apps/participation/views.py:432
#, python-brace-format
msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
-#: apps/participation/views.py:443
+#: apps/participation/views.py:450
msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
-#: apps/participation/views.py:490
+#: apps/participation/views.py:497
msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée."
-#: apps/participation/views.py:504
+#: apps/participation/views.py:511
#, python-brace-format
msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}"
-#: apps/participation/views.py:630
+#: apps/participation/views.py:637
msgid "You can't upload a solution after the deadline."
msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
-#: apps/participation/views.py:733
+#: apps/participation/views.py:740
msgid "The following user is not registered as a jury:"
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
-#: apps/participation/views.py:741
+#: apps/participation/views.py:748
msgid "Notes were successfully uploaded."
msgstr "Les notes ont bien été envoyées."
-#: apps/participation/views.py:853
+#: apps/participation/views.py:860
msgid "You can't upload a synthesis after the deadline."
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
@@ -1194,7 +1209,7 @@ msgstr "rôle"
msgid "participant"
msgstr "participant⋅e"
-#: apps/registration/forms.py:25 apps/registration/models.py:270
+#: apps/registration/forms.py:25 apps/registration/models.py:281
msgid "coach"
msgstr "encadrant⋅e"
@@ -1202,11 +1217,11 @@ msgstr "encadrant⋅e"
msgid "This email address is already used."
msgstr "Cette adresse e-mail est déjà utilisée."
-#: apps/registration/forms.py:196
+#: apps/registration/forms.py:218
msgid "Pending"
msgstr "En attente"
-#: apps/registration/forms.py:212
+#: apps/registration/forms.py:234
msgid "You must upload your scholarship attestation."
msgstr "Vous devez envoyer votre attestation de bourse."
@@ -1223,7 +1238,7 @@ msgstr "email confirmé"
msgid "Activate your TFJM² account"
msgstr "Activez votre compte du TFJM²"
-#: apps/registration/models.py:99 apps/registration/models.py:319
+#: apps/registration/models.py:99 apps/registration/models.py:330
msgid "registration"
msgstr "inscription"
@@ -1231,43 +1246,43 @@ msgstr "inscription"
msgid "registrations"
msgstr "inscriptions"
-#: apps/registration/models.py:128
+#: apps/registration/models.py:132
msgid "gender"
msgstr "genre"
-#: apps/registration/models.py:130
+#: apps/registration/models.py:134
msgid "Female"
msgstr "Femme"
-#: apps/registration/models.py:131
+#: apps/registration/models.py:135
msgid "Male"
msgstr "Homme"
-#: apps/registration/models.py:132
+#: apps/registration/models.py:136
msgid "Other"
msgstr "Autre"
-#: apps/registration/models.py:139
+#: apps/registration/models.py:143
msgid "address"
msgstr "adresse"
-#: apps/registration/models.py:143
+#: apps/registration/models.py:147
msgid "zip code"
msgstr "code postal"
-#: apps/registration/models.py:149
+#: apps/registration/models.py:153
msgid "city"
msgstr "ville"
-#: apps/registration/models.py:153
+#: apps/registration/models.py:157
msgid "phone number"
msgstr "numéro de téléphone"
-#: apps/registration/models.py:158
+#: apps/registration/models.py:162
msgid "health issues"
msgstr "problèmes de santé"
-#: apps/registration/models.py:160
+#: apps/registration/models.py:164
msgid ""
"You can indicate here your allergies or anything that is important to know "
"for organizers"
@@ -1275,83 +1290,87 @@ msgstr ""
"Vous pouvez indiquer ici vos allergies ou n'importe quoi qui peut être bon à "
"savoir pour les organisateur⋅rices"
-#: apps/registration/models.py:164
+#: apps/registration/models.py:168
msgid "photo authorization"
msgstr "autorisation de droit à l'image"
-#: apps/registration/models.py:197
+#: apps/registration/models.py:201
msgid "birth date"
msgstr "date de naissance"
-#: apps/registration/models.py:203
+#: apps/registration/models.py:207
msgid "12th grade"
msgstr "Terminale"
-#: apps/registration/models.py:204
+#: apps/registration/models.py:208
msgid "11th grade"
msgstr "Première"
-#: apps/registration/models.py:205
+#: apps/registration/models.py:209
msgid "10th grade or lower"
msgstr "Seconde ou inférieur"
-#: apps/registration/models.py:207
+#: apps/registration/models.py:211
msgid "student class"
msgstr "classe"
-#: apps/registration/models.py:212
+#: apps/registration/models.py:216
msgid "school"
msgstr "école"
-#: apps/registration/models.py:217
+#: apps/registration/models.py:221
msgid "responsible name"
msgstr "nom de læ responsable légal⋅e"
-#: apps/registration/models.py:222
+#: apps/registration/models.py:226
msgid "responsible phone number"
msgstr "numéro de téléphone de læ responsable légal⋅e"
-#: apps/registration/models.py:227
+#: apps/registration/models.py:231
msgid "responsible email address"
msgstr "adresse e-mail de læ responsable légal⋅e"
-#: apps/registration/models.py:232
+#: apps/registration/models.py:236
msgid "parental authorization"
msgstr "autorisation parentale"
-#: apps/registration/models.py:239
+#: apps/registration/models.py:243
msgid "health sheet"
msgstr "fiche sanitaire"
-#: apps/registration/models.py:247
+#: apps/registration/models.py:250
+msgid "vaccine sheet"
+msgstr "carnet de vaccination"
+
+#: apps/registration/models.py:258
msgid "student"
msgstr "étudiant⋅e"
-#: apps/registration/models.py:255
+#: apps/registration/models.py:266
msgid "student registration"
msgstr "inscription d'élève"
-#: apps/registration/models.py:256
+#: apps/registration/models.py:267
msgid "student registrations"
msgstr "inscriptions d'élève"
-#: apps/registration/models.py:265 apps/registration/models.py:287
+#: apps/registration/models.py:276 apps/registration/models.py:298
msgid "professional activity"
msgstr "activité professionnelle"
-#: apps/registration/models.py:278
+#: apps/registration/models.py:289
msgid "coach registration"
msgstr "inscription d'encadrant⋅e"
-#: apps/registration/models.py:279
+#: apps/registration/models.py:290
msgid "coach registrations"
msgstr "inscriptions d'encadrant⋅es"
-#: apps/registration/models.py:291
+#: apps/registration/models.py:302
msgid "administrator"
msgstr "administrateur⋅rice"
-#: apps/registration/models.py:292
+#: apps/registration/models.py:303
msgid ""
"An administrator has all rights. Please don't give this right to all juries "
"and volunteers."
@@ -1359,64 +1378,64 @@ msgstr ""
"Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit "
"à toustes les juré⋅es et bénévoles."
-#: apps/registration/models.py:302
+#: apps/registration/models.py:313
msgid "admin"
msgstr "admin"
-#: apps/registration/models.py:302
+#: apps/registration/models.py:313
msgid "volunteer"
msgstr "bénévole"
-#: apps/registration/models.py:323
+#: apps/registration/models.py:334
msgid "type"
msgstr "type"
-#: apps/registration/models.py:326
+#: apps/registration/models.py:337
msgid "No payment"
msgstr "Pas de paiement"
-#: apps/registration/models.py:328
+#: apps/registration/models.py:339
msgid "Scholarship"
msgstr "Notification de bourse"
-#: apps/registration/models.py:329
+#: apps/registration/models.py:340
msgid "Bank transfer"
msgstr "Virement bancaire"
-#: apps/registration/models.py:330
+#: apps/registration/models.py:341
msgid "Other (please indicate)"
msgstr "Autre (veuillez spécifier)"
-#: apps/registration/models.py:331
+#: apps/registration/models.py:342
msgid "The tournament is free"
msgstr "Le tournoi est gratuit"
-#: apps/registration/models.py:338
+#: apps/registration/models.py:349
msgid "scholarship file"
msgstr "Notification de bourse"
-#: apps/registration/models.py:339
+#: apps/registration/models.py:350
msgid "only if you have a scholarship."
msgstr "Nécessaire seulement si vous déclarez être boursier."
-#: apps/registration/models.py:346
+#: apps/registration/models.py:357
msgid "additional information"
msgstr "informations additionnelles"
-#: apps/registration/models.py:347
+#: apps/registration/models.py:358
msgid "To help us to find your payment."
msgstr "Pour nous aider à retrouver votre paiement, si nécessaire."
-#: apps/registration/models.py:362
+#: apps/registration/models.py:373
#, python-brace-format
msgid "Payment of {registration}"
msgstr "Paiement de {registration}"
-#: apps/registration/models.py:365
+#: apps/registration/models.py:376
msgid "payment"
msgstr "paiement"
-#: apps/registration/models.py:366
+#: apps/registration/models.py:377
msgid "payments"
msgstr "paiements"
@@ -1640,6 +1659,7 @@ msgstr "Inscription"
#: apps/registration/templates/registration/upload_health_sheet.html:6
#: apps/registration/templates/registration/upload_parental_authorization.html:6
#: apps/registration/templates/registration/upload_photo_authorization.html:6
+#: apps/registration/templates/registration/upload_vaccine_sheet.html:6
msgid "Back to the user detail"
msgstr "Retour aux détails de l'utilisateur⋅rice"
@@ -1716,80 +1736,89 @@ msgid "Health sheet:"
msgstr "Fiche sanitaire :"
#: apps/registration/templates/registration/user_detail.html:82
+msgid "Vaccine sheet:"
+msgstr "Carnet de vaccination :"
+
+#: apps/registration/templates/registration/user_detail.html:92
msgid "Parental authorization:"
msgstr "Autorisation parentale :"
-#: apps/registration/templates/registration/user_detail.html:93
+#: apps/registration/templates/registration/user_detail.html:103
msgid "Student class:"
msgstr "Classe :"
-#: apps/registration/templates/registration/user_detail.html:96
+#: apps/registration/templates/registration/user_detail.html:106
msgid "School:"
msgstr "École :"
-#: apps/registration/templates/registration/user_detail.html:99
+#: apps/registration/templates/registration/user_detail.html:109
msgid "Responsible name:"
msgstr "Nom de læ responsable légal⋅e :"
-#: apps/registration/templates/registration/user_detail.html:102
+#: apps/registration/templates/registration/user_detail.html:112
msgid "Responsible phone number:"
msgstr "Numéro de téléphone de læ responsable légal⋅e :"
-#: apps/registration/templates/registration/user_detail.html:105
+#: apps/registration/templates/registration/user_detail.html:115
msgid "Responsible email address:"
msgstr "Adresse e-mail de læ responsable légal⋅e :"
-#: apps/registration/templates/registration/user_detail.html:110
+#: apps/registration/templates/registration/user_detail.html:120
msgid "Admin:"
msgstr "Administrateur⋅rice :"
-#: apps/registration/templates/registration/user_detail.html:113
+#: apps/registration/templates/registration/user_detail.html:123
msgid "Profesional activity:"
msgstr "Activité professionnelle :"
-#: apps/registration/templates/registration/user_detail.html:117
+#: apps/registration/templates/registration/user_detail.html:127
msgid "Grant Animath to contact me in the future about other actions:"
msgstr "Autorise Animath à recontacter à propos d'autres actions :"
-#: apps/registration/templates/registration/user_detail.html:125
+#: apps/registration/templates/registration/user_detail.html:135
msgid "Payment information:"
msgstr "Informations de paiement :"
-#: apps/registration/templates/registration/user_detail.html:127
+#: apps/registration/templates/registration/user_detail.html:137
msgid "yes,no,pending"
msgstr "oui,non,en attente"
-#: apps/registration/templates/registration/user_detail.html:131
-#: apps/registration/templates/registration/user_detail.html:134
+#: apps/registration/templates/registration/user_detail.html:141
+#: apps/registration/templates/registration/user_detail.html:144
msgid "valid:"
msgstr "valide :"
-#: apps/registration/templates/registration/user_detail.html:138
-#: apps/registration/templates/registration/user_detail.html:186
+#: apps/registration/templates/registration/user_detail.html:148
+#: apps/registration/templates/registration/user_detail.html:201
msgid "Update payment"
msgstr "Modifier le paiement"
-#: apps/registration/templates/registration/user_detail.html:144
+#: apps/registration/templates/registration/user_detail.html:154
msgid "Download scholarship attestation"
msgstr "Télécharger l'attestation de bourse"
-#: apps/registration/templates/registration/user_detail.html:157
+#: apps/registration/templates/registration/user_detail.html:167
msgid "Impersonate"
msgstr "Impersonifier"
-#: apps/registration/templates/registration/user_detail.html:164
+#: apps/registration/templates/registration/user_detail.html:174
#: apps/registration/views.py:312
msgid "Upload photo authorization"
msgstr "Téléverser l'autorisation de droit à l'image"
-#: apps/registration/templates/registration/user_detail.html:169
+#: apps/registration/templates/registration/user_detail.html:179
#: apps/registration/views.py:333
msgid "Upload health sheet"
msgstr "Téléverser la fiche sanitaire"
-#: apps/registration/templates/registration/user_detail.html:174
-#: apps/registration/templates/registration/user_detail.html:179
+#: apps/registration/templates/registration/user_detail.html:184
#: apps/registration/views.py:354
+msgid "Upload vaccine sheet"
+msgstr "Téléverser le carnet de vaccination"
+
+#: apps/registration/templates/registration/user_detail.html:189
+#: apps/registration/templates/registration/user_detail.html:194
+#: apps/registration/views.py:375
msgid "Upload parental authorization"
msgstr "Téléverser l'autorisation parentale"
@@ -1827,22 +1856,27 @@ msgstr "Détails de l'utilisateur⋅rice {user}"
msgid "Update user {user}"
msgstr "Mise à jour de l'utilisateur⋅rice {user}"
-#: apps/registration/views.py:460
+#: apps/registration/views.py:481
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
-#: apps/registration/views.py:483
+#: apps/registration/views.py:504
#, python-brace-format
msgid "Health sheet of {student}.{ext}"
msgstr "Fiche sanitaire de {student}.{ext}"
-#: apps/registration/views.py:506
+#: apps/registration/views.py:527
+#, python-brace-format
+msgid "Vaccine sheet of {student}.{ext}"
+msgstr "Carnet de vaccination de {student}.{ext}"
+
+#: apps/registration/views.py:550
#, python-brace-format
msgid "Parental authorization of {student}.{ext}"
msgstr "Autorisation parentale de {student}.{ext}"
-#: apps/registration/views.py:528
+#: apps/registration/views.py:572
#, python-brace-format
msgid "Scholarship attestation of {user}.{ext}"
msgstr "Notification de bourse de {user}.{ext}"
diff --git a/tfjm/urls.py b/tfjm/urls.py
index 517c9e4..bd365c6 100644
--- a/tfjm/urls.py
+++ b/tfjm/urls.py
@@ -23,7 +23,7 @@ from django.views.defaults import bad_request, page_not_found, permission_denied
from django.views.generic import TemplateView
from participation.views import MotivationLetterView
from registration.views import HealthSheetView, ParentalAuthorizationView, PhotoAuthorizationView, \
- ScholarshipView, SolutionView, SynthesisView
+ ScholarshipView, SolutionView, SynthesisView, VaccineSheetView
from .views import AdminSearchView
@@ -44,6 +44,8 @@ urlpatterns = [
name='photo_authorization'),
path('media/authorization/health//', HealthSheetView.as_view(),
name='health_sheet'),
+ path('media/authorization/vaccine//', VaccineSheetView.as_view(),
+ name='vaccine_sheet'),
path('media/authorization/parental//', ParentalAuthorizationView.as_view(),
name='parental_authorization'),
path('media/authorization/scholarship//', ScholarshipView.as_view(),