mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-23 06:36:35 +02:00
Move apps in main directory
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
377
registration/models.py
Normal file
377
registration/models.py
Normal file
@ -0,0 +1,377 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from datetime import date
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.template import loader
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
from polymorphic.models import PolymorphicModel
|
||||
from tfjm.tokens import email_validation_token
|
||||
|
||||
|
||||
class Registration(PolymorphicModel):
|
||||
"""
|
||||
Registrations store extra content that are not asked in the User Model.
|
||||
This is specific to the role of the user, see StudentRegistration,
|
||||
CoachRegistration or VolunteerRegistration.
|
||||
"""
|
||||
user = models.OneToOneField(
|
||||
"auth.User",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_("user"),
|
||||
)
|
||||
|
||||
give_contact_to_animath = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("Grant Animath to contact me in the future about other actions"),
|
||||
)
|
||||
|
||||
email_confirmed = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("email confirmed"),
|
||||
)
|
||||
|
||||
def send_email_validation_link(self):
|
||||
"""
|
||||
The account got created or the email got changed.
|
||||
Send an email that contains a link to validate the address.
|
||||
"""
|
||||
subject = "[TFJM²] " + str(_("Activate your TFJM² account"))
|
||||
token = email_validation_token.make_token(self.user)
|
||||
uid = urlsafe_base64_encode(force_bytes(self.user.pk))
|
||||
site = Site.objects.first()
|
||||
message = loader.render_to_string('registration/mails/email_validation_email.txt',
|
||||
{
|
||||
'user': self.user,
|
||||
'domain': site.domain,
|
||||
'token': token,
|
||||
'uid': uid,
|
||||
})
|
||||
html = loader.render_to_string('registration/mails/email_validation_email.html',
|
||||
{
|
||||
'user': self.user,
|
||||
'domain': site.domain,
|
||||
'token': token,
|
||||
'uid': uid,
|
||||
})
|
||||
self.user.email_user(subject, message, html_message=html)
|
||||
|
||||
@property
|
||||
def type(self): # pragma: no cover
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def form_class(self): # pragma: no cover
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def participates(self):
|
||||
return isinstance(self, ParticipantRegistration)
|
||||
|
||||
@property
|
||||
def is_admin(self):
|
||||
return isinstance(self, VolunteerRegistration) and self.admin or self.user.is_superuser
|
||||
|
||||
@property
|
||||
def is_volunteer(self):
|
||||
return isinstance(self, VolunteerRegistration)
|
||||
|
||||
@property
|
||||
def matrix_username(self):
|
||||
return f"tfjm_{self.user.pk}"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse_lazy("registration:user_detail", args=(self.user_id,))
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.user.first_name} {self.user.last_name}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("registration")
|
||||
verbose_name_plural = _("registrations")
|
||||
|
||||
|
||||
def get_random_photo_filename(instance, filename):
|
||||
return "authorization/photo/" + get_random_string(64)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class ParticipantRegistration(Registration):
|
||||
team = models.ForeignKey(
|
||||
"participation.Team",
|
||||
related_name="participants",
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None,
|
||||
verbose_name=_("team"),
|
||||
)
|
||||
|
||||
gender = models.CharField(
|
||||
max_length=6,
|
||||
verbose_name=_("gender"),
|
||||
choices=[
|
||||
("female", _("Female")),
|
||||
("male", _("Male")),
|
||||
("other", _("Other")),
|
||||
],
|
||||
default="other",
|
||||
)
|
||||
|
||||
address = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("address"),
|
||||
)
|
||||
|
||||
zip_code = models.PositiveIntegerField(
|
||||
verbose_name=_("zip code"),
|
||||
validators=[MinValueValidator(1000), MaxValueValidator(99999)],
|
||||
)
|
||||
|
||||
city = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("city"),
|
||||
)
|
||||
|
||||
phone_number = PhoneNumberField(
|
||||
verbose_name=_("phone number"),
|
||||
blank=True,
|
||||
)
|
||||
|
||||
health_issues = models.TextField(
|
||||
verbose_name=_("health issues"),
|
||||
blank=True,
|
||||
help_text=_("You can indicate here your allergies or anything that is important to know for organizers"),
|
||||
)
|
||||
|
||||
photo_authorization = models.FileField(
|
||||
verbose_name=_("photo authorization"),
|
||||
upload_to=get_random_photo_filename,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
@property
|
||||
def under_18(self):
|
||||
if isinstance(self, CoachRegistration):
|
||||
return False # In normal case
|
||||
important_date = timezone.now().date()
|
||||
if self.team and self.team.participation.tournament:
|
||||
important_date = self.team.participation.tournament.date_start
|
||||
if self.team.participation.final:
|
||||
from participation.models import Tournament
|
||||
important_date = Tournament.final_tournament().date_start
|
||||
return (important_date - self.birth_date).days < 18 * 365.24
|
||||
|
||||
@property
|
||||
def type(self): # pragma: no cover
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def form_class(self): # pragma: no cover
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class StudentRegistration(ParticipantRegistration):
|
||||
"""
|
||||
Specific registration for students.
|
||||
They have a team, a student class and a school.
|
||||
"""
|
||||
birth_date = models.DateField(
|
||||
verbose_name=_("birth date"),
|
||||
default=date.today,
|
||||
)
|
||||
|
||||
student_class = models.IntegerField(
|
||||
choices=[
|
||||
(12, _("12th grade")),
|
||||
(11, _("11th grade")),
|
||||
(10, _("10th grade or lower")),
|
||||
],
|
||||
verbose_name=_("student class"),
|
||||
)
|
||||
|
||||
school = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("school"),
|
||||
)
|
||||
|
||||
responsible_name = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("responsible name"),
|
||||
default="",
|
||||
)
|
||||
|
||||
responsible_phone = PhoneNumberField(
|
||||
verbose_name=_("responsible phone number"),
|
||||
default="",
|
||||
)
|
||||
|
||||
responsible_email = models.EmailField(
|
||||
verbose_name=_("responsible email address"),
|
||||
default="",
|
||||
)
|
||||
|
||||
parental_authorization = models.FileField(
|
||||
verbose_name=_("parental authorization"),
|
||||
upload_to=get_random_parental_filename,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
health_sheet = models.FileField(
|
||||
verbose_name=_("health sheet"),
|
||||
upload_to=get_random_health_filename,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
vaccine_sheet = models.FileField(
|
||||
verbose_name=_("vaccine sheet"),
|
||||
upload_to=get_random_vaccine_filename,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return _("student")
|
||||
|
||||
@property
|
||||
def form_class(self):
|
||||
from registration.forms import StudentRegistrationForm
|
||||
return StudentRegistrationForm
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("student registration")
|
||||
verbose_name_plural = _("student registrations")
|
||||
|
||||
|
||||
class CoachRegistration(ParticipantRegistration):
|
||||
"""
|
||||
Specific registration for coaches.
|
||||
They have a team and a professional activity.
|
||||
"""
|
||||
professional_activity = models.TextField(
|
||||
verbose_name=_("professional activity"),
|
||||
)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return _("coach")
|
||||
|
||||
@property
|
||||
def form_class(self):
|
||||
from registration.forms import CoachRegistrationForm
|
||||
return CoachRegistrationForm
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("coach registration")
|
||||
verbose_name_plural = _("coach registrations")
|
||||
|
||||
|
||||
class VolunteerRegistration(Registration):
|
||||
"""
|
||||
Specific registration for organizers and juries.
|
||||
"""
|
||||
professional_activity = models.TextField(
|
||||
verbose_name=_("professional activity"),
|
||||
)
|
||||
|
||||
admin = models.BooleanField(
|
||||
verbose_name=_("administrator"),
|
||||
help_text=_("An administrator has all rights. Please don't give this right to all juries and volunteers."),
|
||||
default=False,
|
||||
)
|
||||
|
||||
@property
|
||||
def interesting_tournaments(self) -> set:
|
||||
return set(self.organized_tournaments.all()).union(map(lambda pool: pool.tournament, self.jury_in.all()))
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return _('admin') if self.is_admin else _('volunteer')
|
||||
|
||||
@property
|
||||
def form_class(self):
|
||||
from registration.forms import VolunteerRegistrationForm
|
||||
return VolunteerRegistrationForm
|
||||
|
||||
|
||||
def get_scholarship_filename(instance, filename):
|
||||
return f"authorization/scholarship/scholarship_{instance.registration.pk}"
|
||||
|
||||
|
||||
class Payment(models.Model):
|
||||
registration = models.OneToOneField(
|
||||
ParticipantRegistration,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="payment",
|
||||
verbose_name=_("registration"),
|
||||
)
|
||||
|
||||
type = models.CharField(
|
||||
verbose_name=_("type"),
|
||||
max_length=16,
|
||||
choices=[
|
||||
('', _("No payment")),
|
||||
('helloasso', "Hello Asso"),
|
||||
('scholarship', _("Scholarship")),
|
||||
('bank_transfer', _("Bank transfer")),
|
||||
('other', _("Other (please indicate)")),
|
||||
('free', _("The tournament is free")),
|
||||
],
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
scholarship_file = models.FileField(
|
||||
verbose_name=_("scholarship file"),
|
||||
help_text=_("only if you have a scholarship."),
|
||||
upload_to=get_scholarship_filename,
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
additional_information = models.TextField(
|
||||
verbose_name=_("additional information"),
|
||||
help_text=_("To help us to find your payment."),
|
||||
blank=True,
|
||||
default="",
|
||||
)
|
||||
|
||||
valid = models.BooleanField(
|
||||
verbose_name=_("valid"),
|
||||
null=True,
|
||||
default=False,
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse_lazy("registration:user_detail", args=(self.registration.user.id,))
|
||||
|
||||
def __str__(self):
|
||||
return _("Payment of {registration}").format(registration=self.registration)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("payment")
|
||||
verbose_name_plural = _("payments")
|
Reference in New Issue
Block a user