mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-21 05:18:26 +02:00
Implement final selection
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
@ -1,11 +1,8 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import csv
|
||||
import math
|
||||
from io import StringIO
|
||||
import re
|
||||
from typing import Iterable
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Div, Field, Submit
|
||||
|
@ -64,6 +64,15 @@ def create_payments(instance: Participation, created, raw, **_):
|
||||
else:
|
||||
payment = Payment.objects.create(final=True)
|
||||
payment.registrations.add(student)
|
||||
|
||||
payment_regional = Payment.objects.get(registrations=student, final=False)
|
||||
if payment_regional.type == 'scholarship':
|
||||
payment.type = 'scholarship'
|
||||
with open(payment_regional.receipt.path, 'rb') as f:
|
||||
payment.receipt.save(payment_regional.receipt.name, f)
|
||||
payment.additional_information = payment_regional.additional_information
|
||||
payment.fee = 0
|
||||
payment.valid = payment_regional.valid
|
||||
payment.save()
|
||||
payment.amount = Tournament.final_tournament().price
|
||||
if payment.amount == 0:
|
||||
|
@ -60,6 +60,19 @@
|
||||
{% endfor %}
|
||||
</dd>
|
||||
|
||||
{% if team.participation.final %}
|
||||
<dt class="col-sm-6 text-end">{% trans "Photo authorizations (final):" %}</dt>
|
||||
<dd class="col-sm-6">
|
||||
{% for participant in team.participants.all %}
|
||||
{% if participant.photo_authorization_final %}
|
||||
<a href="{{ participant.photo_authorization_final.url }}">{{ participant }}</a>{% if not forloop.last %},{% endif %}
|
||||
{% else %}
|
||||
{{ participant }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if not team.participation.tournament.remote %}
|
||||
<dt class="col-sm-6 text-end">{% trans "Health sheets:" %}</dt>
|
||||
<dd class="col-sm-6">
|
||||
@ -99,6 +112,21 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</dd>
|
||||
|
||||
{% if team.participation.final %}
|
||||
<dt class="col-sm-6 text-end">{% trans "Parental authorizations (final):" %}</dt>
|
||||
<dd class="col-sm-6">
|
||||
{% for student in team.students.all %}
|
||||
{% if student.under_18_final %}
|
||||
{% if student.parental_authorization_final %}
|
||||
<a href="{{ student.parental_authorization_final.url }}">{{ student }}</a>{% if not forloop.last %},{% endif %}
|
||||
{% else %}
|
||||
{{ student }} ({% trans "Not uploaded yet" %}){% if not forloop.last %},{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<dt class="col-sm-6 text-end">{% trans "Motivation letter:" %}</dt>
|
||||
|
@ -103,7 +103,24 @@
|
||||
<div class="card-body">
|
||||
<ul>
|
||||
{% for participation, note in notes %}
|
||||
<li><strong>{{ participation.team }} :</strong> {{ note|floatformat }}</li>
|
||||
<li>
|
||||
<strong>{{ participation.team }} :</strong> {{ note|floatformat }}
|
||||
{% if participation.final %}
|
||||
<span class="badge badge-sm bg-warning">
|
||||
<i class="fas fa-medal"></i>
|
||||
{% trans "Selected for final tournament" %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
||||
{% if team_selectable_for_final == participation %}
|
||||
<a href="{% url 'participation:select_team_final' pk=tournament.pk participation_id=participation.pk %}"
|
||||
class="badge badge-sm bg-success">
|
||||
<i class="fas fa-medal"></i>
|
||||
{% trans "Select for final tournament" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -8,7 +8,8 @@ from .views import CreateTeamView, FinalNotationSheetTemplateView, GSheetNotific
|
||||
MyParticipationDetailView, MyTeamDetailView, NotationSheetsArchiveView, NoteUpdateView, ParticipationDetailView, \
|
||||
PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, PoolJuryView, PoolNotesTemplateView, \
|
||||
PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateView, PoolUploadNotesView, \
|
||||
ScaleNotationSheetTemplateView, SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \
|
||||
ScaleNotationSheetTemplateView, SelectTeamFinalView, \
|
||||
SolutionsDownloadView, SolutionUploadView, SynthesisUploadView, \
|
||||
TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \
|
||||
TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \
|
||||
TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \
|
||||
@ -54,6 +55,8 @@ urlpatterns = [
|
||||
name="tournament_harmonize"),
|
||||
path("tournament/<int:pk>/harmonize/<int:round>/<str:action>/<str:trigram>/", TournamentHarmonizeNoteView.as_view(),
|
||||
name="tournament_harmonize_note"),
|
||||
path("tournament/<int:pk>/select-final/<int:participation_id>/", SelectTeamFinalView.as_view(),
|
||||
name="select_team_final"),
|
||||
path("pools/create/", PoolCreateView.as_view(), name="pool_create"),
|
||||
path("pools/<int:pk>/", PoolDetailView.as_view(), name="pool_detail"),
|
||||
path("pools/<int:pk>/update/", PoolUpdateView.as_view(), name="pool_update"),
|
||||
|
@ -399,6 +399,7 @@ class TeamAuthorizationsView(LoginRequiredMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'team_id' in kwargs:
|
||||
team = Team.objects.get(pk=kwargs["team_id"])
|
||||
tournament = team.participation.tournament
|
||||
teams = [team]
|
||||
filename = _("Authorizations of team {trigram}.zip").format(trigram=team.trigram)
|
||||
else:
|
||||
@ -415,21 +416,25 @@ class TeamAuthorizationsView(LoginRequiredMixin, View):
|
||||
for participant in team.participants.all():
|
||||
user_prefix = f"{team_prefix}{participant.user.first_name} {participant.user.last_name}/"
|
||||
|
||||
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 'team_id' in kwargs or not tournament.final:
|
||||
# Don't include the photo authorization and the parental authorization of the regional tournament
|
||||
# in the final authorizations
|
||||
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 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.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):
|
||||
@ -447,6 +452,26 @@ class TeamAuthorizationsView(LoginRequiredMixin, View):
|
||||
user_prefix + _("Vaccine sheet of {participant}.{ext}")
|
||||
.format(participant=str(participant), ext=ext))
|
||||
|
||||
if 'team_id' in kwargs or tournament.final:
|
||||
# Don't include final authorizations in the regional authorizations
|
||||
if participant.photo_authorization_final \
|
||||
and participant.photo_authorization_final.storage.exists(
|
||||
participant.photo_authorization_final.path):
|
||||
mime_type = magic.from_file("media/" + participant.photo_authorization_final.name)
|
||||
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
||||
zf.write("media/" + participant.photo_authorization_final.name,
|
||||
user_prefix + _("Photo authorization of {participant} (final).{ext}")
|
||||
.format(participant=str(participant), ext=ext))
|
||||
|
||||
if participant.is_student and participant.parental_authorization_final \
|
||||
and participant.parental_authorization_final.storage.exists(
|
||||
participant.parental_authorization_final.path):
|
||||
mime_type = magic.from_file("media/" + participant.parental_authorization_final.name)
|
||||
ext = mime_type.split("/")[1].replace("jpeg", "jpg")
|
||||
zf.write("media/" + participant.parental_authorization_final.name,
|
||||
user_prefix + _("Parental authorization of {participant} (final).{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")
|
||||
@ -591,10 +616,15 @@ class TournamentDetailView(MultiTableMixin, DetailView):
|
||||
or (self.request.user.is_authenticated and self.request.user.registration.is_volunteer))
|
||||
if note:
|
||||
notes[participation] = note
|
||||
context["notes"] = sorted(notes.items(), key=lambda x: x[1], reverse=True)
|
||||
sorted_notes = sorted(notes.items(), key=lambda x: x[1], reverse=True)
|
||||
context["notes"] = sorted_notes
|
||||
context["available_notes_1"] = all(pool.results_available for pool in self.object.pools.filter(round=1).all())
|
||||
context["available_notes_2"] = all(pool.results_available for pool in self.object.pools.filter(round=2).all())
|
||||
|
||||
if not self.object.final and notes and self.request.user.registration.is_volunteer:
|
||||
context["team_selectable_for_final"] = next(participation for participation, _note in sorted_notes
|
||||
if not participation.final)
|
||||
|
||||
return context
|
||||
|
||||
def get_tables(self):
|
||||
@ -625,8 +655,11 @@ class TournamentPaymentsView(VolunteerMixin, SingleTableMixin, DetailView):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_table_data(self):
|
||||
return Payment.objects.filter(registrations__team__participation__tournament=self.get_object()) \
|
||||
.annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \
|
||||
if self.object.final:
|
||||
payments = Payment.objects.filter(final=True)
|
||||
else:
|
||||
payments = Payment.objects.filter(registrations__team__participation__tournament=self.get_object())
|
||||
return payments.annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \
|
||||
.distinct().all()
|
||||
|
||||
|
||||
@ -795,6 +828,30 @@ class TournamentHarmonizeNoteView(VolunteerMixin, DetailView):
|
||||
return redirect(reverse_lazy("participation:tournament_harmonize", args=(tournament.pk, kwargs['round'],)))
|
||||
|
||||
|
||||
class SelectTeamFinalView(VolunteerMixin, DetailView):
|
||||
model = Tournament
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
tournament = self.get_object()
|
||||
reg = request.user.registration
|
||||
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()):
|
||||
return self.handle_no_permission()
|
||||
participation_qs = tournament.participations.filter(pk=self.kwargs["participation_id"])
|
||||
if not participation_qs.exists():
|
||||
raise Http404
|
||||
self.participation = participation_qs.get()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@transaction.atomic
|
||||
def get(self, request, *args, **kwargs):
|
||||
tournament = self.get_object()
|
||||
self.participation.final = True
|
||||
self.participation.save()
|
||||
return redirect(reverse_lazy("participation:tournament_detail", args=(tournament.pk,)))
|
||||
|
||||
|
||||
class SolutionUploadView(LoginRequiredMixin, FormView):
|
||||
template_name = "participation/upload_solution.html"
|
||||
form_class = SolutionForm
|
||||
|
Reference in New Issue
Block a user