1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-02-18 23:41:19 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Yohann D'ANELLO
fd4280426b
Add missing models in Django Admin 2021-01-21 22:22:21 +01:00
Yohann D'ANELLO
1a63c1f399
health_sheet field is now in StudentRegistration 2021-01-21 22:16:01 +01:00
Yohann D'ANELLO
b40c06fe9e
Linting 2021-01-21 22:12:36 +01:00
Yohann D'ANELLO
416135ca3a
Squash migrations 2021-01-21 22:06:58 +01:00
Yohann D'ANELLO
497b3ad8aa
Indicate the tournament name in the photo authorizations 2021-01-21 22:04:49 +01:00
Yohann D'ANELLO
72fe279f15
The health sheet is required only for children 2021-01-21 21:55:19 +01:00
Yohann D'ANELLO
ae520f791c
Generate authorization templates as PDF 2021-01-21 21:44:43 +01:00
34 changed files with 391 additions and 483 deletions

View File

@ -1,4 +1,4 @@
# Generated by Django 3.1.3 on 2020-11-04 12:05
# Generated by Django 3.0.11 on 2021-01-21 21:06
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={

View File

@ -4,7 +4,7 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from .models import Participation, Pool, Solution, Synthesis, Team, Tournament
from .models import Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
@admin.register(Team)
@ -31,6 +31,11 @@ class PoolAdmin(admin.ModelAdmin):
search_fields = ('participations__team__name', 'participations__team__trigram',)
@admin.register(Passage)
class PassageAdmin(admin.ModelAdmin):
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
@admin.register(Solution)
class SolutionAdmin(admin.ModelAdmin):
list_display = ('participation',)

View File

@ -3,12 +3,12 @@
import re
from PyPDF3 import PdfFileReader
from bootstrap_datepicker_plus import DatePickerInput, DateTimePickerInput
from django import forms
from django.core.exceptions import ValidationError
from django.utils import formats
from django.utils.translation import gettext_lazy as _
from PyPDF3 import PdfFileReader
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament

View File

@ -1,10 +1,10 @@
# Generated by Django 3.0.11 on 2020-12-30 12:02
from datetime import date
# Generated by Django 3.0.11 on 2021-01-21 21:06
import datetime
import django.core.validators
from django.db import migrations, models
import django.utils.timezone
import participation.models
class Migration(migrations.Migration):
@ -15,22 +15,52 @@ class Migration(migrations.Migration):
]
operations = [
migrations.CreateModel(
name='Note',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('defender_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19), (20, 20)], default=0, verbose_name='defender writing note')),
('defender_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16)], default=0, verbose_name='defender oral note')),
('opponent_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)], default=0, verbose_name='opponent writing note')),
('opponent_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)], default=0, verbose_name='opponent oral note')),
('reporter_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)], default=0, verbose_name='reporter writing note')),
('reporter_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)], default=0, verbose_name='reporter oral note')),
],
options={
'verbose_name': 'note',
'verbose_name_plural': 'notes',
},
),
migrations.CreateModel(
name='Participation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('valid', models.BooleanField(default=None, help_text='The participation got the validation of the organizers.', null=True, verbose_name='valid')),
('final', models.BooleanField(default=False, help_text='The team is selected for the final tournament.', verbose_name='selected for final')),
],
options={
'verbose_name': 'participation',
'verbose_name_plural': 'participations',
},
),
migrations.CreateModel(
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')),
],
options={
'verbose_name': 'passage',
'verbose_name_plural': 'passages',
},
),
migrations.CreateModel(
name='Pool',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('round', models.PositiveSmallIntegerField(verbose_name='round')),
('round', models.PositiveSmallIntegerField(choices=[(1, 'Round 1'), (2, 'Round 2')], verbose_name='round')),
('bbb_code', models.CharField(blank=True, default='', help_text='The code of the form xxx-xxx-xxx at the end of the BBB link.', max_length=11, validators=[django.core.validators.RegexValidator('[a-z]{3}-[a-z]{3}-[a-z]{3}')], verbose_name='BigBlueButton code')),
],
options={
'verbose_name': 'pool',
@ -41,9 +71,9 @@ class Migration(migrations.Migration):
name='Solution',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('problem', models.PositiveSmallIntegerField(verbose_name='problem')),
('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='solutions/', verbose_name='file')),
('file', models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_solution_filename, verbose_name='file')),
],
options={
'verbose_name': 'solution',
@ -55,7 +85,7 @@ 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='syntheses/', verbose_name='file')),
('file', models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_synthesis_filename, verbose_name='file')),
],
options={
'verbose_name': 'synthesis',
@ -80,11 +110,15 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True, verbose_name='name')),
('date_start', models.DateField(default=date.today, verbose_name='start')),
('date_end', models.DateField(default=date.today, verbose_name='end')),
('date_start', models.DateField(default=datetime.date.today, verbose_name='start')),
('date_end', models.DateField(default=datetime.date.today, verbose_name='end')),
('max_teams', models.PositiveSmallIntegerField(default=9, verbose_name='max team count')),
('price', models.PositiveSmallIntegerField(default=21, verbose_name='price')),
('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')),
('syntheses_first_phase_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date to upload the syntheses for the first phase')),
('solutions_available_second_phase', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date when the solutions for the second round become available')),
('syntheses_second_phase_limit', models.DateTimeField(default=django.utils.timezone.now, verbose_name='limit date to upload the syntheses for the second phase')),
('description', models.TextField(blank=True, verbose_name='description')),
('final', models.BooleanField(default=False, verbose_name='final')),

View File

@ -1,4 +1,4 @@
# Generated by Django 3.0.11 on 2020-12-30 12:02
# Generated by Django 3.0.11 on 2021-01-21 21:06
import address.models
from django.db import migrations, models
@ -10,8 +10,8 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('registration', '0001_initial'),
('address', '0003_auto_20200830_1851'),
('registration', '0001_initial'),
('participation', '0001_initial'),
]
@ -37,8 +37,8 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='synthesis',
name='pool',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.Pool', verbose_name='pool'),
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',
@ -60,6 +60,26 @@ class Migration(migrations.Migration):
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'),
),
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'),
),
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'),
),
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'),
),
migrations.AddField(
model_name='participation',
name='team',
@ -70,13 +90,23 @@ class Migration(migrations.Migration):
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'),
),
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'),
),
migrations.AddIndex(
model_name='tournament',
index=models.Index(fields=['name', 'date_start', 'date_end'], name='participati_name_b43174_idx'),
),
migrations.AlterUniqueTogether(
name='synthesis',
unique_together={('participation', 'pool', 'type')},
unique_together={('participation', 'passage', 'type')},
),
migrations.AlterUniqueTogether(
name='solution',

View File

@ -1,18 +0,0 @@
# Generated by Django 3.0.11 on 2020-12-31 11:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0002_auto_20201230_1302'),
]
operations = [
migrations.AddField(
model_name='tournament',
name='max_teams',
field=models.PositiveSmallIntegerField(default=9, verbose_name='max team count'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-01 10:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0003_tournament_max_teams'),
]
operations = [
migrations.AddField(
model_name='tournament',
name='price',
field=models.PositiveSmallIntegerField(default=21, verbose_name='price'),
),
]

View File

@ -1,24 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-01 10:49
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('participation', '0004_tournament_price'),
]
operations = [
migrations.AddField(
model_name='tournament',
name='solutions_available_second_phase',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='date when the solutions for the second round become available'),
),
migrations.AddField(
model_name='tournament',
name='solutions_draw',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='random draw for solutions'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-12 16:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0005_auto_20210101_1149'),
]
operations = [
migrations.AddField(
model_name='participation',
name='final',
field=models.BooleanField(default=False, help_text='The team is selected for the final tournament.', verbose_name='selected for final'),
),
]

View File

@ -1,29 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-12 17:01
from django.db import migrations, models
import participation.models
class Migration(migrations.Migration):
dependencies = [
('participation', '0006_participation_final'),
]
operations = [
migrations.AlterField(
model_name='solution',
name='file',
field=models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_solution_filename, verbose_name='file'),
),
migrations.AlterField(
model_name='solution',
name='problem',
field=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'),
),
migrations.AlterField(
model_name='synthesis',
name='file',
field=models.FileField(blank=True, default='', unique=True, upload_to=participation.models.get_synthesis_filename, verbose_name='file'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-13 16:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0007_auto_20210112_1801'),
]
operations = [
migrations.AlterField(
model_name='pool',
name='round',
field=models.PositiveSmallIntegerField(choices=[(1, 'Round 1'), (2, 'Round 2')], verbose_name='round'),
),
]

View File

@ -1,43 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-14 12:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('participation', '0008_auto_20210113_1700'),
]
operations = [
migrations.CreateModel(
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')),
('defender', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='defender')),
('opponent', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='opponent')),
('pool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='passages', to='participation.Pool', verbose_name='pool')),
('reporter', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='participation.Participation', verbose_name='reporter')),
],
options={
'verbose_name': 'passage',
'verbose_name_plural': 'passages',
},
),
migrations.AddField(
model_name='synthesis',
name='passage',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='syntheses', to='participation.Passage', verbose_name='passage'),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name='synthesis',
unique_together={('participation', 'passage', 'type')},
),
migrations.RemoveField(
model_name='synthesis',
name='pool',
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-14 13:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0009_auto_20210114_1313'),
]
operations = [
migrations.AddField(
model_name='passage',
name='solution_number',
field=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')], default=None, verbose_name='defended solution'),
preserve_default=False,
),
]

