1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-02-26 05:46:33 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Emmy D'Anello
0f2c44331c
Add vaccine sheet field, closes #18 2023-02-20 00:38:57 +01:00
Emmy D'Anello
fae4ee7105
Drop AdminRegistration in favour of a new boolean field, closes #19 2023-02-20 00:25:06 +01:00
22 changed files with 471 additions and 265 deletions

View File

@ -12,7 +12,6 @@ from django.core.exceptions import ValidationError
from django.core.validators import FileExtensionValidator
from django.utils.translation import gettext_lazy as _
from pypdf import PdfFileReader
from registration.models import VolunteerRegistration
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament

View File

@ -8,7 +8,7 @@ from django.core.management import BaseCommand
from django.utils.http import urlencode
from django.utils.translation import activate
from participation.models import Team, Tournament
from registration.models import AdminRegistration, Registration, VolunteerRegistration
from registration.models import Registration, VolunteerRegistration
from tfjm.matrix import Matrix, RoomPreset, RoomVisibility
@ -163,7 +163,7 @@ class Command(BaseCommand):
self.stdout.write(f"Invite {volunteer} in #aide-jury-orgas...")
# Admins are admins
for admin in AdminRegistration.objects.all():
for admin in VolunteerRegistration.objects.filter(admin=True).all():
self.stdout.write(f"Invite {admin} in #cno and #dev-bot...")
await Matrix.invite("#cno:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
await Matrix.invite("#dev-bot:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
@ -264,7 +264,7 @@ class Command(BaseCommand):
await Matrix.set_room_avatar(f"#tirage-au-sort-{slug}:tfjm.org", avatar_uri)
# Invite admins and give permissions
for admin in AdminRegistration.objects.all():
for admin in VolunteerRegistration.objects.filter(admin=True).all():
self.stdout.write(f"Invite {admin} in all channels of the tournament {name}...")
await Matrix.invite(f"#annonces-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
await Matrix.invite(f"#flood-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
@ -374,7 +374,7 @@ class Command(BaseCommand):
"customwidget", "Tableau", str(pool))
# Invite admins and give permissions
for admin in AdminRegistration.objects.all():
for admin in VolunteerRegistration.objects.filter(admin=True).all():
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
f"@{admin.matrix_username}:tfjm.org")
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",

View File

@ -4,7 +4,7 @@
from django.core.management import BaseCommand
from django.db.models import Q
from participation.models import Team, Tournament
from registration.models import AdminRegistration, ParticipantRegistration, VolunteerRegistration
from registration.models import ParticipantRegistration, VolunteerRegistration
from tfjm.lists import get_sympa_client
@ -71,5 +71,5 @@ class Command(BaseCommand):
slug = jury_in.tournament.name.lower().replace(" ", "-")
sympa.subscribe(volunteer.user.email, f"jurys-{slug}", True)
for admin in AdminRegistration.objects.all():
for admin in VolunteerRegistration.objects.filter(admin=True).all():
sympa.subscribe(admin.user.email, "admins", True)

View File

@ -74,6 +74,19 @@
{% endfor %}
</dd>
<dt class="col-sm-6 text-right">{% trans "Vaccine sheets:" %}</dt>
<dd class="col-sm-6">
{% for student in team.students.all %}
{% if student.under_18 %}
{% if student.vaccine_sheet %}
<a href="{{ student.vaccine_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>
<dt class="col-sm-6 text-right">{% trans "Parental authorizations:" %}</dt>
<dd class="col-sm-6">
{% for student in team.students.all %}

View File

@ -230,6 +230,7 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/mai-linh",
health_sheet="authorization/health/mai-linh",
vaccine_sheet="authorization/vaccine/mai-linh",
parental_authorization="authorization/parental/mai-linh",
)
@ -251,6 +252,7 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/emmy",
health_sheet="authorization/health/emmy",
vaccine_sheet="authorization/vaccine/emmy",
parental_authorization="authorization/parental/emmy",
)
@ -272,11 +274,13 @@ class TestStudentParticipation(TestCase):
city="Paris",
photo_authorization="authorization/photo/tfjm",
health_sheet="authorization/health/tfjm",
vaccine_sheet="authorization/health/tfjm",
parental_authorization="authorization/parental/tfjm",
)
self.coach.registration.team = self.team
self.coach.registration.health_sheet = "authorization/health/coach"
self.coach.registration.vaccine_sheet = "authorization/vaccine/coach"
self.coach.registration.photo_authorization = "authorization/photo/coach"
self.coach.registration.email_confirmed = True
self.coach.registration.save()
@ -305,6 +309,7 @@ class TestStudentParticipation(TestCase):
self.user.registration.photo_authorization = "authorization/photo/ananas"
self.user.registration.health_sheet = "authorization/health/ananas"
self.user.registration.vaccine_sheet = "authorization/health/ananas"
self.user.registration.parental_authorization = "authorization/parental/ananas"
self.user.registration.save()

View File

