From 0f2c44331c3e44b93356fbed083e0e11d82f2198 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Mon, 20 Feb 2023 00:38:57 +0100 Subject: [PATCH] Add vaccine sheet field, closes #18 --- .../templates/participation/team_detail.html | 13 + apps/participation/tests.py | 5 + apps/participation/views.py | 7 + apps/registration/forms.py | 22 ++ .../0005_studentregistration_vaccine_sheet.py | 19 + apps/registration/models.py | 11 + .../registration/upload_vaccine_sheet.html | 15 + .../templates/registration/user_detail.html | 15 + apps/registration/urls.py | 4 +- apps/registration/views.py | 46 ++- locale/fr/LC_MESSAGES/django.po | 324 ++++++++++-------- tfjm/urls.py | 4 +- 12 files changed, 337 insertions(+), 148 deletions(-) create mode 100644 apps/registration/migrations/0005_studentregistration_vaccine_sheet.py create mode 100644 apps/registration/templates/registration/upload_vaccine_sheet.html 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" %} +
+
+
+ {% csrf_token %} + {{ form|crispy }} +
+ +
+{% 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(),