1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-06-29 20:51:11 +02:00

Compare commits

..

11 Commits

Author SHA1 Message Date
80427bc00a Merge branch 'WEI_with_questions' into 'main'
Wei with questions

See merge request bde/nk20!218
2023-08-30 16:18:08 +02:00
c6a2849d35 test 2023-08-30 16:16:29 +02:00
4ab22c92b3 After WEI registration validation, come back to unvalidate registration page 2023-08-30 09:52:17 +02:00
c328c1457c add register button at the end of WEI registration 2023-08-28 22:27:45 +02:00
96da7d01ae change on a field that everyone have (1A don't have bus) 2023-08-28 19:26:51 +02:00
d27f942339 typo 2023-08-28 10:13:28 +02:00
738d6c932d questions ! 2023-08-28 00:42:33 +02:00
1760196578 more tests 2023-08-27 23:11:40 +02:00
13b9b6edea tests 2023-08-27 18:09:46 +02:00
e06e3b2972 one question by page 2023-08-26 23:47:10 +02:00
9596aa7b8c base for questions instead of words 2023-08-26 17:52:48 +02:00
13 changed files with 442 additions and 401 deletions

View File

@ -47,13 +47,6 @@ class ProfileForm(forms.ModelForm):
last_report = forms.DateTimeField(required=False, disabled=True, label=_("Last report date"))
VSS_charter_read = forms.BooleanField(
required=True,
label=_("Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) charter read and approved"),
help_text=_("Tick after having read and accepted the anti-VSS charter \
<a href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> available here in pdf</a>")
)
def clean_promotion(self):
promotion = self.cleaned_data["promotion"]
if promotion > timezone.now().year:

View File

@ -1,18 +0,0 @@
# Generated by Django 2.2.28 on 2023-08-31 09:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('member', '0010_new_default_year'),
]
operations = [
migrations.AddField(
model_name='profile',
name='VSS_charter_read',
field=models.BooleanField(default=False, verbose_name='VSS charter read'),
),
]

View File

