1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-11-09 10:13:24 +01:00

Add distinction between scientific coach and accompanying coach

This commit is contained in:
Maxime JUST
2025-11-07 17:24:53 +01:00
parent 8af11cd56f
commit 7ae98cd64d
9 changed files with 528 additions and 437 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -71,12 +71,20 @@ class Team(models.Model):
def coaches(self): def coaches(self):
return self.participants.filter(coachregistration__isnull=False) return self.participants.filter(coachregistration__isnull=False)
@property
def scientific_coaches(self):
return self.participants.filter(coachregistration__isnull=False, coachregistration__is_scientific_coach=True)
@property
def accompanying_coaches(self):
return self.participants.filter(coachregistration__isnull=False, coachregistration__is_accompanying_coach=True)
def can_validate(self): def can_validate(self):
if any(not r.email_confirmed for r in self.participants.all()): if any(not r.email_confirmed for r in self.participants.all()):
return False return False
if self.students.count() < 4: if self.students.count() < 4:
return False return False
if not self.coaches.exists(): if not self.scientific_coaches.exists():
return False return False
if not self.participation.tournament: if not self.participation.tournament:
return False return False
@@ -212,6 +220,7 @@ class Team(models.Model):
""" """
return f"equipe-{slugify(self.trigram)}@{settings.SYMPA_HOST}" return f"equipe-{slugify(self.trigram)}@{settings.SYMPA_HOST}"
def create_mailing_list(self): def create_mailing_list(self):
""" """
Create a new Sympa mailing list to contact the team. Create a new Sympa mailing list to contact the team.

View File

@@ -22,9 +22,18 @@
<dt class="col-sm-6 text-sm-end">{% trans "Access code:" %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "Access code:" %}</dt>
<dd class="col-sm-6">{{ team.access_code }}</dd> <dd class="col-sm-6">{{ team.access_code }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans "Coaches:" %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "Scientific coaches:" %}</dt>
<dd class="col-sm-6"> <dd class="col-sm-6">
{% for coach in team.coaches.all %} {% for coach in team.scientific_coaches.all %}
<a href="{% url "registration:user_detail" pk=coach.user.pk %}">{{ coach }}</a>{% if not forloop.last %},{% endif %}
{% empty %}
{% trans "any" %}
{% endfor %}
</dd>
<dt class="col-sm-6 text-sm-end">{% trans "Accompanying coaches:" %}</dt>
<dd class="col-sm-6">
{% for coach in team.accompanying_coaches.all %}
<a href="{% url "registration:user_detail" pk=coach.user.pk %}">{{ coach }}</a>{% if not forloop.last %},{% endif %} <a href="{% url "registration:user_detail" pk=coach.user.pk %}">{{ coach }}</a>{% if not forloop.last %},{% endif %}
{% empty %} {% empty %}
{% trans "any" %} {% trans "any" %}

View File

@@ -285,6 +285,7 @@ class TestStudentParticipation(TestCase):
self.coach.registration.vaccine_sheet = "authorization/vaccine/coach" self.coach.registration.vaccine_sheet = "authorization/vaccine/coach"
self.coach.registration.photo_authorization = "authorization/photo/coach" self.coach.registration.photo_authorization = "authorization/photo/coach"
self.coach.registration.email_confirmed = True self.coach.registration.email_confirmed = True
self.coach.registration.is_scientific_coach = True
self.coach.registration.save() self.coach.registration.save()
self.client.force_login(self.superuser) self.client.force_login(self.superuser)

View File

@@ -61,7 +61,7 @@ class RegistrationAdmin(PolymorphicParentModelAdmin):
@admin.register(ParticipantRegistration) @admin.register(ParticipantRegistration)
class ParticipantRegistrationAdmin(PolymorphicChildModelAdmin): class ParticipantRegistrationAdmin(PolymorphicChildModelAdmin):
list_display = ('user', 'first_name', 'last_name', 'type', 'team', 'email_confirmed',) list_display = ('user', 'first_name', 'last_name', 'type', 'team', 'email_confirmed')
list_filter = ('email_confirmed',) list_filter = ('email_confirmed',)
search_fields = ('user__first_name', 'user__last_name', 'user__email',) search_fields = ('user__first_name', 'user__last_name', 'user__email',)
autocomplete_fields = ('user', 'team',) autocomplete_fields = ('user', 'team',)
@@ -93,7 +93,7 @@ class StudentRegistrationAdmin(PolymorphicChildModelAdmin):
@admin.register(CoachRegistration) @admin.register(CoachRegistration)
class CoachRegistrationAdmin(PolymorphicChildModelAdmin): class CoachRegistrationAdmin(PolymorphicChildModelAdmin):
list_display = ('user', 'first_name', 'last_name', 'team', 'email_confirmed',) list_display = ('user', 'first_name', 'last_name', 'team', 'email_confirmed', 'is_accompanying_coach', 'is_scientific_coach')
list_filter = ('email_confirmed',) list_filter = ('email_confirmed',)
search_fields = ('user__first_name', 'user__last_name', 'user__email',) search_fields = ('user__first_name', 'user__last_name', 'user__email',)
autocomplete_fields = ('user', 'team',) autocomplete_fields = ('user', 'team',)

