mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-10-31 22:24:30 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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,
 | |
|         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"),
 | |
|     )
 | |
| 
 | |
|     @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.order_by('participation__tournament__name', 'trigram').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.order_by('team__participation__tournament__name', 'team__trigram').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")
 |