From 1493df0078771a016c04b80d1cad4d1207837075 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Sun, 7 Apr 2024 11:40:58 +0200 Subject: [PATCH] Implement final selection Signed-off-by: Emmy D'Anello --- locale/fr/LC_MESSAGES/django.po | 554 ++++++++++-------- participation/forms.py | 3 - participation/signals.py | 9 + .../templates/participation/team_detail.html | 28 + .../participation/tournament_detail.html | 19 +- participation/urls.py | 5 +- participation/views.py | 91 ++- registration/forms.py | 44 ++ ...tion_photo_authorization_final_and_more.py | 34 ++ registration/models.py | 31 +- .../upload_parental_authorization.html | 2 +- .../upload_photo_authorization.html | 4 +- .../templates/registration/user_detail.html | 87 ++- registration/urls.py | 4 + registration/views.py | 52 +- 15 files changed, 657 insertions(+), 310 deletions(-) create mode 100644 registration/migrations/0013_participantregistration_photo_authorization_final_and_more.py diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 0c2bda6..0b6e71f 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: 2024-04-07 09:33+0200\n" +"POT-Creation-Date: 2024-04-07 11:39+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Emmy D'Anello \n" "Language-Team: LANGUAGE \n" @@ -31,7 +31,7 @@ msgstr "équipes" #: participation/admin.py:79 participation/admin.py:140 #: participation/admin.py:171 participation/models.py:656 #: participation/models.py:680 participation/models.py:861 -#: registration/models.py:674 +#: registration/models.py:695 #: registration/templates/registration/payment_form.html:53 msgid "tournament" msgstr "tournoi" @@ -334,7 +334,7 @@ msgstr "Continuer le tirage" #: draw/templates/draw/tournament_content.html:216 participation/admin.py:167 #: participation/models.py:252 participation/models.py:671 #: participation/templates/participation/tournament_harmonize.html:15 -#: registration/models.py:157 registration/models.py:665 +#: registration/models.py:157 registration/models.py:686 #: registration/tables.py:39 #: registration/templates/registration/payment_form.html:52 msgid "team" @@ -378,8 +378,8 @@ msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?" msgid "Close" msgstr "Fermer" -#: draw/views.py:31 participation/views.py:161 participation/views.py:475 -#: participation/views.py:506 +#: draw/views.py:31 participation/views.py:161 participation/views.py:500 +#: participation/views.py:531 msgid "You are not in a team." msgstr "Vous n'êtes pas dans une équipe." @@ -475,73 +475,75 @@ msgstr "rapporteur⋅rice" msgid "problem" msgstr "numéro de problème" -#: participation/forms.py:32 +#: participation/forms.py:29 msgid "This name is already used." msgstr "Ce nom est déjà utilisé." -#: participation/forms.py:39 participation/models.py:42 +#: participation/forms.py:36 participation/models.py:42 msgid "The trigram must be composed of three uppercase letters." msgstr "Le trigramme doit être composé de trois lettres majuscules." -#: participation/forms.py:42 +#: participation/forms.py:39 msgid "This trigram is already used." msgstr "Ce trigramme est déjà utilisé." -#: participation/forms.py:57 +#: participation/forms.py:54 msgid "No team was found with this access code." msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." -#: participation/forms.py:61 participation/views.py:477 +#: participation/forms.py:58 participation/views.py:502 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: participation/forms.py:90 participation/forms.py:350 +#: participation/forms.py:87 participation/forms.py:347 #: registration/forms.py:122 registration/forms.py:144 #: registration/forms.py:166 registration/forms.py:188 -#: registration/forms.py:237 registration/forms.py:270 +#: registration/forms.py:210 registration/forms.py:232 +#: registration/forms.py:281 registration/forms.py:314 msgid "The uploaded file size must be under 2 Mo." msgstr "Le fichier envoyé doit peser moins de 2 Mo." -#: participation/forms.py:92 registration/forms.py:124 +#: participation/forms.py:89 registration/forms.py:124 #: registration/forms.py:146 registration/forms.py:168 -#: registration/forms.py:190 registration/forms.py:239 -#: registration/forms.py:272 +#: registration/forms.py:190 registration/forms.py:212 +#: registration/forms.py:234 registration/forms.py:283 +#: registration/forms.py:316 msgid "The uploaded file must be a PDF, PNG of JPEG file." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." -#: participation/forms.py:110 +#: participation/forms.py:107 msgid "I engage myself to participate to the whole TFJM²." msgstr "Je m'engage à participer à l'intégralité du TFJM²." -#: participation/forms.py:125 +#: participation/forms.py:122 msgid "Message to address to the team:" msgstr "Message à adresser à l'équipe :" -#: participation/forms.py:160 +#: participation/forms.py:157 msgid "The uploaded file size must be under 5 Mo." msgstr "Le fichier envoyé doit peser moins de 5 Mo." -#: participation/forms.py:162 participation/forms.py:352 +#: participation/forms.py:159 participation/forms.py:349 msgid "The uploaded file must be a PDF file." msgstr "Le fichier envoyé doit être au format PDF." -#: participation/forms.py:166 +#: participation/forms.py:163 msgid "The PDF file must not have more than 30 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages." -#: participation/forms.py:220 +#: participation/forms.py:217 msgid "Add" msgstr "Ajouter" -#: participation/forms.py:235 +#: participation/forms.py:232 msgid "This user already exists, but is a participant." msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e." -#: participation/forms.py:246 +#: participation/forms.py:243 msgid "Spreadsheet file:" msgstr "Fichier tableur :" -#: participation/forms.py:272 +#: participation/forms.py:269 msgid "" "This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your " "sheet as a CSV file." @@ -549,30 +551,30 @@ msgstr "" "Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci " "d'envoyer votre tableur au format CSV." -#: participation/forms.py:293 +#: participation/forms.py:290 msgid "Can't determine the pool size. Are you sure your file is correct?" msgstr "" "Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le " "fichier est correct ?" -#: participation/forms.py:313 +#: participation/forms.py:310 msgid "The following note is higher of the maximum expected value:" msgstr "La note suivante est supérieure au maximum attendu :" -#: participation/forms.py:319 +#: participation/forms.py:316 msgid "The following user was not found:" msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" -#: participation/forms.py:333 +#: participation/forms.py:330 msgid "The defender, the opponent and the reporter must be different." msgstr "" "Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es." -#: participation/forms.py:337 +#: participation/forms.py:334 msgid "This defender did not work on this problem." msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." -#: participation/forms.py:356 +#: participation/forms.py:353 msgid "The PDF file must not have more than 2 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages." @@ -718,7 +720,7 @@ msgstr "" "L'équipe {trigram} n'a pas encore été validée par les organisateurices. " "Merci de patienter." -#: participation/models.py:196 registration/models.py:493 +#: participation/models.py:196 registration/models.py:514 msgid "Pending validation" msgstr "Validation en attente" @@ -789,7 +791,7 @@ msgid "organizers" msgstr "organisateur⋅rices" #: participation/models.py:339 -#: participation/templates/participation/team_detail.html:133 +#: participation/templates/participation/team_detail.html:161 msgid "final" msgstr "finale" @@ -854,7 +856,7 @@ msgstr "" msgid "Solutions due" msgstr "Rendu des solutions" -#: participation/models.py:737 registration/models.py:518 +#: participation/models.py:737 registration/models.py:539 msgid "" "

The draw of the solutions for the tournament {tournament} is planned on " "the {date:%Y-%m-%d %H:%M}. You can join it on this link." @@ -864,7 +866,7 @@ msgstr "" "{date:%d/%m/%Y %H:%M}. Vous pouvez y participer sur ce lien.

" -#: participation/models.py:743 registration/models.py:525 +#: participation/models.py:743 registration/models.py:546 msgid "Draw of solutions" msgstr "Tirage au sort des solutions" @@ -902,7 +904,7 @@ msgstr "" "href='{solution_url}'>problème {problem}. Vous pouvez envoyer votre note " "de synthèse sur cette page.

" -#: participation/models.py:788 registration/models.py:540 +#: participation/models.py:788 registration/models.py:561 msgid "First round" msgstr "Premier tour" @@ -915,7 +917,7 @@ msgstr "" "

Pour le second tour, vous défendrez votre " "solution du problème {problem}.