View File

@ -1,33 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-14 16:59
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('registration', '0001_initial'),
('participation', '0010_passage_solution_number'),
]
operations = [
migrations.CreateModel(
name='Note',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('defender_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19), (20, 20)], default=0, verbose_name='defender writing note')),
('defender_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16)], default=0, verbose_name='defender oral note')),
('opponent_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)], default=0, verbose_name='opponent writing note')),
('opponent_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)], default=0, verbose_name='opponent oral note')),
('reporter_writing', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)], default=0, verbose_name='reporter writing note')),
('reporter_oral', models.PositiveSmallIntegerField(choices=[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)], default=0, verbose_name='reporter oral note')),
('jury', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='registration.VolunteerRegistration', verbose_name='jury')),
('passage', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='participation.Passage', verbose_name='passage')),
],
options={
'verbose_name': 'note',
'verbose_name_plural': 'notes',
},
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-21 16:47
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('participation', '0011_note'),
]
operations = [
migrations.AddField(
model_name='pool',
name='bbb_code',
field=models.CharField(blank=True, default='', help_text='The code of the form xxx-xxx-xxx at the end of the BBB link.', max_length=11, validators=[django.core.validators.RegexValidator('[a-z]{3}-[a-z]{3}-[a-z]{3}')], verbose_name='BigBlueButton code'),
),
]

