Compare commits
11 Commits
7f8934a647
...
0e7be7e27c
Author | SHA1 | Date | |
---|---|---|---|
0e7be7e27c | |||
b95b41a2ed
|
|||
444bea2440
|
|||
7bb4e2c8eb
|
|||
0f176ea4c6
|
|||
63a10c1be5
|
|||
f7eddd289b
|
|||
6b4553b76b
|
|||
ccfd2c155b | |||
814cb10439 | |||
df8f6cff2b |
@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-21 21:06
|
||||
# Generated by Django 3.2.13 on 2023-01-10 19:22
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
@ -26,7 +26,7 @@ class Migration(migrations.Migration):
|
||||
('data', models.TextField(blank=True, default='', verbose_name='new data')),
|
||||
('action', models.CharField(choices=[('create', 'create'), ('edit', 'edit'), ('delete', 'delete')], default='edit', max_length=16, verbose_name='action')),
|
||||
('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='timestamp')),
|
||||
('model', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.ContentType', verbose_name='model')),
|
||||
('model', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype', verbose_name='model')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
|
@ -1,8 +1,9 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-22 18:26
|
||||
# Generated by Django 3.2.13 on 2023-01-10 19:22
|
||||
|
||||
import datetime
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import participation.models
|
||||
|
||||
@ -47,8 +48,8 @@ class Migration(migrations.Migration):
|
||||
name='Passage',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('place', models.CharField(default='Non indiqué', help_text='Where the solution is presented?', max_length=255, verbose_name='place')),
|
||||
('solution_number', models.PositiveSmallIntegerField(choices=[(1, 'Problem #1'), (2, 'Problem #2'), (3, 'Problem #3'), (4, 'Problem #4'), (5, 'Problem #5'), (6, 'Problem #6'), (7, 'Problem #7'), (8, 'Problem #8')], verbose_name='defended solution')),
|
||||
('defender_penalties', models.PositiveSmallIntegerField(default=0, help_text='Number of penalties for the defender. The defender will loose a 0.5 coefficient per penalty.', verbose_name='penalties')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'passage',
|
||||
@ -61,6 +62,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('round', models.PositiveSmallIntegerField(choices=[(1, 'Round 1'), (2, 'Round 2')], verbose_name='round')),
|
||||
('bbb_url', models.CharField(blank=True, default='', help_text='The link of the BBB visio for this pool.', max_length=255, verbose_name='BigBlueButton URL')),
|
||||
('results_available', models.BooleanField(default=False, help_text='Check this case when results become accessible to teams. They stay accessible to you. Only averages are given.', verbose_name='results available')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'pool',
|
||||
@ -73,11 +75,12 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('problem', models.PositiveSmallIntegerField(choices=[(1, 'Problem #1'), (2, 'Problem #2'), (3, 'Problem #3'), (4, 'Problem #4'), (5, 'Problem #5'), (6, 'Problem #6'), (7, 'Problem #7'), (8, 'Problem #8')], verbose_name='problem')),
|
||||
('final_solution', models.BooleanField(default=False, verbose_name='solution for the final tournament')),
|
||||
('file', models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_solution_filename, verbose_name='file')),
|
||||
('file', models.FileField(unique=True, upload_to=participation.models.get_solution_filename, verbose_name='file')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'solution',
|
||||
'verbose_name_plural': 'solutions',
|
||||
'ordering': ('participation__team__trigram', 'final_solution', 'problem'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -85,11 +88,12 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.PositiveSmallIntegerField(choices=[(1, 'opponent'), (2, 'reporter')])),
|
||||
('file', models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_synthesis_filename, verbose_name='file')),
|
||||
('file', models.FileField(unique=True, upload_to=participation.models.get_synthesis_filename, verbose_name='file')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'synthesis',
|
||||
'verbose_name_plural': 'syntheses',
|
||||
'ordering': ('passage__pool__round', 'type'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -113,8 +117,10 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=255, unique=True, verbose_name='name')),
|
||||
('date_start', models.DateField(default=datetime.date.today, verbose_name='start')),
|
||||
('date_end', models.DateField(default=datetime.date.today, verbose_name='end')),
|
||||
('place', models.CharField(max_length=255, verbose_name='place')),
|
||||
('max_teams', models.PositiveSmallIntegerField(default=9, verbose_name='max team count')),
|
||||
('price', models.PositiveSmallIntegerField(default=21, verbose_name='price')),
|
||||
('remote', models.BooleanField(default=False, verbose_name='remote')),
|
||||
('inscription_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date for registrations')),
|
||||
('solution_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date to upload solutions')),
|
||||
('solutions_draw', models.DateTimeField(default=django.utils.timezone.now, verbose_name='random draw for solutions')),
|
||||
@ -129,4 +135,17 @@ class Migration(migrations.Migration):
|
||||
'verbose_name_plural': 'tournaments',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tweak',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('diff', models.IntegerField(help_text='Score to add/remove on the final score', verbose_name='difference')),
|
||||
('participation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tweaks', to='participation.participation', verbose_name='participation')),
|
||||
('pool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.pool', verbose_name='passage')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'tweak',
|
||||
'verbose_name_plural': 'tweaks',
|
||||
},
|
||||
),
|
||||
]
|
||||
|
@ -1,6 +1,5 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-22 18:26
|
||||
# Generated by Django 3.2.13 on 2023-01-10 19:22
|
||||
|
||||
import address.models
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
@ -10,9 +9,8 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('registration', '0001_initial'),
|
||||
('address', '0003_auto_20200830_1851'),
|
||||
('participation', '0001_initial'),
|
||||
('registration', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@ -21,11 +19,6 @@ class Migration(migrations.Migration):
|
||||
name='organizers',
|
||||
field=models.ManyToManyField(related_name='organized_tournaments', to='registration.VolunteerRegistration', verbose_name='organizers'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='place',
|
||||
field=address.models.AddressField(on_delete=django.db.models.deletion.CASCADE, to='address.Address', verbose_name='place'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='team',
|
||||
index=models.Index(fields=['trigram'], name='participati_trigram_239255_idx'),
|
||||
@ -33,17 +26,17 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='synthesis',
|
||||
name='participation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.Participation', verbose_name='participation'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.participation', verbose_name='participation'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='synthesis',
|
||||
name='passage',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.Passage', verbose_name='passage'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.passage', verbose_name='passage'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='solution',
|
||||
name='participation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='solutions', to='participation.Participation', verbose_name='participation'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='solutions', to='participation.participation', verbose_name='participation'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='pool',
|
||||
@ -58,47 +51,47 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='pool',
|
||||
name='tournament',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pools', to='participation.Tournament', verbose_name='tournament'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pools', to='participation.tournament', verbose_name='tournament'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='passage',
|
||||
name='defender',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='defender'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.participation', verbose_name='defender'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='passage',
|
||||
name='opponent',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='opponent'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.participation', verbose_name='opponent'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='passage',
|
||||
name='pool',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='passages', to='participation.Pool', verbose_name='pool'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='passages', to='participation.pool', verbose_name='pool'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='passage',
|
||||
name='reporter',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='reporter'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.participation', verbose_name='reporter'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='participation',
|
||||
name='team',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='participation.Team', verbose_name='team'),
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='participation.team', verbose_name='team'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='participation',
|
||||
name='tournament',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='participation.Tournament', verbose_name='tournament'),
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='participation.tournament', verbose_name='tournament'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='note',
|
||||
name='jury',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='registration.VolunteerRegistration', verbose_name='jury'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='registration.volunteerregistration', verbose_name='jury'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='note',
|
||||
name='passage',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='participation.Passage', verbose_name='passage'),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='participation.passage', verbose_name='passage'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='tournament',
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-23 18:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0002_auto_20210122_1926'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='remote',
|
||||
field=models.BooleanField(default=False, verbose_name='remote'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.7 on 2021-04-03 19:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0003_tournament_remote'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='passage',
|
||||
name='defender_penalties',
|
||||
field=models.PositiveSmallIntegerField(default=0, help_text='Number of penalties for the defender. The defender will loose a 0.5 coefficient per penalty.', verbose_name='penalties'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.7 on 2021-04-10 07:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0004_passage_defender_penalties'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='pool',
|
||||
name='results_available',
|
||||
field=models.BooleanField(default=False, help_text='Check this case when results become accessible to teams. They stay accessible to you. Only averages are given.', verbose_name='results available'),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-04-26 11:46
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0005_pool_results_available'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='solution',
|
||||
options={'ordering': ('participation__team__trigram', 'final_solution', 'problem'), 'verbose_name': 'solution', 'verbose_name_plural': 'solutions'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='synthesis',
|
||||
options={'ordering': ('passage__pool__round', 'type'), 'verbose_name': 'synthesis', 'verbose_name_plural': 'syntheses'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-04-26 19:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0006_auto_20220426_1346'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='passage',
|
||||
name='place',
|
||||
),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-04-29 16:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import participation.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0007_remove_passage_place'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='solution',
|
||||
name='file',
|
||||
field=models.FileField(unique=True, upload_to=participation.models.get_solution_filename, verbose_name='file'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='synthesis',
|
||||
name='file',
|
||||
field=models.FileField(unique=True, upload_to=participation.models.get_synthesis_filename, verbose_name='file'),
|
||||
),
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-15 14:40
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('participation', '0008_auto_20220429_1853'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Tweak',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('diff', models.IntegerField(help_text='Score to add/remove on the final score', verbose_name='difference')),
|
||||
('participation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tweaks', to='participation.participation', verbose_name='participation')),
|
||||
('pool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.pool', verbose_name='passage')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'tweak',
|
||||
'verbose_name_plural': 'tweaks',
|
||||
},
|
||||
),
|
||||
]
|
@ -4,7 +4,6 @@
|
||||
from datetime import date
|
||||
import os
|
||||
|
||||
from address.models import AddressField
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
@ -143,7 +142,8 @@ class Tournament(models.Model):
|
||||
default=date.today,
|
||||
)
|
||||
|
||||
place = AddressField(
|
||||
place = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("place"),
|
||||
)
|
||||
|
||||
|
@ -29,6 +29,9 @@ class TestStudentParticipation(TestCase):
|
||||
StudentRegistration.objects.create(
|
||||
user=self.user,
|
||||
student_class=12,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
school="Earth",
|
||||
give_contact_to_animath=True,
|
||||
email_confirmed=True,
|
||||
@ -49,6 +52,9 @@ class TestStudentParticipation(TestCase):
|
||||
StudentRegistration.objects.create(
|
||||
user=self.second_user,
|
||||
student_class=11,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
school="Moon",
|
||||
give_contact_to_animath=True,
|
||||
email_confirmed=True,
|
||||
@ -65,7 +71,12 @@ class TestStudentParticipation(TestCase):
|
||||
email="coach@example.com",
|
||||
password="coach",
|
||||
)
|
||||
CoachRegistration.objects.create(user=self.coach)
|
||||
CoachRegistration.objects.create(
|
||||
user=self.coach,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
)
|
||||
|
||||
self.tournament = Tournament.objects.create(
|
||||
name="France",
|
||||
@ -214,6 +225,9 @@ class TestStudentParticipation(TestCase):
|
||||
give_contact_to_animath=True,
|
||||
email_confirmed=True,
|
||||
team=self.team,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
photo_authorization="authorization/photo/mai-linh",
|
||||
health_sheet="authorization/health/mai-linh",
|
||||
parental_authorization="authorization/parental/mai-linh",
|
||||
@ -232,6 +246,9 @@ class TestStudentParticipation(TestCase):
|
||||
give_contact_to_animath=False,
|
||||
email_confirmed=True,
|
||||
team=self.team,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
photo_authorization="authorization/photo/yohann",
|
||||
health_sheet="authorization/health/yohann",
|
||||
parental_authorization="authorization/parental/yohann",
|
||||
@ -250,6 +267,9 @@ class TestStudentParticipation(TestCase):
|
||||
give_contact_to_animath=False,
|
||||
email_confirmed=True,
|
||||
team=self.team,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
photo_authorization="authorization/photo/tfjm",
|
||||
health_sheet="authorization/health/tfjm",
|
||||
parental_authorization="authorization/parental/tfjm",
|
||||
|
@ -305,12 +305,16 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["participation_form"] = ParticipationForm(data=self.request.POST or None,
|
||||
instance=self.object.participation)
|
||||
if not self.request.user.registration.is_volunteer:
|
||||
del context["participation_form"].fields['final']
|
||||
context["title"] = _("Update team {trigram}").format(trigram=self.object.trigram)
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
participation_form = ParticipationForm(data=self.request.POST or None, instance=self.object.participation)
|
||||
if not self.request.user.registration.is_volunteer:
|
||||
del participation_form.fields['final']
|
||||
if not participation_form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
@ -101,8 +101,8 @@ class StudentRegistrationForm(forms.ModelForm):
|
||||
"""
|
||||
class Meta:
|
||||
model = StudentRegistration
|
||||
fields = ('team', 'student_class', 'birth_date', 'gender', 'address', 'phone_number', 'health_issues',
|
||||
'school', 'responsible_name', 'responsible_phone', 'responsible_email',
|
||||
fields = ('team', 'student_class', 'birth_date', 'gender', 'address', 'zip_code', 'city', 'phone_number',
|
||||
'health_issues', 'school', 'responsible_name', 'responsible_phone', 'responsible_email',
|
||||
'give_contact_to_animath', 'email_confirmed',)
|
||||
|
||||
|
||||
@ -178,8 +178,8 @@ class CoachRegistrationForm(forms.ModelForm):
|
||||
"""
|
||||
class Meta:
|
||||
model = CoachRegistration
|
||||
fields = ('team', 'birth_date', 'gender', 'address', 'phone_number', 'health_issues', 'professional_activity',
|
||||
'give_contact_to_animath', 'email_confirmed',)
|
||||
fields = ('team', 'gender', 'address', 'zip_code', 'city', 'phone_number', 'health_issues',
|
||||
'professional_activity', 'give_contact_to_animath', 'email_confirmed',)
|
||||
|
||||
|
||||
class VolunteerRegistrationForm(forms.ModelForm):
|
||||
|
@ -1,8 +1,8 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-22 18:26
|
||||
# Generated by Django 3.2.13 on 2023-01-10 19:22
|
||||
|
||||
import address.models
|
||||
import datetime
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import phonenumber_field.modelfields
|
||||
@ -14,10 +14,9 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('address', '0003_auto_20200830_1851'),
|
||||
('participation', '0001_initial'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@ -27,7 +26,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('give_contact_to_animath', models.BooleanField(default=False, verbose_name='Grant Animath to contact me in the future about other actions')),
|
||||
('email_confirmed', models.BooleanField(default=False, verbose_name='email confirmed')),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_registration.registration_set+', to='contenttypes.ContentType')),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_registration.registration_set+', to='contenttypes.contenttype')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
@ -38,13 +37,16 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='ParticipantRegistration',
|
||||
fields=[
|
||||
('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.Registration')),
|
||||
('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')),
|
||||
('birth_date', models.DateField(default=datetime.date.today, verbose_name='birth date')),
|
||||
('gender', models.CharField(choices=[('female', 'Female'), ('male', 'Male'), ('other', 'Other')], default='other', max_length=6, verbose_name='gender')),
|
||||
('address', models.CharField(max_length=255, verbose_name='address')),
|
||||
('zip_code', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1000), django.core.validators.MaxValueValidator(99999)], verbose_name='zip code')),
|
||||
('city', models.CharField(max_length=255, verbose_name='city')),
|
||||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='phone number')),
|
||||
('health_issues', models.TextField(blank=True, help_text='You can indicate here your allergies or anything that is important to know for organizers', verbose_name='health issues')),
|
||||
('photo_authorization', models.FileField(blank=True, default='', upload_to=registration.models.get_random_photo_filename, verbose_name='photo authorization')),
|
||||
('address', address.models.AddressField(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.Address', verbose_name='address')),
|
||||
('team', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='participants', to='participation.Team', verbose_name='team')),
|
||||
('team', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='participants', to='participation.team', verbose_name='team')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
@ -55,7 +57,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='VolunteerRegistration',
|
||||
fields=[
|
||||
('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.Registration')),
|
||||
('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')),
|
||||
('professional_activity', models.TextField(verbose_name='professional activity')),
|
||||
],
|
||||
options={
|
||||
@ -67,7 +69,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='AdminRegistration',
|
||||
fields=[
|
||||
('volunteerregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.VolunteerRegistration')),
|
||||
('volunteerregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.volunteerregistration')),
|
||||
('role', models.TextField(verbose_name='role of the administrator')),
|
||||
],
|
||||
options={
|
||||
@ -79,7 +81,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='CoachRegistration',
|
||||
fields=[
|
||||
('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.ParticipantRegistration')),
|
||||
('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.participantregistration')),
|
||||
('professional_activity', models.TextField(verbose_name='professional activity')),
|
||||
],
|
||||
options={
|
||||
@ -91,7 +93,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='StudentRegistration',
|
||||
fields=[
|
||||
('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.ParticipantRegistration')),
|
||||
('participantregistration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.participantregistration')),
|
||||
('student_class', models.IntegerField(choices=[(12, '12th grade'), (11, '11th grade'), (10, '10th grade or lower')], verbose_name='student class')),
|
||||
('school', models.CharField(max_length=255, verbose_name='school')),
|
||||
('responsible_name', models.CharField(default='', max_length=255, verbose_name='responsible name')),
|
||||
@ -110,11 +112,11 @@ class Migration(migrations.Migration):
|
||||
name='Payment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.CharField(blank=True, choices=[('', 'No payment'), ('helloasso', 'Hello Asso'), ('scholarship', 'Scholarship'), ('bank_transfer', 'Bank transfer'), ('free', 'The tournament is free')], default='', max_length=16, verbose_name='type')),
|
||||
('type', models.CharField(blank=True, choices=[('', 'No payment'), ('helloasso', 'Hello Asso'), ('scholarship', 'Scholarship'), ('bank_transfer', 'Bank transfer'), ('other', 'Other (please indicate)'), ('free', 'The tournament is free')], default='', max_length=16, verbose_name='type')),
|
||||
('scholarship_file', models.FileField(blank=True, default='', help_text='only if you have a scholarship.', upload_to=registration.models.get_scholarship_filename, verbose_name='scholarship file')),
|
||||
('additional_information', models.TextField(blank=True, default='', help_text='To help us to find your payment.', verbose_name='additional information')),
|
||||
('valid', models.BooleanField(default=False, null=True, verbose_name='valid')),
|
||||
('registration', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment', to='registration.ParticipantRegistration', verbose_name='registration')),
|
||||
('registration', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment', to='registration.participantregistration', verbose_name='registration')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'payment',
|
||||
|
29
apps/registration/migrations/0002_auto_20230110_2031.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Generated by Django 3.2.13 on 2023-01-10 19:31
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('registration', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='participantregistration',
|
||||
name='birth_date',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studentregistration',
|
||||
name='birth_date',
|
||||
field=models.DateField(default=datetime.date.today, verbose_name='birth date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='studentregistration',
|
||||
name='responsible_phone',
|
||||
field=phonenumber_field.modelfields.PhoneNumberField(default='', max_length=128, region=None, verbose_name='responsible phone number'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.0.11 on 2021-01-23 20:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('registration', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='participantregistration',
|
||||
name='health_issues',
|
||||
field=models.TextField(blank=True, help_text='You can indicate here your allergies or anything that is important to know for organizers', verbose_name='health issues'),
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.2.13 on 2023-01-16 22:13
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('registration', '0002_auto_20230110_2031'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='participantregistration',
|
||||
name='zip_code',
|
||||
field=models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1000), django.core.validators.MaxValueValidator(99999)], verbose_name='zip code'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-04-26 11:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('registration', '0002_participantregistration_health_issues'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='payment',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, choices=[('', 'No payment'), ('helloasso', 'Hello Asso'), ('scholarship', 'Scholarship'), ('bank_transfer', 'Bank transfer'), ('other', 'Other (please indicate)'), ('free', 'The tournament is free')], default='', max_length=16, verbose_name='type'),
|
||||
),
|
||||
]
|
@ -3,8 +3,8 @@
|
||||
|
||||
from datetime import date
|
||||
|
||||
from address.models import AddressField
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.template import loader
|
||||
from django.urls import reverse_lazy
|
||||
@ -123,11 +123,6 @@ class ParticipantRegistration(Registration):
|
||||
verbose_name=_("team"),
|
||||
)
|
||||
|
||||
birth_date = models.DateField(
|
||||
verbose_name=_("birth date"),
|
||||
default=date.today,
|
||||
)
|
||||
|
||||
gender = models.CharField(
|
||||
max_length=6,
|
||||
verbose_name=_("gender"),
|
||||
@ -139,10 +134,19 @@ class ParticipantRegistration(Registration):
|
||||
default="other",
|
||||
)
|
||||
|
||||
address = AddressField(
|
||||
address = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("address"),
|
||||
null=True,
|
||||
default=None,
|
||||
)
|
||||
|
||||
zip_code = models.PositiveIntegerField(
|
||||
verbose_name=_("zip code"),
|
||||
validators=[MinValueValidator(1000), MaxValueValidator(99999)],
|
||||
)
|
||||
|
||||
city = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("city"),
|
||||
)
|
||||
|
||||
phone_number = PhoneNumberField(
|
||||
@ -165,6 +169,8 @@ class ParticipantRegistration(Registration):
|
||||
|
||||
@property
|
||||
def under_18(self):
|
||||
if isinstance(self, CoachRegistration):
|
||||
return False # In normal case
|
||||
important_date = timezone.now().date()
|
||||
if self.team and self.team.participation.tournament:
|
||||
important_date = self.team.participation.tournament.date_start
|
||||
@ -187,6 +193,11 @@ class StudentRegistration(ParticipantRegistration):
|
||||
Specific registration for students.
|
||||
They have a team, a student class and a school.
|
||||
"""
|
||||
birth_date = models.DateField(
|
||||
verbose_name=_("birth date"),
|
||||
default=date.today,
|
||||
)
|
||||
|
||||
student_class = models.IntegerField(
|
||||
choices=[
|
||||
(12, _("12th grade")),
|
||||
@ -209,7 +220,7 @@ class StudentRegistration(ParticipantRegistration):
|
||||
|
||||
responsible_phone = PhoneNumberField(
|
||||
verbose_name=_("responsible phone number"),
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
responsible_email = models.EmailField(
|
||||
|
@ -39,14 +39,16 @@
|
||||
</a>
|
||||
</dd>
|
||||
|
||||
<dt class="col-sm-6 text-right">{% trans "Birth date:" %}</dt>
|
||||
<dd class="col-sm-6">{{ user_object.registration.birth_date }}</dd>
|
||||
{% if user_object.registration.studentregistration %}
|
||||
<dt class="col-sm-6 text-right">{% trans "Birth date:" %}</dt>
|
||||
<dd class="col-sm-6">{{ user_object.registration.birth_date }}</dd>
|
||||
{% endif %}
|
||||
|
||||
<dt class="col-sm-6 text-right">{% trans "Gender:" %}</dt>
|
||||
<dd class="col-sm-6">{{ user_object.registration.get_gender_display }}</dd>
|
||||
|
||||
<dt class="col-sm-6 text-right">{% trans "Address:" %}</dt>
|
||||
<dd class="col-sm-6">{{ user_object.registration.address }}</dd>
|
||||
<dd class="col-sm-6">{{ user_object.registration.address }}, {{ user_object.registration.zip_code|stringformat:'05d' }} {{ user_object.registration.city }}</dd>
|
||||
|
||||
<dt class="col-sm-6 text-right">{% trans "Phone number:" %}</dt>
|
||||
<dd class="col-sm-6">{{ user_object.registration.phone_number }}</dd>
|
||||
|
@ -3,8 +3,9 @@
|
||||
{{ object.user.email }}
|
||||
{{ object.type }}
|
||||
{{ object.professional_activity }}
|
||||
{{ object.birth_date }}
|
||||
{{ object.address }}
|
||||
{{ object.zip_code }}
|
||||
{{ object.city }}
|
||||
{{ object.phone_number }}
|
||||
{{ object.team.name }}
|
||||
{{ object.team.trigram }}
|
||||
|
@ -6,6 +6,8 @@
|
||||
{{ object.school }}
|
||||
{{ object.birth_date }}
|
||||
{{ object.address }}
|
||||
{{ object.zip_code }}
|
||||
{{ object.city }}
|
||||
{{ object.phone_number }}
|
||||
{{ object.responsible_name }}
|
||||
{{ object.reponsible_phone }}
|
||||
|
@ -64,9 +64,22 @@ class TestRegistration(TestCase):
|
||||
self.client.force_login(self.user)
|
||||
|
||||
self.student = User.objects.create(email="student@example.com")
|
||||
StudentRegistration.objects.create(user=self.student, student_class=11, school="Earth")
|
||||
StudentRegistration.objects.create(
|
||||
user=self.student,
|
||||
student_class=11,
|
||||
school="Earth",
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
)
|
||||
self.coach = User.objects.create(email="coach@example.com")
|
||||
CoachRegistration.objects.create(user=self.coach, professional_activity="Teacher")
|
||||
CoachRegistration.objects.create(
|
||||
user=self.coach,
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
professional_activity="Teacher",
|
||||
)
|
||||
|
||||
def test_admin_pages(self):
|
||||
"""
|
||||
@ -131,7 +144,9 @@ class TestRegistration(TestCase):
|
||||
school="God",
|
||||
birth_date="2000-01-01",
|
||||
gender="other",
|
||||
address="1 Rue de Rivoli, 75001 Paris, France",
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
phone_number="0123456789",
|
||||
responsible_name="Toto",
|
||||
responsible_phone="0123456789",
|
||||
@ -155,7 +170,9 @@ class TestRegistration(TestCase):
|
||||
school="God",
|
||||
birth_date="2000-01-01",
|
||||
gender="other",
|
||||
address="1 Rue de Rivoli, 75001 Paris, France",
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
phone_number="0123456789",
|
||||
responsible_name="Toto",
|
||||
responsible_phone="0123456789",
|
||||
@ -174,9 +191,10 @@ class TestRegistration(TestCase):
|
||||
password1="azertyuiopazertyuiop",
|
||||
password2="azertyuiopazertyuiop",
|
||||
role="coach",
|
||||
birth_date="1980-01-01",
|
||||
gender="other",
|
||||
address="1 Rue de Rivoli, 75001 Paris, France",
|
||||
address="1 Rue de Rivoli",
|
||||
zip_code=75001,
|
||||
city="Paris",
|
||||
phone_number="0123456789",
|
||||
professional_activity="God",
|
||||
give_contact_to_animath=True,
|
||||
@ -255,10 +273,12 @@ class TestRegistration(TestCase):
|
||||
|
||||
for user, data in [(self.user, dict(role="Bot")),
|
||||
(self.student, dict(student_class=11, school="Sky", birth_date="2001-01-01",
|
||||
gender="female", address="1 Rue de Rivoli, 75001 Paris, France",
|
||||
responsible_name="Toto", responsible_email="toto@example.com")),
|
||||
(self.coach, dict(professional_activity="God", birth_date="2001-01-01",
|
||||
gender="male", address="1 Rue de Rivoli, 75001 Paris, France"))]:
|
||||
gender="female", address="1 Rue de Rivoli", zip_code=75001,
|
||||
city="Paris", responsible_name="Toto",
|
||||
responsible_phone="0123456789",
|
||||
responsible_email="toto@example.com")),
|
||||
(self.coach, dict(professional_activity="God", gender="male",
|
||||
address="1 Rue de Rivoli", zip_code=75001, city="Paris"))]:
|
||||
response = self.client.get(reverse("registration:update_user", args=(user.pk,)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
BIN
docs/_static/img/choose_tournament.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/_static/img/create_team.png
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/_static/img/join_team.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
docs/_static/img/team_info.png
vendored
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
docs/_static/img/tournament_info.png
vendored
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
docs/_static/img/user_info.png
vendored
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
docs/_static/img/validate_team.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
@ -18,7 +18,7 @@
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Plateforme du TFJM²'
|
||||
copyright = "2020-2021"
|
||||
copyright = "2020-2023"
|
||||
author = "Animath"
|
||||
|
||||
|
||||
|
4
docs/dev/index.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Développer la plateforme
|
||||
========================
|
||||
|
||||
Cette page est dédiée aux responsables informatiques qui cherchent à contribuer à la plateforme.
|
@ -1,23 +1,21 @@
|
||||
Documentation de la plateforme du TFJM²
|
||||
=======================================
|
||||
|
||||
.. image:: https://gitlab.com/animath/si/plateforme-tfjm/badges/master/pipeline.svg
|
||||
:target: https://gitlab.com/animath/si/plateforme-tfjm/-/commits/master
|
||||
:alt: Pipeline status
|
||||
Ce site vise à documenter l'usage de la plateforme de gestion du TFJM², aussi
|
||||
bien du côté utilisateur⋅rice que du côté organisateur⋅rice ou bien
|
||||
administrateur⋅rice.
|
||||
|
||||
.. image:: https://gitlab.com/animath/si/plateforme-tfjm/badges/master/coverage.svg
|
||||
:target: https://gitlab.com/animath/si/plateforme-tfjm/-/commits/master
|
||||
:alt: Coverage report
|
||||
|
||||
.. image:: https://img.shields.io/badge/License-GPL%20v3-blue.svg
|
||||
:target: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
:alt: License: GPL v3
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Utiliser
|
||||
|
||||
user
|
||||
orga
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Développer
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Jouer
|
||||
dev/index
|
||||
|
114
docs/orga.rst
Normal file
@ -0,0 +1,114 @@
|
||||
Partie organisateur⋅rices
|
||||
=========================
|
||||
|
||||
.. contents::
|
||||
|
||||
Cette page est dédiée aux organisateur⋅rices qui souhaitent utiliser la plateforme pour gérer
|
||||
les différentes équipes et les inscriptions.
|
||||
|
||||
|
||||
Ajouter un⋅e nouvelleau organisateur⋅rice
|
||||
-----------------------------------------
|
||||
|
||||
Seul⋅es les actuel⋅les organisateur⋅rices peuvent en ajouter de nouvelleaux. Il n'est pas possible
|
||||
de s'inscrire.
|
||||
|
||||
Pour cela, il faut se connecter, aller dans l'onglet « Utilisateur⋅rices », puis « Ajouter un⋅e organisateur⋅rice ».
|
||||
|
||||
Les informations suivantes sont demandées :
|
||||
|
||||
* Prénom
|
||||
* Nom de famille
|
||||
* Adresse e-mail (préférer une adresse institutionnelle)
|
||||
* Rôle (Bénévole ou administrateur⋅rice)
|
||||
* Activité professionnelle (permet de savoir d'où viennent les bénévoles)
|
||||
|
||||
Les bénévoles peuvent gérer ce qui les concernent (tournois, jurys,…), les administrateur⋅rices ont un accès
|
||||
intégral à l'ensemble de la plateforme, non restreint. Ce dernier statut ne devrait être réservé qu'aux membres du CNO.
|
||||
|
||||
Une fois le formulaire validé, un mail est envoyé permettant de définir son mot de passe. Iel peut ensuite se
|
||||
connecter en utilisant son adresse e-mail et son mot de passe.
|
||||
|
||||
|
||||
Gestion des tournois
|
||||
--------------------
|
||||
|
||||
Créer un tournoi
|
||||
""""""""""""""""
|
||||
|
||||
.. important::
|
||||
Seul⋅es les administrateur⋅rices peuvent créer des tournois.
|
||||
|
||||
Pour créer un tournoi, il suffit de cliquer dans l'onglet « Tournois » puis « Ajouter un tournoi ».
|
||||
Les descriptions des différents paramètres sont dans la section suivante.
|
||||
|
||||
|
||||
Modifier un tournoi
|
||||
"""""""""""""""""""
|
||||
|
||||
.. important::
|
||||
Seul⋅es les administrateur⋅rices ainsi que les organisateur⋅rices dudit tournoi peuvent modifier le tournoi.
|
||||
|
||||
Pour modifier un tournoi, il faut déjà se rendre sur la page du tournoi : onglet « Tournois » puis cliquer sur
|
||||
le bon tournoi. Le bouton « Modifier le tournoi » devrait être accessible.
|
||||
|
||||
.. warning::
|
||||
Si le bouton n'est pas visible, vérifiez que vous êtes bien connecté⋅e, et que vous êtes bien marqué⋅es parmi
|
||||
les organisateur⋅rices. N'hésitez pas à les contacter si ce n'est pas le cas.
|
||||
|
||||
Les informations suivantes peuvent être modifiées :
|
||||
|
||||
* Nom du tournoi
|
||||
* Date de début (le samedi)
|
||||
* Date de fin (le dimanche)
|
||||
* Adresse du lieu physique
|
||||
* Nombre indicatif maximal d'équipes autorisées
|
||||
(un multiple de 3, n'est là qu'à titre indicatif et n'est pas bloquant pour la suite)
|
||||
* Prix demandé aux participant⋅es, normalement 21 € sauf pour la finale 35 € (hors boursièr⋅es et tournois en visio)
|
||||
* La case « À distance » doit rester décochée tant que les tournois en visio n'ont pas repris
|
||||
* Date limite d'inscription : date jusqu'à laquelle les équipes peuvent finaliser leur inscription (non bloquant).
|
||||
En général le mois précédent le tournoi
|
||||
* Date limite pour envoyer les solutions : date jusqu'à laquelle les équipes peuvent soumettre leurs solutions
|
||||
(au-delà, le remplacement de solutions déjà soumises n'est plus permis mais l'envoi de nouvelles reste possible en
|
||||
cas de besoin, à décourager). En général le dimanche avant le tournoi vers 22h
|
||||
* Tirage au sort : date indicative qui dit quand le tirage au sort va se dérouler. En général le mardi précédent
|
||||
le tournoi vers 20h
|
||||
* Date limite pour envoyer les notes de synthèses pour la première/seconde phase : même règle que pour les solutions,
|
||||
mais pour les notes de synthèse. Généralement le vendredi à 22h pour le premier tour et le dimanche à 10h pour le
|
||||
second tour
|
||||
* Date à laquelle les solutions pour le second tour sont accessibles : seules les solutions pour le premier tour sont
|
||||
directement accessible après le tirage au sort, celles pour le second tour sont libérées automatiquement une fois
|
||||
cette date passée. Généralement le samedi entre 17h et 18h (à adapter)
|
||||
* Description
|
||||
* Organisateur⋅rices : liste des personnes qui organisent le tournoi et peuvent le gérer numériquement. N'inclut pas
|
||||
les juré⋅es
|
||||
* Finale (admin uniquement) : cette case ne doit être cochée que pour le tournoi de la finale.
|
||||
|
||||
|
||||
Liste des équipes
|
||||
"""""""""""""""""
|
||||
|
||||
Lorsque les équipes choisissent leur tournoi, elle est répertoriée sur la page du tournoi.
|
||||
|
||||
|
||||
Valider une équipe
|
||||
""""""""""""""""""
|
||||
|
||||
Lorsqu'une équipe a finalisé son inscription et a demandé à être validée, un mail est envoyé à l'ensemble des
|
||||
organisateur⋅rices. Sur l'interface du tournoi, il est possible de cliquer sur l'équipe et accéder à l'ensemble
|
||||
de ses informations :
|
||||
|
||||
* Nom de l'équipe
|
||||
* Trigramme
|
||||
* Encadrant⋅es
|
||||
* Participant⋅es
|
||||
* Diverses autorisations
|
||||
* Lettre de motivation
|
||||
|
||||
Lorsqu'il est temps de valider l'équipe, un formulaire dédié apparaît en bas. Un texte peut être envoyé à l'équipe,
|
||||
et le choix est proposé de valider l'équipe ou non.
|
||||
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette documentation sera complétée à l'avenir pour prendre en compte les enjeux du tournoi au moment venu.
|
222
docs/user.rst
Normal file
@ -0,0 +1,222 @@
|
||||
Utiliser la plateforme
|
||||
======================
|
||||
|
||||
.. contents::
|
||||
|
||||
Cette plateforme est conçue pour que les différentes équipes puissent s'inscrire au TFJM² et envoyer
|
||||
leurs solutions.
|
||||
|
||||
Si vous êtes ici, c'est que vous avez des questions sur l'utilisation du site en tant que participant⋅e.
|
||||
|
||||
Les inscriptions ouvrent dans le courant du mois de janvier, généralement une semaine après la publication
|
||||
des problèmes. Pour l'édition 2023, les inscriptions ouvrent le 11 janvier 2023.
|
||||
|
||||
Tout se passe sur le site https://inscription.tfjm.org/.
|
||||
|
||||
|
||||
S'inscrire
|
||||
----------
|
||||
|
||||
Il est important de noter que chaque personne d'une équipe doit s'inscrire, y compris les encadrant⋅es.
|
||||
|
||||
Rendez-vous sur le site d'inscription, bouton « S'inscrire » en haut à droite.
|
||||
|
||||
Les informations suivantes sont requises pour tout le monde :
|
||||
|
||||
* Prénom d'usage
|
||||
* Nom de famille (ou d'usage)
|
||||
* Adresse électronique (sera vérifiée)
|
||||
* Mot de passe et confirmation
|
||||
* Rôle (participant⋅e ou encadrant⋅e)
|
||||
* Date de naissance
|
||||
* Genre
|
||||
* Adresse postale
|
||||
* Numéro de téléphone de contact
|
||||
* Problèmes de santé à déclarer
|
||||
* Donne son consentement pour se faire recontacter par Animath
|
||||
|
||||
Informations demandées exclusivement aux élèves :
|
||||
|
||||
* Classe (seconde ou avant/première/terminale)
|
||||
* Établissement scolaire
|
||||
* Nom du responsable légal
|
||||
* Numéro de téléphone du responsable légal
|
||||
* Adresse e-mail du responsable légal
|
||||
|
||||
Informations exclusivement demandées aux encadrant⋅es :
|
||||
|
||||
* Activité professionnelle
|
||||
|
||||
Une fois inscrit⋅e, vous recevrez par mail un lien de confirmation, qu'il vous faudra cliquer.
|
||||
|
||||
|
||||
Connexion
|
||||
---------
|
||||
|
||||
Une fois inscrit⋅e, vous pouvez vous connecter en utilisant le bouton en haut à droite.
|
||||
|
||||
Dans le champ « nom d'utilisateur », rentrez votre adresse mail. Si vous avez oublié votre mot de
|
||||
passe, un formulaire est disponible pour vous aider à le réinitialiser. Vous pouvez ensuite vous
|
||||
connecter. Votre prénom et votre nom apparaîtra en haut à droite.
|
||||
|
||||
|
||||
Créer une équipe
|
||||
----------------
|
||||
|
||||
Il suffit d'une seule personne (participant⋅e ou encadrant⋅e) pour créer une équipe. Pour créer une
|
||||
équipe, il faut cliquer sur le bouton « créer une équipe ». Un nom d'équipe et un trigramme seront
|
||||
demandés. Le trigramme est composé de 3 lettres majuscules, c'est ce qui permettra aux
|
||||
organisateur⋅rices d'identifier rapidement votre équipe.
|
||||
|
||||
.. image:: /_static/img/create_team.png
|
||||
:alt: Création d'une équipe
|
||||
|
||||
Une fois l'équipe créée, vous obtenez un code à 6 caractères, lettres ou chiffre. Ce code est à
|
||||
transettre à l'ensemble des membres de votre équipe (et seulement à elleux).
|
||||
|
||||
.. image:: /_static/img/team_info.png
|
||||
:alt: Information sur l'équipe nouvellement créée
|
||||
|
||||
|
||||
Rejoindre une équipe
|
||||
--------------------
|
||||
|
||||
Si l'équipe est déjà créée, vous aurez besoin du code d'accès transmis par la personne ayant créé
|
||||
l'équipe. Vous pouvez cliquer sur « Rejoindre une équipe », et entrer le code.
|
||||
|
||||
.. image:: /_static/img/join_team.png
|
||||
:alt: Rejoindre une équipe par son code d'accès
|
||||
|
||||
Vous avez désormais normalement rejoint l'équipe.
|
||||
|
||||
En cas de problème, ou si vous ne savez pas de quel code on parle, contactez-nous à l'adresse
|
||||
contact@tfjm.org.
|
||||
|
||||
|
||||
Informations sur les tournois
|
||||
-----------------------------
|
||||
|
||||
Les tournois peuvent être trouvés dans l'onglet « Tournois ». Vous avez accès, pour chaque tournoi,
|
||||
à l'ensemble des dates importantes et les lieux des tournois.
|
||||
|
||||
.. image:: /_static/img/tournament_info.png
|
||||
:alt: Informations sur un tournoi
|
||||
|
||||
Davantage d'informations peuvent être trouvées sur le site vitrine : https://tfjm.org/infos-tournois/.
|
||||
|
||||
|
||||
Choisir un tournoi
|
||||
------------------
|
||||
|
||||
Pour accéder aux paramètres de votre équipe, vous pouvez aller sur l'onglet « Mon équipe », dans la
|
||||
barre de navigation.
|
||||
|
||||
Pour choisir votre tournoi, il vous suffit de vous rendre sur la page de votre équipe et de cliquer
|
||||
sur « Modifier ». Un formulaire vous permet alors de choisir votre tournoi.
|
||||
|
||||
.. image:: /_static/img/choose_tournament.png
|
||||
:alt: Formulaire de mise à jour de l'équipe permettant de choisir un tournoi
|
||||
|
||||
Attention cependant : cela ne confirme pas votre inscription. Vous devez pour cela envoyer l'ensemble
|
||||
de vos documents (voir ci-dessous).
|
||||
|
||||
|
||||
Transmettre ses documents
|
||||
-------------------------
|
||||
|
||||
Pour valider votre inscription, vous devez :
|
||||
|
||||
* Avoir choisi un tournoi ;
|
||||
* Que chaque membre de l'équipe ait transmis :
|
||||
|
||||
* Autorisation de droit à l'image ;
|
||||
* Fiche sanitaire de liaison et carnet de vaccination (pour les mineur⋅es) ;
|
||||
* Autorisation parentale (pour les mineur⋅es) ;
|
||||
|
||||
* Transmettre une lettre de motivation.
|
||||
|
||||
La lettre de motivation doit être envoyée une seule fois pour toute l'équipe, peut être envoyée
|
||||
depuis l'interface « Mon équipe », au format PDF, dont le contenu est défini dans l'article 5.3
|
||||
du guide de læ participant⋅e : https://tfjm.org/reglement/.
|
||||
|
||||
Concernant les documents personnels, ils peuvent être envoyés depuis le menu « Mon compte », qui
|
||||
peut être trouvé en haut à droite dans la barre de navigation. Chaque fichier doit être envoyé
|
||||
au format PDF et peser moins de 2 Mo.
|
||||
|
||||
.. image:: /_static/img/user_info.png
|
||||
:alt: Informations sur l'utilisateur⋅rice
|
||||
|
||||
En cas de besoin, contactez-nous à l'adresse contact@tfjm.org.
|
||||
|
||||
|
||||
Valider son équipe
|
||||
------------------
|
||||
|
||||
Pour prétendre à la validation, il faut que l'équipe compte au moins 1 encadrant⋅e et 4 participant⋅es.
|
||||
Il faut ensuite que la lettre de motivation soit transmise, le tournoi choisi et que tous les documents
|
||||
nécessaires ont été transmis (voir section précédente).
|
||||
|
||||
Une fois tous les prérequis réunis, sur la page « Mon équipe », il est possible de cliquer sur le bouton
|
||||
pour demander la validation.
|
||||
|
||||
.. image:: /_static/img/validate_team.png
|
||||
:alt: Formulaire de validation d'équipe
|
||||
|
||||
.. warning::
|
||||
Les places étant limitées, rien ne garantit que vous pourrez avoir votre place dans le tournoi. Nous
|
||||
vous encourageons à respecter un maximum les critères définis dans le règlement :
|
||||
https://tfjm.org/reglement/. Selon les disponiblités et votre position géographique, il pourra
|
||||
vous être proposé de participer à un tournoi voisin.
|
||||
|
||||
Une fois les deadlines dépassées, rien ne vous garantit une place au TFJM², alors attention aux dates.
|
||||
|
||||
Vous recevrez par mail une réponse des organisateur⋅rices locaux⋅ales. En cas de besoin, contactez-nous
|
||||
à l'adresse contact@tfjm.org.
|
||||
|
||||
|
||||
Payer son inscription
|
||||
---------------------
|
||||
|
||||
Une fois votre inscription validée, il vous faudra payer votre inscription. Les frais s'élèvent à
|
||||
23 € par élève, sauf pour les élèves boursièr⋅es qui en sont exonéré⋅es. Les encadrant⋅es n'ont pas
|
||||
à payer.
|
||||
|
||||
.. note::
|
||||
Ces frais couvrent une partie des frais de restauration et d'hébergement. L'organisation reste
|
||||
bénévole.
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette section sera mise à jour plus tard.
|
||||
|
||||
|
||||
Envoyer ses solutions
|
||||
---------------------
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette section sera mise à jour plus tard.
|
||||
|
||||
|
||||
Participer au tirage au sort
|
||||
----------------------------
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette section sera mise à jour plus tard.
|
||||
|
||||
|
||||
Envoyer ses notes de synthèse
|
||||
-----------------------------
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette section sera mise à jour plus tard.
|
||||
|
||||
|
||||
Récupérer les solutions adverses
|
||||
--------------------------------
|
||||
|
||||
.. TODO
|
||||
.. note::
|
||||
Cette section sera mise à jour plus tard.
|
@ -1,5 +1,4 @@
|
||||
Django>=3.2,<4.0
|
||||
django-address~=0.2
|
||||
django-bootstrap-datepicker-plus~=4.0
|
||||
django-cas-server~=1.3
|
||||
django-crispy-forms~=1.9
|
||||
|
@ -53,7 +53,6 @@ INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'django.forms',
|
||||
|
||||
'address',
|
||||
'bootstrap_datepicker_plus',
|
||||
'crispy_forms',
|
||||
'django_filters',
|
||||
|
@ -5,11 +5,12 @@
|
||||
|
||||
<div class="alert alert-success">
|
||||
<p>
|
||||
Les inscriptions sont à présent ouvertes, vous pouvez créer votre compte. Prenez garde toutefois
|
||||
aux dates indiquées qui sont pour l'instant provisoires.
|
||||
Les inscriptions pour la session 2023 sont à présent ouvertes, vous pouvez créer votre compte.
|
||||
Prenez garde toutefois aux dates indiquées qui sont pour l'instant provisoires.
|
||||
</p>
|
||||
<p>
|
||||
Une documentation plus complète sera disponible dans les jours à venir et régulièrement mise à jour pour apprendre à utiliser la plateforme.
|
||||
Une documentation plus complète est disponible à l'adresse
|
||||
<a href="https://inscription.tfjm.org/doc/">https://inscription.tfjm.org/doc/</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -36,20 +37,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success">
|
||||
<h4><strong><i class="fas fa-newspaper"></i> Informations 2022 :</strong></h4>
|
||||
<p>
|
||||
Après 2 ans de pandémie, le tournoi devrait (enfin !) revenir en présentiel. Selon les mesures
|
||||
gouvernementales en vigueur au moment du tournoi et peut-être même selon le lieu d'accueil du tournoi,
|
||||
le pass sanitaire ou vaccinal pourra être requis.
|
||||
</p>
|
||||
<p>
|
||||
La plateforme <a class="alert-link" href="https://element.tfjm.org">element.tfjm.org</a> reste ouverte
|
||||
cette année pour faciliter d'éventuelles communications. C'est ici notamment que se déroulera le tirage
|
||||
au sort. Nous vous invitons à tenter de vous connecter sur la plateforme une fois votre compte créé.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron">
|
||||
<h5 class="display-4">Comment ça marche ?</h5>
|
||||
<p>
|
||||
@ -59,10 +46,10 @@
|
||||
|
||||
<p class="text-justify">
|
||||
Vous pouvez accéder à votre compte via la rubrique <strong><a href="{% url "login" %}">Connexion</a></strong>.
|
||||
Une fois connecté, vous pourrez créer une équipe ou en rejoindre une déjà créée par l'un de vos camarades
|
||||
via un code d'accès qui vous aura été transmis. Vous serez ensuite invité à soumettre une autorisation de droit à l'image,
|
||||
indispensable au bon déroulement du 𝕋𝔽𝕁𝕄². Une fois que votre équipe comporte au moins 4 participants (maximum 6)
|
||||
et un encadrant, vous pourrez demander à valider votre équipe pour être apte à travailler sur les problèmes de votre choix.
|
||||
Une fois connecté⋅e, vous pourrez créer une équipe ou en rejoindre une déjà créée par l'un⋅e de vos camarades
|
||||
via un code d'accès qui vous aura été transmis. Vous serez ensuite invité⋅e à soumettre une autorisation de droit à l'image,
|
||||
indispensable au bon déroulement du 𝕋𝔽𝕁𝕄². Une fois que votre équipe comporte au moins 4 participant⋅es (maximum 6)
|
||||
et un⋅e encadrant⋅e, vous pourrez demander à valider votre équipe pour être apte à travailler sur les problèmes de votre choix.
|
||||
</p>
|
||||
|
||||
<h2>Je ne trouve pas d'équipe, aidez-moi !</h2>
|
||||
@ -72,13 +59,13 @@
|
||||
au 𝕋𝔽𝕁𝕄², basée sur le protocole <a href="https://matrix.org/">Matrix</a> et le client
|
||||
<a href="https://element.io">Element</a>. Cette interface de chat vous permet de communiquer avec les membres
|
||||
de votre équipe, mais surtout de pouvoir participer au tirage au sort et discuter avec les autres équipes et
|
||||
les organisateurs.
|
||||
les organisateur⋅rices.
|
||||
</p>
|
||||
|
||||
<p class="text-justify">
|
||||
Ce chat contient également un salon <code>#je-cherche-une-equipe</code> où vous pouvez crier à l'aide pour trouver
|
||||
une équipe, ou compléter la votre s'il vous manque des participants. C'est un petit coin auprès du feu, un parc à
|
||||
jeu où vous pouvez descendre en toboggan (en le désinfectant après utilisation), ne cherchez pas à être trop formel.
|
||||
une équipe, ou compléter la votre s'il vous manque des participant⋅es. C'est un petit coin auprès du feu,
|
||||
ne cherchez pas à être trop formel⋅le.
|
||||
</p>
|
||||
|
||||
<h2>J'ai une question</h2>
|
||||
|