mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-04-01 19:31:11 +00:00
Add survey notification in the menu
This commit is contained in:
parent
702c8d8c9e
commit
97eea3b11a
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.db.models.signals import post_save, pre_save
|
from django.db.models.signals import post_save, pre_save
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class ParticipationConfig(AppConfig):
|
class ParticipationConfig(AppConfig):
|
||||||
@ -10,6 +11,7 @@ class ParticipationConfig(AppConfig):
|
|||||||
The participation app contains the data about the teams, solutions, ...
|
The participation app contains the data about the teams, solutions, ...
|
||||||
"""
|
"""
|
||||||
name = 'participation'
|
name = 'participation'
|
||||||
|
verbose_name = _("participations")
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
from participation import signals
|
from participation import signals
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
import math
|
import math
|
||||||
import os
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
||||||
from django.db import models
|
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.template.defaultfilters import slugify
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils import timezone, translation
|
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)
|
return _("Participation of the team {name} ({trigram})").format(name=self.team.name, trigram=self.team.trigram)
|
||||||
|
|
||||||
def important_informations(self):
|
def important_informations(self):
|
||||||
|
from survey.models import Survey
|
||||||
|
|
||||||
informations = []
|
informations = []
|
||||||
|
|
||||||
missing_payments = Payment.objects.filter(registrations__in=self.team.participants.all(), valid=False)
|
missing_payments = Payment.objects.filter(registrations__in=self.team.participants.all(), valid=False)
|
||||||
@ -865,6 +866,19 @@ class Participation(models.Model):
|
|||||||
'content': content,
|
'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:
|
if self.tournament:
|
||||||
informations.extend(self.informations_for_tournament(self.tournament))
|
informations.extend(self.informations_for_tournament(self.tournament))
|
||||||
if self.final:
|
if self.final:
|
||||||
|
@ -234,7 +234,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
|
|||||||
mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
|
mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
|
||||||
mail_html = render_to_string("participation/mails/request_validation.html", 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,
|
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)
|
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_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)
|
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,
|
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:
|
elif "invalidate" in self.request.POST:
|
||||||
self.object.participation.valid = None
|
self.object.participation.valid = None
|
||||||
self.object.participation.save()
|
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_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)
|
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,
|
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:
|
else:
|
||||||
form.add_error(None, _("You must specify if you validate the registration or not."))
|
form.add_error(None, _("You must specify if you validate the registration or not."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.db.models.signals import post_save, pre_save
|
from django.db.models.signals import post_save, pre_save
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class RegistrationConfig(AppConfig):
|
class RegistrationConfig(AppConfig):
|
||||||
@ -10,6 +11,7 @@ class RegistrationConfig(AppConfig):
|
|||||||
Registration app contains the detail about users only.
|
Registration app contains the detail about users only.
|
||||||
"""
|
"""
|
||||||
name = 'registration'
|
name = 'registration'
|
||||||
|
verbose_name = _("registrations")
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
from registration import signals
|
from registration import signals
|
||||||
|
@ -8,6 +8,7 @@ from django.contrib.sites.models import Site
|
|||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import timezone, translation
|
from django.utils import timezone, translation
|
||||||
@ -260,6 +261,8 @@ class ParticipantRegistration(Registration):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def registration_informations(self):
|
def registration_informations(self):
|
||||||
|
from survey.models import Survey
|
||||||
|
|
||||||
informations = []
|
informations = []
|
||||||
if not self.team:
|
if not self.team:
|
||||||
text = _("You are not in a team. You can <a href=\"{create_url}\">create one</a> "
|
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,
|
'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())
|
informations.extend(self.team.important_informations())
|
||||||
|
|
||||||
return informations
|
return informations
|
||||||
@ -315,19 +332,19 @@ class ParticipantRegistration(Registration):
|
|||||||
tournament = Tournament.final_tournament()
|
tournament = Tournament.final_tournament()
|
||||||
payment = self.payments.filter(final=True).first() if self.is_student else None
|
payment = self.payments.filter(final=True).first() if self.is_student else None
|
||||||
message = loader.render_to_string('registration/mails/final_selection.txt',
|
message = loader.render_to_string('registration/mails/final_selection.txt',
|
||||||
{
|
{
|
||||||
'user': self.user,
|
'user': self.user,
|
||||||
'domain': site.domain,
|
'domain': site.domain,
|
||||||
'tournament': tournament,
|
'tournament': tournament,
|
||||||
'payment': payment,
|
'payment': payment,
|
||||||
})
|
})
|
||||||
html = loader.render_to_string('registration/mails/final_selection.html',
|
html = loader.render_to_string('registration/mails/final_selection.html',
|
||||||
{
|
{
|
||||||
'user': self.user,
|
'user': self.user,
|
||||||
'domain': site.domain,
|
'domain': site.domain,
|
||||||
'tournament': tournament,
|
'tournament': tournament,
|
||||||
'payment': payment,
|
'payment': payment,
|
||||||
})
|
})
|
||||||
self.user.email_user(subject, message, html_message=html)
|
self.user.email_user(subject, message, html_message=html)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -807,9 +824,9 @@ class Payment(models.Model):
|
|||||||
site = Site.objects.first()
|
site = Site.objects.first()
|
||||||
for registration in self.registrations.all():
|
for registration in self.registrations.all():
|
||||||
message = loader.render_to_string('registration/mails/payment_reminder.txt',
|
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',
|
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)
|
registration.user.email_user(subject, message, html_message=html)
|
||||||
|
|
||||||
def send_helloasso_payment_confirmation_mail(self):
|
def send_helloasso_payment_confirmation_mail(self):
|
||||||
@ -818,18 +835,18 @@ class Payment(models.Model):
|
|||||||
site = Site.objects.first()
|
site = Site.objects.first()
|
||||||
for registration in self.registrations.all():
|
for registration in self.registrations.all():
|
||||||
message = loader.render_to_string('registration/mails/payment_confirmation.txt',
|
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',
|
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)
|
registration.user.email_user(subject, message, html_message=html)
|
||||||
|
|
||||||
payer = self.get_checkout_intent()['order']['payer']
|
payer = self.get_checkout_intent()['order']['payer']
|
||||||
payer_name = f"{payer['firstName']} {payer['lastName']}"
|
payer_name = f"{payer['firstName']} {payer['lastName']}"
|
||||||
if not self.registrations.filter(user__email=payer['email']).exists():
|
if not self.registrations.filter(user__email=payer['email']).exists():
|
||||||
message = loader.render_to_string('registration/mails/payment_confirmation.txt',
|
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',
|
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)
|
send_mail(subject, message, None, [payer['email']], html_message=html)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
|
@ -145,9 +145,9 @@ class AddOrganizerView(VolunteerMixin, CreateView):
|
|||||||
password=password,
|
password=password,
|
||||||
domain=site.domain))
|
domain=site.domain))
|
||||||
html = render_to_string('registration/mails/add_organizer.html', dict(user=registration.user,
|
html = render_to_string('registration/mails/add_organizer.html', dict(user=registration.user,
|
||||||
inviter=self.request.user,
|
inviter=self.request.user,
|
||||||
password=password,
|
password=password,
|
||||||
domain=site.domain))
|
domain=site.domain))
|
||||||
registration.user.email_user(subject, message, html_message=html)
|
registration.user.email_user(subject, message, html_message=html)
|
||||||
|
|
||||||
if registration.is_admin:
|
if registration.is_admin:
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
# Copyright (C) 2025 by Animath
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class SurveyConfig(AppConfig):
|
class SurveyConfig(AppConfig):
|
||||||
default_auto_field = "django.db.models.BigAutoField"
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
name = "survey"
|
name = "survey"
|
||||||
|
verbose_name = _("surveys")
|
||||||
|
@ -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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -45,18 +45,21 @@ class Survey(models.Model):
|
|||||||
blank=True,
|
blank=True,
|
||||||
default=None,
|
default=None,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
|
related_name="surveys",
|
||||||
verbose_name=_("tournament restriction"),
|
verbose_name=_("tournament restriction"),
|
||||||
help_text=_("When this field is filled, the survey participants will be restricted to this tournament members."),
|
help_text=_("When this field is filled, the survey participants will be restricted to this tournament members."),
|
||||||
)
|
)
|
||||||
|
|
||||||
completed_registrations = models.ManyToManyField(
|
completed_registrations = models.ManyToManyField(
|
||||||
ParticipantRegistration,
|
ParticipantRegistration,
|
||||||
|
blank=True,
|
||||||
related_name="completed_surveys",
|
related_name="completed_surveys",
|
||||||
verbose_name=_("participants that completed the survey"),
|
verbose_name=_("participants that completed the survey"),
|
||||||
)
|
)
|
||||||
|
|
||||||
completed_teams = models.ManyToManyField(
|
completed_teams = models.ManyToManyField(
|
||||||
Team,
|
Team,
|
||||||
|
blank=True,
|
||||||
related_name="completed_surveys",
|
related_name="completed_surveys",
|
||||||
verbose_name=_("teams that completed the survey"),
|
verbose_name=_("teams that completed the survey"),
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# Copyright (C) 2020 by Animath
|
# Copyright (C) 2020 by Animath
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
_client = None
|
_client = None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user