# Copyright (C) 2025 by Animath # SPDX-License-Identifier: GPL-3.0-or-later from citric import Client from django.conf import settings from django.db import models from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from participation.models import Team, Tournament from registration.models import ParticipantRegistration, StudentRegistration class Survey(models.Model): """ Ce modèle représente un sondage LimeSurvey afin de faciliter l'import des participant⋅es au sondage et d'effectuer le suivi. """ survey_id = models.IntegerField( primary_key=True, verbose_name=_("survey identifier"), help_text=_("The numeric identifier of the Limesurvey."), ) name = models.CharField( max_length=255, verbose_name=_("display name"), ) invite_team = models.BooleanField( default=False, verbose_name=_("invite whole team"), help_text=_("When this field is checked, teams will get only one survey invitation instead of one per person."), ) invite_coaches = models.BooleanField( default=True, verbose_name=_("invite coaches"), help_text=_("When this field is checked, coaches will also be invited in the survey. No effect when the whole team is invited."), ) tournament = models.ForeignKey( Tournament, null=True, blank=True, default=None, on_delete=models.SET_NULL, 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, related_name="completed_surveys", verbose_name=_("participants that completed the survey"), ) completed_teams = models.ManyToManyField( Team, related_name="completed_surveys", verbose_name=_("teams that completed the survey"), ) @property def participants(self): if self.invite_team: teams = Team.objects.filter(participation__valid=True) if self.tournament: teams = teams.filter(participation__tournament=self.tournament) return teams.all() else: if self.invite_coaches: registrations = ParticipantRegistration.objects.filter(team__participation__valid=True) else: registrations = StudentRegistration.objects.filter(team__participation__valid=True) if self.tournament: registrations = registrations.filter(team__participation__tournament=self.tournament) return registrations.all() @property def completed(self): if self.invite_team: return self.completed_teams else: return self.completed_registrations def get_absolute_url(self): return reverse_lazy("survey:survey_detail", args=(self.survey_id,)) def generate_participants_data(self): participants_data = [] if self.invite_team: for team in self.participants: participant_data = {"firstname": team.name, "lastname": f"(équipe {team.trigram})", "email": team.email} participants_data.append(participant_data) else: for reg in self.participants: participant_data = {"firstname": reg.user.first_name, "lastname": reg.user.last_name, "email": reg.user.email} participants_data.append(participant_data) return participants_data def invite_all(self): participants_data = self.generate_participants_data() with Client(f"{settings.LIMESURVEY_URL}/index.php/admin/remotecontrol", settings.LIMESURVEY_USER, settings.LIMESURVEY_PASSWORD) as client: try: current_participants = client.list_participants(self.survey_id, limit=10000) except: current_participants = [] current_participants_email = set(participant['participant_info']['email'] for participant in current_participants) participants_data = [participant_data for participant_data in participants_data if participant_data['email'] not in current_participants_email] try: client.activate_tokens(self.survey_id) except: pass new_participants = client.add_participants(self.survey_id, participant_data=participants_data) if new_participants: client.invite_participants(self.survey_id, token_ids=[participant['tid'] for participant in new_participants]) return new_participants def fetch_completion_data(self): with Client(f"{settings.LIMESURVEY_URL}/index.php/admin/remotecontrol", settings.LIMESURVEY_USER, settings.LIMESURVEY_PASSWORD) as client: participants = client.list_participants(self.survey_id, limit=10000, attributes=['completed']) if self.invite_team: team_names = [participant['participant_info']['firstname'] for participant in participants if participant['completed'] != 'N'] self.completed_teams.set(list(Team.objects.filter(name__in=team_names).values_list('id', flat=True))) else: mails = [participant['participant_info']['email'] for participant in participants if participant['completed'] != 'N'] self.completed_registrations.set(list(ParticipantRegistration.objects.filter(user__email__in=mails).values_list('id', flat=True))) self.save() class Meta: verbose_name = _("survey") verbose_name_plural = _("surveys")