" -#: participation/models.py:831 registration/models.py:551 +#: participation/models.py:831 registration/models.py:572 msgid "Second round" msgstr "Second tour" @@ -1166,14 +1168,14 @@ msgstr "Pas d'équipe définie" #: participation/templates/participation/passage_detail.html:167 #: participation/templates/participation/pool_detail.html:13 #: participation/templates/participation/pool_detail.html:157 -#: participation/templates/participation/team_detail.html:151 -#: participation/templates/participation/team_detail.html:215 +#: participation/templates/participation/team_detail.html:179 +#: participation/templates/participation/team_detail.html:243 #: participation/templates/participation/tournament_form.html:12 #: participation/templates/participation/update_team.html:12 #: registration/tables.py:46 #: registration/templates/registration/payment_form.html:210 #: registration/templates/registration/update_user.html:16 -#: registration/templates/registration/user_detail.html:186 +#: registration/templates/registration/user_detail.html:211 msgid "Update" msgstr "Modifier" @@ -1267,7 +1269,7 @@ msgstr "Envoyer une solution" #: participation/templates/participation/participation_detail.html:65 #: participation/templates/participation/passage_detail.html:173 #: participation/templates/participation/pool_detail.html:162 -#: participation/templates/participation/team_detail.html:210 +#: participation/templates/participation/team_detail.html:238 #: participation/templates/participation/upload_motivation_letter.html:13 #: participation/templates/participation/upload_notes.html:24 #: participation/templates/participation/upload_solution.html:11 @@ -1276,11 +1278,12 @@ msgstr "Envoyer une solution" #: registration/templates/registration/upload_parental_authorization.html:17 #: registration/templates/registration/upload_photo_authorization.html:18 #: registration/templates/registration/upload_vaccine_sheet.html:13 -#: registration/templates/registration/user_detail.html:196 -#: registration/templates/registration/user_detail.html:201 -#: registration/templates/registration/user_detail.html:206 -#: registration/templates/registration/user_detail.html:211 -#: registration/templates/registration/user_detail.html:216 +#: registration/templates/registration/user_detail.html:221 +#: registration/templates/registration/user_detail.html:227 +#: registration/templates/registration/user_detail.html:232 +#: registration/templates/registration/user_detail.html:237 +#: registration/templates/registration/user_detail.html:245 +#: registration/templates/registration/user_detail.html:251 msgid "Upload" msgstr "Téléverser" @@ -1541,79 +1544,93 @@ msgid "Photo authorizations:" msgstr "Autorisations de droit à l'image :" #: participation/templates/participation/team_detail.html:58 -#: participation/templates/participation/team_detail.html:71 +#: participation/templates/participation/team_detail.html:70 #: participation/templates/participation/team_detail.html:84 #: participation/templates/participation/team_detail.html:97 -#: participation/templates/participation/team_detail.html:109 +#: participation/templates/participation/team_detail.html:110 +#: participation/templates/participation/team_detail.html:124 +#: participation/templates/participation/team_detail.html:137 msgid "Not uploaded yet" msgstr "Pas encore envoyée" #: participation/templates/participation/team_detail.html:64 +msgid "Photo authorizations (final):" +msgstr "Autorisations de droit à l'image (finale) :" + +#: participation/templates/participation/team_detail.html:77 msgid "Health sheets:" msgstr "Fiches sanitaires :" -#: participation/templates/participation/team_detail.html:77 +#: participation/templates/participation/team_detail.html:90 msgid "Vaccine sheets:" msgstr "Carnets de vaccination :" -#: participation/templates/participation/team_detail.html:90 +#: participation/templates/participation/team_detail.html:103 msgid "Parental authorizations:" msgstr "Autorisations parentales :" -#: participation/templates/participation/team_detail.html:104 +#: participation/templates/participation/team_detail.html:117 +msgid "Parental authorizations (final):" +msgstr "Autorisations parentale (finale) :" + +#: participation/templates/participation/team_detail.html:132 msgid "Motivation letter:" msgstr "Lettre de motivation :" -#: participation/templates/participation/team_detail.html:107 +#: participation/templates/participation/team_detail.html:135 #: registration/templates/registration/payment_form.html:247 #: registration/templates/registration/payment_form.html:269 #: registration/templates/registration/upload_health_sheet.html:12 #: registration/templates/registration/upload_parental_authorization.html:12 #: registration/templates/registration/user_detail.html:69 -#: registration/templates/registration/user_detail.html:82 +#: registration/templates/registration/user_detail.html:80 #: registration/templates/registration/user_detail.html:92 #: registration/templates/registration/user_detail.html:102 +#: registration/templates/registration/user_detail.html:112 +#: registration/templates/registration/user_detail.html:123 msgid "Download" msgstr "Télécharger" -#: participation/templates/participation/team_detail.html:112 +#: participation/templates/participation/team_detail.html:140 #: registration/templates/registration/user_detail.html:72 -#: registration/templates/registration/user_detail.html:85 +#: registration/templates/registration/user_detail.html:82 #: registration/templates/registration/user_detail.html:95 #: registration/templates/registration/user_detail.html:105 +#: registration/templates/registration/user_detail.html:115 +#: registration/templates/registration/user_detail.html:125 msgid "Replace" msgstr "Remplacer" -#: participation/templates/participation/team_detail.html:120 +#: participation/templates/participation/team_detail.html:148 msgid "Download all submitted authorizations" msgstr "Télécharger toutes les autorisations soumises" -#: participation/templates/participation/team_detail.html:131 +#: participation/templates/participation/team_detail.html:159 msgid "Payment of" msgstr "Paiement de" -#: participation/templates/participation/team_detail.html:132 -#: registration/models.py:595 +#: participation/templates/participation/team_detail.html:160 +#: registration/models.py:616 msgid "grouped" msgstr "groupé" -#: participation/templates/participation/team_detail.html:140 -#: registration/templates/registration/user_detail.html:163 -#: registration/views.py:464 +#: participation/templates/participation/team_detail.html:168 +#: registration/templates/registration/user_detail.html:188 +#: registration/views.py:490 msgid "Update payment" msgstr "Mettre à jour le paiement" -#: participation/templates/participation/team_detail.html:153 -#: participation/templates/participation/team_detail.html:220 +#: participation/templates/participation/team_detail.html:181 +#: participation/templates/participation/team_detail.html:248 #: participation/templates/participation/team_leave.html:11 msgid "Leave" msgstr "Quitter" -#: participation/templates/participation/team_detail.html:163 +#: participation/templates/participation/team_detail.html:191 msgid "Access to team participation" msgstr "Accéder à la participation de l'équipe" -#: participation/templates/participation/team_detail.html:170 +#: participation/templates/participation/team_detail.html:198 msgid "" "Your team has at least 4 members and a coach and all authorizations were " "given: the team can be validated." @@ -1621,11 +1638,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." -#: participation/templates/participation/team_detail.html:175 +#: participation/templates/participation/team_detail.html:203 msgid "Submit my team to validation" msgstr "Soumettre mon équipe à validation" -#: participation/templates/participation/team_detail.html:181 +#: participation/templates/participation/team_detail.html:209 msgid "" "Your team must be composed of 4 members and a coach and each member must " "upload their authorizations and confirm its email address." @@ -1633,15 +1650,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." -#: participation/templates/participation/team_detail.html:186 +#: participation/templates/participation/team_detail.html:214 msgid "This team didn't ask for validation yet." msgstr "L'équipe n'a pas encore demandé à être validée." -#: participation/templates/participation/team_detail.html:192 +#: participation/templates/participation/team_detail.html:220 msgid "Your validation is pending." msgstr "Votre validation est en attente." -#: participation/templates/participation/team_detail.html:196 +#: participation/templates/participation/team_detail.html:224 msgid "" "The team requested to be validated. You may now control the authorizations " "and confirm that they can participate." @@ -1649,25 +1666,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." -#: participation/templates/participation/team_detail.html:202 +#: participation/templates/participation/team_detail.html:230 msgid "Validate" msgstr "Valider" -#: participation/templates/participation/team_detail.html:203 +#: participation/templates/participation/team_detail.html:231 msgid "Invalidate" msgstr "Invalider" -#: participation/templates/participation/team_detail.html:209 +#: participation/templates/participation/team_detail.html:237 #: participation/views.py:332 msgid "Upload motivation letter" msgstr "Envoyer la lettre de motivation" -#: participation/templates/participation/team_detail.html:214 +#: participation/templates/participation/team_detail.html:242 msgid "Update team" msgstr "Modifier l'équipe" -#: participation/templates/participation/team_detail.html:219 -#: participation/views.py:469 +#: participation/templates/participation/team_detail.html:247 +#: participation/views.py:494 msgid "Leave team" msgstr "Quitter l'équipe" @@ -1753,33 +1770,41 @@ msgstr "Accéder à la liste des paiements" msgid "Pools" msgstr "Poules" -#: participation/templates/participation/tournament_detail.html:115 +#: participation/templates/participation/tournament_detail.html:111 +msgid "Selected for final tournament" +msgstr "Sélectionnée pour la finale" + #: participation/templates/participation/tournament_detail.html:119 +msgid "Select for final tournament" +msgstr "Sélectionner pour la finale" + +#: participation/templates/participation/tournament_detail.html:132 +#: participation/templates/participation/tournament_detail.html:136 msgid "Harmonize" msgstr "Harmoniser" -#: participation/templates/participation/tournament_detail.html:115 -#: participation/templates/participation/tournament_detail.html:119 +#: participation/templates/participation/tournament_detail.html:132 +#: participation/templates/participation/tournament_detail.html:136 msgid "Day" msgstr "Jour" -#: participation/templates/participation/tournament_detail.html:128 +#: participation/templates/participation/tournament_detail.html:145 msgid "Publish notes for first round" msgstr "Publier les notes pour le premier tour" -#: participation/templates/participation/tournament_detail.html:133 +#: participation/templates/participation/tournament_detail.html:150 msgid "Unpublish notes for first round" msgstr "Dépublier les notes pour le premier tour" -#: participation/templates/participation/tournament_detail.html:139 +#: participation/templates/participation/tournament_detail.html:156 msgid "Publish notes for second round" msgstr "Publier les notes pour le second tour" -#: participation/templates/participation/tournament_detail.html:144 +#: participation/templates/participation/tournament_detail.html:161 msgid "Unpublish notes for second round" msgstr "Dépublier les notes pour le second tour" -#: participation/templates/participation/tournament_detail.html:156 +#: participation/templates/participation/tournament_detail.html:173 msgid "Files available for download" msgstr "Fichiers disponibles au téléchargement" @@ -1788,7 +1813,7 @@ msgid "Rank" msgstr "Rang" #: participation/templates/participation/tournament_harmonize.html:16 -#: registration/models.py:566 +#: registration/models.py:587 msgid "Note" msgstr "Note" @@ -1855,7 +1880,7 @@ msgstr "Vous êtes déjà dans une équipe." msgid "Join team" msgstr "Rejoindre une équipe" -#: participation/views.py:162 participation/views.py:507 +#: participation/views.py:162 participation/views.py:532 msgid "You don't participate, so you don't have any team." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." @@ -1900,150 +1925,158 @@ msgstr "Vous devez spécifier si vous validez l'inscription ou non." msgid "Update team {trigram}" msgstr "Mise à jour de l'équipe {trigram}" -#: participation/views.py:371 participation/views.py:454 +#: participation/views.py:371 participation/views.py:479 #, python-brace-format msgid "Motivation letter of {team}.{ext}" msgstr "Lettre de motivation de {team}.{ext}" -#: participation/views.py:403 +#: participation/views.py:404 #, python-brace-format msgid "Authorizations of team {trigram}.zip" msgstr "Autorisations de l'équipe {trigram}.zip" -#: participation/views.py:407 +#: participation/views.py:408 #, python-brace-format msgid "Authorizations of {tournament}.zip" msgstr "Autorisations du tournoi {tournament}.zip" -#: participation/views.py:423 +#: participation/views.py:427 #, python-brace-format msgid "Photo authorization of {participant}.{ext}" msgstr "Autorisation de droit à l'image de {participant}.{ext}" -#: participation/views.py:431 +#: participation/views.py:436 #, python-brace-format msgid "Parental authorization of {participant}.{ext}" msgstr "Autorisation parentale de {participant}.{ext}" -#: participation/views.py:439 +#: participation/views.py:444 #, python-brace-format msgid "Health sheet of {participant}.{ext}" msgstr "Fiche sanitaire de {participant}.{ext}" -#: participation/views.py:447 +#: participation/views.py:452 #, python-brace-format msgid "Vaccine sheet of {participant}.{ext}" msgstr "Carnet de vaccination de {participant}.{ext}" -#: participation/views.py:521 +#: participation/views.py:463 +msgid "Photo authorization of {participant} (final).{ext}" +msgstr "Autorisation de droit à l'image de {participant} (finale).{ext}" + +#: participation/views.py:472 +msgid "Parental authorization of {participant} (final).{ext}" +msgstr "Autorisation parentale de {participant} (finale).{ext}" + +#: participation/views.py:546 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: participation/views.py:535 +#: participation/views.py:560 #, python-brace-format msgid "Participation of team {trigram}" msgstr "Participation de l'équipe {trigram}" -#: participation/views.py:617 +#: participation/views.py:647 #, python-brace-format msgid "Payments of {tournament}" msgstr "Paiements de {tournament}" -#: participation/views.py:713 +#: participation/views.py:746 msgid "Notes published!" msgstr "Notes publiées !" -#: participation/views.py:715 +#: participation/views.py:748 msgid "Notes hidden!" msgstr "Notes dissimulées !" -#: participation/views.py:746 +#: participation/views.py:779 #, python-brace-format msgid "Harmonize notes of {tournament} - Day {round}" msgstr "Harmoniser les notes de {tournament} - Jour {round}" -#: participation/views.py:827 +#: participation/views.py:884 msgid "You can't upload a solution after the deadline." msgstr "Vous ne pouvez pas envoyer de solution après la date limite." -#: participation/views.py:944 +#: participation/views.py:1001 #, python-brace-format msgid "Solutions of team {trigram}.zip" msgstr "Solutions de l'équipe {trigram}.zip" -#: participation/views.py:944 +#: participation/views.py:1001 #, python-brace-format msgid "Syntheses of team {trigram}.zip" msgstr "Notes de synthèse de l'équipe {trigram}.zip" -#: participation/views.py:961 participation/views.py:976 +#: participation/views.py:1018 participation/views.py:1033 #, python-brace-format msgid "Solutions of {tournament}.zip" msgstr "Solutions de {tournament}.zip" -#: participation/views.py:961 participation/views.py:976 +#: participation/views.py:1018 participation/views.py:1033 #, python-brace-format msgid "Syntheses of {tournament}.zip" msgstr "Notes de synthèse de {tournament}.zip" -#: participation/views.py:985 +#: participation/views.py:1042 #, python-brace-format msgid "Solutions for pool {pool} of tournament {tournament}.zip" msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:986 +#: participation/views.py:1043 #, python-brace-format msgid "Syntheses for pool {pool} of tournament {tournament}.zip" msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:1028 +#: participation/views.py:1085 #, python-brace-format msgid "Jury of pool {pool} for {tournament} with teams {teams}" msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}" -#: participation/views.py:1044 +#: participation/views.py:1101 #, python-brace-format msgid "The jury {name} is already in the pool!" msgstr "{name} est déjà dans la poule !" -#: participation/views.py:1064 +#: participation/views.py:1121 msgid "New TFJM² jury account" msgstr "Nouveau compte de juré⋅e pour le TFJM²" -#: participation/views.py:1085 +#: participation/views.py:1142 #, python-brace-format msgid "The jury {name} has been successfully added!" msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" -#: participation/views.py:1121 +#: participation/views.py:1178 #, python-brace-format msgid "The jury {name} has been successfully removed!" msgstr "{name} a été retiré⋅e avec succès du jury !" -#: participation/views.py:1147 +#: participation/views.py:1204 #, python-brace-format msgid "The jury {name} has been successfully promoted president!" msgstr "{name} a été nommé⋅e président⋅e du jury !" -#: participation/views.py:1175 +#: participation/views.py:1232 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 :" -#: participation/views.py:1192 +#: participation/views.py:1249 msgid "Notes were successfully uploaded." msgstr "Les notes ont bien été envoyées." -#: participation/views.py:1825 +#: participation/views.py:1882 #, python-brace-format msgid "Notation sheets of pool {pool} of {tournament}.zip" msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:1830 +#: participation/views.py:1887 #, python-brace-format msgid "Notation sheets of {tournament}.zip" msgstr "Feuilles de notation de {tournament}.zip" -#: participation/views.py:2007 +#: participation/views.py:2064 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." @@ -2082,7 +2115,7 @@ msgstr "rôle" msgid "participant" msgstr "participant⋅e" -#: registration/forms.py:25 registration/models.py:427 +#: registration/forms.py:25 registration/models.py:448 msgid "coach" msgstr "encadrant⋅e" @@ -2090,11 +2123,11 @@ msgstr "encadrant⋅e" msgid "This email address is already used." msgstr "Cette adresse e-mail est déjà utilisée." -#: registration/forms.py:228 +#: registration/forms.py:272 msgid "Pending" msgstr "En attente" -#: registration/forms.py:247 registration/forms.py:280 +#: registration/forms.py:291 registration/forms.py:324 msgid "You must upload your receipt." msgstr "Vous devez envoyer votre justificatif." @@ -2126,7 +2159,7 @@ msgstr "" msgid "registration" msgstr "inscription" -#: registration/models.py:130 registration/models.py:591 +#: registration/models.py:130 registration/models.py:612 msgid "registrations" msgstr "inscriptions" @@ -2196,7 +2229,11 @@ msgstr "" msgid "photo authorization" msgstr "autorisation de droit à l'image" -#: registration/models.py:236 +#: registration/models.py:214 +msgid "photo authorization (final)" +msgstr "autorisation de droit à l'image (finale)" + +#: registration/models.py:250 #, python-brace-format msgid "" "You are not in a team. You can create one or ou rejoindre une équipe existante pour " "participer." -#: registration/models.py:242 +#: registration/models.py:256 msgid "No team" msgstr "Pas d'équipe" -#: registration/models.py:250 +#: registration/models.py:264 #, python-brace-format msgid "" "You have not uploaded your photo authorization. You can do it by clicking on " @@ -2219,71 +2256,75 @@ msgstr "" "Vous n'avez pas envoyé votre autorisation de droit à l'image. Vous pouvez le " "faire en cliquant sur ce lien." -#: registration/models.py:255 +#: registration/models.py:269 msgid "Photo authorization" msgstr "Autorisation de droit à l'image" -#: registration/models.py:266 +#: registration/models.py:280 msgid "participant registration" msgstr "inscription de participant⋅e" -#: registration/models.py:267 +#: registration/models.py:281 msgid "participant registrations" msgstr "inscriptions de participant⋅es" -#: registration/models.py:276 +#: registration/models.py:290 msgid "birth date" msgstr "date de naissance" -#: registration/models.py:282 +#: registration/models.py:296 msgid "12th grade" msgstr "Terminale" -#: registration/models.py:283 +#: registration/models.py:297 msgid "11th grade" msgstr "Première" -#: registration/models.py:284 +#: registration/models.py:298 msgid "10th grade or lower" msgstr "Seconde ou inférieur" -#: registration/models.py:286 +#: registration/models.py:300 msgid "student class" msgstr "classe" -#: registration/models.py:291 +#: registration/models.py:305 msgid "school" msgstr "école" -#: registration/models.py:296 +#: registration/models.py:310 msgid "responsible name" msgstr "nom d'un⋅e responsable légal⋅e" -#: registration/models.py:301 +#: registration/models.py:315 msgid "responsible phone number" msgstr "numéro de téléphone d'un⋅e responsable légal⋅e" -#: registration/models.py:306 +#: registration/models.py:320 msgid "responsible email address" msgstr "adresse e-mail d'un⋅e responsable légal⋅e" -#: registration/models.py:311 +#: registration/models.py:325 msgid "parental authorization" msgstr "autorisation parentale" -#: registration/models.py:318 +#: registration/models.py:332 +msgid "parental authorization (final)" +msgstr "autorisation parentale (finale)" + +#: registration/models.py:339 msgid "health sheet" msgstr "fiche sanitaire" -#: registration/models.py:325 +#: registration/models.py:346 msgid "vaccine sheet" msgstr "carnet de vaccination" -#: registration/models.py:333 +#: registration/models.py:354 msgid "student" msgstr "élève" -#: registration/models.py:344 +#: registration/models.py:365 #, python-brace-format msgid "" "You have not uploaded your parental authorization. You can do it by clicking " @@ -2292,11 +2333,11 @@ msgstr "" "Vous n'avez pas envoyé votre autorisation parentale. Vous pouvez le faire en " "cliquant sur ce lien." -#: registration/models.py:349 +#: registration/models.py:370 msgid "Parental authorization" msgstr "Autorisation parentale" -#: registration/models.py:355 +#: registration/models.py:376 #, python-brace-format msgid "" "You have not uploaded your health sheet. You can do it by clicking on ce lien." -#: registration/models.py:360 +#: registration/models.py:381 msgid "Health sheet" msgstr "Fiche sanitaire" -#: registration/models.py:366 +#: registration/models.py:387 #, python-brace-format msgid "" "You have not uploaded your vaccine sheet. You can do it by clicking on ce lien." -#: registration/models.py:371 +#: registration/models.py:392 msgid "Vaccine sheet" msgstr "Carnet de vaccination" -#: registration/models.py:380 +#: registration/models.py:401 #, python-brace-format msgid "" "You have to pay {amount} € for your registration, or send a scholarship " @@ -2333,27 +2374,27 @@ msgstr "" "notification de bourse ou un justificatif de paiement. Vous pouvez le faire " "sur la page de paiement." -#: registration/models.py:386 registration/models.py:395 +#: registration/models.py:407 registration/models.py:416 msgid "Payment" msgstr "Paiement" -#: registration/models.py:392 +#: registration/models.py:413 msgid "Your payment is under approval." msgstr "Votre paiement est en cours de validation." -#: registration/models.py:404 +#: registration/models.py:425 msgid "student registration" msgstr "inscription d'élève" -#: registration/models.py:405 +#: registration/models.py:426 msgid "student registrations" msgstr "inscriptions d'élève" -#: registration/models.py:416 +#: registration/models.py:437 msgid "most recent degree in mathematics, computer science or physics" msgstr "Dernier diplôme obtenu en mathématiques, informatique ou physique" -#: registration/models.py:417 +#: registration/models.py:438 msgid "" "Your most recent degree in maths, computer science or physics, or your last " "entrance exam (CAPES, Agrégation,…)" @@ -2361,23 +2402,23 @@ msgstr "" "Votre dernier diplôme en mathématiques, informatique ou physique, ou votre " "dernier concours obtenu (CAPES, Agrégation, …)" -#: registration/models.py:422 registration/models.py:444 +#: registration/models.py:443 registration/models.py:465 msgid "professional activity" msgstr "activité professionnelle" -#: registration/models.py:435 +#: registration/models.py:456 msgid "coach registration" msgstr "inscription d'encadrant⋅e" -#: registration/models.py:436 +#: registration/models.py:457 msgid "coach registrations" msgstr "inscriptions d'encadrant⋅es" -#: registration/models.py:448 +#: registration/models.py:469 msgid "administrator" msgstr "administrateur⋅rice" -#: registration/models.py:449 +#: registration/models.py:470 msgid "" "An administrator has all rights. Please don't give this right to all juries " "and volunteers." @@ -2385,15 +2426,15 @@ msgstr "" "Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit " "à toustes les juré⋅es et bénévoles." -#: registration/models.py:459 +#: registration/models.py:480 msgid "admin" msgstr "admin" -#: registration/models.py:459 +#: registration/models.py:480 msgid "volunteer" msgstr "bénévole" -#: registration/models.py:472 +#: registration/models.py:493 msgid "" "Registrations for tournament {tournament} are closing on {date:%Y-%m-%d %H:" "%M}. There are for now {validated_teams} validated teams (+ {pending_teams} " @@ -2403,11 +2444,11 @@ msgstr "" "%M}. Il y a pour l'instant {validated_teams} équipes validées (+ " "{pending_teams} en attente) sur {max_teams} attendues." -#: registration/models.py:480 +#: registration/models.py:501 msgid "Registrations" msgstr "Inscriptions" -#: registration/models.py:487 +#: registration/models.py:508 #, python-brace-format msgid "" "The team {trigram} requested to be validated for the tournament of " @@ -2418,7 +2459,7 @@ msgstr "" "Vous pouvez vérifier le statut de l'équipe sur la page de " "l'équipe." -#: registration/models.py:504 +#: registration/models.py:525 #, python-brace-format msgid "" "There are {valid} validated payments, {pending} pending and {invalid} " @@ -2429,11 +2470,11 @@ msgstr "" "invalides pour le tournoi {tournament}. Vous pouvez vérifier le statut des " "paiements sur la liste des paiements." -#: registration/models.py:511 +#: registration/models.py:532 msgid "Payments" msgstr "Paiements" -#: registration/models.py:535 registration/models.py:546 +#: registration/models.py:556 registration/models.py:567 #, python-brace-format msgid "" "