@ -134,11 +134,6 @@ class Profile(models.Model):
default=False,
)
VSS_charter_read = models.BooleanField(
verbose_name=_("VSS charter read"),
default=False
)
@property
def ens_year(self):
"""

View File

@ -335,7 +335,6 @@ class TestMemberships(TestCase):
ml_sports_registration=True,
ml_art_registration=True,
report_frequency=7,
VSS_charter_read=True
))
self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
self.assertTrue(User.objects.filter(username="toto changed").exists())

View File

@ -3259,8 +3259,6 @@
136,
137,
150,
163,
164,
166,
167,
168,
@ -3580,20 +3578,6 @@
]
}
},
{
"model": "permission.role",
"pk": 21,
"fields": {
"for_club": 1,
"name": "GC anti-VSS",
"permissions": [
150,
163,
164,
182
]
}
},
{
"model": "wei.weirole",
"pk": 12,

View File

@ -48,7 +48,6 @@ class TestSignup(TestCase):
ml_events_registration="en",
ml_sport_registration=True,
ml_art_registration=True,
VSS_charter_read=True
))
self.assertRedirects(response, reverse("registration:email_validation_sent"), 302, 200)
self.assertTrue(User.objects.filter(username="toto").exists())
@ -106,7 +105,6 @@ class TestSignup(TestCase):
ml_events_registration="en",
ml_sport_registration=True,
ml_art_registration=True,
VSS_charter_read=True
))
self.assertTrue(response.status_code, 200)
@ -126,7 +124,6 @@ class TestSignup(TestCase):
ml_events_registration="en",
ml_sport_registration=True,
ml_art_registration=True,
VSS_charter_read=True
))
self.assertTrue(response.status_code, 200)
@ -146,27 +143,6 @@ class TestSignup(TestCase):
ml_events_registration="en",
ml_sport_registration=True,
ml_art_registration=True,
VSS_charter_read=True
))
self.assertTrue(response.status_code, 200)
# The VSS charter is not read
response = self.client.post(reverse("registration:signup"), dict(
first_name="Toto",
last_name="TOTO",
username="Ihaveanotherusername",
email="othertoto@example.com",
password1="toto1234",
password2="toto1234",
phone_number="+33123456789",
department="EXT",
promotion=Club.objects.get(name="BDE").membership_start.year,
address="Earth",
paid=False,
ml_events_registration="en",
ml_sport_registration=True,
ml_art_registration=True,
VSS_charter_read=False
))
self.assertTrue(response.status_code, 200)

View File

@ -1,90 +1,189 @@
# Copyright (C) 2018-2023 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import time
from functools import lru_cache
from random import Random
from django import forms
from django.db import transaction
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from .base import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, WEIBusInformation
from ...models import WEIMembership
WORDS = [
'ABBA', 'After', 'Alcoolique anonyme', 'Ambiance festive', 'Années 2000', 'Apéro', 'Art',
'Baby foot billard biere pong', 'BBQ', 'Before', 'Bière pong', 'Bon enfant', 'Calme', 'Canapé',
'Chanson paillarde', 'Chanson populaire', 'Chartreuse', 'Cheerleader', 'Chill', 'Choré',
'Cinéma', 'Cocktail', 'Comédie musicle', 'Commercial', 'Copaing', 'Danse', 'Dancefloor',
'Electro', 'Fanfare', 'Gin tonic', 'Inclusif', 'Jazz', "Jeux d'alcool", 'Jeux de carte',
'Jeux de rôle', 'Jeux de société', 'JUL', 'Jus de fruit', 'Kfet', 'Kleptomanie assurée',
'LGBTQ+', 'Livre', 'Morning beer', 'Musique', 'NAPS', 'Paillettes', 'Pastis', 'Paté Hénaff',
'Peluche', 'Pena baiona', "Peu d'alcool", 'Pilier de bar', 'PMU', 'Poulpe', 'Punch', 'Rap',
'Réveil', 'Rock', 'Rugby', 'Sandwich', 'Serge', 'Shot', 'Sociable', 'Spectacle', 'Techno',
'Techno house', 'Thérapie Taxi', 'Tradition kchanaises', 'Troisième mi-temps', 'Turn up',
'Vodka', 'Vodka pomme', 'Volley', 'Vomi stratégique'
]
WORDS = {
"ambiance": ["Ambiance de bus :", {
1: "Ambiance calme et posée",
2: "Ambiance rigolage entre copaing",
3: "Ambiance danse de camping autour d'une piscine inexistante",
4: "Grosse soirée avec de la musique qui fait bouger",
5: "On retourne le camping et le bus (dans le respect et le savoir vivre)"
}],
"musique": ["Musique :", {
1: "Musique tranquille",
2: "Musique commerciale",
3: "Chansons paillardes",
4: "Musique de Colonie de vacances",
5: "Grosse techno"
}],
"boisson": ["Boissons :", {
1: "Boisson soft",
2: "Des cocktails de temps en temps",
3: "Des coktails fancy de pétasse (parce que c'est les meilleurs)",
4: "Bière !",
5: "L'alcool c'est dans les céréales"
}],
"beauferie": ["Échelle de la beauferie :", {
1: "Je suis toujours classe",
2: "Je rote de temps en temps",
3: "Claquette chaussette, c'est confortable",
4: "L'aviron bayonnais est dans ma plyaylist",
5: "Je suis champion⋅ne de concours de rots et d'éclatage de gobelet sur mon front"
}],
"sommeil": ["Échelle de ton sommeil pendant le WEI :", {
1: "Dormir, c'est pour les faibles",
2: "5h maximum",
3: "10h",
4: "15h",
5: "Deux bonnes nuits de sommeil, c'est important pour être en forme pour les activités proposées par nos supers GC WEI"
}],
"vacances": ["Tes vacances de rêve :", {
1: "Dans ma chambre",
2: "Retourner chez popa et moman pour pouvoir enfin arrêter de manger des pasta box",
3: "Être une grosse larve sous le soleil des troopiiiiiiiiques",
4: "Faire un road trip camping sauvage, manger des racines et boire son pipi",
5: "Le crime ne prend pas de vacances"
}],
"activite": ["T'as une heure de trou pendant ton WEI, que fais-tu ?", {
1: "Je cherche des copaines pour faire un petit jeu de société",
2: "Je cherche un moyen de me dépenser, n'importe quel ballon ferait l'affaire",
3: "Je cherche un endroit où il y a de la musique pour bouger sur le dancefloor",
4: "Petit apéro, petite pétanque avec les collègues autour d'un bon pastaga",
5: "Je cherche une connerie à faire (mais pas trop méchante, pour ne pas embêter mes GC WEI préférés)"
}],
"hygiene": ["Échelle de ton hygiène :", {
1: "La douche, c'eest tous les jours",
2: "La règle des 2 jours, c'est un droit et un devoir",
3: "Je ne me lave qu'après le sport",
4: "« Ne vous inquiétez pas, je pue pas »",
5: "Y a que les sales qui se lavent"
}],
"animal": ["Tu décrirais ton animal totem plutôt comme :", {
1: "Un dragon qui raserait des villes entières d'un seul souffle",
2: "Une mouette qui pique des frites aux dunkerquois",
3: "Un poulpe tout meunion",
4: "Un pitbull qui au fond cache un petit cœur en sucre",
5: "Un canard en plastique au bord d'une baignoire qui n'a pas servi depuis 10 ans"
}],
"fensfoire": ["Quel est ton rapport à la F[ENS]foire ?", {
1: "Je réveille les autres à 6h avec mon instrument",
2: "Je la suis partout",
3: "J'aime bien l'écouter de temps en temps",
4: "Je mets des bouchons d'oreilles pour ne pas l'entendre",
5: "La quoi ?"
}],
"kokarde": ["Qu'est-ce que le mot Kokarde t'évoque ?", {
1: "Vraiment pas mon truc les soirées…",
2: "Bof, je viens pour manger et je repars aussitôt",
3: "Je kiffe, good vibes",
4: "Perso, je ne m'arrêterai pas de danser sur la piste !",
5: "J'resterai jusqu'à 3h ou rien"
}],
"copain": ["Qu'est-ce que tu fais avec un⋅e «copain⋅ine» ?", {
1: "Je l'insulte de sale merde",
2: "J'lui fais faire des trucs cons et je l'affiche !",
3: "On parlerait ensemble et on se marrerait",
4: "On aurait des vrais gros délires",
5: "Je meurs pour lui/elle"
}],
"vie": ["Selon toi, qu'est-ce que la vie ?", {
1: "La vie, cette sale race !",
2: "Un moment paisible avant la mort",
3: "C'est difficile à définir...",
4: "En vrai, c'est cool !",
5: "Une gigantestque tranche de kiff ! Et tous les jours, j'en mange un morceau"
}],
"jeux": ["Quel est ton rapport avec les jeux de société ?", {
1: "éloigné",
2: "nonchalant",
3: "timide",
4: "assumé",
5: "sexuel"
}],
"calin": ["Qu'est-ce que tu penses des câlins ?", {
1: "Jamais je n'en fais et jamais je n'en ferai !",
2: "J'en fais mais ça ne me plaît pas",
3: "J'en fais rarement mais c'est toujours cool",
4: "J'en fais tous les jours avec mes ami⋅es !",
5: "Je pourrais en faire à n'importe qui. Pourquoi ne pas créer le club Câl[ENS] ?"
}],
"vomi": ["Quel est ton rapport au vomi ?", {
1: "C'est compliqué…",
2: "Jamais je ne vomis mais je nettoie quand mes potes vomissent",
3: "Jamais je ne vomis et jamais je ne nettoie celui de quelqu'un d'autre",
4: "Je vomis quelquefois, ça arrive, faites pas cette tête, mais je fins toujours par nettoyer !",
5: "Je vomis à chaque soirée et ce n'est jamais moi qui nettoie"
}],
"kfet": ["Qu'est ce que la Kfet t'évoque ?", {
1: "La Kfet, quel lieu de dépravé⋅es sérieux…",
2: "C'est un endroit à l'hygiène plus que douteuse…",
3: "Téma les prix des boissons et des snacks, c'est aberrant !",
4: "En vrai, c'est cool, petit billard, petit canapé, chill !",
5: "Banger, j'y reste jusqu'à la fin de mes jours"
}],
"fatigue": ["Comment combattre la fatigue lors de ton WEI ?", {
1: "Le sport en journée, ça réveille",
2: "Le sucre du coca, ça réveille",
3: "La taurine du Red Bull, ça réveille",
4: "L'alcool dans le sang, ça réveille",
5: "L'écocup sur le front, ça réveille"
}],
"duree trajet": ["Quelle serait ta durée de trajet préférée ?", {
1: "Trajet instantané, pas le temps de niaiser",
2: "1h, histoire de faire connaissance avec quelques personnes avant de se jeter sur les boissons",
3: "3h, on peut vraiment parler et apprendre à connaître nos voisin⋅es",
4: "6h, histoire d'avoir le temps de faire des conneries dans le bus pour bien se marrer !",
5: "12h, il faut bien trouver un moment pour dormir, ce seront deux gros dodos dans un bus"
}],
"scolarite": ["Comment tu vois ton cursus à l'ENS ?", {
1: "La tranquillité et le travail",
2: "On va s'amuser tout en bossant",
3: "Ça va profiter et réviser au dernier moment pour les exams…",
4: "Nous festoierons sans songer aux conséquences",
5: "Je ne vois qu'une seule issue : la débauche"
}]
}
class WEISurveyForm2023(forms.Form):
"""
Survey form for the year 2023.
Members choose 20 words, from which we calculate the best associated bus.
Members answer 20 question, from which we calculate the best associated bus.
"""
word = forms.ChoiceField(
label=_("Choose a word:"),
widget=forms.RadioSelect(),
)
def set_registration(self, registration):
"""
Filter the bus selector with the buses of the current WEI.
"""
information = WEISurveyInformation2023(registration)
if not information.seed:
information.seed = int(1000 * time.time())
information.save(registration)
registration._force_save = True
registration.save()
if self.data:
self.fields["word"].choices = [(w, w) for w in WORDS]
if self.is_valid():
return
rng = Random((information.step + 1) * information.seed)
words = None
buses = WEISurveyAlgorithm2023.get_buses()
informations = {bus: WEIBusInformation2023(bus) for bus in buses}
scores = sum((list(informations[bus].scores.values()) for bus in buses), [])
average_score = sum(scores) / len(scores)
preferred_words = {bus: [word for word in WORDS
if informations[bus].scores[word] >= average_score]
for bus in buses}
while words is None or len(set(words)) != len(words):
# Ensure that there is no the same word 2 times
words = [rng.choice(words) for _ignored2, words in preferred_words.items()]
rng.shuffle(words)
words = [(w, w) for w in words]
self.fields["word"].choices = words
question = information.questions[information.step]
self.fields[question] = forms.ChoiceField(
label=WORDS[question][0],
widget=forms.RadioSelect(),
)
answers = [(answer, WORDS[question][1][answer]) for answer in WORDS[question][1]]
self.fields[question].choices = answers
class WEIBusInformation2023(WEIBusInformation):
"""
For each word, the bus has a score
For each question, the bus has ordered answers
"""
scores: dict
def __init__(self, bus):
self.scores = {}
for word in WORDS:
self.scores[word] = 0.0
for question in WORDS:
self.scores[question] = []
super().__init__(bus)
@ -93,13 +192,13 @@ class WEISurveyInformation2023(WEISurveyInformation):
We store the id of the selected bus. We store only the name, but is not used in the selection:
that's only for humans that try to read data.
"""
# Random seed that is stored at the first time to ensure that words are generated only once
seed = 0
step = 0
questions = list(WORDS.keys())
def __init__(self, registration):
for i in range(1, 21):
setattr(self, "word" + str(i), None)
for question in WORDS:
setattr(self, str(question), None)
super().__init__(registration)
@ -127,9 +226,11 @@ class WEISurvey2023(WEISurvey):
@transaction.atomic
def form_valid(self, form):
word = form.cleaned_data["word"]
self.information.step += 1
setattr(self.information, "word" + str(self.information.step), word)
for question in WORDS:
if question in form.cleaned_data:
answer = form.cleaned_data[question]
setattr(self.information, question, answer)
self.save()
@classmethod
@ -140,16 +241,10 @@ class WEISurvey2023(WEISurvey):
"""
The survey is complete once the bus is chosen.
"""
return self.information.step == 20
@classmethod
@lru_cache()
def word_mean(cls, word):
"""
Calculate the mid-score given by all buses.
"""
buses = cls.get_algorithm_class().get_buses()
return sum([cls.get_algorithm_class().get_bus_information(bus).scores[word] for bus in buses]) / buses.count()
for question in WORDS:
if not getattr(self.information, question):
return False
return True
@lru_cache()
def score(self, bus):
@ -158,8 +253,9 @@ class WEISurvey2023(WEISurvey):
bus_info = self.get_algorithm_class().get_bus_information(bus)
# Score is the given score by the bus subtracted to the mid-score of the buses.
s = sum(bus_info.scores[getattr(self.information, 'word' + str(i))]
- self.word_mean(getattr(self.information, 'word' + str(i))) for i in range(1, 21)) / 20
s = 0
for question in WORDS:
s += bus_info.scores[question][str(getattr(self.information, question))]
return s
@lru_cache()
@ -174,7 +270,6 @@ class WEISurvey2023(WEISurvey):
@classmethod
def clear_cache(cls):
cls.word_mean.cache_clear()
return super().clear_cache()

