mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-30 13:11:09 +02:00
Compare commits
35 Commits
451aa64f33
...
VSS
Author | SHA1 | Date | |
---|---|---|---|
f545af4977 | |||
103e2d0635 | |||
aedf0e87ba | |||
dab45b5fd4 | |||
b3353b563c | |||
ba0d64f0d4 | |||
8d17801e28 | |||
609362c4f8 | |||
03d2d5f03e | |||
d2057a9f45 | |||
b6e68eeebe | |||
6410542027 | |||
6b1cd3ba7a | |||
9f114b8ca2 | |||
e0132b6dc8 | |||
f1cc82fab3 | |||
644cf14c4b | |||
f19a489313 | |||
dedd6c69cc | |||
b42f5afeab | |||
31e67ae3f6 | |||
b08da7a727 | |||
11223430fd | |||
7aeb977e72 | |||
52fef1df42 | |||
2839d3de1e | |||
30afa6da0a | |||
84fc77696f | |||
19fc620d1f | |||
6bceb394c5 | |||
62cf8f9d84 | |||
2dd1c3fb89 | |||
c8665c5798 | |||
e9f1b6f52d | |||
1d95ae4810 |
@ -6,7 +6,7 @@
|
||||
"name": "Pot",
|
||||
"manage_entries": true,
|
||||
"can_invite": true,
|
||||
"guest_entry_fee": 500
|
||||
"guest_entry_fee": 1000
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -28,5 +28,25 @@
|
||||
"can_invite": false,
|
||||
"guest_entry_fee": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "activity.activitytype",
|
||||
"pk": 5,
|
||||
"fields": {
|
||||
"name": "Soir\u00e9e avec entrées",
|
||||
"manage_entries": true,
|
||||
"can_invite": false,
|
||||
"guest_entry_fee": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "activity.activitytype",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"name": "Soir\u00e9e avec invitations",
|
||||
"manage_entries": true,
|
||||
"can_invite": true,
|
||||
"guest_entry_fee": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -47,6 +47,13 @@ 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:
|
||||
|
18
apps/member/migrations/0010_new_default_year.py
Normal file
18
apps/member/migrations/0010_new_default_year.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2.28 on 2023-08-23 21:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('member', '0009_auto_20220904_2325'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='profile',
|
||||
name='promotion',
|
||||
field=models.PositiveSmallIntegerField(default=2023, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion'),
|
||||
),
|
||||
]
|
18
apps/member/migrations/0011_profile_vss_charter_read.py
Normal file
18
apps/member/migrations/0011_profile_vss_charter_read.py
Normal file
@ -0,0 +1,18 @@
|
||||
# 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'),
|
||||
),
|
||||
]
|
@ -134,6 +134,11 @@ class Profile(models.Model):
|
||||
default=False,
|
||||
)
|
||||
|
||||
VSS_charter_read = models.BooleanField(
|
||||
verbose_name=_("VSS charter read"),
|
||||
default=False
|
||||
)
|
||||
|
||||
@property
|
||||
def ens_year(self):
|
||||
"""
|
||||
|
@ -335,6 +335,7 @@ 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())
|
||||
|
@ -221,7 +221,7 @@ function consume (source, source_alias, dest, quantity, amount, reason, type, ca
|
||||
.done(function () {
|
||||
if (!isNaN(source.balance)) {
|
||||
const newBalance = source.balance - quantity * amount
|
||||
if (newBalance <= -5000) {
|
||||
if (newBalance <= -2000) {
|
||||
addMsg(interpolate(gettext('Warning, the transaction from the note %s succeed, ' +
|
||||
'but the emitter note %s is very negative.'), [source_alias, source_alias]), 'danger', 30000)
|
||||
} else if (newBalance < 0) {
|
||||
|
@ -314,7 +314,7 @@ $('#btn_transfer').click(function () {
|
||||
|
||||
if (!isNaN(source.note.balance)) {
|
||||
const newBalance = source.note.balance - source.quantity * dest.quantity * amount
|
||||
if (newBalance <= -5000) {
|
||||
if (newBalance <= -2000) {
|
||||
addMsg(interpolate(gettext('Warning, the transaction of %s from the note %s to the note %s succeed, but the emitter note %s is very negative.'),
|
||||
[pretty_money(source.quantity * dest.quantity * amount), source.name, dest.name, source.name]), 'danger', 10000)
|
||||
reset()
|
||||
|
File diff suppressed because it is too large
Load Diff
19
apps/permission/migrations/0002_club_not_required.py
Normal file
19
apps/permission/migrations/0002_club_not_required.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.2.28 on 2023-07-24 10:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('permission', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='for_club',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='member.Club', verbose_name='for club'),
|
||||
),
|
||||
]
|
@ -339,6 +339,7 @@ class Role(models.Model):
|
||||
"member.Club",
|
||||
verbose_name=_("for club"),
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None,
|
||||
)
|
||||
|
@ -122,5 +122,5 @@ class ValidationForm(forms.Form):
|
||||
join_bda = forms.BooleanField(
|
||||
label=_("Join BDA Club"),
|
||||
required=False,
|
||||
initial=False,
|
||||
initial=True,
|
||||
)
|
||||
|
@ -48,6 +48,7 @@ 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())
|
||||
@ -105,6 +106,7 @@ 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)
|
||||
|
||||
@ -124,6 +126,7 @@ 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)
|
||||
|
||||
@ -143,6 +146,27 @@ 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)
|
||||
|
||||
|
Submodule apps/scripts updated: 4471307b37...f580f9b9e9
@ -108,7 +108,7 @@ class InvoiceListView(LoginRequiredMixin, SingleTableView):
|
||||
name="",
|
||||
address="",
|
||||
)
|
||||
if not PermissionBackend.check_perm(self.request, "treasury.add_invoice", sample_invoice):
|
||||
if not PermissionBackend.check_perm(self.request, "treasury.view_invoice", sample_invoice):
|
||||
raise PermissionDenied(_("You are not able to see the treasury interface."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .base import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm
|
||||
from .wei2022 import WEISurvey2022
|
||||
from .wei2023 import WEISurvey2023
|
||||
|
||||
|
||||
__all__ = [
|
||||
'WEISurvey', 'WEISurveyInformation', 'WEISurveyAlgorithm', 'CurrentSurvey',
|
||||
]
|
||||
|
||||
CurrentSurvey = WEISurvey2022
|
||||
CurrentSurvey = WEISurvey2023
|
||||
|
@ -148,7 +148,7 @@ class WEISurvey2021(WEISurvey):
|
||||
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()
|
||||
|
||||
# @lru_cache
|
||||
@lru_cache()
|
||||
def score(self, bus):
|
||||
if not self.is_complete():
|
||||
raise ValueError("Survey is not ended, can't calculate score")
|
||||
@ -159,11 +159,11 @@ class WEISurvey2021(WEISurvey):
|
||||
- self.word_mean(getattr(self.information, 'word' + str(i))) for i in range(1, 21)) / 20
|
||||
return s
|
||||
|
||||
# @lru_cache()
|
||||
@lru_cache()
|
||||
def scores_per_bus(self):
|
||||
return {bus: self.score(bus) for bus in self.get_algorithm_class().get_buses()}
|
||||
|
||||
# @lru_cache()
|
||||
@lru_cache()
|
||||
def ordered_buses(self):
|
||||
values = list(self.scores_per_bus().items())
|
||||
values.sort(key=lambda item: -item[1])
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2018-2022 by BDE ENS Paris-Saclay
|
||||
# Copyright (C) 2018-2023 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import time
|
||||
@ -151,7 +151,7 @@ class WEISurvey2022(WEISurvey):
|
||||
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()
|
||||
|
||||
# @lru_cache()
|
||||
@lru_cache()
|
||||
def score(self, bus):
|
||||
if not self.is_complete():
|
||||
raise ValueError("Survey is not ended, can't calculate score")
|
||||
@ -162,11 +162,11 @@ class WEISurvey2022(WEISurvey):
|
||||
- self.word_mean(getattr(self.information, 'word' + str(i))) for i in range(1, 21)) / 20
|
||||
return s
|
||||
|
||||
# @lru_cache()
|
||||
@lru_cache()
|
||||
def scores_per_bus(self):
|
||||
return {bus: self.score(bus) for bus in self.get_algorithm_class().get_buses()}
|
||||
|
||||
# @lru_cache()
|
||||
@lru_cache()
|
||||
def ordered_buses(self):
|
||||
values = list(self.scores_per_bus().items())
|
||||
values.sort(key=lambda item: -item[1])
|
||||
|
296
apps/wei/forms/surveys/wei2023.py
Normal file
296
apps/wei/forms/surveys/wei2023.py
Normal file
@ -0,0 +1,296 @@
|
||||
# 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'
|
||||
]
|
||||
|
||||
|
||||
class WEISurveyForm2023(forms.Form):
|
||||
"""
|
||||
Survey form for the year 2023.
|
||||
Members choose 20 words, 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
|
||||
|
||||
|
||||
class WEIBusInformation2023(WEIBusInformation):
|
||||
"""
|
||||
For each word, the bus has a score
|
||||
"""
|
||||
scores: dict
|
||||
|
||||
def __init__(self, bus):
|
||||
self.scores = {}
|
||||
for word in WORDS:
|
||||
self.scores[word] = 0.0
|
||||
super().__init__(bus)
|
||||
|
||||
|
||||
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
|
||||
|
||||
def __init__(self, registration):
|
||||
for i in range(1, 21):
|
||||
setattr(self, "word" + str(i), None)
|
||||
super().__init__(registration)
|
||||
|
||||
|
||||
class WEISurvey2023(WEISurvey):
|
||||
"""
|
||||
Survey for the year 2023.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_year(cls):
|
||||
return 2023
|
||||
|
||||
@classmethod
|
||||
def get_survey_information_class(cls):
|
||||
return WEISurveyInformation2023
|
||||
|
||||
def get_form_class(self):
|
||||
return WEISurveyForm2023
|
||||
|
||||
def update_form(self, form):
|
||||
"""
|
||||
Filter the bus selector with the buses of the WEI.
|
||||
"""
|
||||
form.set_registration(self.registration)
|
||||
|
||||
@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)
|
||||
self.save()
|
||||
|
||||
@classmethod
|
||||
def get_algorithm_class(cls):
|
||||
return WEISurveyAlgorithm2023
|
||||
|
||||
def is_complete(self) -> bool:
|
||||
"""
|
||||
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()
|
||||
|
||||
@lru_cache()
|
||||
def score(self, bus):
|
||||
if not self.is_complete():
|
||||
raise ValueError("Survey is not ended, can't calculate score")
|
||||
|
||||
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
|
||||
return s
|
||||
|
||||
@lru_cache()
|
||||
def scores_per_bus(self):
|
||||
return {bus: self.score(bus) for bus in self.get_algorithm_class().get_buses()}
|
||||
|
||||
@lru_cache()
|
||||
def ordered_buses(self):
|
||||
values = list(self.scores_per_bus().items())
|
||||
values.sort(key=lambda item: -item[1])
|
||||
return values
|
||||
|
||||
@classmethod
|
||||
def clear_cache(cls):
|
||||
cls.word_mean.cache_clear()
|
||||
return super().clear_cache()
|
||||
|
||||
|
||||
class WEISurveyAlgorithm2023(WEISurveyAlgorithm):
|
||||
"""
|
||||
The algorithm class for the year 2023.
|
||||
We use Gale-Shapley algorithm to attribute 1y students into buses.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_survey_class(cls):
|
||||
return WEISurvey2023
|
||||
|
||||
@classmethod
|
||||
def get_bus_information_class(cls):
|
||||
return WEIBusInformation2023
|
||||
|
||||
def run_algorithm(self, display_tqdm=False):
|
||||
"""
|
||||
Gale-Shapley algorithm implementation.
|
||||
We modify it to allow buses to have multiple "weddings".
|
||||
"""
|
||||
surveys = list(self.get_survey_class()(r) for r in self.get_registrations()) # All surveys
|
||||
surveys = [s for s in surveys if s.is_complete()] # Don't consider invalid surveys
|
||||
# Don't manage hardcoded people
|
||||
surveys = [s for s in surveys if not hasattr(s.information, 'hardcoded') or not s.information.hardcoded]
|
||||
|
||||
# Reset previous algorithm run
|
||||
for survey in surveys:
|
||||
survey.free()
|
||||
survey.save()
|
||||
|
||||
non_men = [s for s in surveys if s.registration.gender != 'male']
|
||||
men = [s for s in surveys if s.registration.gender == 'male']
|
||||
|
||||
quotas = {}
|
||||
registrations = self.get_registrations()
|
||||
non_men_total = registrations.filter(~Q(gender='male')).count()
|
||||
for bus in self.get_buses():
|
||||
free_seats = bus.size - WEIMembership.objects.filter(bus=bus, registration__first_year=False).count()
|
||||
# Remove hardcoded people
|
||||
free_seats -= WEIMembership.objects.filter(bus=bus, registration__first_year=True,
|
||||
registration__information_json__icontains="hardcoded").count()
|
||||
quotas[bus] = 4 + int(non_men_total / registrations.count() * free_seats)
|
||||
|
||||
tqdm_obj = None
|
||||
if display_tqdm:
|
||||
from tqdm import tqdm
|
||||
tqdm_obj = tqdm(total=len(non_men), desc="Non-hommes")
|
||||
|
||||
# Repartition for non men people first
|
||||
self.make_repartition(non_men, quotas, tqdm_obj=tqdm_obj)
|
||||
|
||||
quotas = {}
|
||||
for bus in self.get_buses():
|
||||
free_seats = bus.size - WEIMembership.objects.filter(bus=bus, registration__first_year=False).count()
|
||||
free_seats -= sum(1 for s in non_men if s.information.selected_bus_pk == bus.pk)
|
||||
# Remove hardcoded people
|
||||
free_seats -= WEIMembership.objects.filter(bus=bus, registration__first_year=True,
|
||||
registration__information_json__icontains="hardcoded").count()
|
||||
quotas[bus] = free_seats
|
||||
|
||||
if display_tqdm:
|
||||
tqdm_obj.close()
|
||||
|
||||
from tqdm import tqdm
|
||||
tqdm_obj = tqdm(total=len(men), desc="Hommes")
|
||||
|
||||
self.make_repartition(men, quotas, tqdm_obj=tqdm_obj)
|
||||
|
||||
if display_tqdm:
|
||||
tqdm_obj.close()
|
||||
|
||||
# Clear cache information after running algorithm
|
||||
WEISurvey2023.clear_cache()
|
||||
|
||||
def make_repartition(self, surveys, quotas=None, tqdm_obj=None):
|
||||
free_surveys = surveys.copy() # Remaining surveys
|
||||
while free_surveys: # Some students are not affected
|
||||
survey = free_surveys[0]
|
||||
buses = survey.ordered_buses() # Preferences of the student
|
||||
for bus, current_score in buses:
|
||||
if self.get_bus_information(bus).has_free_seats(surveys, quotas):
|
||||
# Selected bus has free places. Put student in the bus
|
||||
survey.select_bus(bus)
|
||||
survey.save()
|
||||
free_surveys.remove(survey)
|
||||
break
|
||||
else:
|
||||
# Current bus has not enough places. Remove the least preferred student from the bus if existing
|
||||
least_preferred_survey = None
|
||||
least_score = -1
|
||||
# Find the least student in the bus that has a lower score than the current student
|
||||
for survey2 in surveys:
|
||||
if not survey2.information.valid or survey2.information.get_selected_bus() != bus:
|
||||
continue
|
||||
score2 = survey2.score(bus)
|
||||
if current_score <= score2: # Ignore better students
|
||||
continue
|
||||
if least_preferred_survey is None or score2 < least_score:
|
||||
least_preferred_survey = survey2
|
||||
least_score = score2
|
||||
|
||||
if least_preferred_survey is not None:
|
||||
# Remove the least student from the bus and put the current student in.
|
||||
# If it does not exist, choose the next bus.
|
||||
least_preferred_survey.free()
|
||||
least_preferred_survey.save()
|
||||
free_surveys.append(least_preferred_survey)
|
||||
survey.select_bus(bus)
|
||||
survey.save()
|
||||
free_surveys.remove(survey)
|
||||
break
|
||||
else:
|
||||
raise ValueError(f"User {survey.registration.user} has no free seat")
|
||||
|
||||
if tqdm_obj is not None:
|
||||
tqdm_obj.n = len(surveys) - len(free_surveys)
|
||||
tqdm_obj.refresh()
|
18
apps/wei/migrations/0007_help_text_emergency_contact.py
Normal file
18
apps/wei/migrations/0007_help_text_emergency_contact.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.2.28 on 2023-07-09 12:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wei', '0006_unisex_clothing_cut'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='weiregistration',
|
||||
name='emergency_contact_name',
|
||||
field=models.CharField(help_text='The emergency contact must not be a WEI participant', max_length=255, verbose_name='emergency contact name'),
|
||||
),
|
||||
]
|
@ -237,6 +237,7 @@ class WEIRegistration(models.Model):
|
||||
emergency_contact_name = models.CharField(
|
||||
max_length=255,
|
||||
verbose_name=_("emergency contact name"),
|
||||
help_text=_("The emergency contact must not be a WEI participant")
|
||||
)
|
||||
|
||||
emergency_contact_phone = PhoneNumberField(
|
||||
|
110
apps/wei/tests/test_wei_algorithm_2023.py
Normal file
110
apps/wei/tests/test_wei_algorithm_2023.py
Normal file
@ -0,0 +1,110 @@
|
||||
# Copyright (C) 2018-2023 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import random
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
|
||||
from ..forms.surveys.wei2023 import WEIBusInformation2023, WEISurvey2023, WORDS, WEISurveyInformation2023
|
||||
from ..models import Bus, WEIClub, WEIRegistration
|
||||
|
||||
|
||||
class TestWEIAlgorithm(TestCase):
|
||||
"""
|
||||
Run some tests to ensure that the WEI algorithm is working well.
|
||||
"""
|
||||
fixtures = ('initial',)
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Create some test data, with one WEI and 10 buses with random score attributions.
|
||||
"""
|
||||
self.wei = WEIClub.objects.create(
|
||||
name="WEI 2023",
|
||||
email="wei2023@example.com",
|
||||
date_start='2023-09-16',
|
||||
date_end='2023-09-18',
|
||||
year=2023,
|
||||
)
|
||||
|
||||
self.buses = []
|
||||
for i in range(10):
|
||||
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)
|
||||
information.save()
|
||||
bus.save()
|
||||
|
||||
def test_survey_algorithm_small(self):
|
||||
"""
|
||||
There are only a few people in each bus, ensure that each person has its best bus
|
||||
"""
|
||||
# Add a few users
|
||||
for i in range(10):
|
||||
user = User.objects.create(username=f"user{i}")
|
||||
registration = WEIRegistration.objects.create(
|
||||
user=user,
|
||||
wei=self.wei,
|
||||
first_year=True,
|
||||
birth_date='2000-01-01',
|
||||
)
|
||||
information = WEISurveyInformation2023(registration)
|
||||
for j in range(1, 21):
|
||||
setattr(information, f'word{j}', random.choice(WORDS))
|
||||
information.step = 20
|
||||
information.save(registration)
|
||||
registration.save()
|
||||
|
||||
# Run algorithm
|
||||
WEISurvey2023.get_algorithm_class()().run_algorithm()
|
||||
|
||||
# Ensure that everyone has its first choice
|
||||
for r in WEIRegistration.objects.filter(wei=self.wei).all():
|
||||
survey = WEISurvey2023(r)
|
||||
preferred_bus = survey.ordered_buses()[0][0]
|
||||
chosen_bus = survey.information.get_selected_bus()
|
||||
self.assertEqual(preferred_bus, chosen_bus)
|
||||
|
||||
def test_survey_algorithm_full(self):
|
||||
"""
|
||||
Buses are full of first year people, ensure that they are happy
|
||||
"""
|
||||
# Add a lot of users
|
||||
for i in range(95):
|
||||
user = User.objects.create(username=f"user{i}")
|
||||
registration = WEIRegistration.objects.create(
|
||||
user=user,
|
||||
wei=self.wei,
|
||||
first_year=True,
|
||||
birth_date='2000-01-01',
|
||||
)
|
||||
information = WEISurveyInformation2023(registration)
|
||||
for j in range(1, 21):
|
||||
setattr(information, f'word{j}', random.choice(WORDS))
|
||||
information.step = 20
|
||||
information.save(registration)
|
||||
registration.save()
|
||||
|
||||
# Run algorithm
|
||||
WEISurvey2023.get_algorithm_class()().run_algorithm()
|
||||
|
||||
penalty = 0
|
||||
# Ensure that everyone seems to be happy
|
||||
# We attribute a penalty for each user that didn't have its first choice
|
||||
# The penalty is the square of the distance between the score of the preferred bus
|
||||
# and the score of the attributed bus
|
||||
# We consider it acceptable if the mean of this distance is lower than 5 %
|
||||
for r in WEIRegistration.objects.filter(wei=self.wei).all():
|
||||
survey = WEISurvey2023(r)
|
||||
chosen_bus = survey.information.get_selected_bus()
|
||||
buses = survey.ordered_buses()
|
||||
score = min(v for bus, v in buses if bus == chosen_bus)
|
||||
max_score = buses[0][1]
|
||||
penalty += (max_score - score) ** 2
|
||||
|
||||
self.assertLessEqual(max_score - score, 25) # Always less than 25 % of tolerance
|
||||
|
||||
self.assertLessEqual(penalty / 100, 25) # Tolerance of 5 %
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
|
||||
# Copyright (C) 2018-2023 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import subprocess
|
||||
@ -782,7 +782,7 @@ class TestDefaultWEISurvey(TestCase):
|
||||
WEISurvey.update_form(None, None)
|
||||
|
||||
self.assertEqual(CurrentSurvey.get_algorithm_class().get_survey_class(), CurrentSurvey)
|
||||
self.assertEqual(CurrentSurvey.get_year(), 2022)
|
||||
self.assertEqual(CurrentSurvey.get_year(), 2023)
|
||||
|
||||
|
||||
class TestWeiAPI(TestAPI):
|
||||
|
@ -118,13 +118,13 @@ Exemples
|
||||
{"F": [
|
||||
"ADD",
|
||||
["F", "source__balance"],
|
||||
5000]
|
||||
2000]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
| si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 50 €,
|
||||
autrement dit le solde final est au-dessus de -50 €.
|
||||
| si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 20 €,
|
||||
autrement dit le solde final est au-dessus de -20 €.
|
||||
|
||||
|
||||
Masques de permissions
|
||||
|
@ -83,13 +83,6 @@ Je suis trésorier d'un club, qu'ai-je le droit de faire ?
|
||||
bien sûr permis pour faciliter des transferts. Tout abus de droits constaté
|
||||
pourra mener à des sanctions prises par le bureau du BDE.
|
||||
|
||||
.. warning::
|
||||
Une fonctionnalité pour permettre de gérer plus proprement les remboursements
|
||||
entre amis est en cours de développement. Temporairement et pour des raisons
|
||||
de confort, les trésoriers de clubs ont le droit de prélever n'importe quelle
|
||||
adhérente vers n'importe quelle autre note adhérente, tant que la source ne
|
||||
descend pas sous ``- 50 €``. Ces droits seront retirés d'ici quelques semaines.
|
||||
|
||||
|
||||
Je suis trésorier d'un club, je n'arrive pas à voir le solde du club / faire des transactions
|
||||
---------------------------------------------------------------------------------------------------
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-09 11:55+0200\n"
|
||||
"POT-Creation-Date: 2023-08-31 13:25+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:199
|
||||
#: apps/member/models.py:204
|
||||
#: 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:307
|
||||
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
|
||||
#: 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:186
|
||||
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
|
||||
#: apps/activity/tables.py:84 apps/member/forms.py:193
|
||||
#: apps/registration/forms.py:93 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:191
|
||||
#: apps/activity/tables.py:86 apps/member/forms.py:198
|
||||
#: apps/note/templates/note/transaction_form.html:138
|
||||
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
|
||||
#: apps/registration/forms.py:98 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:226
|
||||
#: apps/member/admin.py:50 apps/member/models.py:231
|
||||
#: 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:231
|
||||
#: apps/member/admin.py:51 apps/member/models.py:236
|
||||
#: 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:319
|
||||
#: apps/member/admin.py:65 apps/member/models.py:324
|
||||
msgid "roles"
|
||||
msgstr "Rollen"
|
||||
|
||||
#: apps/member/admin.py:66 apps/member/models.py:333
|
||||
#: apps/member/admin.py:66 apps/member/models.py:338
|
||||
msgid "fee"
|
||||
msgstr "Preis"
|
||||
|
||||
@ -532,65 +532,81 @@ 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:79
|
||||
#: apps/member/forms.py:86
|
||||
msgid "select an image"
|
||||
msgstr "Wählen sie ein Bild aus"
|
||||
|
||||
#: apps/member/forms.py:80
|
||||
#: apps/member/forms.py:87
|
||||
msgid "Maximal size: 2MB"
|
||||
msgstr "Maximal Größe: 2MB"
|
||||
|
||||
#: apps/member/forms.py:105
|
||||
#: apps/member/forms.py:112
|
||||
msgid "This image cannot be loaded."
|
||||
msgstr "Dieses Bild kann nicht geladen werden."
|
||||
|
||||
#: apps/member/forms.py:141 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:34 apps/registration/views.py:266
|
||||
#: apps/member/forms.py:148 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:35 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:165
|
||||
#: apps/member/forms.py:172
|
||||
msgid "Inscription paid by Société Générale"
|
||||
msgstr "Mitgliedschaft von der Société Générale bezahlt"
|
||||
|
||||
#: apps/member/forms.py:167
|
||||
#: apps/member/forms.py:174
|
||||
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:172 apps/registration/forms.py:79
|
||||
#: apps/member/forms.py:179 apps/registration/forms.py:80
|
||||
#: apps/wei/forms/registration.py:91
|
||||
msgid "Credit type"
|
||||
msgstr "Kredittype"
|
||||
|
||||
#: apps/member/forms.py:173 apps/registration/forms.py:80
|
||||
#: apps/member/forms.py:180 apps/registration/forms.py:81
|
||||
#: apps/wei/forms/registration.py:92
|
||||
msgid "No credit"
|
||||
msgstr "Kein Kredit"
|
||||
|
||||
#: apps/member/forms.py:175
|
||||
#: apps/member/forms.py:182
|
||||
msgid "You can credit the note of the user."
|
||||
msgstr "Sie dûrfen diese Note kreditieren."
|
||||
|
||||
#: apps/member/forms.py:179 apps/registration/forms.py:85
|
||||
#: apps/member/forms.py:186 apps/registration/forms.py:86
|
||||
#: apps/wei/forms/registration.py:97
|
||||
msgid "Credit amount"
|
||||
msgstr "Kreditanzahl"
|
||||
|
||||
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
|
||||
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
|
||||
#: apps/wei/forms/registration.py:114
|
||||
msgid "Bank"
|
||||
msgstr "Bank"
|
||||
|
||||
#: apps/member/forms.py:223
|
||||
#: apps/member/forms.py:230
|
||||
msgid "User"
|
||||
msgstr "User"
|
||||
|
||||
#: apps/member/forms.py:237
|
||||
#: apps/member/forms.py:244
|
||||
msgid "Roles"
|
||||
msgstr "Rollen"
|
||||
|
||||
@ -777,15 +793,19 @@ msgstr "email bestätigt"
|
||||
msgid "registration valid"
|
||||
msgstr "Anmeldung gültig"
|
||||
|
||||
#: apps/member/models.py:162 apps/member/models.py:163
|
||||
#: apps/member/models.py:138
|
||||
msgid "VSS charter read"
|
||||
msgstr "VSS-Charta gelesen"
|
||||
|
||||
#: apps/member/models.py:167 apps/member/models.py:168
|
||||
msgid "user profile"
|
||||
msgstr "Userprofile"
|
||||
|
||||
#: apps/member/models.py:173
|
||||
#: apps/member/models.py:178
|
||||
msgid "Activate your Note Kfet account"
|
||||
msgstr "Ihre Note Kfet Konto bestätigen"
|
||||
|
||||
#: apps/member/models.py:204
|
||||
#: apps/member/models.py:209
|
||||
#: 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
|
||||
@ -794,88 +814,88 @@ msgstr "Ihre Note Kfet Konto bestätigen"
|
||||
msgid "email"
|
||||
msgstr "Email"
|
||||
|
||||
#: apps/member/models.py:211
|
||||
#: apps/member/models.py:216
|
||||
msgid "parent club"
|
||||
msgstr "Urclub"
|
||||
|
||||
#: apps/member/models.py:220
|
||||
#: apps/member/models.py:225
|
||||
msgid "require memberships"
|
||||
msgstr "erfordern Mitgliedschaft"
|
||||
|
||||
#: apps/member/models.py:221
|
||||
#: apps/member/models.py:226
|
||||
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:237
|
||||
#: apps/member/models.py:242
|
||||
#: apps/member/templates/member/includes/club_info.html:26
|
||||
msgid "membership duration"
|
||||
msgstr "Mitgliedscahftzeit"
|
||||
|
||||
#: apps/member/models.py:238
|
||||
#: apps/member/models.py:243
|
||||
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:245
|
||||
#: apps/member/models.py:250
|
||||
#: apps/member/templates/member/includes/club_info.html:16
|
||||
msgid "membership start"
|
||||
msgstr "Mitgliedschaftanfangsdatum"
|
||||
|
||||
#: apps/member/models.py:246
|
||||
#: apps/member/models.py:251
|
||||
msgid "Date from which the members can renew their membership."
|
||||
msgstr "Ab wann kann man sein Mitgliedschaft erneuern."
|
||||
|
||||
#: apps/member/models.py:252
|
||||
#: apps/member/models.py:257
|
||||
#: apps/member/templates/member/includes/club_info.html:21
|
||||
msgid "membership end"
|
||||
msgstr "Mitgliedschaftenddatum"
|
||||
|
||||
#: apps/member/models.py:253
|
||||
#: apps/member/models.py:258
|
||||
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:288 apps/member/models.py:313
|
||||
#: apps/member/models.py:293 apps/member/models.py:318
|
||||
#: apps/note/models/notes.py:176
|
||||
msgid "club"
|
||||
msgstr "Club"
|
||||
|
||||
#: apps/member/models.py:289
|
||||
#: apps/member/models.py:294
|
||||
msgid "clubs"
|
||||
msgstr "Clubs"
|
||||
|
||||
#: apps/member/models.py:324
|
||||
#: apps/member/models.py:329
|
||||
msgid "membership starts on"
|
||||
msgstr "Mitgliedschaft fängt an"
|
||||
|
||||
#: apps/member/models.py:328
|
||||
#: apps/member/models.py:333
|
||||
msgid "membership ends on"
|
||||
msgstr "Mitgliedschaft endet am"
|
||||
|
||||
#: apps/member/models.py:430
|
||||
#: apps/member/models.py:435
|
||||
#, 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:439 apps/member/views.py:712
|
||||
#: apps/member/models.py:444 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:451 apps/member/views.py:721
|
||||
#: apps/member/models.py:456 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:504
|
||||
#: apps/member/models.py:509
|
||||
#, python-brace-format
|
||||
msgid "Membership of {user} for the club {club}"
|
||||
msgstr "Mitgliedschaft von {user} für das Club {club}"
|
||||
|
||||
#: apps/member/models.py:507 apps/note/models/transactions.py:389
|
||||
#: apps/member/models.py:512 apps/note/models/transactions.py:389
|
||||
msgid "membership"
|
||||
msgstr "Mitgliedschaft"
|
||||
|
||||
#: apps/member/models.py:508
|
||||
#: apps/member/models.py:513
|
||||
msgid "memberships"
|
||||
msgstr "Mitgliedschaften"
|
||||
|
||||
@ -1860,7 +1880,7 @@ msgstr "Angabefeld gilt nur zum Anzeigen und Ändern von Berechtigungstypen."
|
||||
msgid "for club"
|
||||
msgstr "Für Club"
|
||||
|
||||
#: apps/permission/models.py:350 apps/permission/models.py:351
|
||||
#: apps/permission/models.py:351 apps/permission/models.py:352
|
||||
msgid "role permissions"
|
||||
msgstr "Berechtigung Rollen"
|
||||
|
||||
@ -1982,15 +2002,15 @@ msgstr "Alle Rechten"
|
||||
msgid "registration"
|
||||
msgstr "Anmeldung"
|
||||
|
||||
#: apps/registration/forms.py:40
|
||||
#: apps/registration/forms.py:41
|
||||
msgid "This email address is already used."
|
||||
msgstr "Diese email adresse ist schon benutzt."
|
||||
|
||||
#: apps/registration/forms.py:60
|
||||
#: apps/registration/forms.py:61
|
||||
msgid "Register to the WEI"
|
||||
msgstr "Zu WEI anmelden"
|
||||
|
||||
#: apps/registration/forms.py:62
|
||||
#: apps/registration/forms.py:63
|
||||
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 +2019,15 @@ msgstr ""
|
||||
"falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im Kfet "
|
||||
"registrieren."
|
||||
|
||||
#: apps/registration/forms.py:107
|
||||
#: apps/registration/forms.py:108
|
||||
msgid "Join BDE Club"
|
||||
msgstr "BDE Mitglieder werden"
|
||||
|
||||
#: apps/registration/forms.py:114
|
||||
#: apps/registration/forms.py:115
|
||||
msgid "Join Kfet Club"
|
||||
msgstr "Kfet Mitglieder werden"
|
||||
|
||||
#: apps/registration/forms.py:123
|
||||
#: apps/registration/forms.py:124
|
||||
msgid "Join BDA Club"
|
||||
msgstr "BDA Mitglieder werden"
|
||||
|
||||
@ -2592,7 +2612,7 @@ msgid "The selected user is not validated. Please validate its account first"
|
||||
msgstr ""
|
||||
|
||||
#: apps/wei/forms/registration.py:59 apps/wei/models.py:126
|
||||
#: apps/wei/models.py:325
|
||||
#: apps/wei/models.py:326
|
||||
msgid "bus"
|
||||
msgstr "Bus"
|
||||
|
||||
@ -2631,6 +2651,7 @@ 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:"
|
||||
|
||||
@ -2738,23 +2759,27 @@ msgstr "Gesundheitsprobleme"
|
||||
msgid "emergency contact name"
|
||||
msgstr "Notfall-Kontakt"
|
||||
|
||||
#: apps/wei/models.py:244 apps/wei/templates/wei/weimembership_form.html:73
|
||||
#: apps/wei/models.py:240
|
||||
msgid "The emergency contact must not be a WEI participant"
|
||||
msgstr "Der Notfallkontakt darf kein WEI-Teilnehmer sein"
|
||||
|
||||
#: apps/wei/models.py:245 apps/wei/templates/wei/weimembership_form.html:73
|
||||
msgid "emergency contact phone"
|
||||
msgstr "Notfallkontakttelefon"
|
||||
|
||||
#: apps/wei/models.py:249 apps/wei/templates/wei/weimembership_form.html:52
|
||||
#: apps/wei/models.py:250 apps/wei/templates/wei/weimembership_form.html:52
|
||||
msgid "first year"
|
||||
msgstr "Erste Jahr"
|
||||
|
||||
#: apps/wei/models.py:250
|
||||
#: apps/wei/models.py:251
|
||||
msgid "Tells if the user is new in the school."
|
||||
msgstr "Gibt an, ob der USer neu in der Schule ist."
|
||||
|
||||
#: apps/wei/models.py:255
|
||||
#: apps/wei/models.py:256
|
||||
msgid "registration information"
|
||||
msgstr "Registrierung Detailen"
|
||||
|
||||
#: apps/wei/models.py:256
|
||||
#: apps/wei/models.py:257
|
||||
msgid ""
|
||||
"Information about the registration (buses for old members, survey for the "
|
||||
"new members), encoded in JSON"
|
||||
@ -2762,27 +2787,27 @@ msgstr ""
|
||||
"Informationen zur Registrierung (Busse für alte Mitglieder, Umfrage für neue "
|
||||
"Mitglieder), verschlüsselt in JSON"
|
||||
|
||||
#: apps/wei/models.py:314
|
||||
#: apps/wei/models.py:315
|
||||
msgid "WEI User"
|
||||
msgstr "WEI User"
|
||||
|
||||
#: apps/wei/models.py:315
|
||||
#: apps/wei/models.py:316
|
||||
msgid "WEI Users"
|
||||
msgstr "WEI Users"
|
||||
|
||||
#: apps/wei/models.py:335
|
||||
#: apps/wei/models.py:336
|
||||
msgid "team"
|
||||
msgstr "Team"
|
||||
|
||||
#: apps/wei/models.py:345
|
||||
#: apps/wei/models.py:346
|
||||
msgid "WEI registration"
|
||||
msgstr "WEI Registrierung"
|
||||
|
||||
#: apps/wei/models.py:349
|
||||
#: apps/wei/models.py:350
|
||||
msgid "WEI membership"
|
||||
msgstr "WEI Mitgliedschaft"
|
||||
|
||||
#: apps/wei/models.py:350
|
||||
#: apps/wei/models.py:351
|
||||
msgid "WEI memberships"
|
||||
msgstr "WEI Mitgliedschaften"
|
||||
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-09 11:55+0200\n"
|
||||
"POT-Creation-Date: 2023-08-31 13:25+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:199
|
||||
#: apps/member/models.py:204
|
||||
#: 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:307
|
||||
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
|
||||
#: 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:186
|
||||
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
|
||||
#: apps/activity/tables.py:84 apps/member/forms.py:193
|
||||
#: apps/registration/forms.py:93 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:191
|
||||
#: apps/activity/tables.py:86 apps/member/forms.py:198
|
||||
#: apps/note/templates/note/transaction_form.html:138
|
||||
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
|
||||
#: apps/registration/forms.py:98 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:226
|
||||
#: apps/member/admin.py:50 apps/member/models.py:231
|
||||
#: 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:231
|
||||
#: apps/member/admin.py:51 apps/member/models.py:236
|
||||
#: 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:319
|
||||
#: apps/member/admin.py:65 apps/member/models.py:324
|
||||
msgid "roles"
|
||||
msgstr "papel"
|
||||
|
||||
#: apps/member/admin.py:66 apps/member/models.py:333
|
||||
#: apps/member/admin.py:66 apps/member/models.py:338
|
||||
msgid "fee"
|
||||
msgstr "pago"
|
||||
|
||||
@ -529,65 +529,81 @@ 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:79
|
||||
#: apps/member/forms.py:86
|
||||
msgid "select an image"
|
||||
msgstr "elegir una imagen"
|
||||
|
||||
#: apps/member/forms.py:80
|
||||
#: apps/member/forms.py:87
|
||||
msgid "Maximal size: 2MB"
|
||||
msgstr "Tamaño máximo : 2Mo"
|
||||
|
||||
#: apps/member/forms.py:105
|
||||
#: apps/member/forms.py:112
|
||||
msgid "This image cannot be loaded."
|
||||
msgstr "Esta imagen no puede ser cargada."
|
||||
|
||||
#: apps/member/forms.py:141 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:34 apps/registration/views.py:266
|
||||
#: apps/member/forms.py:148 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:35 apps/registration/views.py:266
|
||||
msgid "An alias with a similar name already exists."
|
||||
msgstr "Un alias similar ya existe."
|
||||
|
||||
#: apps/member/forms.py:165
|
||||
#: apps/member/forms.py:172
|
||||
msgid "Inscription paid by Société Générale"
|
||||
msgstr "Registración pagadas por Société Générale"
|
||||
|
||||
#: apps/member/forms.py:167
|
||||
#: apps/member/forms.py:174
|
||||
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:172 apps/registration/forms.py:79
|
||||
#: apps/member/forms.py:179 apps/registration/forms.py:80
|
||||
#: apps/wei/forms/registration.py:91
|
||||
msgid "Credit type"
|
||||
msgstr "Tipo de crédito"
|
||||
|
||||
#: apps/member/forms.py:173 apps/registration/forms.py:80
|
||||
#: apps/member/forms.py:180 apps/registration/forms.py:81
|
||||
#: apps/wei/forms/registration.py:92
|
||||
msgid "No credit"
|
||||
msgstr "No crédito"
|
||||
|
||||
#: apps/member/forms.py:175
|
||||
#: apps/member/forms.py:182
|
||||
msgid "You can credit the note of the user."
|
||||
msgstr "Usted puede acreditar la note del usuario."
|
||||
|
||||
#: apps/member/forms.py:179 apps/registration/forms.py:85
|
||||
#: apps/member/forms.py:186 apps/registration/forms.py:86
|
||||
#: apps/wei/forms/registration.py:97
|
||||
msgid "Credit amount"
|
||||
msgstr "Valor del crédito"
|
||||
|
||||
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
|
||||
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
|
||||
#: apps/wei/forms/registration.py:114
|
||||
msgid "Bank"
|
||||
msgstr "Banco"
|
||||
|
||||
#: apps/member/forms.py:223
|
||||
#: apps/member/forms.py:230
|
||||
msgid "User"
|
||||
msgstr "Usuario"
|
||||
|
||||
#: apps/member/forms.py:237
|
||||
#: apps/member/forms.py:244
|
||||
msgid "Roles"
|
||||
msgstr "Papeles"
|
||||
|
||||
@ -772,15 +788,19 @@ msgstr "correo electrónico confirmado"
|
||||
msgid "registration valid"
|
||||
msgstr "registración valida"
|
||||
|
||||
#: apps/member/models.py:162 apps/member/models.py:163
|
||||
#: apps/member/models.py:138
|
||||
msgid "VSS charter read"
|
||||
msgstr "Carta VSS leída"
|
||||
|
||||
#: apps/member/models.py:167 apps/member/models.py:168
|
||||
msgid "user profile"
|
||||
msgstr "perfil usuario"
|
||||
|
||||
#: apps/member/models.py:173
|
||||
#: apps/member/models.py:178
|
||||
msgid "Activate your Note Kfet account"
|
||||
msgstr "Active su cuenta Note Kfet"
|
||||
|
||||
#: apps/member/models.py:204
|
||||
#: apps/member/models.py:209
|
||||
#: 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
|
||||
@ -789,87 +809,87 @@ msgstr "Active su cuenta Note Kfet"
|
||||
msgid "email"
|
||||
msgstr "correo electrónico"
|
||||
|
||||
#: apps/member/models.py:211
|
||||
#: apps/member/models.py:216
|
||||
msgid "parent club"
|
||||
msgstr "club pariente"
|
||||
|
||||
#: apps/member/models.py:220
|
||||
#: apps/member/models.py:225
|
||||
msgid "require memberships"
|
||||
msgstr "necesita afiliaciones"
|
||||
|
||||
#: apps/member/models.py:221
|
||||
#: apps/member/models.py:226
|
||||
msgid "Uncheck if this club don't require memberships."
|
||||
msgstr "Desmarcar si este club no usa afiliaciones."
|
||||
|
||||
#: apps/member/models.py:237
|
||||
#: apps/member/models.py:242
|
||||
#: apps/member/templates/member/includes/club_info.html:26
|
||||
msgid "membership duration"
|
||||
msgstr "duración de la afiliación"
|
||||
|
||||
#: apps/member/models.py:238
|
||||
#: apps/member/models.py:243
|
||||
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:245
|
||||
#: apps/member/models.py:250
|
||||
#: apps/member/templates/member/includes/club_info.html:16
|
||||
msgid "membership start"
|
||||
msgstr "inicio de la afiliación"
|
||||
|
||||
#: apps/member/models.py:246
|
||||
#: apps/member/models.py:251
|
||||
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:252
|
||||
#: apps/member/models.py:257
|
||||
#: apps/member/templates/member/includes/club_info.html:21
|
||||
msgid "membership end"
|
||||
msgstr "fin de la afiliación"
|
||||
|
||||
#: apps/member/models.py:253
|
||||
#: apps/member/models.py:258
|
||||
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:288 apps/member/models.py:313
|
||||
#: apps/member/models.py:293 apps/member/models.py:318
|
||||
#: apps/note/models/notes.py:176
|
||||
msgid "club"
|
||||
msgstr "club"
|
||||
|
||||
#: apps/member/models.py:289
|
||||
#: apps/member/models.py:294
|
||||
msgid "clubs"
|
||||
msgstr "clubs"
|
||||
|
||||
#: apps/member/models.py:324
|
||||
#: apps/member/models.py:329
|
||||
msgid "membership starts on"
|
||||
msgstr "afiliación empezá el"
|
||||
|
||||
#: apps/member/models.py:328
|
||||
#: apps/member/models.py:333
|
||||
msgid "membership ends on"
|
||||
msgstr "afiliación termina el"
|
||||
|
||||
#: apps/member/models.py:430
|
||||
#: apps/member/models.py:435
|
||||
#, 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:439 apps/member/views.py:712
|
||||
#: apps/member/models.py:444 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:451 apps/member/views.py:721
|
||||
#: apps/member/models.py:456 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:504
|
||||
#: apps/member/models.py:509
|
||||
#, python-brace-format
|
||||
msgid "Membership of {user} for the club {club}"
|
||||
msgstr "Afiliación of {user} for the club {club}"
|
||||
|
||||
#: apps/member/models.py:507 apps/note/models/transactions.py:389
|
||||
#: apps/member/models.py:512 apps/note/models/transactions.py:389
|
||||
msgid "membership"
|
||||
msgstr "afiliación"
|
||||
|
||||
#: apps/member/models.py:508
|
||||
#: apps/member/models.py:513
|
||||
msgid "memberships"
|
||||
msgstr "afiliaciones"
|
||||
|
||||
@ -1845,7 +1865,7 @@ msgstr ""
|
||||
msgid "for club"
|
||||
msgstr "interesa el club"
|
||||
|
||||
#: apps/permission/models.py:350 apps/permission/models.py:351
|
||||
#: apps/permission/models.py:351 apps/permission/models.py:352
|
||||
msgid "role permissions"
|
||||
msgstr "permisos por papeles"
|
||||
|
||||
@ -1963,15 +1983,15 @@ msgstr "Todos los permisos"
|
||||
msgid "registration"
|
||||
msgstr "afiliación"
|
||||
|
||||
#: apps/registration/forms.py:40
|
||||
#: apps/registration/forms.py:41
|
||||
msgid "This email address is already used."
|
||||
msgstr "Este correo electrónico ya esta utilizado."
|
||||
|
||||
#: apps/registration/forms.py:60
|
||||
#: apps/registration/forms.py:61
|
||||
msgid "Register to the WEI"
|
||||
msgstr "Registrarse en el WEI"
|
||||
|
||||
#: apps/registration/forms.py:62
|
||||
#: apps/registration/forms.py:63
|
||||
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."
|
||||
@ -1979,15 +1999,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:107
|
||||
#: apps/registration/forms.py:108
|
||||
msgid "Join BDE Club"
|
||||
msgstr "Afiliarse al club BDE"
|
||||
|
||||
#: apps/registration/forms.py:114
|
||||
#: apps/registration/forms.py:115
|
||||
msgid "Join Kfet Club"
|
||||
msgstr "Afiliarse al club Kfet"
|
||||
|
||||
#: apps/registration/forms.py:123
|
||||
#: apps/registration/forms.py:124
|
||||
msgid "Join BDA Club"
|
||||
msgstr "Afiliarse al club BDA"
|
||||
|
||||
@ -2562,7 +2582,7 @@ msgstr ""
|
||||
"El usuario seleccionado no ha sido validado. Validar esta cuenta primero"
|
||||
|
||||
#: apps/wei/forms/registration.py:59 apps/wei/models.py:126
|
||||
#: apps/wei/models.py:325
|
||||
#: apps/wei/models.py:326
|
||||
msgid "bus"
|
||||
msgstr "bus"
|
||||
|
||||
@ -2601,6 +2621,7 @@ 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 :"
|
||||
|
||||
@ -2708,23 +2729,27 @@ msgstr "problemas de salud"
|
||||
msgid "emergency contact name"
|
||||
msgstr "nombre del contacto de emergencia"
|
||||
|
||||
#: apps/wei/models.py:244 apps/wei/templates/wei/weimembership_form.html:73
|
||||
#: apps/wei/models.py:240
|
||||
msgid "The emergency contact must not be a WEI participant"
|
||||
msgstr "El contacto de emergencia no debe ser un participante de WEI"
|
||||
|
||||
#: apps/wei/models.py:245 apps/wei/templates/wei/weimembership_form.html:73
|
||||
msgid "emergency contact phone"
|
||||
msgstr "teléfono del contacto de emergencia"
|
||||
|
||||
#: apps/wei/models.py:249 apps/wei/templates/wei/weimembership_form.html:52
|
||||
#: apps/wei/models.py:250 apps/wei/templates/wei/weimembership_form.html:52
|
||||
msgid "first year"
|
||||
msgstr "primer año"
|
||||
|
||||
#: apps/wei/models.py:250
|
||||
#: apps/wei/models.py:251
|
||||
msgid "Tells if the user is new in the school."
|
||||
msgstr "Indica si el usuario es nuevo en la escuela."
|
||||
|
||||
#: apps/wei/models.py:255
|
||||
#: apps/wei/models.py:256
|
||||
msgid "registration information"
|
||||
msgstr "informaciones sobre la afiliación"
|
||||
|
||||
#: apps/wei/models.py:256
|
||||
#: apps/wei/models.py:257
|
||||
msgid ""
|
||||
"Information about the registration (buses for old members, survey for the "
|
||||
"new members), encoded in JSON"
|
||||
@ -2732,27 +2757,27 @@ msgstr ""
|
||||
"Informaciones sobre la afiliacion (bus para miembros ancianos, cuestionario "
|
||||
"para los nuevos miembros), registrado en JSON"
|
||||
|
||||
#: apps/wei/models.py:314
|
||||
#: apps/wei/models.py:315
|
||||
msgid "WEI User"
|
||||
msgstr "Participante WEI"
|
||||
|
||||
#: apps/wei/models.py:315
|
||||
#: apps/wei/models.py:316
|
||||
msgid "WEI Users"
|
||||
msgstr "Participantes WEI"
|
||||
|
||||
#: apps/wei/models.py:335
|
||||
#: apps/wei/models.py:336
|
||||
msgid "team"
|
||||
msgstr "equipo"
|
||||
|
||||
#: apps/wei/models.py:345
|
||||
#: apps/wei/models.py:346
|
||||
msgid "WEI registration"
|
||||
msgstr "Apuntación al WEI"
|
||||
|
||||
#: apps/wei/models.py:349
|
||||
#: apps/wei/models.py:350
|
||||
msgid "WEI membership"
|
||||
msgstr "Afiliación al WEI"
|
||||
|
||||
#: apps/wei/models.py:350
|
||||
#: apps/wei/models.py:351
|
||||
msgid "WEI memberships"
|
||||
msgstr "Afiliaciones al WEI"
|
||||
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-09 11:55+0200\n"
|
||||
"POT-Creation-Date: 2023-08-31 13:25+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:199
|
||||
#: apps/member/models.py:204
|
||||
#: 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:307
|
||||
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:312
|
||||
#: 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:186
|
||||
#: apps/registration/forms.py:92 apps/treasury/forms.py:131
|
||||
#: apps/activity/tables.py:84 apps/member/forms.py:193
|
||||
#: apps/registration/forms.py:93 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:191
|
||||
#: apps/activity/tables.py:86 apps/member/forms.py:198
|
||||
#: apps/note/templates/note/transaction_form.html:138
|
||||
#: apps/registration/forms.py:97 apps/treasury/forms.py:133
|
||||
#: apps/registration/forms.py:98 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:226
|
||||
#: apps/member/admin.py:50 apps/member/models.py:231
|
||||
#: 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:231
|
||||
#: apps/member/admin.py:51 apps/member/models.py:236
|
||||
#: 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:319
|
||||
#: apps/member/admin.py:65 apps/member/models.py:324
|
||||
msgid "roles"
|
||||
msgstr "rôles"
|
||||
|
||||
#: apps/member/admin.py:66 apps/member/models.py:333
|
||||
#: apps/member/admin.py:66 apps/member/models.py:338
|
||||
msgid "fee"
|
||||
msgstr "cotisation"
|
||||
|
||||
@ -531,65 +531,81 @@ 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:79
|
||||
#: apps/member/forms.py:86
|
||||
msgid "select an image"
|
||||
msgstr "choisissez une image"
|
||||
|
||||
#: apps/member/forms.py:80
|
||||
#: apps/member/forms.py:87
|
||||
msgid "Maximal size: 2MB"
|
||||
msgstr "Taille maximale : 2 Mo"
|
||||
|
||||
#: apps/member/forms.py:105
|
||||
#: apps/member/forms.py:112
|
||||
msgid "This image cannot be loaded."
|
||||
msgstr "Cette image ne peut pas être chargée."
|
||||
|
||||
#: apps/member/forms.py:141 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:34 apps/registration/views.py:266
|
||||
#: apps/member/forms.py:148 apps/member/views.py:103
|
||||
#: apps/registration/forms.py:35 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:165
|
||||
#: apps/member/forms.py:172
|
||||
msgid "Inscription paid by Société Générale"
|
||||
msgstr "Inscription payée par la Société générale"
|
||||
|
||||
#: apps/member/forms.py:167
|
||||
#: apps/member/forms.py:174
|
||||
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:172 apps/registration/forms.py:79
|
||||
#: apps/member/forms.py:179 apps/registration/forms.py:80
|
||||
#: apps/wei/forms/registration.py:91
|
||||
msgid "Credit type"
|
||||
msgstr "Type de rechargement"
|
||||
|
||||
#: apps/member/forms.py:173 apps/registration/forms.py:80
|
||||
#: apps/member/forms.py:180 apps/registration/forms.py:81
|
||||
#: apps/wei/forms/registration.py:92
|
||||
msgid "No credit"
|
||||
msgstr "Pas de rechargement"
|
||||
|
||||
#: apps/member/forms.py:175
|
||||
#: apps/member/forms.py:182
|
||||
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:179 apps/registration/forms.py:85
|
||||
#: apps/member/forms.py:186 apps/registration/forms.py:86
|
||||
#: apps/wei/forms/registration.py:97
|
||||
msgid "Credit amount"
|
||||
msgstr "Montant à créditer"
|
||||
|
||||
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:102 apps/treasury/forms.py:135
|
||||
#: apps/member/forms.py:203 apps/note/templates/note/transaction_form.html:144
|
||||
#: apps/registration/forms.py:103 apps/treasury/forms.py:135
|
||||
#: apps/wei/forms/registration.py:114
|
||||
msgid "Bank"
|
||||
msgstr "Banque"
|
||||
|
||||
#: apps/member/forms.py:223
|
||||
#: apps/member/forms.py:230
|
||||
msgid "User"
|
||||
msgstr "Utilisateur"
|
||||
|
||||
#: apps/member/forms.py:237
|
||||
#: apps/member/forms.py:244
|
||||
msgid "Roles"
|
||||
msgstr "Rôles"
|
||||
|
||||
@ -774,15 +790,19 @@ msgstr "adresse email confirmée"
|
||||
msgid "registration valid"
|
||||
msgstr "inscription valide"
|
||||
|
||||
#: apps/member/models.py:162 apps/member/models.py:163
|
||||
#: apps/member/models.py:138
|
||||
msgid "VSS charter read"
|
||||
msgstr "Charte VSS lue"
|
||||
|
||||
#: apps/member/models.py:167 apps/member/models.py:168
|
||||
msgid "user profile"
|
||||
msgstr "profil utilisateur"
|
||||
|
||||
#: apps/member/models.py:173
|
||||
#: apps/member/models.py:178
|
||||
msgid "Activate your Note Kfet account"
|
||||
msgstr "Activez votre compte Note Kfet"
|
||||
|
||||
#: apps/member/models.py:204
|
||||
#: apps/member/models.py:209
|
||||
#: 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
|
||||
@ -791,88 +811,88 @@ msgstr "Activez votre compte Note Kfet"
|
||||
msgid "email"
|
||||
msgstr "courriel"
|
||||
|
||||
#: apps/member/models.py:211
|
||||
#: apps/member/models.py:216
|
||||
msgid "parent club"
|
||||
msgstr "club parent"
|
||||
|
||||
#: apps/member/models.py:220
|
||||
#: apps/member/models.py:225
|
||||
msgid "require memberships"
|
||||
msgstr "nécessite des adhésions"
|
||||
|
||||
#: apps/member/models.py:221
|
||||
#: apps/member/models.py:226
|
||||
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:237
|
||||
#: apps/member/models.py:242
|
||||
#: apps/member/templates/member/includes/club_info.html:26
|
||||
msgid "membership duration"
|
||||
msgstr "durée de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:238
|
||||
#: apps/member/models.py:243
|
||||
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:245
|
||||
#: apps/member/models.py:250
|
||||
#: apps/member/templates/member/includes/club_info.html:16
|
||||
msgid "membership start"
|
||||
msgstr "début de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:246
|
||||
#: apps/member/models.py:251
|
||||
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:252
|
||||
#: apps/member/models.py:257
|
||||
#: apps/member/templates/member/includes/club_info.html:21
|
||||
msgid "membership end"
|
||||
msgstr "fin de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:253
|
||||
#: apps/member/models.py:258
|
||||
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:288 apps/member/models.py:313
|
||||
#: apps/member/models.py:293 apps/member/models.py:318
|
||||
#: apps/note/models/notes.py:176
|
||||
msgid "club"
|
||||
msgstr "club"
|
||||
|
||||
#: apps/member/models.py:289
|
||||
#: apps/member/models.py:294
|
||||
msgid "clubs"
|
||||
msgstr "clubs"
|
||||
|
||||
#: apps/member/models.py:324
|
||||
#: apps/member/models.py:329
|
||||
msgid "membership starts on"
|
||||
msgstr "l'adhésion commence le"
|
||||
|
||||
#: apps/member/models.py:328
|
||||
#: apps/member/models.py:333
|
||||
msgid "membership ends on"
|
||||
msgstr "l'adhésion finit le"
|
||||
|
||||
#: apps/member/models.py:430
|
||||
#: apps/member/models.py:435
|
||||
#, 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:439 apps/member/views.py:712
|
||||
#: apps/member/models.py:444 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:451 apps/member/views.py:721
|
||||
#: apps/member/models.py:456 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:504
|
||||
#: apps/member/models.py:509
|
||||
#, python-brace-format
|
||||
msgid "Membership of {user} for the club {club}"
|
||||
msgstr "Adhésion de {user} pour le club {club}"
|
||||
|
||||
#: apps/member/models.py:507 apps/note/models/transactions.py:389
|
||||
#: apps/member/models.py:512 apps/note/models/transactions.py:389
|
||||
msgid "membership"
|
||||
msgstr "adhésion"
|
||||
|
||||
#: apps/member/models.py:508
|
||||
#: apps/member/models.py:513
|
||||
msgid "memberships"
|
||||
msgstr "adhésions"
|
||||
|
||||
@ -1851,7 +1871,7 @@ msgstr ""
|
||||
msgid "for club"
|
||||
msgstr "s'applique au club"
|
||||
|
||||
#: apps/permission/models.py:350 apps/permission/models.py:351
|
||||
#: apps/permission/models.py:351 apps/permission/models.py:352
|
||||
msgid "role permissions"
|
||||
msgstr "permissions par rôles"
|
||||
|
||||
@ -1972,15 +1992,15 @@ msgstr "Tous les droits"
|
||||
msgid "registration"
|
||||
msgstr "inscription"
|
||||
|
||||
#: apps/registration/forms.py:40
|
||||
#: apps/registration/forms.py:41
|
||||
msgid "This email address is already used."
|
||||
msgstr "Cet email est déjà pris."
|
||||
|
||||
#: apps/registration/forms.py:60
|
||||
#: apps/registration/forms.py:61
|
||||
msgid "Register to the WEI"
|
||||
msgstr "S'inscrire au WEI"
|
||||
|
||||
#: apps/registration/forms.py:62
|
||||
#: apps/registration/forms.py:63
|
||||
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."
|
||||
@ -1989,15 +2009,15 @@ msgstr ""
|
||||
"pourrez toujours vous inscrire plus tard, après avoir validé votre compte à "
|
||||
"la Kfet."
|
||||
|
||||
#: apps/registration/forms.py:107
|
||||
#: apps/registration/forms.py:108
|
||||
msgid "Join BDE Club"
|
||||
msgstr "Adhérer au club BDE"
|
||||
|
||||
#: apps/registration/forms.py:114
|
||||
#: apps/registration/forms.py:115
|
||||
msgid "Join Kfet Club"
|
||||
msgstr "Adhérer au club Kfet"
|
||||
|
||||
#: apps/registration/forms.py:123
|
||||
#: apps/registration/forms.py:124
|
||||
msgid "Join BDA Club"
|
||||
msgstr "Adhérer au club BDA"
|
||||
|
||||
@ -2574,7 +2594,7 @@ msgstr ""
|
||||
"compte"
|
||||
|
||||
#: apps/wei/forms/registration.py:59 apps/wei/models.py:126
|
||||
#: apps/wei/models.py:325
|
||||
#: apps/wei/models.py:326
|
||||
msgid "bus"
|
||||
msgstr "bus"
|
||||
|
||||
@ -2613,6 +2633,7 @@ 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 :"
|
||||
|
||||
@ -2720,23 +2741,29 @@ msgstr "problèmes de santé"
|
||||
msgid "emergency contact name"
|
||||
msgstr "nom du contact en cas d'urgence"
|
||||
|
||||
#: apps/wei/models.py:244 apps/wei/templates/wei/weimembership_form.html:73
|
||||
#: 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"
|
||||
|
||||
#: apps/wei/models.py:245 apps/wei/templates/wei/weimembership_form.html:73
|
||||
msgid "emergency contact phone"
|
||||
msgstr "téléphone du contact en cas d'urgence"
|
||||
|
||||
#: apps/wei/models.py:249 apps/wei/templates/wei/weimembership_form.html:52
|
||||
#: apps/wei/models.py:250 apps/wei/templates/wei/weimembership_form.html:52
|
||||
msgid "first year"
|
||||
msgstr "première année"
|
||||
|
||||
#: apps/wei/models.py:250
|
||||
#: apps/wei/models.py:251
|
||||
msgid "Tells if the user is new in the school."
|
||||
msgstr "Indique si l'utilisateur est nouveau dans l'école."
|
||||
|
||||
#: apps/wei/models.py:255
|
||||
#: apps/wei/models.py:256
|
||||
msgid "registration information"
|
||||
msgstr "informations sur l'inscription"
|
||||
|
||||
#: apps/wei/models.py:256
|
||||
#: apps/wei/models.py:257
|
||||
msgid ""
|
||||
"Information about the registration (buses for old members, survey for the "
|
||||
"new members), encoded in JSON"
|
||||
@ -2744,27 +2771,27 @@ msgstr ""
|
||||
"Informations sur l'inscription (bus pour les 2A+, questionnaire pour les "
|
||||
"1A), encodées en JSON"
|
||||
|
||||
#: apps/wei/models.py:314
|
||||
#: apps/wei/models.py:315
|
||||
msgid "WEI User"
|
||||
msgstr "Participant au WEI"
|
||||
|
||||
#: apps/wei/models.py:315
|
||||
#: apps/wei/models.py:316
|
||||
msgid "WEI Users"
|
||||
msgstr "Participants au WEI"
|
||||
|
||||
#: apps/wei/models.py:335
|
||||
#: apps/wei/models.py:336
|
||||
msgid "team"
|
||||
msgstr "équipe"
|
||||
|
||||
#: apps/wei/models.py:345
|
||||
#: apps/wei/models.py:346
|
||||
msgid "WEI registration"
|
||||
msgstr "Inscription au WEI"
|
||||
|
||||
#: apps/wei/models.py:349
|
||||
#: apps/wei/models.py:350
|
||||
msgid "WEI membership"
|
||||
msgstr "Adhésion au WEI"
|
||||
|
||||
#: apps/wei/models.py:350
|
||||
#: apps/wei/models.py:351
|
||||
msgid "WEI memberships"
|
||||
msgstr "Adhésions au WEI"
|
||||
|
||||
|
@ -96,7 +96,7 @@ function displayStyle (note) {
|
||||
if (!note) { return '' }
|
||||
const balance = note.balance
|
||||
var css = ''
|
||||
if (balance < -5000) { css += ' text-danger bg-dark' }
|
||||
if (balance < -2000) { css += ' text-danger bg-dark' }
|
||||
else if (balance < -1000) { css += ' text-danger' }
|
||||
else if (balance < 0) { css += ' text-warning' }
|
||||
if (!note.email_confirmed) { css += ' bg-primary' }
|
||||
|
Reference in New Issue
Block a user