1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-03-31 00:51:13 +00:00

Add survey notification in the menu

This commit is contained in:
Emmy D'Anello 2025-03-19 23:56:53 +01:00
parent 702c8d8c9e
commit 97eea3b11a
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
11 changed files with 450 additions and 339 deletions

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
from django.apps import AppConfig
from django.db.models.signals import post_save, pre_save
from django.utils.translation import gettext_lazy as _
class ParticipationConfig(AppConfig):
@ -10,6 +11,7 @@ class ParticipationConfig(AppConfig):
The participation app contains the data about the teams, solutions, ...
"""
name = 'participation'
verbose_name = _("participations")
def ready(self):
from participation import signals

View File

@ -3,13 +3,12 @@
from datetime import date, timedelta
import math
import os
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import models
from django.db.models import Index
from django.db.models import Index, Q
from django.template.defaultfilters import slugify
from django.urls import reverse_lazy
from django.utils import timezone, translation
@ -847,6 +846,8 @@ class Participation(models.Model):
return _("Participation of the team {name} ({trigram})").format(name=self.team.name, trigram=self.team.trigram)
def important_informations(self):
from survey.models import Survey
informations = []
missing_payments = Payment.objects.filter(registrations__in=self.team.participants.all(), valid=False)
@ -865,6 +866,19 @@ class Participation(models.Model):
'content': content,
})
if self.valid:
for survey in Survey.objects.filter(Q(tournament__isnull=True) | Q(tournament=self.tournament), Q(invite_team=True),
~Q(completed_teams=self.team)).all():
text = _("Please answer to the survey \"{name}\". You can go to the survey on <a href=\"{survey_link}\">that link</a>, "
"using the token code you received by mail.")
content = format_lazy(text, name=survey.name, survey_link=f"{settings.LIMESURVEY_URL}/index.php/{survey.survey_id}")
informations.append({
'title': _("Required answer to survey"),
'type': "warning",
'priority': 12,
'content': content
})
if self.tournament:
informations.extend(self.informations_for_tournament(self.tournament))
if self.final:

View File

@ -234,7 +234,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
mail_html = render_to_string("participation/mails/request_validation.html", mail_context)
send_mail(f"[{settings.APP_NAME}] {_('Team validation')}", mail_plain, settings.DEFAULT_FROM_EMAIL,
[self.object.participation.tournament.organizers_email], html_message=mail_html)
[self.object.participation.tournament.organizers_email], html_message=mail_html)
return super().form_valid(form)
@ -270,7 +270,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
mail_plain = render_to_string("participation/mails/team_validated.txt", mail_context_plain)
mail_html = render_to_string("participation/mails/team_validated.html", mail_context_html)
registration.user.email_user(f"[{settings.APP_NAME}] {_('Team validated')}", mail_plain,
html_message=mail_html)
html_message=mail_html)
elif "invalidate" in self.request.POST:
self.object.participation.valid = None
self.object.participation.save()
@ -280,7 +280,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
mail_plain = render_to_string("participation/mails/team_not_validated.txt", mail_context_plain)
mail_html = render_to_string("participation/mails/team_not_validated.html", mail_context_html)
send_mail(f"[{settings.APP_NAME}] {_('Team not validated')}", mail_plain,
None, [self.object.email], html_message=mail_html)
None, [self.object.email], html_message=mail_html)
else:
form.add_error(None, _("You must specify if you validate the registration or not."))
return self.form_invalid(form)

View File

@ -3,6 +3,7 @@
from django.apps import AppConfig
from django.db.models.signals import post_save, pre_save
from django.utils.translation import gettext_lazy as _
class RegistrationConfig(AppConfig):
@ -10,6 +11,7 @@ class RegistrationConfig(AppConfig):
Registration app contains the detail about users only.
"""
name = 'registration'
verbose_name = _("registrations")
def ready(self):
from registration import signals

View File