View File

@ -2,9 +2,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import random
from datetime import date
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
from note.models import NoteUser
from ..forms.surveys.wei2023 import WEIBusInformation2023, WEISurvey2023, WORDS, WEISurveyInformation2023
from ..models import Bus, WEIClub, WEIRegistration
@ -20,9 +23,25 @@ class TestWEIAlgorithm(TestCase):
"""
Create some test data, with one WEI and 10 buses with random score attributions.
"""
self.user = User.objects.create_superuser(
username="weiadmin",
password="admin",
email="admin@example.com",
)
self.user.save()
self.client.force_login(self.user)
sess = self.client.session
sess["permission_mask"] = 42
sess.save()
self.wei = WEIClub.objects.create(
name="WEI 2023",
email="wei2023@example.com",
parent_club_id=2,
membership_fee_paid=12500,
membership_fee_unpaid=5500,
membership_start='2023-08-26',
membership_end='2023-09-15',
date_start='2023-09-16',
date_end='2023-09-18',
year=2023,
@ -33,8 +52,8 @@ class TestWEIAlgorithm(TestCase):
bus = Bus.objects.create(wei=self.wei, name=f"Bus {i}", size=10)
self.buses.append(bus)
information = WEIBusInformation2023(bus)
for word in WORDS:
information.scores[word] = random.randint(0, 101)
for question in WORDS:
information.scores[question] = {answer: random.randint(1, 5) for answer in WORDS[question][1]}
information.save()
bus.save()
@ -52,8 +71,8 @@ class TestWEIAlgorithm(TestCase):
birth_date='2000-01-01',
)
information = WEISurveyInformation2023(registration)
for j in range(1, 21):
setattr(information, f'word{j}', random.choice(WORDS))
for question in WORDS:
setattr(information, question, random.randint(1, 5))
information.step = 20
information.save(registration)
registration.save()
@ -82,8 +101,8 @@ class TestWEIAlgorithm(TestCase):
birth_date='2000-01-01',
)
information = WEISurveyInformation2023(registration)
for j in range(1, 21):
setattr(information, f'word{j}', random.choice(WORDS))
for question in WORDS:
setattr(information, question, random.randint(1, 5))
information.step = 20
information.save(registration)
registration.save()
@ -108,3 +127,44 @@ class TestWEIAlgorithm(TestCase):
self.assertLessEqual(max_score - score, 25) # Always less than 25 % of tolerance
self.assertLessEqual(penalty / 100, 25) # Tolerance of 5 %
def test_register_1a(self):
"""
Test register a first year member to the WEI and complete the survey
"""
response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=self.wei.pk)))
self.assertEqual(response.status_code, 200)
user = User.objects.create(username="toto", email="toto@example.com")
NoteUser.objects.create(user=user)
response = self.client.post(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=self.wei.pk)), dict(
user=user.id,
soge_credit=True,
birth_date=date(2000, 1, 1),
gender='nonbinary',
clothing_cut='female',
clothing_size='XS',
health_issues='I am a bot',
emergency_contact_name='NoteKfet2020',
emergency_contact_phone='+33123456789',
))
qs = WEIRegistration.objects.filter(user_id=user.id)
self.assertTrue(qs.exists())
registration = qs.get()
self.assertRedirects(response, reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), 302, 200)
for question in WORDS:
# Fill 1A Survey, 20 pages
# be careful if questionnary form change (number of page, type of answer...)
response = self.client.post(reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), {
question: "1"
})
registration.refresh_from_db()
survey = WEISurvey2023(registration)
self.assertRedirects(response, reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), 302,
302 if survey.is_complete() else 200)
self.assertIsNotNone(getattr(survey.information, question), "Survey page " + question + " failed")
survey = WEISurvey2023(registration)
self.assertTrue(survey.is_complete())
survey.select_bus(self.buses[0])
survey.save()
self.assertIsNotNone(survey.information.get_selected_bus())

View File