View File

@ -62,11 +62,13 @@
<dt class="col-sm-6 text-right">{% trans "Health sheets:" %}</dt>
<dd class="col-sm-6">
{% for participant in team.participants.all %}
{% if participant.health_sheet %}
<a href="{{ participant.health_sheet.url }}" data-turbolinks="false">{{ participant }}</a>{% if not forloop.last %},{% endif %}
{% else %}
{{ participant }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %}
{% for student in team.students.all %}
{% if student.under_18 %}
{% if student.health_sheet %}
<a href="{{ student.health_sheet.url }}" data-turbolinks="false">{{ student }}</a>{% if not forloop.last %},{% endif %}
{% else %}
{{ student }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</dd>

View File

@ -177,7 +177,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
context["can_validate"] = team.students.count() >= 4 and team.coaches.exists() and \
all(r.email_confirmed for r in team.students.all()) and \
all(r.photo_authorization for r in team.participants.all()) and \
all(r.health_sheet for r in team.participants.all()) and \
all(r.health_sheet for r in team.students.all() if r.under_18) and \
all(r.parental_authorization for r in team.students.all() if r.under_18)
return context

View File

@ -2,9 +2,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import admin
from django.contrib.admin import ModelAdmin
from polymorphic.admin import PolymorphicChildModelAdmin, PolymorphicParentModelAdmin
from .models import AdminRegistration, CoachRegistration, Registration, StudentRegistration
from .models import AdminRegistration, CoachRegistration, Payment, Registration, StudentRegistration
@admin.register(Registration)
@ -27,3 +28,10 @@ class CoachRegistrationAdmin(PolymorphicChildModelAdmin):
@admin.register(AdminRegistration)
class AdminRegistrationAdmin(PolymorphicChildModelAdmin):
pass
@admin.register(Payment)
class PaymentAdmin(ModelAdmin):
list_display = ('registration', 'type', 'valid', )
search_fields = ('registration__user__last_name', 'registration__user__first_name', 'registration__user__email',)
list_filter = ('type', 'valid',)

View File

@ -1,4 +1,4 @@
# Generated by Django 3.0.11 on 2020-12-30 12:02
# Generated by Django 3.0.11 on 2021-01-21 21:06
import address.models
import datetime
@ -14,10 +14,10 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('address', '0003_auto_20200830_1851'),
('participation', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('participation', '0001_initial'),
]
operations = [
@ -42,7 +42,6 @@ class Migration(migrations.Migration):
('birth_date', models.DateField(default=datetime.date.today, verbose_name='birth date')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='phone number')),
('photo_authorization', models.FileField(blank=True, default='', upload_to=registration.models.get_random_photo_filename, verbose_name='photo authorization')),
('health_sheet', models.FileField(blank=True, default='', upload_to=registration.models.get_random_health_filename, verbose_name='health sheet')),
('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')),
],
@ -98,6 +97,7 @@ class Migration(migrations.Migration):
('responsible_phone', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, region=None, verbose_name='responsible phone number')),
('responsible_email', models.EmailField(default='', max_length=254, verbose_name='responsible email address')),
('parental_authorization', models.FileField(blank=True, default='', upload_to=registration.models.get_random_parental_filename, verbose_name='parental authorization')),
('health_sheet', models.FileField(blank=True, default='', upload_to=registration.models.get_random_health_filename, verbose_name='health sheet')),
],
options={
'verbose_name': 'student registration',
@ -105,4 +105,19 @@ class Migration(migrations.Migration):
},
bases=('registration.participantregistration',),
),
migrations.CreateModel(
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')),
('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')),
],
options={
'verbose_name': 'payment',
'verbose_name_plural': 'payments',
},
),
]

