import os from django.core.mail import send_mail from django.db import models from django.template.loader import render_to_string from django.urls import reverse_lazy from django.utils import timezone from django.utils.translation import gettext_lazy as _ class Tournament(models.Model): name = models.CharField( max_length=255, verbose_name=_("name"), ) organizers = models.ManyToManyField( 'member.TFJMUser', related_name="organized_tournaments", verbose_name=_("organizers"), ) size = models.PositiveSmallIntegerField( verbose_name=_("size"), ) place = models.CharField( max_length=255, verbose_name=_("place"), ) price = models.PositiveSmallIntegerField( verbose_name=_("price"), ) description = models.TextField( verbose_name=_("description"), ) date_start = models.DateField( default=timezone.now, verbose_name=_("date start"), ) date_end = models.DateField( default=timezone.now, verbose_name=_("date end"), ) date_inscription = models.DateTimeField( default=timezone.now, verbose_name=_("date of registration closing"), ) date_solutions = models.DateTimeField( default=timezone.now, verbose_name=_("date of maximal solution submission"), ) date_syntheses = models.DateTimeField( default=timezone.now, verbose_name=_("date of maximal syntheses submission for the first round"), ) date_solutions_2 = models.DateTimeField( default=timezone.now, verbose_name=_("date when solutions of round 2 are available"), ) date_syntheses_2 = models.DateTimeField( default=timezone.now, verbose_name=_("date of maximal syntheses submission for the second round"), ) final = models.BooleanField( verbose_name=_("final tournament"), ) year = models.PositiveIntegerField( default=os.getenv("TFJM_YEAR", timezone.now().year), verbose_name=_("year"), ) @property def teams(self): return self._teams if not self.final else Team.objects.filter(selected_for_final=True) @property def linked_organizers(self): return [''.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '' for user in self.organizers.all()] @property def solutions(self): from member.models import Solution return Solution.objects.filter(final=self.final) if self.final \ else Solution.objects.filter(team__tournament=self) @property def syntheses(self): from member.models import Synthesis return Synthesis.objects.filter(final=self.final) if self.final \ else Synthesis.objects.filter(team__tournament=self) @classmethod def get_final(cls): return cls.objects.get(year=os.getenv("TFJM_YEAR"), final=True) class Meta: verbose_name = _("tournament") verbose_name_plural = _("tournaments") def send_mail_to_organizers(self, template_name, subject="Contact TFJM²", **kwargs): context = kwargs context["tournament"] = self for user in self.organizers.all(): context["user"] = user message = render_to_string("mail_templates/" + template_name + ".txt", context=context) message_html = render_to_string("mail_templates/" + template_name + ".html", context=context) send_mail(subject, message, "contact@tfjm.org", [user.email], html_message=message_html) from member.models import TFJMUser for user in TFJMUser.objects.get(is_superuser=True).all(): context["user"] = user message = render_to_string("mail_templates/" + template_name + ".txt", context=context) message_html = render_to_string("mail_templates/" + template_name + ".html", context=context) send_mail(subject, message, "contact@tfjm.org", [user.email], html_message=message_html) def __str__(self): return self.name class Team(models.Model): name = models.CharField( max_length=255, verbose_name=_("name"), ) trigram = models.CharField( max_length=3, verbose_name=_("trigram"), ) tournament = models.ForeignKey( Tournament, on_delete=models.PROTECT, related_name="_teams", verbose_name=_("tournament"), ) inscription_date = models.DateTimeField( auto_now_add=True, verbose_name=_("inscription date"), ) validation_status = models.CharField( max_length=8, choices=[ ("0invalid", _("Registration not validated")), ("1waiting", _("Waiting for validation")), ("2valid", _("Registration validated")), ], verbose_name=_("validation status"), ) selected_for_final = models.BooleanField( default=False, verbose_name=_("selected for final"), ) access_code = models.CharField( max_length=6, unique=True, verbose_name=_("access code"), ) year = models.PositiveIntegerField( default=os.getenv("TFJM_YEAR", timezone.now().year), verbose_name=_("year"), ) @property def valid(self): return self.validation_status == "2valid" @property def waiting(self): return self.validation_status == "1waiting" @property def invalid(self): return self.validation_status == "0invalid" @property def encadrants(self): return self.users.all().filter(role="2coach") @property def linked_encadrants(self): return [''.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '' for user in self.encadrants] @property def participants(self): return self.users.all().filter(role="3participant") @property def linked_participants(self): return [''.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '' for user in self.participants] @property def future_tournament(self): return Tournament.get_final() if self.selected_for_final else self.tournament @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: verbose_name = _("team") verbose_name_plural = _("teams") unique_together = (('name', 'year',), ('trigram', 'year',),) def send_mail(self, template_name, subject="Contact TFJM²", **kwargs): context = kwargs context["team"] = self for user in self.users.all(): context["user"] = user message = render_to_string("mail_templates/" + template_name + ".txt", context=context) message_html = render_to_string("mail_templates/" + template_name + ".html", context=context) send_mail(subject, message, "contact@tfjm.org", [user.email], html_message=message_html) def __str__(self): return self.trigram + " -- " + self.name class Pool(models.Model): teams = models.ManyToManyField( Team, related_name="pools", verbose_name=_("teams"), ) solutions = models.ManyToManyField( "member.Solution", related_name="pools", verbose_name=_("solutions"), ) round = models.PositiveIntegerField( choices=[ (1, _("Round 1")), (2, _("Round 2")), ], verbose_name=_("round"), ) juries = models.ManyToManyField( "member.TFJMUser", related_name="pools", verbose_name=_("juries"), ) @property def problems(self): return list(d["problem"] for d in self.solutions.values("problem").all()) @property def tournament(self): return self.solutions.first().tournament @property def syntheses(self): from member.models import Synthesis return Synthesis.objects.filter(team__in=self.teams.all(), round=self.round, final=self.tournament.final) class Meta: verbose_name = _("pool") verbose_name_plural = _("pools") class Payment(models.Model): user = models.OneToOneField( 'member.TFJMUser', on_delete=models.CASCADE, related_name="payment", verbose_name=_("user"), ) team = models.ForeignKey( Team, on_delete=models.CASCADE, related_name="payments", verbose_name=_("team"), ) method = models.CharField( max_length=16, choices=[ ("not_paid", _("Not paid")), ("credit_card", _("Credit card")), ("check", _("Bank check")), ("transfer", _("Bank transfer")), ("cash", _("Cash")), ("scholarship", _("Scholarship")), ], default="not_paid", verbose_name=_("payment method"), ) validation_status = models.CharField( max_length=8, choices=[ ("0invalid", _("Registration not validated")), ("1waiting", _("Waiting for validation")), ("2valid", _("Registration validated")), ], verbose_name=_("validation status"), ) class Meta: verbose_name = _("payment") verbose_name_plural = _("payments") def __str__(self): return _("Payment of {user}").format(str(self.user))