@ -380,7 +380,7 @@ class TestWEIRegistration(TestCase):
def test_register_1a(self):
"""
Test register a first year member to the WEI and complete the survey.
Test register a first year member to the WEI.
"""
response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=self.wei.pk)))
self.assertEqual(response.status_code, 200)
@ -402,21 +402,6 @@ class TestWEIRegistration(TestCase):
self.assertTrue(qs.exists())
registration = qs.get()
self.assertRedirects(response, reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), 302, 200)
for i in range(1, 21):
# Fill 1A Survey, 20 pages
response = self.client.post(reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), dict(
word="Jus de fruit",
))
registration.refresh_from_db()
survey = CurrentSurvey(registration)
self.assertRedirects(response, reverse("wei:wei_survey", kwargs=dict(pk=registration.pk)), 302,
302 if survey.is_complete() else 200)
self.assertIsNotNone(getattr(survey.information, "word" + str(i)), "Survey page #" + str(i) + " failed")
survey = CurrentSurvey(registration)
self.assertTrue(survey.is_complete())
survey.select_bus(self.bus)
survey.save()
self.assertIsNotNone(survey.information.get_selected_bus())
# Check that the user can't be registered twice
response = self.client.post(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=self.wei.pk)), dict(
@ -662,7 +647,7 @@ class TestWEIRegistration(TestCase):
first_name="admin",
bank="Société générale",
))
self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.registration.wei.pk)), 302, 200)
self.assertRedirects(response, reverse("wei:wei_registrations", kwargs=dict(pk=self.registration.wei.pk)), 302, 200)
# Check if the membership is successfully created
membership = WEIMembership.objects.filter(user_id=self.user.id, club=self.wei)
self.assertTrue(membership.exists())

View File