You are in the jury of the pool {pool} for the tournament of " @@ -2442,7 +2483,7 @@ msgstr "" "

Vous êtes dans le jury de la poule {pool} pour le tournoi {tournament}. " "Vous pouvez trouver la page de la poule ici.

" -#: registration/models.py:559 +#: registration/models.py:580 #, python-brace-format msgid "" "

You don't have given any note as a jury for the passage {passage} in the " @@ -2453,15 +2494,15 @@ msgstr "" "{passage} dans la poule {pool} de {tournament}. Vous pouvez donner vos notes " "ici.

" -#: registration/models.py:575 +#: registration/models.py:596 msgid "volunteer registration" msgstr "inscription de bénévole" -#: registration/models.py:576 +#: registration/models.py:597 msgid "volunteer registrations" msgstr "inscriptions de bénévoles" -#: registration/models.py:597 +#: registration/models.py:618 msgid "" "If set to true, then one payment is made for the full team, for example if " "the school pays for all." @@ -2469,100 +2510,100 @@ msgstr "" "Si vrai, alors un seul paiement est fait pour toute l'équipe, par exemple si " "le lycée paie pour tout le monde." -#: registration/models.py:602 +#: registration/models.py:623 msgid "total amount" msgstr "montant total" -#: registration/models.py:603 +#: registration/models.py:624 msgid "Corresponds to the total required amount to pay, in euros." msgstr "Correspond au montant total à payer, en euros." -#: registration/models.py:608 +#: registration/models.py:629 msgid "token" msgstr "jeton" -#: registration/models.py:611 +#: registration/models.py:632 msgid "A token to authorize external users to make this payment." msgstr "Un jeton pour autoriser des utilisateurs externes à faire ce paiement." -#: registration/models.py:615 +#: registration/models.py:636 msgid "for final tournament" msgstr "pour la finale" -#: registration/models.py:620 +#: registration/models.py:641 msgid "type" msgstr "type" -#: registration/models.py:623 +#: registration/models.py:644 msgid "No payment" msgstr "Pas de paiement" -#: registration/models.py:624 +#: registration/models.py:645 #: registration/templates/registration/payment_form.html:72 msgid "Credit card" msgstr "Carte bancaire" -#: registration/models.py:625 +#: registration/models.py:646 msgid "Scholarship" msgstr "Notification de bourse" -#: registration/models.py:626 +#: registration/models.py:647 #: registration/templates/registration/payment_form.html:77 msgid "Bank transfer" msgstr "Virement bancaire" -#: registration/models.py:627 +#: registration/models.py:648 msgid "Other (please indicate)" msgstr "Autre (veuillez spécifier)" -#: registration/models.py:628 +#: registration/models.py:649 msgid "The tournament is free" msgstr "Le tournoi est gratuit" -#: registration/models.py:635 +#: registration/models.py:656 msgid "Hello Asso checkout intent ID" msgstr "ID de l'intention de paiement Hello Asso" -#: registration/models.py:642 +#: registration/models.py:663 msgid "receipt" msgstr "justificatif" -#: registration/models.py:643 +#: registration/models.py:664 msgid "only if you have a scholarship or if you chose a bank transfer." msgstr "" "Nécessaire seulement si vous déclarez être boursièr⋅e ou si vous payez par " "virement bancaire." -#: registration/models.py:650 +#: registration/models.py:671 msgid "additional information" msgstr "informations additionnelles" -#: registration/models.py:651 +#: registration/models.py:672 msgid "To help us to find your payment." msgstr "Pour nous aider à retrouver votre paiement, si nécessaire." -#: registration/models.py:657 +#: registration/models.py:678 msgid "payment valid" msgstr "paiement valide" -#: registration/models.py:717 +#: registration/models.py:738 msgid "Reminder for your payment" msgstr "Rappel pour votre paiement" -#: registration/models.py:728 +#: registration/models.py:749 msgid "Payment confirmation" msgstr "Confirmation de paiement" -#: registration/models.py:750 +#: registration/models.py:771 #, python-brace-format msgid "Payment of {registrations}" msgstr "Paiements de {registrations}" -#: registration/models.py:753 +#: registration/models.py:774 msgid "payment" msgstr "paiement" -#: registration/models.py:754 +#: registration/models.py:775 msgid "payments" msgstr "paiements" @@ -2574,7 +2615,7 @@ msgstr "Pas encore de paiement." #: registration/templates/registration/add_organizer.html:12 #: registration/templates/registration/add_organizer.html:21 #: registration/templates/registration/user_list.html:9 -#: registration/views.py:90 +#: registration/views.py:92 msgid "Add organizer" msgstr "Ajouter un⋅e organisateur⋅rice" @@ -3070,7 +3111,7 @@ msgstr "" #: registration/templates/registration/signup.html:5 #: registration/templates/registration/signup.html:12 -#: registration/templates/registration/signup.html:26 registration/views.py:46 +#: registration/templates/registration/signup.html:26 registration/views.py:48 msgid "Sign up" msgstr "Inscription" @@ -3161,140 +3202,159 @@ msgstr "Contraintes de logement :" msgid "Photo authorization:" msgstr "Autorisation de droit à l'image :" -#: registration/templates/registration/user_detail.html:79 +#: registration/templates/registration/user_detail.html:77 +msgid "Photo authorization (final):" +msgstr "Autorisation de droit à l'image (finale) :" + +#: registration/templates/registration/user_detail.html:89 msgid "Health sheet:" msgstr "Fiche sanitaire :" -#: registration/templates/registration/user_detail.html:89 +#: registration/templates/registration/user_detail.html:99 msgid "Vaccine sheet:" msgstr "Carnet de vaccination :" -#: registration/templates/registration/user_detail.html:99 +#: registration/templates/registration/user_detail.html:109 msgid "Parental authorization:" msgstr "Autorisation parentale :" -#: registration/templates/registration/user_detail.html:110 +#: registration/templates/registration/user_detail.html:120 +msgid "Parental authorization (final):" +msgstr "Autorisation parentale (finale) :" + +#: registration/templates/registration/user_detail.html:130 msgid "Student class:" msgstr "Classe :" -#: registration/templates/registration/user_detail.html:113 +#: registration/templates/registration/user_detail.html:133 msgid "School:" msgstr "École :" -#: registration/templates/registration/user_detail.html:116 +#: registration/templates/registration/user_detail.html:136 msgid "Responsible name:" msgstr "Nom d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:119 +#: registration/templates/registration/user_detail.html:139 msgid "Responsible phone number:" msgstr "Numéro de téléphone d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:122 +#: registration/templates/registration/user_detail.html:142 msgid "Responsible email address:" msgstr "Adresse e-mail d'un⋅e responsable légal⋅e :" -#: registration/templates/registration/user_detail.html:127 +#: registration/templates/registration/user_detail.html:147 msgid "Most recent degree:" msgstr "Dernier diplôme obtenu :" -#: registration/templates/registration/user_detail.html:130 -#: registration/templates/registration/user_detail.html:134 +#: registration/templates/registration/user_detail.html:150 +#: registration/templates/registration/user_detail.html:154 msgid "Professional activity:" msgstr "Activité professionnelle :" -#: registration/templates/registration/user_detail.html:137 +#: registration/templates/registration/user_detail.html:157 msgid "Admin:" msgstr "Administrateur⋅rice :" -#: registration/templates/registration/user_detail.html:141 +#: registration/templates/registration/user_detail.html:161 msgid "Grant Animath to contact me in the future about other actions:" msgstr "Autorise Animath à recontacter à propos d'autres actions :" -#: registration/templates/registration/user_detail.html:150 +#: registration/templates/registration/user_detail.html:171 +msgid "Payment information (final):" +msgstr "Informations de paiement (finale) :" + +#: registration/templates/registration/user_detail.html:173 msgid "Payment information:" msgstr "Informations de paiement :" -#: registration/templates/registration/user_detail.html:152 +#: registration/templates/registration/user_detail.html:177 msgid "yes,no,pending" msgstr "oui,non,en attente" -#: registration/templates/registration/user_detail.html:156 -#: registration/templates/registration/user_detail.html:159 +#: registration/templates/registration/user_detail.html:181 +#: registration/templates/registration/user_detail.html:184 msgid "valid:" msgstr "valide :" -#: registration/templates/registration/user_detail.html:171 +#: registration/templates/registration/user_detail.html:196 msgid "Download scholarship attestation" msgstr "Télécharger l'attestation de bourse" -#: registration/templates/registration/user_detail.html:173 +#: registration/templates/registration/user_detail.html:198 msgid "Download bank transfer receipt" msgstr "Télécharger le justificatif de virement bancaire" -#: registration/templates/registration/user_detail.html:188 +#: registration/templates/registration/user_detail.html:213 msgid "Impersonate" msgstr "Impersonifier" -#: registration/templates/registration/user_detail.html:195 -#: registration/views.py:316 +#: registration/templates/registration/user_detail.html:220 +#: registration/views.py:317 msgid "Upload photo authorization" msgstr "Téléverser l'autorisation de droit à l'image" -#: registration/templates/registration/user_detail.html:200 -#: registration/views.py:337 +#: registration/templates/registration/user_detail.html:226 +#: registration/views.py:351 msgid "Upload health sheet" msgstr "Téléverser la fiche sanitaire" -#: registration/templates/registration/user_detail.html:205 -#: registration/views.py:358 +#: registration/templates/registration/user_detail.html:231 +#: registration/views.py:372 msgid "Upload vaccine sheet" msgstr "Téléverser le carnet de vaccination" -#: registration/templates/registration/user_detail.html:210 -#: registration/templates/registration/user_detail.html:215 -#: registration/views.py:379 +#: registration/templates/registration/user_detail.html:236 +#: registration/views.py:392 msgid "Upload parental authorization" msgstr "Téléverser l'autorisation parentale" -#: registration/views.py:122 +#: registration/templates/registration/user_detail.html:244 +msgid "Upload photo authorization (final)" +msgstr "Téléverser l'autorisation de droit à l'image (finale)" + +#: registration/templates/registration/user_detail.html:250 +msgid "Upload parental authorization (final)" +msgstr "Téléverser l'autorisation parentale (finale)" + +#: registration/views.py:124 msgid "New TFJM² organizer account" msgstr "Nouveau compte organisateur⋅rice pour le TFJM²" -#: registration/views.py:148 +#: registration/views.py:150 msgid "Email validation" msgstr "Validation de l'adresse mail" -#: registration/views.py:150 +#: registration/views.py:152 msgid "Validate email" msgstr "Valider l'adresse mail" -#: registration/views.py:189 +#: registration/views.py:191 msgid "Email validation unsuccessful" msgstr "Échec de la validation de l'adresse mail" -#: registration/views.py:200 +#: registration/views.py:202 msgid "Email validation email sent" msgstr "Mail de confirmation de l'adresse mail envoyé" -#: registration/views.py:208 +#: registration/views.py:210 msgid "Resend email validation link" msgstr "Renvoyé le lien de validation de l'adresse mail" -#: registration/views.py:251 +#: registration/views.py:253 #, python-brace-format msgid "Detail of user {user}" msgstr "Détails de l'utilisateur⋅rice {user}" -#: registration/views.py:276 +#: registration/views.py:278 #, python-brace-format msgid "Update user {user}" msgstr "Mise à jour de l'utilisateur⋅rice {user}" -#: registration/views.py:486 registration/views.py:520 +#: registration/views.py:512 registration/views.py:546 msgid "This payment is already valid or pending validation." msgstr "Le paiement est déjà validé ou en attente de validation." -#: registration/views.py:512 +#: registration/views.py:538 msgid "" "Since one payment is already validated, or pending validation, grouping is " "not possible." @@ -3302,34 +3362,34 @@ msgstr "" "Puisque un paiement est déjà validé, ou en attente de validation, le " "regroupement n'est pas possible." -#: registration/views.py:587 +#: registration/views.py:613 msgid "The payment is already valid or pending validation." msgstr "Le paiement est déjà validé ou en attente de validation." -#: registration/views.py:601 +#: registration/views.py:627 msgid "The payment is not found or is already validated." msgstr "Le paiement n'est pas trouvé ou déjà validé." -#: registration/views.py:620 +#: registration/views.py:646 #, python-brace-format msgid "An error occurred during the payment: {error}" msgstr "Une erreur est survenue lors du paiement : {error}" -#: registration/views.py:626 +#: registration/views.py:652 msgid "The payment has been refused." msgstr "Le paiement a été refusé." -#: registration/views.py:629 +#: registration/views.py:655 #, python-brace-format msgid "The return code is unknown: {code}" msgstr "Le code de retour est inconnu : {code}" -#: registration/views.py:632 +#: registration/views.py:658 #, python-brace-format msgid "The return type is unknown: {type}" msgstr "Le type de retour est inconnu : {type}" -#: registration/views.py:641 +#: registration/views.py:667 msgid "" "The payment has been successfully validated! Your registration is now " "complete." @@ -3337,7 +3397,7 @@ msgstr "" "Le paiement a été validé avec succès ! Votre inscription est désormais " "complète." -#: registration/views.py:648 +#: registration/views.py:674 msgid "" "Your payment is done! The validation of your payment may takes a few " "minutes, and will be automatically done. If it is not the case, please " @@ -3347,27 +3407,27 @@ msgstr "" "quelques minutes, et sera faite automatiquement. Si ce n'est pas le cas, " "merci de nous contacter." -#: registration/views.py:679 +#: registration/views.py:706 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}" -#: registration/views.py:703 +#: registration/views.py:730 #, python-brace-format msgid "Health sheet of {student}.{ext}" msgstr "Fiche sanitaire de {student}.{ext}" -#: registration/views.py:727 +#: registration/views.py:754 #, python-brace-format msgid "Vaccine sheet of {student}.{ext}" msgstr "Carnet de vaccination de {student}.{ext}" -#: registration/views.py:751 +#: registration/views.py:779 #, python-brace-format msgid "Parental authorization of {student}.{ext}" msgstr "Autorisation parentale de {student}.{ext}" -#: registration/views.py:775 +#: registration/views.py:803 #, python-brace-format msgid "Payment receipt of {registrations}.{ext}" msgstr "Justificatif de paiement de {registrations}.{ext}" diff --git a/participation/forms.py b/participation/forms.py index 08b0aed..fa5a2b0 100644 --- a/participation/forms.py +++ b/participation/forms.py @@ -1,11 +1,8 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later -import csv -import math from io import StringIO import re -from typing import Iterable from crispy_forms.helper import FormHelper from crispy_forms.layout import Div, Field, Submit diff --git a/participation/signals.py b/participation/signals.py index 5044e5c..e7c041f 100644 --- a/participation/signals.py +++ b/participation/signals.py @@ -64,6 +64,15 @@ def create_payments(instance: Participation, created, raw, **_): else: payment = Payment.objects.create(final=True) payment.registrations.add(student) + + payment_regional = Payment.objects.get(registrations=student, final=False) + if payment_regional.type == 'scholarship': + payment.type = 'scholarship' + with open(payment_regional.receipt.path, 'rb') as f: + payment.receipt.save(payment_regional.receipt.name, f) + payment.additional_information = payment_regional.additional_information + payment.fee = 0 + payment.valid = payment_regional.valid payment.save() payment.amount = Tournament.final_tournament().price if payment.amount == 0: diff --git a/participation/templates/participation/team_detail.html b/participation/templates/participation/team_detail.html index 93ee148..125625e 100644 --- a/participation/templates/participation/team_detail.html +++ b/participation/templates/participation/team_detail.html @@ -60,6 +60,19 @@ {% endfor %} + {% if team.participation.final %} +
{% trans "Photo authorizations (final):" %}
+
+ {% for participant in team.participants.all %} + {% if participant.photo_authorization_final %} + {{ participant }}{% if not forloop.last %},{% endif %} + {% else %} + {{ participant }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %} + {% endif %} + {% endfor %} +
+ {% endif %} + {% if not team.participation.tournament.remote %}
{% trans "Health sheets:" %}
@@ -99,6 +112,21 @@ {% endif %} {% endfor %}
+ + {% if team.participation.final %} +
{% trans "Parental authorizations (final):" %}
+
+ {% for student in team.students.all %} + {% if student.under_18_final %} + {% if student.parental_authorization_final %} + {{ student }}{% if not forloop.last %},{% endif %} + {% else %} + {{ student }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %} + {% endif %} + {% endif %} + {% endfor %} +
+ {% endif %} {% endif %}
{% trans "Motivation letter:" %}
diff --git a/participation/templates/participation/tournament_detail.html b/participation/templates/participation/tournament_detail.html index 18d68f7..0fc8535 100644 --- a/participation/templates/participation/tournament_detail.html +++ b/participation/templates/participation/tournament_detail.html @@ -103,7 +103,24 @@
    {% for participation, note in notes %} -
  • {{ participation.team }} : {{ note|floatformat }}
  • +
  • + {{ participation.team }} : {{ note|floatformat }} + {% if participation.final %} + + + {% trans "Selected for final tournament" %} + + {% endif %} + {% if user.registration.is_admin or user.registration in tournament.organizers.all %} + {% if team_selectable_for_final == participation %} + + + {% trans "Select for final tournament" %} + + {% endif %} + {% endif %} +
  • {% endfor %}