View File

@ -1,26 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-18 15:35
from django.db import migrations, models
import django.db.models.deletion
import registration.models
class Migration(migrations.Migration):
dependencies = [
('registration', '0001_initial'),
]
operations = [
migrations.CreateModel(
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')),
('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='registration', to='registration.ParticipantRegistration', verbose_name='registration')),
],
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 3.0.11 on 2021-01-18 16:38
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('registration', '0002_payment'),
]
operations = [
migrations.AlterModelOptions(
name='payment',
options={'verbose_name': 'payment', 'verbose_name_plural': 'payments'},
),
migrations.AlterField(
model_name='payment',
name='registration',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment', to='registration.ParticipantRegistration', verbose_name='registration'),
),
]

View File

@ -146,13 +146,6 @@ class ParticipantRegistration(Registration):
default="",
)
health_sheet = models.FileField(
verbose_name=_("health sheet"),
upload_to=get_random_health_filename,
blank=True,
default="",
)
@property
def under_18(self):
return (timezone.now().date() - self.birth_date).days < 18 * 365.24
@ -208,6 +201,13 @@ class StudentRegistration(ParticipantRegistration):
default="",
)
health_sheet = models.FileField(
verbose_name=_("health sheet"),
upload_to=get_random_health_filename,
blank=True,
default="",
)
@property
def type(self):
return _("student")

View File