@ -180,6 +180,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
context["validation_form"] = ValidateParticipationForm(self.request.POST or None)
# A team is complete when there are at least 4 members plus a coache that have sent their authorizations,
# their health sheet, they confirmed their email address and under-18 people sent their parental authorization.
# TODO: Add vaccine sheets
context["can_validate"] = team.students.count() >= 4 and team.coaches.exists() and \
team.participation.tournament and \
all(r.photo_authorization for r in team.participants.all()) and \
@ -414,6 +415,12 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
zf.write("media/" + participant.health_sheet.name,
_("Health sheet of {participant}.{ext}").format(participant=str(participant), ext=ext))
if isinstance(participant, StudentRegistration) and participant.vaccine_sheet:
mime_type = magic.from_file("media/" + participant.vaccine_sheet.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.vaccine_sheet.name,
_("Vaccine sheet of {participant}.{ext}").format(participant=str(participant), ext=ext))
if team.motivation_letter:
mime_type = magic.from_file("media/" + team.motivation_letter.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")

View File

@ -5,12 +5,12 @@ from django.contrib import admin
from django.contrib.admin import ModelAdmin
from polymorphic.admin import PolymorphicChildModelAdmin, PolymorphicParentModelAdmin
from .models import AdminRegistration, CoachRegistration, Payment, Registration, StudentRegistration
from .models import CoachRegistration, Payment, Registration, StudentRegistration, VolunteerRegistration
@admin.register(Registration)
class RegistrationAdmin(PolymorphicParentModelAdmin):
child_models = (StudentRegistration, CoachRegistration, AdminRegistration,)
child_models = (StudentRegistration, CoachRegistration, VolunteerRegistration,)
list_display = ("user", "type", "email_confirmed",)
polymorphic_list = True
@ -25,8 +25,8 @@ class CoachRegistrationAdmin(PolymorphicChildModelAdmin):
pass
@admin.register(AdminRegistration)
class AdminRegistrationAdmin(PolymorphicChildModelAdmin):
@admin.register(VolunteerRegistration)
class VolunteerRegistrationAdmin(PolymorphicChildModelAdmin):
pass

View File

@ -4,16 +4,10 @@
from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer
from ..models import AdminRegistration, CoachRegistration, ParticipantRegistration, \
from ..models import CoachRegistration, ParticipantRegistration, \
StudentRegistration, VolunteerRegistration
class AdminSerializer(serializers.ModelSerializer):
class Meta:
model = AdminRegistration
fields = '__all__'
class CoachSerializer(serializers.ModelSerializer):
class Meta:
model = CoachRegistration
@ -40,7 +34,6 @@ class VolunteerSerializer(serializers.ModelSerializer):
class RegistrationSerializer(PolymorphicSerializer):
model_serializer_mapping = {
AdminRegistration: AdminSerializer,
CoachRegistration: CoachSerializer,
StudentRegistration: StudentSerializer,
VolunteerRegistration: VolunteerSerializer,

View File

@ -20,4 +20,3 @@ class RegistrationConfig(AppConfig):
post_save.connect(create_payment, "registration.Registration")
post_save.connect(create_payment, "registration.StudentRegistration")
post_save.connect(create_payment, "registration.CoachRegistration")
post_save.connect(create_payment, "registration.AdminRegistration")

View File

@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
from django.forms import FileInput
from django.utils.translation import gettext_lazy as _
from .models import AdminRegistration, CoachRegistration, ParticipantRegistration, Payment, \
from .models import CoachRegistration, ParticipantRegistration, Payment, \
StudentRegistration, VolunteerRegistration
@ -50,14 +50,6 @@ class AddOrganizerForm(forms.ModelForm):
"""
Signup form to registers volunteers
"""
type = forms.ChoiceField(
label=lambda: _("role").capitalize(),
choices=lambda: [
("volunteer", _("volunteer").capitalize()),
("admin", _("admin").capitalize()),
],
initial="volunteer",
)
def clean_email(self):
"""
@ -76,7 +68,7 @@ class AddOrganizerForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'type',)
fields = ('first_name', 'last_name', 'email',)
class UserForm(forms.ModelForm):
@ -154,6 +146,28 @@ class HealthSheetForm(forms.ModelForm):
fields = ('health_sheet',)
class VaccineSheetForm(forms.ModelForm):
"""
Form to send a vaccine sheet.
"""
def clean_vaccine_sheet(self):
if "vaccine_sheet" in self.files:
file = self.files["vaccine_sheet"]
if file.size > 2e6:
raise ValidationError(_("The uploaded file size must be under 2 Mo."))
if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]:
raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file."))
return self.cleaned_data["vaccine_sheet"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["vaccine_sheet"].widget = FileInput()
class Meta:
model = StudentRegistration
fields = ('vaccine_sheet',)
class ParentalAuthorizationForm(forms.ModelForm):
"""
Form to send a parental authorization.
@ -192,16 +206,7 @@ class VolunteerRegistrationForm(forms.ModelForm):
"""
class Meta:
model = VolunteerRegistration
fields = ('professional_activity', 'give_contact_to_animath', 'email_confirmed',)
class AdminRegistrationForm(forms.ModelForm):
"""
Admins can tell everything they want.
"""
class Meta:
model = AdminRegistration
fields = ('role', 'give_contact_to_animath', 'email_confirmed',)
fields = ('professional_activity', 'admin', 'give_contact_to_animath', 'email_confirmed',)
class PaymentForm(forms.ModelForm):

View File

@ -0,0 +1,51 @@
# Generated by Django 3.2.18 on 2023-02-19 22:13
from django.contrib.contenttypes.models import ContentType
from django.db import migrations, models
from django.db.models import F
def merge_admins(apps, schema_editor):
AdminRegistration = apps.get_model('registration', 'AdminRegistration')
VolunteerRegistration = apps.get_model('registration', 'VolunteerRegistration')
db_alias = schema_editor.connection.alias
AdminRegistration.objects.using(db_alias).update(admin=True)
for admin in AdminRegistration.objects.all():
admin.professional_activity = admin.role
admin.polymorphic_ctype_id = ContentType.objects.get_for_model(VolunteerRegistration).id
admin.save()
def separate_admins(apps, schema_editor):
AdminRegistration = apps.get_model('registration', 'AdminRegistration')
VolunteerRegistration = apps.get_model('registration', 'VolunteerRegistration')
for admin in VolunteerRegistration.objects.filter(admin=True).all():
admin.delete()
AdminRegistration.objects.create(user=admin.user,
professional_activity=admin.professional_activity,
role=admin.professional_activity)
class Migration(migrations.Migration):
dependencies = [
('participation', '0003_alter_team_trigram'),
('registration', '0003_alter_participantregistration_zip_code'),
]
operations = [
migrations.AddField(
model_name='volunteerregistration',
name='admin',
field=models.BooleanField(
default=False,
help_text="An administrator has all rights. Please don't give this right to all juries and volunteers.",
verbose_name='administrator'),
),
migrations.RunPython(
merge_admins,
separate_admins,
elidable=True,
),
migrations.DeleteModel(
name='AdminRegistration',
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.18 on 2023-02-19 23:38
from django.db import migrations, models
import registration.models
class Migration(migrations.Migration):
dependencies = [
('registration', '0004_volunteer_admin'),
]
operations = [
migrations.AddField(
model_name='studentregistration',
name='vaccine_sheet',
field=models.FileField(blank=True, default='', upload_to=registration.models.get_random_vaccine_filename, verbose_name='vaccine sheet'),
),
]

View File

@ -22,7 +22,7 @@ class Registration(PolymorphicModel):
"""
Registrations store extra content that are not asked in the User Model.
This is specific to the role of the user, see StudentRegistration,
ClassRegistration or AdminRegistration..
CoachRegistration or VolunteerRegistration.
"""
user = models.OneToOneField(
"auth.User",
@ -79,7 +79,7 @@ class Registration(PolymorphicModel):
@property
def is_admin(self):
return isinstance(self, AdminRegistration) or self.user.is_superuser
return isinstance(self, VolunteerRegistration) and self.admin or self.user.is_superuser
@property
def is_volunteer(self):
@ -108,6 +108,10 @@ def get_random_health_filename(instance, filename):
return "authorization/health/" + get_random_string(64)
def get_random_vaccine_filename(instance, filename):
return "authorization/vaccine/" + get_random_string(64)
def get_random_parental_filename(instance, filename):
return "authorization/parental/" + get_random_string(64)
@ -242,6 +246,13 @@ class StudentRegistration(ParticipantRegistration):
default="",
)
vaccine_sheet = models.FileField(
verbose_name=_("vaccine sheet"),
upload_to=get_random_vaccine_filename,
blank=True,
default="",
)
@property
def type(self):
return _("student")
@ -287,13 +298,19 @@ class VolunteerRegistration(Registration):
verbose_name=_("professional activity"),
)
admin = models.BooleanField(
verbose_name=_("administrator"),
help_text=_("An administrator has all rights. Please don't give this right to all juries and volunteers."),
default=False,
)
@property
def interesting_tournaments(self) -> set:
return set(self.organized_tournaments.all()).union(map(lambda pool: pool.tournament, self.jury_in.all()))
@property
def type(self):
return _('volunteer')
return _('admin') if self.is_admin else _('volunteer')
@property
def form_class(self):
@ -301,29 +318,6 @@ class VolunteerRegistration(Registration):
return VolunteerRegistrationForm
class AdminRegistration(VolunteerRegistration):
"""
Specific registration for admins.
They have a field to justify they status.
"""
role = models.TextField(
verbose_name=_("role of the administrator"),
)
@property
def type(self):
return _("admin")
@property
def form_class(self):
from registration.forms import AdminRegistrationForm
return AdminRegistrationForm
class Meta:
verbose_name = _("admin registration")
verbose_name_plural = _("admin registrations")
def get_scholarship_filename(instance, filename):
return f"authorization/scholarship/scholarship_{instance.registration.pk}"

View File

@ -4,7 +4,7 @@
from django.contrib.auth.models import User
from tfjm.lists import get_sympa_client
from .models import AdminRegistration, Payment, Registration
from .models import Payment, Registration, VolunteerRegistration
def set_username(instance, **_):
@ -40,7 +40,7 @@ def create_admin_registration(instance, **_):
ensure that an admin registration is created.
"""
if instance.is_superuser:
AdminRegistration.objects.get_or_create(user=instance)
VolunteerRegistration.objects.get_or_create(user=instance, admin=True)
def create_payment(instance: Registration, **_):

View File

@ -19,7 +19,7 @@ class RegistrationTable(tables.Table):
)
def order_type(self, queryset, desc):
types = ["volunteerregistration__adminregistration", "volunteerregistration", "participantregistration"]
types = ["-volunteerregistration__admin", "volunteerregistration", "participantregistration"]
return queryset.order_by(*(("-" if desc else "") + t for t in types)), True
class Meta:

View File

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% load i18n static crispy_forms_filters %}
{% block content %}
<a class="btn btn-info" href="{% url "registration:user_detail" pk=object.user.pk %}"><i class="fas fa-arrow-left"></i> {% trans "Back to the user detail" %}</a>
<hr>
<form method="post" enctype="multipart/form-data">
<div id="form-content">
{% csrf_token %}
{{ form|crispy }}
</div>
<button class="btn btn-success" type="submit">{% trans "Upload" %}</button>
</form>
{% endblock %}