diff --git a/participation/urls.py b/participation/urls.py index 292ab1c..4125a4c 100644 --- a/participation/urls.py +++ b/participation/urls.py @@ -8,7 +8,8 @@ from .views import CreateTeamView, FinalNotationSheetTemplateView, GSheetNotific MyParticipationDetailView, MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, \ PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \ PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \ - ScaleNotationSheetTemplateView, SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \ + ScaleNotationSheetTemplateView, SelectTeamFinalView, \ + SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \ TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \ TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \ @@ -54,6 +55,8 @@ urlpatterns = [ name="tournament_harmonize"), path("tournament//harmonize////", TournamentHarmonizeNoteView.as_view(), name="tournament_harmonize_note"), + path("tournament//select-final//", SelectTeamFinalView.as_view(), + name="select_team_final"), path("pools/create/", PoolCreateView.as_view(), name="pool_create"), path("pools//", PoolDetailView.as_view(), name="pool_detail"), path("pools//update/", PoolUpdateView.as_view(), name="pool_update"), diff --git a/participation/views.py b/participation/views.py index e7ed4ef..cdbe1c4 100644 --- a/participation/views.py +++ b/participation/views.py @@ -399,6 +399,7 @@ class TeamAuthorizationsView(LoginRequiredMixin, View): def get(self, request, *args, **kwargs): if 'team_id' in kwargs: team = Team.objects.get(pk=kwargs["team_id"]) + tournament = team.participation.tournament teams = [team] filename = _("Authorizations of team {trigram}.zip").format(trigram=team.trigram) else: @@ -415,21 +416,25 @@ class TeamAuthorizationsView(LoginRequiredMixin, View): for participant in team.participants.all(): user_prefix = f"{team_prefix}{participant.user.first_name} {participant.user.last_name}/" - if participant.photo_authorization \ - and participant.photo_authorization.storage.exists(participant.photo_authorization.path): - mime_type = magic.from_file("media/" + participant.photo_authorization.name) - ext = mime_type.split("/")[1].replace("jpeg", "jpg") - zf.write("media/" + participant.photo_authorization.name, - user_prefix + _("Photo authorization of {participant}.{ext}") - .format(participant=str(participant), ext=ext)) + if 'team_id' in kwargs or not tournament.final: + # Don't include the photo authorization and the parental authorization of the regional tournament + # in the final authorizations + if participant.photo_authorization \ + and participant.photo_authorization.storage.exists(participant.photo_authorization.path): + mime_type = magic.from_file("media/" + participant.photo_authorization.name) + ext = mime_type.split("/")[1].replace("jpeg", "jpg") + zf.write("media/" + participant.photo_authorization.name, + user_prefix + _("Photo authorization of {participant}.{ext}") + .format(participant=str(participant), ext=ext)) - if participant.is_student and participant.parental_authorization \ - and participant.parental_authorization.storage.exists(participant.parental_authorization.path): - mime_type = magic.from_file("media/" + participant.parental_authorization.name) - ext = mime_type.split("/")[1].replace("jpeg", "jpg") - zf.write("media/" + participant.parental_authorization.name, - user_prefix + _("Parental authorization of {participant}.{ext}") - .format(participant=str(participant), ext=ext)) + if participant.is_student and participant.parental_authorization \ + and participant.parental_authorization.storage.exists( + participant.parental_authorization.path): + mime_type = magic.from_file("media/" + participant.parental_authorization.name) + ext = mime_type.split("/")[1].replace("jpeg", "jpg") + zf.write("media/" + participant.parental_authorization.name, + user_prefix + _("Parental authorization of {participant}.{ext}") + .format(participant=str(participant), ext=ext)) if participant.is_student and participant.health_sheet \ and participant.health_sheet.storage.exists(participant.health_sheet.path): @@ -447,6 +452,26 @@ class TeamAuthorizationsView(LoginRequiredMixin, View): user_prefix + _("Vaccine sheet of {participant}.{ext}") .format(participant=str(participant), ext=ext)) + if 'team_id' in kwargs or tournament.final: + # Don't include final authorizations in the regional authorizations + if participant.photo_authorization_final \ + and participant.photo_authorization_final.storage.exists( + participant.photo_authorization_final.path): + mime_type = magic.from_file("media/" + participant.photo_authorization_final.name) + ext = mime_type.split("/")[1].replace("jpeg", "jpg") + zf.write("media/" + participant.photo_authorization_final.name, + user_prefix + _("Photo authorization of {participant} (final).{ext}") + .format(participant=str(participant), ext=ext)) + + if participant.is_student and participant.parental_authorization_final \ + and participant.parental_authorization_final.storage.exists( + participant.parental_authorization_final.path): + mime_type = magic.from_file("media/" + participant.parental_authorization_final.name) + ext = mime_type.split("/")[1].replace("jpeg", "jpg") + zf.write("media/" + participant.parental_authorization_final.name, + user_prefix + _("Parental authorization of {participant} (final).{ext}") + .format(participant=str(participant), ext=ext)) + if team.motivation_letter and team.motivation_letter.storage.exists(team.motivation_letter.path): mime_type = magic.from_file("media/" + team.motivation_letter.name) ext = mime_type.split("/")[1].replace("jpeg", "jpg") @@ -591,10 +616,15 @@ class TournamentDetailView(MultiTableMixin, DetailView): or (self.request.user.is_authenticated and self.request.user.registration.is_volunteer)) if note: notes[participation] = note - context["notes"] = sorted(notes.items(), key=lambda x: x[1], reverse=True) + sorted_notes = sorted(notes.items(), key=lambda x: x[1], reverse=True) + context["notes"] = sorted_notes context["available_notes_1"] = all(pool.results_available for pool in self.object.pools.filter(round=1).all()) context["available_notes_2"] = all(pool.results_available for pool in self.object.pools.filter(round=2).all()) + if not self.object.final and notes and self.request.user.registration.is_volunteer: + context["team_selectable_for_final"] = next(participation for participation, _note in sorted_notes + if not participation.final) + return context def get_tables(self): @@ -625,8 +655,11 @@ class TournamentPaymentsView(VolunteerMixin, SingleTableMixin, DetailView): return super().dispatch(request, *args, **kwargs) def get_table_data(self): - return Payment.objects.filter(registrations__team__participation__tournament=self.get_object()) \ - .annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \ + if self.object.final: + payments = Payment.objects.filter(final=True) + else: + payments = Payment.objects.filter(registrations__team__participation__tournament=self.get_object()) + return payments.annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \ .distinct().all() @@ -795,6 +828,30 @@ class TournamentHarmonizeNoteView(VolunteerMixin, DetailView): return redirect(reverse_lazy("participation:tournament_harmonize", args=(tournament.pk, kwargs['round'],))) +class SelectTeamFinalView(VolunteerMixin, DetailView): + model = Tournament + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + tournament = self.get_object() + reg = request.user.registration + if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()): + return self.handle_no_permission() + participation_qs = tournament.participations.filter(pk=self.kwargs["participation_id"]) + if not participation_qs.exists(): + raise Http404 + self.participation = participation_qs.get() + return super().dispatch(request, *args, **kwargs) + + @transaction.atomic + def get(self, request, *args, **kwargs): + tournament = self.get_object() + self.participation.final = True + self.participation.save() + return redirect(reverse_lazy("participation:tournament_detail", args=(tournament.pk,))) + + class SolutionUploadView(LoginRequiredMixin, FormView): template_name = "participation/upload_solution.html" form_class = SolutionForm diff --git a/registration/forms.py b/registration/forms.py index dc6c3d6..1ed5f95 100644 --- a/registration/forms.py +++ b/registration/forms.py @@ -133,6 +133,28 @@ class PhotoAuthorizationForm(forms.ModelForm): fields = ('photo_authorization',) +class PhotoAuthorizationFinalForm(forms.ModelForm): + """ + Form to send a photo authorization. + """ + def clean_photo_authorization_final(self): + if "photo_authorization_final" in self.files: + file = self.files["photo_authorization_final"] + 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["photo_authorization_final"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields["photo_authorization_final"].widget = FileInput() + + class Meta: + model = ParticipantRegistration + fields = ('photo_authorization_final',) + + class HealthSheetForm(forms.ModelForm): """ Form to send a health sheet. @@ -199,6 +221,28 @@ class ParentalAuthorizationForm(forms.ModelForm): fields = ('parental_authorization',) +class ParentalAuthorizationFinalForm(forms.ModelForm): + """ + Form to send a parental authorization. + """ + def clean_parental_authorization(self): + if "parental_authorization_final" in self.files: + file = self.files["parental_authorization_final"] + 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["parental_authorization"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields["parental_authorization_final"].widget = FileInput() + + class Meta: + model = StudentRegistration + fields = ('parental_authorization_final',) + + class CoachRegistrationForm(forms.ModelForm): """ A coach can tell its professional activity. diff --git a/registration/migrations/0013_participantregistration_photo_authorization_final_and_more.py b/registration/migrations/0013_participantregistration_photo_authorization_final_and_more.py new file mode 100644 index 0000000..4918db7 --- /dev/null +++ b/registration/migrations/0013_participantregistration_photo_authorization_final_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 5.0.3 on 2024-04-07 08:34 + +import registration.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("registration", "0012_payment_token_alter_payment_type"), + ] + + operations = [ + migrations.AddField( + model_name="participantregistration", + name="photo_authorization_final", + field=models.FileField( + blank=True, + default="", + upload_to=registration.models.get_random_photo_filename, + verbose_name="photo authorization (final)", + ), + ), + migrations.AddField( + model_name="studentregistration", + name="parental_authorization_final", + field=models.FileField( + blank=True, + default="", + upload_to=registration.models.get_random_parental_filename, + verbose_name="parental authorization (final)", + ), + ), + ] diff --git a/registration/models.py b/registration/models.py index 97de14c..5e9a882 100644 --- a/registration/models.py +++ b/registration/models.py @@ -210,17 +210,31 @@ class ParticipantRegistration(Registration): default="", ) + photo_authorization_final = models.FileField( + verbose_name=_("photo authorization (final)"), + upload_to=get_random_photo_filename, + blank=True, + default="", + ) + @property def under_18(self): if isinstance(self, CoachRegistration): return False # In normal case - important_date = timezone.now().date() + important_date = localtime(timezone.now()).date() if self.team and self.team.participation.tournament: important_date = self.team.participation.tournament.date_start - if self.team.participation.final: - from participation.models import Tournament - important_date = Tournament.final_tournament().date_start - return (important_date - self.birth_date).days < 18 * 365.24 + over_18_on = self.birth_date.replace(year=self.birth_date.year + 18) + return important_date < over_18_on + + @property + def under_18_final(self): + if isinstance(self, CoachRegistration): + return False # In normal case + from participation.models import Tournament + important_date = Tournament.final_tournament().date_start + over_18_on = self.birth_date.replace(year=self.birth_date.year + 18) + return important_date < over_18_on @property def type(self): # pragma: no cover @@ -314,6 +328,13 @@ class StudentRegistration(ParticipantRegistration): default="", ) + parental_authorization_final = models.FileField( + verbose_name=_("parental authorization (final)"), + upload_to=get_random_parental_filename, + blank=True, + default="", + ) + health_sheet = models.FileField( verbose_name=_("health sheet"), upload_to=get_random_health_filename, diff --git a/registration/templates/registration/upload_parental_authorization.html b/registration/templates/registration/upload_parental_authorization.html index 117e1fc..58688bf 100644 --- a/registration/templates/registration/upload_parental_authorization.html +++ b/registration/templates/registration/upload_parental_authorization.html @@ -9,7 +9,7 @@
{% trans "Authorization template:" %} - {% trans "Download" %} + {% trans "Download" %}
{% csrf_token %} {{ form|crispy }} diff --git a/registration/templates/registration/upload_photo_authorization.html b/registration/templates/registration/upload_photo_authorization.html index 9b6109c..5b25608 100644 --- a/registration/templates/registration/upload_photo_authorization.html +++ b/registration/templates/registration/upload_photo_authorization.html @@ -9,8 +9,8 @@
{% trans "Authorization templates:" %} - {% trans "Adult" %} — - {% trans "Child" %} + {% trans "Adult" %} — + {% trans "Child" %}
{% csrf_token %} {{ form|crispy }} diff --git a/registration/templates/registration/user_detail.html b/registration/templates/registration/user_detail.html index a5f1c72..a799b15 100644 --- a/registration/templates/registration/user_detail.html +++ b/registration/templates/registration/user_detail.html @@ -72,6 +72,16 @@ {% endif %} + + {% if user_object.registration.team.participation.final %} +
{% trans "Photo authorization (final):" %}
+
+ {% if user_object.registration.photo_authorization_final %} + {% trans "Download" %} + {% endif %} + +
+ {% endif %} {% endif %} {% if user_object.registration.studentregistration %} @@ -105,6 +115,16 @@ {% endif %} + + {% if user_object.registration.team.participation.final %} +
{% trans "Parental authorization (final):" %}
+
+ {% if user_object.registration.parental_authorization_final %} + {% trans "Download" %} + {% endif %} + +
+ {% endif %} {% endif %}
{% trans "Student class:" %}
@@ -143,11 +163,16 @@ {% if user_object.registration.participates and user_object.registration.team.participation.valid %} +
{% for payment in user_object.registration.payments.all %} -
-
-
{% trans "Payment information:" %}
+
+ {% if payment.final %} + {% trans "Payment information (final):" %} + {% else %} + {% trans "Payment information:" %} + {% endif %} +
{% trans "yes,no,pending" as yesnodefault %} {% with info=payment.additional_information %} @@ -197,25 +222,36 @@ {% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk as modal_action %} {% include "base_modal.html" with modal_id="uploadPhotoAuthorization" modal_enctype="multipart/form-data" %} - {% trans "Upload health sheet" as modal_title %} - {% trans "Upload" as modal_button %} - {% 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" %} + {% if user_object.registration.under_18 %} + {% trans "Upload health sheet" as modal_title %} + {% trans "Upload" as modal_button %} + {% 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 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 %} - {% include "base_modal.html" with modal_id="uploadParentalAuthorization" 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 %} + {% include "base_modal.html" with modal_id="uploadParentalAuthorization" modal_enctype="multipart/form-data" %} + {% endif %} + {% endif %} - {% trans "Upload parental authorization" as modal_title %} + {% if user_object.registration.team.participation.final %} + {% trans "Upload photo authorization (final)" as modal_title %} {% trans "Upload" as modal_button %} - {% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %} - {% include "base_modal.html" with modal_id="uploadParentalAuthorization" modal_enctype="multipart/form-data" %} + {% url "registration:upload_user_photo_authorization_final" pk=user_object.registration.pk as modal_action %} + {% include "base_modal.html" with modal_id="uploadPhotoAuthorizationFinal" modal_enctype="multipart/form-data" %} + + {% if user_object.registration.under_18_final %} + {% trans "Upload parental authorization (final)" as modal_title %} + {% trans "Upload" as modal_button %} + {% url "registration:upload_user_parental_authorization_final" pk=user_object.registration.pk as modal_action %} + {% include "base_modal.html" with modal_id="uploadParentalAuthorizationFinal" modal_enctype="multipart/form-data" %} + {% endif %} {% endif %} {% endblock %} @@ -224,9 +260,18 @@ document.addEventListener('DOMContentLoaded', () => { {% if user_object.registration.team and not user_object.registration.team.participation.valid %} initModal("uploadPhotoAuthorization", "{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk %}") - initModal("uploadHealthSheet", "{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk %}") - initModal("uploadVaccineSheet", "{% url "registration:upload_user_vaccine_sheet" pk=user_object.registration.pk %}") - initModal("uploadParentalAuthorization", "{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk %}") + {% if user_object.registration.under_18 %} + initModal("uploadHealthSheet", "{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk %}") + initModal("uploadVaccineSheet", "{% url "registration:upload_user_vaccine_sheet" pk=user_object.registration.pk %}") + initModal("uploadParentalAuthorization", "{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk %}") + {% endif %} + {% endif %} + + {% if user_object.registration.team.participation.final %} + initModal("uploadPhotoAuthorizationFinal", "{% url "registration:upload_user_photo_authorization_final" pk=user_object.registration.pk %}") + {% if user_object.registration.under_18_final %} + initModal("uploadParentalAuthorizationFinal", "{% url "registration:upload_user_parental_authorization_final" pk=user_object.registration.pk %}") + {% endif %} {% endif %} }); diff --git a/registration/urls.py b/registration/urls.py index 38c0872..d5654a7 100644 --- a/registration/urls.py +++ b/registration/urls.py @@ -24,6 +24,8 @@ urlpatterns = [ path("user//update/", UserUpdateView.as_view(), name="update_user"), path("user//upload-photo-authorization/", UserUploadPhotoAuthorizationView.as_view(), name="upload_user_photo_authorization"), + path("user//upload-photo-authorization/final/", UserUploadPhotoAuthorizationView.as_view(), + name="upload_user_photo_authorization_final"), path("parental-authorization-template/", ParentalAuthorizationTemplateView.as_view(), name="parental_authorization_template"), path("photo-authorization-template/adult/", AdultPhotoAuthorizationTemplateView.as_view(), @@ -37,6 +39,8 @@ urlpatterns = [ name="upload_user_vaccine_sheet"), path("user//upload-parental-authorization/", UserUploadParentalAuthorizationView.as_view(), name="upload_user_parental_authorization"), + path("user//upload-parental-authorization/final/", UserUploadParentalAuthorizationView.as_view(), + name="upload_user_parental_authorization_final"), path("update-payment//", PaymentUpdateView.as_view(), name="update_payment"), path("update-payment//toggle-group-mode/", PaymentUpdateGroupView.as_view(), name="update_payment_group_mode"), diff --git a/registration/views.py b/registration/views.py index 2d2d5af..858ee07 100644 --- a/registration/views.py +++ b/registration/views.py @@ -1,5 +1,6 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later + import json import os import subprocess @@ -29,8 +30,9 @@ from participation.models import Passage, Solution, Synthesis, Tournament from tfjm.tokens import email_validation_token from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin -from .forms import AddOrganizerForm, CoachRegistrationForm, HealthSheetForm, ParentalAuthorizationForm, \ - PaymentAdminForm, PaymentForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \ +from .forms import AddOrganizerForm, CoachRegistrationForm, HealthSheetForm, \ + PhotoAuthorizationFinalForm, ParentalAuthorizationForm, PaymentAdminForm, PaymentForm, \ + ParentalAuthorizationFinalForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \ VaccineSheetForm, VolunteerRegistrationForm from .models import ParticipantRegistration, Payment, Registration, StudentRegistration from .tables import RegistrationTable @@ -311,15 +313,27 @@ class UserUploadPhotoAuthorizationView(UserRegistrationMixin, UpdateView): A participant can send its photo authorization. """ model = ParticipantRegistration - form_class = PhotoAuthorizationForm template_name = "registration/upload_photo_authorization.html" extra_context = dict(title=_("Upload photo authorization")) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + if self.object.team: + tournament = self.object.team.participation.tournament \ + if 'final' not in self.request.path else Tournament.final_tournament() + context["tournament"] = tournament + return context + + def get_form_class(self): + return PhotoAuthorizationForm if 'final' not in self.request.path else PhotoAuthorizationFinalForm + @transaction.atomic def form_valid(self, form): - old_instance = ParticipantRegistration.objects.get(pk=self.object.pk) - if old_instance.photo_authorization: - old_instance.photo_authorization.delete() + old_instance: ParticipantRegistration = ParticipantRegistration.objects.get(pk=self.object.pk) + old_field = old_instance.photo_authorization \ + if 'final' not in self.request.path else old_instance.photo_authorization_final + if old_field: + old_field.delete() old_instance.save() return super().form_valid(form) @@ -374,15 +388,27 @@ class UserUploadParentalAuthorizationView(UserRegistrationMixin, UpdateView): A participant can send its parental authorization. """ model = StudentRegistration - form_class = ParentalAuthorizationForm template_name = "registration/upload_parental_authorization.html" extra_context = dict(title=_("Upload parental authorization")) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + if self.object.team: + tournament = self.object.team.participation.tournament \ + if 'final' not in self.request.path else Tournament.final_tournament() + context["tournament"] = tournament + return context + + def get_form_class(self): + return ParentalAuthorizationForm if 'final' not in self.request.path else ParentalAuthorizationFinalForm + @transaction.atomic def form_valid(self, form): - old_instance = StudentRegistration.objects.get(pk=self.object.pk) - if old_instance.parental_authorization: - old_instance.parental_authorization.delete() + old_instance: StudentRegistration = StudentRegistration.objects.get(pk=self.object.pk) + old_field = old_instance.parental_authorization \ + if 'final' not in self.request.path else old_instance.parental_authorization_final + if old_field: + old_field.delete() old_instance.save() return super().form_valid(form) @@ -666,7 +692,8 @@ class PhotoAuthorizationView(LoginRequiredMixin, View): path = f"media/authorization/photo/{filename}" if not os.path.exists(path): raise Http404 - student = ParticipantRegistration.objects.get(photo_authorization__endswith=filename) + student = ParticipantRegistration.objects.get(Q(photo_authorization__endswith=filename) + | Q(photo_authorization_final__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()): @@ -738,7 +765,8 @@ class ParentalAuthorizationView(LoginRequiredMixin, View): path = f"media/authorization/parental/{filename}" if not os.path.exists(path): raise Http404 - student = StudentRegistration.objects.get(parental_authorization__endswith=filename) + student = StudentRegistration.objects.get(Q(parental_authorization__endswith=filename) + | Q(parental_authorization_final__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()):