1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-09-25 19:08:18 +02:00

Compare commits

...

15 Commits

Author SHA1 Message Date
sable
6eb192b823 minor fixe 2025-08-31 12:43:37 +02:00
ehouarn
bcd6444ff2 Merge branch 'family' into 'main'
INSTALLED_APPS checks

See merge request bde/nk20!347
2025-08-30 02:12:51 +02:00
Ehouarn
2a638e7b32 INSTALLED_APPS checks 2025-08-30 01:55:03 +02:00
ehouarn
bb06206a9b Merge branch 'wei' into 'main'
Answers to survey

See merge request bde/nk20!346
2025-08-29 17:31:13 +02:00
Ehouarn
55be3c9836 Answers to survey 2025-08-29 17:13:52 +02:00
ehouarn
2ac19ab7be Merge branch 'translations' into 'main'
Translations

See merge request bde/nk20!345
2025-08-29 14:44:17 +02:00
ehouarn
7d359dec13 Update django.po 2025-08-29 14:12:25 +02:00
ehouarn
1015a5dba1 Merge branch 'main' into 'translations'
Main

See merge request bde/nk20!344
2025-08-29 14:08:58 +02:00
ehouarn
8f9f650826 Merge branch 'family' into 'main'
Family

See merge request bde/nk20!343
2025-08-28 12:03:09 +02:00
ehouarn
99a90867cc Merge branch 'main' into 'family'
# Conflicts:
#   locale/fr/LC_MESSAGES/django.po
2025-08-28 11:23:22 +02:00
Ehouarn
0d69695b00 Last commit 2025-08-28 11:19:45 +02:00
ehouarn
92f6d11cb5 Merge branch 'translations' into 'main'
Some WEI translations

See merge request bde/nk20!342
2025-08-21 00:03:43 +02:00
Ehouarn
1fdb30d7d2 Some WEI translations 2025-08-20 23:37:34 +02:00
ehouarn
6975ed6df6 Merge branch 'wei' into 'main'
Survey questions

See merge request bde/nk20!341
2025-08-20 23:30:34 +02:00
Ehouarn
4da87872bd Survey questions 2025-08-20 22:59:37 +02:00
10 changed files with 259 additions and 198 deletions

View File