View File

@ -79,6 +79,16 @@
{% endif %}
</dd>
<dt class="col-sm-6 text-right">{% trans "Vaccine sheet:" %}</dt>
<dd class="col-sm-6">
{% if user_object.registration.vaccine_sheet %}
<a href="{{ user_object.registration.vaccine_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="#uploadVaccineSheetModal">{% 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 %}
@ -107,8 +117,8 @@
<dd class="col-sm-6"><a href="mailto:{{ email }}">{{ email }}</a></dd>
{% endwith %}
{% elif user_object.registration.is_admin %}
<dt class="col-sm-6 text-right">{% trans "Role:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.role }}</dd>
<dt class="col-sm-6 text-right">{% trans "Admin:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.is_admin|yesno }}</dd>
{% elif user_object.registration.coachregistration or user_object.registration.is_volunteer %}
<dt class="col-sm-6 text-right">{% trans "Profesional activity:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.professional_activity }}</dd>
@ -171,6 +181,11 @@
{% url "registration:upload_user_health_sheet" pk=user_object.registration.pk as modal_action %}
{% include "base_modal.html" with modal_id="uploadHealthSheet" modal_enctype="multipart/form-data" %}
{% trans "Upload vaccine sheet" as modal_title %}
{% trans "Upload" as modal_button %}
{% url "registration:upload_user_vaccine_sheet" pk=user_object.registration.pk as modal_action %}
{% include "base_modal.html" with modal_id="uploadVaccineSheet" modal_enctype="multipart/form-data" %}
{% trans "Upload parental authorization" as modal_title %}
{% trans "Upload" as modal_button %}
{% url "registration:upload_user_parental_authorization" pk=user_object.registration.pk as modal_action %}

View File

@ -15,7 +15,7 @@ from django.utils.http import urlsafe_base64_encode
from participation.models import Team
from tfjm.tokens import email_validation_token
from .models import AdminRegistration, CoachRegistration, StudentRegistration
from .models import CoachRegistration, StudentRegistration, VolunteerRegistration
class TestIndexPage(TestCase):
@ -92,7 +92,7 @@ class TestRegistration(TestCase):
+ f"registration/registration/{self.user.registration.pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index") +
f"r/{ContentType.objects.get_for_model(AdminRegistration).id}/"
f"r/{ContentType.objects.get_for_model(VolunteerRegistration).id}/"
f"{self.user.registration.pk}/")
self.assertRedirects(response, "http://" + Site.objects.get().domain +
str(self.user.registration.get_absolute_url()), 302, 200)
@ -271,7 +271,7 @@ class TestRegistration(TestCase):
)
self.student.registration.save()
for user, data in [(self.user, dict(role="Bot")),
for user, data in [(self.user, dict(professional_activity="Bot", admin=True)),
(self.student, dict(student_class=11, school="Sky", birth_date="2001-01-01",
gender="female", address="1 Rue de Rivoli", zip_code=75001,
city="Paris", responsible_name="Toto",

View File

@ -7,7 +7,7 @@ from .views import AddOrganizerView, AdultPhotoAuthorizationTemplateView, ChildP
InstructionsTemplateView, MyAccountDetailView, ParentalAuthorizationTemplateView, PaymentUpdateView, \
ResetAdminView, SignupView, UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, \
UserUpdateView, UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
UserValidateView, UserValidationEmailSentView
UserUploadVaccineSheetView, UserValidateView, UserValidationEmailSentView
app_name = "registration"
@ -32,6 +32,8 @@ urlpatterns = [
path("instructions-template/", InstructionsTemplateView.as_view(), name="instructions_template"),
path("user/<int:pk>/upload-health-sheet/", UserUploadHealthSheetView.as_view(),
name="upload_user_health_sheet"),
path("user/<int:pk>/upload-vaccine-sheet/", UserUploadVaccineSheetView.as_view(),
name="upload_user_vaccine_sheet"),
path("user/<int:pk>/upload-parental-authorization/", UserUploadParentalAuthorizationView.as_view(),
name="upload_user_parental_authorization"),
path("update-payment/<int:pk>/", PaymentUpdateView.as_view(), name="update_payment"),

View File

@ -27,9 +27,9 @@ from participation.models import Passage, Solution, Synthesis, Tournament
from tfjm.tokens import email_validation_token
from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
from .forms import AddOrganizerForm, AdminRegistrationForm, CoachRegistrationForm, HealthSheetForm, \
from .forms import AddOrganizerForm, CoachRegistrationForm, HealthSheetForm, \
ParentalAuthorizationForm, PaymentForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm, \
VolunteerRegistrationForm
VaccineSheetForm, VolunteerRegistrationForm
from .models import ParticipantRegistration, Payment, Registration, StudentRegistration
from .tables import RegistrationTable
@ -91,24 +91,21 @@ class AddOrganizerView(VolunteerMixin, CreateView):
context = super().get_context_data()
context["volunteer_registration_form"] = VolunteerRegistrationForm(self.request.POST or None)
context["admin_registration_form"] = AdminRegistrationForm(self.request.POST or None)
del context["volunteer_registration_form"].fields["email_confirmed"]
del context["admin_registration_form"].fields["email_confirmed"]
if not self.request.user.registration.is_admin:
context["form"].fields["type"].widget.attrs['readonly'] = True
del context["admin_registration_form"]
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
if not self.request.user.registration.is_admin:
del form.fields["admin"]
return form
@transaction.atomic
def form_valid(self, form):
role = form.cleaned_data["type"]
if role == "admin":
registration_form = AdminRegistrationForm(self.request.POST)
else:
registration_form = VolunteerRegistrationForm(self.request.POST)
registration_form = VolunteerRegistrationForm(self.request.POST)
del registration_form.fields["email_confirmed"]
if not registration_form.is_valid():
@ -347,6 +344,27 @@ class UserUploadHealthSheetView(UserRegistrationMixin, UpdateView):
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
class UserUploadVaccineSheetView(UserRegistrationMixin, UpdateView):
"""
A participant can send its vaccine sheet.
"""
model = StudentRegistration
form_class = VaccineSheetForm
template_name = "registration/upload_vaccine_sheet.html"
extra_context = dict(title=_("Upload vaccine sheet"))
@transaction.atomic
def form_valid(self, form):
old_instance = StudentRegistration.objects.get(pk=self.object.pk)
if old_instance.vaccine_sheet:
old_instance.vaccine_sheet.delete()
old_instance.save()
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("registration:user_detail", args=(self.object.user.pk,))
class UserUploadParentalAuthorizationView(UserRegistrationMixin, UpdateView):
"""
A participant can send its parental authorization.
@ -487,6 +505,29 @@ class HealthSheetView(LoginRequiredMixin, View):
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
class VaccineSheetView(LoginRequiredMixin, View):
"""
Display the sent health sheet.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/vaccine/{filename}"
if not os.path.exists(path):
raise Http404
student = StudentRegistration.objects.get(vaccine_sheet__endswith=filename)
user = request.user
if not (student.user == user or user.registration.is_admin or user.registration.is_volunteer and student.team
and student.team.participation.tournament in user.registration.organized_tournaments.all()):
raise PermissionDenied
# Guess mime type of the file
mime = Magic(mime=True)
mime_type = mime.from_file(path)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
# Replace file name
true_file_name = _("Vaccine sheet of {student}.{ext}").format(student=str(student), ext=ext)
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
class ParentalAuthorizationView(LoginRequiredMixin, View):
"""
Display the sent parental authorization.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-19 19:48+0100\n"
"POT-Creation-Date: 2023-02-20 00:37+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -100,83 +100,84 @@ msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
#: apps/participation/admin.py:19 apps/participation/models.py:318
#: apps/participation/tables.py:44 apps/registration/models.py:370
#: apps/participation/tables.py:44 apps/registration/models.py:364
msgid "valid"
msgstr "valide"
#: apps/participation/forms.py:29
#: apps/participation/forms.py:28
msgid "This name is already used."
msgstr "Ce nom est déjà utilisé."
#: apps/participation/forms.py:36 apps/participation/models.py:40
#: apps/participation/forms.py:35 apps/participation/models.py:40
msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules."
#: apps/participation/forms.py:39
#: apps/participation/forms.py:38
msgid "This trigram is already used."
msgstr "Ce trigramme est déjà utilisé."
#: apps/participation/forms.py:54
#: apps/participation/forms.py:53
msgid "No team was found with this access code."
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
#: apps/participation/forms.py:83 apps/participation/forms.py:281
#: apps/registration/forms.py:121 apps/registration/forms.py:143
#: apps/registration/forms.py:165 apps/registration/forms.py:219
#: apps/participation/forms.py:82 apps/participation/forms.py:280
#: apps/registration/forms.py:113 apps/registration/forms.py:135
#: apps/registration/forms.py:157 apps/registration/forms.py:179
#: apps/registration/forms.py:224
msgid "The uploaded file size must be under 2 Mo."
msgstr "Le fichier envoyé doit peser moins de 2 Mo."
#: apps/participation/forms.py:85 apps/registration/forms.py:123
#: apps/registration/forms.py:145 apps/registration/forms.py:167
#: apps/registration/forms.py:221
#: apps/participation/forms.py:84 apps/registration/forms.py:115
#: apps/registration/forms.py:137 apps/registration/forms.py:159
#: apps/registration/forms.py:181 apps/registration/forms.py:226
msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG."
#: apps/participation/forms.py:103
#: apps/participation/forms.py:102
msgid "I engage myself to participate to the whole TFJM²."
msgstr "Je m'engage à participer à l'intégralité du TFJM²."
#: apps/participation/forms.py:118
#: apps/participation/forms.py:117
msgid "Message to address to the team:"
msgstr "Message à adresser à l'équipe :"
#: apps/participation/forms.py:154
#: apps/participation/forms.py:153
msgid "The uploaded file size must be under 5 Mo."
msgstr "Le fichier envoyé doit peser moins de 5 Mo."
#: apps/participation/forms.py:156 apps/participation/forms.py:283
#: apps/participation/forms.py:155 apps/participation/forms.py:282
msgid "The uploaded file must be a PDF file."
msgstr "Le fichier envoyé doit être au format PDF."
#: apps/participation/forms.py:160
#: apps/participation/forms.py:159
msgid "The PDF file must not have more than 30 pages."
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
#: apps/participation/forms.py:197
#: apps/participation/forms.py:196
msgid "CSV file:"
msgstr "Tableur au format CSV :"
#: apps/participation/forms.py:214
#: apps/participation/forms.py:213
msgid ""
"This file contains non-UTF-8 content. Please send your sheet as a CSV file."
msgstr ""
"Ce fichier contient des éléments non-UTF-8. Merci d'envoyer votre tableur au "
"format CSV."
#: apps/participation/forms.py:239
#: apps/participation/forms.py:238
msgid "The following note is higher of the maximum expected value:"
msgstr "La note suivante est supérieure au maximum attendu :"
#: apps/participation/forms.py:247
#: apps/participation/forms.py:246
msgid "The following user was not found:"
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
#: apps/participation/forms.py:264
#: apps/participation/forms.py:263
msgid "The defender, the opponent and the reporter must be different."
msgstr ""
"Læ défenseur⋅se, l'opposant⋅e et læ rapporteur⋅e doivent être différent⋅es."
#: apps/participation/forms.py:268
#: apps/participation/forms.py:267
msgid "This defender did not work on this problem."
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
@ -211,7 +212,7 @@ msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})"
#: apps/participation/models.py:125 apps/participation/models.py:303
#: apps/registration/models.py:123
#: apps/registration/models.py:127
msgid "team"
msgstr "équipe"
@ -597,14 +598,14 @@ msgstr "Rejoindre"
#: apps/participation/templates/participation/pool_detail.html:55
#: apps/participation/templates/participation/pool_detail.html:74
#: apps/participation/templates/participation/pool_detail.html:79
#: apps/participation/templates/participation/team_detail.html:113
#: apps/participation/templates/participation/team_detail.html:177
#: apps/participation/templates/participation/team_detail.html:126
#: apps/participation/templates/participation/team_detail.html:190
#: apps/participation/templates/participation/tournament_form.html:12
#: apps/participation/templates/participation/update_team.html:12
#: apps/registration/templates/registration/payment_form.html:49
#: apps/registration/templates/registration/update_user.html:16
#: apps/registration/templates/registration/user_detail.html:155
#: apps/registration/templates/registration/user_detail.html:187
#: apps/registration/templates/registration/user_detail.html:165
#: apps/registration/templates/registration/user_detail.html:202
msgid "Update"
msgstr "Modifier"
@ -661,7 +662,7 @@ msgstr "Envoyer une solution"
#: apps/participation/templates/participation/participation_detail.html:59
#: apps/participation/templates/participation/passage_detail.html:114
#: apps/participation/templates/participation/pool_detail.html:84
#: apps/participation/templates/participation/team_detail.html:172
#: apps/participation/templates/participation/team_detail.html:185
#: apps/participation/templates/participation/upload_motivation_letter.html:13
#: apps/participation/templates/participation/upload_notes.html:12
#: apps/participation/templates/participation/upload_solution.html:11
@ -669,10 +670,12 @@ msgstr "Envoyer une solution"
#: apps/registration/templates/registration/upload_health_sheet.html:17
#: apps/registration/templates/registration/upload_parental_authorization.html:17
#: apps/registration/templates/registration/upload_photo_authorization.html:18
#: apps/registration/templates/registration/user_detail.html:165
#: apps/registration/templates/registration/user_detail.html:170
#: apps/registration/templates/registration/upload_vaccine_sheet.html:13
#: apps/registration/templates/registration/user_detail.html:175
#: apps/registration/templates/registration/user_detail.html:180
#: apps/registration/templates/registration/user_detail.html:185
#: apps/registration/templates/registration/user_detail.html:190
#: apps/registration/templates/registration/user_detail.html:195
msgid "Upload"
msgstr "Téléverser"
@ -852,7 +855,8 @@ msgstr "Autorisations de droit à l'image :"
#: apps/participation/templates/participation/team_detail.html:58
#: apps/participation/templates/participation/team_detail.html:71
#: apps/participation/templates/participation/team_detail.html:84
#: apps/participation/templates/participation/team_detail.html:96
#: apps/participation/templates/participation/team_detail.html:97
#: apps/participation/templates/participation/team_detail.html:109
msgid "Not uploaded yet"
msgstr "Pas encore envoyée"
@ -861,44 +865,50 @@ msgid "Health sheets:"
msgstr "Fiches sanitaires :"
#: apps/participation/templates/participation/team_detail.html:77
msgid "Vaccine sheets:"
msgstr "Carnets de vaccination :"
#: apps/participation/templates/participation/team_detail.html:90
msgid "Parental authorizations:"
msgstr "Autorisations parentales :"
#: apps/participation/templates/participation/team_detail.html:91
#: apps/participation/templates/participation/team_detail.html:104
msgid "Motivation letter:"
msgstr "Lettre de motivation :"
#: apps/participation/templates/participation/team_detail.html:94
#: apps/participation/templates/participation/team_detail.html:107
#: apps/registration/templates/registration/upload_health_sheet.html:12
#: apps/registration/templates/registration/upload_parental_authorization.html:12
#: apps/registration/templates/registration/user_detail.html:62
#: apps/registration/templates/registration/user_detail.html:75
#: apps/registration/templates/registration/user_detail.html:85
#: apps/registration/templates/registration/user_detail.html:95
msgid "Download"
msgstr "Télécharger"
#: apps/participation/templates/participation/team_detail.html:99
#: apps/participation/templates/participation/team_detail.html:112
#: apps/registration/templates/registration/user_detail.html:65
#: apps/registration/templates/registration/user_detail.html:78
#: apps/registration/templates/registration/user_detail.html:88
#: apps/registration/templates/registration/user_detail.html:98
msgid "Replace"
msgstr "Remplacer"
#: apps/participation/templates/participation/team_detail.html:107
#: apps/participation/templates/participation/team_detail.html:120
msgid "Download all submitted authorizations"
msgstr "Télécharger toutes les autorisations soumises"
#: apps/participation/templates/participation/team_detail.html:115
#: apps/participation/templates/participation/team_detail.html:182
#: apps/participation/templates/participation/team_detail.html:128
#: apps/participation/templates/participation/team_detail.html:195
#: apps/participation/templates/participation/team_leave.html:11
msgid "Leave"
msgstr "Quitter"
#: apps/participation/templates/participation/team_detail.html:125
#: apps/participation/templates/participation/team_detail.html:138
msgid "Access to team participation"
msgstr "Accéder à la participation de l'équipe"
#: apps/participation/templates/participation/team_detail.html:132
#: apps/participation/templates/participation/team_detail.html:145
msgid ""
"Your team has at least 4 members and a coach and all authorizations were "
"given: the team can be validated."
@ -906,11 +916,11 @@ msgstr ""
"Votre équipe contient au moins 4 personnes et un⋅e encadrant⋅e et toutes les "
"autorisations ont été données : l'équipe peut être validée."
#: apps/participation/templates/participation/team_detail.html:137
#: apps/participation/templates/participation/team_detail.html:150
msgid "Submit my team to validation"
msgstr "Soumettre mon équipe à validation"
#: apps/participation/templates/participation/team_detail.html:143
#: apps/participation/templates/participation/team_detail.html:156
msgid ""
"Your team must be composed of 4 members and a coach and each member must "
"upload their authorizations and confirm its email address."
@ -918,15 +928,15 @@ msgstr ""
"Votre équipe doit être composée d'au moins 4 membres et un⋅e encadrant⋅e et "
"chaque membre doit envoyer ses autorisations et confirmé son adresse e-mail."
#: apps/participation/templates/participation/team_detail.html:148
#: apps/participation/templates/participation/team_detail.html:161
msgid "This team didn't ask for validation yet."
msgstr "L'équipe n'a pas encore demandé à être validée."
#: apps/participation/templates/participation/team_detail.html:154
#: apps/participation/templates/participation/team_detail.html:167
msgid "Your validation is pending."
msgstr "Votre validation est en attente."
#: apps/participation/templates/participation/team_detail.html:158
#: apps/participation/templates/participation/team_detail.html:171
msgid ""
"The team requested to be validated. You may now control the authorizations "
"and confirm that they can participate."
@ -934,25 +944,25 @@ msgstr ""
"L'équipe a demandé à être validée. Vous pouvez désormais contrôler les "
"différentes autorisations et confirmer qu'elle peut participer."
#: apps/participation/templates/participation/team_detail.html:164
#: apps/participation/templates/participation/team_detail.html:177
msgid "Validate"
msgstr "Valider"
#: apps/participation/templates/participation/team_detail.html:165
#: apps/participation/templates/participation/team_detail.html:178
msgid "Invalidate"
msgstr "Invalider"
#: apps/participation/templates/participation/team_detail.html:171
#: apps/participation/views.py:332
#: apps/participation/templates/participation/team_detail.html:184
#: apps/participation/views.py:333
msgid "Upload motivation letter"
msgstr "Envoyer la lettre de motivation"
#: apps/participation/templates/participation/team_detail.html:176
#: apps/participation/templates/participation/team_detail.html:189
msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/participation/templates/participation/team_detail.html:181
#: apps/participation/views.py:435
#: apps/participation/templates/participation/team_detail.html:194
#: apps/participation/views.py:442
msgid "Leave team"
msgstr "Quitter l'équipe"
@ -1082,12 +1092,12 @@ msgstr "Vous êtes déjà dans une équipe."
msgid "Join team"
msgstr "Rejoindre une équipe"
#: apps/participation/views.py:151 apps/participation/views.py:441
#: apps/participation/views.py:475
#: apps/participation/views.py:151 apps/participation/views.py:448
#: apps/participation/views.py:482
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
#: apps/participation/views.py:152 apps/participation/views.py:476
#: apps/participation/views.py:152 apps/participation/views.py:483
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
@ -1096,17 +1106,17 @@ msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
msgid "Detail of team {trigram}"
msgstr "Détails de l'équipe {trigram}"
#: apps/participation/views.py:214
#: apps/participation/views.py:215
msgid "You don't participate, so you can't request the validation of the team."
msgstr ""
"Vous ne participez pas, vous ne pouvez pas demander la validation de "
"l'équipe."
#: apps/participation/views.py:217
#: apps/participation/views.py:218
msgid "The validation of the team is already done or pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
#: apps/participation/views.py:220
#: apps/participation/views.py:221
msgid ""
"The team can't be validated: missing email address confirmations, "
"authorizations, people, motivation letter or the tournament is not set."
@ -1115,78 +1125,83 @@ msgstr ""
"d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre "
"de motivation, soit le tournoi n'a pas été choisi."
#: apps/participation/views.py:242
#: apps/participation/views.py:243
msgid "You are not an organizer of the tournament."
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi."
#: apps/participation/views.py:245
#: apps/participation/views.py:246
msgid "This team has no pending validation."
msgstr "L'équipe n'a pas de validation en attente."
#: apps/participation/views.py:275
#: apps/participation/views.py:276
msgid "You must specify if you validate the registration or not."
msgstr "Vous devez spécifier si vous validez l'inscription ou non."
#: apps/participation/views.py:310
#: apps/participation/views.py:311
#, python-brace-format
msgid "Update team {trigram}"
msgstr "Mise à jour de l'équipe {trigram}"
#: apps/participation/views.py:371 apps/participation/views.py:421
#: apps/participation/views.py:372 apps/participation/views.py:428
#, python-brace-format
msgid "Motivation letter of {team}.{ext}"
msgstr "Lettre de motivation de {team}.{ext}"
#: apps/participation/views.py:402
#: apps/participation/views.py:403
#, python-brace-format
msgid "Photo authorization of {participant}.{ext}"
msgstr "Autorisation de droit à l'image de {participant}.{ext}"
#: apps/participation/views.py:408
#: apps/participation/views.py:409
#, python-brace-format
msgid "Parental authorization of {participant}.{ext}"
msgstr "Autorisation parentale de {participant}.{ext}"
#: apps/participation/views.py:415
#: apps/participation/views.py:416
#, python-brace-format
msgid "Health sheet of {participant}.{ext}"
msgstr "Fiche sanitaire de {participant}.{ext}"
#: apps/participation/views.py:425
#: apps/participation/views.py:422
#, python-brace-format
msgid "Vaccine sheet of {participant}.{ext}"
msgstr "Carnet de vaccination de {participant}.{ext}"
#: apps/participation/views.py:432
#, python-brace-format
msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
#: apps/participation/views.py:443
#: apps/participation/views.py:450
msgid "The team is already validated or the validation is pending."
msgstr "La validation de l'équipe est déjà faite ou en cours."
#: apps/participation/views.py:490
#: apps/participation/views.py:497
msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée."
#: apps/participation/views.py:504
#: apps/participation/views.py:511
#, python-brace-format
msgid "Participation of team {trigram}"
msgstr "Participation de l'équipe {trigram}"
#: apps/participation/views.py:630
#: apps/participation/views.py:637
msgid "You can't upload a solution after the deadline."
msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
#: apps/participation/views.py:733
#: apps/participation/views.py:740
msgid "The following user is not registered as a jury:"
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
#: apps/participation/views.py:741
#: apps/participation/views.py:748
msgid "Notes were successfully uploaded."
msgstr "Les notes ont bien été envoyées."
#: apps/participation/views.py:853
#: apps/participation/views.py:860
msgid "You can't upload a synthesis after the deadline."
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
#: apps/registration/forms.py:22 apps/registration/forms.py:54
#: apps/registration/forms.py:22
msgid "role"
msgstr "rôle"
@ -1194,27 +1209,19 @@ msgstr "rôle"
msgid "participant"
msgstr "participant⋅e"
#: apps/registration/forms.py:25 apps/registration/models.py:270
#: apps/registration/forms.py:25 apps/registration/models.py:281
msgid "coach"
msgstr "encadrant⋅e"
#: apps/registration/forms.py:35 apps/registration/forms.py:68
#: apps/registration/forms.py:35 apps/registration/forms.py:60
msgid "This email address is already used."
msgstr "Cette adresse e-mail est déjà utilisée."
#: apps/registration/forms.py:56 apps/registration/models.py:296
msgid "volunteer"
msgstr "bénévole"
#: apps/registration/forms.py:57 apps/registration/models.py:315
msgid "admin"
msgstr "admin"
#: apps/registration/forms.py:213
#: apps/registration/forms.py:218
msgid "Pending"
msgstr "En attente"
#: apps/registration/forms.py:229
#: apps/registration/forms.py:234
msgid "You must upload your scholarship attestation."
msgstr "Vous devez envoyer votre attestation de bourse."
@ -1231,7 +1238,7 @@ msgstr "email confirmé"
msgid "Activate your TFJM² account"
msgstr "Activez votre compte du TFJM²"
#: apps/registration/models.py:99 apps/registration/models.py:336
#: apps/registration/models.py:99 apps/registration/models.py:330
msgid "registration"
msgstr "inscription"
@ -1239,43 +1246,43 @@ msgstr "inscription"
msgid "registrations"
msgstr "inscriptions"
#: apps/registration/models.py:128
#: apps/registration/models.py:132
msgid "gender"
msgstr "genre"
#: apps/registration/models.py:130
#: apps/registration/models.py:134
msgid "Female"
msgstr "Femme"
#: apps/registration/models.py:131
#: apps/registration/models.py:135
msgid "Male"
msgstr "Homme"
#: apps/registration/models.py:132
#: apps/registration/models.py:136
msgid "Other"
msgstr "Autre"
#: apps/registration/models.py:139
#: apps/registration/models.py:143
msgid "address"
msgstr "adresse"
#: apps/registration/models.py:143
#: apps/registration/models.py:147
msgid "zip code"
msgstr "code postal"
#: apps/registration/models.py:149
#: apps/registration/models.py:153
msgid "city"
msgstr "ville"
#: apps/registration/models.py:153
#: apps/registration/models.py:157
msgid "phone number"
msgstr "numéro de téléphone"
#: apps/registration/models.py:158
#: apps/registration/models.py:162
msgid "health issues"
msgstr "problèmes de santé"
#: apps/registration/models.py:160
#: apps/registration/models.py:164
msgid ""
"You can indicate here your allergies or anything that is important to know "
"for organizers"
@ -1283,140 +1290,152 @@ msgstr ""
"Vous pouvez indiquer ici vos allergies ou n'importe quoi qui peut être bon à "
"savoir pour les organisateur⋅rices"
#: apps/registration/models.py:164
#: apps/registration/models.py:168
msgid "photo authorization"
msgstr "autorisation de droit à l'image"
#: apps/registration/models.py:197
#: apps/registration/models.py:201
msgid "birth date"
msgstr "date de naissance"
#: apps/registration/models.py:203
#: apps/registration/models.py:207
msgid "12th grade"
msgstr "Terminale"
#: apps/registration/models.py:204
#: apps/registration/models.py:208
msgid "11th grade"
msgstr "Première"
#: apps/registration/models.py:205
#: apps/registration/models.py:209
msgid "10th grade or lower"
msgstr "Seconde ou inférieur"
#: apps/registration/models.py:207
#: apps/registration/models.py:211
msgid "student class"
msgstr "classe"
#: apps/registration/models.py:212
#: apps/registration/models.py:216
msgid "school"
msgstr "école"
#: apps/registration/models.py:217
#: apps/registration/models.py:221
msgid "responsible name"
msgstr "nom de læ responsable légal⋅e"
#: apps/registration/models.py:222
#: apps/registration/models.py:226
msgid "responsible phone number"
msgstr "numéro de téléphone de læ responsable légal⋅e"
#: apps/registration/models.py:227
#: apps/registration/models.py:231
msgid "responsible email address"
msgstr "adresse e-mail de læ responsable légal⋅e"
#: apps/registration/models.py:232
#: apps/registration/models.py:236
msgid "parental authorization"
msgstr "autorisation parentale"
#: apps/registration/models.py:239
#: apps/registration/models.py:243
msgid "health sheet"
msgstr "fiche sanitaire"
#: apps/registration/models.py:247
#: apps/registration/models.py:250
msgid "vaccine sheet"
msgstr "carnet de vaccination"
#: apps/registration/models.py:258
msgid "student"
msgstr "étudiant⋅e"
#: apps/registration/models.py:255
#: apps/registration/models.py:266
msgid "student registration"
msgstr "inscription d'élève"
#: apps/registration/models.py:256
#: apps/registration/models.py:267
msgid "student registrations"
msgstr "inscriptions d'élève"
#: apps/registration/models.py:265 apps/registration/models.py:287
#: apps/registration/models.py:276 apps/registration/models.py:298
msgid "professional activity"
msgstr "activité professionnelle"
#: apps/registration/models.py:278
#: apps/registration/models.py:289
msgid "coach registration"
msgstr "inscription d'encadrant⋅e"
#: apps/registration/models.py:279
#: apps/registration/models.py:290
msgid "coach registrations"
msgstr "inscriptions d'encadrant⋅es"
#: apps/registration/models.py:310
msgid "role of the administrator"
msgstr "rôle de l'administrateur⋅rice"
#: apps/registration/models.py:302
msgid "administrator"
msgstr "administrateur⋅rice"
#: apps/registration/models.py:323
msgid "admin registration"
msgstr "inscription d'administrateur⋅rice"
#: apps/registration/models.py:303
msgid ""
"An administrator has all rights. Please don't give this right to all juries "
"and volunteers."
msgstr ""
"Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit "
"à toustes les juré⋅es et bénévoles."
#: apps/registration/models.py:324
msgid "admin registrations"
msgstr "inscriptions d'administrateur⋅rices"
#: apps/registration/models.py:313
msgid "admin"
msgstr "admin"
#: apps/registration/models.py:340
#: apps/registration/models.py:313
msgid "volunteer"
msgstr "bénévole"
#: apps/registration/models.py:334
msgid "type"
msgstr "type"
#: apps/registration/models.py:343
#: apps/registration/models.py:337
msgid "No payment"
msgstr "Pas de paiement"
#: apps/registration/models.py:345
#: apps/registration/models.py:339
msgid "Scholarship"
msgstr "Notification de bourse"
#: apps/registration/models.py:346
#: apps/registration/models.py:340
msgid "Bank transfer"
msgstr "Virement bancaire"
#: apps/registration/models.py:347
#: apps/registration/models.py:341
msgid "Other (please indicate)"
msgstr "Autre (veuillez spécifier)"
#: apps/registration/models.py:348
#: apps/registration/models.py:342
msgid "The tournament is free"
msgstr "Le tournoi est gratuit"
#: apps/registration/models.py:355
#: apps/registration/models.py:349
msgid "scholarship file"
msgstr "Notification de bourse"
#: apps/registration/models.py:356
#: apps/registration/models.py:350
msgid "only if you have a scholarship."
msgstr "Nécessaire seulement si vous déclarez être boursier."
#: apps/registration/models.py:363
#: apps/registration/models.py:357
msgid "additional information"
msgstr "informations additionnelles"
#: apps/registration/models.py:364
#: apps/registration/models.py:358
msgid "To help us to find your payment."
msgstr "Pour nous aider à retrouver votre paiement, si nécessaire."
#: apps/registration/models.py:379
#: apps/registration/models.py:373
#, python-brace-format
msgid "Payment of {registration}"
msgstr "Paiement de {registration}"
#: apps/registration/models.py:382
#: apps/registration/models.py:376
msgid "payment"
msgstr "paiement"
#: apps/registration/models.py:383
#: apps/registration/models.py:377
msgid "payments"
msgstr "paiements"
@ -1640,6 +1659,7 @@ msgstr "Inscription"
#: apps/registration/templates/registration/upload_health_sheet.html:6
#: apps/registration/templates/registration/upload_parental_authorization.html:6
#: apps/registration/templates/registration/upload_photo_authorization.html:6
#: apps/registration/templates/registration/upload_vaccine_sheet.html:6
msgid "Back to the user detail"
msgstr "Retour aux détails de l'utilisateur⋅rice"
@ -1716,133 +1736,147 @@ msgid "Health sheet:"
msgstr "Fiche sanitaire :"
#: apps/registration/templates/registration/user_detail.html:82
msgid "Vaccine sheet:"
msgstr "Carnet de vaccination :"
#: apps/registration/templates/registration/user_detail.html:92
msgid "Parental authorization:"
msgstr "Autorisation parentale :"
#: apps/registration/templates/registration/user_detail.html:93
#: apps/registration/templates/registration/user_detail.html:103
msgid "Student class:"
msgstr "Classe :"
#: apps/registration/templates/registration/user_detail.html:96
#: apps/registration/templates/registration/user_detail.html:106
msgid "School:"
msgstr "École :"
#: apps/registration/templates/registration/user_detail.html:99
#: apps/registration/templates/registration/user_detail.html:109
msgid "Responsible name:"
msgstr "Nom de læ responsable légal⋅e :"
#: apps/registration/templates/registration/user_detail.html:102
#: apps/registration/templates/registration/user_detail.html:112
msgid "Responsible phone number:"
msgstr "Numéro de téléphone de læ responsable légal⋅e :"
#: apps/registration/templates/registration/user_detail.html:105
#: apps/registration/templates/registration/user_detail.html:115
msgid "Responsible email address:"
msgstr "Adresse e-mail de læ responsable légal⋅e :"
#: apps/registration/templates/registration/user_detail.html:110
msgid "Role:"
msgstr "Rôle :"
#: apps/registration/templates/registration/user_detail.html:120
msgid "Admin:"
msgstr "Administrateur⋅rice :"
#: apps/registration/templates/registration/user_detail.html:113
#: apps/registration/templates/registration/user_detail.html:123
msgid "Profesional activity:"
msgstr "Activité professionnelle :"
#: apps/registration/templates/registration/user_detail.html:117
#: apps/registration/templates/registration/user_detail.html:127
msgid "Grant Animath to contact me in the future about other actions:"
msgstr "Autorise Animath à recontacter à propos d'autres actions :"
#: apps/registration/templates/registration/user_detail.html:125
#: apps/registration/templates/registration/user_detail.html:135
msgid "Payment information:"
msgstr "Informations de paiement :"
#: apps/registration/templates/registration/user_detail.html:127
#: apps/registration/templates/registration/user_detail.html:137
msgid "yes,no,pending"
msgstr "oui,non,en attente"
#: apps/registration/templates/registration/user_detail.html:131
#: apps/registration/templates/registration/user_detail.html:134
#: apps/registration/templates/registration/user_detail.html:141
#: apps/registration/templates/registration/user_detail.html:144
msgid "valid:"
msgstr "valide :"
#: apps/registration/templates/registration/user_detail.html:138
#: apps/registration/templates/registration/user_detail.html:186
#: apps/registration/templates/registration/user_detail.html:148
#: apps/registration/templates/registration/user_detail.html:201
msgid "Update payment"
msgstr "Modifier le paiement"
#: apps/registration/templates/registration/user_detail.html:144
#: apps/registration/templates/registration/user_detail.html:154
msgid "Download scholarship attestation"
msgstr "Télécharger l'attestation de bourse"
#: apps/registration/templates/registration/user_detail.html:157
#: apps/registration/templates/registration/user_detail.html:167
msgid "Impersonate"
msgstr "Impersonifier"
#: apps/registration/templates/registration/user_detail.html:164
#: apps/registration/views.py:315
#: apps/registration/templates/registration/user_detail.html:174
#: apps/registration/views.py:312
msgid "Upload photo authorization"
msgstr "Téléverser l'autorisation de droit à l'image"
#: apps/registration/templates/registration/user_detail.html:169
#: apps/registration/views.py:336
#: apps/registration/templates/registration/user_detail.html:179
#: apps/registration/views.py:333
msgid "Upload health sheet"
msgstr "Téléverser la fiche sanitaire"
#: apps/registration/templates/registration/user_detail.html:174
#: apps/registration/templates/registration/user_detail.html:179
#: apps/registration/views.py:357
#: apps/registration/templates/registration/user_detail.html:184
#: apps/registration/views.py:354
msgid "Upload vaccine sheet"
msgstr "Téléverser le carnet de vaccination"
#: apps/registration/templates/registration/user_detail.html:189
#: apps/registration/templates/registration/user_detail.html:194
#: apps/registration/views.py:375
msgid "Upload parental authorization"
msgstr "Téléverser l'autorisation parentale"
#: apps/registration/views.py:127
#: apps/registration/views.py:124
msgid "New TFJM² organizer account"
msgstr "Nouveau compte organisateur⋅rice pour le TFJM²"
#: apps/registration/views.py:153
#: apps/registration/views.py:150
msgid "Email validation"
msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:155
#: apps/registration/views.py:152
msgid "Validate email"
msgstr "Valider l'adresse mail"
#: apps/registration/views.py:194
#: apps/registration/views.py:191
msgid "Email validation unsuccessful"
msgstr "Échec de la validation de l'adresse mail"
#: apps/registration/views.py:205
#: apps/registration/views.py:202
msgid "Email validation email sent"
msgstr "Mail de confirmation de l'adresse mail envoyé"
#: apps/registration/views.py:213
#: apps/registration/views.py:210
msgid "Resend email validation link"
msgstr "Renvoyé le lien de validation de l'adresse mail"
#: apps/registration/views.py:255
#: apps/registration/views.py:252
#, python-brace-format
msgid "Detail of user {user}"
msgstr "Détails de l'utilisateur⋅rice {user}"
#: apps/registration/views.py:279
#: apps/registration/views.py:276
#, python-brace-format
msgid "Update user {user}"
msgstr "Mise à jour de l'utilisateur⋅rice {user}"
#: apps/registration/views.py:463
#: apps/registration/views.py:481
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
#: apps/registration/views.py:486
#: apps/registration/views.py:504
#, python-brace-format
msgid "Health sheet of {student}.{ext}"
msgstr "Fiche sanitaire de {student}.{ext}"
#: apps/registration/views.py:509
#: apps/registration/views.py:527
#, python-brace-format
msgid "Vaccine sheet of {student}.{ext}"
msgstr "Carnet de vaccination de {student}.{ext}"
#: apps/registration/views.py:550
#, python-brace-format
msgid "Parental authorization of {student}.{ext}"
msgstr "Autorisation parentale de {student}.{ext}"
#: apps/registration/views.py:531
#: apps/registration/views.py:572
#, python-brace-format
msgid "Scholarship attestation of {user}.{ext}"
msgstr "Notification de bourse de {user}.{ext}"
@ -2011,3 +2045,15 @@ msgstr "Résultats"
#: tfjm/templates/search/search.html:25
msgid "No results found."
msgstr "Aucun résultat."
#~ msgid "Role:"
#~ msgstr "Rôle :"
#~ msgid "role of the administrator"
#~ msgstr "rôle de l'administrateur⋅rice"
#~ msgid "admin registration"
#~ msgstr "inscription d'administrateur⋅rice"
#~ msgid "admin registrations"
#~ msgstr "inscriptions d'administrateur⋅rices"

View File

@ -23,7 +23,7 @@ from django.views.defaults import bad_request, page_not_found, permission_denied
from django.views.generic import TemplateView
from participation.views import MotivationLetterView
from registration.views import HealthSheetView, ParentalAuthorizationView, PhotoAuthorizationView, \
ScholarshipView, SolutionView, SynthesisView
ScholarshipView, SolutionView, SynthesisView, VaccineSheetView
from .views import AdminSearchView
@ -44,6 +44,8 @@ urlpatterns = [
name='photo_authorization'),
path('media/authorization/health/<str:filename>/', HealthSheetView.as_view(),
name='health_sheet'),
path('media/authorization/vaccine/<str:filename>/', VaccineSheetView.as_view(),
name='vaccine_sheet'),
path('media/authorization/parental/<str:filename>/', ParentalAuthorizationView.as_view(),
name='parental_authorization'),
path('media/authorization/scholarship/<str:filename>/', ScholarshipView.as_view(),