View File

@@ -251,6 +251,9 @@ class CoachRegistrationForm(forms.ModelForm):
""" """
A coach can tell its professional activity. A coach can tell its professional activity.
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if not settings.SUGGEST_ANIMATH: if not settings.SUGGEST_ANIMATH:
@@ -258,9 +261,9 @@ class CoachRegistrationForm(forms.ModelForm):
class Meta: class Meta:
model = CoachRegistration model = CoachRegistration
fields = ('team', 'gender', 'address', 'zip_code', 'city', 'country', 'phone_number', fields = ('team', 'is_scientific_coach', 'is_accompanying_coach', 'gender', 'address', 'zip_code', 'city', 'country', 'phone_number',
'last_degree', 'professional_activity', 'health_issues', 'housing_constraints', 'last_degree', 'professional_activity', 'health_issues', 'housing_constraints',
'give_contact_to_animath', 'email_confirmed',) 'give_contact_to_animath', 'email_confirmed')
class VolunteerRegistrationForm(forms.ModelForm): class VolunteerRegistrationForm(forms.ModelForm):

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.2.8 on 2025-11-06 18:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('registration', '0015_alter_participantregistration_gender'),
]
operations = [
migrations.AddField(
model_name='coachregistration',
name='is_accompanying_coach',
field=models.BooleanField(default=False, help_text='Accompanies the team during the weekend and stays for the entire tournament.', verbose_name='Accompanying coach'),
),
migrations.AddField(
model_name='coachregistration',
name='is_scientific_coach',
field=models.BooleanField(default=False, help_text='Provides scientific guidance: methodology, content review, and project mentoring during the preparation phase. <a href="https://tfjm.org/wp-content/uploads/2024/01/note____l_intention_des_encadrants.pdf" target="_blank" rel="noopener">see practical sheet</a>.', verbose_name='Scientific coach'),
),
]

View File

@@ -22,6 +22,7 @@ from phonenumber_field.modelfields import PhoneNumberField
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
from tfjm import helloasso from tfjm import helloasso
from tfjm.tokens import email_validation_token from tfjm.tokens import email_validation_token
from django.utils.html import format_html
class Registration(PolymorphicModel): class Registration(PolymorphicModel):
@@ -527,6 +528,23 @@ class CoachRegistration(ParticipantRegistration):
verbose_name=_("professional activity"), verbose_name=_("professional activity"),
) )
is_scientific_coach = models.BooleanField(
default=False,
verbose_name=_("Scientific coach"),
help_text=format_html(
'{} <a href="{}" target="_blank" rel="noopener">{}</a>.',
_("Provides scientific guidance: methodology, content review, and project mentoring during the preparation phase."),
"https://tfjm.org/wp-content/uploads/2024/01/note____l_intention_des_encadrants.pdf",
_("see practical sheet"),
),
)
is_accompanying_coach = models.BooleanField(
default=False,
verbose_name=_("Accompanying coach"),
help_text=_("Accompanies the team during the weekend and stays for the entire tournament."),
)
@property @property
def type(self): def type(self):
return _("coach") return _("coach")

View File

@@ -151,6 +151,12 @@
<dd class="col-sm-6"><a href="mailto:{{ email }}">{{ email }}</a></dd> <dd class="col-sm-6"><a href="mailto:{{ email }}">{{ email }}</a></dd>
{% endwith %} {% endwith %}
{% elif user_object.registration.coachregistration %} {% elif user_object.registration.coachregistration %}
<dt class="col-sm-6 text-sm-end">{% trans "Scientific coach:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.is_scientific_coach|yesno }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans "Accompanying coach:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.is_accompanying_coach|yesno }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans "Most recent degree:" %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "Most recent degree:" %}</dt>
<dd class="col-sm-6">{{ user_object.registration.last_degree }}</dd> <dd class="col-sm-6">{{ user_object.registration.last_degree }}</dd>