mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-29 22:31:14 +02:00
Add vaccine sheet field, closes #18
This commit is contained in:
@ -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 %}
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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")
|
||||
|
@ -146,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.
|
||||
|
@ -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'),
|
||||
),
|
||||
]
|
@ -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")
|
||||
|
@ -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 %}
|
@ -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 %}
|
||||
@ -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 %}
|
||||
|
@ -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"),
|
||||
|
@ -29,7 +29,7 @@ from tfjm.views import UserMixin, UserRegistrationMixin, VolunteerMixin
|
||||
|
||||
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
|
||||
|
||||
@ -344,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.
|
||||
@ -484,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.
|
||||
|
Reference in New Issue
Block a user