mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-11-04 08:22:10 +01:00 
			
		
		
		
	Validate teams
This commit is contained in:
		@@ -77,10 +77,18 @@ class AddTeamView(LoginRequiredMixin, CreateView):
 | 
				
			|||||||
    form_class = TeamForm
 | 
					    form_class = TeamForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def form_valid(self, form):
 | 
					    def form_valid(self, form):
 | 
				
			||||||
 | 
					        if self.request.user.organizes:
 | 
				
			||||||
 | 
					            form.add_error('name', _("You can't organize and participate at the same time."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.user.team:
 | 
				
			||||||
 | 
					            form.add_error('name', _("You are already in a team."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        team = form.instance
 | 
					        team = form.instance
 | 
				
			||||||
        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
					        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
				
			||||||
        code = ""
 | 
					        code = ""
 | 
				
			||||||
        for _ in range(6):
 | 
					        for i in range(6):
 | 
				
			||||||
            code += random.choice(alphabet)
 | 
					            code += random.choice(alphabet)
 | 
				
			||||||
        team.access_code = code
 | 
					        team.access_code = code
 | 
				
			||||||
        team.validation_status = "0invalid"
 | 
					        team.validation_status = "0invalid"
 | 
				
			||||||
@@ -104,6 +112,23 @@ class JoinTeamView(LoginRequiredMixin, FormView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def form_valid(self, form):
 | 
					    def form_valid(self, form):
 | 
				
			||||||
        team = form.cleaned_data["team"]
 | 
					        team = form.cleaned_data["team"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.user.organizes:
 | 
				
			||||||
 | 
					            form.add_error('access_code', _("You can't organize and participate at the same time."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.user.team:
 | 
				
			||||||
 | 
					            form.add_error('access_code', _("You are already in a team."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.user.role == '2coach' and team.encadrants.size() == 3:
 | 
				
			||||||
 | 
					            form.add_error('access_code', _("This team is full of coachs."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.request.user.role == '3participant' and team.participants.size() == 5:
 | 
				
			||||||
 | 
					            form.add_error('access_code', _("This team is full of participants."))
 | 
				
			||||||
 | 
					            return self.form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.request.user.team = team
 | 
					        self.request.user.team = team
 | 
				
			||||||
        self.request.user.save()
 | 
					        self.request.user.save()
 | 
				
			||||||
        return super().form_valid(form)
 | 
					        return super().form_valid(form)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
from django.utils.translation import gettext_lazy as _
 | 
					from django.utils.translation import gettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,6 +11,17 @@ from tournament.models import Tournament, Team
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TournamentForm(forms.ModelForm):
 | 
					class TournamentForm(forms.ModelForm):
 | 
				
			||||||
 | 
					    def clean(self):
 | 
				
			||||||
 | 
					        cleaned_data = super().clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not self.instance.pk:
 | 
				
			||||||
 | 
					            if Tournament.objects.filter(name=cleaned_data["data"], year=os.getenv("TFJM_YEAR")):
 | 
				
			||||||
 | 
					                self.add_error("name", _("This tournament already exists."))
 | 
				
			||||||
 | 
					            if cleaned_data["final"] and Tournament.objects.filter(final=True, year=os.getenv("TFJM_YEAR")):
 | 
				
			||||||
 | 
					                self.add_error("name", _("The final tournament was already defined."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Tournament
 | 
					        model = Tournament
 | 
				
			||||||
        fields = '__all__'
 | 
					        fields = '__all__'
 | 
				
			||||||
@@ -25,6 +40,14 @@ class OrganizerForm(forms.ModelForm):
 | 
				
			|||||||
        model = TFJMUser
 | 
					        model = TFJMUser
 | 
				
			||||||
        fields = ('last_name', 'first_name', 'email', 'is_superuser',)
 | 
					        fields = ('last_name', 'first_name', 'email', 'is_superuser',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean(self):
 | 
				
			||||||
 | 
					        cleaned_data = super().clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if TFJMUser.objects.filter(email=cleaned_data["email"], year=os.getenv("TFJM_YEAR")).exists():
 | 
				
			||||||
 | 
					            self.add_error("trigram", _("This organizer already exist."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, commit=True):
 | 
					    def save(self, commit=True):
 | 
				
			||||||
        user = self.instance
 | 
					        user = self.instance
 | 
				
			||||||
        user.role = '0admin' if user.is_superuser else '1organizer'
 | 
					        user.role = '0admin' if user.is_superuser else '1organizer'
 | 
				
			||||||
@@ -32,10 +55,34 @@ class OrganizerForm(forms.ModelForm):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TeamForm(forms.ModelForm):
 | 
					class TeamForm(forms.ModelForm):
 | 
				
			||||||
 | 
					    tournament = forms.ModelChoiceField(
 | 
				
			||||||
 | 
					        Tournament.objects.filter(date_inscription__gte=datetime.today(), final=False),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Team
 | 
					        model = Team
 | 
				
			||||||
        fields = ('name', 'trigram', 'tournament',)
 | 
					        fields = ('name', 'trigram', 'tournament',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean(self):
 | 
				
			||||||
 | 
					        cleaned_data = super().clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cleaned_data["trigram"] = cleaned_data["trigram"].upper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not re.match("[A-Z]{3}", cleaned_data["trigram"]):
 | 
				
			||||||
 | 
					            self.add_error("trigram", _("The trigram must be composed of three upcase letters."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not self.instance.pk:
 | 
				
			||||||
 | 
					            if Team.objects.filter(trigram=cleaned_data["trigram"], year=os.getenv("TFJM_YEAR")).exists():
 | 
				
			||||||
 | 
					                self.add_error("trigram", _("This trigram is already used."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if Team.objects.filter(name=cleaned_data["name"], year=os.getenv("TFJM_YEAR")).exists():
 | 
				
			||||||
 | 
					                self.add_error("name", _("This name is already used."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if cleaned_data["tournament"].date_inscription < datetime.today():
 | 
				
			||||||
 | 
					                self.add_error("tournament", _("This tournament is already closed."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class JoinTeam(forms.Form):
 | 
					class JoinTeam(forms.Form):
 | 
				
			||||||
    access_code = forms.CharField(
 | 
					    access_code = forms.CharField(
 | 
				
			||||||
@@ -46,10 +93,16 @@ class JoinTeam(forms.Form):
 | 
				
			|||||||
    def clean(self):
 | 
					    def clean(self):
 | 
				
			||||||
        cleaned_data = super().clean()
 | 
					        cleaned_data = super().clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not re.match("[a-z0-9]{6}", cleaned_data["access_code"]):
 | 
				
			||||||
 | 
					            self.add_error('access_code', _("The access code must be composed of 6 alphanumeric characters."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        team = Team.objects.filter(access_code=cleaned_data["access_code"])
 | 
					        team = Team.objects.filter(access_code=cleaned_data["access_code"])
 | 
				
			||||||
        if not team.exists():
 | 
					        if not team.exists():
 | 
				
			||||||
            self.add_error('access_code', _("This access code is invalid."))
 | 
					            self.add_error('access_code', _("This access code is invalid."))
 | 
				
			||||||
        cleaned_data["team"] = team.get()
 | 
					        team = team.get()
 | 
				
			||||||
 | 
					        if not team.invalid:
 | 
				
			||||||
 | 
					            self.add_error('access_code', _("The team is already validated."))
 | 
				
			||||||
 | 
					        cleaned_data["team"] = team
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return cleaned_data
 | 
					        return cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
from datetime import date
 | 
					from datetime import date, datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.urls import reverse_lazy
 | 
					from django.urls import reverse_lazy
 | 
				
			||||||
@@ -36,23 +36,38 @@ class Tournament(models.Model):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_start = models.DateField(
 | 
					    date_start = models.DateField(
 | 
				
			||||||
 | 
					        default=datetime.today,
 | 
				
			||||||
        verbose_name=_("date start"),
 | 
					        verbose_name=_("date start"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_end = models.DateField(
 | 
					    date_end = models.DateField(
 | 
				
			||||||
 | 
					        default=datetime.today,
 | 
				
			||||||
        verbose_name=_("date end"),
 | 
					        verbose_name=_("date end"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_inscription = models.DateTimeField(
 | 
					    date_inscription = models.DateTimeField(
 | 
				
			||||||
 | 
					        default=datetime.now,
 | 
				
			||||||
        verbose_name=_("date of registration closing"),
 | 
					        verbose_name=_("date of registration closing"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_solutions = models.DateTimeField(
 | 
					    date_solutions = models.DateTimeField(
 | 
				
			||||||
 | 
					        default=datetime.now,
 | 
				
			||||||
        verbose_name=_("date of maximal solution submission"),
 | 
					        verbose_name=_("date of maximal solution submission"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date_syntheses = models.DateTimeField(
 | 
					    date_syntheses = models.DateTimeField(
 | 
				
			||||||
        verbose_name=_("date of maximal syntheses submission"),
 | 
					        default=datetime.now,
 | 
				
			||||||
 | 
					        verbose_name=_("date of maximal syntheses submission for the first round"),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    date_solutions_2 = models.DateTimeField(
 | 
				
			||||||
 | 
					        default=datetime.now,
 | 
				
			||||||
 | 
					        verbose_name=_("date when solutions of round 2 are available"),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    date_syntheses_2 = models.DateTimeField(
 | 
				
			||||||
 | 
					        default=datetime.now,
 | 
				
			||||||
 | 
					        verbose_name=_("date of maximal syntheses submission for the second round"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    final = models.BooleanField(
 | 
					    final = models.BooleanField(
 | 
				
			||||||
@@ -172,6 +187,11 @@ class Team(models.Model):
 | 
				
			|||||||
        return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
 | 
					        return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
 | 
				
			||||||
                for user in self.participants]
 | 
					                for user in self.participants]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def can_validate(self):
 | 
				
			||||||
 | 
					        # TODO In a normal time, team needs a motivation letter and authorizations.
 | 
				
			||||||
 | 
					        return self.encadrants.exists() and self.participants.count() >= 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _("team")
 | 
					        verbose_name = _("team")
 | 
				
			||||||
        verbose_name_plural = _("teams")
 | 
					        verbose_name_plural = _("teams")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import random
 | 
					import random
 | 
				
			||||||
import zipfile
 | 
					import zipfile
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
					from django.contrib.auth.mixins import LoginRequiredMixin
 | 
				
			||||||
@@ -21,21 +22,21 @@ from .tables import TournamentTable, TeamTable, SolutionTable, SynthesisTable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class AdminMixin(LoginRequiredMixin):
 | 
					class AdminMixin(LoginRequiredMixin):
 | 
				
			||||||
    def dispatch(self, request, *args, **kwargs):
 | 
					    def dispatch(self, request, *args, **kwargs):
 | 
				
			||||||
        if not request.user.admin:
 | 
					        if not request.user.is_authenticated or not request.user.admin:
 | 
				
			||||||
            raise PermissionDenied
 | 
					            raise PermissionDenied
 | 
				
			||||||
        return super().dispatch(request, *args, **kwargs)
 | 
					        return super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OrgaMixin(LoginRequiredMixin):
 | 
					class OrgaMixin(LoginRequiredMixin):
 | 
				
			||||||
    def dispatch(self, request, *args, **kwargs):
 | 
					    def dispatch(self, request, *args, **kwargs):
 | 
				
			||||||
        if not request.user.organizes:
 | 
					        if not request.user.is_authenticated or not request.user.organizes:
 | 
				
			||||||
            raise PermissionDenied
 | 
					            raise PermissionDenied
 | 
				
			||||||
        return super().dispatch(request, *args, **kwargs)
 | 
					        return super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TeamMixin(LoginRequiredMixin):
 | 
					class TeamMixin(LoginRequiredMixin):
 | 
				
			||||||
    def dispatch(self, request, *args, **kwargs):
 | 
					    def dispatch(self, request, *args, **kwargs):
 | 
				
			||||||
        if not request.user.team:
 | 
					        if not request.user.is_authenticated or not request.user.team:
 | 
				
			||||||
            raise PermissionDenied
 | 
					            raise PermissionDenied
 | 
				
			||||||
        return super().dispatch(request, *args, **kwargs)
 | 
					        return super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,12 +106,14 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
 | 
				
			|||||||
    model = Team
 | 
					    model = Team
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def dispatch(self, request, *args, **kwargs):
 | 
					    def dispatch(self, request, *args, **kwargs):
 | 
				
			||||||
        if not request.user.admin and self.request.user not in self.get_object().tournament.organizers.all()\
 | 
					        if not request.user.is_authenticated or \
 | 
				
			||||||
                and self.get_object() != request.user.team:
 | 
					                (not request.user.admin and self.request.user not in self.get_object().tournament.organizers.all()
 | 
				
			||||||
 | 
					                 and self.get_object() != request.user.team):
 | 
				
			||||||
            raise PermissionDenied
 | 
					            raise PermissionDenied
 | 
				
			||||||
        return super().dispatch(request, *args, **kwargs)
 | 
					        return super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post(self, request, *args, **kwargs):
 | 
					    def post(self, request, *args, **kwargs):
 | 
				
			||||||
 | 
					        print(request.POST)
 | 
				
			||||||
        team = self.get_object()
 | 
					        team = self.get_object()
 | 
				
			||||||
        if "zip" in request.POST:
 | 
					        if "zip" in request.POST:
 | 
				
			||||||
            solutions = team.solutions.all()
 | 
					            solutions = team.solutions.all()
 | 
				
			||||||
@@ -128,13 +131,28 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
 | 
				
			|||||||
                .format(_("Solutions for team {team}.zip")
 | 
					                .format(_("Solutions for team {team}.zip")
 | 
				
			||||||
                        .format(team=str(team)).replace(" ", "%20"))
 | 
					                        .format(team=str(team)).replace(" ", "%20"))
 | 
				
			||||||
            return resp
 | 
					            return resp
 | 
				
			||||||
        elif "leave" in request.POST:
 | 
					        elif "leave" in request.POST and request.user.participates:
 | 
				
			||||||
            request.user.team = None
 | 
					            request.user.team = None
 | 
				
			||||||
            request.user.save()
 | 
					            request.user.save()
 | 
				
			||||||
            if not team.users.exists():
 | 
					            if not team.users.exists():
 | 
				
			||||||
                team.delete()
 | 
					                team.delete()
 | 
				
			||||||
            return redirect('tournament:detail', pk=team.tournament.pk)
 | 
					            return redirect('tournament:detail', pk=team.tournament.pk)
 | 
				
			||||||
        elif "delete" in request.POST:
 | 
					        elif "request_validation" in request.POST and request.user.participates:
 | 
				
			||||||
 | 
					            team.validation_status = "1waiting"
 | 
				
			||||||
 | 
					            team.save()
 | 
				
			||||||
 | 
					            # TODO Send mail
 | 
				
			||||||
 | 
					            return redirect('tournament:team_detail', pk=team.pk)
 | 
				
			||||||
 | 
					        elif "validate" in request.POST and request.user.organizes:
 | 
				
			||||||
 | 
					            team.validation_status = "2valid"
 | 
				
			||||||
 | 
					            team.save()
 | 
				
			||||||
 | 
					            # TODO Send mail
 | 
				
			||||||
 | 
					            return redirect('tournament:team_detail', pk=team.pk)
 | 
				
			||||||
 | 
					        elif "invalidate" in request.POST and request.user.organizes:
 | 
				
			||||||
 | 
					            team.validation_status = "0invalid"
 | 
				
			||||||
 | 
					            team.save()
 | 
				
			||||||
 | 
					            # TODO Send mail
 | 
				
			||||||
 | 
					            return redirect('tournament:team_detail', pk=team.pk)
 | 
				
			||||||
 | 
					        elif "delete" in request.POST and request.user.organizes:
 | 
				
			||||||
            team.delete()
 | 
					            team.delete()
 | 
				
			||||||
            return redirect('tournament:detail', pk=team.tournament.pk)
 | 
					            return redirect('tournament:detail', pk=team.tournament.pk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -204,12 +222,18 @@ class SolutionsView(TeamMixin, BaseFormView, SingleTableView):
 | 
				
			|||||||
        solution = form.instance
 | 
					        solution = form.instance
 | 
				
			||||||
        solution.team = self.request.user.team
 | 
					        solution.team = self.request.user.team
 | 
				
			||||||
        solution.final = solution.team.selected_for_final
 | 
					        solution.final = solution.team.selected_for_final
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if datetime.now() > solution.tournament.date_solutions:
 | 
				
			||||||
 | 
					            form.add_error('file', _("You can't publish your solution anymore. Deadline: {date:%m-%d-%Y %h:%M}.")
 | 
				
			||||||
 | 
					                           .format(date=solution.tournament.date_solutions))
 | 
				
			||||||
 | 
					            return super().form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prev_sol = Solution.objects.filter(problem=solution.problem, team=solution.team, final=solution.final)
 | 
					        prev_sol = Solution.objects.filter(problem=solution.problem, team=solution.team, final=solution.final)
 | 
				
			||||||
        for sol in prev_sol.all():
 | 
					        for sol in prev_sol.all():
 | 
				
			||||||
            sol.delete()
 | 
					            sol.delete()
 | 
				
			||||||
        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
					        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
				
			||||||
        id = ""
 | 
					        id = ""
 | 
				
			||||||
        for _ in range(64):
 | 
					        for i in range(64):
 | 
				
			||||||
            id += random.choice(alphabet)
 | 
					            id += random.choice(alphabet)
 | 
				
			||||||
        solution.file.name = id
 | 
					        solution.file.name = id
 | 
				
			||||||
        solution.save()
 | 
					        solution.save()
 | 
				
			||||||
@@ -302,13 +326,26 @@ class SynthesesView(TeamMixin, BaseFormView, SingleTableView):
 | 
				
			|||||||
        synthesis = form.instance
 | 
					        synthesis = form.instance
 | 
				
			||||||
        synthesis.team = self.request.user.team
 | 
					        synthesis.team = self.request.user.team
 | 
				
			||||||
        synthesis.final = synthesis.team.selected_for_final
 | 
					        synthesis.final = synthesis.team.selected_for_final
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if synthesis.round == '1' and datetime.now() > synthesis.tournament.date_syntheses:
 | 
				
			||||||
 | 
					            form.add_error('file', _("You can't publish your synthesis anymore for the first round."
 | 
				
			||||||
 | 
					                                     " Deadline: {date:%m-%d-%Y %h:%M}.")
 | 
				
			||||||
 | 
					                           .format(date=synthesis.tournament.date_syntheses))
 | 
				
			||||||
 | 
					            return super().form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if synthesis.round == '2' and datetime.now() > synthesis.tournament.date_syntheses_2:
 | 
				
			||||||
 | 
					            form.add_error('file', _("You can't publish your synthesis anymore for the second round."
 | 
				
			||||||
 | 
					                                     " Deadline: {date:%m-%d-%Y %h:%M}.")
 | 
				
			||||||
 | 
					                           .format(date=synthesis.tournament.date_syntheses_2))
 | 
				
			||||||
 | 
					            return super().form_invalid(form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prev_syn = Synthesis.objects.filter(team=synthesis.team, round=synthesis.round, source=synthesis.source,
 | 
					        prev_syn = Synthesis.objects.filter(team=synthesis.team, round=synthesis.round, source=synthesis.source,
 | 
				
			||||||
                                            final=synthesis.final)
 | 
					                                            final=synthesis.final)
 | 
				
			||||||
        for syn in prev_syn.all():
 | 
					        for syn in prev_syn.all():
 | 
				
			||||||
            syn.delete()
 | 
					            syn.delete()
 | 
				
			||||||
        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
					        alphabet = "0123456789abcdefghijklmnopqrstuvwxyz0123456789"
 | 
				
			||||||
        id = ""
 | 
					        id = ""
 | 
				
			||||||
        for _ in range(64):
 | 
					        for i in range(64):
 | 
				
			||||||
            id += random.choice(alphabet)
 | 
					            id += random.choice(alphabet)
 | 
				
			||||||
        synthesis.file.name = id
 | 
					        synthesis.file.name = id
 | 
				
			||||||
        synthesis.save()
 | 
					        synthesis.save()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,60 @@
 | 
				
			|||||||
        {% endif %}
 | 
					        {% endif %}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if user.participates and team.invalid %}
 | 
				
			||||||
 | 
					        <hr>
 | 
				
			||||||
 | 
					        {% if team.can_validate %}
 | 
				
			||||||
 | 
					            <form method="post">
 | 
				
			||||||
 | 
					                {% csrf_token %}
 | 
				
			||||||
 | 
					                <label for="engage">Je m'engage à participer à l'intégralité du TFJM²*</label>
 | 
				
			||||||
 | 
					                <input type="checkbox" name="engage" id="engage" required/>
 | 
				
			||||||
 | 
					                <div class="alert alert-warning">
 | 
				
			||||||
 | 
					                    <strong>Attention !</strong> Une fois votre équipe validée, vous ne pourrez plus modifier le nom
 | 
				
			||||||
 | 
					                    de l'équipe, le trigramme ou la composition de l'équipe.
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <input class="btn btn-success btn-block" type="submit" name="request_validation"
 | 
				
			||||||
 | 
					                       value="Demander la validation"/>
 | 
				
			||||||
 | 
					            </form>
 | 
				
			||||||
 | 
					        {% else %}
 | 
				
			||||||
 | 
					            <div class="alert alert-warning">
 | 
				
			||||||
 | 
					                Pour demander à valider votre équipe, vous devez avoir au moins un encadrant, quatre participants
 | 
				
			||||||
 | 
					                et soumis une autorisation de droit à l'image, une fiche sanitaire et une autorisation
 | 
				
			||||||
 | 
					                parentale (si besoin) par participant, ainsi qu'une lettre de motivation à transmettre aux organisateurs.
 | 
				
			||||||
 | 
					                Les encadrants doivent également fournir une autorisation de droit à l'image.
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					        <hr>
 | 
				
			||||||
 | 
					        <div class="alert alert-danger">
 | 
				
			||||||
 | 
					            En raison du changement de format du TFJM² 2020, il n'y a plus de document obligatoire à envoyer. Les autorisations
 | 
				
			||||||
 | 
					            précédemment envoyées ont été détruites. Seules les lettres de motivation ont été conservées, mais leur envoi
 | 
				
			||||||
 | 
					            n'est plus obligatoire.
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if team.waiting %}
 | 
				
			||||||
 | 
					        <hr>
 | 
				
			||||||
 | 
					        <div class="alert alert-warning">
 | 
				
			||||||
 | 
					        {% trans "The team is waiting about validation." %}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {% if user.admin %}
 | 
				
			||||||
 | 
					            <form method="POST">
 | 
				
			||||||
 | 
					                {% csrf_token %}
 | 
				
			||||||
 | 
					                <div class="form-group row">
 | 
				
			||||||
 | 
					                    <label for="message">{% trans "Message addressed to the team:" %}</label>
 | 
				
			||||||
 | 
					                    <textarea class="form-control" id="message" name="message" placeholder="{% trans "Message..." %}"></textarea>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div class="form-group">
 | 
				
			||||||
 | 
					                    <div class="btn-group btn-block">
 | 
				
			||||||
 | 
					                        <button class="btn btn-danger" name="invalidate">{% trans "Invalidate team" %}</button>
 | 
				
			||||||
 | 
					                        <button class="btn btn-success" name="validate">{% trans "Validate team" %}</button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </form>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <hr>
 | 
					    <hr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <h4>{% trans "Documents" %}</h4>
 | 
					    <h4>{% trans "Documents" %}</h4>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user