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

Add ZIP archive for tournament authorizations

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello
2024-03-26 23:55:29 +01:00
parent a865361117
commit 4583cf46b1
5 changed files with 237 additions and 148 deletions

View File

@ -116,7 +116,7 @@
{% if user.registration.is_volunteer %}
{% if user.registration in self.team.participation.tournament.organizers or user.registration.is_admin %}
<div class="text-center">
<a class="btn btn-info" href="{% url "participation:team_authorizations" pk=team.pk %}">
<a class="btn btn-info" href="{% url "participation:team_authorizations" team_id=team.id %}">
<i class="fas fa-file-archive"></i> {% trans "Download all submitted authorizations" %}
</a>
</div>

View File

@ -62,7 +62,6 @@
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
<div class="card-footer text-center">
<a href="{% url "participation:tournament_update" pk=tournament.pk %}"><button class="btn btn-secondary">{% trans "Edit tournament" %}</button></a>
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}"><button class="btn btn-success">{% trans "Export as CSV" %}</button></a>
</div>
{% endif %}
</div>
@ -91,12 +90,6 @@
</div>
{% endif %}
{% if user.registration.is_admin %}
<div class="d-grid">
<button class="btn gap-0 btn-success" data-bs-toggle="modal" data-bs-target="#addPoolModal">{% trans "Add new pool" %}</button>
</div>
{% endif %}
{% if notes %}
<hr>
@ -134,20 +127,81 @@
</div>
{% endif %}
{% if user.registration.is_admin %}
{% trans "Add pool" as modal_title %}
{% trans "Add" as modal_button %}
{% url "participation:pool_create" as modal_action %}
{% include "base_modal.html" with modal_id="addPool" %}
{% endif %}
{% endblock %}
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
<hr>
<h3>{% trans "Files available for download" %}</h3>
<div class="alert alert-warning fade show files-to-download-collapse" id="files-to-download-popup">
<h4>IMPORTANT</h4>
<p>
Les fichiers accessibles ci-dessous peuvent contenir des informations personnelles.
Par conformité avec le droit européen et par respect de la confidentialité des données
des participant⋅es, vous ne devez utiliser ces données que dans un cadre strictement
nécessaire en lien avec l'organisation du tournoi.
</p>
<p>
De plus, il est de votre responsabilité de supprimer ces fichiers une fois que vous
n'en avez plus besoin, notamment à la fin du tournoi.
</p>
<p class="text-center">
<button class="btn btn-warning" data-bs-toggle="collapse" href=".files-to-download-collapse"
role="button" aria-expanded="false" aria-controls="files-to-download files-to-download-popup">
Je m'engage à ne pas divulguer les données des participant⋅es
et de les supprimer à l'issue du tournoi
</button>
</p>
</div>
<div class="card bg-body shadow fade collapse files-to-download-collapse" id="files-to-download">
<div class="card-body">
<ul>
<li>
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}">
Tableur de données des participant⋅es des équipes validées
</a>
</li>
<li>
<a href="{% url "participation:tournament_csv" pk=tournament.pk %}?all">
Tableur de données des participant⋅es de toutes les équipes
</a>
</li>
<li>
<a href="{% url "participation:tournament_authorizations" tournament_id=tournament.id %}">
Archive de toutes les autorisations triées par équipe et par personne
</a>
</li>
<li>
<a>
Archive de toutes les solutions envoyées triées par équipe
</a>
</li>
<li>
<a>
Archive de toutes les solutions envoyées triées par problème
</a>
</li>
<li>
<a>
Archive de toutes les notes de synthèse triées par poule et par passage
</a>
</li>
<li>
<a>
Archive de tous les barèmes de notes à imprimer triés par poule
</a>
</li>
<li>
<a>
Archive de tous les tableurs de notes à saisir triés par poule
</a>
</li>
</ul>
</div>
</div>
{% endif %}
{% block extrajavascript %}
<script>
document.addEventListener('DOMContentLoaded', () => {
{% if user.registration.is_admin %}
initModal("addPool", "{% url "participation:pool_create" %}")
{% endif %}
});
</script>
{% endblock %}

View File