@ -969,7 +969,7 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
if not registration.soge_credit and user.note.balance + credit_amount < fee:
# Users must have money before registering to the WEI.
form.add_error('bus',
form.add_error('credit_type',
_("This user don't have enough money to join this club, and can't have a negative balance."))
return super().form_invalid(form)
@ -1014,7 +1014,7 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
def get_success_url(self):
self.object.refresh_from_db()
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.club.pk})
return reverse_lazy("wei:wei_registrations", kwargs={"pk": self.object.club.pk})
class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
@ -1084,7 +1084,44 @@ class WEISurveyEndView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
club = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
context["club"] = club
random_user = User.objects.filter(~Q(wei__wei__in=[club])).first()
if random_user is None:
# This case occurs when all users are registered to the WEI.
# Don't worry, Pikachu never went to the WEI.
# This bug can arrive only in dev mode.
context["can_add_first_year_member"] = True
context["can_add_any_member"] = True
else:
# Check if the user has the right to create a registration of a random first year member.
empty_fy_registration = WEIRegistration(
wei=club,
user=random_user,
first_year=True,
birth_date="1970-01-01",
gender="No",
emergency_contact_name="No",
emergency_contact_phone="No",
)
context["can_add_first_year_member"] = PermissionBackend \
.check_perm(self.request, "wei.add_weiregistration", empty_fy_registration)
# Check if the user has the right to create a registration of a random old member.
empty_old_registration = WEIRegistration(
wei=club,
user=User.objects.filter(~Q(wei__wei__in=[club])).first(),
first_year=False,
birth_date="1970-01-01",
gender="No",
emergency_contact_name="No",
emergency_contact_phone="No",
)
context["can_add_any_member"] = PermissionBackend \
.check_perm(self.request, "wei.add_weiregistration", empty_old_registration)
return context

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-31 13:25+0200\n"
"POT-Creation-Date: 2023-07-09 14:46+0200\n"
"PO-Revision-Date: 2020-11-16 20:02+0000\n"
"Last-Translator: bleizi <bleizi@crans.org>\n"
"Language-Team: German <http://translate.ynerant.fr/projects/nk20/nk20/de/>\n"
@ -53,7 +53,7 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "Sie dürfen höchstens 3 Leute zu dieser Veranstaltung einladen."
#: apps/activity/models.py:28 apps/activity/models.py:63
#: apps/member/models.py:204
#: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:263 apps/note/models/transactions.py:26
@ -114,7 +114,7 @@ msgstr "Wo findet die Veranstaltung statt ? (z.B Kfet)."
msgid "type"
msgstr "Type"
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:307
#: apps/note/models/notes.py:148 apps/treasury/models.py:287
#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13
#: apps/wei/templates/wei/survey.html:15
@ -262,15 +262,15 @@ msgstr "entfernen"
msgid "Type"
msgstr "Type"
#: apps/activity/tables.py:84 apps/member/forms.py:193
#: apps/registration/forms.py:93 apps/treasury/forms.py:131
#: apps/activity/tables.py:84 apps/member/forms.py:186
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
#: apps/wei/forms/registration.py:104
msgid "Last name"
msgstr "Nachname"
#: apps/activity/tables.py:86 apps/member/forms.py:198
#: apps/activity/tables.py:86 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:138
#: apps/registration/forms.py:98 apps/treasury/forms.py:133
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
#: apps/wei/forms/registration.py:109
msgid "First name"
msgstr "Vorname"
@ -498,21 +498,21 @@ msgstr "Changelogs"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog \"{action}\" für Model {model} an {timestamp}"
#: apps/member/admin.py:50 apps/member/models.py:231
#: apps/member/admin.py:50 apps/member/models.py:226
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "Mitgliedschaftpreis (bezahlte Studenten)"
#: apps/member/admin.py:51 apps/member/models.py:236
#: apps/member/admin.py:51 apps/member/models.py:231
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "Mitgliedschaftpreis (unbezahlte Studenten)"
#: apps/member/admin.py:65 apps/member/models.py:324
#: apps/member/admin.py:65 apps/member/models.py:319
msgid "roles"
msgstr "Rollen"
#: apps/member/admin.py:66 apps/member/models.py:338
#: apps/member/admin.py:66 apps/member/models.py:333
msgid "fee"
msgstr "Preis"
@ -532,81 +532,65 @@ msgstr "Bericht Frequenz"
msgid "Last report date"
msgstr "Letzen Bericht Datum"
#: apps/member/forms.py:52
msgid ""
"Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) charter read and approved"
msgstr ""
"Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) Charta gelesen und angenommen"
#: apps/member/forms.py:53
msgid ""
"Tick after having read and accepted the anti-VSS charter <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"available here in pdf</a>"
msgstr ""
"Kreuzen Sie an, nachdem Sie die Anti-VSS-Charta gelesen und akzeptiert haben, <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"die hier als pdf-Datei verfügbar ist</a>"
#: apps/member/forms.py:60
msgid "You can't register to the note if you come from the future."
msgstr "Sie dürfen nicht einloggen wenn sie aus der Zukunft kommen."
#: apps/member/forms.py:86
#: apps/member/forms.py:79
msgid "select an image"
msgstr "Wählen sie ein Bild aus"
#: apps/member/forms.py:87
#: apps/member/forms.py:80
msgid "Maximal size: 2MB"
msgstr "Maximal Größe: 2MB"
#: apps/member/forms.py:112
#: apps/member/forms.py:105
msgid "This image cannot be loaded."
msgstr "Dieses Bild kann nicht geladen werden."
#: apps/member/forms.py:148 apps/member/views.py:103
#: apps/registration/forms.py:35 apps/registration/views.py:266
#: apps/member/forms.py:141 apps/member/views.py:103
#: apps/registration/forms.py:34 apps/registration/views.py:266
msgid "An alias with a similar name already exists."
msgstr "Ein ähnliches Alias ist schon benutzt."
#: apps/member/forms.py:172
#: apps/member/forms.py:165
msgid "Inscription paid by Société Générale"
msgstr "Mitgliedschaft von der Société Générale bezahlt"
#: apps/member/forms.py:174
#: apps/member/forms.py:167
msgid "Check this case if the Société Générale paid the inscription."
msgstr "Die Société Générale die Mitgliedschaft bezahlt."
#: apps/member/forms.py:179 apps/registration/forms.py:80
#: apps/member/forms.py:172 apps/registration/forms.py:79
#: apps/wei/forms/registration.py:91
msgid "Credit type"
msgstr "Kredittype"
#: apps/member/forms.py:180 apps/registration/forms.py:81
#: apps/member/forms.py:173 apps/registration/forms.py:80
#: apps/wei/forms/registration.py:92
msgid "No credit"
msgstr "Kein Kredit"
#: apps/member/forms.py:182
#: apps/member/forms.py:175
msgid "You can credit the note of the user."
msgstr "Sie dûrfen diese Note kreditieren."
#: apps/member/forms.py:186 apps/registration/forms.py:86
#: apps/member/forms.py:179 apps/registration/forms.py:85
#: apps/wei/forms/registration.py:97
msgid "Credit amount"
msgstr "Kreditanzahl"
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
#: apps/wei/forms/registration.py:114
msgid "Bank"
msgstr "Bank"
#: apps/member/forms.py:230
#: apps/member/forms.py:223
msgid "User"
msgstr "User"
#: apps/member/forms.py:244
#: apps/member/forms.py:237
msgid "Roles"
msgstr "Rollen"
@ -793,19 +777,15 @@ msgstr "email bestätigt"
msgid "registration valid"
msgstr "Anmeldung gültig"
#: apps/member/models.py:138
msgid "VSS charter read"
msgstr "VSS-Charta gelesen"
#: apps/member/models.py:167 apps/member/models.py:168
#: apps/member/models.py:162 apps/member/models.py:163
msgid "user profile"
msgstr "Userprofile"
#: apps/member/models.py:178
#: apps/member/models.py:173
msgid "Activate your Note Kfet account"
msgstr "Ihre Note Kfet Konto bestätigen"
#: apps/member/models.py:209
#: apps/member/models.py:204
#: apps/member/templates/member/includes/club_info.html:55
#: apps/member/templates/member/includes/profile_info.html:40
#: apps/registration/templates/registration/future_profile_detail.html:22
@ -814,88 +794,88 @@ msgstr "Ihre Note Kfet Konto bestätigen"
msgid "email"
msgstr "Email"
#: apps/member/models.py:216
#: apps/member/models.py:211
msgid "parent club"
msgstr "Urclub"
#: apps/member/models.py:225
#: apps/member/models.py:220
msgid "require memberships"
msgstr "erfordern Mitgliedschaft"
#: apps/member/models.py:226
#: apps/member/models.py:221
msgid "Uncheck if this club don't require memberships."
msgstr ""
"Deaktivieren Sie diese Option, wenn für diesen Club keine Mitgliedschaft "
"erforderlich ist."
#: apps/member/models.py:242
#: apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:26
msgid "membership duration"
msgstr "Mitgliedscahftzeit"
#: apps/member/models.py:243
#: apps/member/models.py:238
msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "Wie lang am höchsten eine Mitgliedschaft dauern kann."
#: apps/member/models.py:250
#: apps/member/models.py:245
#: apps/member/templates/member/includes/club_info.html:16
msgid "membership start"
msgstr "Mitgliedschaftanfangsdatum"
#: apps/member/models.py:251
#: apps/member/models.py:246
msgid "Date from which the members can renew their membership."
msgstr "Ab wann kann man sein Mitgliedschaft erneuern."
#: apps/member/models.py:257
#: apps/member/models.py:252
#: apps/member/templates/member/includes/club_info.html:21
msgid "membership end"
msgstr "Mitgliedschaftenddatum"
#: apps/member/models.py:258
#: apps/member/models.py:253
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Maximales Datum einer Mitgliedschaft, nach dem Mitglieder es erneuern müssen."
#: apps/member/models.py:293 apps/member/models.py:318
#: apps/member/models.py:288 apps/member/models.py:313
#: apps/note/models/notes.py:176
msgid "club"
msgstr "Club"
#: apps/member/models.py:294
#: apps/member/models.py:289
msgid "clubs"
msgstr "Clubs"
#: apps/member/models.py:329
#: apps/member/models.py:324
msgid "membership starts on"
msgstr "Mitgliedschaft fängt an"
#: apps/member/models.py:333
#: apps/member/models.py:328
msgid "membership ends on"
msgstr "Mitgliedschaft endet am"
#: apps/member/models.py:435
#: apps/member/models.py:430
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Die Rolle {role} ist nicht erlaubt für das Club {club}."
#: apps/member/models.py:444 apps/member/views.py:712
#: apps/member/models.py:439 apps/member/views.py:712
msgid "User is already a member of the club"
msgstr "User ist schon ein Mitglied dieser club"
#: apps/member/models.py:456 apps/member/views.py:721
#: apps/member/models.py:451 apps/member/views.py:721
msgid "User is not a member of the parent club"
msgstr "User ist noch nicht Mitglied des Urclubs"
#: apps/member/models.py:509
#: apps/member/models.py:504
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Mitgliedschaft von {user} für das Club {club}"
#: apps/member/models.py:512 apps/note/models/transactions.py:389
#: apps/member/models.py:507 apps/note/models/transactions.py:389
msgid "membership"
msgstr "Mitgliedschaft"
#: apps/member/models.py:513
#: apps/member/models.py:508
msgid "memberships"
msgstr "Mitgliedschaften"
@ -1880,7 +1860,7 @@ msgstr "Angabefeld gilt nur zum Anzeigen und Ändern von Berechtigungstypen."
msgid "for club"
msgstr "Für Club"
#: apps/permission/models.py:351 apps/permission/models.py:352
#: apps/permission/models.py:350 apps/permission/models.py:351
msgid "role permissions"
msgstr "Berechtigung Rollen"
@ -2002,15 +1982,15 @@ msgstr "Alle Rechten"
msgid "registration"
msgstr "Anmeldung"
#: apps/registration/forms.py:41
#: apps/registration/forms.py:40
msgid "This email address is already used."
msgstr "Diese email adresse ist schon benutzt."
#: apps/registration/forms.py:61
#: apps/registration/forms.py:60
msgid "Register to the WEI"
msgstr "Zu WEI anmelden"
#: apps/registration/forms.py:63
#: apps/registration/forms.py:62
msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you "
"will be able to register later, after validating your account in the Kfet."
@ -2019,15 +1999,15 @@ msgstr ""
"falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im Kfet "
"registrieren."
#: apps/registration/forms.py:108
#: apps/registration/forms.py:107
msgid "Join BDE Club"
msgstr "BDE Mitglieder werden"
#: apps/registration/forms.py:115
#: apps/registration/forms.py:114
msgid "Join Kfet Club"
msgstr "Kfet Mitglieder werden"
#: apps/registration/forms.py:124
#: apps/registration/forms.py:123
msgid "Join BDA Club"
msgstr "BDA Mitglieder werden"
@ -2651,7 +2631,6 @@ msgid "This team doesn't belong to the given bus."
msgstr "Dieses Team gehört nicht zum angegebenen Bus."
#: apps/wei/forms/surveys/wei2021.py:35 apps/wei/forms/surveys/wei2022.py:38
#: apps/wei/forms/surveys/wei2023.py:38
msgid "Choose a word:"
msgstr "Wählen Sie ein Wort:"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-31 13:25+0200\n"
"POT-Creation-Date: 2023-07-09 14:46+0200\n"
"PO-Revision-Date: 2022-04-11 23:12+0200\n"
"Last-Translator: bleizi <bleizi@crans.org>\n"
"Language-Team: \n"
@ -52,7 +52,7 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "Usted no puede invitar más de 3 persona a esta actividad."
#: apps/activity/models.py:28 apps/activity/models.py:63
#: apps/member/models.py:204
#: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:263 apps/note/models/transactions.py:26
@ -113,7 +113,7 @@ msgstr "Lugar donde se organiza la actividad, por ejemplo la Kfet."
msgid "type"
msgstr "tipo"
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:307
#: apps/note/models/notes.py:148 apps/treasury/models.py:287
#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13
#: apps/wei/templates/wei/survey.html:15
@ -261,15 +261,15 @@ msgstr "quitar"
msgid "Type"
msgstr "Tipo"
#: apps/activity/tables.py:84 apps/member/forms.py:193
#: apps/registration/forms.py:93 apps/treasury/forms.py:131
#: apps/activity/tables.py:84 apps/member/forms.py:186
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
#: apps/wei/forms/registration.py:104
msgid "Last name"
msgstr "Apellido"
#: apps/activity/tables.py:86 apps/member/forms.py:198
#: apps/activity/tables.py:86 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:138
#: apps/registration/forms.py:98 apps/treasury/forms.py:133
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
#: apps/wei/forms/registration.py:109
msgid "First name"
msgstr "Nombre"
@ -495,21 +495,21 @@ msgstr "diario de cambios"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr ""
#: apps/member/admin.py:50 apps/member/models.py:231
#: apps/member/admin.py:50 apps/member/models.py:226
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "pago de afiliación (estudiantes pagados)"
#: apps/member/admin.py:51 apps/member/models.py:236
#: apps/member/admin.py:51 apps/member/models.py:231
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "pago de afiliación (estudiantes no pagados)"
#: apps/member/admin.py:65 apps/member/models.py:324
#: apps/member/admin.py:65 apps/member/models.py:319
msgid "roles"
msgstr "papel"
#: apps/member/admin.py:66 apps/member/models.py:338
#: apps/member/admin.py:66 apps/member/models.py:333
msgid "fee"
msgstr "pago"
@ -529,81 +529,65 @@ msgstr "Frecuencia de los informes (en días)"
msgid "Last report date"
msgstr "Fecha del último informe"
#: apps/member/forms.py:52
msgid ""
"Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) charter read and approved"
msgstr ""
"Carta Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) leída y aprobada"
#: apps/member/forms.py:53
msgid ""
"Tick after having read and accepted the anti-VSS charter <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"available here in pdf</a>"
msgstr ""
"Marque después de leer y aceptar la carta anti-VVS <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"disponible en pdf aquí</a>"
#: apps/member/forms.py:60
msgid "You can't register to the note if you come from the future."
msgstr "Usted no puede registrar si viene del futuro."
#: apps/member/forms.py:86
#: apps/member/forms.py:79
msgid "select an image"
msgstr "elegir una imagen"
#: apps/member/forms.py:87
#: apps/member/forms.py:80
msgid "Maximal size: 2MB"
msgstr "Tamaño máximo : 2Mo"
#: apps/member/forms.py:112
#: apps/member/forms.py:105
msgid "This image cannot be loaded."
msgstr "Esta imagen no puede ser cargada."
#: apps/member/forms.py:148 apps/member/views.py:103
#: apps/registration/forms.py:35 apps/registration/views.py:266
#: apps/member/forms.py:141 apps/member/views.py:103
#: apps/registration/forms.py:34 apps/registration/views.py:266
msgid "An alias with a similar name already exists."
msgstr "Un alias similar ya existe."
#: apps/member/forms.py:172
#: apps/member/forms.py:165
msgid "Inscription paid by Société Générale"
msgstr "Registración pagadas por Société Générale"
#: apps/member/forms.py:174
#: apps/member/forms.py:167
msgid "Check this case if the Société Générale paid the inscription."
msgstr "Marcar esta casilla si Société Générale pagó la registración."
#: apps/member/forms.py:179 apps/registration/forms.py:80
#: apps/member/forms.py:172 apps/registration/forms.py:79
#: apps/wei/forms/registration.py:91
msgid "Credit type"
msgstr "Tipo de crédito"
#: apps/member/forms.py:180 apps/registration/forms.py:81
#: apps/member/forms.py:173 apps/registration/forms.py:80
#: apps/wei/forms/registration.py:92
msgid "No credit"
msgstr "No crédito"
#: apps/member/forms.py:182
#: apps/member/forms.py:175
msgid "You can credit the note of the user."
msgstr "Usted puede acreditar la note del usuario."
#: apps/member/forms.py:186 apps/registration/forms.py:86
#: apps/member/forms.py:179 apps/registration/forms.py:85
#: apps/wei/forms/registration.py:97
msgid "Credit amount"
msgstr "Valor del crédito"
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
#: apps/wei/forms/registration.py:114
msgid "Bank"
msgstr "Banco"
#: apps/member/forms.py:230
#: apps/member/forms.py:223
msgid "User"
msgstr "Usuario"
#: apps/member/forms.py:244
#: apps/member/forms.py:237
msgid "Roles"
msgstr "Papeles"
@ -788,19 +772,15 @@ msgstr "correo electrónico confirmado"
msgid "registration valid"
msgstr "registración valida"
#: apps/member/models.py:138
msgid "VSS charter read"
msgstr "Carta VSS leída"
#: apps/member/models.py:167 apps/member/models.py:168
#: apps/member/models.py:162 apps/member/models.py:163
msgid "user profile"
msgstr "perfil usuario"
#: apps/member/models.py:178
#: apps/member/models.py:173
msgid "Activate your Note Kfet account"
msgstr "Active su cuenta Note Kfet"
#: apps/member/models.py:209
#: apps/member/models.py:204
#: apps/member/templates/member/includes/club_info.html:55
#: apps/member/templates/member/includes/profile_info.html:40
#: apps/registration/templates/registration/future_profile_detail.html:22
@ -809,87 +789,87 @@ msgstr "Active su cuenta Note Kfet"
msgid "email"
msgstr "correo electrónico"
#: apps/member/models.py:216
#: apps/member/models.py:211
msgid "parent club"
msgstr "club pariente"
#: apps/member/models.py:225
#: apps/member/models.py:220
msgid "require memberships"
msgstr "necesita afiliaciones"
#: apps/member/models.py:226
#: apps/member/models.py:221
msgid "Uncheck if this club don't require memberships."
msgstr "Desmarcar si este club no usa afiliaciones."
#: apps/member/models.py:242
#: apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:26
msgid "membership duration"
msgstr "duración de la afiliación"
#: apps/member/models.py:243
#: apps/member/models.py:238
msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "La duración máxima (en días) de una afiliación (NULL = infinito)."
#: apps/member/models.py:250
#: apps/member/models.py:245
#: apps/member/templates/member/includes/club_info.html:16
msgid "membership start"
msgstr "inicio de la afiliación"
#: apps/member/models.py:251
#: apps/member/models.py:246
msgid "Date from which the members can renew their membership."
msgstr "Fecha a partir de la cual los miembros pueden prorrogar su afiliación."
#: apps/member/models.py:257
#: apps/member/models.py:252
#: apps/member/templates/member/includes/club_info.html:21
msgid "membership end"
msgstr "fin de la afiliación"
#: apps/member/models.py:258
#: apps/member/models.py:253
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Ultima fecha de una afiliación, después de la cual los miembros tienen que "
"prorrogarla."
#: apps/member/models.py:293 apps/member/models.py:318
#: apps/member/models.py:288 apps/member/models.py:313
#: apps/note/models/notes.py:176
msgid "club"
msgstr "club"
#: apps/member/models.py:294
#: apps/member/models.py:289
msgid "clubs"
msgstr "clubs"
#: apps/member/models.py:329
#: apps/member/models.py:324
msgid "membership starts on"
msgstr "afiliación empezá el"
#: apps/member/models.py:333
#: apps/member/models.py:328
msgid "membership ends on"
msgstr "afiliación termina el"
#: apps/member/models.py:435
#: apps/member/models.py:430
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "El papel {role} no se encuentra en el club {club}."
#: apps/member/models.py:444 apps/member/views.py:712
#: apps/member/models.py:439 apps/member/views.py:712
msgid "User is already a member of the club"
msgstr "Usuario ya esta un miembro del club"
#: apps/member/models.py:456 apps/member/views.py:721
#: apps/member/models.py:451 apps/member/views.py:721
msgid "User is not a member of the parent club"
msgstr "Usuario no es un miembro del club pariente"
#: apps/member/models.py:509
#: apps/member/models.py:504
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Afiliación of {user} for the club {club}"
#: apps/member/models.py:512 apps/note/models/transactions.py:389
#: apps/member/models.py:507 apps/note/models/transactions.py:389
msgid "membership"
msgstr "afiliación"
#: apps/member/models.py:513
#: apps/member/models.py:508
msgid "memberships"
msgstr "afiliaciones"
@ -1865,7 +1845,7 @@ msgstr ""
msgid "for club"
msgstr "interesa el club"
#: apps/permission/models.py:351 apps/permission/models.py:352
#: apps/permission/models.py:350 apps/permission/models.py:351
msgid "role permissions"
msgstr "permisos por papeles"
@ -1983,15 +1963,15 @@ msgstr "Todos los permisos"
msgid "registration"
msgstr "afiliación"
#: apps/registration/forms.py:41
#: apps/registration/forms.py:40
msgid "This email address is already used."
msgstr "Este correo electrónico ya esta utilizado."
#: apps/registration/forms.py:61
#: apps/registration/forms.py:60
msgid "Register to the WEI"
msgstr "Registrarse en el WEI"
#: apps/registration/forms.py:63
#: apps/registration/forms.py:62
msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you "
"will be able to register later, after validating your account in the Kfet."
@ -1999,15 +1979,15 @@ msgstr ""
"Marcar esta casilla si usted quiere registrarse en el WEI. Si duda, podrá "
"registrarse más tarde, después de validar su cuenta Note Kfet."
#: apps/registration/forms.py:108
#: apps/registration/forms.py:107
msgid "Join BDE Club"
msgstr "Afiliarse al club BDE"
#: apps/registration/forms.py:115
#: apps/registration/forms.py:114
msgid "Join Kfet Club"
msgstr "Afiliarse al club Kfet"
#: apps/registration/forms.py:124
#: apps/registration/forms.py:123
msgid "Join BDA Club"
msgstr "Afiliarse al club BDA"
@ -2621,7 +2601,6 @@ msgid "This team doesn't belong to the given bus."
msgstr "Este equipo no pertenece al bus dado."
#: apps/wei/forms/surveys/wei2021.py:35 apps/wei/forms/surveys/wei2022.py:38
#: apps/wei/forms/surveys/wei2023.py:38
msgid "Choose a word:"
msgstr "Elegir una palabra :"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-08-31 13:25+0200\n"
"POT-Creation-Date: 2023-07-09 14:46+0200\n"
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
"Last-Translator: bleizi <bleizi@crans.org>\n"
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
@ -53,7 +53,7 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/activity/models.py:28 apps/activity/models.py:63
#: apps/member/models.py:204
#: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:263 apps/note/models/transactions.py:26
@ -114,7 +114,7 @@ msgstr "Lieu où l'activité est organisée, par exemple la Kfet."
msgid "type"
msgstr "type"
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:307
#: apps/note/models/notes.py:148 apps/treasury/models.py:287
#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13
#: apps/wei/templates/wei/survey.html:15
@ -262,15 +262,15 @@ msgstr "supprimer"
msgid "Type"
msgstr "Type"
#: apps/activity/tables.py:84 apps/member/forms.py:193
#: apps/registration/forms.py:93 apps/treasury/forms.py:131
#: apps/activity/tables.py:84 apps/member/forms.py:186
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
#: apps/wei/forms/registration.py:104
msgid "Last name"
msgstr "Nom de famille"
#: apps/activity/tables.py:86 apps/member/forms.py:198
#: apps/activity/tables.py:86 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:138
#: apps/registration/forms.py:98 apps/treasury/forms.py:133
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
#: apps/wei/forms/registration.py:109
msgid "First name"
msgstr "Prénom"
@ -497,21 +497,21 @@ msgstr "journaux de modifications"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type « {action} » pour le modèle {model} à {timestamp}"
#: apps/member/admin.py:50 apps/member/models.py:231
#: apps/member/admin.py:50 apps/member/models.py:226
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "cotisation pour adhérer (normalien élève)"
#: apps/member/admin.py:51 apps/member/models.py:236
#: apps/member/admin.py:51 apps/member/models.py:231
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "cotisation pour adhérer (normalien étudiant)"
#: apps/member/admin.py:65 apps/member/models.py:324
#: apps/member/admin.py:65 apps/member/models.py:319
msgid "roles"
msgstr "rôles"
#: apps/member/admin.py:66 apps/member/models.py:338
#: apps/member/admin.py:66 apps/member/models.py:333
msgid "fee"
msgstr "cotisation"
@ -531,81 +531,65 @@ msgstr "Fréquence des rapports (en jours)"
msgid "Last report date"
msgstr "Date de dernier rapport"
#: apps/member/forms.py:52
msgid ""
"Anti-VSS (<em>Violences Sexistes et Sexuelles</em>) charter read and approved"
msgstr ""
"Charte Anti-VSS (Violences Sexistes et Sexuelles) lue et approuvée"
#: apps/member/forms.py:53
msgid ""
"Tick after having read and accepted the anti-VSS charter <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"available here in pdf</a>"
msgstr ""
"Cochez après avoir lu la chartre anti-VSS <a "
"href=https://perso.crans.org/club-bde/Charte-anti-VSS.pdf target=_blank> "
"disponible en pdf ici</a>"
#: apps/member/forms.py:60
msgid "You can't register to the note if you come from the future."
msgstr "Vous ne pouvez pas vous inscrire à la note si vous venez du futur."
#: apps/member/forms.py:86
#: apps/member/forms.py:79
msgid "select an image"
msgstr "choisissez une image"
#: apps/member/forms.py:87
#: apps/member/forms.py:80
msgid "Maximal size: 2MB"
msgstr "Taille maximale : 2 Mo"
#: apps/member/forms.py:112
#: apps/member/forms.py:105
msgid "This image cannot be loaded."
msgstr "Cette image ne peut pas être chargée."
#: apps/member/forms.py:148 apps/member/views.py:103
#: apps/registration/forms.py:35 apps/registration/views.py:266
#: apps/member/forms.py:141 apps/member/views.py:103
#: apps/registration/forms.py:34 apps/registration/views.py:266
msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà."
#: apps/member/forms.py:172
#: apps/member/forms.py:165
msgid "Inscription paid by Société Générale"
msgstr "Inscription payée par la Société générale"
#: apps/member/forms.py:174
#: apps/member/forms.py:167
msgid "Check this case if the Société Générale paid the inscription."
msgstr "Cochez cette case si la Société Générale a payé l'inscription."
#: apps/member/forms.py:179 apps/registration/forms.py:80
#: apps/member/forms.py:172 apps/registration/forms.py:79
#: apps/wei/forms/registration.py:91
msgid "Credit type"
msgstr "Type de rechargement"
#: apps/member/forms.py:180 apps/registration/forms.py:81
#: apps/member/forms.py:173 apps/registration/forms.py:80
#: apps/wei/forms/registration.py:92
msgid "No credit"
msgstr "Pas de rechargement"
#: apps/member/forms.py:182
#: apps/member/forms.py:175
msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utilisateur avant l'adhésion."
#: apps/member/forms.py:186 apps/registration/forms.py:86
#: apps/member/forms.py:179 apps/registration/forms.py:85
#: apps/wei/forms/registration.py:97
msgid "Credit amount"
msgstr "Montant à créditer"
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
#: apps/wei/forms/registration.py:114
msgid "Bank"
msgstr "Banque"
#: apps/member/forms.py:230
#: apps/member/forms.py:223
msgid "User"
msgstr "Utilisateur"
#: apps/member/forms.py:244
#: apps/member/forms.py:237
msgid "Roles"
msgstr "Rôles"
@ -790,19 +774,15 @@ msgstr "adresse email confirmée"
msgid "registration valid"
msgstr "inscription valide"
#: apps/member/models.py:138
msgid "VSS charter read"
msgstr "Charte VSS lue"
#: apps/member/models.py:167 apps/member/models.py:168
#: apps/member/models.py:162 apps/member/models.py:163
msgid "user profile"
msgstr "profil utilisateur"
#: apps/member/models.py:178
#: apps/member/models.py:173
msgid "Activate your Note Kfet account"
msgstr "Activez votre compte Note Kfet"
#: apps/member/models.py:209
#: apps/member/models.py:204
#: apps/member/templates/member/includes/club_info.html:55
#: apps/member/templates/member/includes/profile_info.html:40
#: apps/registration/templates/registration/future_profile_detail.html:22
@ -811,88 +791,88 @@ msgstr "Activez votre compte Note Kfet"
msgid "email"
msgstr "courriel"
#: apps/member/models.py:216
#: apps/member/models.py:211
msgid "parent club"
msgstr "club parent"
#: apps/member/models.py:225
#: apps/member/models.py:220
msgid "require memberships"
msgstr "nécessite des adhésions"
#: apps/member/models.py:226
#: apps/member/models.py:221
msgid "Uncheck if this club don't require memberships."
msgstr "Décochez si ce club n'utilise pas d'adhésions."
#: apps/member/models.py:242
#: apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:26
msgid "membership duration"
msgstr "durée de l'adhésion"
#: apps/member/models.py:243
#: apps/member/models.py:238
msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)."
#: apps/member/models.py:250
#: apps/member/models.py:245
#: apps/member/templates/member/includes/club_info.html:16
msgid "membership start"
msgstr "début de l'adhésion"
#: apps/member/models.py:251
#: apps/member/models.py:246
msgid "Date from which the members can renew their membership."
msgstr ""
"Date à partir de laquelle les adhérents peuvent renouveler leur adhésion."
#: apps/member/models.py:257
#: apps/member/models.py:252
#: apps/member/templates/member/includes/club_info.html:21
msgid "membership end"
msgstr "fin de l'adhésion"
#: apps/member/models.py:258
#: apps/member/models.py:253
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Date maximale d'une fin d'adhésion, après laquelle les adhérents doivent la "
"renouveler."
#: apps/member/models.py:293 apps/member/models.py:318
#: apps/member/models.py:288 apps/member/models.py:313
#: apps/note/models/notes.py:176
msgid "club"
msgstr "club"
#: apps/member/models.py:294
#: apps/member/models.py:289
msgid "clubs"
msgstr "clubs"
#: apps/member/models.py:329
#: apps/member/models.py:324
msgid "membership starts on"
msgstr "l'adhésion commence le"
#: apps/member/models.py:333
#: apps/member/models.py:328
msgid "membership ends on"
msgstr "l'adhésion finit le"
#: apps/member/models.py:435
#: apps/member/models.py:430
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:444 apps/member/views.py:712
#: apps/member/models.py:439 apps/member/views.py:712
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
#: apps/member/models.py:456 apps/member/views.py:721
#: apps/member/models.py:451 apps/member/views.py:721
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
#: apps/member/models.py:509
#: apps/member/models.py:504
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}"
#: apps/member/models.py:512 apps/note/models/transactions.py:389
#: apps/member/models.py:507 apps/note/models/transactions.py:389
msgid "membership"
msgstr "adhésion"
#: apps/member/models.py:513
#: apps/member/models.py:508
msgid "memberships"
msgstr "adhésions"
@ -1871,7 +1851,7 @@ msgstr ""
msgid "for club"
msgstr "s'applique au club"
#: apps/permission/models.py:351 apps/permission/models.py:352
#: apps/permission/models.py:350 apps/permission/models.py:351
msgid "role permissions"
msgstr "permissions par rôles"
@ -1992,15 +1972,15 @@ msgstr "Tous les droits"
msgid "registration"
msgstr "inscription"
#: apps/registration/forms.py:41
#: apps/registration/forms.py:40
msgid "This email address is already used."
msgstr "Cet email est déjà pris."
#: apps/registration/forms.py:61
#: apps/registration/forms.py:60
msgid "Register to the WEI"
msgstr "S'inscrire au WEI"
#: apps/registration/forms.py:63
#: apps/registration/forms.py:62
msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you "
"will be able to register later, after validating your account in the Kfet."
@ -2009,15 +1989,15 @@ msgstr ""
"pourrez toujours vous inscrire plus tard, après avoir validé votre compte à "
"la Kfet."
#: apps/registration/forms.py:108
#: apps/registration/forms.py:107
msgid "Join BDE Club"
msgstr "Adhérer au club BDE"
#: apps/registration/forms.py:115
#: apps/registration/forms.py:114
msgid "Join Kfet Club"
msgstr "Adhérer au club Kfet"
#: apps/registration/forms.py:124
#: apps/registration/forms.py:123
msgid "Join BDA Club"
msgstr "Adhérer au club BDA"
@ -2633,7 +2613,6 @@ msgid "This team doesn't belong to the given bus."
msgstr "Cette équipe n'appartient pas à ce bus."
#: apps/wei/forms/surveys/wei2021.py:35 apps/wei/forms/surveys/wei2022.py:38
#: apps/wei/forms/surveys/wei2023.py:38
msgid "Choose a word:"
msgstr "Choisissez un mot :"
@ -2743,9 +2722,7 @@ msgstr "nom du contact en cas d'urgence"
#: apps/wei/models.py:240
msgid "The emergency contact must not be a WEI participant"
msgstr ""
"Le contact en cas d'urgence ne doit pas être une personne qui participe au "
"WEI"
msgstr "Le contact en cas d'urgence ne doit pas être une personne qui participe au WEI"
#: apps/wei/models.py:245 apps/wei/templates/wei/weimembership_form.html:73
msgid "emergency contact phone"