@ -8,6 +8,7 @@ from django.contrib.sites.models import Site
from django.core.mail import send_mail
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Q
from django.template import loader
from django.urls import reverse, reverse_lazy
from django.utils import timezone, translation
@ -260,6 +261,8 @@ class ParticipantRegistration(Registration):
raise NotImplementedError
def registration_informations(self):
from survey.models import Survey
informations = []
if not self.team:
text = _("You are not in a team. You can <a href=\"{create_url}\">create one</a> "
@ -300,6 +303,20 @@ class ParticipantRegistration(Registration):
'content': content,
})
if self.team.participation.valid:
for survey in Survey.objects.filter(Q(tournament__isnull=True) | Q(tournament=self.team.participation.tournament),
Q(invite_team=False), Q(invite_coaches=True) | Q(invite_coaches=self.is_coach),
~Q(completed_registrations=self)):
text = _("Please answer to the survey \"{name}\". You can go to the survey on <a href=\"{survey_link}\">that link</a>, "
"using the token code you received by mail.")
content = format_lazy(text, name=survey.name, survey_link=f"{settings.LIMESURVEY_URL}/index.php/{survey.survey_id}")
informations.append({
'title': _("Required answer to survey"),
'type': "warning",
'priority': 12,
'content': content
})
informations.extend(self.team.important_informations())
return informations
@ -315,19 +332,19 @@ class ParticipantRegistration(Registration):
tournament = Tournament.final_tournament()
payment = self.payments.filter(final=True).first() if self.is_student else None
message = loader.render_to_string('registration/mails/final_selection.txt',
{
'user': self.user,
'domain': site.domain,
'tournament': tournament,
'payment': payment,
})
{
'user': self.user,
'domain': site.domain,
'tournament': tournament,
'payment': payment,
})
html = loader.render_to_string('registration/mails/final_selection.html',
{
'user': self.user,
'domain': site.domain,
'tournament': tournament,
'payment': payment,
})
{
'user': self.user,
'domain': site.domain,
'tournament': tournament,
'payment': payment,
})
self.user.email_user(subject, message, html_message=html)
class Meta:
@ -807,9 +824,9 @@ class Payment(models.Model):
site = Site.objects.first()
for registration in self.registrations.all():
message = loader.render_to_string('registration/mails/payment_reminder.txt',
dict(registration=registration, payment=self, domain=site.domain))
dict(registration=registration, payment=self, domain=site.domain))
html = loader.render_to_string('registration/mails/payment_reminder.html',
dict(registration=registration, payment=self, domain=site.domain))
dict(registration=registration, payment=self, domain=site.domain))
registration.user.email_user(subject, message, html_message=html)
def send_helloasso_payment_confirmation_mail(self):
@ -818,18 +835,18 @@ class Payment(models.Model):
site = Site.objects.first()
for registration in self.registrations.all():
message = loader.render_to_string('registration/mails/payment_confirmation.txt',
dict(registration=registration, payment=self, domain=site.domain))
dict(registration=registration, payment=self, domain=site.domain))
html = loader.render_to_string('registration/mails/payment_confirmation.html',
dict(registration=registration, payment=self, domain=site.domain))
dict(registration=registration, payment=self, domain=site.domain))
registration.user.email_user(subject, message, html_message=html)
payer = self.get_checkout_intent()['order']['payer']
payer_name = f"{payer['firstName']} {payer['lastName']}"
if not self.registrations.filter(user__email=payer['email']).exists():
message = loader.render_to_string('registration/mails/payment_confirmation.txt',
dict(registration=payer_name, payment=self, domain=site.domain))
dict(registration=payer_name, payment=self, domain=site.domain))
html = loader.render_to_string('registration/mails/payment_confirmation.html',
dict(registration=payer_name, payment=self, domain=site.domain))
dict(registration=payer_name, payment=self, domain=site.domain))
send_mail(subject, message, None, [payer['email']], html_message=html)
def get_absolute_url(self):

View File

@ -145,9 +145,9 @@ class AddOrganizerView(VolunteerMixin, CreateView):
password=password,
domain=site.domain))
html = render_to_string('registration/mails/add_organizer.html', dict(user=registration.user,
inviter=self.request.user,
password=password,
domain=site.domain))
inviter=self.request.user,
password=password,
domain=site.domain))
registration.user.email_user(subject, message, html_message=html)
if registration.is_admin:

View File

@ -1,6 +1,11 @@
# Copyright (C) 2025 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class SurveyConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "survey"
verbose_name = _("surveys")

View File

@ -0,0 +1,53 @@
# Generated by Django 5.1.5 on 2025-03-19 22:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"participation",
"0023_tournament_unified_registration",
),
("registration", "0014_participantregistration_country"),
("survey", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="survey",
name="completed_registrations",
field=models.ManyToManyField(
blank=True,
related_name="completed_surveys",
to="registration.participantregistration",
verbose_name="participants that completed the survey",
),
),
migrations.AlterField(
model_name="survey",
name="completed_teams",
field=models.ManyToManyField(
blank=True,
related_name="completed_surveys",
to="participation.team",
verbose_name="teams that completed the survey",
),
),
migrations.AlterField(
model_name="survey",
name="tournament",
field=models.ForeignKey(
blank=True,
default=None,
help_text="When this field is filled, the survey participants will be restricted to this tournament members.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="surveys",
to="participation.tournament",
verbose_name="tournament restriction",
),
),
]

View File

@ -45,18 +45,21 @@ class Survey(models.Model):
blank=True,
default=None,
on_delete=models.SET_NULL,
related_name="surveys",
verbose_name=_("tournament restriction"),
help_text=_("When this field is filled, the survey participants will be restricted to this tournament members."),
)
completed_registrations = models.ManyToManyField(
ParticipantRegistration,
blank=True,
related_name="completed_surveys",
verbose_name=_("participants that completed the survey"),
)
completed_teams = models.ManyToManyField(
Team,
blank=True,
related_name="completed_surveys",
verbose_name=_("teams that completed the survey"),
)

View File

@ -1,8 +1,6 @@
# Copyright (C) 2020 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later
import os
from django.conf import settings
_client = None