@ -25,7 +25,7 @@ urlpatterns = [
path("team/<int:pk>/update/", TeamUpdateView.as_view(), name="update_team"),
path("team/<int:pk>/upload-motivation-letter/", TeamUploadMotivationLetterView.as_view(),
name="upload_team_motivation_letter"),
path("team/<int:pk>/authorizations/", TeamAuthorizationsView.as_view(), name="team_authorizations"),
path("team/<int:team_id>/authorizations/", TeamAuthorizationsView.as_view(), name="team_authorizations"),
path("team/leave/", TeamLeaveView.as_view(), name="team_leave"),
path("detail/", MyParticipationDetailView.as_view(), name="my_participation_detail"),
path("detail/<int:pk>/", ParticipationDetailView.as_view(), name="participation_detail"),
@ -36,6 +36,8 @@ urlpatterns = [
path("tournament/<int:pk>/update/", TournamentUpdateView.as_view(), name="tournament_update"),
path("tournament/<int:pk>/payments/", TournamentPaymentsView.as_view(), name="tournament_payments"),
path("tournament/<int:pk>/csv/", TournamentExportCSVView.as_view(), name="tournament_csv"),
path("tournament/<int:tournament_id>/authorizations/", TeamAuthorizationsView.as_view(),
name="tournament_authorizations"),
path("tournament/<int:pk>/publish-notes/<int:round>/", TournamentPublishNotesView.as_view(),
name="tournament_publish_notes"),
path("pools/create/", PoolCreateView.as_view(), name="pool_create"),

View File

@ -366,63 +366,91 @@ class MotivationLetterView(LoginRequiredMixin, View):
return FileResponse(open(path, "rb"), content_type=mime_type, filename=true_file_name)
class TeamAuthorizationsView(LoginRequiredMixin, DetailView):
class TeamAuthorizationsView(LoginRequiredMixin, View):
"""
Get as a ZIP archive all the authorizations that are sent
"""
model = Team
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_authenticated:
return super().handle_no_permission()
if 'team_id' in kwargs:
team = Team.objects.get(pk=kwargs["team_id"])
tournament = team.participation.tournament
else:
team = None
tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
if user.registration.is_admin or user.registration.is_volunteer \
and (user.registration in self.get_object().participation.tournament.organizers
or self.get_object().participation.final
and user.registration in Tournament.final_tournament().organizers):
and (user.registration in tournament.organizers
or (team is not None and team.participation.final
and user.registration in Tournament.final_tournament().organizers)):
return super().dispatch(request, *args, **kwargs)
raise PermissionDenied
def get(self, request, *args, **kwargs):
team = self.get_object()
if 'team_id' in kwargs:
team = Team.objects.get(pk=kwargs["team_id"])
teams = [team]
filename = _("Authorizations of team {trigram}.zip").format(trigram=team.trigram)
else:
tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
teams = [p.team for p in tournament.participations.filter(valid=True)]
filename = _("Authorizations of {tournament}.zip").format(tournament=tournament.name)
magic = Magic(mime=True)
output = BytesIO()
zf = ZipFile(output, "w")
for participant in team.participants.all():
if participant.photo_authorization:
mime_type = magic.from_file("media/" + participant.photo_authorization.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.photo_authorization.name,
_("Photo authorization of {participant}.{ext}").format(participant=str(participant), ext=ext))
for team in teams:
team_prefix = f"{team.trigram}/" if len(teams) > 1 else ""
if isinstance(participant, StudentRegistration) and participant.parental_authorization:
mime_type = magic.from_file("media/" + participant.parental_authorization.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.parental_authorization.name,
_("Parental authorization of {participant}.{ext}")
.format(participant=str(participant), ext=ext))
for participant in team.participants.all():
user_prefix = f"{team_prefix}{participant.user.first_name} {participant.user.last_name}/"
if isinstance(participant, StudentRegistration) and participant.health_sheet:
mime_type = magic.from_file("media/" + participant.health_sheet.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.health_sheet.name,
_("Health sheet of {participant}.{ext}").format(participant=str(participant), ext=ext))
if participant.photo_authorization \
and participant.photo_authorization.storage.exists(participant.photo_authorization.path):
mime_type = magic.from_file("media/" + participant.photo_authorization.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.photo_authorization.name,
user_prefix + _("Photo authorization 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 participant.is_student and participant.parental_authorization \
and participant.parental_authorization.storage.exists(participant.parental_authorization.path):
mime_type = magic.from_file("media/" + participant.parental_authorization.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.parental_authorization.name,
user_prefix + _("Parental authorization of {participant}.{ext}")
.format(participant=str(participant), ext=ext))
if participant.is_student and participant.health_sheet \
and participant.health_sheet.storage.exists(participant.health_sheet.path):
mime_type = magic.from_file("media/" + participant.health_sheet.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + participant.health_sheet.name,
user_prefix + _("Health sheet of {participant}.{ext}")
.format(participant=str(participant), ext=ext))
if participant.is_student and participant.vaccine_sheet \
and participant.vaccine_sheet.storage.exists(participant.vaccine_sheet.path):
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,
user_prefix + _("Vaccine sheet of {participant}.{ext}")
.format(participant=str(participant), ext=ext))
if team.motivation_letter and team.motivation_letter.storage.exists(team.motivation_letter.path):
mime_type = magic.from_file("media/" + team.motivation_letter.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + team.motivation_letter.name,
team_prefix + _("Motivation letter of {team}.{ext}")
.format(team=str(team), ext=ext))
if team.motivation_letter:
mime_type = magic.from_file("media/" + team.motivation_letter.name)
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
zf.write("media/" + team.motivation_letter.name,
_("Motivation letter of {team}.{ext}").format(team=str(team), ext=ext))
zf.close()
response = HttpResponse(content_type="application/zip")
response["Content-Disposition"] = "attachment; filename=\"{filename}\"" \
.format(filename=_("Photo authorizations of team {trigram}.zip").format(trigram=team.trigram))
response["Content-Disposition"] = f"attachment; filename=\"{filename}\""
response.write(output.getvalue())
return response