mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-07-07 18:40:15 +02:00
Compare commits
21 Commits
d24f8cab16
...
main
Author | SHA1 | Date | |
---|---|---|---|
905b96fbcf
|
|||
be2e258948
|
|||
882570800c
|
|||
df31968a77
|
|||
df6fb3b3f3
|
|||
3807fbcf45
|
|||
8433390e19
|
|||
ec85f62ab6
|
|||
74b2a0c095
|
|||
67958335ab
|
|||
20410cc17f
|
|||
a5aff5ff21
|
|||
196dbc8275
|
|||
0847e5a308
|
|||
e5aa3ef059
|
|||
e1b4e1bb6b
|
|||
ecc59a6c8c
|
|||
b053a47a19
|
|||
ab2e49e8fb
|
|||
fe399c869d
|
|||
9de8a2ed0e
|
@ -2,15 +2,6 @@ stages:
|
||||
- test
|
||||
- quality-assurance
|
||||
|
||||
py311:
|
||||
stage: test
|
||||
image: python:3.11-alpine
|
||||
before_script:
|
||||
- apk add --no-cache libmagic
|
||||
- apk add --no-cache gettext
|
||||
- pip install tox --no-cache-dir
|
||||
script: tox -e py311
|
||||
|
||||
py312:
|
||||
stage: test
|
||||
image: python:3.12-alpine
|
||||
|
@ -3,7 +3,8 @@ FROM python:3.13-alpine
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV DJANGO_ALLOW_ASYNC_UNSAFE 1
|
||||
|
||||
RUN apk add --no-cache gettext nginx gcc git libc-dev libffi-dev libxml2-dev libxslt-dev npm postgresql-dev libmagic texlive texmf-dist-fontsrecommended texmf-dist-lang texmf-dist-latexextra
|
||||
RUN apk add --no-cache gettext nginx gcc git libc-dev libffi-dev libpq-dev libxml2-dev libxslt-dev \
|
||||
npm libmagic texlive texmf-dist-fontsrecommended texmf-dist-lang texmf-dist-latexextra
|
||||
|
||||
RUN apk add --no-cache bash
|
||||
|
||||
|
211
docs/dev/transition.rst
Normal file
211
docs/dev/transition.rst
Normal file
@ -0,0 +1,211 @@
|
||||
Transition d'années
|
||||
===================
|
||||
|
||||
Entre deux sessions du TFJM², certaines opérations doivent être effectuées chaque année,
|
||||
afin de réinitialiser les données et de passer à l'année suivante.
|
||||
|
||||
Réinitialisation de la base de données
|
||||
--------------------------------------
|
||||
|
||||
Conservation des autorisations de droit à l'image
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
La base de données du TFJM² est supprimée chaque année, avant chaque tournoi. Il n'y a
|
||||
pas de conservation de données personnelles à l'exception des autorisations de droit
|
||||
à l'image qui doivent être conservées pour des raisons légales pendant 5 ans.
|
||||
|
||||
Elles doivent alors être stockées sur Owncloud. Pour cela, il faut commencer par créer
|
||||
un dossier dans Owncloud, qui stockera lesdites autorisations.
|
||||
|
||||
Rendez-vous ensuite dans le conteneur Docker et exécuter le script :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./manage.py export_photo_authorizations
|
||||
|
||||
Cela a pour effet de générer un dossier dans ``output/photo_authorizations``, qui contient
|
||||
un dossier par équipe avec les différentes autorisations de droit à l'image.
|
||||
|
||||
Il faut maintenant récupérer ce dossier. Sortir du conteneur, et exécuter dans ``/srv/TFJM`` :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker cp tfjm-inscription-1:/code/output/photo_authorizations .
|
||||
sudo mv photo_authorizations/* "data/owncloud/data/Emmy/files/Autorisations de droit à l'image/Autorisations de droit à l'image 2024/"
|
||||
sudo chown -R www-data:root "data/owncloud/data/Emmy/files/Autorisations de droit à l'image/Autorisations de droit à l'image 2024"
|
||||
sudo rmdir photo_authorizations
|
||||
|
||||
Il faut enfin réactualiser Owncloud. Exécuter en tant que www-data :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker compose exec -u www-data cloud php occ files:scan Emmy
|
||||
|
||||
Vérifiez enfin que les fichiers sont bien accessibles dans l'interface Web.
|
||||
Ne pas oublier enfin de partager le dossier.
|
||||
|
||||
|
||||
Sauvegarde de secours
|
||||
"""""""""""""""""""""
|
||||
|
||||
Si les données doivent être supprimées, il peut être utile de réaliser une sauvegarde à conserver
|
||||
quelques mois.
|
||||
|
||||
.. danger::
|
||||
|
||||
Cette sauvegarde ne doit être faite qu'à des fins utiles et supprimée dès que plus nécessaire.
|
||||
|
||||
Sauvegardez alors le dossier ``/srv/TFJM/data/inscription/media`` et exportez la base de données :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo cp -r data/inscription/media data/inscription/media-2024
|
||||
sudo docker compose exec -u postgres postgres pg_dump inscription_tfjm | sudo tee inscription_tfjm_bkp_2024.sql > /dev/null
|
||||
|
||||
|
||||
Réinitialisation effective
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
Il est désormais possible de réinitialiser la base de données, après avoir éteint le serveur :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker compose stop inscription
|
||||
sudo rm -r data/inscription/media/*
|
||||
sudo docker compose exec -u postgres postgres dropdb inscription_tfjm
|
||||
sudo docker compose exec -u postgres postgres createdb -O inscription_tfjm inscription_tfjm
|
||||
|
||||
Redémarrez enfin le serveur (les migrations seront créées automatiquement)
|
||||
et créez un nouveau compte administrateur⋅rice :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker compose up -d inscription
|
||||
sudo docker compose exec inscription bash
|
||||
./manage.py createsuperuser
|
||||
|
||||
Vérifiez finalement le bon fonctionnement du site.
|
||||
|
||||
|
||||
Sites Django
|
||||
""""""""""""
|
||||
|
||||
Après avoir réinitialisé les données, il faut mettre à jour le site Django, qui permettra
|
||||
d'avoir notamment des noms de domaine correct dans les mails envoyés.
|
||||
|
||||
Se connecter alors sur le site réouvert, puis dans la partie « Administration », chercher la
|
||||
section « Sites » et modifier l'unique site présent. Vous pouvez ensuite effectuer les modifications
|
||||
à réaliser.
|
||||
|
||||
|
||||
Nouveaux paramètres pour la nouvelle année
|
||||
------------------------------------------
|
||||
|
||||
Certains paramètres doivent être modifiés pour prendre en compte la nouvelle année.
|
||||
|
||||
Dates d'inscription
|
||||
"""""""""""""""""""
|
||||
|
||||
Les inscriptions sont permises uniquement entre l'ouverture et la fermeture, afin d'éviter
|
||||
d'avoir des personnes s'inscrivant en dehors du TFJM².
|
||||
|
||||
Pour cela, dans votre projet local, rendez-vous dans ``tfjm/settings.py`` et cherchez
|
||||
le paramètre ``REGISTRATION_DATES`` (pour le TFJM²). Modifiez alors les sous-paramètres
|
||||
``open`` et ``close`` pour définir les dates pendant lesquelles les inscriptions des
|
||||
participant⋅es sont permises pour cette nouvelle année. Elles doivent être au format ISO.
|
||||
|
||||
Exemple pour l'année 2025 où les inscriptions ouvrent au 8 janvier midi pour fermer
|
||||
le 2 mars à 22h :
|
||||
|
||||
.. code:: python
|
||||
|
||||
REGISTRATION_DATES = dict(
|
||||
open=datetime.fromisoformat("2025-01-15T12:00:00+0100"),
|
||||
close=datetime.fromisoformat("2025-03-02T22:00:00+0100"),
|
||||
)
|
||||
|
||||
Il faudra ensuite commiter la modification et redémarrer le serveur pour que la modification
|
||||
prenne effet.
|
||||
|
||||
|
||||
Noms des problèmes
|
||||
""""""""""""""""""
|
||||
|
||||
Toujours dans la configuration dans ``tfjm/settings.py``, la liste des problèmes doit être
|
||||
modifiée pour que leurs noms s'affichent correctement lors du tirage au sort.
|
||||
|
||||
Cherchez le paramètre ``PROBLEMS`` et mettez alors à jour la liste, dans l'ordre, des noms
|
||||
des problèmes.
|
||||
|
||||
À nouveau, il est nécessaire de commiter la modification et redémarrer le serveur.
|
||||
|
||||
|
||||
Paramètres des tournois
|
||||
"""""""""""""""""""""""
|
||||
|
||||
Il faut enfin paramétrer les différentes dates des tournois.
|
||||
|
||||
Pour cela, connectez-vous sur la plateforme (avec un compte administrateur⋅rice), et dans l'onglet
|
||||
« Tournois », vous pouvez créer les différents tournois avec les différentes dates pour chaque tournoi.
|
||||
Plus d'information sur les différents paramètres dans la `section concernée
|
||||
<../orga.html#creer-un-tournoi>`_
|
||||
|
||||
|
||||
À la fin du tournoi
|
||||
-------------------
|
||||
|
||||
Lorsque le tournoi est terminé, il faut récupérer les informations à stocker de façon pérenne,
|
||||
notamment les solutions des équipes, les résultats ainsi que les autorisation de droit à l'image
|
||||
comme indiqué précédemment.
|
||||
|
||||
Conservation des autorisations de droit à l'image
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Se référer à la section plus haut.
|
||||
|
||||
|
||||
Conservation des solutions des équipes
|
||||
""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Le processus est très similaire à la conservation des autorisations de droit à l'image.
|
||||
Il faut d'abord, dans le conteneur, lancer le script dédié pour récupérer les solutions
|
||||
dans ``/code/output/solutions`` :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./manage.py export_solutions
|
||||
|
||||
On sort du conteneur et on récupère les solutions pour les déplacer dans Owncloud :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker cp tfjm-inscription-1:/code/output/solutions .
|
||||
sudo mv solutions/* "data/owncloud/data/Emmy/files/Solutions écrites 2024/"
|
||||
sudo chown -R www-data:root "data/owncloud/data/Emmy/files/Solutions écrites 2024"
|
||||
sudo rmdir solutions
|
||||
|
||||
Il faut enfin réactualiser Owncloud. Exécuter en tant que www-data :
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo docker compose exec -u www-data cloud php occ files:scan Emmy
|
||||
|
||||
Vérifiez enfin que les fichiers sont bien accessibles dans l'interface Web.
|
||||
Ne pas oublier enfin de partager le dossier.
|
||||
|
||||
|
||||
Génération de la page de résultats Wordpress
|
||||
""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Pour finir, il est possible de récupérer les notes pour chaque tournoi afin de générer
|
||||
la page Wordpress dans la section *Éditions précédentes*.
|
||||
|
||||
Il suffit de lancer le script ``./manage.py export_results``, qui donne le texte brut pour
|
||||
Wordpress à ajouter sur la page de l'édition qui vient de se terminer dans l'onglet
|
||||
*Éditions précédentes*.
|
||||
|
||||
Pensez à bien inclure sur cette page le lien vers les problèmes de l'année, ainsi que le
|
||||
lien vers le dossier partagé dans le Owncloud concernant les solutions des équipes.
|
||||
|
||||
Assurez-vous de mettre à jour la page *Éditions précédentes* afin d'inclure le lien vers
|
||||
la page nouvellement créée.
|
@ -21,3 +21,4 @@ administrateur⋅rice.
|
||||
|
||||
dev/index
|
||||
dev/install
|
||||
dev/transition
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@ from io import StringIO
|
||||
import re
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Div, Field, Submit
|
||||
from crispy_forms.layout import Div, Field, HTML, Layout, Submit
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
@ -77,9 +77,30 @@ class ParticipationForm(forms.ModelForm):
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if settings.TFJM_APP == "ETEAM":
|
||||
# One single tournament only
|
||||
if settings.SINGLE_TOURNAMENT:
|
||||
del self.fields['tournament']
|
||||
self.helper = FormHelper()
|
||||
idf_warning_banner = f"""
|
||||
<div class=\"alert alert-warning\">
|
||||
<h5 class=\"alert-heading\">{_("IMPORTANT")}</h4>
|
||||
{_("""For the tournaments in the region "Île-de-France": registration is
|
||||
unified for each tournament. By choosing a tournament "Île-de-France",
|
||||
you're accepting that your team may be selected for one of these tournaments.
|
||||
In case of date conflict, please write them in your motivation letter.""")}
|
||||
</div>
|
||||
"""
|
||||
unified_registration_tournament_ids = ",".join(
|
||||
str(tournament.id) for tournament in Tournament.objects.filter(
|
||||
unified_registration=True).all())
|
||||
self.helper.layout = Layout(
|
||||
'tournament',
|
||||
Div(
|
||||
HTML(idf_warning_banner),
|
||||
css_id="idf_warning_banner",
|
||||
data_tid_unified=unified_registration_tournament_ids,
|
||||
),
|
||||
'final',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Participation
|
||||
|
@ -5,16 +5,16 @@ from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import BaseCommand
|
||||
from django.utils.translation import activate
|
||||
from participation.models import Solution, Tournament
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
activate(settings.PROBLEMS)
|
||||
|
||||
base_dir = Path(__file__).parent.parent.parent.parent
|
||||
base_dir /= "output"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
base_dir /= "solutions"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
base_dir /= "Par équipe"
|
||||
|
@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.1.5 on 2025-01-14 18:06
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("participation", "0022_alter_note_observer_oral"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="tournament",
|
||||
name="unified_registration",
|
||||
field=models.BooleanField(
|
||||
default=False, verbose_name="unified registration"
|
||||
),
|
||||
),
|
||||
]
|
@ -283,6 +283,11 @@ class Tournament(models.Model):
|
||||
default=date.today,
|
||||
)
|
||||
|
||||
unified_registration = models.BooleanField(
|
||||
verbose_name=_("unified registration"),
|
||||
default=False,
|
||||
)
|
||||
|
||||
place = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("place"),
|
||||
|
@ -2,28 +2,28 @@
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Validation request - ETEAM</title>
|
||||
<title>Demande de validation - TFJM²</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hi,
|
||||
Bonjour,
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The team "{{ team.name }}" ({{ team.trigram }}) has just asked to validate his team to take part
|
||||
in ETEAM.
|
||||
You can decide whether or not to accept the team by going to the team page:
|
||||
L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer
|
||||
au {{ team.participation.get_problem_display }} du TFJM².
|
||||
Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe :
|
||||
<a href="https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}">
|
||||
https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sincerely yours,
|
||||
Cordialement,
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The ETEAM team
|
||||
L'organisation du TFJM²
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,10 +1,10 @@
|
||||
Hi {{ user }},
|
||||
Bonjour {{ user }},
|
||||
|
||||
The team "{{ team.name }}" ({{ team.trigram }}) has just asked to validate his team to take part
|
||||
in ETEAM.
|
||||
You can decide whether or not to accept the team by going to the team page:
|
||||
L'équipe « {{ team.name }} » ({{ team.trigram }}) vient de demander à valider son équipe pour participer
|
||||
au {{ team.participation.get_problem_display }} du TFJM².
|
||||
Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur la page de l'équipe :
|
||||
https://{{ domain }}{% url "participation:team_detail" pk=team.pk %}
|
||||
|
||||
Sincerely yours,
|
||||
Cordialement,
|
||||
|
||||
The ETEAM team
|
||||
L'organisation du TFJM²
|
||||
|
@ -2,21 +2,21 @@
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Team not validated – ETEAM</title>
|
||||
<title>Équipe non validée – TFJM²</title>
|
||||
</head>
|
||||
<body>
|
||||
Hi,<br/>
|
||||
Bonjour,<br/>
|
||||
<br />
|
||||
Unfortunately, your team "{{ team.name }}" ({{ team.trigram }}) has not been validated.
|
||||
Please check that your authorisations are correctly filled in.
|
||||
The organisers are sending you this message:<br />
|
||||
Maleureusement, votre équipe « {{ team.name }} » ({{ team.trigram }}) n'a pas été validée. Veuillez vérifier que vos autorisations
|
||||
de droit à l'image sont correctes. Les organisateurs vous adressent ce message :<br />
|
||||
<br />
|
||||
{{ message }}<br />
|
||||
<br />
|
||||
Please contact us at <a href="mailto:eteam_moc@proton.me">eteam_moc@proton.me</a> if you need further information.
|
||||
N'hésitez pas à nous contacter à l'adresse <a href="mailto:contact@tfjm.org">contact@tfjm.org</a>
|
||||
pour plus d'informations.
|
||||
<br/>
|
||||
Sincerely yours,<br/>
|
||||
Cordialement,<br/>
|
||||
<br/>
|
||||
The ETEAM team
|
||||
Le comité d'organisation du TFJM²
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,13 +1,12 @@
|
||||
Hi,
|
||||
Bonjour,
|
||||
|
||||
Unfortunately, your team "{{ team.name }}" ({{ team.trigram }}) has not been validated.
|
||||
Please check that your authorisations are correctly filled in.
|
||||
The organisers are sending you this message:<br />
|
||||
Maleureusement, votre équipe « {{ team.name }} » ({{ team.trigram }}) n'a pas été validée. Veuillez vérifier que vos
|
||||
autorisations de droit à l'image sont correctes. Les organisateurs vous adressent ce message :
|
||||
|
||||
{{ message }}
|
||||
|
||||
Please contact us at eteam_moc@proton.me if you need further information.
|
||||
N'hésitez pas à nous contacter à l'adresse contact@tfjm.org pour plus d'informations.
|
||||
|
||||
Sincerely yours,
|
||||
Cordialement,
|
||||
|
||||
The ETEAM team
|
||||
Le comité d'organisation du TFJM²
|
||||
|
@ -2,36 +2,37 @@
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Team validated – ETEAM</title>
|
||||
<title>Équipe validée – TFJM²</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hello {{ registration }},
|
||||
Bonjour {{ registration }},
|
||||
</p>
|
||||
<p>
|
||||
Congratulations! Your team "{{ team.name }}" ({{ team.trigram }}) is now validated! You are now ready to
|
||||
to work on your problems. You can then upload your solutions to the platform.
|
||||
Félicitations ! Votre équipe « {{ team.name }} » ({{ team.trigram }}) est désormais validée ! Vous êtes désormais
|
||||
apte à travailler sur vos problèmes. Vous pourrez ensuite envoyer vos solutions sur la plateforme.
|
||||
</p>
|
||||
|
||||
{% if payment %}
|
||||
<p>
|
||||
You must now pay your participation fee of € {{ payment.amount }}.
|
||||
You can pay by credit card or bank transfer. You'll find information
|
||||
on the payment page which you can find on
|
||||
<a href="https://{{ domain }}{% url 'registration:my_account_detail' %}">your account</a>.
|
||||
If you have a scholarship, registration is free, but you must submit a justification on the same page.
|
||||
Vous devez désormais vous acquitter de vos frais de participation, de {{ payment.amount }} € par élève.
|
||||
Vous pouvez payer par carte bancaire ou par virement bancaire. Vous trouverez les informations
|
||||
sur <a href="https://{{ domain }}{% url 'registration:update_payment' pk=payment.pk %}">la page de paiement</a>.
|
||||
Si vous disposez d'une bourse, l'inscription est gratuite, mais vous devez soumettre un justificatif
|
||||
sur la même page.
|
||||
</p>
|
||||
{% elif registration.is_coach and team.participation.tournament.price %}
|
||||
<p>
|
||||
Your team must now pay a participation fee of {{ team.participation.tournament.price }} € per student (supervisors are exempt). Students with scholarships are exempt⋅es from these fees.
|
||||
You can track the status of payments on
|
||||
<a href="https://{{ domain }}{% url 'participation:team_detail' pk=team.pk %}">your team page</a>.
|
||||
Votre équipe doit désormais s'acquitter des frais de participation de {{ team.participation.tournament.price }} €
|
||||
par élève (les encadrant⋅es sont exonéré⋅es). Les élèves qui disposent d'une bourse sont exonéré⋅es de ces frais.
|
||||
Vous pouvez suivre l'état des paiements sur
|
||||
<a href="https://{{ domain }}{% url 'participation:team_detail' pk=team.pk %}">la page de votre équipe</a>.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if message %}
|
||||
<p>
|
||||
The organisers send you this message:
|
||||
Les organisateur⋅ices vous adressent ce message :
|
||||
</p>
|
||||
<p>
|
||||
{{ message }}
|
||||
@ -39,7 +40,7 @@
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
The ETEAM team
|
||||
Le comité d'organisation du TFJM²
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,21 +1,23 @@
|
||||
Hello {{registration }},
|
||||
Bonjour {{ registration }},
|
||||
|
||||
Congratulations! Your team "{{ team.name }}" ({{ team.trigram }}) is now validated! You are now ready to
|
||||
to work on your problems. You can then upload your solutions to the platform.
|
||||
{% if payment %}
|
||||
You must now pay your participation fee of € {{ payment.amount }}.
|
||||
You can pay by credit card or bank transfer. You'll find information
|
||||
on the payment page which you can find on your account:
|
||||
Félicitations ! Votre équipe « {{ team.name }} » ({{ team.trigram }}) est désormais validée ! Vous êtes désormais apte
|
||||
à travailler sur vos problèmes. Vous pourrez ensuite envoyer vos solutions sur la plateforme.
|
||||
{% if team.participation.amount %}
|
||||
Vous devez désormais vous acquitter de vos frais de participation, de {{ team.participation.amount }} €.
|
||||
Vous pouvez payer par carte bancaire ou par virement bancaire. Vous trouverez les informations
|
||||
sur la page de paiement que vous pouvez retrouver sur votre compte :
|
||||
https://{{ domain }}{% url 'registration:my_account_detail' %}
|
||||
If you have a scholarship, registration is free, but you must submit a justification on the same page.
|
||||
Si vous disposez d'une bourse, l'inscription est gratuite, mais vous devez soumettre un justificatif
|
||||
sur la même page.
|
||||
{% elif registration.is_coach and team.participation.tournament.price %}
|
||||
Your team must now pay a participation fee of {{ team.participation.tournament.price }} € per student (supervisors are exempt). Students with scholarships are exempt⋅es from these fees.
|
||||
You can track the status of payments on your team page:
|
||||
Votre équipe doit désormais s'acquitter des frais de participation de {{ team.participation.tournament.price }} €
|
||||
par élève (les encadrant⋅es sont exonéré⋅es). Les élèves qui disposent d'une bourse sont exonéré⋅es de ces frais.
|
||||
Vous pouvez suivre l'état des paiements sur la page de votre équipe :
|
||||
https://{{ domain }}{% url 'participation:team_detail' pk=team.pk %}
|
||||
{% endif %}
|
||||
{% if message %}
|
||||
The organisers send you this message:
|
||||
Les organisateurices vous adressent ce message :
|
||||
|
||||
{{ message }}
|
||||
{% endif %}
|
||||
The ETEAM team
|
||||
Le comité d'organisation du TFJM²
|
||||
|
@ -208,22 +208,26 @@
|
||||
<h3>{% trans "Files available for download" %}</h3>
|
||||
|
||||
<div class="alert alert-warning fade show files-to-download-collapse" id="files-to-download-popup">
|
||||
<h4>IMPORTANT</h4>
|
||||
<h4>{% trans "IMPORTANT" %}</h4>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
The files accessible below may contain personal information.
|
||||
In compliance with European law and out of respect for the confidentiality of participants' data,
|
||||
In compliance with European law and out of respect for the confidentiality of participants data,
|
||||
you may only use this data for purposes strictly necessary to the organization of the tournament.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Moreover, it is your responsibility to delete these files once you no longer need them, especially at the end of the tournament.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p class="text-center">
|
||||
<button class="btn btn-warning" data-bs-toggle="collapse" href=".files-to-download-collapse"
|
||||
role="button" aria-expanded="false" aria-controls="files-to-download files-to-download-popup">
|
||||
I agree not to divulge participants' data and to delete them at the end of the tournament.
|
||||
{% trans "I agree not to divulge participants data and to delete them at the end of the tournament." %}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -1,15 +1,37 @@
|
||||
{% extends request.content_only|yesno:"empty.html,base.html" %}
|
||||
|
||||
{% load crispy_forms_filters i18n %}
|
||||
{% load crispy_forms_filters crispy_forms_tags i18n %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
<div id="form-content">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{{ participation_form|crispy }}
|
||||
{% crispy participation_form %}
|
||||
</div>
|
||||
<button class="btn btn-success" type="submit">{% trans "Update" %}</button>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
<script>
|
||||
const tournamentSelect = document.getElementById('id_tournament')
|
||||
const idfWarningBanner = document.getElementById('idf_warning_banner')
|
||||
const unifiedRegistrationTournamentIds = idfWarningBanner.getAttribute('data-tid-unified').split(',')
|
||||
if (idfWarningBanner.getAttribute('data-tid-unified') !== "") {
|
||||
function updateIDFWarningBannerVisibility() {
|
||||
const tid = tournamentSelect.value
|
||||
if (unifiedRegistrationTournamentIds.includes(tid))
|
||||
idfWarningBanner.classList.remove('d-none')
|
||||
else
|
||||
idfWarningBanner.classList.add('d-none')
|
||||
}
|
||||
|
||||
tournamentSelect.addEventListener('change', updateIDFWarningBannerVisibility)
|
||||
updateIDFWarningBannerVisibility()
|
||||
}
|
||||
else {
|
||||
idfWarningBanner.classList.add('d-none')
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -7,6 +7,8 @@ from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import FileInput
|
||||
from django.utils import timezone
|
||||
from django.utils.text import format_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import CoachRegistration, ParticipantRegistration, Payment, \
|
||||
@ -36,6 +38,19 @@ class SignupForm(UserCreationForm):
|
||||
self.add_error("email", _("This email address is already used."))
|
||||
return email
|
||||
|
||||
def clean(self):
|
||||
# Check that registrations are opened
|
||||
now = timezone.now()
|
||||
if now < settings.REGISTRATION_DATES['open']:
|
||||
self.add_error(None, format_lazy(_("Registrations are not opened yet. "
|
||||
"They will open on the {opening_date:%Y-%m-%d %H:%M}."),
|
||||
opening_date=settings.REGISTRATION_DATES['open']))
|
||||
elif now > settings.REGISTRATION_DATES['close']:
|
||||
self.add_error(None, format_lazy(_("Registrations for this year are closed since "
|
||||
"{closing_date:%Y-%m-%d %H:%M}."),
|
||||
closing_date=settings.REGISTRATION_DATES['close']))
|
||||
return super().clean()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["first_name"].required = True
|
||||
|
@ -0,0 +1,37 @@
|
||||
# Copyright (C) 2024 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from participation.models import Team
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = """Cette commande permet d'exporter dans le dossier output/photo_authorizations l'ensemble des
|
||||
autorisations de droit à l'image des participant⋅es, triées par équipe, incluant aussi celles de la finale."""
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
base_dir = Path(__file__).parent.parent.parent.parent
|
||||
base_dir /= "output"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
base_dir /= "photo_authorizations"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
|
||||
for team in Team.objects.filter(participation__valid=True).all():
|
||||
team_dir = base_dir / f"{team.trigram} - {team.name}"
|
||||
if not team_dir.is_dir():
|
||||
team_dir.mkdir()
|
||||
|
||||
for participant in team.participants.all():
|
||||
if participant.photo_authorization:
|
||||
with participant.photo_authorization.file as file_input:
|
||||
with open(team_dir / f"{participant}.pdf", 'wb') as file_output:
|
||||
file_output.write(file_input.read())
|
||||
|
||||
if participant.photo_authorization_final:
|
||||
with participant.photo_authorization_final.file as file_input:
|
||||
with open(team_dir / f"{participant} (finale).pdf", 'wb') as file_output:
|
||||
file_output.write(file_input.read())
|
@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import date, datetime
|
||||
from datetime import date
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
@ -774,7 +774,7 @@ class Payment(models.Model):
|
||||
return checkout_intent
|
||||
|
||||
tournament = self.tournament
|
||||
year = datetime.now().year
|
||||
year = timezone.now().year
|
||||
base_site = "https://" + Site.objects.first().domain
|
||||
checkout_intent = helloasso.create_checkout_intent(
|
||||
amount=100 * self.amount,
|
||||
|
@ -9,29 +9,29 @@
|
||||
<body>
|
||||
|
||||
<p>
|
||||
Hi {{ user.registration }},
|
||||
Bonjour {{ user.registration }},
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You have been invited by {{ inviter.registration }} to join the ETEAM platform, available at
|
||||
<a href="https://{{ domain }}/">https://{{ domain }}/</a>. You have a volunteer account.
|
||||
Vous avez été invités par {{ inviter.registration }} à rejoindre la plateforme du TFJM², accessible à l'adresse
|
||||
<a href="https://{{ domain }}/">https://{{ domain }}/</a>. Vous disposez d'un compte de bénévole.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A random password has been set: <strong>{{ password }}</strong>.
|
||||
For security reasons, please change it as soon as you log in the first time.
|
||||
Un mot de passe aléatoire a été défini : <strong>{{ password }}</strong>.
|
||||
Par sécurité, merci de le changer dès votre connexion.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the event of a problem, please contact us by e-mail at the following address
|
||||
<a href="mailto:eteam_moc@proton.me">eteam_moc@proton.me</a>.
|
||||
En cas de problème, merci de nous contacter soit par mail à l'adresse
|
||||
<a href="mailto:contact@tfjm.org">contact@tfjm.org</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sincerely yours,
|
||||
Bien cordialement,
|
||||
</p>
|
||||
|
||||
--
|
||||
<p>
|
||||
{% trans "The ETEAM team." %}<br>
|
||||
{% trans "The TFJM² team." %}<br>
|
||||
</p>
|
||||
|
@ -1,14 +1,17 @@
|
||||
{% load i18n %}
|
||||
|
||||
Hi {{ user.registration }},
|
||||
Bonjour {{ user.registration }},
|
||||
|
||||
You have been invited by {{ inviter.registration }} to join the ETEAM platform, available at https://{{ domain }}. You have a volunteer account.
|
||||
A random password has been set: {{ password }}.
|
||||
For security reasons, please change it as soon as you log in the first time.
|
||||
Vous avez été invités par {{ inviter.registration }} à rejoindre la plateforme du TFJM², accessible à l'adresse
|
||||
https://{{ domain }}/. Vous disposez d'un compte de bénévole.
|
||||
|
||||
In the event of a problem, please contact us by e-mail at the following address eteam_moc@proton.me.
|
||||
Un mot de passe aléatoire a été défini : {{ password }}.
|
||||
Par sécurité, merci de le changer dès votre connexion.
|
||||
|
||||
Sincerely yours,
|
||||
En cas de problème, merci de nous contacter soit par mail à l'adresse contact@tfjm.org, soit sur la plateforme
|
||||
de chat accessible sur https://element.tfjm.org/ en vous connectant avec les mêmes identifiants.
|
||||
|
||||
Bien cordialement,
|
||||
|
||||
--
|
||||
{% trans "The ETEAM team." %}
|
||||
{% trans "The TFJM² team." %}
|
||||
|
@ -13,7 +13,7 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% trans "You recently registered on the ETEAM platform. Please click on the link below to confirm your registration." %}
|
||||
{% trans "You recently registered on the TFJM² platform. Please click on the link below to confirm your registration." %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -36,5 +36,5 @@
|
||||
|
||||
--
|
||||
<p>
|
||||
{% trans "The ETEAM team." %}<br>
|
||||
{% trans "The TFJM² team." %}<br>
|
||||
</p>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% trans "Hi" %} {{ user.registration }},
|
||||
|
||||
{% trans "You recently registered on the ETEAM platform. Please click on the link below to confirm your registration." %}
|
||||
{% trans "You recently registered on the TFJM² platform. Please click on the link below to confirm your registration." %}
|
||||
|
||||
https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %}
|
||||
|
||||
@ -12,4 +12,4 @@ https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=toke
|
||||
|
||||
{% trans "Thanks" %},
|
||||
|
||||
{% trans "The ETEAM team." %}
|
||||
{% trans "The TFJM² team." %}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed with amount=payment.amount team=payment.team.trigram tournament=payment.tournament.name %}
|
||||
We successfully received the payment of {{ amount }} € for your participation for the ETEAM in the team {{ team }}!
|
||||
We successfully received the payment of {{ amount }} € for your participation for the TFJM² in the team {{ team }} for the tournament {{ tournament }}!
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
@ -32,13 +32,17 @@
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% trans "Please note that these dates may be subject to change. If your local organizers gave you different dates, trust them." %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% trans "NB: This mail don't represent a payment receipt. The payer should receive a mail from Hello Asso. If it is not the case, please contact us if necessary" %}
|
||||
</p>
|
||||
|
||||
--
|
||||
<p>
|
||||
{% trans "The ETEAM team." %}<br>
|
||||
{% trans "The TFJM² team." %}<br>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% trans "Hi" %} {{ registration|safe }},
|
||||
|
||||
{% blocktrans trimmed with amount=payment.amount team=payment.team.trigram tournament=payment.tournament.name %}
|
||||
We successfully received the payment of {{ amount }} € for your participation for the ETEAM in the team {{ team }}!
|
||||
We successfully received the payment of {{ amount }} € for your participation for the TFJM² in the team {{ team }} for the tournament {{ tournament }}!
|
||||
{% endblocktrans %}
|
||||
|
||||
{% trans "Your registration is now fully completed, and you can work on your solutions." %}
|
||||
@ -13,8 +13,10 @@ We successfully received the payment of {{ amount }} € for your participation
|
||||
* {% trans "Problems draw:" %} {{ payment.tournament.solutions_draw|date }}
|
||||
* {% trans "Tournament dates:" %} {% trans "From" %} {{ payment.tournament.date_start|date }} {% trans "to" %} {{ payment.tournament.date_end|date }}
|
||||
|
||||
{% trans "Please note that these dates may be subject to change. If your local organizers gave you different dates, trust them." %}
|
||||
|
||||
{% trans "NB: This mail don't represent a payment receipt. The payer should receive a mail from Hello Asso. If it is not the case, please contact us if necessary" %}
|
||||
|
||||
--
|
||||
{% trans "The ETEAM team" %}
|
||||
{% trans "The TFJM² team" %}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed with amount=payment.amount team=payment.team.trigram tournament=payment.tournament %}
|
||||
You are registered for the ETEAM. Your team {{ team }} has been successfully validated.
|
||||
You are registered for the TFJM² of {{ tournament }}. Your team {{ team }} has been successfully validated.
|
||||
To end your inscription, you must pay the amount of {{ amount }} €.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
@ -49,7 +49,7 @@
|
||||
|
||||
--
|
||||
<p>
|
||||
{% trans "The ETEAM team." %}<br>
|
||||
{% trans "The TFJM² team." %}<br>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% trans "Hi" %} {{ registration|safe }},
|
||||
|
||||
{% blocktrans trimmed with amount=payment.amount team=payment.team.trigram tournament=payment.tournament %}
|
||||
You are registered for the ETEAM. Your team {{ team }} has been successfully validated.
|
||||
You are registered for the TFJM² of {{ tournament }}. Your team {{ team }} has been successfully validated.
|
||||
To end your inscription, you must pay the amount of {{ amount }} €.
|
||||
{% endblocktrans %}
|
||||
{% if payment.grouped %}
|
||||
@ -19,4 +19,4 @@ https://{{ domain }}{% url "registration:update_payment" pk=payment.pk %}
|
||||
{% trans "If you have any problem, feel free to contact us." %}
|
||||
|
||||
--
|
||||
The ETEAM team
|
||||
The TFJM² team
|
||||
|
@ -9,30 +9,42 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{% trans "Sign up" %}</h2>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div id="registration_form"></div>
|
||||
|
||||
<div class="py-2 text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
{% trans "By registering, you certify that you have read and accepted our" %}
|
||||
<a href="{% url 'about' %}#politique-confidentialite">{% trans "privacy policy" %}</a>.
|
||||
{% now "c" as now %}
|
||||
{% if now < TFJM.REGISTRATION_DATES.open.isoformat %}
|
||||
<div class="alert alert-warning">
|
||||
{% trans "Thank you for your great interest, but registrations are not opened yet!" %}
|
||||
{% trans "They will open on:" %} {{ TFJM.REGISTRATION_DATES.open|date:'DATETIME_FORMAT' }}.
|
||||
{% trans "Please come back at this time to register!" %}
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success" type="submit">
|
||||
{% trans "Sign up" %}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div id="student_registration_form" class="d-none">
|
||||
{{ student_registration_form|crispy }}
|
||||
</div>
|
||||
<div id="coach_registration_form" class="d-none">
|
||||
{{ coach_registration_form|crispy }}
|
||||
</div>
|
||||
{% elif now > TFJM.REGISTRATION_DATES.close.isoformat %}
|
||||
<div class="alert alert-danger">
|
||||
{% trans "Registrations are closed for this year. We hope to see you next year!" %}
|
||||
{% trans "If needed, you can contact us by mail." %}
|
||||
</div>
|
||||
{% else %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div id="registration_form"></div>
|
||||
|
||||
<div class="py-2 text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
{% trans "By registering, you certify that you have read and accepted our" %}
|
||||
<a href="{% url 'about' %}#politique-confidentialite">{% trans "privacy policy" %}</a>.
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success" type="submit">
|
||||
{% trans "Sign up" %}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div id="student_registration_form" class="d-none">
|
||||
{{ student_registration_form|crispy }}
|
||||
</div>
|
||||
<div id="coach_registration_form" class="d-none">
|
||||
{{ coach_registration_form|crispy }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
% Specials
|
||||
\newcommand{\writingsep}{\vrule height 4ex width 0pt}
|
||||
\newcommand{\cdt}{\kern-0.5pt\ensuremath\cdot\kern-0.5pt}
|
||||
|
||||
% Page formating
|
||||
\hoffset -1in
|
||||
@ -56,19 +57,23 @@ Autorisation d'enregistrement et de diffusion de l'image ({{ tournament.name }})
|
||||
|
||||
|
||||
|
||||
Je soussign\'e {{ registration|safe|default:"\dotfill" }}\\
|
||||
Je soussign\'e\cdt{}e {{ registration|safe|default:"\dotfill" }}\\
|
||||
demeurant au {{ registration.address|safe|default:"\dotfill" }}
|
||||
|
||||
\medskip
|
||||
Cochez la/les cases correspondantes.\\
|
||||
\medskip
|
||||
|
||||
\fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ de {{ tournament.name }}
|
||||
du {{ tournament.date_start }} au {{ tournament.date_end }} à : {{ tournament.place }}, \`a me photographier ou \`a me
|
||||
filmer et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites
|
||||
partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser mon image sur tous ses supports
|
||||
d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des droits
|
||||
pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\
|
||||
\fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$
|
||||
{% if tournament.unified_registration %} dans
|
||||
l'un des tournois d'Île-de-France (selon sélection : du 26 au 27 avril 2025, du 3 au 4 mai 2025, ou du 10 au 11 mai 2025)
|
||||
{% else %} de
|
||||
{{ tournament.name }} du {{ tournament.date_start }} au {{ tournament.date_end }} à : {{ tournament.place }},
|
||||
{% endif %} \`a
|
||||
me photographier ou \`a me filmer et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion
|
||||
sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser mon
|
||||
image sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente,
|
||||
cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\
|
||||
|
||||
\medskip
|
||||
Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la
|
||||
@ -98,7 +103,7 @@ Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
|
||||
|
||||
\bigskip
|
||||
|
||||
Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{}
|
||||
Signature pr\'ec\'ed\'ee de la mention « lu et approuv\'e »
|
||||
|
||||
\medskip
|
||||
|
||||
@ -106,7 +111,7 @@ Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{}
|
||||
|
||||
\begin{minipage}[c]{0.5\textwidth}
|
||||
|
||||
\underline{Le participant :}\\
|
||||
\underline{La/le participant\cdt{}e :}\\
|
||||
|
||||
Fait \`a :\\
|
||||
le
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
% Specials
|
||||
\newcommand{\writingsep}{\vrule height 4ex width 0pt}
|
||||
\newcommand{\cdt}{\kern-0.5pt\ensuremath\cdot\kern-0.5pt}
|
||||
|
||||
% Page formating
|
||||
\hoffset -1in
|
||||
@ -57,20 +58,25 @@ Autorisation d'enregistrement et de diffusion de l'image
|
||||
|
||||
|
||||
|
||||
Je soussign\'e \dotfill (p\`ere, m\`ere, responsable l\'egal) \\
|
||||
agissant en qualit\'e de repr\'esentant de {{ registration|safe|default:"\dotfill" }}\\
|
||||
Je soussign\'e\cdt{}e \dotfill (p\`ere, m\`ere, responsable l\'egal) \\
|
||||
agissant en qualit\'e de repr\'esentant\cdt{}e de {{ registration|safe|default:"\dotfill" }}\\
|
||||
demeurant au {{ registration.address|safe|default:"\dotfill" }}
|
||||
|
||||
\medskip
|
||||
Cochez la/les cases correspondantes.\\
|
||||
\medskip
|
||||
|
||||
\fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ de {{ tournament.name }}
|
||||
du {{ tournament.date_start }} au {{ tournament.date_end }} à : {{ tournament.place }}, \`a photographier ou \`a filmer
|
||||
l'enfant et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites
|
||||
partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser l'image de l'enfant sur tous ses
|
||||
supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des
|
||||
droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\
|
||||
\fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$
|
||||
{% if tournament.unified_registration %} dans
|
||||
l'un des tournois d'Île-de-France (selon sélection : du 26 au 27 avril 2025, du 3 au 4 mai 2025, ou du 10 au 11 mai 2025)
|
||||
{% else %} de
|
||||
{{ tournament.name }} du {{ tournament.date_start }} au {{ tournament.date_end }} à : {{ tournament.place }},
|
||||
{% endif %} \`a
|
||||
photographier ou \`a filmer l'enfant et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion
|
||||
sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser l'image
|
||||
de l'enfant sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la
|
||||
pr\'esente, cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de
|
||||
ces photographies.\\
|
||||
|
||||
\medskip
|
||||
Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la
|
||||
@ -100,14 +106,14 @@ Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
|
||||
|
||||
\bigskip
|
||||
|
||||
Signatures pr\'ec\'ed\'ees de la mention \og lu et approuv\'e \fg{}
|
||||
Signatures pr\'ec\'ed\'ees de la mention « lu et approuv\'e »
|
||||
|
||||
\medskip
|
||||
|
||||
|
||||
\begin{minipage}[c]{0.5\textwidth}
|
||||
|
||||
\underline{Le responsable l\'egal :}\\
|
||||
\underline{La/le responsable l\'egal\cdt{}e :}\\
|
||||
|
||||
Fait \`a :\\
|
||||
le :
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
% Specials
|
||||
\newcommand{\writingsep}{\vrule height 4ex width 0pt}
|
||||
\newcommand{\cdt}{\kern-0.5pt\ensuremath\cdot\kern-0.5pt}
|
||||
|
||||
% Page formating
|
||||
\hoffset -1in
|
||||
@ -45,16 +46,25 @@
|
||||
\Large \bf Autorisation parentale pour les mineurs ({{ tournament.name }})
|
||||
\end{center}
|
||||
|
||||
Je soussigné(e) \hrulefill,\\
|
||||
responsable légal, demeurant \writingsep\hrulefill\\
|
||||
Je soussigné\cdt{}e \hrulefill,\\
|
||||
responsable légal\cdt{}e, demeurant \writingsep\hrulefill\\
|
||||
\writingsep\hrulefill,\\
|
||||
\writingsep autorise {{ registration|default:"\hrulefill" }},\\
|
||||
né(e) le {{ registration.birth_date }},
|
||||
à participer au Tournoi Français des Jeunes Mathématiciennes et Mathématiciens ($\mathbb{TFJM}^2$) organisé \`a :
|
||||
né\cdt{}e le {{ registration.birth_date|default:"\underline{\phantom{dd/mm/aaaa} }" }},
|
||||
à participer au Tournoi Français des Jeunes Mathématiciennes et Mathématiciens ($\mathbb{TFJM}^2$)
|
||||
{% if tournament.unified_registration %} dans l'un des tournois d'Île-de-France selon sélection :
|
||||
\begin{itemize}
|
||||
\item Île-de-France 1, du 26 au 27 avril 2025 ;
|
||||
\item Île-de-France 2, du 3 au 4 mai 2025 ;
|
||||
\item Île-de-France 3, du 10 au 11 mai 2025.
|
||||
\end{itemize}
|
||||
{% else %}
|
||||
organisé \`a :
|
||||
{{ tournament.place }}, du {{ tournament.date_start }} au {{ tournament.date_end }}.
|
||||
{% endif %}
|
||||
|
||||
Iel se rendra au lieu indiqu\'e ci-dessus le samedi matin et quittera les lieux l'après-midi du dimanche par
|
||||
ses propres moyens et sous la responsabilité du représentant légal.
|
||||
ses propres moyens et sous la responsabilité du/de la représentant\cdt{}e légal\cdt{}e.
|
||||
|
||||
|
||||
|
||||
|
@ -1,14 +1,17 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import timedelta
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase
|
||||
from django.test import override_settings, TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from participation.models import Team
|
||||
@ -114,6 +117,9 @@ class TestRegistration(TestCase):
|
||||
self.assertRedirects(response, "http://" + Site.objects.get().domain +
|
||||
str(self.coach.registration.get_absolute_url()), 302, 200)
|
||||
|
||||
# Ensure that we are between registration dates
|
||||
@override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=1),
|
||||
'close': timezone.now() + timedelta(days=1)})
|
||||
def test_registration(self):
|
||||
"""
|
||||
Ensure that the signup form is working successfully.
|
||||
@ -223,6 +229,52 @@ class TestRegistration(TestCase):
|
||||
response = self.client.get(reverse("registration:email_validation_resend", args=(user.pk,)))
|
||||
self.assertRedirects(response, reverse("registration:email_validation_sent"), 302, 200)
|
||||
|
||||
def test_registration_dates(self):
|
||||
"""
|
||||
Test that registrations are working only between registration dates.
|
||||
"""
|
||||
self.client.logout()
|
||||
|
||||
# Test that registration between open and close dates are working
|
||||
with override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=2),
|
||||
'close': timezone.now() + timedelta(days=2)}):
|
||||
response = self.client.get(reverse("registration:signup"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("<i class=\"fas fa-user-plus\"></i> Register", response.content.decode())
|
||||
self.assertNotIn("registrations are not opened", response.content.decode())
|
||||
self.assertNotIn("Registrations are closed", response.content.decode())
|
||||
|
||||
response = self.client.post(reverse("registration:signup"))
|
||||
self.assertFormError(response.context['form'], None, [])
|
||||
|
||||
# Test that registration before open date is not working
|
||||
with override_settings(REGISTRATION_DATES={'open': timezone.now() + timedelta(days=1),
|
||||
'close': timezone.now() + timedelta(days=2)}):
|
||||
response = self.client.get(reverse("registration:signup"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotIn("<i class=\"fas fa-user-plus\"></i> Register", response.content.decode())
|
||||
self.assertIn("registrations are not opened", response.content.decode())
|
||||
|
||||
response = self.client.post(reverse("registration:signup"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFormError(response.context['form'], None,
|
||||
"Registrations are not opened yet. They will open on the "
|
||||
f"{settings.REGISTRATION_DATES['open']:%Y-%m-%d %H:%M}.")
|
||||
|
||||
# Test that registration after close date is not working
|
||||
with override_settings(REGISTRATION_DATES={'open': timezone.now() - timedelta(days=2),
|
||||
'close': timezone.now() - timedelta(days=1)}):
|
||||
response = self.client.get(reverse("registration:signup"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotIn("<i class=\"fas fa-user-plus\"></i> Register", response.content.decode())
|
||||
self.assertIn("Registrations are closed", response.content.decode())
|
||||
|
||||
response = self.client.post(reverse("registration:signup"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFormError(response.context['form'], None,
|
||||
"Registrations for this year are closed since "
|
||||
f"{settings.REGISTRATION_DATES['close']:%Y-%m-%d %H:%M}.")
|
||||
|
||||
def test_login(self):
|
||||
"""
|
||||
With a registered user, try to log in
|
||||
|
@ -19,7 +19,7 @@ gunicorn~=23.0.0
|
||||
odfpy~=1.4.1
|
||||
pandas~=2.2.3
|
||||
phonenumbers~=8.13.47
|
||||
psycopg-binary~=3.2.3
|
||||
psycopg~=3.2.3
|
||||
pypdf~=5.0.1
|
||||
ipython~=8.28.0
|
||||
python-magic~=0.4.27
|
||||
|
@ -13,11 +13,12 @@ def tfjm_context(request):
|
||||
'HAS_OBSERVER': settings.HAS_OBSERVER,
|
||||
'HAS_FINAL': settings.HAS_FINAL,
|
||||
'HOME_PAGE_LINK': settings.HOME_PAGE_LINK,
|
||||
'LOGO_PATH': "static/tfjm/img/" + settings.LOGO_FILE,
|
||||
'LOGO_PATH': "tfjm/img/" + settings.LOGO_FILE,
|
||||
'NB_ROUNDS': settings.NB_ROUNDS,
|
||||
'ML_MANAGEMENT': settings.ML_MANAGEMENT,
|
||||
'PAYMENT_MANAGEMENT': settings.PAYMENT_MANAGEMENT,
|
||||
'RECOMMENDED_SOLUTIONS_COUNT': settings.RECOMMENDED_SOLUTIONS_COUNT,
|
||||
'REGISTRATION_DATES': settings.REGISTRATION_DATES,
|
||||
'SINGLE_TOURNAMENT': settings.SINGLE_TOURNAMENT,
|
||||
'HEALTH_SHEET_REQUIRED': settings.HEALTH_SHEET_REQUIRED,
|
||||
'VACCINE_SHEET_REQUIRED': settings.VACCINE_SHEET_REQUIRED,
|
||||
|
@ -13,6 +13,7 @@ For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
@ -195,7 +196,14 @@ STATICFILES_DIRS = [
|
||||
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "static")
|
||||
|
||||
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
'staticfiles': {
|
||||
'BACKEND': 'pipeline.storage.PipelineStorage',
|
||||
},
|
||||
}
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
@ -365,6 +373,11 @@ if TFJM_APP == "TFJM":
|
||||
LOGO_FILE = "tfjm.svg"
|
||||
RULES_LINK = "https://tfjm.org/reglement"
|
||||
|
||||
REGISTRATION_DATES = dict(
|
||||
open=datetime.fromisoformat("2025-01-15T12:00:00+0100"),
|
||||
close=datetime.fromisoformat("2025-03-02T22:00:00+0100"),
|
||||
)
|
||||
|
||||
PROBLEMS = [
|
||||
"Triominos",
|
||||
"Rassemblements mathématiques",
|
||||
@ -395,6 +408,11 @@ elif TFJM_APP == "ETEAM":
|
||||
LOGO_FILE = "eteam.png"
|
||||
RULES_LINK = "https://eteam.tfjm.org/rules/"
|
||||
|
||||
REGISTRATION_DATES = dict(
|
||||
open=datetime.fromisoformat("2024-06-01T12:00:00+0200"),
|
||||
close=datetime.fromisoformat("2024-07-04T20:00:00+0200"),
|
||||
)
|
||||
|
||||
PROBLEMS = [
|
||||
"Exploring Flatland",
|
||||
"A Mazing Hive",
|
||||
|
@ -30,6 +30,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<h3 class="alert-heading"><i class="fas fa-warning"></i> {% trans "New in 2025" %}</h3>
|
||||
{% blocktrans trimmed %}
|
||||
Registration for Ile-de-France tournaments is now unified.
|
||||
If you live in or near the Ile-de-France region, your registration will be pooled with each of the region's tournaments,
|
||||
and the organizers will take care of team allocation. However, date constraints can be indicated in the motivation letter.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
|
||||
<div class="jumbotron p-5 border rounded-5">
|
||||
<h5 class="display-4">{% trans "How does it work?" %}</h5>
|
||||
<p>
|
||||
|
@ -96,9 +96,12 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if not user.is_authenticated %}
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="{% url "registration:signup" %}"><i class="fas fa-user-plus"></i> {% trans "Register" %}</a>
|
||||
</li>
|
||||
{% now "c" as now %}
|
||||
{% if TFJM.REGISTRATION_DATES.open.isoformat <= now and now <= TFJM.REGISTRATION_DATES.close.isoformat %}
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="{% url "registration:signup" %}"><i class="fas fa-user-plus"></i> {% trans "Register" %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#" data-bs-toggle="modal" data-bs-target="#loginModal">
|
||||
<i class="fas fa-sign-in-alt"></i> {% trans "Log in" %}
|
||||
|
Reference in New Issue
Block a user