@@ -1,6 +1,8 @@
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings
def save_user_profile(instance, created, raw, **_kwargs):
"""
@@ -16,7 +18,7 @@ def save_user_profile(instance, created, raw, **_kwargs):
def update_wei_registration_fee_on_membership_creation(sender, instance, created, **kwargs):
if not hasattr(instance, "_no_signal") and created:
if not hasattr(instance, "_no_signal") and 'wei' in settings.INSTALLED_APPS and created:
from wei.models import WEIRegistration
if instance.club.id == 1 or instance.club.id == 2:
registrations = WEIRegistration.objects.filter(
@@ -29,8 +31,8 @@ def update_wei_registration_fee_on_membership_creation(sender, instance, created
def update_wei_registration_fee_on_club_change(sender, instance, **kwargs):
if not hasattr(instance, "_no_signal") and 'wei' in settings.INSTALLED_APPS and (instance.id == 1 or instance.id == 2):
from wei.models import WEIRegistration
if not hasattr(instance, "_no_signal") and (instance.id == 1 or instance.id == 2):
registrations = WEIRegistration.objects.filter(
wei__year=instance.membership_start.year,
)

View File

@@ -7,6 +7,7 @@
<dt class="col-xl-6">{% trans 'username'|capfirst %}</dt>
<dd class="col-xl-6">{{ user_object.username }}</dd>
{% if family_app_installed %}
<dt class="col-xl-6">{% trans 'family'|capfirst %}</dt>
<dd class="col-xl-6">
{% if families %}
@@ -17,6 +18,7 @@
<span class="text-muted">Aucune</span>
{% endif %}
</dd>
{% endif %}
{% if user_object.pk == user.pk %}
<dt class="col-xl-6">{% trans 'password'|capfirst %}</dt>

View File

@@ -207,7 +207,8 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
modified_note.is_active = True
context["can_unlock_note"] = not user.note.is_active and PermissionBackend\
.check_perm(self.request, "note.change_noteuser_is_active", modified_note)
if 'family' in settings.INSTALLED_APPS:
context["family_app_installed"] = True
families = Family.objects.filter(memberships__user=user).distinct()
context["families"] = families

View File

@@ -10,145 +10,199 @@ from django import forms
from django.db import transaction
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe
from .base import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, WEIBusInformation
from ...models import WEIMembership, Bus
WORDS = {
'list': [
'13 organisé', '3ième mi temps', 'Années 2000', 'Apéro', 'BBQ', 'BP', 'Beauf', 'Binge drinking', 'Bon enfant',
'Cartouche', 'Catacombes', 'Chansons paillardes', 'Chansons populaires', 'Chanteur', 'Chartreuse', 'Chill',
'Core', 'DJ', 'Dancefloor', 'Danse', 'David Guetta', 'Disco', 'Eau de vie', 'Électro', 'Escalade', 'Familial',
'Fanfare', 'Fracassage', 'Féria', 'Hard rock', 'Hoeggarden', 'House', 'Huit-six', 'IPA', 'Inclusif', 'Inferno',
'Introverti', 'Jager bomb', 'Jazz', 'Jeux d\'alcool', 'Jeux de rôles', 'Jeux vidéo', 'Jul', 'Jus de fruit',
'Karaoké', 'LGBTQI+', 'Lady Gaga', 'Loup garou', 'Morning beer', 'Métal', 'Nuit blanche', 'Ovalie', 'Psychedelic',
'Pétanque', 'Rave', 'Reggae', 'Rhum', 'Ricard', 'Rock', 'Rosé', 'Rétro', 'Séducteur', 'Techno', 'Thérapie taxi',
'Théâtre', 'Trap', 'Turn up', 'Underground', 'Volley', 'Wati B', 'Zinédine Zidane',
'Fiesta', 'Graillance', 'Move it move it', 'Calme', 'Nert et geek', 'Jeux de rôles et danse rock',
'Strass et paillettes', 'Spectaculaire', 'Splendide', 'Flow inégalable', 'Rap', 'Battles légendaires',
'Techno', 'Alcool', 'Kiffeur·euse', 'Rugby', 'Médiéval', 'Festif',
'Stylé', 'Chipie', 'Rétro', 'Vache', 'Farfadet', 'Fanfare',
],
'questions': {
'Question 1': [
'Description 1',
"alcool": [
"""Sur une échelle allant de 0 (= 0 alcool ou très peu) à 5 (= la fontaine de jouvence alcoolique),
quel niveau de consommation dalcool souhaiterais-tu ?""",
{
3: 'Réponse 1 Madagas[car]',
4: 'Réponse 1 Y2[KAR]',
2: 'Réponse 1 Tcherno[bus]',
5: 'Réponse 1 [Kar]tier',
1: 'Réponse 1 [Car]cassonne',
6: 'Réponse 1 O[car]ina',
7: 'Réponse 1 Show[bus]',
8: 'Réponse 1 [Car]ioca'
42: 4,
47: 1,
48: 3,
45: 3.5,
44: 4,
46: 5,
43: 3,
49: 3
}
],
'Question 2': [
'Description 2',
"voie_post_bac": [
"""Si la DA du bus de ton choix correspondait à une voie post-bac, laquelle serait-elle ?""",
{
3: 'Réponse 2 Madagas[car]',
4: 'Réponse 2 Y2[KAR]',
2: 'Réponse 2 Tcherno[bus]',
5: 'Réponse 2 [Kar]tier',
1: 'Réponse 2 [Car]cassonne',
6: 'Réponse 2 O[car]ina',
7: 'Réponse 2 Show[bus]',
8: 'Réponse 2 [Car]ioca'
42: "Double licence cuisine/arts du cirque option burger",
47: "BTS Exploration de donjon",
48: "Ecole des stars en herbe",
45: "Déscolarisation précoce",
44: "Rattrapage pour excès de kiff",
46: "Double cursus STAPS / Licence dhistoire",
43: "Recherche active dun sugar daddy/dun sugar mommy",
49: "Licence de musicologie"
}
],
'Question 3': [
'Description 3',
"boite": [
"""Tu es seul·e sur une île déserte et devant toi il y a une sombre boîte de taille raisonnable.
Quy a-t-il à lintérieur ?""",
{
3: 'Réponse 3 Madagas[car]',
4: 'Réponse 3 Y2[KAR]',
2: 'Réponse 3 Tcherno[bus]',
5: 'Réponse 3 [Kar]tier',
1: 'Réponse 3 [Car]cassonne',
6: 'Réponse 3 O[car]ina',
7: 'Réponse 3 Show[bus]',
8: 'Réponse 3 [Car]ioca'
42: "Un burgouzz de valouzz",
47: "Un ocarina (pour me téléporter hors de ce bourbier)",
48: "Des paillettes, un micro de karaoké et une enceinte bluetooth",
45: "",
44: "Une 86 et un caisson pour taper du pied",
46: "Une épée, un ballon et une tireuse",
43: "Des lunettes de soleil",
49: "Mon instrument de musique"
}
],
'Question 4': [
'Description 4',
"tardif": [
"""Il est 00h, tu as passé la journée à la plage avec tes copains et iels te proposent de prolonger parce
quaprès tout, il ny a plus personne sur la plage à cette heure-ci. Tu nhabites pas loin mais tenchaînes
demain avec une journée similaire avec un autre groupe damis parce que tes trop #busy. Que fais-tu ?""",
{
3: 'Réponse 4 Madagas[car]',
4: 'Réponse 4 Y2[KAR]',
2: 'Réponse 4 Tcherno[bus]',
5: 'Réponse 4 [Kar]tier',
1: 'Réponse 4 [Car]cassonne',
6: 'Réponse 4 O[car]ina',
7: 'Réponse 4 Show[bus]',
8: 'Réponse 4 [Car]ioca'
42: "On veut se déchaîner toute la nuit !!",
47: "Je prends une glace et chill un moment avant daller dormir",
48: "Jenfile mes boogie shoes pour enflammer le dancefloor avec elleux et lancer un concours de slay, le perdant finit la bouteille de rhum",
45: "La fête continuuuuue",
44: "Soirée sangria plage → boîte → lever de soleil sur la plage",
46: "Minuit ? Cest lheure du genepi. On commence les alcools forts !!",
43: "Tenchaînes direct (faut pas les priver de ta présence)",
49: "On continue en mode chill (soirée potins)"
}
],
'Question 5': [
'Description 5',
"cohesion": [
"""Cest la rentrée de Seconde et tu découvres ta classe, tes camarades et ta prof principale!!!
qui vous propose une activité de cohésion. Laquelle est-elle ?""",
{
3: 'Réponse 5 Madagas[car]',
4: 'Réponse 5 Y2[KAR]',
2: 'Réponse 5 Tcherno[bus]',
5: 'Réponse 5 [Kar]tier',
1: 'Réponse 5 [Car]cassonne',
6: 'Réponse 5 O[car]ina',
7: 'Réponse 5 Show[bus]',
8: 'Réponse 5 [Car]ioca'
42: "Un relais cubi en ventriglisse",
47: "Un jeu de rôle",
48: "Organiser la soirée de lannée dans le lycée. Le thème : SLAY (Spotlight, Love, Amaze/All-night, Yeah), paillettes, disco",
45: "La prof de français propose un slam parce qu'elle pense que c'est du rap littéraire qui fera plaisir aux élèves",
44: "Ptit escape game + apéro",
46: "Joute avec des boucliers Gilbert",
43: "Tournage dun clip de confessions nocturnes de Diams",
49: "Je sais pas jai raté mon BAFA"
}
],
'Question 6': [
'Description 6',
"artiste": [
"""Cest lété et la saison des festivals a commencé. Tu regardes la programmation du festival
pas loin de chez toi et tu découvres avec joie la présence dun·e artiste. De qui sagit-il ?""",
{
3: 'Réponse 6 Madagas[car]',
4: 'Réponse 6 Y2[KAR]',
2: 'Réponse 6 Tcherno[bus]',
5: 'Réponse 6 [Kar]tier',
1: 'Réponse 6 [Car]cassonne',
6: 'Réponse 6 O[car]ina',
7: 'Réponse 6 Show[bus]',
8: 'Réponse 6 [Car]ioca'
42: "Moto-Moto (il chantera son fameux tube “je les aime grosses, je les aime bombées”)",
47: "Hatsune Miku",
48: "Rihanna",
45: "Vald",
44: "Qui connaît vraiment les noms des artistes de tech ?",
46: "Perceval",
43: "Fatal bazooka",
49: "Måneskin"
}
],
'Question 7': [
'Description 7',
"annonce_noel": [
"""Cest Noël et tu revois toute ta famille, oncles, tantes, cousin·e·s, grands-parents, la totale.
Dun coup, tu te lèves, tapotes de manière pompeuse sur ton verre avec un de tes couverts.
Quannonces-tu ?""",
{
3: 'Réponse 7 Madagas[car]',
4: 'Réponse 7 Y2[KAR]',
2: 'Réponse 7 Tcherno[bus]',
5: 'Réponse 7 [Kar]tier',
1: 'Réponse 7 [Car]cassonne',
6: 'Réponse 7 O[car]ina',
7: 'Réponse 7 Show[bus]',
8: 'Réponse 7 [Car]ioca'
42: """« Chère famille. Je sais bien que nous avions dit : pas de politique à table.
Je ne peux toutefois me retenir de vous annoncer une grande nouvelle…
jai décidé de quitter la ville pour consacrer ma vie au culte du Roi Julian.
A moi la jungle luxuriante, là où le soleil chaud caresse les palmiers,
où les lémuriens dansent avec frénésie et où chaque repas est une ode au burger sauvage.
Longue vie à Sa Majesté le Roi Julian ! »""",
47: "« Jai perdu »",
48: "« Mes chers parents je pars, jarrête lENS pour devenir DJ slay à Ibiza »",
45: "Jinterromps le repas pour rapper les 6min de bande organisée",
44: "« Digestif ? Pétanque ? Les deux ? »",
46: "« Montjoie St Denis à bas la Macronie »",
43: "« Je suis enceinte » (cest faux jai juste besoin dattention)",
49: """Discours de remerciement :
je lance un powerpoint de 65 slides et sors une feuille A4 blanche (je fais semblant de lire mon discours dessus)"""
}
],
'Question 8': [
'Description 8',
"vacances": [
"""Les vacances sont là et taimerais bien partir quelque part, mais où ?""",
{
3: 'Réponse 8 Madagas[car]',
4: 'Réponse 8 Y2[KAR]',
2: 'Réponse 8 Tcherno[bus]',
5: 'Réponse 8 [Kar]tier',
1: 'Réponse 8 [Car]cassonne',
6: 'Réponse 8 O[car]ina',
7: 'Réponse 8 Show[bus]',
8: 'Réponse 8 [Car]ioca'
42: "A Madagascar, à bord dun bus conduit par des pingouins",
47: "Dans ma chambre",
48: "Rio de Janeiro",
45: "N'importe où tant qu'on peut sortir tous les soirs",
44: "Tu suis les plans du club ski ou de piratens",
46: "Carcassonne",
43: "Coachella",
49: "Dans les montagnes de la république populaire dAuvergne-Rhônes-Alpes pour profiter de la fraîcheur, de la nature et de mes ami·e·s"
}
],
'Question 9': [
'Description 9',
"loisir": [
"""Tas fini ta journée de cours et tu tapprêtes à profiter dune activité/hobby/loisir de ton choix.
Laquelle est-ce ?""",
{
3: 'Réponse 9 Madagas[car]',
4: 'Réponse 9 Y2[KAR]',
2: 'Réponse 9 Tcherno[bus]',
5: 'Réponse 9 [Kar]tier',
1: 'Réponse 9 [Car]cassonne',
6: 'Réponse 9 O[car]ina',
7: 'Réponse 9 Show[bus]',
8: 'Réponse 9 [Car]ioca'
42: "Cueillir des noix de coco",
47: "Essayer de travailler puis chill avec des potes autour dun jeu en buvant du thé",
48: "Repet du nouveau spectacle de mon club, before (potins) puis sortie avec les potes jusquau bout de la night",
45: "Zoner avec les copaings jusquà pas dheure",
44: "Go Kfet pour se faire traquenard jusquà 3h du mat",
46: "Déterminer ce qui est le plus solide entre mon crâne et une ecocup",
43: "Revoir pour la 6e fois gossip girl au fond de ton lit",
49: "Jouer de mon instrument préféré avec les copains/copines pour préparer le prochain concert #solidays"
}
],
"plan": [
"""Tu reçois un message sur la conversation de groupe que tu partages avec tes potes :
vous êtes chaud·e·s pour vous retrouver. Quel plan tattire le plus ?""",
{
42: """Après-midi piscine, puis before arrosé de mojito,
avant daller séclater en pot avec toute la savane et de finir sur un after spécial pina colada""",
47: """(matin) : Ptit jeu de rôle
(repas) : le traditionnel poké-tacos
(juste après le repas) : combat avec des épées en mousse avec les copains!
(16h00) : pause thé
(fin daprès midi) : initiation à la danse rock
(soirée) : découverte dun jeu de société avec des règles obscures
""",
48: "Soirée champagne and chic : spectacle et dîner au moulin rouge puis soirée sur les champs",
45: "Se regrouper pour une soirée, même si il nest encore que 10h",
44: "Ptit poké qui termine en koin koin avec after poker",
46: "Une dégustation de bière, un rugby et toute autre activité joviale",
43: "Un brunch de pour papoter puis friperies",
49: "Soirée raclette !"
}
]
}
}
IMAGES = {
"vacances": {
49: "/static/wei/img/logo_auvergne_rhone_alpes.jpg",
}
}
NB_WORDS = 5
class OptionalImageRadioSelect(forms.RadioSelect):
def __init__(self, images=None, *args, **kwargs):
self.images = images or {}
super().__init__(*args, **kwargs)
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
option = super().create_option(name, value, label, selected, index, subindex=subindex, attrs=attrs)
img_url = self.images.get(value)
if img_url:
option['label'] = mark_safe(f'{label} <img src="{img_url}" style="height:32px;vertical-align:middle;">')
else:
option['label'] = label
return option
class WEISurveyForm2025(forms.Form):
"""
Survey form for the year 2025.
@@ -170,7 +224,7 @@ class WEISurveyForm2025(forms.Form):
if information.step == 0:
self.fields["words"] = forms.MultipleChoiceField(
label=_(f"Choose {NB_WORDS} words:"),
label=_(f"Select {NB_WORDS} words that describe the WEI experience you want to have."),
choices=[(w, w) for w in WORDS['list']],
widget=forms.CheckboxSelectMultiple(),
required=True,
@@ -178,23 +232,7 @@ class WEISurveyForm2025(forms.Form):
if self.is_valid():
return
buses = WEISurveyAlgorithm2025.get_buses()
informations = {bus: WEIBusInformation2025(bus) for bus in buses}
scores = sum((list(informations[bus].scores.values()) for bus in buses), [])
if scores:
average_score = sum(scores) / len(scores)
else:
average_score = 0
preferred_words = {
bus: [word for word in WORDS['list'] if informations[bus].scores[word] >= average_score]
for bus in buses
}
all_preferred_words = set()
for bus_words in preferred_words.values():
all_preferred_words.update(bus_words)
all_preferred_words = list(all_preferred_words)
all_preferred_words = WORDS['list']
rng.shuffle(all_preferred_words)
self.fields["words"].choices = [(w, w) for w in all_preferred_words]
else:
@@ -202,12 +240,15 @@ class WEISurveyForm2025(forms.Form):
idx = information.step - 1
if idx < len(questions):
q, (desc, answers) = questions[idx]
if q == 'alcool':
choices = [(i / 2, str(i / 2)) for i in range(11)]
else:
choices = [(k, v) for k, v in answers.items()]
rng.shuffle(choices)
self.fields[q] = forms.ChoiceField(
label=desc,
choices=choices,
widget=forms.RadioSelect,
widget=OptionalImageRadioSelect(images=IMAGES.get(q, {})),
required=True,
)
@@ -226,8 +267,6 @@ class WEIBusInformation2025(WEIBusInformation):
def __init__(self, bus):
self.scores = {}
for word in WORDS['list']:
self.scores[word] = 0
super().__init__(bus)
@@ -235,7 +274,9 @@ class BusInformationForm2025(forms.ModelForm):
class Meta:
model = Bus
fields = ['information_json']
widgets = {}
widgets = {
'information_json': forms.HiddenInput(),
}
def __init__(self, *args, words=None, **kwargs):
super().__init__(*args, **kwargs)
@@ -257,7 +298,7 @@ class BusInformationForm2025(forms.ModelForm):
label=word,
choices=choices,
coerce=int,
initial=initial_scores.get(word, 0),
initial=initial_scores.get(word, 0) if word in initial_scores else None,
required=True,
widget=forms.RadioSelect,
help_text=_("Rate between 0 and 5."),
@@ -285,7 +326,7 @@ class WEISurveyInformation2025(WEISurveyInformation):
step = 0
def __init__(self, registration):
for i in range(1, 5):
for i in range(1, NB_WORDS + 1):
setattr(self, "word" + str(i), None)
for q in WORDS['questions']:
setattr(self, q, None)
@@ -297,7 +338,7 @@ class WEISurveyInformation2025(WEISurveyInformation):
"""
self.step = 0
self.seed = 0
for i in range(1, 5):
for i in range(1, NB_WORDS + 1):
setattr(self, f"word{i}", None)
for q in WORDS['questions']:
setattr(self, q, None)
@@ -371,8 +412,9 @@ class WEISurvey2025(WEISurvey):
"""
if not self.is_complete():
raise ValueError("Survey is not ended, can't calculate score")
# Score is the given score by the bus subtracted to the mid-score of the buses.
s = sum(1 for q in WORDS['questions'] if getattr(self.information, q) == bus.pk)
s = sum(1 for q in WORDS['questions'] if q != 'alcool' and getattr(self.information, q) == bus.pk)
if 'alcool' in WORDS['questions'] and bus.pk in WORDS['questions']['alcool'][1] and hasattr(self.information, 'alcool'):
s -= abs(float(self.information.alcool) - float(WORDS['questions']['alcool'][1][bus.pk]))
return s
@lru_cache()
@@ -396,7 +438,7 @@ class WEISurvey2025(WEISurvey):
@lru_cache()
def ordered_buses(self):
"""
Force the choice of bus to be in the 3 preferred buses according to the words
Order the buses by the score_questions of the survey.
"""
values = list(self.scores_per_bus().items())
values.sort(key=lambda item: -item[1][0])
@@ -513,7 +555,7 @@ class WEISurveyAlgorithm2025(WEISurveyAlgorithm):
for survey2 in surveys:
if not survey2.information.valid or survey2.information.get_selected_bus() != bus:
continue
score2 = survey2.score_questions(bus)
score2 = survey2.score_words(bus)
if current_scores[1] <= score2: # Ignore better students
continue
if least_preferred_survey is None or score2 < least_score:

View File

@@ -23,7 +23,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=object.pk %}"
data-turbolinks="false">{% trans "Edit" %}</a>
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus_info' pk=object.pk %}"
data-turbolinks="false">{% trans "Edit information" %}</a>
data-turbolinks="false">{% trans "Edit information for survey" %}</a>
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=object.pk %}"
data-turbolinks="false">{% trans "Add team" %}</a>
</div>

View File

@@ -31,15 +31,24 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="btn btn-success" href="{% url "wei:wei_register_1A_myself" wei_pk=club.pk %}" data-turbolinks="false">
{% trans "Register to the WEI! 1A" %}
</a>
{% endif %}
<a class="btn btn-success" href="{% url "wei:wei_register_2A_myself" wei_pk=club.pk %}" data-turbolinks="false">
{% trans "Register to the WEI! 2A+" %}</a>
{% else %}
<a class="btn btn-success" href="{% url "wei:wei_register_2A_myself" wei_pk=club.pk %}" data-turbolinks="false">
{% trans "Register to the WEI! 2A+" %}
</a>
{% endif %}
{% else %}
{% if registration.validated %}
<a class="btn btn-warning" href="{% url "wei:wei_update_registration" pk=my_registration.pk %}"
data-turbolinks="false">
{% trans "Update my registration" %}
</a>
{% if not not_first_year %}
{% endif %}
{% if my_registration.first_year %}
{% if not survey_complete %}
<a class="btn btn-warning" href="{% url "wei:wei_survey" pk=my_registration.pk %}" data-turbolinks="false">
{% trans "Continue survey" %}
</a>
{% endif %}
<a class="btn btn-warning" href="{% url "wei:wei_survey" pk=my_registration.pk %}?reset=true" data-turbolinks="false">
{% trans "Restart survey" %}
</a>

View File

@@ -105,8 +105,6 @@ class TestWEIAlgorithm(TestCase):
survey = WEISurvey2025(r)
chosen_bus = survey.information.get_selected_bus()
buses = survey.ordered_buses()
'''print(buses)
print(chosen_bus)'''
self.assertIn(chosen_bus, [x[0] for x in buses])
score_questions, score_words = next(scores for bus, scores in buses if bus == chosen_bus)
max_score_questions = max(buses[i][1][0] for i in range(len(buses)))

View File

@@ -166,6 +166,7 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, D
my_registration = WEIRegistration.objects.filter(wei=club, user=self.request.user)
if my_registration.exists():
my_registration = my_registration.get()
context["survey_complete"] = CurrentSurvey(my_registration).is_complete()
else:
my_registration = None
context["my_registration"] = my_registration
@@ -213,6 +214,8 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, D
context["not_first_year"] = WEIMembership.objects.filter(user=self.request.user).exists()
context["registration_validated"] = WEIMembership.objects.filter(registration=my_registration).exists() if my_registration else False
qs = WEIMembership.objects.filter(club=club, registration__first_year=True, bus__isnull=True)
context["can_validate_1a"] = PermissionBackend.check_perm(
self.request, "wei.change_weimembership_bus", qs.first()) if qs.exists() else False
@@ -1231,7 +1234,6 @@ class WEIUpdateMembershipView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateVi
return form
def get_success_url(self):
print("get_success_url")
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.registration.wei.pk})

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-13 23:48+0200\n"
"POT-Creation-Date: 2025-08-20 23:34+0200\n"
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
"Last-Translator: ehouarn <ehouarn@crans.org>\n"
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
@@ -1753,7 +1753,7 @@ msgstr "Membres du club"
#: apps/member/templates/member/club_detail.html:40
#: apps/member/templates/member/profile_detail.html:32
#: apps/wei/templates/wei/weiclub_detail.html:98
#: apps/wei/templates/wei/weiclub_detail.html:105
msgid "Transaction history"
msgstr "Historique des transactions"
@@ -2295,8 +2295,8 @@ msgstr ""
"mode de paiement et un⋅e utilisateur⋅rice ou un club"
#: apps/note/models/transactions.py:357 apps/note/models/transactions.py:360
#: apps/note/models/transactions.py:363 apps/wei/views.py:1134
#: apps/wei/views.py:1138
#: apps/note/models/transactions.py:363 apps/wei/views.py:1135
#: apps/wei/views.py:1139
msgid "This field is required."
msgstr "Ce champ est requis."
@@ -3364,17 +3364,18 @@ msgstr "Cette équipe n'appartient pas à ce bus."
msgid "Choose a word:"
msgstr "Choisissez un mot :"
#: apps/wei/forms/surveys/wei2025.py:173
#: apps/wei/forms/surveys/wei2025.py:211
#, python-brace-format
msgid "Choose {NB_WORDS} words:"
msgstr "Choisissez {NB_WORDS} mots :"
msgid ""
"Select {NB_WORDS} words that describe the WEI experience you want to have."
msgstr "Sélectionne {NB_WORDS} mots qui décrivent lexpérience WEI que tu souhaites vivre."
#: apps/wei/forms/surveys/wei2025.py:217
#: apps/wei/forms/surveys/wei2025.py:242
#, python-brace-format
msgid "Please choose exactly {NB_WORDS} words"
msgstr ""
msgstr "Choisis exactement {NB_WORDS} mots"
#: apps/wei/forms/surveys/wei2025.py:263
#: apps/wei/forms/surveys/wei2025.py:288
msgid "Rate between 0 and 5."
msgstr "Note entre 0 et 5."
@@ -3409,7 +3410,7 @@ msgid "Information about the survey for new members, encoded in JSON"
msgstr ""
"Informations sur le sondage pour les nouveaux membres, encodées en JSON"
#: apps/wei/models.py:108 apps/wei/templates/wei/weiclub_detail.html:56
#: apps/wei/models.py:108 apps/wei/templates/wei/weiclub_detail.html:63
msgid "Buses"
msgstr "Bus"
@@ -3647,11 +3648,11 @@ msgstr "Prix du WEI (étudiant⋅es)"
msgid "WEI list"
msgstr "Liste des WEI"
#: apps/wei/templates/wei/base.html:79 apps/wei/views.py:584
#: apps/wei/templates/wei/base.html:79 apps/wei/views.py:585
msgid "Register 1A"
msgstr "Inscrire un⋅e 1A"
#: apps/wei/templates/wei/base.html:83 apps/wei/views.py:680
#: apps/wei/templates/wei/base.html:83 apps/wei/views.py:681
msgid "Register 2A+"
msgstr "Inscrire un⋅e 2A+"
@@ -3668,8 +3669,8 @@ msgid "View club"
msgstr "Voir le club"
#: apps/wei/templates/wei/bus_detail.html:26
msgid "Edit information"
msgstr "Modifier les informations"
msgid "Edit information for survey"
msgstr "Modifier les informations du sondage"
#: apps/wei/templates/wei/bus_detail.html:28
#: apps/wei/templates/wei/busteam_detail.html:24
@@ -3718,23 +3719,27 @@ msgstr "M'inscrire au WEI ! 1A"
msgid "Register to the WEI! 2A+"
msgstr "M'inscrire au WEI ! 2A+"
#: apps/wei/templates/wei/weiclub_detail.html:40
#: apps/wei/templates/wei/weiclub_detail.html:42
msgid "Update my registration"
msgstr "Modifier mon inscription"
#: apps/wei/templates/wei/weiclub_detail.html:44
#: apps/wei/templates/wei/weiclub_detail.html:47
msgid "Continue survey"
msgstr "Continuer le questionnaire"
#: apps/wei/templates/wei/weiclub_detail.html:51
msgid "Restart survey"
msgstr "Recommencer le questionnaire"
#: apps/wei/templates/wei/weiclub_detail.html:68
#: apps/wei/templates/wei/weiclub_detail.html:75
msgid "Members of the WEI"
msgstr "Membres du WEI"
#: apps/wei/templates/wei/weiclub_detail.html:80
#: apps/wei/templates/wei/weiclub_detail.html:87
msgid "Unvalidated registrations"
msgstr "Inscriptions non validées"
#: apps/wei/templates/wei/weiclub_detail.html:90
#: apps/wei/templates/wei/weiclub_detail.html:97
msgid "Attribute buses"
msgstr "Répartition dans les bus"
@@ -3770,7 +3775,7 @@ msgstr "Informations brutes du sondage"
msgid "The algorithm didn't run."
msgstr "L'algorithme n'a pas été exécuté."
#: apps/wei/templates/wei/weimembership_form.html:98 apps/wei/views.py:1028
#: apps/wei/templates/wei/weimembership_form.html:98 apps/wei/views.py:1029
msgid "Deposit check given"
msgstr "Chèque de caution donné"
@@ -3896,63 +3901,63 @@ msgstr "Chercher un WEI"
msgid "WEI Detail"
msgstr "Détails du WEI"
#: apps/wei/views.py:229
#: apps/wei/views.py:230
msgid "View members of the WEI"
msgstr "Voir les membres du WEI"
#: apps/wei/views.py:262
#: apps/wei/views.py:263
msgid "Find WEI Membership"
msgstr "Trouver une adhésion au WEI"
#: apps/wei/views.py:272
#: apps/wei/views.py:273
msgid "View registrations to the WEI"
msgstr "Voir les inscriptions au WEI"
#: apps/wei/views.py:318
#: apps/wei/views.py:319
msgid "Find WEI Registration"
msgstr "Trouver une inscription au WEI"
#: apps/wei/views.py:329
#: apps/wei/views.py:330
msgid "Update the WEI"
msgstr "Modifier le WEI"
#: apps/wei/views.py:350
#: apps/wei/views.py:351
msgid "Create new bus"
msgstr "Ajouter un nouveau bus"
#: apps/wei/views.py:388
#: apps/wei/views.py:389
msgid "Update bus"
msgstr "Modifier le bus"
#: apps/wei/views.py:420
#: apps/wei/views.py:421
msgid "Manage bus"
msgstr "Gérer le bus"
#: apps/wei/views.py:447
#: apps/wei/views.py:448
msgid "Create new team"
msgstr "Créer une nouvelle équipe"
#: apps/wei/views.py:491
#: apps/wei/views.py:492
msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/wei/views.py:526
#: apps/wei/views.py:527
msgid "Manage WEI team"
msgstr "Gérer l'équipe WEI"
#: apps/wei/views.py:548
#: apps/wei/views.py:549
msgid "Register first year student to the WEI"
msgstr "Inscrire un⋅e 1A au WEI"
#: apps/wei/views.py:605 apps/wei/views.py:698
#: apps/wei/views.py:606 apps/wei/views.py:699
msgid "Check if you will open a Société Générale account"
msgstr "Cochez cette case si vous ouvrez un compte à la Société Générale."
#: apps/wei/views.py:616 apps/wei/views.py:728
#: apps/wei/views.py:617 apps/wei/views.py:729
msgid "This user is already registered to this WEI."
msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:621
#: apps/wei/views.py:622
msgid ""
"This user can't be in her/his first year since he/she has already "
"participated to a WEI."
@@ -3960,67 +3965,67 @@ msgstr ""
"Cet⋅te utilisateur⋅rice ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI."
#: apps/wei/views.py:644
#: apps/wei/views.py:645
msgid "Register old student to the WEI"
msgstr "Inscrire un⋅e 2A+ au WEI"
#: apps/wei/views.py:702 apps/wei/views.py:825
#: apps/wei/views.py:703 apps/wei/views.py:826
msgid "You already opened an account in the Société générale."
msgstr "Vous avez déjà ouvert un compte auprès de la société générale."
#: apps/wei/views.py:715 apps/wei/views.py:821
#: apps/wei/views.py:716 apps/wei/views.py:822
msgid "Choose how you want to pay the deposit"
msgstr "Choisissez comment payer la caution"
#: apps/wei/views.py:767
#: apps/wei/views.py:768
msgid "Update WEI Registration"
msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:811
#: apps/wei/views.py:812
msgid "Tick if the deposit check has been given"
msgstr "Cochez si le chèque de caution a été donné"
#: apps/wei/views.py:850
#: apps/wei/views.py:851
msgid "No membership found for this registration"
msgstr "Pas d'adhésion trouvée pour cette inscription"
#: apps/wei/views.py:859
#: apps/wei/views.py:860
msgid "You don't have the permission to update memberships"
msgstr "Vous n'avez pas la permission de modifier une inscription"
#: apps/wei/views.py:865
#: apps/wei/views.py:866
#, python-format
msgid "You don't have the permission to update the field %(field)s"
msgstr "Vous n'avez pas la permission de modifier le champ %(field)s"
#: apps/wei/views.py:906
#: apps/wei/views.py:907
msgid "Delete WEI registration"
msgstr "Supprimer l'inscription WEI"
#: apps/wei/views.py:917
#: apps/wei/views.py:918
msgid "You don't have the right to delete this WEI registration."
msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI."
#: apps/wei/views.py:935
#: apps/wei/views.py:936
msgid "Validate WEI registration"
msgstr "Valider l'inscription WEI"
#: apps/wei/views.py:1029
#: apps/wei/views.py:1030
msgid "Only treasurers can validate this field"
msgstr "Seul·e·s les trésorier·ère·s peuvent valider ce champ"
#: apps/wei/views.py:1035
#: apps/wei/views.py:1036
msgid "Create deposit transaction"
msgstr "Créer une transaction de caution"
#: apps/wei/views.py:1036
#: apps/wei/views.py:1037
#, python-format
msgid ""
"A transaction of %(amount).2f€ will be created from the user's Note account"
msgstr ""
"Un transaction de %(amount).2f€ va être créée depuis la note de l'utilisateur"
#: apps/wei/views.py:1124
#: apps/wei/views.py:1125
#, python-format
msgid ""
"This user doesn't have enough money to join this club and pay the deposit. "
@@ -4030,12 +4035,12 @@ msgstr ""
"payer la caution. Solde actuel : %(balance)d€, crédit : %(credit)d€, "
"requis : %(needed)d€"
#: apps/wei/views.py:1177
#: apps/wei/views.py:1178
#, python-format
msgid "Deposit %(name)s"
msgstr "Caution %(name)s"
#: apps/wei/views.py:1202
#: apps/wei/views.py:1203
msgid "Update WEI Membership"
msgstr "Modifier une adhésion au WEI"

View File

@@ -82,7 +82,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% if user.is_authenticated %}
<li class="nav-item">
{% url 'family:family_list' as url %}
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-users"></i> {% trans 'Families' %}</a>
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-home"></i> {% trans 'Families' %}</a>
</li>
{% endif %}