@ -0,0 +1,127 @@
\documentclass[a4paper,french,11pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[french]{babel}
\usepackage{fancyhdr}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{amssymb}
%\usepackage{anyfontsize}
\usepackage{fancybox}
\usepackage{eso-pic,graphicx}
\usepackage{xcolor}
% Specials
\newcommand{\writingsep}{\vrule height 4ex width 0pt}
% Page formating
\hoffset -1in
\voffset -1in
\textwidth 180 mm
\textheight 250 mm
\oddsidemargin 15mm
\evensidemargin 15mm
\pagestyle{fancy}
% Headers and footers
\fancyfoot{}
\lhead{}
\rhead{}
\renewcommand{\headrulewidth}{0pt}
\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018}
\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.}
\begin{document}
\includegraphics[height=2cm]{/code/static/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\vfill
\begin{center}
\LARGE
Autorisation d'enregistrement et de diffusion de l'image ({{ tournament.name }})
\end{center}
\normalsize
\thispagestyle{empty}
\bigskip
Je soussign\'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 dutiliser 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
publication et la diffusion de l'image ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie
priv\'ee, \`a la dignit\'e et \`a la r\'eputation de la personne photographiée.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies
prises \`a l'occasion dune \'eventuelle m\'ediatisation de cet événement.\\
\medskip
Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es,
de rectification, de modification et de suppression des donn\'ees qui vous concernent.
Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre
recommand\'ee avec accus\'e de r\'eception adress\'ee \`a
Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par
la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant,
pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\
\medskip
\fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses
partenaires.
\bigskip
Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{}
\medskip
\begin{minipage}[c]{0.5\textwidth}
\underline{Le participant :}\\
Fait \`a :\\
le
\end{minipage}
\vfill
\vfill
\begin{minipage}[c]{0.5\textwidth}
\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018
\end{minipage}
\begin{minipage}[c]{0.5\textwidth}
\footnotesize
\begin{flushright}
Association agréée par\\le Ministère de l'éducation nationale.
\end{flushright}
\end{minipage}
\end{document}

View File

@ -3,7 +3,7 @@
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[frenchb]{babel}
\usepackage[french]{babel}
\usepackage{fancyhdr}
\usepackage{graphicx}
@ -37,7 +37,7 @@
\begin{document}
\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\includegraphics[height=2cm]{/code/static/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\vfill
@ -46,7 +46,7 @@
\LARGE
Autorisation d'enregistrement et de diffusion de l'image
({TOURNAMENT_NAME})
({{ tournament.name }})
\end{center}
\normalsize
@ -58,31 +58,45 @@ 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 {PARTICIPANT_NAME}\\
demeurant au {ADDRESS}
agissant en qualit\'e de repr\'esentant 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$ du {START_DATE} au {END_DATE} {YEAR} à : {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 dutiliser 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$ 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 dutiliser 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 publication et la diffusion de l'image de l'enfant ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de lenfant.\\
Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la
publication et la diffusion de l'image de l'enfant ainsi que des commentaires l'accompagnant ne portent pas atteinte
\`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de lenfant.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies de mon enfant prises \`a l'occasion dune \'eventuelle m\'ediatisation de cet événement.\\
\fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de
photographies de mon enfant prises \`a l'occasion dune \'eventuelle m\'ediatisation de cet événement.\\
\medskip
Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent.
Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de
rectification, de modification et de suppression des donn\'ees qui vous concernent.
Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre
recommand\'ee avec accus\'e de r\'eception adress\'ee \`a
Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\
\fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par
la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant,
pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\
\medskip
\fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires.
\fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses
partenaires.
\bigskip

View File

@ -37,28 +37,30 @@
\begin{document}
\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\includegraphics[height=2cm]{/code/static/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\vfill
\begin{center}
\Large \bf Autorisation parentale pour les mineurs ({TOURNAMENT_NAME})
\Large \bf Autorisation parentale pour les mineurs ({{ tournament.name }})
\end{center}
Je soussigné(e) \hrulefill,\\
responsable légal, demeurant \writingsep\hrulefill\\
\writingsep\hrulefill,\\
\writingsep autorise {PARTICIPANT_NAME},\\
né(e) le {BIRTHDAY},
à participer au Tournoi Français des Jeunes Mathématiciennes et Mathématiciens ($\mathbb{TFJM}^2$) organisé \`a : {PLACE}, du {START_DATE} au {END_DATE} {YEAR}.
\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 :
{{ tournament.place }}, du {{ tournament.date_start }} au {{ tournament.date_end }}.
{PRONOUN} se rendra au lieu indiqu\'e ci-dessus le vendredi matin et quittera les lieux l'après-midi du dimanche par ses propres moyens et sous la responsabilité du représentant légal.
Iel se rendra au lieu indiqu\'e ci-dessus le vendredi matin et quittera les lieux l'après-midi du dimanche par
ses propres moyens et sous la responsabilité du représentant légal.
\vspace{8ex}
Fait à \vrule width 10cm height 0pt depth 0.4pt, le \phantom{232323}/\phantom{XXX}/{YEAR},
Fait à \vrule width 10cm height 0pt depth 0.4pt, le \phantom{232323}/\phantom{XXX}/{% now "Y" %},
\vfill
\vfill

View File

@ -38,12 +38,12 @@
\begin{document}
\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{50pt}{50pt}{$\mathbb{TFJM}^2$}}
\includegraphics[height=2cm]{/code/static/logo_animath.png}\hfill{\fontsize{50pt}{50pt}{$\mathbb{TFJM}^2$}}
\begin{center}
\Large \bf Instructions ({TOURNAMENT_NAME})
\Large \bf Instructions ({{ tournament.name }})
\end{center}
\section{Documents}
@ -51,7 +51,8 @@
Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi).
\subsection{Autorisation de prise de vue}
Si l'élève est mineur \textbf{au moment de la signature}, il convient de remplir l'autorisation pour les mineurs. En revanche, s'il est majeur \textbf{au moment de la signature}, il convient de remplir la fiche pour majeur.
Si l'élève est mineur \textbf{au moment de la signature}, il convient de remplir l'autorisation pour les mineurs.
En revanche, s'il est majeur \textbf{au moment de la signature}, il convient de remplir la fiche pour majeur.
\subsection{Fiche sanitaire}
Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi).
@ -59,20 +60,27 @@ Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si
\section{Paiement}
{% if tournament.price %}
\subsection{Montant}
Les frais d'inscription sont fixés à {PRICE} euros. Vous devez vous en acquitter \textbf{avant le {END_PAYMENT_DATE} {YEAR}}. Si l'élève est boursier, il en est dispensé, vous devez alors fournir une copie de sa notification de bourse directement sur la plateforme \textbf{avant le {END_PAYMENT_DATE} {YEAR}}.
Les frais d'inscription sont fixés à {{ tournament.price }} euros. Vous devez vous en acquitter
\textbf{avant le {{ tournament.inscription_limit.date }}}. Si l'élève est boursier, il en est dispensé, vous devez alors
fournir une copie de sa notification de bourse directement sur la plateforme
\textbf{avant le {{ tournament.inscription_limit.date }}}.
\subsection{Procédure}
Si le paiement de plusieurs élèves est fait en une seule opération, merci de contacter \href{mailto: contact@tfjm.org}{contact@tfjm.org} \textbf{avant le paiement} pour garantir l'identification de ce dernier
Si le paiement de plusieurs élèves est fait en une seule opération, merci de contacter
\href{mailto: contact@tfjm.org}{contact@tfjm.org} \textbf{avant le paiement} pour garantir l'identification de ce dernier.
\subsubsection*{Carte bancaire (uniquement les cartes françaises)}
Le paiement s'effectue en ligne via la plateforme à l'adresse : \url{https://www.helloasso.com/associations/animath/evenements/tfjm-2020}
Le paiement s'effectue en ligne via la plateforme à l'adresse : \url{https://www.helloasso.com/associations/animath/evenements/tfjmm-2021}
Vous devez impérativement indiquer dans le champ "Référence" la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}.
\subsubsection*{Virement}
\textbf{Si vous ne pouvez pas utiliser le paiement par carte}, vous pouvez faire un virement sur le compte ci-dessous en indiquant bien dans le champ "motif" (ou autre champ propre à votre banque dont le contenu est communiqué au destinataire) la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}.
\textbf{Si vous ne pouvez pas utiliser le paiement par carte}, vous pouvez faire un virement sur le compte ci-dessous en
indiquant bien dans le champ "motif" (ou autre champ propre à votre banque dont le contenu est communiqué au destinataire)
la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}.
IBAN FR76 1027 8065 0000 0206 4290 127
@ -80,7 +88,12 @@ BIC CMCIFR2A
\subsubsection*{Autre}
Si aucune de ces procédures n'est possible pour vous, envoyez un mail à \href{mailto: contact@tfjm.org}{contact@tfjm.org} pour que nous trouvions une solution à vos difficultés.
Si aucune de ces procédures n'est possible pour vous, envoyez un mail à \href{mailto: contact@tfjm.org}{contact@tfjm.org}
pour que nous trouvions une solution à vos difficultés.
{% else %}
Le tournoi est gratuit, vous n'avez aucun frais à avoir.
{% endif %}

View File

@ -9,7 +9,7 @@
<div id="form-content">
<div class="alert alert-info">
{% trans "Authorization template:" %}
<a class="alert-link" href="{% static "Autorisation_parentale.tex" %}">{% trans "Download" %}</a>
<a class="alert-link" href="{% url "registration:parental_authorization_template" %}?registration_id={{ object.pk }}&tournament_id={{ object.team.participation.tournament.pk }}" data-turbolinks="false">{% trans "Download" %}</a>
</div>
{% csrf_token %}
{{ form|crispy }}

View File

@ -9,8 +9,8 @@
<div id="form-content">
<div class="alert alert-info">
{% trans "Authorization templates:" %}
<a class="alert-link" href="{% static "Autorisation_droit_image_majeur.tex" %}">{% trans "Adult" %}</a>
<a class="alert-link" href="{% static "Autorisation_droit_image_mineur.tex" %}">{% trans "Child" %}</a>
<a class="alert-link" href="{% url "registration:photo_authorization_adult_template" %}?registration_id={{ object.pk }}&tournament_id={{ object.team.participation.tournament.pk }}" data-turbolinks="false">{% trans "Adult" %}</a>
<a class="alert-link" href="{% url "registration:photo_authorization_child_template" %}?registration_id={{ object.pk }}&tournament_id={{ object.team.participation.tournament.pk }}" data-turbolinks="false">{% trans "Child" %}</a>
</div>
{% csrf_token %}
{{ form|crispy }}

View File

@ -57,20 +57,20 @@
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadPhotoAuthorizationModal">{% trans "Replace" %}</button>
{% endif %}
</dd>
<dt class="col-sm-6 text-right">{% trans "Health sheet:" %}</dt>
<dd class="col-sm-6">
{% if user_object.registration.health_sheet %}
<a href="{{ user_object.registration.health_sheet.url }}" data-turbolinks="false">{% trans "Download" %}</a>
{% endif %}
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadHealthSheetModal">{% trans "Replace" %}</button>
{% endif %}
</dd>
{% endif %}
{% if user_object.registration.studentregistration %}
{% if user_object.registration.under_18 %}
<dt class="col-sm-6 text-right">{% trans "Health sheet:" %}</dt>
<dd class="col-sm-6">
{% if user_object.registration.health_sheet %}
<a href="{{ user_object.registration.health_sheet.url }}" data-turbolinks="false">{% trans "Download" %}</a>
{% endif %}
{% if user_object.registration.team and not user_object.registration.team.participation.valid %}
<button class="btn btn-primary" data-toggle="modal" data-target="#uploadHealthSheetModal">{% trans "Replace" %}</button>
{% endif %}
</dd>
<dt class="col-sm-6 text-right">{% trans "Parental authorization:" %}</dt>
<dd class="col-sm-6">
{% if user_object.registration.parental_authorization %}

View File

@ -3,9 +3,10 @@
from django.urls import path
from .views import AddOrganizerView, MyAccountDetailView, PaymentUpdateView, ResetAdminView, SignupView, \
UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, UserUpdateView, \
UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
from .views import AddOrganizerView, AdultPhotoAuthorizationTemplateView, ChildPhotoAuthorizationTemplateView, \
InstructionsTemplateView, MyAccountDetailView, ParentalAuthorizationTemplateView, PaymentUpdateView, \
ResetAdminView, SignupView, UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, \
UserUpdateView, UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
UserValidateView, UserValidationEmailSentView
app_name = "registration"
@ -22,7 +23,14 @@ urlpatterns = [
path("user/<int:pk>/update/", UserUpdateView.as_view(), name="update_user"),
path("user/<int:pk>/upload-photo-authorization/", UserUploadPhotoAuthorizationView.as_view(),
name="upload_user_photo_authorization"),
path("user/<int:pk>/upload-health_sheet/", UserUploadHealthSheetView.as_view(),
path("parental-authorization-template/", ParentalAuthorizationTemplateView.as_view(),
name="parental_authorization_template"),
path("photo-authorization-template/adult/", AdultPhotoAuthorizationTemplateView.as_view(),
name="photo_authorization_adult_template"),
path("photo-authorization-template/child/", ChildPhotoAuthorizationTemplateView.as_view(),
name="photo_authorization_child_template"),
path("instructions-template/", InstructionsTemplateView.as_view(), name="instructions_template"),
path("user/<int:pk>/upload-health-sheet/", UserUploadHealthSheetView.as_view(),
name="upload_user_health_sheet"),
path("user/<int:pk>/upload-parental-authorization/", UserUploadParentalAuthorizationView.as_view(),
name="upload_user_parental_authorization"),

View File

@ -2,6 +2,8 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import subprocess
from tempfile import mkdtemp
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
@ -21,7 +23,7 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
from django_tables2 import SingleTableView
from magic import Magic
from participation.models import Passage, Solution, Synthesis
from participation.models import Passage, Solution, Synthesis, Tournament
from tfjm.tokens import email_validation_token
from tfjm.views import AdminMixin, UserMixin, VolunteerMixin
@ -381,6 +383,52 @@ class UserUploadParentalAuthorizationView(UserMixin, UpdateView):
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
class AuthorizationTemplateView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if "registration_id" in self.request.GET:
registration = Registration.objects.get(pk=self.request.GET.get("registration_id"))
# Don't get unwanted information
if registration.user == self.request.user \
or self.request.user.is_authenticated and self.request.user.registration.is_admin:
context["registration"] = registration
if "tournament_id" in self.request.GET:
context["tournament"] = Tournament.objects.get(pk=self.request.GET.get("tournament_id"))
else:
raise ValueError("Merci d'indiquer un tournoi.")
return context
def render_to_response(self, context, **response_kwargs):
tex = render_to_string(self.template_name, context=context, request=self.request)
temp_dir = mkdtemp()
with open(os.path.join(temp_dir, "texput.tex"), "w") as f:
f.write(tex)
process = subprocess.Popen(["pdflatex", "-interaction=nonstopmode", f"-output-directory={temp_dir}",
os.path.join(temp_dir, "texput.tex"), ])
process.wait()
return FileResponse(open(os.path.join(temp_dir, "texput.pdf"), "rb"),
content_type="application/pdf",
filename=self.template_name.split("/")[-1][:-3] + "pdf")
class AdultPhotoAuthorizationTemplateView(AuthorizationTemplateView):
template_name = "registration/tex/Autorisation_droit_image_majeur.tex"
class ChildPhotoAuthorizationTemplateView(AuthorizationTemplateView):
template_name = "registration/tex/Autorisation_droit_image_mineur.tex"
class ParentalAuthorizationTemplateView(AuthorizationTemplateView):
template_name = "registration/tex/Autorisation_parentale.tex"
class InstructionsTemplateView(AuthorizationTemplateView):
template_name = "registration/tex/Instructions.tex"
class PaymentUpdateView(LoginRequiredMixin, UpdateView):
model = Payment
form_class = PaymentForm
@ -438,7 +486,7 @@ class HealthSheetView(LoginRequiredMixin, View):
path = f"media/authorization/health/{filename}"
if not os.path.exists(path):
raise Http404
student = ParticipantRegistration.objects.get(health_sheet__endswith=filename)
student = StudentRegistration.objects.get(health_sheet__endswith=filename)
user = request.user
if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
and student.team.participation.tournament in user.registration.organized_tournaments.all()):

View File

@ -15,3 +15,6 @@
# Check payments from Hello Asso
*/6 * * * * cd /code && python manage.py check_hello_asso &> /dev/null
# Clean temporary files
30 * * * * rm -rf /tmp/*

View File

@ -1,113 +0,0 @@
\documentclass[a4paper,french,11pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[frenchb]{babel}
\usepackage{fancyhdr}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{amssymb}
%\usepackage{anyfontsize}
\usepackage{fancybox}
\usepackage{eso-pic,graphicx}
\usepackage{xcolor}
% Specials
\newcommand{\writingsep}{\vrule height 4ex width 0pt}
% Page formating
\hoffset -1in
\voffset -1in
\textwidth 180 mm
\textheight 250 mm
\oddsidemargin 15mm
\evensidemargin 15mm
\pagestyle{fancy}
% Headers and footers
\fancyfoot{}
\lhead{}
\rhead{}
\renewcommand{\headrulewidth}{0pt}
\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018}
\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.}
\begin{document}
\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}}
\vfill
\begin{center}
\LARGE
Autorisation d'enregistrement et de diffusion de l'image ({TOURNAMENT_NAME})
\end{center}
\normalsize
\thispagestyle{empty}
\bigskip
Je soussign\'e {PARTICIPANT_NAME}\\
demeurant au {ADDRESS}
\medskip
Cochez la/les cases correspondantes.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ du {START_DATE} au {END_DATE} {YEAR} à : {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 dutiliser 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 publication et la diffusion de l'image ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de la personne photographiée.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies prises \`a l'occasion dune \'eventuelle m\'ediatisation de cet événement.\\
\medskip
Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent.
Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\
\medskip
\fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\
\medskip
\fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires.
\bigskip
Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{}
\medskip
\begin{minipage}[c]{0.5\textwidth}
\underline{L'\'el\`eve :}\\
Fait \`a :\\
le
\end{minipage}
\vfill
\vfill
\begin{minipage}[c]{0.5\textwidth}
\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018
\end{minipage}
\begin{minipage}[c]{0.5\textwidth}
\footnotesize
\begin{flushright}
Association agréée par\\le Ministère de l'éducation nationale.
\end{flushright}
\end{minipage}
\end{document}

Binary file not shown.