diff --git a/.gitignore b/.gitignore index b31756b..caa056f 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,5 @@ ansible/host_vars/*.yaml !ansible/host_vars/bde* ansible/hosts +apps/member/migrations +apps/wei/migrations diff --git a/.gitpod.yml b/.gitpod.yml index 6de1ba5..b488382 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -3,39 +3,33 @@ # and commit this file to your remote git repository to share the goodness with others. tasks: + - name: Apt update + init: sudo apt update - name: Apt install - command: | - sudo apt update - sudo apt install --no-install-recommends -y \ + init: sudo apt install --no-install-recommends -y \ ipython3 python3-setuptools python3-venv python3-dev \ texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome git - gp sync-done apt - name : Install requirements - init : gp sync-await apt - command: | - pip3 install -r requirements.txt - gp sync-done pip + init: pip3 install -r requirements.txt - name : Setup env - command: cp .env_example .env - - name: Django Init - init : gp sync-await pip - command: | - python3 manage.py collectstatic --noinput - python3 manage.py compilemessages - python3 manage.py makemigrations - python3 manage.py migrate - python3 manage.py loaddata initial - python3 manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'adminpass')" - gp sync-done django - + init: cp .env_example .env + - name: Django collectstatic + init: python3 manage.py collectstatic --noinput + - name: Django compilemessages + init: python3 manage.py compilemessages + - name: Django makemigrations + init: python3 manage.py makemigrations + - name: Django migrate + init: python3 manage.py migrate + - name: Django loaddata + init: python3 manage.py loaddata initial + - name: Django create dev superuser + init: python3 manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'adminpass')" - name: Django start server - init : gp sync-await django command: python3 manage.py runserver 0.0.0.0:8000 ports: - - name: Web Dev Server - port: 8000 - visibility: public - + - port: 8000 + onOpen: open-preview diff --git a/README.md b/README.md index 06ba125..db695cf 100644 --- a/README.md +++ b/README.md @@ -35,27 +35,11 @@ Bien que cela permette de créer une instance sur toutes les distributions, texlive-bin gettext ttf-font-awesome git $ paru -S bootstrap jquery # AUR only, need manuel install bootstrap4 and popper.js ``` - Pour Arch il faut installer manuellement libjs-bootstrap4, popper.js et jquery par l'AUR : - ```bash - yay -S jquery - ``` - ```bash - mkdir temp - cd temp - curl http://fr.archive.ubuntu.com/ubuntu/pool/universe/p/popper.js/libjs-popper.js_1.16.1+ds-6_all.deb --output libjs-popper.js_1.16.1+ds-6_all.deb - curl http://fr.archive.ubuntu.com/ubuntu/pool/universe/t/twitter-bootstrap4/libjs-bootstrap4_4.6.1+dfsg1-4_all.deb -o libjs-bootstrap4_4.6.1+dfsg1-4_all.deb # Dl paquet Debian - ar vx libjs-bootstrap4_4.6.1+dfsg1-4_all.deb # Unpack deb - ar -xvf data.tar.zst # Extract files - ar vx libjs-popper.js_1.16.1+ds-6_all.deb # Unpack deb - ar -xvf data.tar.zst # Extract files - sudo cp -Rp usr/* /usr # Copy file to correct locations - ``` - Proposer un packaging correct pour Arch de ce paquet serait une bonne idée. 2. **Clonage du dépot** là où vous voulez : ```bash - $ git clone git@github.com:jbdoderlein/notes-ker-lann.git --recursive && cd notes-ker-lann + $ git clone git@gitlab.crans.org:bde/nk20.git --recursive && cd nk20 ``` 3. **Création d'un environment de travail Python décorrélé du système.** @@ -145,13 +129,13 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous. nginx python3-venv git acl ``` -2. **Clonage du dépot** dans `/var/www/notes-ker-lann`, +2. **Clonage du dépot** dans `/var/www/note_kfet`, ```bash - $ sudo mkdir -p /var/www/notes-ker-lann && cd /var/www/notes-ker-lann + $ sudo mkdir -p /var/www/note_kfet && cd /var/www/note_kfet $ sudo chown www-data:www-data . $ sudo chmod g+rwx . - $ sudo -u www-data git clone https://github.com/jbdoderlein/notes-ker-lann.git --recursive + $ sudo -u www-data git clone https://gitlab.crans.org/bde/nk20.git --recursive ``` 3. **Création d'un environment de travail Python décorrélé du système.** @@ -168,19 +152,19 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous. ```bash $ cp nginx_note.conf_example nginx_note.conf - $ sudo ln -sf /var/www/notes-ker-lann/nginx_note.conf /etc/nginx/sites-enabled/ + $ sudo ln -sf /var/www/note_kfet/nginx_note.conf /etc/nginx/sites-enabled/ ``` Si l'on a un emperor (plusieurs instance uwsgi): ```bash - $ sudo ln -sf /var/www/notes-ker-lann/uwsgi_note.ini /etc/uwsgi/sites/ + $ sudo ln -sf /var/www/note_kfet/uwsgi_note.ini /etc/uwsgi/sites/ ``` Sinon si on est dans le cas habituel : ```bash - $ sudo ln -sf /var/www/notes-ker-lann/uwsgi_note.ini /etc/uwsgi/apps-enabled/ + $ sudo ln -sf /var/www/note_kfet/uwsgi_note.ini /etc/uwsgi/apps-enabled/ ``` Le touch-reload est activé par défault, pour redémarrer la note il suffit donc de faire `touch uwsgi_note.ini`. @@ -235,7 +219,7 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous. DJANGO_DB_PASSWORD=CHANGE_ME DJANGO_DB_PORT= DJANGO_SECRET_KEY=CHANGE_ME - DJANGO_SETTINGS_MODULE="notes-ker-lann.settings + DJANGO_SETTINGS_MODULE="note_kfet.settings NOTE_URL=localhost # URL où accéder à la note CONTACT_EMAIL=tresorerie.bde@localhost # Le reste n'est utile qu'en production, pour configurer l'envoi des mails @@ -263,21 +247,21 @@ Il est possible de travailler sur une instance Docker. Pour construire l'image Docker `nk20`, ``` -git clone https://github.com/jbdoderlein/notes-ker-lann.git/ --recursive && cd notes-ker-lann -docker build . -t notes-ker-lann +git clone https://gitlab.crans.org/bde/nk20/ --recursive && cd nk20 +docker build . -t nk20 ``` -Ensuite pour lancer la note de Ker Lann en tant que vous (option `-u`), +Ensuite pour lancer la note Kfet en tant que vous (option `-u`), l'exposer sur son port 80 (option `-p`) et monter le code en écriture (option `-v`), ``` -docker run -it --rm -u $(id -u):$(id -g) -v "$(pwd):/var/www/notes-ker-lann/" -p 80:8080 nk20 +docker run -it --rm -u $(id -u):$(id -g) -v "$(pwd):/var/www/note_kfet/" -p 80:8080 nk20 ``` Si vous souhaitez lancer une commande spéciale, vous pouvez l'ajouter à la fin, par exemple, ``` -docker run -it --rm -u $(id -u):$(id -g) -v "$(pwd):/var/www/notes-ker-lann/" -p 80:8080 nk20 python3 ./manage.py createsuperuser +docker run -it --rm -u $(id -u):$(id -g) -v "$(pwd):/var/www/note_kfet/" -p 80:8080 nk20 python3 ./manage.py createsuperuser ``` #### Avec Docker Compose @@ -287,15 +271,15 @@ On vous conseilles de faire un fichier d'environnement `.env` en prenant exemple Pour par exemple utiliser le Docker de la note Kfet avec Traefik pour réaliser le HTTPS, ```YAML -notes-ker-lann: - build: /chemin/vers/le/code/notes-ker-lann +nk20: + build: /chemin/vers/le/code/nk20 volumes: - - /chemin/vers/le/code/notes-ker-lann:/var/www/notes-ker-lann/ - env_file: /chemin/vers/le/code/notes-ker-lann/.env + - /chemin/vers/le/code/nk20:/var/www/note_kfet/ + env_file: /chemin/vers/le/code/nk20/.env restart: always labels: - - "traefik.http.routers.notes-ker-lann.rule=Host(`ndd.example.com`)" - - "traefik.http.services.notes-ker-lann.loadbalancer.server.port=8080" + - "traefik.http.routers.nk20.rule=Host(`ndd.example.com`)" + - "traefik.http.services.nk20.loadbalancer.server.port=8080" ``` ## Documentation diff --git a/apps/activity/fixtures/initial.json b/apps/activity/fixtures/initial.json index 2ebec84..63c5009 100644 --- a/apps/activity/fixtures/initial.json +++ b/apps/activity/fixtures/initial.json @@ -1 +1,32 @@ -[{"model": "activity.activitytype", "pk": 4, "fields": {"name": "Activit\u00e9 gratuite ouverte", "manage_entries": false, "can_invite": true, "guest_entry_fee": 0}}, {"model": "activity.activitytype", "pk": 5, "fields": {"name": "Soir\u00e9e", "manage_entries": true, "can_invite": false, "guest_entry_fee": 500}}] \ No newline at end of file +[ + { + "model": "activity.activitytype", + "pk": 1, + "fields": { + "name": "Pot", + "manage_entries": true, + "can_invite": true, + "guest_entry_fee": 500 + } + }, + { + "model": "activity.activitytype", + "pk": 2, + "fields": { + "name": "Soir\u00e9e de club", + "manage_entries": false, + "can_invite": false, + "guest_entry_fee": 0 + } + }, + { + "model": "activity.activitytype", + "pk": 3, + "fields": { + "name": "Autre", + "manage_entries": false, + "can_invite": false, + "guest_entry_fee": 0 + } + } +] diff --git a/apps/activity/forms.py b/apps/activity/forms.py index a37a2bf..1ca98ce 100644 --- a/apps/activity/forms.py +++ b/apps/activity/forms.py @@ -20,9 +20,9 @@ from .models import Activity, Guest class ActivityForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # By default, the BDE club is attended - self.fields["attendees_club"].initial = Club.objects.get(name="BDE") - self.fields["attendees_club"].widget.attrs["placeholder"] = "BDE" + # By default, the Kfet club is attended + self.fields["attendees_club"].initial = Club.objects.get(name="Kfet") + self.fields["attendees_club"].widget.attrs["placeholder"] = "Kfet" clubs = list(Club.objects.filter(PermissionBackend .filter_queryset(get_current_request(), Club, "view")).all()) shuffle(clubs) diff --git a/apps/activity/migrations/0001_initial.py b/apps/activity/migrations/0001_initial.py index 1ead0b8..ba2d68d 100644 --- a/apps/activity/migrations/0001_initial.py +++ b/apps/activity/migrations/0001_initial.py @@ -1,7 +1,7 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 -import django.utils.timezone from django.db import migrations, models +import django.utils.timezone class Migration(migrations.Migration): @@ -18,7 +18,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, verbose_name='name')), ('description', models.TextField(verbose_name='description')), - ('location', models.CharField(blank=True, default='', help_text='Place where the activity is organized, eg. BDE.', max_length=255, verbose_name='location')), + ('location', models.CharField(blank=True, default='', help_text='Place where the activity is organized, eg. Kfet.', max_length=255, verbose_name='location')), ('date_start', models.DateTimeField(verbose_name='start date')), ('date_end', models.DateTimeField(verbose_name='end date')), ('valid', models.BooleanField(default=False, verbose_name='valid')), diff --git a/apps/activity/migrations/0002_initial.py b/apps/activity/migrations/0002_auto_20200904_2341.py similarity index 80% rename from apps/activity/migrations/0002_initial.py rename to apps/activity/migrations/0002_auto_20200904_2341.py index ca40bef..4afa74d 100644 --- a/apps/activity/migrations/0002_initial.py +++ b/apps/activity/migrations/0002_auto_20200904_2341.py @@ -1,8 +1,8 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 -import django.db.models.deletion from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -11,16 +11,58 @@ class Migration(migrations.Migration): dependencies = [ ('activity', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('member', '0001_initial'), ('note', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ + migrations.CreateModel( + name='GuestTransaction', + fields=[ + ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')), + ('entry', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='activity.Entry')), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + bases=('note.transaction',), + ), + migrations.AddField( + model_name='guest', + name='activity', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='activity.Activity'), + ), + migrations.AddField( + model_name='guest', + name='inviter', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='guests', to='note.NoteUser', verbose_name='inviter'), + ), + migrations.AddField( + model_name='entry', + name='activity', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='entries', to='activity.Activity', verbose_name='activity'), + ), + migrations.AddField( + model_name='entry', + name='guest', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='activity.Guest'), + ), + migrations.AddField( + model_name='entry', + name='note', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.NoteUser', verbose_name='note'), + ), + migrations.AddField( + model_name='activity', + name='activity_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='activity.ActivityType', verbose_name='type'), + ), migrations.AddField( model_name='activity', name='attendees_club', - field=models.ForeignKey(help_text='Club that is authorized to join the activity.', on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.club', verbose_name='attendees club'), + field=models.ForeignKey(help_text='Club that is authorized to join the activity. Mostly the Kfet club.', on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='attendees club'), ), migrations.AddField( model_name='activity', @@ -30,53 +72,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='activity', name='organizer', - field=models.ForeignKey(help_text='Club that organizes the activity. The entry fees will go to this club.', on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.club', verbose_name='organizer'), - ), - migrations.AddField( - model_name='activity', - name='activity_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='activity.activitytype', verbose_name='type'), - ), - migrations.AddField( - model_name='entry', - name='activity', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='entries', to='activity.activity', verbose_name='activity'), - ), - migrations.AddField( - model_name='entry', - name='note', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.noteuser', verbose_name='note'), - ), - migrations.AddField( - model_name='guest', - name='activity', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='activity.activity'), - ), - migrations.AddField( - model_name='guest', - name='inviter', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='guests', to='note.noteuser', verbose_name='inviter'), - ), - migrations.AddField( - model_name='entry', - name='guest', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='activity.guest'), - ), - migrations.CreateModel( - name='GuestTransaction', - fields=[ - ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.transaction')), - ('entry', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='activity.entry')), - ], - options={ - 'abstract': False, - 'base_manager_name': 'objects', - }, - bases=('note.transaction',), - ), - migrations.AlterUniqueTogether( - name='activity', - unique_together={('name', 'date_start', 'date_end')}, + field=models.ForeignKey(help_text='Club that organizes the activity. The entry fees will go to this club.', on_delete=django.db.models.deletion.PROTECT, related_name='+', to='member.Club', verbose_name='organizer'), ), migrations.AlterUniqueTogether( name='guest', @@ -86,4 +82,8 @@ class Migration(migrations.Migration): name='entry', unique_together={('activity', 'note', 'guest')}, ), + migrations.AlterUniqueTogether( + name='activity', + unique_together={('name', 'date_start', 'date_end')}, + ), ] diff --git a/apps/activity/models.py b/apps/activity/models.py index b9541cb..f8e5fab 100644 --- a/apps/activity/models.py +++ b/apps/activity/models.py @@ -73,7 +73,7 @@ class Activity(models.Model): max_length=255, blank=True, default="", - help_text=_("Place where the activity is organized, eg. BDE."), + help_text=_("Place where the activity is organized, eg. Kfet."), ) activity_type = models.ForeignKey( @@ -102,7 +102,7 @@ class Activity(models.Model): on_delete=models.PROTECT, related_name='+', verbose_name=_('attendees club'), - help_text=_("Club that is authorized to join the activity."), + help_text=_("Club that is authorized to join the activity. Mostly the Kfet club."), ) date_start = models.DateTimeField( diff --git a/apps/activity/templates/activity/activity_entry.html b/apps/activity/templates/activity/activity_entry.html index 22374dd..0286bdb 100644 --- a/apps/activity/templates/activity/activity_entry.html +++ b/apps/activity/templates/activity/activity_entry.html @@ -91,7 +91,7 @@ SPDX-License-Identifier: GPL-3.0-or-later }).done(function () { if (target.hasClass("table-info")) addMsg( - "{% trans "Entry done, but caution: the user is not a member." %}", + "{% trans "Entry done, but caution: the user is not a Kfet member." %}", "warning", 10000); else addMsg("Entry made!", "success", 4000); @@ -126,7 +126,7 @@ SPDX-License-Identifier: GPL-3.0-or-later }).done(function () { if (target.hasClass("table-info")) addMsg( - "{% trans "Entry done, but caution: the user is not a member." %}", + "{% trans "Entry done, but caution: the user is not a Kfet member." %}", "warning", 10000); else addMsg("{% trans "Entry done!" %}", "success", 4000); @@ -150,7 +150,8 @@ SPDX-License-Identifier: GPL-3.0-or-later "source": credit_id, "destination": target.attr('data-inviter'), "last_name": last_name, - "first_name": first_name + "first_name": first_name, + "bank": "" }).done(function () { makeTransaction(); reset(); diff --git a/apps/activity/templates/activity/includes/activity_info.html b/apps/activity/templates/activity/includes/activity_info.html index 8619cf0..a16ad33 100644 --- a/apps/activity/templates/activity/includes/activity_info.html +++ b/apps/activity/templates/activity/includes/activity_info.html @@ -40,7 +40,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ activity.attendees_club }}
{% trans 'can invite'|capfirst %}
-
{{ activity.activity_type.can_invite|yesno:_("yes,no,maybe") }}
+
{{ activity.activity_type.can_invite|yesno }}
{% if activity.activity_type.can_invite %}
{% trans 'guest entry fee'|capfirst %}
@@ -48,10 +48,10 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %}
{% trans 'valid'|capfirst %}
-
{{ activity.valid|yesno:_("yes,no,maybe") }}
+
{{ activity.valid|yesno }}
{% trans 'opened'|capfirst %}
-
{{ activity.open|yesno:_("yes,no,maybe") }}
+
{{ activity.open|yesno }}
diff --git a/apps/activity/tests/test_activities.py b/apps/activity/tests/test_activities.py index 1fafae7..1fcc776 100644 --- a/apps/activity/tests/test_activities.py +++ b/apps/activity/tests/test_activities.py @@ -36,10 +36,10 @@ class TestActivities(TestCase): name="Activity", description="This is a test activity\non two very very long lines\nbecause this is very important.", location="Earth", - activity_type=ActivityType.objects.get(name="Soir\u00e9e"), + activity_type=ActivityType.objects.get(name="Pot"), creater=self.user, - organizer=Club.objects.get(name="BDE"), - attendees_club=Club.objects.get(name="BDE"), + organizer=Club.objects.get(name="Kfet"), + attendees_club=Club.objects.get(name="Kfet"), date_start=timezone.now(), date_end=timezone.now() + timedelta(days=2), valid=True, @@ -70,10 +70,10 @@ class TestActivities(TestCase): name="Activity created", description="This activity was successfully created.", location="Earth", - activity_type=ActivityType.objects.get(name="Soir\u00e9e").id, + activity_type=ActivityType.objects.get(name="Soirée de club").id, creater=self.user.id, - organizer=Club.objects.get(name="BDE").id, - attendees_club=Club.objects.get(name="BDE").id, + organizer=Club.objects.get(name="Kfet").id, + attendees_club=Club.objects.get(name="Kfet").id, date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()), date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)), valid=True, @@ -100,10 +100,10 @@ class TestActivities(TestCase): name=str(self.activity) + " updated", description="This activity was successfully updated.", location="Earth", - activity_type=ActivityType.objects.get(name="Soir\u00e9e").id, + activity_type=ActivityType.objects.get(name="Autre").id, creater=self.user.id, - organizer=Club.objects.get(name="BDE").id, - attendees_club=Club.objects.get(name="BDE").id, + organizer=Club.objects.get(name="Kfet").id, + attendees_club=Club.objects.get(name="Kfet").id, date_start="{:%Y-%m-%d %H:%M}".format(timezone.now()), date_end="{:%Y-%m-%d %H:%M}".format(timezone.now() + timedelta(days=2)), valid=True, @@ -186,10 +186,10 @@ class TestActivityAPI(TestAPI): name="Activity", description="This is a test activity\non two very very long lines\nbecause this is very important.", location="Earth", - activity_type=ActivityType.objects.get(name="Activit\u00e9 gratuite ouverte"), + activity_type=ActivityType.objects.get(name="Pot"), creater=self.user, - organizer=Club.objects.get(name="BDE"), - attendees_club=Club.objects.get(name="BDE"), + organizer=Club.objects.get(name="Kfet"), + attendees_club=Club.objects.get(name="Kfet"), date_start=timezone.now(), date_end=timezone.now() + timedelta(days=2), valid=True, diff --git a/apps/activity/views.py b/apps/activity/views.py index 214e230..1f966c6 100644 --- a/apps/activity/views.py +++ b/apps/activity/views.py @@ -340,7 +340,7 @@ UID:{md5((activity.name + "$" + str(activity.id) + str(activity.date_start)).enc SUMMARY;CHARSET=UTF-8:{self.multilines(activity.name, 75, 22)} DTSTART;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_start)} DTEND;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_end)} -LOCATION:{self.multilines(activity.location, 75, 9) if activity.location else "BDA"} +LOCATION:{self.multilines(activity.location, 75, 9) if activity.location else "Kfet"} DESCRIPTION;CHARSET=UTF-8:""" + self.multilines(activity.description.replace("\n", "\\n"), 75, 26) + """ -- {activity.organizer.name} END:VEVENT diff --git a/apps/api/urls.py b/apps/api/urls.py index ee8c34e..5d8b8b9 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -2,8 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.conf import settings -from django.conf.urls import include -from django.urls import re_path as url +from django.conf.urls import url, include from rest_framework import routers from .views import UserInformationView @@ -39,6 +38,10 @@ if "logs" in settings.INSTALLED_APPS: from logs.api.urls import register_logs_urls register_logs_urls(router, 'logs') +if "wei" in settings.INSTALLED_APPS: + from wei.api.urls import register_wei_urls + register_wei_urls(router, 'wei') + app_name = 'api' # Wire up our API using automatic URL routing. diff --git a/apps/logs/migrations/0001_initial.py b/apps/logs/migrations/0001_initial.py index 73cafb9..e517edf 100644 --- a/apps/logs/migrations/0001_initial.py +++ b/apps/logs/migrations/0001_initial.py @@ -1,9 +1,9 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 -import django.db.models.deletion -import django.utils.timezone from django.conf import settings from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): @@ -11,8 +11,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('contenttypes', '0002_remove_content_type_name'), ] operations = [ @@ -22,11 +22,11 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('ip', models.GenericIPAddressField(blank=True, null=True, verbose_name='IP Address')), ('instance_pk', models.CharField(max_length=255, verbose_name='identifier')), - ('previous', models.TextField(blank=True, default='', verbose_name='previous data')), - ('data', models.TextField(blank=True, default='', verbose_name='new data')), + ('previous', models.TextField(null=True, verbose_name='previous data')), + ('data', models.TextField(null=True, verbose_name='new data')), ('action', models.CharField(choices=[('create', 'create'), ('edit', 'edit'), ('delete', 'delete')], default='edit', max_length=16, verbose_name='action')), ('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='timestamp')), - ('model', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype', verbose_name='model')), + ('model', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.ContentType', verbose_name='model')), ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='user')), ], options={ diff --git a/apps/logs/migrations/0002_replace_null_by_blank.py b/apps/logs/migrations/0002_replace_null_by_blank.py new file mode 100644 index 0000000..65fc4b1 --- /dev/null +++ b/apps/logs/migrations/0002_replace_null_by_blank.py @@ -0,0 +1,17 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('logs', '0001_initial'), + ] + + operations = [ + migrations.RunSQL( + "UPDATE logs_changelog SET previous = '' WHERE previous IS NULL;" + ), + migrations.RunSQL( + "UPDATE logs_changelog SET data = '' WHERE data IS NULL;" + ), + ] diff --git a/apps/logs/migrations/0003_remove_null_tag_on_charfields.py b/apps/logs/migrations/0003_remove_null_tag_on_charfields.py new file mode 100644 index 0000000..a6e3a58 --- /dev/null +++ b/apps/logs/migrations/0003_remove_null_tag_on_charfields.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.16 on 2020-09-06 19:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('logs', '0002_replace_null_by_blank'), + ] + + operations = [ + migrations.AlterField( + model_name='changelog', + name='data', + field=models.TextField(blank=True, default='', verbose_name='new data'), + ), + migrations.AlterField( + model_name='changelog', + name='previous', + field=models.TextField(blank=True, default='', verbose_name='previous data'), + ), + ] diff --git a/apps/member/forms.py b/apps/member/forms.py index 62e5525..ffa3b4c 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -19,12 +19,20 @@ from permission.models import PermissionMask, Role from .models import Profile, Club, Membership +class CustomAuthenticationForm(AuthenticationForm): + permission_mask = forms.ModelChoiceField( + label=_("Permission mask"), + queryset=PermissionMask.objects.order_by("rank"), + empty_label=None, + ) + + class UserForm(forms.ModelForm): - def get_validation_exclusions(self): + def _get_validation_exclusions(self): # Django usernames can only contain letters, numbers, @, ., +, - and _. # We want to allow users to have uncommon and unpractical usernames: # That is their problem, and we have normalized aliases for us. - return super().get_validation_exclusions() + ["username"] + return super()._get_validation_exclusions() + ["username"] class Meta: model = User @@ -60,7 +68,7 @@ class ProfileForm(forms.ModelForm): class Meta: model = Profile fields = '__all__' - exclude = ('user', 'email_confirmed', 'registration_valid', 'section' ) + exclude = ('user', 'email_confirmed', 'registration_valid', ) class ImageForm(forms.Form): @@ -106,7 +114,7 @@ class ImageForm(forms.Form): frame = frame.crop((x, y, x + w, y + h)) frame = frame.resize( (settings.PIC_WIDTH, settings.PIC_RATIO * settings.PIC_WIDTH), - Image.Resampling.LANCZOS, + Image.ANTIALIAS, ) frames.append(frame) @@ -178,6 +186,11 @@ class MembershipForm(forms.ModelForm): required=False, ) + bank = forms.CharField( + label=_("Bank"), + required=False, + ) + class Meta: model = Membership fields = ('user', 'date_start') @@ -214,7 +227,7 @@ class MembershipRolesForm(forms.ModelForm): ) roles = forms.ModelMultipleChoiceField( - queryset=Role.objects.all(), + queryset=Role.objects.filter(weirole=None).all(), label=_("Roles"), widget=CheckboxSelectMultiple(), ) diff --git a/apps/member/migrations/0001_initial.py b/apps/member/migrations/0001_initial.py index 27b85dd..be35756 100644 --- a/apps/member/migrations/0001_initial.py +++ b/apps/member/migrations/0001_initial.py @@ -1,10 +1,11 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 import datetime +from django.conf import settings +from django.db import migrations, models import django.db.models.deletion import django.utils.timezone import phonenumber_field.modelfields -from django.db import migrations, models class Migration(migrations.Migration): @@ -12,29 +13,10 @@ class Migration(migrations.Migration): initial = True dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.CreateModel( - name='Profile', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=50, null=True, region=None, verbose_name='phone number')), - ('section', models.CharField(blank=True, default='', help_text='Auto generated', max_length=255, verbose_name='section')), - ('department', models.CharField(choices=[('INFO', 'Informatique'), ('MATH', 'Mathématiques'), ('DEM', 'Droit - économie - management'), ('MECATRO', 'Mécatronique'), ('2SEP', 'Sciences du sport et éducation physique'), ('SE', 'Sciences pour l’Environnement'), ('EXT', 'Externe')], max_length=8, verbose_name='department')), - ('promotion', models.PositiveSmallIntegerField(default=2024, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion')), - ('address', models.CharField(blank=True, default='', max_length=255, verbose_name='address')), - ('paid', models.BooleanField(default=False, help_text='Tells if the user receive a salary.', verbose_name='paid')), - ('report_frequency', models.PositiveSmallIntegerField(default=0, verbose_name='report frequency (in days)')), - ('last_report', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last report date')), - ('email_confirmed', models.BooleanField(default=False, verbose_name='email confirmed')), - ('registration_valid', models.BooleanField(default=False, verbose_name='registration valid')), - ], - options={ - 'verbose_name': 'user profile', - 'verbose_name_plural': 'user profile', - }, - ), migrations.CreateModel( name='Club', fields=[ @@ -47,13 +29,36 @@ class Migration(migrations.Migration): ('membership_duration', models.PositiveIntegerField(blank=True, help_text='The longest time (in days) a membership can last (NULL = infinite).', null=True, verbose_name='membership duration')), ('membership_start', models.DateField(blank=True, help_text='Date from which the members can renew their membership.', null=True, verbose_name='membership start')), ('membership_end', models.DateField(blank=True, help_text='Maximal date of a membership, after which members must renew it.', null=True, verbose_name='membership end')), - ('parent_club', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='member.club', verbose_name='parent club')), ], options={ 'verbose_name': 'club', 'verbose_name_plural': 'clubs', }, ), + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=50, null=True, region=None, verbose_name='phone number')), + ('section', models.CharField(blank=True, help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, null=True, verbose_name='section')), + ('department', models.CharField(choices=[('A0', 'Informatics (A0)'), ('A1', 'Mathematics (A1)'), ('A2', 'Physics (A2)'), ("A'2", "Applied physics (A'2)"), ('A2', "Chemistry (A''2)"), ('A3', 'Biology (A3)'), ('B1234', 'SAPHIRE (B1234)'), ('B1', 'Mechanics (B1)'), ('B2', 'Civil engineering (B2)'), ('B3', 'Mechanical engineering (B3)'), ('B4', 'EEA (B4)'), ('C', 'Design (C)'), ('D2', 'Economy-management (D2)'), ('D3', 'Social sciences (D3)'), ('E', 'English (E)'), ('EXT', 'External (EXT)')], max_length=8, verbose_name='department')), + ('promotion', models.PositiveSmallIntegerField(default=2020, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion')), + ('address', models.CharField(blank=True, max_length=255, null=True, verbose_name='address')), + ('paid', models.BooleanField(default=False, help_text='Tells if the user receive a salary.', verbose_name='paid')), + ('ml_events_registration', models.CharField(blank=True, choices=[(None, 'No'), ('fr', 'Yes (receive them in french)'), ('en', 'Yes (receive them in english)')], default=None, max_length=2, null=True, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)')), + ('ml_sport_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the sport events of the campus (1 mail/week)')), + ('ml_art_registration', models.BooleanField(default=False, verbose_name='Register on the mailing list to stay informed of the art events of the campus (1 mail/week)')), + ('report_frequency', models.PositiveSmallIntegerField(default=0, verbose_name='report frequency (in days)')), + ('last_report', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last report date')), + ('email_confirmed', models.BooleanField(default=False, verbose_name='email confirmed')), + ('registration_valid', models.BooleanField(default=False, verbose_name='registration valid')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'user profile', + 'verbose_name_plural': 'user profile', + }, + ), migrations.CreateModel( name='Membership', fields=[ @@ -61,7 +66,7 @@ class Migration(migrations.Migration): ('date_start', models.DateField(default=datetime.date.today, verbose_name='membership starts on')), ('date_end', models.DateField(null=True, verbose_name='membership ends on')), ('fee', models.PositiveIntegerField(verbose_name='fee')), - ('club', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='member.club', verbose_name='club')), + ('club', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='member.Club', verbose_name='club')), ], options={ 'verbose_name': 'membership', diff --git a/apps/member/migrations/0002_initial.py b/apps/member/migrations/0002_auto_20200904_2341.py similarity index 75% rename from apps/member/migrations/0002_initial.py rename to apps/member/migrations/0002_auto_20200904_2341.py index bd1b907..3dd9d04 100644 --- a/apps/member/migrations/0002_initial.py +++ b/apps/member/migrations/0002_auto_20200904_2341.py @@ -1,8 +1,8 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 -import django.db.models.deletion from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -10,16 +10,16 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('member', '0001_initial'), ('permission', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('member', '0001_initial'), ] operations = [ migrations.AddField( model_name='membership', name='roles', - field=models.ManyToManyField(related_name='memberships', to='permission.role', verbose_name='roles'), + field=models.ManyToManyField(to='permission.Role', verbose_name='roles'), ), migrations.AddField( model_name='membership', @@ -27,16 +27,16 @@ class Migration(migrations.Migration): field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='memberships', to=settings.AUTH_USER_MODEL, verbose_name='user'), ), migrations.AddField( - model_name='profile', - name='user', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), - ), - migrations.AddIndex( - model_name='membership', - index=models.Index(fields=['user'], name='member_memb_user_id_945dbc_idx'), + model_name='club', + name='parent_club', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='member.Club', verbose_name='parent club'), ), migrations.AddIndex( model_name='profile', index=models.Index(fields=['user'], name='member_prof_user_id_30c316_idx'), ), + migrations.AddIndex( + model_name='membership', + index=models.Index(fields=['user'], name='member_memb_user_id_945dbc_idx'), + ), ] diff --git a/apps/member/migrations/0003_create_bde_and_kfet.py b/apps/member/migrations/0003_create_bde_and_kfet.py new file mode 100644 index 0000000..2dbcd9d --- /dev/null +++ b/apps/member/migrations/0003_create_bde_and_kfet.py @@ -0,0 +1,71 @@ +from django.db import migrations + + +def create_bde_and_kfet(apps, schema_editor): + """ + The clubs BDE and Kfet are pre-injected. + """ + Club = apps.get_model("member", "club") + NoteClub = apps.get_model("note", "noteclub") + Alias = apps.get_model("note", "alias") + ContentType = apps.get_model('contenttypes', 'ContentType') + polymorphic_ctype_id = ContentType.objects.get_for_model(NoteClub).id + + Club.objects.get_or_create( + id=1, + name="BDE", + email="tresorerie.bde@example.com", + require_memberships=True, + membership_fee_paid=500, + membership_fee_unpaid=500, + membership_duration=396, + membership_start="2021-08-01", + membership_end="2022-09-30", + ) + Club.objects.get_or_create( + id=2, + name="Kfet", + parent_club_id=1, + email="tresorerie.bde@example.com", + require_memberships=True, + membership_fee_paid=3500, + membership_fee_unpaid=3500, + membership_duration=396, + membership_start="2021-08-01", + membership_end="2022-09-30", + ) + + NoteClub.objects.get_or_create( + id=5, + club_id=1, + polymorphic_ctype_id=polymorphic_ctype_id, + ) + NoteClub.objects.get_or_create( + id=6, + club_id=2, + polymorphic_ctype_id=polymorphic_ctype_id, + ) + + Alias.objects.get_or_create( + id=5, + note_id=5, + name="BDE", + normalized_name="bde", + ) + Alias.objects.get_or_create( + id=6, + note_id=6, + name="Kfet", + normalized_name="kfet", + ) + + +class Migration(migrations.Migration): + dependencies = [ + ('member', '0002_auto_20200904_2341'), + ('note', '0002_create_special_notes'), + ] + + operations = [ + migrations.RunPython(create_bde_and_kfet), + ] diff --git a/apps/member/migrations/0003_initial_club.py b/apps/member/migrations/0003_initial_club.py deleted file mode 100644 index a8c77b3..0000000 --- a/apps/member/migrations/0003_initial_club.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Migration member default BDE BDA""" - -from django.db import migrations - - -def create_initial_club(apps, schema_editor): - """ - The clubs BDE BDA BDS are pre-injected. - """ - Club = apps.get_model("member", "club") - NoteClub = apps.get_model("note", "noteclub") - Alias = apps.get_model("note", "alias") - ContentType = apps.get_model('contenttypes', 'ContentType') - polymorphic_ctype_id = ContentType.objects.get_for_model(NoteClub).id - - Club.objects.get_or_create( - id=1, - name="BDE", - email="tresorerie.bde@example.com", - require_memberships=True, - membership_fee_paid=3500, - membership_fee_unpaid=2800, - membership_duration=396, - membership_start="2022-08-01", - membership_end="2023-09-30", - ) - - Club.objects.get_or_create( - id=2, - name="BDA", - email="tresorerie.bda@example.com", - require_memberships=True, - membership_fee_paid=2500, - membership_fee_unpaid=1700, - membership_duration=396, - membership_start="2022-08-01", - membership_end="2023-09-30", - ) - - Club.objects.get_or_create( - id=3, - name="BDS", - email="tresorerie.bds@example.com", - require_memberships=True, - membership_fee_paid=3000, - membership_fee_unpaid=2300, - membership_duration=396, - membership_start="2022-08-01", - membership_end="2023-09-30", - ) - - Club.objects.get_or_create( - id=4, - name="Sinfonie", - email="tresorerie@sinfonie.com", - require_memberships=False, - membership_fee_paid=0, - membership_fee_unpaid=0, - membership_duration=396, - membership_start="2022-08-01", - membership_end="2023-09-30", - ) - - - NoteClub.objects.get_or_create( - id=5, - club_id=1, - polymorphic_ctype_id=polymorphic_ctype_id, - ) - NoteClub.objects.get_or_create( - id=6, - club_id=2, - polymorphic_ctype_id=polymorphic_ctype_id, - ) - NoteClub.objects.get_or_create( - id=7, - club_id=3, - polymorphic_ctype_id=polymorphic_ctype_id, - ) - NoteClub.objects.get_or_create( - id=8, - club_id=4, - polymorphic_ctype_id=polymorphic_ctype_id, - ) - - Alias.objects.get_or_create( - id=5, - note_id=5, - name="BDE", - normalized_name="bde", - ) - Alias.objects.get_or_create( - id=6, - note_id=6, - name="BDA", - normalized_name="bda", - ) - Alias.objects.get_or_create( - id=7, - note_id=7, - name="BDS", - normalized_name="bds", - ) - Alias.objects.get_or_create( - id=8, - note_id=8, - name="Sinfonie", - normalized_name="sinfonie", - ) - - -class Migration(migrations.Migration): - dependencies = [ - ('member', '0002_initial'), - ('note', '0002_special_note'), - ] - - operations = [ - migrations.RunPython(create_initial_club), - ] diff --git a/apps/member/migrations/0004_replace_null_by_blank.py b/apps/member/migrations/0004_replace_null_by_blank.py new file mode 100644 index 0000000..a53e380 --- /dev/null +++ b/apps/member/migrations/0004_replace_null_by_blank.py @@ -0,0 +1,20 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('member', '0003_create_bde_and_kfet'), + ] + + operations = [ + migrations.RunSQL( + "UPDATE member_profile SET address = '' WHERE address IS NULL;", + ), + migrations.RunSQL( + "UPDATE member_profile SET ml_events_registration = '' WHERE ml_events_registration IS NULL;", + ), + migrations.RunSQL( + "UPDATE member_profile SET section = '' WHERE section IS NULL;", + ), + ] diff --git a/apps/member/migrations/0005_remove_null_tag_on_charfields.py b/apps/member/migrations/0005_remove_null_tag_on_charfields.py new file mode 100644 index 0000000..11b9f37 --- /dev/null +++ b/apps/member/migrations/0005_remove_null_tag_on_charfields.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.16 on 2020-09-06 19:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('member', '0004_replace_null_by_blank'), + ] + + operations = [ + migrations.AlterField( + model_name='profile', + name='address', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='address'), + ), + migrations.AlterField( + model_name='profile', + name='ml_events_registration', + field=models.CharField(blank=True, choices=[('', 'No'), ('fr', 'Yes (receive them in french)'), ('en', 'Yes (receive them in english)')], default='', max_length=2, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)'), + ), + migrations.AlterField( + model_name='profile', + name='section', + field=models.CharField(blank=True, default='', help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, verbose_name='section'), + ), + ] diff --git a/apps/member/migrations/0006_create_note_account_bde_membership.py b/apps/member/migrations/0006_create_note_account_bde_membership.py new file mode 100644 index 0000000..4a18301 --- /dev/null +++ b/apps/member/migrations/0006_create_note_account_bde_membership.py @@ -0,0 +1,50 @@ +import sys + +from django.db import migrations + + +def give_note_account_permissions(apps, schema_editor): + """ + Automatically manage the membership of the Note account. + """ + User = apps.get_model("auth", "user") + Membership = apps.get_model("member", "membership") + Role = apps.get_model("permission", "role") + + note = User.objects.filter(username="note") + if not note.exists(): + # We are in a test environment, don't log error message + if len(sys.argv) > 1 and sys.argv[1] == 'test': + return + print("Warning: Note account was not found. The note account was not imported.") + print("Make sure you have imported the NK15 database. The new import script handles correctly the permissions.") + print("This migration will be ignored, you can re-run it if you forgot the note account or ignore it if you " + "don't want this account.") + return + + note = note.get() + + # Set for the two clubs a large expiration date and the correct role. + for m in Membership.objects.filter(user_id=note.id).all(): + m.date_end = "3142-12-12" + m.roles.set(Role.objects.filter(name="PC Kfet").all()) + m.save() + # By default, the note account is only authorized to be logged from localhost. + note.password = "ipbased$127.0.0.1" + note.is_active = True + note.save() + # Ensure that the note of the account is disabled + note.note.inactivity_reason = 'forced' + note.note.is_active = False + note.save() + + +class Migration(migrations.Migration): + dependencies = [ + ('member', '0005_remove_null_tag_on_charfields'), + ('permission', '0001_initial'), + ] + + operations = [ + migrations.RunPython(give_note_account_permissions), + ] diff --git a/apps/member/migrations/0007_auto_20210313_1235.py b/apps/member/migrations/0007_auto_20210313_1235.py new file mode 100644 index 0000000..01ad239 --- /dev/null +++ b/apps/member/migrations/0007_auto_20210313_1235.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.19 on 2021-03-13 11:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('member', '0006_create_note_account_bde_membership'), + ] + + operations = [ + migrations.AlterField( + model_name='membership', + name='roles', + field=models.ManyToManyField(related_name='memberships', to='permission.Role', verbose_name='roles'), + ), + migrations.AlterField( + model_name='profile', + name='promotion', + field=models.PositiveSmallIntegerField(default=2021, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion'), + ), + ] diff --git a/apps/member/migrations/0008_auto_20211005_1544.py b/apps/member/migrations/0008_auto_20211005_1544.py new file mode 100644 index 0000000..a057299 --- /dev/null +++ b/apps/member/migrations/0008_auto_20211005_1544.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2021-10-05 13:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('member', '0007_auto_20210313_1235'), + ] + + operations = [ + migrations.AlterField( + model_name='profile', + name='department', + field=models.CharField(choices=[('A0', 'Informatics (A0)'), ('A1', 'Mathematics (A1)'), ('A2', 'Physics (A2)'), ("A'2", "Applied physics (A'2)"), ("A''2", "Chemistry (A''2)"), ('A3', 'Biology (A3)'), ('B1234', 'SAPHIRE (B1234)'), ('B1', 'Mechanics (B1)'), ('B2', 'Civil engineering (B2)'), ('B3', 'Mechanical engineering (B3)'), ('B4', 'EEA (B4)'), ('C', 'Design (C)'), ('D2', 'Economy-management (D2)'), ('D3', 'Social sciences (D3)'), ('E', 'English (E)'), ('EXT', 'External (EXT)')], max_length=8, verbose_name='department'), + ), + ] diff --git a/apps/member/models.py b/apps/member/models.py index 30a381e..a2976f7 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -43,7 +43,7 @@ class Profile(models.Model): section = models.CharField( verbose_name=_('section'), - help_text=_('Auto generated'), + help_text=_('e.g. "1A0", "9A♥", "SAPHIRE"'), max_length=255, blank=True, default="", @@ -83,6 +83,26 @@ class Profile(models.Model): default=False, ) + ml_events_registration = models.CharField( + blank=True, + default='', + max_length=2, + choices=[ + ('', _("No")), + ('fr', _("Yes")), + ], + verbose_name=_("Register on the mailing list to stay informed of the events of the campus (1 mail/week)"), + ) + + ml_sport_registration = models.BooleanField( + default=False, + verbose_name=_("Register on the mailing list to stay informed of the sport events of the campus (1 mail/week)"), + ) + + ml_art_registration = models.BooleanField( + default=False, + verbose_name=_("Register on the mailing list to stay informed of the art events of the campus (1 mail/week)"), + ) report_frequency = models.PositiveSmallIntegerField( verbose_name=_("report frequency (in days)"), @@ -133,7 +153,7 @@ class Profile(models.Model): return str(self.user) def send_email_validation_link(self): - subject = "[Note Ker Lann] " + str(_("Activate your Note Ker Lann account")) + subject = "[Note Kfet] " + str(_("Activate your Note Kfet account")) token = email_validation_token.make_token(self.user) uid = urlsafe_base64_encode(force_bytes(self.user_id)) message = loader.render_to_string('registration/mails/email_validation_email.txt', @@ -358,10 +378,14 @@ class Membership(models.Model): parent_membership.save() parent_membership.refresh_from_db() - - parent_membership.roles.set( - Role.objects.filter(Q(name="Adhérent")).all()) - + if self.club.parent_club.name == "BDE": + parent_membership.roles.set( + Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all()) + elif self.club.parent_club.name == "Kfet": + parent_membership.roles.set( + Role.objects.filter(Q(name="Adhérent Kfet") | Q(name="Membre de club")).all()) + else: + parent_membership.roles.set(Role.objects.filter(name="Membre de club").all()) parent_membership.save() @transaction.atomic diff --git a/apps/member/templates/member/add_members.html b/apps/member/templates/member/add_members.html index 3adb925..07b4931 100644 --- a/apps/member/templates/member/add_members.html +++ b/apps/member/templates/member/add_members.html @@ -13,15 +13,29 @@ SPDX-License-Identifier: GPL-3.0-or-later {% if additional_fee_renewal %}
{% if renewal %} - {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} - The user is not a member of the club·s {{ clubs }}. Please create the required memberships, - otherwise it will fail. - {% endblocktrans %} + {% if club.name == "Kfet" %} {# Auto-renewal #} + {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} + The user is not a member of the club·s {{ clubs }}. An additional fee of {{ pretty_fee }} + will be charged to renew automatically the membership in this/these club·s. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} + The user is not a member of the club·s {{ clubs }}. Please create the required memberships, + otherwise it will fail. + {% endblocktrans %} + {% endif %} {% else %} - {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} - This club has parents {{ clubs }}. Please make sure that the user is a member of this or these club·s, - otherwise the creation of this membership will fail. - {% endblocktrans %} + {% if club.name == "Kfet" %} + {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} + This club has parents {{ clubs }}. An additional fee of {{ pretty_fee }} + will be charged to adhere automatically to this/these club·s. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %} + This club has parents {{ clubs }}. Please make sure that the user is a member of this or these club·s, + otherwise the creation of this membership will fail. + {% endblocktrans %} + {% endif %} {% endif %}
{% endif %} @@ -55,6 +69,10 @@ SPDX-License-Identifier: GPL-3.0-or-later let credit_amount = $("#id_credit_amount"); credit_amount.attr('disabled', true); credit_amount.val('{{ total_fee }}'); + + let bank = $("#id_bank"); + bank.attr('disabled', true); + bank.val('Société générale'); } {% endblock %} \ No newline at end of file diff --git a/apps/member/templates/member/base.html b/apps/member/templates/member/base.html index d291e44..e1e9335 100644 --- a/apps/member/templates/member/base.html +++ b/apps/member/templates/member/base.html @@ -3,7 +3,6 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endcomment %} {% load i18n perms %} -{% load qr_code %} {# Use a fluid-width container #} {% block containertype %}container-fluid{% endblock %} @@ -25,14 +24,11 @@ SPDX-License-Identifier: GPL-3.0-or-later - {% qr_from_text user_object.username size="M" %} {% elif club %} - {% qr_from_text club.name size="M" %} {% endif %} - {% if note.inactivity_reason %}
@@ -55,7 +51,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% if request.path_info != user_profile_url %} {% trans 'View Profile' %} {% endif %} - {% elif club %} + {% elif club and not club.weiclub %} {% if can_add_members %} {% trans "Add member" %} diff --git a/apps/member/templates/member/includes/club_info.html b/apps/member/templates/member/includes/club_info.html index 05419bf..0efc71d 100644 --- a/apps/member/templates/member/includes/club_info.html +++ b/apps/member/templates/member/includes/club_info.html @@ -1,4 +1,4 @@ -{% load i18n pretty_money perms memberinfo %} +{% load i18n pretty_money perms %}
{% trans 'name'|capfirst %}
@@ -39,7 +39,7 @@ {% endif %} {% endif %} - {% if "note.view_note"|has_perm:club.note and user|is_member:club %} + {% if "note.view_note"|has_perm:club.note %}
{% trans 'balance'|capfirst %}
{{ club.note.balance | pretty_money }}
{% endif %} diff --git a/apps/member/templates/member/includes/profile_info.html b/apps/member/templates/member/includes/profile_info.html index 650bd78..3a927c9 100644 --- a/apps/member/templates/member/includes/profile_info.html +++ b/apps/member/templates/member/includes/profile_info.html @@ -48,7 +48,7 @@
{{ user_object.profile.address }}
{% trans 'paid'|capfirst %}
-
{{ user_object.profile.paid|yesno:_("yes,no,maybe") }}
+
{{ user_object.profile.paid|yesno }}
{% endif %} {% if user_object.note and "note.view_note"|has_perm:user_object.note %} diff --git a/apps/member/templates/member/manage_auth_tokens.html b/apps/member/templates/member/manage_auth_tokens.html index 25a96bc..0f6a64e 100644 --- a/apps/member/templates/member/manage_auth_tokens.html +++ b/apps/member/templates/member/manage_auth_tokens.html @@ -15,7 +15,7 @@ SPDX-License-Identifier: GPL-3.0-or-later

À quoi sert un jeton d'authentification ?

- Un jeton vous permet de vous connecter à l'API de la Note Ker Lann via votre propre compte + Un jeton vous permet de vous connecter à l'API de la Note Kfet via votre propre compte depuis un client externe.
Il suffit pour cela d'ajouter en en-tête de vos requêtes Authorization: Token <TOKEN> pour pouvoir vous identifier.

@@ -55,10 +55,10 @@ SPDX-License-Identifier: GPL-3.0-or-later

- La Note Ker Lann implémente également le protocole OAuth2, afin de + La Note Kfet implémente également le protocole OAuth2, afin de permettre à des applications tierces d'interagir avec la Note en récoltant des informations (de connexion par exemple) voir en permettant des modifications à distance, par exemple lorsqu'il - s'agit d'avoir un site marchand sur lequel faire des transactions via la Note Ker Lann. + s'agit d'avoir un site marchand sur lequel faire des transactions via la Note Kfet.

diff --git a/apps/member/templates/member/profile_trust.html b/apps/member/templates/member/profile_trust.html index 696c0d4..bd8d6b5 100644 --- a/apps/member/templates/member/profile_trust.html +++ b/apps/member/templates/member/profile_trust.html @@ -28,7 +28,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% blocktrans trimmed %} Adding someone as a friend enables them to initiate transactions coming from your account (while keeping your balance positive). This is - designed to simplify using note ker lann transfers to transfer money between + designed to simplify using note kfet transfers to transfer money between users. The intent is that one person can make all transfers for a group of friends without needing additional rights among them. {% endblocktrans %} diff --git a/apps/member/tests/test_memberships.py b/apps/member/tests/test_memberships.py index b329138..a46a23e 100644 --- a/apps/member/tests/test_memberships.py +++ b/apps/member/tests/test_memberships.py @@ -49,7 +49,7 @@ class TestMemberships(TestCase): self.club = Club.objects.create(name="totoclub", parent_club=Club.objects.get(name="BDE")) self.bde_membership = Membership.objects.create(user=self.user, club=Club.objects.get(name="BDE")) self.membership = Membership.objects.create(user=self.user, club=self.club) - self.membership.roles.add(Role.objects.get(name="Pr\u00e9sident\u00b7e")) + self.membership.roles.add(Role.objects.get(name="Bureau de club")) self.membership.save() def test_admin_pages(self): @@ -161,7 +161,7 @@ class TestMemberships(TestCase): response = self.client.get(reverse("member:club_members", args=(self.club.pk,)) + "?search=toto&roles=" + ",".join([str(role.pk) for role in - Role.objects.all()])) + Role.objects.filter(weirole__isnull=True).all()])) self.assertEqual(response.status_code, 200) def test_render_club_add_member(self): @@ -179,17 +179,20 @@ class TestMemberships(TestCase): # We create a club without any parent and one club with parent BDE (that is the club Kfet) for bde_parent in False, True: - club = Club.objects.create( - name="Second club " + ("with BDE" if bde_parent else "without BDE"), - parent_club=None, - email="newclub@example.com", - require_memberships=True, - membership_fee_paid=1000, - membership_fee_unpaid=500, - membership_start=date.today(), - membership_end=date.today() + timedelta(days=366), - membership_duration=366, - ) + if bde_parent: + club = Club.objects.get(name="Kfet") + else: + club = Club.objects.create( + name="Second club " + ("with BDE" if bde_parent else "without BDE"), + parent_club=None, + email="newclub@example.com", + require_memberships=True, + membership_fee_paid=1000, + membership_fee_unpaid=500, + membership_start=date.today(), + membership_end=date.today() + timedelta(days=366), + membership_duration=366, + ) response = self.client.get(reverse("member:club_add_member", args=(club.pk,))) self.assertEqual(response.status_code, 200) @@ -201,7 +204,8 @@ class TestMemberships(TestCase): credit_type=NoteSpecial.objects.get(special_type="Espèces").id, credit_amount=4200, last_name="TOTO", - first_name="Toto" + first_name="Toto", + bank="Le matelas", )) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200) @@ -219,6 +223,11 @@ class TestMemberships(TestCase): self.assertEqual(response.status_code, 200) bde_membership = self.bde_membership + if bde_parent: + bde_membership = Membership.objects.get(club__name="BDE", user=user) + bde_membership.date_start = date(year=2000, month=1, day=1) + bde_membership.date_end = date(year=2000, month=12, day=31) + bde_membership.save() response = self.client.get(reverse("member:club_renew_membership", args=(bde_membership.pk,))) self.assertEqual(response.status_code, 200) @@ -234,6 +243,7 @@ class TestMemberships(TestCase): credit_amount=14242, last_name="TOTO", first_name="Toto", + bank="Bank", )) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200) @@ -251,11 +261,11 @@ class TestMemberships(TestCase): response = self.client.post(reverse("member:club_manage_roles", args=(self.membership.pk,)), data=dict( roles=[role.id for role in Role.objects.filter( - Q(name="Trésorier·ère")).all()], + Q(name="Membre de club") | Q(name="Trésorier·ère de club") | Q(name="Bureau de club")).all()], )) self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200) self.membership.refresh_from_db() - self.assertEqual(self.membership.roles.count(), 1) + self.assertEqual(self.membership.roles.count(), 3) def test_render_user_list(self): """ @@ -389,7 +399,7 @@ class TestMemberAPI(TestAPI): ) self.bde_membership = Membership.objects.create(user=self.user, club=Club.objects.get(name="BDE")) self.membership = Membership.objects.create(user=self.user, club=self.club) - self.membership.roles.add(Role.objects.get(name="Pr\u00e9sident\u00b7e")) + self.membership.roles.add(Role.objects.get(name="Bureau de club")) self.membership.save() def test_club_api(self): diff --git a/apps/member/views.py b/apps/member/views.py index 2b7a1a1..5605330 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -28,7 +28,7 @@ from permission.models import Role from permission.views import ProtectQuerysetMixin, ProtectedCreateView from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm,\ - MembershipRolesForm, AuthenticationForm + CustomAuthenticationForm, MembershipRolesForm from .models import Club, Membership from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable @@ -37,19 +37,16 @@ class CustomLoginView(LoginView): """ Login view, where the user can select its permission mask. """ - form_class = AuthenticationForm + form_class = CustomAuthenticationForm @transaction.atomic def form_valid(self, form): logout(self.request) self.request.user = form.get_user() _set_current_request(self.request) - self.request.session['permission_mask'] = 42#form.cleaned_data['permission_mask'].rank + self.request.session['permission_mask'] = form.cleaned_data['permission_mask'].rank return super().form_valid(form) -def logout_view(request): - logout(request) - return redirect('index') class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): """ @@ -272,7 +269,7 @@ class ProfileTrustView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): "class": "autocomplete form-control", "id": "trusted", "resetable": True, - "api_url": "/api/note/alias/", + "api_url": "/api/note/alias/?note__polymorphic_ctype__model=noteuser", "name_field": "name", "placeholder": "" } @@ -448,7 +445,7 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): club.update_membership_dates() # managers list - managers = Membership.objects.filter(club=self.object, roles__name="Pr\u00e9sident\u00b7e", + managers = Membership.objects.filter(club=self.object, roles__name="Bureau de club", date_start__lte=date.today(), date_end__gte=date.today())\ .order_by('user__last_name').all() context["managers"] = ClubManagerTable(data=managers, prefix="managers-") @@ -544,6 +541,11 @@ class ClubUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): def get_queryset(self, **kwargs): qs = super().get_queryset(**kwargs) + + # Don't update a WEI club through this view + if "wei" in settings.INSTALLED_APPS: + qs = qs.filter(weiclub=None) + return qs def get_success_url(self): @@ -595,7 +597,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): if "club_pk" in self.kwargs: # We create a new membership. club = Club.objects.filter(PermissionBackend.filter_queryset(self.request, Club, "view"))\ - .get(pk=self.kwargs["club_pk"]) + .get(pk=self.kwargs["club_pk"], weiclub=None) form.fields['credit_amount'].initial = club.membership_fee_paid # Ensure that the user is member of the parent club and all its the family tree. c = club @@ -659,7 +661,12 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): if not credit_type: credit_amount = 0 - if user.note.balance + credit_amount < fee: + if user.note.balance + credit_amount < fee and not Membership.objects.filter( + club__name="Kfet", + user=user, + date_start__lte=date.today(), + date_end__gte=date.today(), + ).exists(): # Users without a valid Kfet membership can't have a negative balance. # TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note form.add_error('user', @@ -676,7 +683,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): error = True # Must join the parent club before joining this club, except for the Kfet club where it can be at the same time. - if club.parent_club and not Membership.objects.filter( + if club.name != "Kfet" and club.parent_club and not Membership.objects.filter( user=form.instance.user, club=club.parent_club, date_start__gte=club.parent_club.membership_start, @@ -724,6 +731,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): credit_amount = form.cleaned_data["credit_amount"] last_name = form.cleaned_data["last_name"] first_name = form.cleaned_data["first_name"] + bank = form.cleaned_data["bank"] if credit_type is None: @@ -747,7 +755,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): # Now, all is fine, the membership can be created. - if club.name == "BDE" or club.name == "BDA" or club.name == "BDS": + if club.name == "BDE" or club.name == "Kfet": # When we renew the BDE membership, we update the profile section # that should happens at least once a year. user.profile.section = user.profile.section_generated @@ -764,6 +772,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): reason="Crédit " + credit_type.special_type + " (Adhésion " + club.name + ")", last_name=last_name, first_name=first_name, + bank=bank, valid=True, ) transaction._force_save = True @@ -775,8 +784,9 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView): ret = super().form_valid(form) - member_role = Role.objects.filter(Q(name="Adhérent")).all() - + member_role = Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).all() \ + if club.name == "BDE" else Role.objects.filter(Q(name="Adhérent Kfet") | Q(name="Membre de club")).all() \ + if club.name == "Kfet"else Role.objects.filter(name="Membre de club").all() # Set the same roles as before if old_membership: member_role = member_role.union(old_membership.roles.all()) @@ -809,7 +819,8 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): form = super().get_form(form_class) club = self.object.club - form.fields['roles'].queryset = Role.objects.filter((Q(for_club__isnull=True) | Q(for_club=club))).all() + form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub')) + & (Q(for_club__isnull=True) | Q(for_club=club))).all() return form @@ -855,7 +866,8 @@ class ClubMembersListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableV ).get(pk=self.kwargs["pk"]) context["club"] = club - applicable_roles = Role.objects.filter((Q(for_club__isnull=True) | Q(for_club=club))).all() + applicable_roles = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub')) + & (Q(for_club__isnull=True) | Q(for_club=club))).all() context["applicable_roles"] = applicable_roles context["only_active"] = "only_active" not in self.request.GET or self.request.GET["only_active"] != '0' diff --git a/apps/note/api/serializers.py b/apps/note/api/serializers.py index c6f62e3..33bf75b 100644 --- a/apps/note/api/serializers.py +++ b/apps/note/api/serializers.py @@ -160,7 +160,7 @@ class ConsumerSerializer(serializers.ModelSerializer): memberships = Membership.objects.filter( PermissionBackend.filter_queryset(get_current_request(), Membership, "view")).filter( user=obj.note.user, - club=2, # BDA + club=2, # Kfet ).order_by("-date_start") if memberships.exists(): return MembershipSerializer().to_representation(memberships.first()) diff --git a/apps/note/api/urls.py b/apps/note/api/urls.py index 8e3b184..d15e824 100644 --- a/apps/note/api/urls.py +++ b/apps/note/api/urls.py @@ -13,7 +13,7 @@ def register_note_urls(router, path): router.register(path + '/note', NotePolymorphicViewSet) router.register(path + '/alias', AliasViewSet) router.register(path + '/trust', TrustViewSet) - router.register(path + '/consumer', ConsumerViewSet,"consumer") + router.register(path + '/consumer', ConsumerViewSet) router.register(path + '/transaction/category', TemplateCategoryViewSet) router.register(path + '/transaction/transaction', TransactionViewSet) diff --git a/apps/note/api/views.py b/apps/note/api/views.py index 6ee2c00..34ffaf2 100644 --- a/apps/note/api/views.py +++ b/apps/note/api/views.py @@ -160,13 +160,11 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet): """ queryset = super().get_queryset().distinct() - # Sqlite doesn't support ORDER BY in subqueries queryset = queryset.order_by("name") \ if settings.DATABASES[queryset.db]["ENGINE"] == 'django.db.backends.postgresql' else queryset alias = self.request.query_params.get("alias", None) - # Check if this is a valid regex. If not, we won't check regex try: re.compile(alias) @@ -176,14 +174,13 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet): suffix = '__iregex' if valid_regex else '__istartswith' alias_prefix = '^' if valid_regex else '' queryset = queryset.prefetch_related('note') - + if alias: # We match first an alias if it is matched without normalization, # then if the normalized pattern matches a normalized alias. queryset = queryset.filter( **{f'name{suffix}': alias_prefix + alias} - ) - """.union( + ).union( queryset.filter( Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) & ~Q(**{f'name{suffix}': alias_prefix + alias}) @@ -194,12 +191,12 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet): & ~Q(**{f'normalized_name{suffix}': alias_prefix + Alias.normalize(alias)}) & ~Q(**{f'name{suffix}': alias_prefix + alias}) ), - all=True)""" + all=True) queryset = queryset if settings.DATABASES[queryset.db]["ENGINE"] == 'django.db.backends.postgresql' \ else queryset.order_by("name") - return queryset#.distinct() + return queryset.distinct() class TemplateCategoryViewSet(ReadProtectedModelViewSet): diff --git a/apps/note/fixtures/initial.json b/apps/note/fixtures/initial.json deleted file mode 100644 index 56be0fa..0000000 --- a/apps/note/fixtures/initial.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "model": "note.templatecategory", - "pk": 1, - "fields": { - "name": "Soft" - } - }, - { - "model": "note.templatecategory", - "pk": 2, - "fields": { - "name": "Alcool" - } - }, - { - "model": "note.templatecategory", - "pk": 3, - "fields": { - "name": "Nourriture" - } - }, - { - "model": "note.templatecategory", - "pk": 4, - "fields": { - "name": "Clubs" - } - }, - { - "model": "note.templatecategory", - "pk": 5, - "fields": { - "name": "Goodies" - } - }, - { - "model": "note.templatecategory", - "pk": 6, - "fields": { - "name": "Autre" - } - }, - { - "model": "note.transactiontemplate", - "pk": 1, - "fields": { - "name": "Test Button", - "destination": 5, - "amount": 1, - "category": 6, - "display": false, - "highlighted": false, - "description": "Test button" - } - } -] \ No newline at end of file diff --git a/apps/note/migrations/0001_initial.py b/apps/note/migrations/0001_initial.py index 2eca3e2..a0ebda3 100644 --- a/apps/note/migrations/0001_initial.py +++ b/apps/note/migrations/0001_initial.py @@ -1,9 +1,9 @@ -# Generated by Django 5.1 on 2024-08-13 09:26 +# Generated by Django 2.2.16 on 2020-09-04 21:41 -import django.db.models.deletion -import django.utils.timezone from django.conf import settings from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): @@ -11,31 +11,12 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('member', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('member', '0001_initial'), + ('contenttypes', '0002_remove_content_type_name'), ] operations = [ - migrations.CreateModel( - name='Transaction', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('source_alias', models.CharField(default='', max_length=255, verbose_name='used alias')), - ('destination_alias', models.CharField(default='', max_length=255, verbose_name='used alias')), - ('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created at')), - ('quantity', models.PositiveIntegerField(default=1, verbose_name='quantity')), - ('amount', models.PositiveIntegerField(verbose_name='amount')), - ('reason', models.CharField(max_length=255, verbose_name='reason')), - ('valid', models.BooleanField(default=True, verbose_name='valid')), - ('invalidity_reason', models.CharField(blank=True, default='', max_length=255, verbose_name='invalidity reason')), - ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')), - ], - options={ - 'verbose_name': 'transaction', - 'verbose_name_plural': 'transactions', - }, - ), migrations.CreateModel( name='Note', fields=[ @@ -45,8 +26,8 @@ class Migration(migrations.Migration): ('display_image', models.ImageField(default='pic/default.png', max_length=255, upload_to='pic/', verbose_name='display image')), ('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created at')), ('is_active', models.BooleanField(default=True, help_text='Designates whether this note should be treated as active. Unselect this instead of deleting notes.', verbose_name='active')), - ('inactivity_reason', models.CharField(blank=True, choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default='', max_length=255)), - ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')), + ('inactivity_reason', models.CharField(choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default=None, max_length=255, null=True)), + ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.note_set+', to='contenttypes.ContentType')), ], options={ 'verbose_name': 'note', @@ -65,23 +46,41 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='SpecialTransaction', + name='Transaction', fields=[ - ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.transaction')), - ('last_name', models.CharField(max_length=255, verbose_name='name')), - ('first_name', models.CharField(max_length=255, verbose_name='first_name')), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_alias', models.CharField(default='', max_length=255, verbose_name='used alias')), + ('destination_alias', models.CharField(default='', max_length=255, verbose_name='used alias')), + ('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created at')), + ('quantity', models.PositiveIntegerField(default=1, verbose_name='quantity')), + ('amount', models.PositiveIntegerField(verbose_name='amount')), + ('reason', models.CharField(max_length=255, verbose_name='reason')), + ('valid', models.BooleanField(default=True, verbose_name='valid')), + ('invalidity_reason', models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='invalidity reason')), + ('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='destination')), + ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_note.transaction_set+', to='contenttypes.ContentType')), + ('source', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.Note', verbose_name='source')), ], options={ - 'verbose_name': 'Special transaction', - 'verbose_name_plural': 'Special transactions', + 'verbose_name': 'transaction', + 'verbose_name_plural': 'transactions', + }, + ), + migrations.CreateModel( + name='MembershipTransaction', + fields=[ + ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')), + ], + options={ + 'verbose_name': 'membership transaction', + 'verbose_name_plural': 'membership transactions', }, bases=('note.transaction',), ), migrations.CreateModel( name='NoteClub', fields=[ - ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.note')), - ('club', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='note', to='member.club', verbose_name='club')), + ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Note')), ], options={ 'verbose_name': 'club note', @@ -92,7 +91,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='NoteSpecial', fields=[ - ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.note')), + ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Note')), ('special_type', models.CharField(max_length=255, unique=True, verbose_name='type')), ], options={ @@ -101,15 +100,41 @@ class Migration(migrations.Migration): }, bases=('note.note',), ), - migrations.AddField( - model_name='transaction', - name='destination', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.note', verbose_name='destination'), + migrations.CreateModel( + name='NoteUser', + fields=[ + ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Note')), + ], + options={ + 'verbose_name': "one's note", + 'verbose_name_plural': 'users note', + }, + bases=('note.note',), ), - migrations.AddField( - model_name='transaction', - name='source', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.note', verbose_name='source'), + migrations.CreateModel( + name='RecurrentTransaction', + fields=[ + ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')), + ], + options={ + 'verbose_name': 'recurrent transaction', + 'verbose_name_plural': 'recurrent transactions', + }, + bases=('note.transaction',), + ), + migrations.CreateModel( + name='SpecialTransaction', + fields=[ + ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.Transaction')), + ('last_name', models.CharField(max_length=255, verbose_name='name')), + ('first_name', models.CharField(max_length=255, verbose_name='first_name')), + ('bank', models.CharField(blank=True, max_length=255, verbose_name='bank')), + ], + options={ + 'verbose_name': 'Special transaction', + 'verbose_name_plural': 'Special transactions', + }, + bases=('note.transaction',), ), migrations.CreateModel( name='Alias', @@ -117,7 +142,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, unique=True, verbose_name='name')), ('normalized_name', models.CharField(editable=False, max_length=255, unique=True)), - ('note', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='alias', to='note.note')), + ('note', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.Note')), ], options={ 'verbose_name': 'alias', @@ -133,62 +158,14 @@ class Migration(migrations.Migration): ('display', models.BooleanField(default=True, verbose_name='display')), ('highlighted', models.BooleanField(default=False, verbose_name='highlighted')), ('description', models.CharField(blank=True, max_length=255, verbose_name='description')), - ('category', models.ForeignKey(max_length=31, on_delete=django.db.models.deletion.PROTECT, related_name='templates', to='note.templatecategory', verbose_name='type')), - ('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.noteclub', verbose_name='destination')), + ('category', models.ForeignKey(max_length=31, on_delete=django.db.models.deletion.PROTECT, related_name='templates', to='note.TemplateCategory', verbose_name='type')), + ('destination', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='note.NoteClub', verbose_name='destination')), ], options={ 'verbose_name': 'transaction template', 'verbose_name_plural': 'transaction templates', }, ), - migrations.CreateModel( - name='Trust', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('trusted', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusted', to='note.note', verbose_name='trusted')), - ('trusting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusting', to='note.note', verbose_name='trusting')), - ], - options={ - 'verbose_name': 'frienship', - 'verbose_name_plural': 'friendships', - }, - ), - migrations.CreateModel( - name='MembershipTransaction', - fields=[ - ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.transaction')), - ('membership', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='transaction', to='member.membership')), - ], - options={ - 'verbose_name': 'membership transaction', - 'verbose_name_plural': 'membership transactions', - }, - bases=('note.transaction',), - ), - migrations.CreateModel( - name='RecurrentTransaction', - fields=[ - ('transaction_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.transaction')), - ('template', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.transactiontemplate')), - ], - options={ - 'verbose_name': 'recurrent transaction', - 'verbose_name_plural': 'recurrent transactions', - }, - bases=('note.transaction',), - ), - migrations.CreateModel( - name='NoteUser', - fields=[ - ('note_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='note.note')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='note', to=settings.AUTH_USER_MODEL, verbose_name='user')), - ], - options={ - 'verbose_name': "one's note", - 'verbose_name_plural': 'users note', - }, - bases=('note.note',), - ), migrations.AddIndex( model_name='transaction', index=models.Index(fields=['created_at'], name='note_transa_created_bea8b1_idx'), @@ -201,6 +178,26 @@ class Migration(migrations.Migration): model_name='transaction', index=models.Index(fields=['destination'], name='note_transa_destina_6e1bb4_idx'), ), + migrations.AddField( + model_name='recurrenttransaction', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='note.TransactionTemplate'), + ), + migrations.AddField( + model_name='noteuser', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='note', to=settings.AUTH_USER_MODEL, verbose_name='user'), + ), + migrations.AddField( + model_name='noteclub', + name='club', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='note', to='member.Club', verbose_name='club'), + ), + migrations.AddField( + model_name='membershiptransaction', + name='membership', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='transaction', to='member.Membership'), + ), migrations.AddIndex( model_name='alias', index=models.Index(fields=['name'], name='note_alias_name_a89405_idx'), @@ -209,8 +206,4 @@ class Migration(migrations.Migration): model_name='alias', index=models.Index(fields=['normalized_name'], name='note_alias_normali_bd52b4_idx'), ), - migrations.AlterUniqueTogether( - name='trust', - unique_together={('trusting', 'trusted')}, - ), ] diff --git a/apps/note/migrations/0002_special_note.py b/apps/note/migrations/0002_create_special_notes.py similarity index 100% rename from apps/note/migrations/0002_special_note.py rename to apps/note/migrations/0002_create_special_notes.py diff --git a/apps/note/migrations/0003_replace_null_by_blank.py b/apps/note/migrations/0003_replace_null_by_blank.py new file mode 100644 index 0000000..21da860 --- /dev/null +++ b/apps/note/migrations/0003_replace_null_by_blank.py @@ -0,0 +1,17 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('note', '0002_create_special_notes'), + ] + + operations = [ + migrations.RunSQL( + "UPDATE note_note SET inactivity_reason = '' WHERE inactivity_reason IS NULL;" + ), + migrations.RunSQL( + "UPDATE note_transaction SET invalidity_reason = '' WHERE invalidity_reason IS NULL;" + ), + ] diff --git a/apps/note/migrations/0004_remove_null_tag_on_charfields.py b/apps/note/migrations/0004_remove_null_tag_on_charfields.py new file mode 100644 index 0000000..012fc35 --- /dev/null +++ b/apps/note/migrations/0004_remove_null_tag_on_charfields.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.16 on 2020-09-06 19:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('note', '0003_replace_null_by_blank'), + ] + + operations = [ + migrations.AlterField( + model_name='note', + name='inactivity_reason', + field=models.CharField(blank=True, choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default='', max_length=255), + ), + migrations.AlterField( + model_name='transaction', + name='invalidity_reason', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='invalidity reason'), + ), + ] diff --git a/apps/note/migrations/0005_auto_20210313_1235.py b/apps/note/migrations/0005_auto_20210313_1235.py new file mode 100644 index 0000000..09696c3 --- /dev/null +++ b/apps/note/migrations/0005_auto_20210313_1235.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.19 on 2021-03-13 11:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('note', '0004_remove_null_tag_on_charfields'), + ] + + operations = [ + migrations.AlterField( + model_name='alias', + name='note', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='alias', to='note.Note'), + ), + ] diff --git a/apps/note/migrations/0006_trust.py b/apps/note/migrations/0006_trust.py new file mode 100644 index 0000000..4ed059f --- /dev/null +++ b/apps/note/migrations/0006_trust.py @@ -0,0 +1,27 @@ +# Generated by Django 2.2.24 on 2021-09-05 19:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('note', '0005_auto_20210313_1235'), + ] + + operations = [ + migrations.CreateModel( + name='Trust', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('trusted', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusted', to='note.Note', verbose_name='trusted')), + ('trusting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusting', to='note.Note', verbose_name='trusting')), + ], + options={ + 'verbose_name': 'frienship', + 'verbose_name_plural': 'friendships', + 'unique_together': {('trusting', 'trusted')}, + }, + ), + ] diff --git a/apps/note/models/notes.py b/apps/note/models/notes.py index bdf0354..6db9e5f 100644 --- a/apps/note/models/notes.py +++ b/apps/note/models/notes.py @@ -189,7 +189,7 @@ class NoteClub(Note): def send_mail_negative_balance(self): plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=self)) html = render_to_string("note/mails/negative_balance.html", dict(note=self)) - send_mail("[Note Ker Lann] Passage en négatif (club {})".format(self.club.name), plain_text, + send_mail("[Note Kfet] Passage en négatif (club {})".format(self.club.name), plain_text, settings.DEFAULT_FROM_EMAIL, [self.club.email], html_message=html) @@ -219,7 +219,7 @@ class NoteSpecial(Note): class Trust(models.Model): """ - A one-sided trust relationship between two users + A one-sided trust relationship bertween two users If another user considers you as your friend, you can transfer money from them diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py index 09c9874..3c6b4c7 100644 --- a/apps/note/models/transactions.py +++ b/apps/note/models/transactions.py @@ -306,6 +306,11 @@ class SpecialTransaction(Transaction): verbose_name=_("first_name"), ) + bank = models.CharField( + max_length=255, + verbose_name=_("bank"), + blank=True, + ) @property def type(self): @@ -341,16 +346,20 @@ class SpecialTransaction(Transaction): credit_type = form.cleaned_data["credit_type"] last_name = form.cleaned_data["last_name"] first_name = form.cleaned_data["first_name"] + bank = form.cleaned_data["bank"] error = False - if not last_name or not first_name: + if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"): if not last_name: form.add_error('last_name', _("This field is required.")) error = True if not first_name: form.add_error('first_name', _("This field is required.")) error = True + if not bank and credit_type.special_type == "Chèque": + form.add_error('bank', _("This field is required.")) + error = True return not error diff --git a/apps/note/templates/note/amount_input.html b/apps/note/templates/note/amount_input.html index 3da9ac4..d487311 100644 --- a/apps/note/templates/note/amount_input.html +++ b/apps/note/templates/note/amount_input.html @@ -9,12 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later name="{{ widget.name }}" {# Other attributes are loaded #} {% for name, value in widget.attrs.items %} - {% if value != False %} - {{ name }} - {% if value != True %} - ="{{ value|stringformat:'s' }}" - {% endif %} - {% endif %} + {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %} {% endfor %}>

diff --git a/apps/note/templates/note/conso_form.html b/apps/note/templates/note/conso_form.html index a9e4d15..d6044b8 100644 --- a/apps/note/templates/note/conso_form.html +++ b/apps/note/templates/note/conso_form.html @@ -21,7 +21,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% trans "Please select a note" %}
-
@@ -160,79 +159,6 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblock %} {% block extrajavascript %} - @@ -48,7 +48,7 @@ --

Le BDE
- {% trans "Mail generated by the Note Ker Lann on the" %} {% now "j F Y à H:i:s" %} + {% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %}

\ No newline at end of file diff --git a/apps/note/templates/note/transaction_form.html b/apps/note/templates/note/transaction_form.html index 2355c37..bdf047a 100644 --- a/apps/note/templates/note/transaction_form.html +++ b/apps/note/templates/note/transaction_form.html @@ -47,7 +47,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
{% trans "Please select a note" %}
-
@@ -140,6 +139,12 @@ SPDX-License-Identifier: GPL-2.0-or-later
+
+
+ + +
+

@@ -163,75 +168,6 @@ SPDX-License-Identifier: GPL-2.0-or-later {% endblock %} {% block extrajavascript %} - +{% endblock %} diff --git a/apps/wei/templates/wei/base.html b/apps/wei/templates/wei/base.html new file mode 100644 index 0000000..43d6179 --- /dev/null +++ b/apps/wei/templates/wei/base.html @@ -0,0 +1,109 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n pretty_money perms %} + +{# Use a fluid-width container #} +{% block containertype %}container-fluid{% endblock %} + +{% block content %} +
+
+ {% block profile_info %} + {% if club %} +
+

+ {{ club.name }} +

+
+ + + +
+
+
+
{% trans 'name'|capfirst %}
+
{{ club.name }}
+ + {% if club.require_memberships %} +
{% trans 'date start'|capfirst %}
+
{{ club.date_start }}
+ +
{% trans 'date end'|capfirst %}
+
{{ club.date_end }}
+ +
{% trans 'year'|capfirst %}
+
{{ club.year }}
+ + {% if club.membership_fee_paid == club.membership_fee_unpaid %} +
{% trans 'membership fee'|capfirst %}
+
{{ club.membership_fee_paid|pretty_money }}
+ {% else %} + {% with bde_kfet_fee=club.parent_club.membership_fee_paid|add:club.parent_club.parent_club.membership_fee_paid %} +
{% trans 'WEI fee (paid students)'|capfirst %}
+
{{ club.membership_fee_paid|add:bde_kfet_fee|pretty_money }} +
+ {% endwith %} + + {% with bde_kfet_fee=club.parent_club.membership_fee_unpaid|add:club.parent_club.parent_club.membership_fee_unpaid %} +
{% trans 'WEI fee (unpaid students)'|capfirst %}
+
{{ club.membership_fee_unpaid|add:bde_kfet_fee|pretty_money }} +
+ {% endwith %} + {% endif %} + {% endif %} + + {% if "note.view_note"|has_perm:club.note %} +
{% trans 'balance'|capfirst %}
+
{{ club.note.balance | pretty_money }}
+ {% endif %} + + {% if "note.change_alias"|has_perm:club.note.alias.first %} +
{% trans 'aliases'|capfirst %}
+
{{ club.note.alias.all|join:", " }}
+ {% endif %} + +
{% trans 'email'|capfirst %}
+
{{ club.email }}
+
+
+ +
+ {% endif %} + {% endblock %} +
+
+ {% block profile_content %}{% endblock %} +
+
+{% endblock %} diff --git a/apps/wei/templates/wei/bus_detail.html b/apps/wei/templates/wei/bus_detail.html new file mode 100644 index 0000000..c8f3ce2 --- /dev/null +++ b/apps/wei/templates/wei/bus_detail.html @@ -0,0 +1,57 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load render_table from django_tables2 %} +{% load i18n %} + +{% block profile_content %} +
+
+

{{ object.name }}

+
+ +
+ {{ object.description }} +
+ + +
+ +
+ +{% if teams.data %} +
+ + {% render_table teams %} +
+ +
+{% endif %} + +{% if memberships.data %} +
+ + {% render_table memberships %} +
+ +
+ + + + +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/bus_form.html b/apps/wei/templates/wei/bus_form.html new file mode 100644 index 0000000..c62fec4 --- /dev/null +++ b/apps/wei/templates/wei/bus_form.html @@ -0,0 +1,21 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load crispy_forms_tags %} +{% load i18n %} + +{% block profile_content %} +
+

+ {{ title }} +

+
+
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/busteam_detail.html b/apps/wei/templates/wei/busteam_detail.html new file mode 100644 index 0000000..27348d0 --- /dev/null +++ b/apps/wei/templates/wei/busteam_detail.html @@ -0,0 +1,63 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load render_table from django_tables2 %} +{% load i18n %} + +{% block profile_content %} +
+
+

{{ bus.name }}

+
+ +
+ {{ bus.description }} +
+ + +
+ +
+ +
+
+

{{ object.name }}

+
+ +
+ {{ object.description }} +
+ + +
+ +
+ +{% if memberships.data or True %} +
+ + {% render_table memberships %} +
+ +
+ + + + +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/busteam_form.html b/apps/wei/templates/wei/busteam_form.html new file mode 100644 index 0000000..c62fec4 --- /dev/null +++ b/apps/wei/templates/wei/busteam_form.html @@ -0,0 +1,21 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load crispy_forms_tags %} +{% load i18n %} + +{% block profile_content %} +
+

+ {{ title }} +

+
+
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/survey.html b/apps/wei/templates/wei/survey.html new file mode 100644 index 0000000..9eabab5 --- /dev/null +++ b/apps/wei/templates/wei/survey.html @@ -0,0 +1,28 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block profile_content %} +
+
+

{% trans "Survey WEI" %}

+
+
+
+
{% trans 'user'|capfirst %}
+
{{ object.user }}
+
+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+{% endblock %} diff --git a/apps/wei/templates/wei/survey_closed.html b/apps/wei/templates/wei/survey_closed.html new file mode 100644 index 0000000..aac9e83 --- /dev/null +++ b/apps/wei/templates/wei/survey_closed.html @@ -0,0 +1,22 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block profile_content %} +
+
+

{% trans "Survey WEI" %}

+
+
+

+ {% trans "The inscription for this WEI are now closed." %} +

+
+ +
+{% endblock %} diff --git a/apps/wei/templates/wei/survey_end.html b/apps/wei/templates/wei/survey_end.html new file mode 100644 index 0000000..3152f6e --- /dev/null +++ b/apps/wei/templates/wei/survey_end.html @@ -0,0 +1,19 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block profile_content %} +
+
+

{% trans "Survey WEI" %}

+
+
+

+ {% trans "The survey is now ended. Your answers have been saved." %} +

+
+
+{% endblock %} diff --git a/apps/wei/templates/wei/weiclub_detail.html b/apps/wei/templates/wei/weiclub_detail.html new file mode 100644 index 0000000..cd4b5ef --- /dev/null +++ b/apps/wei/templates/wei/weiclub_detail.html @@ -0,0 +1,122 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load render_table from django_tables2 %} +{% load i18n perms %} + +{% block profile_content %} +
+
+

Week-End d'Intégration

+
+
+

+ Le WEI (Week-End d’Intégration), ou 3 jours d’immersion dans les profondeurs du + monde post-préparatoire. +

+

+ Que serait une école sans son week-end d’intégration ? Quelques semaines après la + rentrée, on embarque tous et toutes à bord de bus à thèmes pour quelques jours + inoubliables dans une destination inconnue. L’objectif de ce week-end : permettre aux + nouvel·les arrivant·es de se lâcher après 2 ans de dur labeur (voire 3 pour les plus + chanceux), de découvrir l’ambiance familiale de l’ENS ainsi que de nouer des liens avec + ceux·elles qu’ils côtoieront par la suite. Dose de chants et de fun garantie ! +

+
+ {% if club.is_current_wei %} + + {% endif %} +
+ +{% if buses.data %} +
+
+ + {% trans "Buses" %} + +
+ {% render_table buses %} +
+{% endif %} + +{% if member_list.data %} +
+ + {% render_table member_list %} +
+{% endif %} + +{% if history_list.data %} +
+ +
+ {% render_table history_list %} +
+
+{% endif %} + +{% if pre_registrations.data %} +
+ +
+ {% render_table pre_registrations %} +
+
+{% endif %} + + {% if can_validate_1a %} + {% trans "Attribute buses" %} + {% endif %} +{% endblock %} + +{% block extrajavascript %} + +{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/weiclub_form.html b/apps/wei/templates/wei/weiclub_form.html new file mode 100644 index 0000000..c62fec4 --- /dev/null +++ b/apps/wei/templates/wei/weiclub_form.html @@ -0,0 +1,21 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load crispy_forms_tags %} +{% load i18n %} + +{% block profile_content %} +
+

+ {{ title }} +

+
+
+ {% csrf_token %} + {{ form|crispy }} + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/weiclub_list.html b/apps/wei/templates/wei/weiclub_list.html new file mode 100644 index 0000000..1202a66 --- /dev/null +++ b/apps/wei/templates/wei/weiclub_list.html @@ -0,0 +1,73 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load render_table from django_tables2 %} +{% load i18n %} + +{% block content %} +
+
+ + {% if can_create_wei %} +
+ {% trans "Create WEI" %} + {% endif %} +
+
+
+
+
+
+
{% trans "WEI listing" %}
+
+
+ {% render_table table %} +
+
+
+
+ +{% endblock %} +{% block extrajavascript %} + +{% endblock %} diff --git a/apps/wei/templates/wei/weilist_sample.tex b/apps/wei/templates/wei/weilist_sample.tex new file mode 100644 index 0000000..820df64 --- /dev/null +++ b/apps/wei/templates/wei/weilist_sample.tex @@ -0,0 +1,47 @@ +\documentclass[a4paper,landscape,10pt]{article} + +\usepackage{fontspec} +\usepackage[margin=1.5cm]{geometry} +\usepackage{longtable} + +\begin{document} +\begin{center} +\huge{Liste des inscrits « {{ wei.name }} »} + +{% if bus %} +\LARGE{Bus {{ bus.name|safe }}} + + +{% if team %} +\Large{Équipe {{ team.name|safe }}} +{% endif %} +{% endif %} +\end{center} + +\begin{center} +\footnotesize +\begin{longtable}{ccccccccc} +\textbf{Nom} & \textbf{Prénom} & \textbf{Date de naissance} & \textbf{Genre} & \textbf{Section} + & \textbf{Bus} & \textbf{Équipe} & \textbf{Rôles} \\ +{% for membership in memberships %} +{{ membership.user.last_name|safe }} & {{ membership.user.first_name|safe }} & {{ membership.registration.birth_date|safe }} +& {{ membership.registration.get_gender_display|safe }} & {{ membership.user.profile.section_generated|safe }} & {{ membership.bus.name|safe }} +& {% if membership.team %}{{ membership.team.name|safe }}{% else %}--{% endif %} & {{ membership.roles.first|safe }} \\ +{% endfor %} +\end{longtable} +\end{center} + +\footnotesize +Section = Année à l'ENS + code du département + +\begin{center} +\begin{longtable}{ccccccccc} +\textbf{Code} & A0 & A1 & A2 & A'2 & A''2 & A3 & B1234 & B1 \\ +\textbf{Département} & Informatique & Maths & Physique & Physique appliquée & Chimie & Biologie & SAPHIRE & Mécanique \\ +\hline +\textbf{Code} & B2 & B3 & B4 & C & D2 & D3 & E & EXT \\ +\textbf{Département} & Génie civil & Génie mécanique & EEA & Design & Éco-gestion & Sciences sociales & Anglais & Extérieur +\end{longtable} +\end{center} + +\end{document} diff --git a/apps/wei/templates/wei/weimembership_form.html b/apps/wei/templates/wei/weimembership_form.html new file mode 100644 index 0000000..7d1059b --- /dev/null +++ b/apps/wei/templates/wei/weimembership_form.html @@ -0,0 +1,203 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags pretty_money perms %} + +{% block profile_content %} +
+
+

{% trans "Review registration" %}

+
+
+
+
{% trans 'name'|capfirst %}, {% trans 'first name' %}
+
{{ registration.user.last_name }} {{ registration.user.first_name }}
+ +
{% trans 'username'|capfirst %}
+
{{ registration.user.username }}
+ +
{% trans 'email'|capfirst %}
+
{{ registration.user.email }}
+ + {% if not registration.user.profile.email_confirmed and "member.change_profile_email_confirmed"|has_perm:registration.user.profile %} +
+
+ {% trans "This user doesn't have confirmed his/her e-mail address." %} + {% trans "Click here to resend a validation link." %} +
+
+ {% endif %} + +
{% trans 'department'|capfirst %}
+
{{ registration.user.profile.department }}
+ +
{% trans 'ENS year'|capfirst %}
+
{{ registration.user.profile.ens_year }}
+ +
{% trans 'section'|capfirst %}
+
{{ registration.user.profile.section }}
+ +
{% trans 'address'|capfirst %}
+
{{ registration.user.profile.address }}
+ +
{% trans 'phone number'|capfirst %}
+
{{ registration.user.profile.phone_number }}
+ +
{% trans 'paid'|capfirst %}
+
{{ registration.user.profile.paid|yesno }}
+ +
+ +
{% trans 'first year'|capfirst %}
+
{{ registration.first_year|yesno }}
+ +
{% trans 'gender'|capfirst %}
+
{{ registration.get_gender_display }}
+ +
{% trans 'clothing cut'|capfirst %}
+
{{ registration.clothing_cut }}
+ +
{% trans 'clothing size'|capfirst %}
+
{{ registration.clothing_size }}
+ +
{% trans 'birth date'|capfirst %}
+
{{ registration.birth_date }}
+ +
{% trans 'health issues'|capfirst %}
+
{{ registration.health_issues }}
+ +
{% trans 'emergency contact name'|capfirst %}
+
{{ registration.emergency_contact_name }}
+ +
{% trans 'emergency contact phone'|capfirst %}
+
{{ registration.emergency_contact_phone }}
+ +
{% trans 'Payment from Société générale' %}
+
{{ registration.soge_credit|yesno }}
+ + {% if registration.first_year %} +
{% trans 'Suggested bus from the survey:' %}
+ {% if registration.information.valid or True %} +
{{ suggested_bus }}
+ +
+
{% trans 'Raw survey information' %}
+
+ + {% with information=registration.information %} + {% for key, value in information.items %} +
{{ key }}
+
{{ value }}
+ {% endfor %} + {% endwith %} + {% else %} +
{% trans "The algorithm didn't run." %}
+ {% endif %} + {% else %} +
{% trans 'caution check given'|capfirst %}
+
{{ registration.caution_check|yesno }}
+ + {% with information=registration.information %} +
{% trans 'preferred bus'|capfirst %}
+
{{ information.preferred_bus_name|join:', ' }}
+ +
{% trans 'preferred team'|capfirst %}
+
{{ information.preferred_team_name|join:', ' }}
+ +
{% trans 'preferred roles'|capfirst %}
+
{{ information.preferred_roles_name|join:', ' }}
+ {% endwith %} + {% endif %} +
+
+ +
+ +
+ +
+
+
+

{% trans "Validate registration" %}

+
+ {% if registration.is_validated %} +
+ {% trans "The registration is already validated and can't be unvalidated." %} + {% trans "The user joined the bus" %} {{ registration.membership.bus }} + {% if registration.membership.team %}{% trans "in the team" %} {{ registration.membership.team }}, + {% else %}{% trans "in no team (staff)" %},{% endif %} {% trans "with the following roles:" %} {{ registration.membership.roles.all|join:", " }} +
+ {% else %} + {% if registration.soge_credit %} +
+ {% blocktrans trimmed %} + The WEI will be paid by Société générale. The membership will be created even if the bank didn't pay the BDE yet. + The membership transaction will be created but will be invalid. You will have to validate it once the bank + validated the creation of the account, or to change the payment method. + {% endblocktrans %} +
+ {% else %} + {% if registration.user.note.balance < fee %} +
+ {% with pretty_fee=fee|pretty_money %} + {% blocktrans trimmed with balance=registration.user.note.balance|pretty_money %} + The note don't have enough money ({{ balance }}, {{ pretty_fee }} required). + The registration may fail if you don't credit the note now. + {% endblocktrans %} + {% endwith %} +
+ {% else %} +
+ {% blocktrans trimmed with pretty_fee=fee|pretty_money %} + The note has enough money ({{ pretty_fee }} required), the registration is possible. + {% endblocktrans %} +
+ {% endif %} + {% endif %} + + {% if not registration.caution_check and not registration.first_year %} +
+ {% trans "The user didn't give her/his caution check." %} +
+ {% endif %} + + {% if not kfet_member %} +
+ {% url 'registration:future_user_detail' pk=registration.user.pk as future_user_detail %} + {% url 'member:club_detail' pk=club.parent_club.parent_club.pk as club_detail %} + {% blocktrans trimmed %} + This user is not a member of the Kfet club for the coming year. The membership will be + processed automatically, the WEI registration includes the membership fee. + {% endblocktrans %} +
+ {% endif %} + +
+ {% csrf_token %} + {{ form|crispy }} +
+ + {% endif %} +
+
+{% endblock %} + +{% block extrajavascript %} + +{% endblock %} diff --git a/apps/wei/templates/wei/weimembership_list.html b/apps/wei/templates/wei/weimembership_list.html new file mode 100644 index 0000000..fe9506b --- /dev/null +++ b/apps/wei/templates/wei/weimembership_list.html @@ -0,0 +1,55 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load render_table from django_tables2 %} + +{% block profile_content %} +
+
+ +
+ +
+ {% if table.data %} + {% render_table table %} + {% else %} +
+ {% trans "There is no membership found with this pattern." %} +
+ {% endif %} +
+
+ + +
+{% endblock %} + +{% block extrajavascript %} + +{% endblock %} diff --git a/apps/wei/templates/wei/weiregistration_confirm_delete.html b/apps/wei/templates/wei/weiregistration_confirm_delete.html new file mode 100644 index 0000000..f1d2e88 --- /dev/null +++ b/apps/wei/templates/wei/weiregistration_confirm_delete.html @@ -0,0 +1,36 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block profile_content %} +
+
+

{% trans "Delete registration" %}

+
+ {% if object.is_validated %} +
+
+ {% blocktrans %}This registration is already validated and can't be deleted.{% endblocktrans %} +
+
+ {% else %} +
+
+ {% with user=object.user wei_name=object.wei.name %} + {% blocktrans %}Are you sure you want to delete the registration of {{ user }} for the WEI {{ wei_name }}? This action can't be undone.{% endblocktrans %} + {% endwith %} +
+
+ + {% endif %} +
+{% endblock %} diff --git a/apps/wei/templates/wei/weiregistration_form.html b/apps/wei/templates/wei/weiregistration_form.html new file mode 100644 index 0000000..fae85e0 --- /dev/null +++ b/apps/wei/templates/wei/weiregistration_form.html @@ -0,0 +1,50 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block profile_content %} +
+

+ {{ title }} +

+
+
+ {% csrf_token %} + {{ form|crispy }} + {{ membership_form|crispy }} + +
+
+
+{% endblock %} + +{% block extrajavascript %} +{% if not object.membership %} + +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/weiregistration_list.html b/apps/wei/templates/wei/weiregistration_list.html new file mode 100644 index 0000000..c0c1e32 --- /dev/null +++ b/apps/wei/templates/wei/weiregistration_list.html @@ -0,0 +1,61 @@ +{% extends "wei/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} +{% load render_table from django_tables2 %} + +{% block profile_content %} +
+
+ +
+ +
+ {% if table.data %} + {% render_table table %} + {% else %} +
+ {% trans "There is no pre-registration found with this pattern." %} +
+ {% endif %} +
+
+ + +
+{% endblock %} + +{% block extrajavascript %} + +{% endblock %} diff --git a/apps/wei/tests/__init__.py b/apps/wei/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/wei/tests/test_wei_algorithm_2021.py b/apps/wei/tests/test_wei_algorithm_2021.py new file mode 100644 index 0000000..5320712 --- /dev/null +++ b/apps/wei/tests/test_wei_algorithm_2021.py @@ -0,0 +1,110 @@ +# Copyright (C) 2018-2021 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.wei2021 import WEIBusInformation2021, WEISurvey2021, WORDS, WEISurveyInformation2021 +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 2021", + email="wei2021@example.com", + date_start='2021-09-17', + date_end='2021-09-19', + year=2021, + ) + + 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 = WEIBusInformation2021(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 = WEISurveyInformation2021(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 + WEISurvey2021.get_algorithm_class()().run_algorithm() + + # Ensure that everyone has its first choice + for r in WEIRegistration.objects.filter(wei=self.wei).all(): + survey = WEISurvey2021(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 = WEISurveyInformation2021(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 + WEISurvey2021.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 = WEISurvey2021(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 % diff --git a/apps/wei/tests/test_wei_algorithm_2022.py b/apps/wei/tests/test_wei_algorithm_2022.py new file mode 100644 index 0000000..2d358db --- /dev/null +++ b/apps/wei/tests/test_wei_algorithm_2022.py @@ -0,0 +1,110 @@ +# Copyright (C) 2018-2022 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.wei2022 import WEIBusInformation2022, WEISurvey2022, WORDS, WEISurveyInformation2022 +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 2022", + email="wei2022@example.com", + date_start='2022-09-16', + date_end='2022-09-18', + year=2022, + ) + + 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 = WEIBusInformation2022(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 = WEISurveyInformation2022(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 + WEISurvey2022.get_algorithm_class()().run_algorithm() + + # Ensure that everyone has its first choice + for r in WEIRegistration.objects.filter(wei=self.wei).all(): + survey = WEISurvey2022(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 = WEISurveyInformation2022(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 + WEISurvey2022.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 = WEISurvey2022(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 % diff --git a/apps/wei/tests/test_wei_registration.py b/apps/wei/tests/test_wei_registration.py new file mode 100644 index 0000000..ef285f4 --- /dev/null +++ b/apps/wei/tests/test_wei_registration.py @@ -0,0 +1,879 @@ +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +import subprocess +from datetime import timedelta, date + +from api.tests import TestAPI +from django.conf import settings +from django.contrib.auth.models import User +from django.db.models import Q +from django.test import TestCase +from django.urls import reverse +from django.utils import timezone +from member.models import Membership, Club +from note.models import NoteClub, SpecialTransaction, NoteUser +from treasury.models import SogeCredit + +from ..api.views import BusViewSet, BusTeamViewSet, WEIClubViewSet, WEIMembershipViewSet, WEIRegistrationViewSet, \ + WEIRoleViewSet +from ..forms import CurrentSurvey, WEISurveyAlgorithm, WEISurvey +from ..models import WEIClub, Bus, BusTeam, WEIRole, WEIRegistration, WEIMembership + + +class TestWEIList(TestCase): + fixtures = ('initial',) + + def setUp(self): + self.user = User.objects.create_superuser( + username="weiadmin", + password="admin", + email="admin@example.com", + ) + self.client.force_login(self.user) + sess = self.client.session + sess["permission_mask"] = 42 + sess.save() + + def test_current_wei_detail(self): + """ + Test that when no WEI is created, the WEI button redirect to the WEI list + """ + response = self.client.get(reverse("wei:current_wei_detail")) + self.assertRedirects(response, reverse("wei:wei_list"), 302, 200) + + +class TestWEIRegistration(TestCase): + """ + Test the whole WEI app + """ + fixtures = ('initial',) + + def setUp(self): + """ + Setup the database with initial data + Create a new user, a new WEI, bus, team, registration + """ + 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.year = timezone.now().year + self.wei = WEIClub.objects.create( + name="Test WEI", + email="gc.wei@example.com", + parent_club_id=2, + membership_fee_paid=12500, + membership_fee_unpaid=5500, + membership_start=date(self.year, 1, 1), + membership_end=date(self.year, 12, 31), + year=self.year, + date_start=date.today() + timedelta(days=2), + date_end=date(self.year, 12, 31), + ) + NoteClub.objects.create(club=self.wei) + self.bus = Bus.objects.create( + name="Test Bus", + wei=self.wei, + description="Test Bus", + ) + + # Setup the bus + bus_info = CurrentSurvey.get_algorithm_class().get_bus_information(self.bus) + bus_info.scores["Jus de fruit"] = 70 + bus_info.save() + self.bus.save() + + self.team = BusTeam.objects.create( + name="Test Team", + bus=self.bus, + color=0xFFFFFF, + description="Test Team", + ) + self.registration = WEIRegistration.objects.create( + user_id=self.user.id, + wei_id=self.wei.id, + soge_credit=True, + caution_check=True, + birth_date=date(2000, 1, 1), + gender="nonbinary", + clothing_cut="male", + clothing_size="XL", + health_issues="I am a bot", + emergency_contact_name="Pikachu", + emergency_contact_phone="+33123456789", + first_year=False, + ) + + def test_create_wei(self): + """ + Test creating a new WEI club. + """ + response = self.client.post(reverse("wei:wei_create"), dict( + name="Create WEI Test", + email="gc.wei@example.com", + membership_fee_paid=12500, + membership_fee_unpaid=5500, + membership_start=str(self.year + 1) + "-08-01", + membership_end=str(self.year + 1) + "-09-30", + year=self.year + 1, + date_start=str(self.year + 1) + "-09-01", + date_end=str(self.year + 1) + "-09-03", + )) + qs = WEIClub.objects.filter(name="Create WEI Test", year=self.year + 1) + self.assertTrue(qs.exists()) + wei = qs.get() + self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=wei.pk)), 302, 200) + + def test_wei_detail(self): + """ + Test display the information about the default WEI. + """ + response = self.client.get(reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + def test_current_wei_detail(self): + """ + Test display the information about the current WEI. + """ + response = self.client.get(reverse("wei:current_wei_detail")) + self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_update_wei(self): + """ + Test update the information about the default WEI. + """ + response = self.client.post(reverse("wei:wei_update", kwargs=dict(pk=self.wei.pk)), dict( + name="Update WEI Test", + year=2000, + email="wei-updated@example.com", + membership_fee_paid=0, + membership_fee_unpaid=0, + membership_start="2000-08-01", + membership_end="2000-09-30", + date_start="2000-09-01", + date_end="2000-09-03", + )) + qs = WEIClub.objects.filter(name="Update WEI Test", id=self.wei.id) + self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk)), 302, 200) + self.assertTrue(qs.exists()) + + # Check that if the WEI is started, we can't update a wei + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:wei_update", kwargs=dict(pk=self.wei.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_wei_closed(self): + """ + Test display the page when a WEI is closed. + """ + response = self.client.get(reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + def test_wei_list(self): + """ + Test display the list of all WEI. + """ + response = self.client.get(reverse("wei:wei_list")) + self.assertEqual(response.status_code, 200) + + def test_add_bus(self): + """ + Test create a new bus. + """ + response = self.client.get(reverse("wei:add_bus", kwargs=dict(pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.post(reverse("wei:add_bus", kwargs=dict(pk=self.wei.pk)), dict( + wei=self.wei.id, + name="Create Bus Test", + size=50, + description="This bus was created.", + information_json="{}", + )) + qs = Bus.objects.filter(name="Create Bus Test") + self.assertTrue(qs.exists()) + bus = qs.get() + CurrentSurvey.get_algorithm_class().get_bus_information(bus).save() + self.assertRedirects(response, reverse("wei:manage_bus", kwargs=dict(pk=bus.pk)), 302, 200) + + # Check that if the WEI is started, we can't create a bus + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:add_bus", kwargs=dict(pk=self.wei.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_detail_bus(self): + """ + Test display the information about a bus. + """ + response = self.client.get(reverse("wei:manage_bus", kwargs=dict(pk=self.bus.pk))) + self.assertEqual(response.status_code, 200) + + def test_update_bus(self): + """ + Test update a bus. + """ + response = self.client.get(reverse("wei:update_bus", kwargs=dict(pk=self.bus.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.post(reverse("wei:update_bus", kwargs=dict(pk=self.bus.pk)), dict( + name="Update Bus Test", + size=40, + description="This bus was updated.", + information_json="{}", + )) + qs = Bus.objects.filter(name="Update Bus Test", id=self.bus.id) + self.assertRedirects(response, reverse("wei:manage_bus", kwargs=dict(pk=self.bus.pk)), 302, 200) + self.assertTrue(qs.exists()) + + # Check that if the WEI is started, we can't update a bus + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:update_bus", kwargs=dict(pk=self.bus.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_add_team(self): + """ + Test create a new team. + """ + response = self.client.get(reverse("wei:add_team", kwargs=dict(pk=self.bus.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.post(reverse("wei:add_team", kwargs=dict(pk=self.bus.pk)), dict( + bus=self.bus.id, + name="Create Team Test", + color="#2A", + description="This team was created.", + )) + qs = BusTeam.objects.filter(name="Create Team Test", color=42) + self.assertTrue(qs.exists()) + team = qs.get() + self.assertRedirects(response, reverse("wei:manage_bus_team", kwargs=dict(pk=team.pk)), 302, 200) + + # Check that if the WEI is started, we can't create a team + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:add_team", kwargs=dict(pk=self.bus.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_detail_team(self): + """ + Test display the detail about a team. + """ + response = self.client.get(reverse("wei:manage_bus_team", kwargs=dict(pk=self.team.pk))) + self.assertEqual(response.status_code, 200) + + def test_update_team(self): + """ + Test update a team. + """ + response = self.client.get(reverse("wei:update_bus_team", kwargs=dict(pk=self.team.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.post(reverse("wei:update_bus_team", kwargs=dict(pk=self.team.pk)), dict( + name="Update Team Test", + color="#A6AA", + description="This team was updated.", + )) + qs = BusTeam.objects.filter(name="Update Team Test", color=42666, id=self.team.id) + self.assertRedirects(response, reverse("wei:manage_bus_team", kwargs=dict(pk=self.team.pk)), 302, 200) + self.assertTrue(qs.exists()) + + # Check that if the WEI is started, we can't update a team + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:update_bus_team", kwargs=dict(pk=self.team.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_register_2a(self): + """ + Test register a new 2A+ to the WEI. + """ + response = self.client.get(reverse("wei:wei_register_2A", 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) + + # Try with an invalid form + response = self.client.post(reverse("wei:wei_register_2A", 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', + bus=[], + team=[], + roles=[], + )) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.context["membership_form"].is_valid()) + + response = self.client.post(reverse("wei:wei_register_2A", 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', + bus=[self.bus.id], + team=[self.team.id], + roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A")).all()], + )) + qs = WEIRegistration.objects.filter(user_id=user.id) + self.assertTrue(qs.exists()) + self.assertRedirects(response, reverse("wei:wei_survey", kwargs=dict(pk=qs.get().pk)), 302, 302) + + # Check that the user can't be registered twice + response = self.client.post(reverse("wei:wei_register_2A", 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', + bus=[self.bus.id], + team=[self.team.id], + roles=[role.id for role in WEIRole.objects.filter(~Q(name="1A")).all()], + )) + self.assertEqual(response.status_code, 200) + self.assertTrue("This user is already registered to this WEI." in str(response.context["form"].errors)) + + # Test the render of the page to register ourself if we have already opened a Société générale account + SogeCredit.objects.create(user=self.user, credit_transaction=SpecialTransaction.objects.create( + source_id=4, # Bank transfer + destination=self.user.note, + quantity=1, + amount=0, + reason="Test", + first_name="toto", + last_name="toto", + bank="Société générale", + )) + response = self.client.get(reverse("wei:wei_register_2A", kwargs=dict(wei_pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + # Check that if the WEI is started, we can't register anyone + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:wei_register_2A", kwargs=dict(wei_pk=self.wei.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + 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 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( + 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', + )) + self.assertEqual(response.status_code, 200) + self.assertTrue("This user is already registered to this WEI." in str(response.context["form"].errors)) + + # Check that the user can't be registered twice as a first year member + second_wei = WEIClub.objects.create( + name="Second WEI", + year=self.year + 1, + date_start=str(self.year + 1) + "-01-01", + date_end=str(self.year + 1) + "-12-31", + membership_start=str(self.year) + "-01-01", + membership_end=str(self.year + 1) + "-12-31", + ) + response = self.client.post(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=second_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', + )) + self.assertEqual(response.status_code, 200) + self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." + in str(response.context["form"].errors)) + + # Check that if the WEI is started, we can't register anyone + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=self.wei.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + response = self.client.get(reverse("wei:wei_survey", kwargs=dict(pk=registration.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_register_myself(self): + """ + Try to register myself to the WEI, and check redirections. + """ + response = self.client.get(reverse('wei:wei_register_1A_myself', args=(self.wei.pk,))) + self.assertRedirects(response, reverse('wei:wei_update_registration', args=(self.registration.pk,))) + + response = self.client.get(reverse('wei:wei_register_2A_myself', args=(self.wei.pk,))) + self.assertRedirects(response, reverse('wei:wei_update_registration', args=(self.registration.pk,))) + + self.registration.delete() + + response = self.client.get(reverse('wei:wei_register_1A_myself', args=(self.wei.pk,))) + self.assertEqual(response.status_code, 200) + + response = self.client.get(reverse('wei:wei_register_2A_myself', args=(self.wei.pk,))) + self.assertEqual(response.status_code, 200) + + def test_wei_survey_ended(self): + """ + Test display the end page of a survey. + """ + response = self.client.get(reverse("wei:wei_survey_end", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 200) + + def test_update_registration(self): + """ + Test update a registration. + """ + self.registration.information = dict( + preferred_bus_pk=[], + preferred_team_pk=[], + preferred_roles_pk=[] + ) + self.registration.save() + + response = self.client.get(reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.post( + reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk)), + dict( + user=self.user.id, + soge_credit=False, + birth_date='2020-01-01', + gender='female', + clothing_cut='male', + clothing_size='M', + health_issues='I am really a bot', + emergency_contact_name='Note Kfet 2020', + emergency_contact_phone='+33600000000', + bus=[self.bus.id], + team=[self.team.id], + roles=[role.id for role in WEIRole.objects.filter(name="Adhérent WEI").all()], + information_json=self.registration.information_json, + ) + ) + qs = WEIRegistration.objects.filter(user_id=self.user.id, soge_credit=False, clothing_size="M") + self.assertTrue(qs.exists()) + self.assertRedirects(response, reverse("wei:validate_registration", kwargs=dict(pk=qs.get().pk)), 302, 200) + + # Check the page when the registration is already validated + membership = WEIMembership( + user=self.user, + club=self.wei, + registration=self.registration, + bus=self.bus, + team=self.team, + ) + membership._soge = True + membership._force_renew_parent = True + membership.save() + soge_credit = SogeCredit.objects.get(user=self.user) + soge_credit.credit_transaction = SpecialTransaction.objects.create( + source_id=4, # Bank transfer + destination=self.user.note, + quantity=1, + amount=0, + reason="Test", + first_name="toto", + last_name="toto", + bank="Société générale", + ) + soge_credit.save() + + sess = self.client.session + sess["permission_mask"] = 0 + sess.save() + response = self.client.get(reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 403) + sess["permission_mask"] = 42 + sess.save() + + response = self.client.post( + reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk)), + dict( + user=self.user.id, + soge_credit=False, + birth_date='2015-01-01', + gender='male', + clothing_cut='female', + clothing_size='L', + health_issues='I am really a bot', + emergency_contact_name='Note Kfet 2020', + emergency_contact_phone='+33600000000', + bus=[self.bus.id], + team=[self.team.id], + roles=[role.id for role in WEIRole.objects.filter(name="Adhérent WEI").all()], + information_json=self.registration.information_json, + ) + ) + qs = WEIRegistration.objects.filter(user_id=self.user.id, clothing_size="L") + self.assertTrue(qs.exists()) + self.assertRedirects(response, reverse("wei:validate_registration", kwargs=dict(pk=qs.get().pk)), 302, 200) + + # Test invalid form + response = self.client.post( + reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk)), + dict( + user=self.user.id, + soge_credit=False, + birth_date='2015-01-01', + gender='male', + clothing_cut='female', + clothing_size='L', + health_issues='I am really a bot', + emergency_contact_name='Note Kfet 2020', + emergency_contact_phone='+33600000000', + bus=[], + team=[], + roles=[], + information_json=self.registration.information_json, + ) + ) + self.assertFalse(response.context["membership_form"].is_valid()) + + # Check that if the WEI is started, we can't update a registration + self.wei.date_start = date(2000, 1, 1) + self.wei.update_membership_dates() + self.wei.save() + response = self.client.get(reverse("wei:wei_update_registration", kwargs=dict(pk=self.registration.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_delete_registration(self): + """ + Test delete a WEI registration. + """ + response = self.client.get(reverse("wei:wei_delete_registration", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.delete(reverse("wei:wei_delete_registration", kwargs=dict(pk=self.registration.pk))) + self.assertRedirects(response, reverse("wei:wei_detail", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_validate_membership(self): + """ + Test validate a membership. + """ + response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 200) + + self.registration.first_year = True + self.registration.save() + + response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk))) + self.assertEqual(response.status_code, 200) + + self.registration.first_year = False + self.registration.save() + + # Check that a team must belong to the bus + second_bus = Bus.objects.create(wei=self.wei, name="Second bus") + second_team = BusTeam.objects.create(bus=second_bus, name="Second team", color=42) + response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict( + roles=[WEIRole.objects.get(name="GC WEI").id], + bus=self.bus.pk, + team=second_team.pk, + credit_type=4, # Bank transfer + credit_amount=420, + last_name="admin", + first_name="admin", + bank="Société générale", + )) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.context["form"].is_valid()) + self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) + + response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict( + roles=[WEIRole.objects.get(name="GC WEI").id], + bus=self.bus.pk, + team=self.team.pk, + credit_type=4, # Bank transfer + credit_amount=420, + last_name="admin", + 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) + # Check if the membership is successfully created + membership = WEIMembership.objects.filter(user_id=self.user.id, club=self.wei) + self.assertTrue(membership.exists()) + membership = membership.get() + # Check if the user is member of the Kfet club and the BDE + kfet_membership = Membership.objects.filter(user_id=self.user.id, club__name="Kfet") + self.assertTrue(kfet_membership.exists()) + kfet_membership = kfet_membership.get() + bde_membership = Membership.objects.filter(user_id=self.user.id, club__name="BDE") + self.assertTrue(bde_membership.exists()) + bde_membership = bde_membership.get() + + if "treasury" in settings.INSTALLED_APPS: + # The registration is made with the Société générale. Ensure that all is fine + from treasury.models import SogeCredit + soge_credit = SogeCredit.objects.filter(user_id=self.user.id) + self.assertTrue(soge_credit.exists()) + soge_credit = soge_credit.get() + self.assertTrue(membership.transaction in soge_credit.transactions.all()) + self.assertTrue(kfet_membership.transaction in soge_credit.transactions.all()) + self.assertTrue(bde_membership.transaction in soge_credit.transactions.all()) + self.assertFalse(membership.transaction.valid) + self.assertFalse(kfet_membership.transaction.valid) + self.assertFalse(bde_membership.transaction.valid) + + # Check that if the WEI is started, we can't update a wei + self.wei.date_start = date(2000, 1, 1) + self.wei.save() + response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk))) + self.assertRedirects(response, reverse("wei:wei_closed", kwargs=dict(pk=self.wei.pk)), 302, 200) + + def test_registrations_list(self): + """ + Test display the registration list, with or without a research + """ + response = self.client.get(reverse("wei:wei_registrations", kwargs=dict(pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.get(reverse("wei:wei_registrations", kwargs=dict(pk=self.wei.pk)) + "?search=.") + self.assertEqual(response.status_code, 200) + + def test_memberships_list(self): + """ + Test display the memberships list, with or without a research + """ + response = self.client.get(reverse("wei:wei_memberships", kwargs=dict(pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + + response = self.client.get(reverse("wei:wei_memberships", kwargs=dict(pk=self.wei.pk)) + "?search=.") + self.assertEqual(response.status_code, 200) + + def is_latex_installed(self): + """ + Check if LaTeX is installed in the machine. Don't check pages that generate a PDF file if LaTeX is not + installed, like in Gitlab. + """ + with open("/dev/null", "wb") as devnull: + return subprocess.call( + ["/usr/bin/which", "xelatex"], + stdout=devnull, + stderr=devnull, + ) == 0 + + def test_memberships_pdf_list(self): + """ + Test display the membership list as a PDF file + """ + if self.is_latex_installed(): + response = self.client.get(reverse("wei:wei_memberships_pdf", kwargs=dict(wei_pk=self.wei.pk))) + self.assertEqual(response.status_code, 200) + self.assertEqual(response["content-type"], "application/pdf") + + def test_bus_memberships_pdf_list(self): + """ + Test display the membership list of a bus as a PDF file + """ + if self.is_latex_installed(): + response = self.client.get(reverse("wei:wei_memberships_bus_pdf", kwargs=dict(wei_pk=self.wei.pk, + bus_pk=self.bus.pk))) + self.assertEqual(response.status_code, 200) + self.assertEqual(response["content-type"], "application/pdf") + + def test_team_memberships_pdf_list(self): + """ + Test display the membership list of a bus team as a PDF file + """ + if self.is_latex_installed(): + response = self.client.get(reverse("wei:wei_memberships_team_pdf", kwargs=dict(wei_pk=self.wei.pk, + bus_pk=self.bus.pk, + team_pk=self.team.pk))) + self.assertEqual(response.status_code, 200) + self.assertEqual(response["content-type"], "application/pdf") + + +class TestDefaultWEISurvey(TestCase): + """ + Doesn't test anything, just cover the default Survey classes. + """ + def check_not_implemented(self, fun: callable, *args, **kwargs): + self.assertRaises(NotImplementedError, fun, *args, **kwargs) + + def test_survey_classes(self): + WEISurveyAlgorithm.get_bus_information_class() + self.check_not_implemented(WEISurveyAlgorithm.get_survey_class) + self.check_not_implemented(WEISurveyAlgorithm.get_registrations) + self.check_not_implemented(WEISurveyAlgorithm.get_buses) + self.check_not_implemented(WEISurveyAlgorithm().run_algorithm) + + self.check_not_implemented(WEISurvey, registration=None) + self.check_not_implemented(WEISurvey.get_wei) + self.check_not_implemented(WEISurvey.get_survey_information_class) + self.check_not_implemented(WEISurvey.get_algorithm_class) + self.check_not_implemented(WEISurvey.get_form_class, None) + self.check_not_implemented(WEISurvey.form_valid, None, None) + self.check_not_implemented(WEISurvey.is_complete, None) + # noinspection PyTypeChecker + WEISurvey.update_form(None, None) + + self.assertEqual(CurrentSurvey.get_algorithm_class().get_survey_class(), CurrentSurvey) + self.assertEqual(CurrentSurvey.get_year(), 2022) + + +class TestWeiAPI(TestAPI): + def setUp(self) -> None: + super().setUp() + + self.year = timezone.now().year + self.wei = WEIClub.objects.create( + name="Test WEI", + email="gc.wei@example.com", + parent_club_id=2, + membership_fee_paid=12500, + membership_fee_unpaid=5500, + membership_start=date(self.year, 1, 1), + membership_end=date(self.year, 12, 31), + membership_duration=396, + year=self.year, + date_start=date.today() + timedelta(days=2), + date_end=date(self.year, 12, 31), + ) + NoteClub.objects.create(club=self.wei) + self.bus = Bus.objects.create( + name="Test Bus", + wei=self.wei, + description="Test Bus", + ) + self.team = BusTeam.objects.create( + name="Test Team", + bus=self.bus, + color=0xFFFFFF, + description="Test Team", + ) + self.registration = WEIRegistration.objects.create( + user_id=self.user.id, + wei_id=self.wei.id, + soge_credit=True, + caution_check=True, + birth_date=date(2000, 1, 1), + gender="nonbinary", + clothing_cut="male", + clothing_size="XL", + health_issues="I am a bot", + emergency_contact_name="Pikachu", + emergency_contact_phone="+33123456789", + first_year=False, + ) + Membership.objects.create(user=self.user, club=Club.objects.get(name="BDE")) + Membership.objects.create(user=self.user, club=Club.objects.get(name="Kfet")) + self.membership = WEIMembership.objects.create( + user=self.user, + club=self.wei, + fee=125, + bus=self.bus, + team=self.team, + registration=self.registration, + ) + self.membership.roles.add(WEIRole.objects.last()) + self.membership.save() + + def test_weiclub_api(self): + """ + Load WEI API page and test all filters and permissions + """ + self.check_viewset(WEIClubViewSet, "/api/wei/club/") + + def test_wei_bus_api(self): + """ + Load Bus API page and test all filters and permissions + """ + self.check_viewset(BusViewSet, "/api/wei/bus/") + + def test_wei_team_api(self): + """ + Load BusTeam API page and test all filters and permissions + """ + self.check_viewset(BusTeamViewSet, "/api/wei/team/") + + def test_weirole_api(self): + """ + Load WEIRole API page and test all filters and permissions + """ + self.check_viewset(WEIRoleViewSet, "/api/wei/role/") + + def test_weiregistration_api(self): + """ + Load WEIRegistration API page and test all filters and permissions + """ + self.check_viewset(WEIRegistrationViewSet, "/api/wei/registration/") + + def test_weimembership_api(self): + """ + Load WEIMembership API page and test all filters and permissions + """ + self.check_viewset(WEIMembershipViewSet, "/api/wei/membership/") diff --git a/apps/wei/urls.py b/apps/wei/urls.py new file mode 100644 index 0000000..fb49721 --- /dev/null +++ b/apps/wei/urls.py @@ -0,0 +1,45 @@ +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.urls import path + +from .views import CurrentWEIDetailView, WEI1AListView, WEIListView, WEICreateView, WEIDetailView, WEIUpdateView, \ + WEIRegistrationsView, WEIMembershipsView, MemberListRenderView, \ + BusCreateView, BusManageView, BusUpdateView, BusTeamCreateView, BusTeamManageView, BusTeamUpdateView, \ + WEIAttributeBus1AView, WEIAttributeBus1ANextView, WEIRegister1AView, WEIRegister2AView, WEIUpdateRegistrationView, \ + WEIDeleteRegistrationView, WEIValidateRegistrationView, WEISurveyView, WEISurveyEndView, WEIClosedView + +app_name = 'wei' +urlpatterns = [ + path('detail/', CurrentWEIDetailView.as_view(), name="current_wei_detail"), + path('list/', WEIListView.as_view(), name="wei_list"), + path('create/', WEICreateView.as_view(), name="wei_create"), + path('detail//', WEIDetailView.as_view(), name="wei_detail"), + path('update//', WEIUpdateView.as_view(), name="wei_update"), + path('detail//registrations/', WEIRegistrationsView.as_view(), name="wei_registrations"), + path('detail//memberships/', WEIMembershipsView.as_view(), name="wei_memberships"), + path('detail//memberships/pdf/', MemberListRenderView.as_view(), name="wei_memberships_pdf"), + path('detail//memberships/pdf//', MemberListRenderView.as_view(), + name="wei_memberships_bus_pdf"), + path('detail//memberships/pdf///', MemberListRenderView.as_view(), + name="wei_memberships_team_pdf"), + path('bus-1A/list//', WEI1AListView.as_view(), name="wei_1A_list"), + path('add-bus//', BusCreateView.as_view(), name="add_bus"), + path('manage-bus//', BusManageView.as_view(), name="manage_bus"), + path('update-bus//', BusUpdateView.as_view(), name="update_bus"), + path('add-bus-team//', BusTeamCreateView.as_view(), name="add_team"), + path('manage-bus-team//', BusTeamManageView.as_view(), name="manage_bus_team"), + path('update-bus-team//', BusTeamUpdateView.as_view(), name="update_bus_team"), + path('register//1A/', WEIRegister1AView.as_view(), name="wei_register_1A"), + path('register//2A+/', WEIRegister2AView.as_view(), name="wei_register_2A"), + path('register//1A/myself/', WEIRegister1AView.as_view(), name="wei_register_1A_myself"), + path('register//2A+/myself/', WEIRegister2AView.as_view(), name="wei_register_2A_myself"), + path('edit-registration//', WEIUpdateRegistrationView.as_view(), name="wei_update_registration"), + path('delete-registration//', WEIDeleteRegistrationView.as_view(), name="wei_delete_registration"), + path('validate//', WEIValidateRegistrationView.as_view(), name="validate_registration"), + path('survey//', WEISurveyView.as_view(), name="wei_survey"), + path('survey//end/', WEISurveyEndView.as_view(), name="wei_survey_end"), + path('detail//closed/', WEIClosedView.as_view(), name="wei_closed"), + path('bus-1A//', WEIAttributeBus1AView.as_view(), name="wei_bus_1A"), + path('bus-1A/next//', WEIAttributeBus1ANextView.as_view(), name="wei_bus_1A_next"), +] diff --git a/apps/wei/views.py b/apps/wei/views.py new file mode 100644 index 0000000..80ff770 --- /dev/null +++ b/apps/wei/views.py @@ -0,0 +1,1241 @@ +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +import os +import shutil +import subprocess +from datetime import date, timedelta +from tempfile import mkdtemp + +from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.models import User +from django.core.exceptions import PermissionDenied +from django.db import transaction +from django.db.models import Q, Count +from django.db.models.functions.text import Lower +from django.http import HttpResponse, Http404 +from django.shortcuts import redirect +from django.template.loader import render_to_string +from django.urls import reverse_lazy +from django.views import View +from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView +from django.utils.translation import gettext_lazy as _ +from django.views.generic.edit import BaseFormView, DeleteView +from django_tables2 import SingleTableView +from member.models import Membership, Club +from note.models import Transaction, NoteClub, Alias, SpecialTransaction, NoteSpecial +from note.tables import HistoryTable +from note_kfet.settings import BASE_DIR +from permission.backends import PermissionBackend +from permission.views import ProtectQuerysetMixin, ProtectedCreateView + +from .forms.registration import WEIChooseBusForm +from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole +from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMembership1AForm, \ + WEIMembershipForm, CurrentSurvey +from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \ + WEIRegistration1ATable, WEIMembershipTable + + +class CurrentWEIDetailView(LoginRequiredMixin, RedirectView): + def get_redirect_url(self, *args, **kwargs): + wei = WEIClub.objects.filter(membership_start__lte=date.today()).order_by('date_start') + if wei.exists(): + wei = wei.last() + return reverse_lazy('wei:wei_detail', args=(wei.pk,)) + else: + return reverse_lazy('wei:wei_list') + + +class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): + """ + List existing WEI + """ + model = WEIClub + table_class = WEITable + ordering = '-year' + extra_context = {"title": _("Search WEI")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["can_create_wei"] = PermissionBackend.check_perm(self.request, "wei.add_weiclub", WEIClub( + name="", + email="weiclub@example.com", + year=0, + date_start=date.today(), + date_end=date.today(), + )) + return context + + +class WEICreateView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Create WEI + """ + + model = WEIClub + form_class = WEIForm + extra_context = {"title": _("Create WEI")} + + def get_sample_object(self): + return WEIClub( + name="", + email="weiclub@example.com", + year=0, + date_start=date.today(), + date_end=date.today(), + ) + + @transaction.atomic + def form_valid(self, form): + form.instance.requires_membership = True + form.instance.parent_club = Club.objects.get(name="Kfet") + ret = super().form_valid(form) + NoteClub.objects.create(club=form.instance) + return ret + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk}) + + +class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): + """ + View WEI information + """ + model = WEIClub + context_object_name = "club" + extra_context = {"title": _("WEI Detail")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + club = context["club"] + + club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note)) \ + .filter(PermissionBackend.filter_queryset(self.request, Transaction, "view")) \ + .order_by('-created_at', '-id') + history_table = HistoryTable(club_transactions, prefix="history-") + history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1)) + context['history_list'] = history_table + + club_member = WEIMembership.objects.filter( + club=club, + date_end__gte=date.today(), + ).filter(PermissionBackend.filter_queryset(self.request, WEIMembership, "view")) + membership_table = WEIMembershipTable(data=club_member, prefix="membership-") + membership_table.paginate(per_page=20, page=self.request.GET.get('membership-page', 1)) + context['member_list'] = membership_table + + pre_registrations = WEIRegistration.objects.filter( + PermissionBackend.filter_queryset(self.request, WEIRegistration, "view")).filter( + membership=None, + wei=club + ) + pre_registrations_table = WEIRegistrationTable(data=pre_registrations, prefix="pre-registration-") + pre_registrations_table.paginate(per_page=20, page=self.request.GET.get('pre-registration-page', 1)) + context['pre_registrations'] = pre_registrations_table + + my_registration = WEIRegistration.objects.filter(wei=club, user=self.request.user) + if my_registration.exists(): + my_registration = my_registration.get() + else: + my_registration = None + context["my_registration"] = my_registration + + buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request, Bus, "view")) \ + .filter(wei=self.object).annotate(count=Count("memberships")).order_by("name") + bus_table = BusTable(data=buses, prefix="bus-") + context['buses'] = bus_table + + 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) + + empty_bus = Bus( + wei=club, + name="", + ) + context["can_add_bus"] = PermissionBackend.check_perm(self.request, "wei.add_bus", empty_bus) + + context["not_first_year"] = WEIMembership.objects.filter(user=self.request.user).exists() + + qs = WEIMembership.objects.filter(club=club, registration__first_year=True, bus__isnull=True) + context["can_validate_1a"] = PermissionBackend.check_perm( + self.request, "wei.change_weimembership_bus", qs.first()) if qs.exists() else False + + return context + + +class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): + """ + List all WEI memberships + """ + model = WEIMembership + table_class = WEIMembershipTable + extra_context = {"title": _("View members of the WEI")} + + def dispatch(self, request, *args, **kwargs): + self.club = WEIClub.objects.get(pk=self.kwargs["pk"]) + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self, **kwargs): + qs = super().get_queryset(**kwargs).filter(club=self.club).distinct() + + pattern = self.request.GET.get("search", "") + + if not pattern: + return qs.none() + + qs = qs.filter( + Q(user__first_name__iregex=pattern) + | Q(user__last_name__iregex=pattern) + | Q(user__note__alias__name__iregex="^" + pattern) + | Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern)) + | Q(bus__name__iregex=pattern) + | Q(team__name__iregex=pattern) + ) + + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.club + context["title"] = _("Find WEI Membership") + return context + + +class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): + """ + List all non-validated WEI registrations. + """ + model = WEIRegistration + table_class = WEIRegistrationTable + extra_context = {"title": _("View registrations to the WEI")} + + def dispatch(self, request, *args, **kwargs): + self.club = WEIClub.objects.get(pk=self.kwargs["pk"]) + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self, **kwargs): + qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None).distinct() + + pattern = self.request.GET.get("search", "") + + if pattern: + qs = qs.filter( + Q(user__first_name__iregex=pattern) + | Q(user__last_name__iregex=pattern) + | Q(user__note__alias__name__iregex="^" + pattern) + | Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern)) + ) + + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.club + context["title"] = _("Find WEI Registration") + return context + + +class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): + """ + Update the information of the WEI. + """ + model = WEIClub + context_object_name = "club" + form_class = WEIForm + extra_context = {"title": _("Update the WEI")} + + def dispatch(self, request, *args, **kwargs): + wei = self.get_object() + today = date.today() + # We can't update a past WEI + # But we can update it while it is not officially opened + if today > wei.date_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_success_url(self): + return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk}) + + +class BusCreateView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Create Bus + """ + model = Bus + form_class = BusForm + extra_context = {"title": _("Create new bus")} + + def get_sample_object(self): + wei = WEIClub.objects.get(pk=self.kwargs["pk"]) + return Bus( + wei=wei, + name="", + ) + + def dispatch(self, request, *args, **kwargs): + wei = WEIClub.objects.get(pk=self.kwargs["pk"]) + today = date.today() + # We can't add a bus once the WEI is started + if today >= wei.date_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"]) + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["wei"].initial = WEIClub.objects.get(pk=self.kwargs["pk"]) + return form + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk}) + + +class BusUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): + """ + Update Bus + """ + model = Bus + form_class = BusForm + extra_context = {"title": _("Update bus")} + + def dispatch(self, request, *args, **kwargs): + wei = self.get_object().wei + today = date.today() + # We can't update a bus once the WEI is started + if today >= wei.date_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.wei + context["information"] = CurrentSurvey.get_algorithm_class().get_bus_information(self.object) + self.object.save() + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["wei"].disabled = True + return form + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk}) + + +class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): + """ + Manage Bus + """ + model = Bus + extra_context = {"title": _("Manage bus")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.wei + + bus = self.object + teams = BusTeam.objects.filter(PermissionBackend.filter_queryset(self.request, BusTeam, "view")) \ + .filter(bus=bus).annotate(count=Count("memberships")).order_by("name") + teams_table = BusTeamTable(data=teams, prefix="team-") + context["teams"] = teams_table + + memberships = WEIMembership.objects.filter(PermissionBackend.filter_queryset( + self.request, WEIMembership, "view")).filter(bus=bus) + memberships_table = WEIMembershipTable(data=memberships, prefix="membership-") + memberships_table.paginate(per_page=20, page=self.request.GET.get("membership-page", 1)) + context["memberships"] = memberships_table + + return context + + +class BusTeamCreateView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Create BusTeam + """ + model = BusTeam + form_class = BusTeamForm + extra_context = {"title": _("Create new team")} + + def get_sample_object(self): + bus = Bus.objects.get(pk=self.kwargs["pk"]) + return BusTeam( + name="", + bus=bus, + color=0, + ) + + def dispatch(self, request, *args, **kwargs): + wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"]) + today = date.today() + # We can't add a team once the WEI is started + if today >= wei.date_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + bus = Bus.objects.get(pk=self.kwargs["pk"]) + context["club"] = bus.wei + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["bus"].initial = Bus.objects.get(pk=self.kwargs["pk"]) + return form + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk}) + + +class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): + """ + Update Bus team + """ + model = BusTeam + form_class = BusTeamForm + extra_context = {"title": _("Update team")} + + def dispatch(self, request, *args, **kwargs): + wei = self.get_object().bus.wei + today = date.today() + # We can't update a bus once the WEI is started + if today >= wei.date_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.bus.wei + context["bus"] = self.object.bus + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["bus"].disabled = True + return form + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk}) + + +class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): + """ + Manage Bus team + """ + model = BusTeam + extra_context = {"title": _("Manage WEI team")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["bus"] = self.object.bus + context["club"] = self.object.bus.wei + + memberships = WEIMembership.objects.filter(PermissionBackend.filter_queryset( + self.request, WEIMembership, "view")).filter(team=self.object) + memberships_table = WEIMembershipTable(data=memberships, prefix="membership-") + memberships_table.paginate(per_page=20, page=self.request.GET.get("membership-page", 1)) + context["memberships"] = memberships_table + + return context + + +class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Register a new user to the WEI + """ + model = WEIRegistration + form_class = WEIRegistrationForm + extra_context = {"title": _("Register first year student to the WEI")} + + def get_sample_object(self): + wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + if "myself" in self.request.path: + user = self.request.user + else: + # To avoid unique validation issues, we use an account that can't join the WEI. + # In development mode, the note account may not exist, we use a random user (may fail) + user = User.objects.get(username="note") \ + if User.objects.filter(username="note").exists() else User.objects.first() + return WEIRegistration( + wei=wei, + user=user, + first_year=True, + birth_date="1970-01-01", + gender="No", + emergency_contact_name="No", + emergency_contact_phone="No", + ) + + def dispatch(self, request, *args, **kwargs): + wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + today = date.today() + # We can't register someone once the WEI is started and before the membership start date + if today >= wei.date_start or today < wei.membership_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + # Don't register twice + if 'myself' in self.request.path and not self.request.user.is_anonymous \ + and WEIRegistration.objects.filter(wei=wei, user=self.request.user).exists(): + obj = WEIRegistration.objects.get(wei=wei, user=self.request.user) + return redirect(reverse_lazy('wei:wei_update_registration', args=(obj.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = _("Register 1A") + context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + if "myself" in self.request.path: + context["form"].fields["user"].disabled = True + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["user"].initial = self.request.user + del form.fields["first_year"] + del form.fields["caution_check"] + del form.fields["information_json"] + return form + + @transaction.atomic + def form_valid(self, form): + form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + form.instance.first_year = True + + if not form.instance.pk: + # Check if the user is not already registered to the WEI + if WEIRegistration.objects.filter(wei=form.instance.wei, user=form.instance.user).exists(): + form.add_error('user', _("This user is already registered to this WEI.")) + return self.form_invalid(form) + + # Check if the user can be in her/his first year (yeah, no cheat) + if WEIRegistration.objects.filter(user=form.instance.user).exists(): + form.add_error('user', _("This user can't be in her/his first year since he/she has already" + " participated to a WEI.")) + return self.form_invalid(form) + + if 'treasury' in settings.INSTALLED_APPS: + from treasury.models import SogeCredit + form.instance.soge_credit = \ + form.instance.soge_credit \ + or SogeCredit.objects.filter(user=form.instance.user, credit_transaction__valid=False).exists() + + return super().form_valid(form) + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk}) + + +class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Register an old user to the WEI + """ + model = WEIRegistration + form_class = WEIRegistrationForm + extra_context = {"title": _("Register old student to the WEI")} + + def get_sample_object(self): + wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + if "myself" in self.request.path: + user = self.request.user + else: + # To avoid unique validation issues, we use an account that can't join the WEI. + # In development mode, the note account may not exist, we use a random user (may fail) + user = User.objects.get(username="note") \ + if User.objects.filter(username="note").exists() else User.objects.first() + return WEIRegistration( + wei=wei, + user=user, + first_year=True, + birth_date="1970-01-01", + gender="No", + emergency_contact_name="No", + emergency_contact_phone="No", + ) + + def dispatch(self, request, *args, **kwargs): + wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + today = date.today() + # We can't register someone once the WEI is started and before the membership start date + if today >= wei.date_start or today < wei.membership_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + # Don't register twice + if 'myself' in self.request.path and not self.request.user.is_anonymous \ + and WEIRegistration.objects.filter(wei=wei, user=self.request.user).exists(): + obj = WEIRegistration.objects.get(wei=wei, user=self.request.user) + return redirect(reverse_lazy('wei:wei_update_registration', args=(obj.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = _("Register 2A+") + context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + + if "myself" in self.request.path: + context["form"].fields["user"].disabled = True + + choose_bus_form = WEIChooseBusForm(self.request.POST if self.request.POST else None) + choose_bus_form.fields["bus"].queryset = Bus.objects.filter(wei=context["club"]).order_by('name') + choose_bus_form.fields["team"].queryset = BusTeam.objects.filter(bus__wei=context["club"])\ + .order_by('bus__name', 'name') + context['membership_form'] = choose_bus_form + + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["user"].initial = self.request.user + if "myself" in self.request.path and self.request.user.profile.soge: + form.fields["soge_credit"].disabled = True + form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.") + + del form.fields["caution_check"] + del form.fields["first_year"] + del form.fields["information_json"] + + return form + + @transaction.atomic + def form_valid(self, form): + form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + form.instance.first_year = False + + if not form.instance.pk: + # Check if the user is not already registered to the WEI + if WEIRegistration.objects.filter(wei=form.instance.wei, user=form.instance.user).exists(): + form.add_error('user', _("This user is already registered to this WEI.")) + return self.form_invalid(form) + + choose_bus_form = WEIChooseBusForm(self.request.POST) + if not choose_bus_form.is_valid(): + return self.form_invalid(form) + + information = form.instance.information + information["preferred_bus_pk"] = [bus.pk for bus in choose_bus_form.cleaned_data["bus"]] + information["preferred_bus_name"] = [bus.name for bus in choose_bus_form.cleaned_data["bus"]] + information["preferred_team_pk"] = [team.pk for team in choose_bus_form.cleaned_data["team"]] + information["preferred_team_name"] = [team.name for team in choose_bus_form.cleaned_data["team"]] + information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]] + information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]] + form.instance.information = information + form.instance.save() + + if 'treasury' in settings.INSTALLED_APPS: + from treasury.models import SogeCredit + form.instance.soge_credit = \ + form.instance.soge_credit \ + or SogeCredit.objects.filter(user=form.instance.user, credit_transaction__valid=False).exists() + + return super().form_valid(form) + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk}) + + +class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): + """ + Update a registration for the WEI + """ + model = WEIRegistration + form_class = WEIRegistrationForm + extra_context = {"title": _("Update WEI Registration")} + + def dispatch(self, request, *args, **kwargs): + wei = self.get_object().wei + today = date.today() + # We can't update a registration once the WEI is started and before the membership start date + if today >= wei.date_start or today < wei.membership_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.wei + + if self.object.is_validated: + membership_form = self.get_membership_form(instance=self.object.membership, + data=self.request.POST) + context["membership_form"] = membership_form + elif not self.object.first_year and PermissionBackend.check_perm( + self.request, "wei.change_weiregistration_information_json", self.object): + information = self.object.information + d = dict( + bus=Bus.objects.filter(pk__in=information["preferred_bus_pk"]).all(), + team=BusTeam.objects.filter(pk__in=information["preferred_team_pk"]).all(), + roles=WEIRole.objects.filter(pk__in=information["preferred_roles_pk"]).all(), + ) if 'preferred_bus_pk' in information else dict() + choose_bus_form = WEIChooseBusForm( + self.request.POST if self.request.POST else d + ) + choose_bus_form.fields["bus"].queryset = Bus.objects.filter(wei=context["club"]) + choose_bus_form.fields["team"].queryset = BusTeam.objects.filter(bus__wei=context["club"]) + context["membership_form"] = choose_bus_form + + if not self.object.soge_credit and self.object.user.profile.soge: + form = context["form"] + form.fields["soge_credit"].disabled = True + form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.") + + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["user"].disabled = True + # The auto-json-format may cause issues with the default field remove + if not PermissionBackend.check_perm(self.request, 'wei.change_weiregistration_information_json', self.object): + del form.fields["information_json"] + return form + + def get_membership_form(self, data=None, instance=None): + membership_form = WEIMembershipForm(data if data else None, instance=instance) + del membership_form.fields["credit_type"] + del membership_form.fields["credit_amount"] + del membership_form.fields["first_name"] + del membership_form.fields["last_name"] + del membership_form.fields["bank"] + for field_name, _field in list(membership_form.fields.items()): + if not PermissionBackend.check_perm( + self.request, "wei.change_weimembership_" + field_name, self.object.membership): + del membership_form.fields[field_name] + return membership_form + + @transaction.atomic + def form_valid(self, form): + # If the membership is already validated, then we update the bus and the team (and the roles) + if form.instance.is_validated: + membership_form = self.get_membership_form(self.request.POST, form.instance.membership) + if not membership_form.is_valid(): + return self.form_invalid(form) + membership_form.save() + # If it is not validated and if this is an old member, then we update the choices + elif not form.instance.first_year and PermissionBackend.check_perm( + self.request, "wei.change_weiregistration_information_json", self.object): + choose_bus_form = WEIChooseBusForm(self.request.POST) + if not choose_bus_form.is_valid(): + return self.form_invalid(form) + information = form.instance.information + information["preferred_bus_pk"] = [bus.pk for bus in choose_bus_form.cleaned_data["bus"]] + information["preferred_bus_name"] = [bus.name for bus in choose_bus_form.cleaned_data["bus"]] + information["preferred_team_pk"] = [team.pk for team in choose_bus_form.cleaned_data["team"]] + information["preferred_team_name"] = [team.name for team in choose_bus_form.cleaned_data["team"]] + information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]] + information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]] + form.instance.information = information + form.instance.save() + + return super().form_valid(form) + + def get_success_url(self): + self.object.refresh_from_db() + if self.object.first_year: + survey = CurrentSurvey(self.object) + if not survey.is_complete(): + return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk}) + if PermissionBackend.check_perm(self.request, "wei.add_weimembership", WEIMembership( + club=self.object.wei, + user=self.object.user, + date_start=date.today(), + date_end=date.today(), + fee=0, + registration=self.object, + )): + return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk}) + return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk}) + + +class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView): + """ + Delete a non-validated WEI registration + """ + model = WEIRegistration + extra_context = {"title": _("Delete WEI registration")} + + def dispatch(self, request, *args, **kwargs): + object = self.get_object() + wei = object.wei + today = date.today() + # We can't delete a registration of a past WEI + if today > wei.membership_end: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + + if not PermissionBackend.check_perm(self.request, "wei.delete_weiregistration", object): + raise PermissionDenied(_("You don't have the right to delete this WEI registration.")) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.wei + return context + + def get_success_url(self): + return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,)) + + +class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView): + """ + Validate WEI Registration + """ + model = WEIMembership + extra_context = {"title": _("Validate WEI registration")} + + def get_sample_object(self): + registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) + return WEIMembership( + club=registration.wei, + user=registration.user, + date_start=date.today(), + date_end=date.today() + timedelta(days=1), + fee=0, + registration=registration, + ) + + def dispatch(self, request, *args, **kwargs): + wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei + today = date.today() + # We can't validate anyone once the WEI is started and before the membership start date + if today >= wei.date_start or today < wei.membership_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) + context["registration"] = registration + survey = CurrentSurvey(registration) + if survey.information.valid: + context["suggested_bus"] = survey.information.get_selected_bus() + context["club"] = registration.wei + + kfet = registration.wei.parent_club + bde = kfet.parent_club + + context["kfet_member"] = Membership.objects.filter( + club__name=kfet.name, + user=registration.user, + date_start__gte=kfet.membership_start, + ).exists() + context["bde_member"] = Membership.objects.filter( + club__name=bde.name, + user=registration.user, + date_start__gte=bde.membership_start, + ).exists() + + context["fee"] = registration.fee + + form = context["form"] + if registration.soge_credit: + form.fields["credit_amount"].initial = registration.fee + else: + form.fields["credit_amount"].initial = max(0, registration.fee - registration.user.note.balance) + + return context + + def get_form_class(self): + registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) + if registration.first_year and 'sleected_bus_pk' not in registration.information: + return WEIMembership1AForm + return WEIMembershipForm + + def get_form(self, form_class=None): + form = super().get_form(form_class) + registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) + form.fields["last_name"].initial = registration.user.last_name + form.fields["first_name"].initial = registration.user.first_name + + if registration.soge_credit: + form.fields["credit_type"].disabled = True + form.fields["credit_type"].initial = NoteSpecial.objects.get(special_type="Virement bancaire") + form.fields["credit_amount"].disabled = True + form.fields["last_name"].disabled = True + form.fields["first_name"].disabled = True + form.fields["bank"].disabled = True + form.fields["bank"].initial = "Société générale" + + if 'bus' in form.fields: + # For 2A+ and hardcoded 1A + form.fields["bus"].widget.attrs["api_url"] = "/api/wei/bus/?wei=" + str(registration.wei.pk) + if registration.first_year: + # Use the results of the survey to fill initial data + # A first year has no other role than "1A" + del form.fields["roles"] + survey = CurrentSurvey(registration) + if survey.information.valid: + form.fields["bus"].initial = survey.information.get_selected_bus() + else: + # Use the choice of the member to fill initial data + information = registration.information + if "preferred_bus_pk" in information and len(information["preferred_bus_pk"]) == 1: + form["bus"].initial = Bus.objects.get(pk=information["preferred_bus_pk"][0]) + if "preferred_team_pk" in information and len(information["preferred_team_pk"]) == 1: + form["team"].initial = BusTeam.objects.get(pk=information["preferred_team_pk"][0]) + if "preferred_roles_pk" in information: + form["roles"].initial = WEIRole.objects.filter( + Q(pk__in=information["preferred_roles_pk"]) | Q(name="Adhérent WEI") + ).all() + return form + + @transaction.atomic + def form_valid(self, form): + """ + Create membership, check that all is good, make transactions + """ + registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) + club = registration.wei + user = registration.user + + membership = form.instance + membership.user = user + membership.club = club + membership.date_start = min(date.today(), club.date_start) + membership.registration = registration + # Force the membership of the clubs BDE and Kfet + membership._force_renew_parent = True + + fee = club.membership_fee_paid if user.profile.paid else club.membership_fee_unpaid + + kfet = club.parent_club + bde = kfet.parent_club + + kfet_member = Membership.objects.filter( + club__name=kfet.name, + user=registration.user, + date_start__gte=kfet.membership_start, + ).exists() + bde_member = Membership.objects.filter( + club__name=bde.name, + user=registration.user, + date_start__gte=bde.membership_start, + ).exists() + + if not kfet_member: + fee += kfet.membership_fee_paid if registration.user.profile.paid else kfet.membership_fee_unpaid + if not bde_member: + fee += bde.membership_fee_paid if registration.user.profile.paid else bde.membership_fee_unpaid + + credit_type = form.cleaned_data["credit_type"] + credit_amount = form.cleaned_data["credit_amount"] + last_name = form.cleaned_data["last_name"] + first_name = form.cleaned_data["first_name"] + bank = form.cleaned_data["bank"] + + if credit_type is None or registration.soge_credit: + credit_amount = 0 + + 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', + _("This user don't have enough money to join this club, and can't have a negative balance.")) + return super().form_invalid(form) + + if credit_amount: + if not last_name: + form.add_error('last_name', _("This field is required.")) + return super().form_invalid(form) + + if not first_name: + form.add_error('first_name', _("This field is required.")) + return super().form_invalid(form) + + # Credit note before adding the membership + SpecialTransaction.objects.create( + source=credit_type, + destination=registration.user.note, + amount=credit_amount, + reason="Crédit " + str(credit_type) + " (WEI)", + last_name=last_name, + first_name=first_name, + bank=bank, + ) + + # Now, all is fine, the membership can be created. + + if registration.soge_credit: + form.instance._soge = True + + if registration.first_year: + membership = form.instance + # If the user is not a member of the club Kfet, then the membership is created. + membership.save() + membership.refresh_from_db() + membership.roles.set(WEIRole.objects.filter(name="1A").all()) + membership.save() + + membership.save() + membership.refresh_from_db() + membership.roles.add(WEIRole.objects.get(name="Adhérent WEI")) + + return super().form_valid(form) + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.club.pk}) + + +class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView): + """ + Display the survey for the WEI for first year members. + Warning: this page is accessible for anyone that is connected, the view doesn't extend ProtectQuerySetMixin. + """ + model = WEIRegistration + template_name = "wei/survey.html" + survey = None + extra_context = {"title": _("Survey WEI")} + + def dispatch(self, request, *args, **kwargs): + obj = self.get_object() + self.object = obj + + wei = obj.wei + today = date.today() + # We can't access to the WEI survey once the WEI is started and before the membership start date + if today >= wei.date_start or today < wei.membership_start: + return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,))) + + if not self.survey: + self.survey = CurrentSurvey(obj) + # If the survey is complete, then display the end page. + if self.survey.is_complete(): + return redirect(reverse_lazy('wei:wei_survey_end', args=(self.survey.registration.pk,))) + # Non first year members don't have a survey + if not obj.first_year: + return redirect(reverse_lazy('wei:wei_survey_end', args=(self.survey.registration.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_form_class(self): + """ + Get the survey form. It may depend on the current state of the survey. + """ + return self.survey.get_form_class() + + def get_form(self, form_class=None): + """ + Update the form with the data of the survey. + """ + form = super().get_form(form_class) + self.survey.update_form(form) + return form + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = self.object.wei + return context + + @transaction.atomic + def form_valid(self, form): + """ + Update the survey with the data of the form. + """ + self.survey.form_valid(form) + return super().form_valid(form) + + def get_success_url(self): + return reverse_lazy('wei:wei_survey', args=(self.get_object().pk,)) + + +class WEISurveyEndView(LoginRequiredMixin, TemplateView): + template_name = "wei/survey_end.html" + extra_context = {"title": _("Survey WEI")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei + return context + + +class WEIClosedView(LoginRequiredMixin, TemplateView): + template_name = "wei/survey_closed.html" + extra_context = {"title": _("Survey WEI")} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"]) + return context + + +class MemberListRenderView(LoginRequiredMixin, View): + """ + Render Invoice as a generated PDF with the given information and a LaTeX template + """ + + def get_queryset(self, **kwargs): + qs = WEIMembership.objects.filter(PermissionBackend.filter_queryset(self.request, WEIMembership, "view")) + qs = qs.filter(club__pk=self.kwargs["wei_pk"]).order_by( + Lower('bus__name'), + Lower('team__name'), + 'user__profile__promotion', + Lower('user__last_name'), + Lower('user__first_name'), + 'id', + ) + + if "bus_pk" in self.kwargs: + qs = qs.filter(bus__pk=self.kwargs["bus_pk"]) + + if "team_pk" in self.kwargs: + qs = qs.filter(team__pk=self.kwargs["team_pk"] if self.kwargs["team_pk"] else None) + + return qs.distinct() + + def get(self, request, **kwargs): + qs = self.get_queryset() + + wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + bus = team = None + if "bus_pk" in self.kwargs: + bus = Bus.objects.get(pk=self.kwargs["bus_pk"]) + if "team_pk" in self.kwargs: + team = BusTeam.objects.filter(pk=self.kwargs["team_pk"] if self.kwargs["team_pk"] else None) + if team.exists(): + team = team.get() + bus = team.bus + else: + team = dict(name="Staff") + + # Fill the template with the information + tex = render_to_string("wei/weilist_sample.tex", dict(memberships=qs.all(), wei=wei, bus=bus, team=team)) + + try: + os.mkdir(BASE_DIR + "/tmp") + except FileExistsError: + pass + # We render the file in a temporary directory + tmp_dir = mkdtemp(prefix=BASE_DIR + "/tmp/") + + try: + with open("{}/wei-list.tex".format(tmp_dir), "wb") as f: + f.write(tex.encode("UTF-8")) + del tex + + with open(os.devnull, "wb") as devnull: + error = subprocess.Popen( + ["/usr/bin/xelatex", "-interaction=nonstopmode", "{}/wei-list.tex".format(tmp_dir)], + cwd=tmp_dir, + stderr=devnull, + stdout=devnull, + ).wait() + + if error: + with open("{}/wei-list.log".format(tmp_dir), "r") as f: + log = f.read() + raise IOError("An error attempted while generating a WEI list (code=" + str(error) + ")\n\n" + log) + + # Display the generated pdf as a HTTP Response + with open("{}/wei-list.pdf".format(tmp_dir), 'rb') as f: + pdf = f.read() + response = HttpResponse(pdf, content_type="application/pdf") + response['Content-Disposition'] = "inline;filename=Liste%20des%20participants%20au%20WEI.pdf" + except IOError as e: + raise e + finally: + # Delete all temporary files + shutil.rmtree(tmp_dir) + + return response + + +class WEI1AListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableView): + model = WEIRegistration + template_name = "wei/1A_list.html" + table_class = WEIRegistration1ATable + extra_context = {"title": _("Attribute buses to first year members")} + + def dispatch(self, request, *args, **kwargs): + self.club = WEIClub.objects.get(pk=self.kwargs["pk"]) + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self, filter_permissions=True, **kwargs): + qs = super().get_queryset(filter_permissions, **kwargs) + qs = qs.filter(first_year=True, membership__isnull=False) + qs = qs.order_by('-membership__bus') + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['club'] = self.club + context['bus_repartition_table'] = BusRepartitionTable( + Bus.objects.filter(wei=self.club, size__gt=0) + .filter(PermissionBackend.filter_queryset(self.request, Bus, "view")) + .all()) + return context + + +class WEIAttributeBus1AView(ProtectQuerysetMixin, DetailView): + model = WEIRegistration + template_name = "wei/attribute_bus_1A.html" + extra_context = {"title": _("Attribute bus")} + + def get_queryset(self, filter_permissions=True, **kwargs): + qs = super().get_queryset(filter_permissions, **kwargs) + qs = qs.filter(first_year=True) + return qs + + def dispatch(self, request, *args, **kwargs): + obj = self.get_object() + if 'selected_bus_pk' not in obj.information: + return redirect(reverse_lazy('wei:wei_survey', args=(obj.pk,))) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['club'] = self.object.wei + context['survey'] = CurrentSurvey(self.object) + return context + + +class WEIAttributeBus1ANextView(LoginRequiredMixin, RedirectView): + def get_redirect_url(self, *args, **kwargs): + wei = WEIClub.objects.filter(pk=self.kwargs['pk']) + if not wei.exists(): + raise Http404 + wei = wei.get() + qs = WEIRegistration.objects.filter(wei=wei, membership__isnull=False, membership__bus__isnull=True) + qs = qs.filter(information_json__contains='selected_bus_pk') # not perfect, but works... + if qs.exists(): + return reverse_lazy('wei:wei_bus_1A', args=(qs.first().pk, )) + return reverse_lazy('wei:wei_1A_list', args=(wei.pk, )) diff --git a/docs/api/wei.rst b/docs/api/wei.rst new file mode 100644 index 0000000..8c92c02 --- /dev/null +++ b/docs/api/wei.rst @@ -0,0 +1,710 @@ +API WEI +======= + +Wei +--- + +**Chemin :** `/api/wei/club/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Wei Club List", + "description": "REST API View set.\nThe djangorestframework plugin will get all `WEIClub` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/club/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "name": { + "type": "string", + "required": true, + "read_only": false, + "label": "Nom", + "max_length": 255 + }, + "email": { + "type": "email", + "required": true, + "read_only": false, + "label": "Courriel", + "max_length": 254 + }, + "require_memberships": { + "type": "boolean", + "required": false, + "read_only": false, + "label": "N\u00e9cessite des adh\u00e9sions", + "help_text": "D\u00e9cochez si ce club n'utilise pas d'adh\u00e9sions." + }, + "membership_fee_paid": { + "type": "integer", + "required": false, + "read_only": false, + "label": "Cotisation pour adh\u00e9rer (normalien \u00e9l\u00e8ve)", + "min_value": 0, + "max_value": 2147483647 + }, + "membership_fee_unpaid": { + "type": "integer", + "required": false, + "read_only": false, + "label": "Cotisation pour adh\u00e9rer (normalien \u00e9tudiant)", + "min_value": 0, + "max_value": 2147483647 + }, + "membership_duration": { + "type": "integer", + "required": false, + "read_only": false, + "label": "Dur\u00e9e de l'adh\u00e9sion", + "help_text": "La dur\u00e9e maximale (en jours) d'une adh\u00e9sion (NULL = infinie).", + "min_value": 0, + "max_value": 2147483647 + }, + "membership_start": { + "type": "date", + "required": false, + "read_only": false, + "label": "D\u00e9but de l'adh\u00e9sion", + "help_text": "Date \u00e0 partir de laquelle les adh\u00e9rents peuvent renouveler leur adh\u00e9sion." + }, + "membership_end": { + "type": "date", + "required": false, + "read_only": false, + "label": "Fin de l'adh\u00e9sion", + "help_text": "Date maximale d'une fin d'adh\u00e9sion, apr\u00e8s laquelle les adh\u00e9rents doivent la renouveler." + }, + "year": { + "type": "integer", + "required": false, + "read_only": false, + "label": "Ann\u00e9e", + "min_value": 0, + "max_value": 2147483647 + }, + "date_start": { + "type": "date", + "required": true, + "read_only": false, + "label": "D\u00e9but" + }, + "date_end": { + "type": "date", + "required": true, + "read_only": false, + "label": "Fin" + }, + "parent_club": { + "type": "field", + "required": false, + "read_only": false, + "label": "Club parent" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``name`` +* ``year`` +* ``date_start`` +* ``date_end`` +* ``email`` +* ``note__alias__name`` +* ``note__alias__normalized_name`` +* ``parent_club`` +* ``parent_club__name`` +* ``require_memberships`` +* ``membership_fee_paid`` +* ``membership_fee_unpaid`` +* ``membership_duration`` +* ``membership_start`` +* ``membership_end`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``name`` (expression régulière) +* ``email`` (expression régulière) +* ``note__alias__name`` (expression régulière) +* ``note__alias__normalized_name`` (expression régulière) + +Bus +--- + +**Chemin :** `/api/wei/bus/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Bus List", + "description": "REST API View set.\nThe djangorestframework plugin will get all `Bus` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/bus/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "name": { + "type": "string", + "required": true, + "read_only": false, + "label": "Nom", + "max_length": 255 + }, + "description": { + "type": "string", + "required": false, + "read_only": false, + "label": "Description" + }, + "information_json": { + "type": "string", + "required": false, + "read_only": false, + "label": "Informations sur le questionnaire", + "help_text": "Informations sur le sondage pour les nouveaux membres, encod\u00e9es en JSON" + }, + "wei": { + "type": "field", + "required": true, + "read_only": false, + "label": "WEI" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``name`` +* ``wei`` +* ``description`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``name`` (expression régulière) +* ``wei__name`` (expression régulière) +* ``description`` (expression régulière) + +Équipe de bus +------------- + +**Chemin :** `/api/wei/team/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Bus Team List", + "description": "REST API View set.\nThe djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/team/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "name": { + "type": "string", + "required": true, + "read_only": false, + "label": "Nom", + "max_length": 255 + }, + "color": { + "type": "integer", + "required": true, + "read_only": false, + "label": "Couleur", + "help_text": "La couleur du T-Shirt, stock\u00e9 sous la forme de son \u00e9quivalent num\u00e9rique", + "min_value": 0, + "max_value": 2147483647 + }, + "description": { + "type": "string", + "required": false, + "read_only": false, + "label": "Description" + }, + "bus": { + "type": "field", + "required": true, + "read_only": false, + "label": "Bus" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``name`` +* ``bus`` +* ``color`` +* ``description`` +* ``bus__wei`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``name`` (expression régulière) +* ``bus__name`` (expression régulière) +* ``bus__wei__name`` (expression régulière) +* ``description`` (expression régulière) + +Rôle au wei +----------- + +**Chemin :** `/api/wei/role/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Wei Role List", + "description": "REST API View set.\nThe djangorestframework plugin will get all `WEIRole` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/role/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "name": { + "type": "string", + "required": true, + "read_only": false, + "label": "Nom", + "max_length": 255 + }, + "for_club": { + "type": "field", + "required": false, + "read_only": false, + "label": "S'applique au club" + }, + "permissions": { + "type": "field", + "required": true, + "read_only": false, + "label": "Permissions" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``name`` +* ``permissions`` +* ``memberships`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``name`` (expression régulière) + +Participant au wei +------------------ + +**Chemin :** `/api/wei/registration/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Wei Registration List", + "description": "REST API View set.\nThe djangorestframework plugin will get all WEIRegistration objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/registration/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "soge_credit": { + "type": "boolean", + "required": false, + "read_only": false, + "label": "Cr\u00e9dit de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale" + }, + "caution_check": { + "type": "boolean", + "required": false, + "read_only": false, + "label": "Ch\u00e8que de caution donn\u00e9" + }, + "birth_date": { + "type": "date", + "required": true, + "read_only": false, + "label": "Date de naissance" + }, + "gender": { + "type": "choice", + "required": true, + "read_only": false, + "label": "Genre", + "choices": [ + { + "value": "male", + "display_name": "Homme" + }, + { + "value": "female", + "display_name": "Femme" + }, + { + "value": "nonbinary", + "display_name": "Non-binaire" + } + ] + }, + "clothing_cut": { + "type": "choice", + "required": true, + "read_only": false, + "label": "Coupe de v\u00eatement", + "choices": [ + { + "value": "male", + "display_name": "Homme" + }, + { + "value": "female", + "display_name": "Femme" + } + ] + }, + "clothing_size": { + "type": "choice", + "required": true, + "read_only": false, + "label": "Taille de v\u00eatement", + "choices": [ + { + "value": "XS", + "display_name": "XS" + }, + { + "value": "S", + "display_name": "S" + }, + { + "value": "M", + "display_name": "M" + }, + { + "value": "L", + "display_name": "L" + }, + { + "value": "XL", + "display_name": "XL" + }, + { + "value": "XXL", + "display_name": "XXL" + } + ] + }, + "health_issues": { + "type": "string", + "required": false, + "read_only": false, + "label": "Probl\u00e8mes de sant\u00e9" + }, + "emergency_contact_name": { + "type": "string", + "required": true, + "read_only": false, + "label": "Nom du contact en cas d'urgence", + "max_length": 255 + }, + "emergency_contact_phone": { + "type": "string", + "required": true, + "read_only": false, + "label": "T\u00e9l\u00e9phone du contact en cas d'urgence", + "max_length": 32 + }, + "first_year": { + "type": "boolean", + "required": false, + "read_only": false, + "label": "Premi\u00e8re ann\u00e9e", + "help_text": "Indique si l'utilisateur est nouveau dans l'\u00e9cole." + }, + "information_json": { + "type": "string", + "required": false, + "read_only": false, + "label": "Informations sur l'inscription", + "help_text": "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les 1A), encod\u00e9es en JSON" + }, + "user": { + "type": "field", + "required": true, + "read_only": false, + "label": "Utilisateur" + }, + "wei": { + "type": "field", + "required": true, + "read_only": false, + "label": "WEI" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``user`` +* ``user__username`` +* ``user__first_name`` +* ``user__last_name`` +* ``user__email`` +* ``user__note__alias__name`` +* ``user__note__alias__normalized_name`` +* ``wei`` +* ``wei__name`` +* ``wei__email`` +* ``wei__year`` +* ``soge_credit`` +* ``caution_check`` +* ``birth_date`` +* ``gender`` +* ``clothing_cut`` +* ``clothing_size`` +* ``first_year`` +* ``emergency_contact_name`` +* ``emergency_contact_phone`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``user__username`` (expression régulière) +* ``user__first_name`` (expression régulière) +* ``user__last_name`` (expression régulière) +* ``user__email`` (expression régulière) +* ``user__note__alias__name`` (expression régulière) +* ``user__note__alias__normalized_name`` (expression régulière) +* ``wei__name`` (expression régulière) +* ``wei__email`` (expression régulière) +* ``health_issues`` (expression régulière) +* ``emergency_contact_name`` (expression régulière) +* ``emergency_contact_phone`` (expression régulière) + +Adhésion au wei +--------------- + +**Chemin :** `/api/wei/membership/ `_ + +Options +~~~~~~~ + +.. code:: json + + { + "name": "Wei Membership List", + "description": "REST API View set.\nThe djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,\nthen render it on /api/wei/membership/", + "renders": [ + "application/json", + "text/html" + ], + "parses": [ + "application/json", + "application/x-www-form-urlencoded", + "multipart/form-data" + ], + "actions": { + "POST": { + "id": { + "type": "integer", + "required": false, + "read_only": true, + "label": "ID" + }, + "date_start": { + "type": "date", + "required": false, + "read_only": false, + "label": "L'adh\u00e9sion commence le" + }, + "date_end": { + "type": "date", + "required": false, + "read_only": false, + "label": "L'adh\u00e9sion finit le" + }, + "fee": { + "type": "integer", + "required": true, + "read_only": false, + "label": "Cotisation", + "min_value": 0, + "max_value": 2147483647 + }, + "user": { + "type": "field", + "required": true, + "read_only": false, + "label": "Utilisateur" + }, + "club": { + "type": "field", + "required": true, + "read_only": false, + "label": "Club" + }, + "bus": { + "type": "field", + "required": false, + "read_only": false, + "label": "Bus" + }, + "team": { + "type": "field", + "required": false, + "read_only": false, + "label": "\u00c9quipe" + }, + "registration": { + "type": "field", + "required": false, + "read_only": false, + "label": "Inscription au WEI" + }, + "roles": { + "type": "field", + "required": true, + "read_only": false, + "label": "R\u00f4les" + } + } + } + } + +Filtres Django +~~~~~~~~~~~~~~ + +* ``club__name`` +* ``club__email`` +* ``club__note__alias__name`` +* ``club__note__alias__normalized_name`` +* ``user__username`` +* ``user__last_name`` +* ``user__first_name`` +* ``user__email`` +* ``user__note__alias__name`` +* ``user__note__alias__normalized_name`` +* ``date_start`` +* ``date_end`` +* ``fee`` +* ``roles`` +* ``bus`` +* ``bus__name`` +* ``team`` +* ``team__name`` +* ``registration`` + +Tris possible +~~~~~~~~~~~~~ + +* ``id`` +* ``date_start`` +* ``date_end`` + +Filtres de recherche +~~~~~~~~~~~~~~~~~~~~ + +* ``club__name`` (expression régulière) +* ``club__email`` (expression régulière) +* ``club__note__alias__name`` (expression régulière) +* ``club__note__alias__normalized_name`` (expression régulière) +* ``user__username`` (expression régulière) +* ``user__last_name`` (expression régulière) +* ``user__first_name`` (expression régulière) +* ``user__email`` (expression régulière) +* ``user__note__alias__name`` (expression régulière) +* ``user__note__alias__normalized_name`` (expression régulière) +* ``roles__name`` (expression régulière) +* ``bus__name`` (expression régulière) +* ``team__name`` (expression régulière) + diff --git a/docs/apps/registration.rst b/docs/apps/registration.rst index 75a70a8..c594734 100644 --- a/docs/apps/registration.rst +++ b/docs/apps/registration.rst @@ -45,7 +45,7 @@ Une fois l'inscription validée, détail de ce qu'il se passe : `Trésorerie `_ section crédits de la société générale). Nécessairement, le club Kfet doit être rejoint. * Sinon, on crédite la note du montant demandé par le nouveau membre (avec comme description "Crédit TYPE (Inscription)" où TYPE est le type de crédit), après avoir vérifié que le crédit est suffisant (on n'ouvre pas une note négative) -* On adhère la personne au BDE, l'adhésion commence aujourd'hui. Il dispose d'un unique rôle : "Adhérent", +* On adhère la personne au BDE, l'adhésion commence aujourd'hui. Il dispose d'un unique rôle : "Adhérent BDE", lui octroyant un faible nombre de permissions de base, telles que la visualisation de son compte. * On adhère la personne au club Kfet si cela est demandé, l'adhésion commence aujourd'hui. Il dispose d'un unique rôle : "Adhérent Kfet", lui octroyant un nombre un peu plus conséquent de permissions basiques, telles que la possibilité de diff --git a/docs/apps/wei.rst b/docs/apps/wei.rst new file mode 100644 index 0000000..51d3375 --- /dev/null +++ b/docs/apps/wei.rst @@ -0,0 +1,333 @@ +WEI +=== + +Cette application gère toute la phase d'inscription au WEI. + +Modèles +------- + +WEIClub +~~~~~~~ + +Le modèle ``WEIClub`` hérite de ``Club`` et contient toutes les informations d'un WEI. + +* ``year`` : ``PositiveIntegerField`` unique, année du WEI. +* ``date_start`` : ``DateField``, date de début du WEI. +* ``date_end`` : ``DateField``, date de fin du WEI. + +Champs hérités de ``Club`` de l'application ``member`` : + +* ``parent_club`` : ``ForeignKey(Club)``. Ce champ vaut toujours ``Kfet`` dans le cas d'un WEI : on doit être membre du + club Kfet pour participer au WEI. +* ``email`` : ``EmailField``, adresse e-mail sur laquelle contacter les gérants du WEI. +* ``membership_start`` : ``DateField``, date à partir de laquelle il est possible de s'inscrire au WEI. +* ``membership_end`` : ``DateField``, date de fin d'adhésion possible au WEI. +* ``membership_duration`` : ``PositiveIntegerField``, inutilisé dans le cas d'un WEI, vaut ``None``. +* ``membership_fee_paid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un élève normalien + (donc rémunéré) puisse adhérer. +* ``membership_fee_unpaid`` : ``PositiveIntegerField``, montant de la cotisation (en centimes) pour qu'un étudiant + normalien (donc non rémunéré) puisse adhérer. +* ``name`` : ``CharField``, nom du WEI. +* ``require_memberships`` : ``BooleanField``, vaut toujours ``True`` pour le WEI. + +Bus +~~~ + +Contient les informations sur un bus allant au WEI. + +* ``wei`` : ``ForeignKey(WEIClub)``, WEI auquel ce bus est rattaché. +* ``name`` : ``CharField``, nom du bus. Le champ est unique pour le WEI attaché. +* ``description`` : ``TextField``, description textuelle de l'ambiance du bus. +* ``information_json`` : ``TextField``, diverses informations non publiques qui permettent d'indiquer divers paramètres + pouvant varier selon les années permettant l'attribution des bus aux 1A. + +Il est souhaitable de créer chaque année un bus "Staff" (non accessible aux 1A bien évidemment) pour les GC WEI qui ne +monteraient pas dans un bus. + +BusTeam +~~~~~~~ + +Contient les informations d'une équipe WEI. + +* ``wei`` : ``ForeignKey(WEIClub)``, WEI auquel cette équipe est rattachée. +* ``name`` : ``CharField``, nom de l'équipe. +* ``color`` : ``PositiveIntegerField``, entier entre 0 et 16777215 = 0xFFFFFF représentant la couleur du T-Shirt. + La donnée se rentre en hexadécimal via un sélecteur de couleur. Cette information est purement cosmétique et n'est + utilisée nulle part. +* ``description`` : ``TextField``, description de l'équipe. + +WEIRole +~~~~~~~ + +Ce modèle hérité de ``Role``, ne contient qu'un champ ``name`` (``CharField``), le nom du rôle. Ce modèle ne permet +que de dissocier les rôles propres au WEI des rôles s'appliquant pour n'importe quel club. + +WEIRegistration +~~~~~~~~~~~~~~~ + +Inscription au WEI, contenant les informations avant validation. Ce modèle est créé dès lors que quelqu'un se pré-inscrit au WEI. + +* ``user`` : ``ForeignKey(User)``, utilisateur qui s'est pré-inscrit. Ce champ est unique avec ``wei``. +* ``wei`` : ``ForeignKey(WEIClub)``, le WEI auquel l'utilisateur s'est pré-inscrit. Ce champ est unique avec ``user``. +* ``soge_credit`` : ``BooleanField``, indique si l'utilisateur a déclaré vouloir ouvrir un compte à la Société générale. +* ``caution_check`` : ``BooleanField``, indique si l'utilisateur (en 2ème année ou plus) a bien remis son chèque de + caution auprès de la trésorerie. +* ``birth_date`` : ``DateField``, date de naissance de l'utilisateur. +* ``gender`` : ``CharField`` parmi ``male`` (Homme), ``female`` (Femme), ``non binary`` (Non binaire), genre de la personne. +* ``health_issues`` : ``TextField``, problèmes de santé déclarés par l'utilisateur. +* ``emergency_contact_name`` : ``CharField``, nom du contact en cas d'urgence. +* ``emergency_contact_phone`` : ``CharField``, numéro de téléphone du contact en cas d'urgence. +* ``ml_events_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des + événements du BDE (1A uniquement) +* ``ml_art_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des + actualités du BDA (1A uniquement) +* ``ml_sport_registration`` : ``BooleanField``, déclare si l'utilisateur veut s'inscrire à la liste de diffusion des + actualités du BDS (1A uniquement) +* ``first_year`` : ``BooleanField``, indique si l'inscription est d'un 1A ou non. Non modifiable par n'importe qui. +* ``information_json`` : ``TextField`` non modifiable manuellement par n'importe qui stockant les informations du + questionnaire d'inscription au WEI pour les 1A, et stocke les demandes faites par un 2A+ concerant bus, équipes et rôles. + On utilise un ``TextField`` contenant des données au format JSON pour permettre de la modularité au fil des années, + sans avoir à tout casser à chaque fois. + +WEIMembership +~~~~~~~~~~~~~ + +Ce modèle hérite de ``Membership`` et contient les informations d'une adhésion au WEI. + +* ``bus`` : ``ForeignKey(Bus)``, bus dans lequel se trouve l'utilisateur. +* ``team`` : ``ForeignKey(BusTeam)`` pouvant être nulle (pour les chefs de bus et électrons libres), équipe dans laquelle + se trouve l'utilisateur. +* ``registration`` : ``OneToOneField(WEIRegistration)``, informations de la pré-inscription. + +Champs hérités du modèle ``Membership`` : + +* ``club`` : ``ForeignKey(Club)``, club lié à l'adhésion. Doit être un ``WEIClub``. +* ``user`` : ``ForeignKey(User)``, utilisateur adhéré. +* ``date_start`` : ``DateField``, date de début d'adhésion. +* ``date_end`` : ``DateField``, date de fin d'adhésion. +* ``fee`` : ``PositiveIntegerField``, montant de la cotisation payée. +* ``roles`` : ``ManyToManyField(Role)``, liste des rôles endossés par l'adhérent. Les rôles doivent être des ``WEIRole``. + +Graphe des modèles +~~~~~~~~~~~~~~~~~~ + +Pour une meilleure compréhension, le graphe des modèles de l'application ``member`` ont été ajoutés au schéma. + +.. image:: ../_static/img/graphs/wei.svg + :width: 960 + :alt: Graphe des modèles de l'application WEI + +Fonctionnement +-------------- + +Création d'un WEI +~~~~~~~~~~~~~~~~~ + +Seul un respo info peut créer un WEI. Pour cela, se rendre dans l'onglet WEI, puis "Liste des WEI" et enfin +"Créer un WEI". Diverses informations sont demandées, comme le nom du WEI, l'adresse mail de contact, l'année du WEI +(doit être unique), les dates de début et de fin, et les dates pendant lesquelles les utilisateurs peuvent s'inscrire. + +Don des droits à un GC WEI +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Le GC WEI peut gérer tout ce qui a un rapport avec le WEI. Il ne peut cependant pas créer le WEI, ce privilège est +réservé au respo info. Pour avoir ses droits, le GC WEI doit s'inscrire au WEI avec le rôle GC WEI, et donc payer +en premier sa cotisation. C'est donc au respo info de créer l'adhésion du GC WEI. Voir ci-dessous pour l'inscription au WEI. + +S'inscrire au WEI +~~~~~~~~~~~~~~~~~ + +N'importe quel utilisateur peut s'auto-inscrire au WEI, lorsque les dates d'adhésion le permettent. Ceux qui se sont +déjà inscrits peuvent également inscrire un 1A. Seuls les GC WEI et les respo info peuvent inscrire un autre 2A+. + +À tout moment, tant que le WEI n'est pas passé, l'inscription peut être modifiée, même après validation. + +Inscription d'un 2A+ +^^^^^^^^^^^^^^^^^^^^ + +Comme indiqué, les 2A+ sont assez autonomes dans leur inscription au WEI. Ils remplissent le questionnaire et sont +ensuite pré-inscrits. Le questionnaire se compose de plusieurs champs (voir WEIRegistration) : + +* Est-ce que l'utilisateur a déclaré avoir ouvert un compte à la Société générale ? (Option disponible uniquemement + si cela n'a pas été fait une année avant) +* Date de naissance +* Genre (Homme/Femme/Non-binaire) +* Problèmes de santé +* Nom du contact en cas d'urgence +* Numéro du contact en cas d'urgence +* Bus préférés (choix multiple, utile pour les électrons libres) +* Équipes préférées (choix multiple éventuellement vide, vide pour les chefs de bus/staff) +* Rôles souhaités + +Les trois derniers champs n'ont aucun caractère définitif et sont simplement là en suggestion pour le GC WEI qui +validera l'inscription. C'est utile si on hésite entre plusieurs bus. + +L'inscription est ensuite créée, le GC WEI devra ensuite la valider (voir plus bas). + +Inscription d'un 1A +^^^^^^^^^^^^^^^^^^^ + +N'importe quelle personne déjà inscrite au WEI peut inscrire un 1A. Le formulaire 1A est assez peu différent du formulaire 2A+ : + +* Est-ce que l'utilisateur a déclaré avoir ouvert un compte à la Société générale ? +* Date de naissance +* Genre (Homme/Femme/Non-binaire) +* Problèmes de santé +* Nom du contact en cas d'urgence +* Numéro du contact en cas d'urgence +* S'inscrire à la ML événements +* S'inscrire à la ML BDA +* S'inscrire à la ML BDS + +Le 1A ne peut donc pas choisir de son bus et de son équipe, et peut s'inscrire aux listes de diffusion. +Il y a néanmoins une différence majeure : une fois le formulaire rempli, un questionnaire se lance. +Ce questionnaire peut varier au fil des années (voir section Questionnaire), et contient divers formulaires de collecte +de données qui serviront à déterminer quel est le meilleur bus pour ce nouvel utilisateur. + +Questionnaire 1A +^^^^^^^^^^^^^^^^ + +Le questionnaire 1A permet de poser des questions aux 1A lors de leur inscription au WEI afin de déterminer quel serait +le meilleur bus pour eux. Un algorithme attribue ensuite à chaque 1A le bus sélectionné. + +Afin de permettre de la modularité et de s'adapter aux changements au fil des années, il n'y a pas de modèle dédié au +sondage. On sauvegarde alors les données du sondage sous la forme d'un dictionnaire enregistré au format JSON +dans le champ ``information_json`` du modèle ``WEIRegistration``. Ce champ est modifiable manuellement uniquement par +les respos info et les GC WEI. + +Je veux changer d'algorithme de répartition, que faire ? +"""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +Cette section est plus technique et s'adresse surtout aux respos info en cours de mandat. + +Première règle : on ne supprime rien (sauf si vraiment c'est du mauvais boulot). En prenant exemple sur des fichiers déjà existant tels que ``apps/wei/forms/surveys/wei2020.py``, créer un nouveau fichier ``apps/wei/forms/surveys/wei20XY.py``. Ce fichier doit inclure les éléments suivants : + +WEISurvey +""""""""" + +Une classe héritant de ``wei.forms.surveys.base.WEISurvey``, comportant les éléments suivants : + +* Une fonction ``get_year(cls)`` indiquant l'année du WEI liée au sondage +* Une fonction ``get_survey_information_class(cls)`` indiquant la classe héritant de + ``wei.forms.surveys.base.WEISurveyInformation`` contenant les données du sondage (voir plus bas) +* Une fonction ``get_algorithm_class(cls)`` indiquant la classe héritant de + ``wei.forms.surveys.base.WEISurveyAlgorithm`` contenant l'algorithme de répartition (voir plus bas) +* Une fonction ``get_form_class(self)`` qui indique la classe du formulaire Django à remplir. Cette classe peut dépendre + de l'état actuel du sondage. +* Une fonction ``update_form(self, form)``, optionnelle, appelée lorsqu'un formulaire dont la classe est spécifiée via + la fonction ``get_form_class``, et permet d'opérer sur le formulaire si besoin. +* Une fonction ``form_valid(self, form)`` qui indique quoi faire lorsque le formulaire est rempli. Cette fonction peut + bien sûr dépendre de l'état actuel du sondage. +* Une fonction ``is_complete(self)`` devant renvoyer un booléen indiquant si le sondage est complet ou non. + +Naturellement, il est implicite qu'une fonction ayant pour premier argument ``cls`` doit être annotée par ``@classmethod``. +Nativement, la classe ``WEISurvey`` comprend les informations suivantes : + +* ``registration``, le modèle ``WEIRegistration`` de l'utilisateur qui remplit le questionnaire +* ``information``, instance de ``WEISurveyInformation``, contient les données du questionnaire en cours de remplissage. +* ``get_wei(cls)``, renvoie le WEI correspondant à l'année du sondage. +* ``save(self)``, enregistre les informations du sondage dans l'objet ``registration`` associé, qui est ensuite + enregistré en base de données. +* ``select_bus(self, bus)``, choisit le bus ``bus`` comme bus préféré. Cela à pour effet de remplir les champs + ``selected_bus_pk`` et ``selected_bus_name`` par les identifiant et nom du bus, et ``valid`` à ``True``. + +Pour information, ``WEISurvey.__init__`` prend comme paramètre l'inscription ``registration``, et récupère les +informations du sondage converties en dictionnaire Python puis en objet ``WEISurveyInformation``. + +WEISurveyInformation +"""""""""""""""""""" + +Une classe héritant de ``wei.forms.surveys.base.WEISurveyInformation``, comportant les informations brutes du sondage. +Le champ ``information_json`` de ``WEIRegistration`` est traduit en dictionnaire Python depuis JSON, puis les différents +champs de WEISurveyInformation sont mis à jour depuis ce dictionnaire. Il n'y a rien de supplémentaire à ajouter, tout +est déjà géré. + +Ainsi, plutôt que de modifier laborieusement le champ JSON, préférez utiliser cette classe. Attention : pour des soucis +de traduction facile, merci de n'utiliser que des objets primitifs (nombres, chaînes de caractère, booléens, listes, +dictionnaires simples). Les instances de modèle sont à proscrire, préférez stocker l'identifiant et créer une fonction +qui récupère l'instance à partir de l'identifiant. + +Attention, 3 noms sont réservés : ``selected_bus_pk``, ``selected_bus_name`` et ``valid``, qui représentent la sortie +de l'algorithme de répartition. + +À noter que l'interface de validation des inscriptions affiche les données brutes du sondage. + +WEIBusInformation +""""""""""""""""" + +Une classe héritant de ``wei.forms.surveys.base.WEIBusInformation``, qui contient les informations sur un bus, +de la même manière que ``WEISurveyInformation`` contient les informations d'un sondage. Le fonctionnement est le même : +on récupère le champ ``information_json`` du modèle ``Bus`` qu'on convertit en dictionnaire puis en objet Python. +Cet objet est en lecture uniquement, on modifie à la main les paramètres d'un bus. + +Le champ ``bus`` est fourni. + +WEISurveyAlgorithm +"""""""""""""""""" + +Une classe héritant de ``wei.forms.surveys.base.WEISurveyAlgorithm``, qui contient 3 fonctions : + +* ``get_survey_class(cls)``, qui renvoie la classe du ``WEISurvey`` associée à l'algorithme. +* ``get_bus_information_class(cls)`` qui renvoie la classe du ``WEIBusInformation`` décrivant les informations d' +* ``run_algorithm(self)``, la fonction importante. Cette fonction n'est supposée n'être exécutée qu'une seule fois + par WEI, et a pour cahier des charges de prendre chaque sondage d'un 1A et d'appeler la fonction ``WEISurvey.select_bus(bus)``, + en décidant convenablement de quel bus le membre doit prendre. C'est bien sûr la fonction la plus complexe à mettre en oeuvre. + Tout est permis tant qu'à la fin tout le monde a bien son bus. + +Trois fonctions sont implémentées nativement : + +* ``get_registrations(cls)``, renvoie un ``QuerySSet`` vers l'ensemble des inscriptions au WEI concerné des 1A. +* ``get_buses(cls)``, renvoie l'ensemble des bus du WEI concerné. +* ``get_bus_information(cls, bus)``, renvoie l'objet ``WEIBusInformation`` instancié avec les informations fournies + par le champ ``information_json`` de ``bus``. + + +La dernière chose à faire est dans le fichier ``apps/wei/forms/surveys/__init__.py``, où la classe ``CurrentSurvey`` +est à mettre à jour. Il n'y a rien d'autre à changer, tout le reste est normalement géré pour qu'il n'y ait pas nécessité +d'y toucher. + +Le lancement de l'algorithme se fait en ligne de commande, via la commande ``python manage.py wei_algorithm``. Elle a +pour unique effet d'appeler la fonction ``run_algorithm`` décrite plus tôt. Une fois cela fait, vous aurez noté qu'il +n'a pas été évoqué d'adhésion. L'adhésion est ensuite manuelle, l'algorithme ne fournit qu'une suggestion. + +Cette structure, complexe mais raisonnable, permet de gérer plus ou moins proprement la répartition des 1A, +en limitant très fortement le hard code. Ami nouveau développeur, merci de bien penser à la propreté du code :) +En particulier, on évitera de mentionner dans le code le nom des bus, et profiter du champ ``information_json`` +présent dans le modèle ``Bus``. + +Valider les inscriptions +~~~~~~~~~~~~~~~~~~~~~~~~ + +Cette partie est moins technique. + +Une fois la pré-inscription faite, elle doit être validée par le BDE, afin de procéder au paiement. Le GC WEI a accès à +la liste des inscriptions non validées, soit sur la page de détails du WEI, soit sur un tableau plus large avec filtre. +Une inscription non validée peut soit être validée, soit supprimée (la suppression est irréversible). + +Lorsque le GC WEI veut valider une inscription, il a accès au récapitulatif de l'inscription ainsi qu'aux informations +personnelles de l'utilisateur. Il lui est proposé de les modifier si besoin (du moins les informations liées au WEI, +pas les informations personnelles). Il a enfin accès aux résultats du sondage et la sortie de l'algorithme s'il s'agit +d'un 1A, aux préférences d'un 2A+. Avant de valider, le GC WEI doit sélectionner un bus, éventuellement une équipe +et un rôle. Si c'est un 1A et que l'algorithme a tourné, ou si c'est un 2A+ qui n'a fait qu'un seul choix de bus, +d'équipe, de rôles, les champs sont automatiquement pré-remplis. + +Quelques restrictions cependant : + +* Si c'est un 2A+, le chèque de caution doit être déclaré déposé +* Si l'inscription se fait via la Société générale, un message expliquant la situation apparaît : la transaction de + paiement sera créée mais invalidée, les trésoriers devront confirmer plus tard sur leur interface que le compte + à la Société générale a bien été créé avant de valider la transaction (voir `Trésorerie `_ section + Crédit de la Société générale). +* Dans le cas contraire, l'utilisateur doit avoir le solde nécessaire sur sa note avant de pouvoir adhérer. +* L'utilisateur doit enfin être membre du club Kfet. Un lien est présent pour le faire adhérer ou réadhérer selon le cas. + +Si tout est bon, le GC WEI peut valider. L'utilisateur a bien payé son WEI, et son interface est un peu plus grande. +Il peut toujours changer ses paramètres au besoin. Un 1A ne voit rien de plus avant la fin du WEI. + +Un adhérent WEI non 1A a accès à la liste des bus, des équipes et de leur descriptions. Les chefs de bus peuvent gérer +les bus et leurs équipes. Les chefs d'équipe peuvent gérer leurs équipes. Cela inclut avoir accès à la liste des membres +de ce bus / de cette équipe. + +Un export au format PDF de la liste des membres *visibles* est disponible pour chacun. + +Bon WEI à tous ! diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index 8eeb0f4..215a09a 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-08 10:30+0100\n" +"POT-Creation-Date: 2022-04-10 22:34+0200\n" "PO-Revision-Date: 2020-11-16 20:02+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: German \n" @@ -53,13 +53,16 @@ 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:182 +#: 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 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301 #: apps/permission/models.py:330 #: apps/registration/templates/registration/future_profile_detail.html:16 +#: apps/wei/models.py:67 apps/wei/models.py:131 apps/wei/tables.py:282 +#: apps/wei/templates/wei/base.html:26 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "name" msgstr "Name" @@ -92,7 +95,7 @@ msgstr "Vearnstaltungarte" #: apps/activity/models.py:68 #: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/note/models/transactions.py:81 apps/permission/models.py:110 -#: apps/permission/models.py:189 +#: apps/permission/models.py:189 apps/wei/models.py:78 apps/wei/models.py:142 msgid "description" msgstr "Beschreibung" @@ -101,9 +104,7 @@ msgid "location" msgstr "Ort" #: apps/activity/models.py:76 -#, fuzzy -#| msgid "Place where the activity is organized, eg. Kfet." -msgid "Place where the activity is organized, eg. BDE." +msgid "Place where the activity is organized, eg. Kfet." msgstr "Wo findet die Veranstaltung statt ? (z.B Kfet)." #: apps/activity/models.py:83 @@ -113,8 +114,10 @@ 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:290 -#: apps/note/models/notes.py:148 +#: 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:285 +#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13 +#: apps/wei/templates/wei/survey.html:15 msgid "user" msgstr "User" @@ -135,9 +138,7 @@ msgid "attendees club" msgstr "Teilnehmer" #: apps/activity/models.py:105 -#, fuzzy -#| msgid "Club that is authorized to join the activity. Mostly the Kfet club." -msgid "Club that is authorized to join the activity." +msgid "Club that is authorized to join the activity. Mostly the Kfet club." msgstr "Club die an die Veranstaltung teilnehmen können." #: apps/activity/models.py:109 @@ -208,6 +209,7 @@ msgstr "Kontostand ist im Rot." #: apps/activity/models.py:240 #: apps/treasury/templates/treasury/sogecredit_detail.html:14 +#: apps/wei/templates/wei/attribute_bus_1A.html:16 msgid "last name" msgstr "Nachname" @@ -215,6 +217,8 @@ msgstr "Nachname" #: apps/member/templates/member/includes/profile_info.html:4 #: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/treasury/templates/treasury/sogecredit_detail.html:17 +#: apps/wei/templates/wei/attribute_bus_1A.html:19 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "first name" msgstr "Vorname" @@ -254,18 +258,20 @@ msgstr "Eingetreten um " msgid "remove" msgstr "entfernen" -#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:196 +#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:199 msgid "Type" msgstr "Type" -#: apps/activity/tables.py:84 apps/member/forms.py:180 -#: apps/registration/forms.py:68 apps/treasury/forms.py:131 +#: apps/activity/tables.py:84 apps/member/forms.py:186 +#: apps/registration/forms.py:91 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:185 +#: apps/activity/tables.py:86 apps/member/forms.py:191 #: apps/note/templates/note/transaction_form.html:138 -#: apps/registration/forms.py:73 apps/treasury/forms.py:133 +#: apps/registration/forms.py:96 apps/treasury/forms.py:133 +#: apps/wei/forms/registration.py:109 msgid "First name" msgstr "Vorname" @@ -290,19 +296,19 @@ msgstr "Gastliste" #: apps/activity/templates/activity/activity_entry.html:14 #: apps/note/models/transactions.py:257 #: apps/note/templates/note/transaction_form.html:17 -#: apps/note/templates/note/transaction_form.html:146 +#: apps/note/templates/note/transaction_form.html:152 #: note_kfet/templates/base.html:72 msgid "Transfer" msgstr "Überweisen" #: apps/activity/templates/activity/activity_entry.html:18 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:22 msgid "Credit" msgstr "Kredit" #: apps/activity/templates/activity/activity_entry.html:21 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:26 msgid "Debit" msgstr "Soll" @@ -318,7 +324,7 @@ msgstr "Zurück zur Veranstaltungseite" #: apps/activity/templates/activity/activity_entry.html:94 #: apps/activity/templates/activity/activity_entry.html:129 -msgid "Entry done, but caution: the user is not a member." +msgid "Entry done, but caution: the user is not a Kfet member." msgstr "" #: apps/activity/templates/activity/activity_entry.html:132 @@ -328,11 +334,15 @@ msgid "Entry done!" msgstr "Eintrittseite" #: apps/activity/templates/activity/activity_form.html:16 -#: apps/member/templates/member/add_members.html:32 +#: apps/member/templates/member/add_members.html:46 #: apps/member/templates/member/club_form.html:16 #: apps/note/templates/note/transactiontemplate_form.html:18 -#: apps/treasury/forms.py:89 apps/treasury/forms.py:141 +#: apps/treasury/forms.py:89 apps/treasury/forms.py:143 #: apps/treasury/templates/treasury/invoice_form.html:74 +#: apps/wei/templates/wei/bus_form.html:17 +#: apps/wei/templates/wei/busteam_form.html:17 +#: apps/wei/templates/wei/weiclub_form.html:17 +#: apps/wei/templates/wei/weiregistration_form.html:18 msgid "Submit" msgstr "Vorlegen" @@ -369,9 +379,6 @@ msgid "Entry page" msgstr "Eintrittseite" #: apps/activity/templates/activity/includes/activity_info.html:65 -#: env/lib/python3.11/site-packages/bootstrap4/components.py:17 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/form_errors.html:3 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/messages.html:4 msgid "close" msgstr "Schlusss" @@ -462,7 +469,7 @@ msgstr "schaffen" #: apps/logs/models.py:65 apps/note/tables.py:166 apps/note/tables.py:190 #: apps/note/tables.py:237 apps/permission/models.py:127 -#: apps/treasury/tables.py:38 +#: apps/treasury/tables.py:38 apps/wei/tables.py:74 msgid "delete" msgstr "entfernen" @@ -491,25 +498,25 @@ 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:209 +#: 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:214 +#: 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:302 +#: apps/member/admin.py:65 apps/member/models.py:319 msgid "roles" msgstr "Rollen" -#: apps/member/admin.py:66 apps/member/models.py:316 +#: apps/member/admin.py:66 apps/member/models.py:333 msgid "fee" msgstr "Preis" -#: apps/member/apps.py:14 +#: apps/member/apps.py:14 apps/wei/tables.py:226 apps/wei/tables.py:257 msgid "member" msgstr "Mitglied" @@ -542,31 +549,48 @@ 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:33 apps/registration/views.py:252 +#: apps/registration/forms.py:33 apps/registration/views.py:262 msgid "An alias with a similar name already exists." msgstr "Ein ähnliches Alias ist schon benutzt." -#: apps/member/forms.py:166 apps/registration/forms.py:55 +#: apps/member/forms.py:165 apps/registration/forms.py:71 +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/registration/forms.py:73 +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:78 +#: apps/wei/forms/registration.py:91 msgid "Credit type" msgstr "Kredittype" -#: apps/member/forms.py:167 apps/registration/forms.py:56 +#: apps/member/forms.py:173 apps/registration/forms.py:79 +#: apps/wei/forms/registration.py:92 msgid "No credit" msgstr "Kein Kredit" -#: apps/member/forms.py:169 +#: 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:173 apps/registration/forms.py:61 +#: apps/member/forms.py:179 apps/registration/forms.py:84 +#: apps/wei/forms/registration.py:97 msgid "Credit amount" msgstr "Kreditanzahl" -#: apps/member/forms.py:212 +#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144 +#: apps/registration/forms.py:101 apps/treasury/forms.py:135 +#: apps/wei/forms/registration.py:114 +msgid "Bank" +msgstr "Bank" + +#: apps/member/forms.py:223 msgid "User" msgstr "User" -#: apps/member/forms.py:226 +#: apps/member/forms.py:237 msgid "Roles" msgstr "Rollen" @@ -591,12 +615,14 @@ msgstr "" #: apps/member/models.py:38 #: apps/member/templates/member/includes/profile_info.html:43 #: apps/registration/templates/registration/future_profile_detail.html:40 +#: apps/wei/templates/wei/weimembership_form.html:44 msgid "phone number" msgstr "Telefonnummer" #: apps/member/models.py:45 #: apps/member/templates/member/includes/profile_info.html:37 #: apps/registration/templates/registration/future_profile_detail.html:34 +#: apps/wei/templates/wei/weimembership_form.html:38 msgid "section" msgstr "Section" @@ -604,79 +630,114 @@ msgstr "Section" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" -#: apps/member/models.py:54 +#: apps/member/models.py:54 apps/wei/templates/wei/attribute_bus_1A.html:25 +#: apps/wei/templates/wei/weimembership_form.html:32 msgid "department" msgstr "Fachabteilung" #: apps/member/models.py:56 -#, fuzzy -#| msgid "Informatics (A0)" -msgid "Informatique" +msgid "Informatics (A0)" msgstr "Informatik (A0)" #: apps/member/models.py:57 -#, fuzzy -#| msgid "Mathematics (A1)" -msgid "Mathématiques" +msgid "Mathematics (A1)" msgstr "Mathematik (A1)" #: apps/member/models.py:58 -#, fuzzy -#| msgid "Economy-management (D2)" -msgid "Droit - économie - management" -msgstr "Wirtschaftingenieure (D2)" +msgid "Physics (A2)" +msgstr "Physik (A2)" #: apps/member/models.py:59 -msgid "Mécatronique" -msgstr "" +msgid "Applied physics (A'2)" +msgstr "Angewandte Physik (A'2)" #: apps/member/models.py:60 -msgid "Sciences du sport et éducation physique" -msgstr "" +msgid "Chemistry (A''2)" +msgstr "Chemie (A''2)" #: apps/member/models.py:61 -msgid "Sciences pour l’Environnement" -msgstr "" +msgid "Biology (A3)" +msgstr "Biologie (A3)" #: apps/member/models.py:62 -msgid "Externe" -msgstr "" +msgid "SAPHIRE (B1234)" +msgstr "SAPHIRE (B1234)" + +#: apps/member/models.py:63 +msgid "Mechanics (B1)" +msgstr "Mechanik (B1)" + +#: apps/member/models.py:64 +msgid "Civil engineering (B2)" +msgstr "Bauingenieur (B2)" + +#: apps/member/models.py:65 +msgid "Mechanical engineering (B3)" +msgstr "Mechanikingenieur (B3)" + +#: apps/member/models.py:66 +msgid "EEA (B4)" +msgstr "Electrotechnik (B4)" + +#: apps/member/models.py:67 +msgid "Design (C)" +msgstr "Design (C)" + +#: apps/member/models.py:68 +msgid "Economy-management (D2)" +msgstr "Wirtschaftingenieure (D2)" #: apps/member/models.py:69 +msgid "Social sciences (D3)" +msgstr "Sozialwissenschaften (D3)" + +#: apps/member/models.py:70 +msgid "English (E)" +msgstr "English (E)" + +#: apps/member/models.py:71 +msgid "External (EXT)" +msgstr "Extern (EXT)" + +#: apps/member/models.py:78 msgid "promotion" msgstr "Promotion" -#: apps/member/models.py:70 +#: apps/member/models.py:79 msgid "Year of entry to the school (None if not ENS student)" msgstr "ENS Eintrittjahr (None wenn kein ENS Student)" -#: apps/member/models.py:74 +#: apps/member/models.py:83 #: apps/member/templates/member/includes/profile_info.html:47 #: apps/registration/templates/registration/future_profile_detail.html:37 +#: apps/wei/templates/wei/weimembership_form.html:41 msgid "address" msgstr "Adresse" -#: apps/member/models.py:81 +#: apps/member/models.py:90 #: apps/member/templates/member/includes/profile_info.html:50 #: apps/registration/templates/registration/future_profile_detail.html:43 +#: apps/wei/templates/wei/weimembership_form.html:47 msgid "paid" msgstr "bezahlt" -#: apps/member/models.py:82 +#: apps/member/models.py:91 msgid "Tells if the user receive a salary." msgstr "User ist bezahlt." -#: apps/member/models.py:91 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:796 +#: apps/member/models.py:100 apps/treasury/tables.py:143 msgid "No" msgstr "Nein" -#: apps/member/models.py:92 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:795 -msgid "Yes" -msgstr "Ja" +#: apps/member/models.py:101 +msgid "Yes (receive them in french)" +msgstr "Ja (auf Fränzosich)" -#: apps/member/models.py:94 +#: apps/member/models.py:102 +msgid "Yes (receive them in english)" +msgstr "Ja (auf English)" + +#: apps/member/models.py:104 msgid "" "Register on the mailing list to stay informed of the events of the campus (1 " "mail/week)" @@ -684,7 +745,7 @@ msgstr "" "Melden Sie sich auf der Mailingliste an, um über die Ereignisse des Campus " "informiert zu bleiben (1 Mail / Woche)" -#: apps/member/models.py:99 +#: apps/member/models.py:109 msgid "" "Register on the mailing list to stay informed of the sport events of the " "campus (1 mail/week)" @@ -692,7 +753,7 @@ msgstr "" "Melden Sie sich auf der Mailingliste an, um über die Sportereignisse des " "Campus informiert zu bleiben (1 Mail / Woche)" -#: apps/member/models.py:104 +#: apps/member/models.py:114 msgid "" "Register on the mailing list to stay informed of the art events of the " "campus (1 mail/week)" @@ -700,121 +761,121 @@ msgstr "" "Melden Sie sich auf der Mailingliste an, um über die Kunstereignisse des " "Campus informiert zu bleiben (1 Mail / Woche)" -#: apps/member/models.py:108 +#: apps/member/models.py:118 msgid "report frequency (in days)" msgstr "Bericht Frequenz (Tagen)" -#: apps/member/models.py:113 +#: apps/member/models.py:123 msgid "last report date" msgstr "letzen Bericht Datum" -#: apps/member/models.py:118 +#: apps/member/models.py:128 msgid "email confirmed" msgstr "email bestätigt" -#: apps/member/models.py:123 +#: apps/member/models.py:133 msgid "registration valid" msgstr "Anmeldung gültig" -#: apps/member/models.py:145 apps/member/models.py:146 +#: apps/member/models.py:162 apps/member/models.py:163 msgid "user profile" msgstr "Userprofile" -#: apps/member/models.py:156 -#, fuzzy -#| msgid "Activate your Note Kfet account" -msgid "Activate your Note Ker Lann account" +#: apps/member/models.py:173 +msgid "Activate your Note Kfet account" msgstr "Ihre Note Kfet Konto bestätigen" -#: apps/member/models.py:187 +#: 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 +#: apps/wei/templates/wei/base.html:70 +#: apps/wei/templates/wei/weimembership_form.html:20 msgid "email" msgstr "Email" -#: apps/member/models.py:194 +#: apps/member/models.py:211 msgid "parent club" msgstr "Urclub" -#: apps/member/models.py:203 +#: apps/member/models.py:220 msgid "require memberships" msgstr "erfordern Mitgliedschaft" -#: apps/member/models.py:204 +#: 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:220 +#: apps/member/models.py:237 #: apps/member/templates/member/includes/club_info.html:26 msgid "membership duration" msgstr "Mitgliedscahftzeit" -#: apps/member/models.py:221 +#: 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:228 +#: apps/member/models.py:245 #: apps/member/templates/member/includes/club_info.html:16 msgid "membership start" msgstr "Mitgliedschaftanfangsdatum" -#: apps/member/models.py:229 +#: 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:235 +#: apps/member/models.py:252 #: apps/member/templates/member/includes/club_info.html:21 msgid "membership end" msgstr "Mitgliedschaftenddatum" -#: apps/member/models.py:236 +#: 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:271 apps/member/models.py:296 +#: apps/member/models.py:288 apps/member/models.py:313 #: apps/note/models/notes.py:176 msgid "club" msgstr "Club" -#: apps/member/models.py:272 +#: apps/member/models.py:289 msgid "clubs" msgstr "Clubs" -#: apps/member/models.py:307 +#: apps/member/models.py:324 msgid "membership starts on" msgstr "Mitgliedschaft fängt an" -#: apps/member/models.py:311 +#: apps/member/models.py:328 msgid "membership ends on" msgstr "Mitgliedschaft endet am" -#: apps/member/models.py:404 +#: 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:413 apps/member/views.py:672 +#: 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:425 apps/member/views.py:681 +#: 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:459 +#: 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:462 apps/note/models/transactions.py:380 +#: apps/member/models.py:507 apps/note/models/transactions.py:389 msgid "membership" msgstr "Mitgliedschaft" -#: apps/member/models.py:463 +#: apps/member/models.py:508 msgid "memberships" msgstr "Mitgliedschaften" @@ -822,7 +883,18 @@ msgstr "Mitgliedschaften" msgid "Renew" msgstr "Erneuern" -#: apps/member/templates/member/add_members.html:16 +#: apps/member/templates/member/add_members.html:17 +#, python-format +msgid "" +"The user is not a member of the club·s %(clubs)s. An additional fee of " +"%(pretty_fee)s will be charged to renew automatically the membership in this/" +"these club·s." +msgstr "" +"Dieser User ist noch nicht Mitglied von den Urclub %(clubs)s. Ein extra " +"Beitrag von %(pretty_fee)s wurde bezahlt um die Mitgliedschaft von dieser/" +"diesen Club zu erneuern." + +#: apps/member/templates/member/add_members.html:22 #, fuzzy, python-format #| msgid "" #| "The user is not a member of the club·s %(clubs)s. An additional fee of " @@ -836,7 +908,16 @@ msgstr "" "Beitrag von %(pretty_fee)s wurde bezahlt um die Mitgliedschaft von dieser/" "diesen Club zu erneuern." -#: apps/member/templates/member/add_members.html:21 +#: apps/member/templates/member/add_members.html:29 +#, python-format +msgid "" +"This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will be " +"charged to adhere automatically to this/these club·s." +msgstr "" +"Dieses Club hat %(clubs)s als Urclub. Eine extra Beitrag von %(pretty_fee)s " +"wurde bezahlt um Mitglied von dieser/diesen Club zu werden." + +#: apps/member/templates/member/add_members.html:34 #, python-format msgid "" "This club has parents %(clubs)s. Please make sure that the user is a member " @@ -851,6 +932,7 @@ msgstr "Konto #" #: apps/member/templates/member/base.html:48 #: apps/member/templates/member/base.html:62 apps/member/views.py:60 #: apps/registration/templates/registration/future_profile_detail.html:48 +#: apps/wei/templates/wei/weimembership_form.html:117 msgid "Update Profile" msgstr "Profile bearbeiten" @@ -924,7 +1006,7 @@ msgid "Add" msgstr "Neue" #: apps/member/templates/member/club_detail.html:13 -#: apps/permission/templates/permission/all_rights.html:77 +#: apps/permission/templates/permission/all_rights.html:32 msgid "Club managers" msgstr "Clubmanager" @@ -934,6 +1016,7 @@ msgstr "Mitglied" #: apps/member/templates/member/club_detail.html:40 #: apps/member/templates/member/profile_detail.html:32 +#: apps/wei/templates/wei/weiclub_detail.html:75 msgid "Transaction history" msgstr "Transaktionvergangenheit" @@ -950,6 +1033,7 @@ msgid "Filter roles:" msgstr "Rollen filter:" #: apps/member/templates/member/club_members.html:36 +#: apps/wei/templates/wei/weimembership_list.html:19 msgid "There is no membership found with this pattern." msgstr "Keine Mitgliedschaft mit diesem pattern gefunden." @@ -962,18 +1046,20 @@ msgid "days" msgstr "Tagen" #: apps/member/templates/member/includes/club_info.html:31 +#: apps/wei/templates/wei/base.html:40 msgid "membership fee" msgstr "Mitgliedsachftpreis" #: apps/member/templates/member/includes/club_info.html:43 #: apps/member/templates/member/includes/profile_info.html:55 #: apps/treasury/templates/treasury/sogecredit_detail.html:24 +#: apps/wei/templates/wei/base.html:60 msgid "balance" msgstr "Kontostand" #: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/profile_info.html:20 -#: apps/note/models/notes.py:287 +#: apps/note/models/notes.py:287 apps/wei/templates/wei/base.html:66 msgid "aliases" msgstr "Aliases" @@ -985,6 +1071,7 @@ msgstr "Aliases bearbeiten" #: apps/member/templates/member/includes/profile_info.html:7 #: apps/registration/templates/registration/future_profile_detail.html:19 #: apps/treasury/templates/treasury/sogecredit_detail.html:20 +#: apps/wei/templates/wei/weimembership_form.html:17 msgid "username" msgstr "Username" @@ -1071,11 +1158,13 @@ msgstr "Beschneiden und hochladen" #: apps/member/templates/member/profile_detail.html:11 #: apps/registration/templates/registration/future_profile_detail.html:28 +#: apps/wei/templates/wei/weimembership_form.html:26 msgid "This user doesn't have confirmed his/her e-mail address." msgstr "Dieser User hat noch nicht sein email bestätigt." #: apps/member/templates/member/profile_detail.html:13 #: apps/registration/templates/registration/future_profile_detail.html:29 +#: apps/wei/templates/wei/weimembership_form.html:27 msgid "Click here to resend a validation link." msgstr "Click hier um eine Bestätigunglinke zu schicken." @@ -1091,7 +1180,7 @@ msgstr "" msgid "" "Adding someone as a friend enables them to initiate transactions coming from " "your account (while keeping your balance positive). This is designed to " -"simplify using note ker lann transfers to transfer money between users. The " +"simplify using note kfet transfers to transfer money between users. The " "intent is that one person can make all transfers for a group of friends " "without needing additional rights among them." msgstr "" @@ -1140,11 +1229,11 @@ msgstr "Club Details" msgid "Update club" msgstr "Club bearbeiten" -#: apps/member/views.py:569 +#: apps/member/views.py:574 msgid "Add new member to the club" msgstr "Neue Mitglieder" -#: apps/member/views.py:663 +#: apps/member/views.py:703 apps/wei/views.py:973 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." @@ -1152,19 +1241,19 @@ msgstr "" "Diese User hat nicht genug Geld um Mitglied zu werden, und darf nich im Rot " "sein." -#: apps/member/views.py:685 +#: apps/member/views.py:725 msgid "The membership must start after {:%m-%d-%Y}." msgstr "Die Mitgliedschaft muss nach {:%m-%d-Y} anfängen." -#: apps/member/views.py:690 +#: apps/member/views.py:730 msgid "The membership must begin before {:%m-%d-%Y}." msgstr "Die Mitgliedschaft muss vor {:%m-%d-Y} anfängen." -#: apps/member/views.py:797 +#: apps/member/views.py:876 msgid "Manage roles of an user in the club" msgstr "Rollen in diesen Club bearbeiten" -#: apps/member/views.py:821 +#: apps/member/views.py:901 msgid "Members of the club" msgstr "Mitlglieder dieses Club" @@ -1203,7 +1292,7 @@ msgstr "Empfänger" msgid "Reason" msgstr "Grund" -#: apps/note/forms.py:79 +#: apps/note/forms.py:79 apps/treasury/tables.py:136 msgid "Valid" msgstr "Gültig" @@ -1451,7 +1540,11 @@ msgstr "wiederkehrende Transaktionen" msgid "first_name" msgstr "Vorname" -#: apps/note/models/transactions.py:323 +#: apps/note/models/transactions.py:311 +msgid "bank" +msgstr "Bank" + +#: apps/note/models/transactions.py:328 msgid "" "A special transaction is only possible between a Note associated to a " "payment method and a User or a Club" @@ -1459,24 +1552,25 @@ msgstr "" "Eine Sondertransaktion ist nur zwischen einer Note, die einer " "Zahlungsmethode zugeordnet ist, und einem User oder einem Club möglich" -#: apps/note/models/transactions.py:349 apps/note/models/transactions.py:352 -#: env/lib/python3.11/site-packages/django/forms/fields.py:91 +#: apps/note/models/transactions.py:355 apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:361 apps/wei/views.py:978 +#: apps/wei/views.py:982 msgid "This field is required." msgstr "Dies ist ein Pflichtfeld." -#: apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:367 msgid "Special transaction" msgstr "Sondertransaktion" -#: apps/note/models/transactions.py:359 +#: apps/note/models/transactions.py:368 msgid "Special transactions" msgstr "Sondertranskationen" -#: apps/note/models/transactions.py:375 +#: apps/note/models/transactions.py:384 msgid "membership transaction" msgstr "Mitgliedschafttransaktion" -#: apps/note/models/transactions.py:376 +#: apps/note/models/transactions.py:385 apps/treasury/models.py:292 msgid "membership transactions" msgstr "Mitgliedschaftttransaktionen" @@ -1496,10 +1590,8 @@ msgstr "Kein Grund gegeben" #: apps/treasury/tables.py:39 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:30 #: apps/treasury/templates/treasury/sogecredit_detail.html:65 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:499 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:13 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:38 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:7 +#: apps/wei/tables.py:75 apps/wei/tables.py:118 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:31 #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:18 #: note_kfet/templates/oauth2_provider/application_detail.html:39 #: note_kfet/templates/oauth2_provider/authorized-token-delete.html:12 @@ -1507,7 +1599,11 @@ msgid "Delete" msgstr "Löschen" #: apps/note/tables.py:222 apps/note/templates/note/conso_form.html:132 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:37 +#: apps/wei/tables.py:49 apps/wei/tables.py:50 +#: apps/wei/templates/wei/base.html:89 +#: apps/wei/templates/wei/bus_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:40 #: note_kfet/templates/oauth2_provider/application_detail.html:38 msgid "Edit" msgstr "Bearbeiten" @@ -1552,28 +1648,23 @@ msgid "Double consumptions" msgstr "Doppelte Modus" #: apps/note/templates/note/conso_form.html:154 -#: apps/note/templates/note/transaction_form.html:157 +#: apps/note/templates/note/transaction_form.html:163 msgid "Recent transactions history" msgstr "Verlauf der letzten Transaktionen" #: apps/note/templates/note/mails/negative_balance.html:43 +#: apps/note/templates/note/mails/negative_balance.txt:25 #: apps/note/templates/note/mails/negative_notes_report.html:46 +#: apps/note/templates/note/mails/negative_notes_report.txt:13 #: apps/note/templates/note/mails/weekly_report.html:51 +#: apps/note/templates/note/mails/weekly_report.txt:32 #: apps/registration/templates/registration/mails/email_validation_email.html:40 #: apps/registration/templates/registration/mails/email_validation_email.txt:16 -#, fuzzy -#| msgid "Mail generated by the Note Kfet on the" -msgid "Mail generated by the Note Ker Lann on the" -msgstr "Mail generiert vom Note Kfet auf dem" - -#: apps/note/templates/note/mails/negative_balance.txt:25 -#: apps/note/templates/note/mails/negative_notes_report.txt:13 -#: apps/note/templates/note/mails/weekly_report.txt:32 msgid "Mail generated by the Note Kfet on the" msgstr "Mail generiert vom Note Kfet auf dem" #: apps/note/templates/note/transaction_form.html:58 -#: apps/note/templates/note/transaction_form.html:172 +#: apps/note/templates/note/transaction_form.html:178 msgid "Select emitters" msgstr "Sender auswählen" @@ -1582,7 +1673,7 @@ msgid "I am the emitter" msgstr "Ich bin der Sender" #: apps/note/templates/note/transaction_form.html:85 -#: apps/note/templates/note/transaction_form.html:174 +#: apps/note/templates/note/transaction_form.html:180 msgid "Select receivers" msgstr "Empfänger auswählen" @@ -1591,25 +1682,26 @@ msgid "Action" msgstr "Aktion" #: apps/note/templates/note/transaction_form.html:116 -#: apps/treasury/forms.py:135 apps/treasury/tables.py:67 +#: apps/treasury/forms.py:137 apps/treasury/tables.py:67 +#: apps/treasury/tables.py:132 #: apps/treasury/templates/treasury/remittance_form.html:23 msgid "Amount" msgstr "Anzahl" #: apps/note/templates/note/transaction_form.html:132 -#: apps/treasury/models.py:51 +#: apps/treasury/models.py:54 msgid "Name" msgstr "Name" -#: apps/note/templates/note/transaction_form.html:171 +#: apps/note/templates/note/transaction_form.html:177 msgid "Select emitter" msgstr "Sender auswählen" -#: apps/note/templates/note/transaction_form.html:173 +#: apps/note/templates/note/transaction_form.html:179 msgid "Select receiver" msgstr "Empfänger auswählen" -#: apps/note/templates/note/transaction_form.html:175 +#: apps/note/templates/note/transaction_form.html:181 msgid "Transfer type" msgstr "Überweisungtype" @@ -1748,7 +1840,7 @@ msgstr "" "Mitgliedschaft des Benutzers abgelaufen ist." #: apps/permission/models.py:183 -#: apps/permission/templates/permission/all_rights.html:56 +#: apps/permission/templates/permission/all_rights.html:89 msgid "permanent" msgstr "permanent" @@ -1799,56 +1891,61 @@ msgstr "" "Sie haben nicht die Berechtigung, eine Instanz von model {app_label}. " "{model_name} zulöschen." -#: apps/permission/templates/permission/all_rights.html:13 +#: apps/permission/templates/permission/all_rights.html:12 +msgid "Users that have surnormal rights" +msgstr "User die Oberberechtigung haben" + +#: apps/permission/templates/permission/all_rights.html:16 +msgid "Superusers have all rights on everything, to manage the website." +msgstr "Superuser haben alle Berechtigung, um das Website zu handeln." + +#: apps/permission/templates/permission/all_rights.html:21 +msgid "Superusers" +msgstr "Superusers" + +#: apps/permission/templates/permission/all_rights.html:45 msgid "Roles description" msgstr "Rolle Beschreibung" -#: apps/permission/templates/permission/all_rights.html:20 +#: apps/permission/templates/permission/all_rights.html:52 msgid "Filter with roles that I have in at least one club" msgstr "Filtern Sie nach Rollen, die ich in mindestens einem Club habe" -#: apps/permission/templates/permission/all_rights.html:36 +#: apps/permission/templates/permission/all_rights.html:69 msgid "Owned" msgstr "Besetzt" -#: apps/permission/templates/permission/all_rights.html:47 +#: apps/permission/templates/permission/all_rights.html:80 msgid "Own this role in the clubs" msgstr "Besitze diese Rolle in den Clubs" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Mask:" msgstr "Mask:" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Query:" msgstr "Abfrage:" -#: apps/permission/templates/permission/all_rights.html:59 +#: apps/permission/templates/permission/all_rights.html:92 msgid "No associated permission" msgstr "Keine zugehörige Berechtigung" -#: apps/permission/templates/permission/all_rights.html:71 -msgid "Users that have surnormal rights" -msgstr "User die Oberberechtigung haben" - #: apps/permission/templates/permission/scopes.html:8 msgid "Available scopes" msgstr "" #: apps/permission/templates/permission/scopes.html:42 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:24 msgid "No applications defined" msgstr "" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "Click here" msgstr "" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "if you want to register a new one" msgstr "" @@ -1873,7 +1970,7 @@ msgstr "" "diesen Parametern zu erstellen. Bitte korrigieren Sie Ihre Daten und " "versuchen Sie es erneut." -#: apps/permission/views.py:112 note_kfet/templates/base.html:102 +#: apps/permission/views.py:112 note_kfet/templates/base.html:108 msgid "Rights" msgstr "Rechten" @@ -1889,21 +1986,40 @@ msgstr "Anmeldung" msgid "This email address is already used." msgstr "Diese email adresse ist schon benutzt." -#: apps/registration/forms.py:78 +#: apps/registration/forms.py:49 +#, fuzzy +#| msgid "You already opened an account in the Société générale." +msgid "" +"I declare that I opened or I will open soon a bank account in the Société " +"générale with the BDE partnership." +msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." + +#: apps/registration/forms.py:51 +msgid "" +"Warning: this engages you to open your bank account. If you finally decides " +"to don't open your account, you will have to pay the BDE membership." +msgstr "" + +#: apps/registration/forms.py:59 +msgid "Register to the WEI" +msgstr "Zu WEI anmelden" + +#: apps/registration/forms.py:61 +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." +msgstr "" +"Überprüfen Sie diesen Fall, wenn Sie sich beim WEI registrieren möchten. " +"falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im Kfet " +"registrieren." + +#: apps/registration/forms.py:106 msgid "Join BDE Club" msgstr "BDE Mitglieder werden" -#: apps/registration/forms.py:84 -#, fuzzy -#| msgid "Join BDE Club" -msgid "Join BDA Club" -msgstr "BDE Mitglieder werden" - -#: apps/registration/forms.py:90 -#, fuzzy -#| msgid "Join BDE Club" -msgid "Join BDS Club" -msgstr "BDE Mitglieder werden" +#: apps/registration/forms.py:113 +msgid "Join Kfet Club" +msgstr "Kfet Mitglieder werden" #: apps/registration/templates/registration/email_validation_complete.html:15 msgid "Your email have successfully been validated." @@ -1915,11 +2031,8 @@ msgid "You can now log in." msgstr "Sie können sich jetz anmelden ." #: apps/registration/templates/registration/email_validation_complete.html:23 -#, fuzzy -#| msgid "" -#| "You must pay now your membership in the Kfet to complete your " -#| "registration." -msgid "You must pay now your membership to complete your registration." +msgid "" +"You must pay now your membership in the Kfet to complete your registration." msgstr "" "Sie müssen jetzt Ihre Mitgliedschaft im Kfet bezahlen, um Ihre Registrierung " "abzuschließen." @@ -1944,18 +2057,11 @@ msgstr "" "aktivieren." #: apps/registration/templates/registration/email_validation_email_sent.html:17 -#, fuzzy -#| msgid "" -#| "You must pay now your membership in the Kfet to complete your " -#| "registration." -msgid "" -"You must also pay your membership. A administrator will then activate your " -"account" -msgstr "" -"Sie müssen jetzt Ihre Mitgliedschaft im Kfet bezahlen, um Ihre Registrierung " -"abzuschließen." +msgid "You must also go to the Kfet to pay your membership." +msgstr "Sie müssen auch zum Kfet gehen, um Ihre Mitgliedschaft zu bezahlen." #: apps/registration/templates/registration/future_profile_detail.html:49 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:11 msgid "Delete registration" msgstr "Registrierung löschen" @@ -1963,7 +2069,16 @@ msgstr "Registrierung löschen" msgid "Validate account" msgstr "Konto validieren" -#: apps/registration/templates/registration/future_profile_detail.html:65 +#: apps/registration/templates/registration/future_profile_detail.html:62 +#, fuzzy +#| msgid "You already opened an account in the Société générale." +msgid "" +"The user declared that he/she opened a bank account in the Société générale." +msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." + +#: apps/registration/templates/registration/future_profile_detail.html:71 +#: apps/wei/templates/wei/weimembership_form.html:127 +#: apps/wei/templates/wei/weimembership_form.html:186 msgid "Validate registration" msgstr "Registrierung validieren" @@ -1971,12 +2086,6 @@ msgstr "Registrierung validieren" msgid "New user" msgstr "Neue User" -#: apps/registration/templates/registration/mails/email_validation_email.html:7 -#, fuzzy -#| msgid "Activate your Note Kfet account" -msgid "Activation of your Note Ker Lann account" -msgstr "Ihre Note Kfet Konto bestätigen" - #: apps/registration/templates/registration/mails/email_validation_email.html:12 #: apps/registration/templates/registration/mails/email_validation_email.txt:3 msgid "Hi" @@ -1984,13 +2093,9 @@ msgstr "Hallo" #: apps/registration/templates/registration/mails/email_validation_email.html:16 #: apps/registration/templates/registration/mails/email_validation_email.txt:5 -#, fuzzy -#| msgid "" -#| "You recently registered on the Note Kfet. Please click on the link below " -#| "to confirm your registration." msgid "" -"You recently registered on the Note Ker Lann. Please click on the link below " -"to confirm your registration." +"You recently registered on the Note Kfet. Please click on the link below to " +"confirm your registration." msgstr "" "Sie haben sich kürzlich beim Note Kfet registriert. Bitte klicken Sie auf " "den Link unten, um Ihre Registrierung zu bestätigen." @@ -2006,13 +2111,9 @@ msgstr "" #: apps/registration/templates/registration/mails/email_validation_email.html:30 #: apps/registration/templates/registration/mails/email_validation_email.txt:11 -#, fuzzy -#| msgid "" -#| "After that, you'll have to wait that someone validates your account " -#| "before you can log in. You will need to pay your membership in the Kfet." msgid "" "After that, you'll have to wait that someone validates your account before " -"you can log in. You will need to pay your membership." +"you can log in. You will need to pay your membership in the Kfet." msgstr "" "Danach müssen Sie warten, bis jemand Ihr Konto validiert, bevor Sie sich " "anmelden können. Sie müssen Ihre Mitgliedschaft im Kfet bezahlen." @@ -2024,55 +2125,57 @@ msgstr "Danke" #: apps/registration/templates/registration/mails/email_validation_email.html:39 #: apps/registration/templates/registration/mails/email_validation_email.txt:15 -#, fuzzy -#| msgid "The Note Kfet team." -msgid "The Note Ker Lann team." +msgid "The Note Kfet team." msgstr "Die NoteKfet Team." -#: apps/registration/views.py:39 +#: apps/registration/views.py:40 msgid "Register new user" msgstr "Neuen User registrieren" -#: apps/registration/views.py:89 +#: apps/registration/views.py:98 msgid "Email validation" msgstr "Email validierung" -#: apps/registration/views.py:91 +#: apps/registration/views.py:100 msgid "Validate email" msgstr "Email validieren" -#: apps/registration/views.py:135 +#: apps/registration/views.py:144 msgid "Email validation unsuccessful" msgstr "Email validierung unerfolgreich" -#: apps/registration/views.py:146 +#: apps/registration/views.py:155 msgid "Email validation email sent" msgstr "Validierungsemail wurde gesendet" -#: apps/registration/views.py:154 +#: apps/registration/views.py:163 msgid "Resend email validation link" msgstr "E-Mail-Validierungslink erneut senden" -#: apps/registration/views.py:172 +#: apps/registration/views.py:181 msgid "Pre-registered users list" msgstr "Vorregistrierte Userliste" -#: apps/registration/views.py:196 +#: apps/registration/views.py:205 msgid "Unregistered users" msgstr "Unregistrierte Users" -#: apps/registration/views.py:209 +#: apps/registration/views.py:218 msgid "Registration detail" msgstr "Registrierung Detailen" -#: apps/registration/views.py:281 +#: apps/registration/views.py:282 +msgid "You must join the BDE." +msgstr "Sie müssen die BDE beitreten." + +#: apps/registration/views.py:306 msgid "" "The entered amount is not enough for the memberships, should be at least {}" msgstr "" "Der eingegebene Betrag reicht für die Mitgliedschaft nicht aus, sollte " "mindestens {} betragen" -#: apps/registration/views.py:335 +#: apps/registration/views.py:387 msgid "Invalidate pre-registration" msgstr "Ungültige Vorregistrierung" @@ -2080,7 +2183,7 @@ msgstr "Ungültige Vorregistrierung" msgid "Treasury" msgstr "Quaestor" -#: apps/treasury/forms.py:26 apps/treasury/models.py:90 +#: apps/treasury/forms.py:26 apps/treasury/models.py:93 #: apps/treasury/templates/treasury/invoice_form.html:22 msgid "This invoice is locked and can no longer be edited." msgstr "Diese Rechnung ist gesperrt und kann nicht mehr bearbeitet werden." @@ -2093,7 +2196,7 @@ msgstr "Überweisung ist bereits geschlossen." msgid "You can't change the type of the remittance." msgstr "Sie können die Art der Überweisung nicht ändern." -#: apps/treasury/forms.py:125 apps/treasury/models.py:264 +#: apps/treasury/forms.py:125 apps/treasury/models.py:267 #: apps/treasury/tables.py:97 apps/treasury/tables.py:105 #: apps/treasury/templates/treasury/invoice_list.html:16 #: apps/treasury/templates/treasury/remittance_list.html:16 @@ -2109,113 +2212,137 @@ msgstr "Keine beigefügte Überweisung" msgid "Invoice identifier" msgstr "Rechnungskennung" -#: apps/treasury/models.py:37 -#, fuzzy -#| msgid "BDE" -msgid "BD?" +#: apps/treasury/models.py:40 +msgid "BDE" msgstr "BDE" -#: apps/treasury/models.py:42 +#: apps/treasury/models.py:45 msgid "Object" msgstr "Objekt" -#: apps/treasury/models.py:46 +#: apps/treasury/models.py:49 msgid "Description" msgstr "Beschreibung" -#: apps/treasury/models.py:55 +#: apps/treasury/models.py:58 msgid "Address" msgstr "Adresse" -#: apps/treasury/models.py:60 apps/treasury/models.py:190 +#: apps/treasury/models.py:63 apps/treasury/models.py:193 msgid "Date" msgstr "Datum" -#: apps/treasury/models.py:64 +#: apps/treasury/models.py:67 msgid "Acquitted" msgstr "Bezahlt" -#: apps/treasury/models.py:69 +#: apps/treasury/models.py:72 msgid "Locked" msgstr "Gesperrt" -#: apps/treasury/models.py:70 +#: apps/treasury/models.py:73 msgid "An invoice can't be edited when it is locked." msgstr "Eine Rechnung kann nicht bearbeitet werden, wenn sie gesperrt ist." -#: apps/treasury/models.py:76 +#: apps/treasury/models.py:79 msgid "tex source" msgstr "Tex Quelle" -#: apps/treasury/models.py:110 apps/treasury/models.py:126 +#: apps/treasury/models.py:113 apps/treasury/models.py:129 msgid "invoice" msgstr "Rechnung" -#: apps/treasury/models.py:111 +#: apps/treasury/models.py:114 msgid "invoices" msgstr "Rechnungen" -#: apps/treasury/models.py:114 +#: apps/treasury/models.py:117 #, python-brace-format msgid "Invoice #{id}" msgstr "Rechnung #{id}" -#: apps/treasury/models.py:131 +#: apps/treasury/models.py:134 msgid "Designation" msgstr "Bezeichnung" -#: apps/treasury/models.py:137 +#: apps/treasury/models.py:140 msgid "Quantity" msgstr "Qualität" -#: apps/treasury/models.py:142 +#: apps/treasury/models.py:145 msgid "Unit price" msgstr "Einzelpreis" -#: apps/treasury/models.py:158 +#: apps/treasury/models.py:161 msgid "product" msgstr "Produkt" -#: apps/treasury/models.py:159 +#: apps/treasury/models.py:162 msgid "products" msgstr "Produkten" -#: apps/treasury/models.py:179 +#: apps/treasury/models.py:182 msgid "remittance type" msgstr "Überweisungstyp" -#: apps/treasury/models.py:180 +#: apps/treasury/models.py:183 msgid "remittance types" msgstr "Überweisungstypen" -#: apps/treasury/models.py:201 +#: apps/treasury/models.py:204 msgid "Comment" msgstr "Kommentar" -#: apps/treasury/models.py:206 +#: apps/treasury/models.py:209 msgid "Closed" msgstr "Geschlossen" -#: apps/treasury/models.py:210 +#: apps/treasury/models.py:213 msgid "remittance" msgstr "Überweisung" -#: apps/treasury/models.py:211 +#: apps/treasury/models.py:214 msgid "remittances" msgstr "Überweisungen" -#: apps/treasury/models.py:244 +#: apps/treasury/models.py:247 msgid "Remittance #{:d}: {}" msgstr "Überweisung #{:d}:{}" -#: apps/treasury/models.py:268 +#: apps/treasury/models.py:271 msgid "special transaction proxy" msgstr "spezielle Transaktion Proxy" -#: apps/treasury/models.py:269 +#: apps/treasury/models.py:272 msgid "special transaction proxies" msgstr "spezielle Transaktion Proxies" +#: apps/treasury/models.py:298 +msgid "credit transaction" +msgstr "Kredit Transaktion" + +#: apps/treasury/models.py:430 +msgid "" +"This user doesn't have enough money to pay the memberships with its note. " +"Please ask her/him to credit the note before invalidating this credit." +msgstr "" +"Dieser Benutzer hat nicht genug Geld, um die Mitgliedschaften mit seiner " +"Note zu bezahlen." + +#: apps/treasury/models.py:451 +#: apps/treasury/templates/treasury/sogecredit_detail.html:10 +msgid "Credit from the Société générale" +msgstr "Kredit von der Société générale" + +#: apps/treasury/models.py:452 +msgid "Credits from the Société générale" +msgstr "Krediten von der Société générale" + +#: apps/treasury/models.py:455 +#, python-brace-format +msgid "Soge credit for {user}" +msgstr "Kredit von der Société générale für {user}" + #: apps/treasury/tables.py:20 msgid "Invoice #{:d}" msgstr "Rechnung #{:d}" @@ -2235,6 +2362,10 @@ msgstr "Transaktionanzahl" msgid "View" msgstr "Schauen" +#: apps/treasury/tables.py:143 +msgid "Yes" +msgstr "Ja" + #: apps/treasury/templates/treasury/invoice_confirm_delete.html:10 #: apps/treasury/views.py:180 msgid "Delete invoice" @@ -2273,7 +2404,13 @@ msgstr "Produkt hinzufügen" msgid "Remove product" msgstr "Produkt entfernen" -#: apps/treasury/templates/treasury/invoice_list.html:28 +#: apps/treasury/templates/treasury/invoice_list.html:19 +#: apps/treasury/templates/treasury/remittance_list.html:19 +#: apps/treasury/templates/treasury/sogecredit_list.html:20 +msgid "Société générale credits" +msgstr "Krediten von der Société générale" + +#: apps/treasury/templates/treasury/invoice_list.html:31 msgid "New invoice" msgstr "Neue Rechnung" @@ -2293,47 +2430,43 @@ msgstr "Transaktionen" msgid "There is no transaction linked with this remittance." msgstr "Mit dieser Überweisung ist keine Transaktion verbunden." -#: apps/treasury/templates/treasury/remittance_list.html:24 +#: apps/treasury/templates/treasury/remittance_list.html:27 msgid "Opened remittances" msgstr "Geöffnete Überweisungen" -#: apps/treasury/templates/treasury/remittance_list.html:31 +#: apps/treasury/templates/treasury/remittance_list.html:34 msgid "There is no opened remittance." msgstr "Es gibt keine offene Überweisung." -#: apps/treasury/templates/treasury/remittance_list.html:36 +#: apps/treasury/templates/treasury/remittance_list.html:39 msgid "New remittance" msgstr "Neue Überweisung" -#: apps/treasury/templates/treasury/remittance_list.html:42 +#: apps/treasury/templates/treasury/remittance_list.html:45 msgid "Transfers without remittances" msgstr "Transfer ohne Überweisungen" -#: apps/treasury/templates/treasury/remittance_list.html:49 +#: apps/treasury/templates/treasury/remittance_list.html:52 msgid "There is no transaction without any linked remittance." msgstr "Mit dieser Überweisung ist keine Transaktion verbunden." -#: apps/treasury/templates/treasury/remittance_list.html:57 +#: apps/treasury/templates/treasury/remittance_list.html:60 msgid "Transfers with opened remittances" msgstr "Transfer mit geöffneten Überweisungen" -#: apps/treasury/templates/treasury/remittance_list.html:64 +#: apps/treasury/templates/treasury/remittance_list.html:67 msgid "There is no transaction with an opened linked remittance." msgstr "" "Es gibt keine Transaktion mit einer geöffneten verknüpften Überweisung." -#: apps/treasury/templates/treasury/remittance_list.html:72 +#: apps/treasury/templates/treasury/remittance_list.html:75 msgid "Closed remittances" msgstr "Geschlossene Überweisungen" -#: apps/treasury/templates/treasury/remittance_list.html:79 +#: apps/treasury/templates/treasury/remittance_list.html:82 msgid "There is no closed remittance yet." msgstr "Es gibt noch keine geschlossene Überweisung." -#: apps/treasury/templates/treasury/sogecredit_detail.html:10 -msgid "Credit from the Société générale" -msgstr "Kredit von der Société générale" - #: apps/treasury/templates/treasury/sogecredit_detail.html:35 msgid "total amount" msgstr "Totalanzahlt" @@ -2387,6 +2520,7 @@ msgstr "" "Kredit löschen." #: apps/treasury/templates/treasury/sogecredit_detail.html:63 +#: apps/wei/tables.py:60 apps/wei/tables.py:102 msgid "Validate" msgstr "Validieren" @@ -2394,10 +2528,6 @@ msgstr "Validieren" msgid "Return to credit list" msgstr "Zurück zur Kreditlist" -#: apps/treasury/templates/treasury/sogecredit_list.html:20 -msgid "Société générale credits" -msgstr "Krediten von der Société générale" - #: apps/treasury/templates/treasury/sogecredit_list.html:40 msgid "Filter with unvalidated credits only" msgstr "Filtern Sie nur mit nicht validierten Kredits" @@ -2429,6 +2559,7 @@ msgid "Invoices list" msgstr "Rechnunglist" #: apps/treasury/views.py:112 apps/treasury/views.py:286 +#: apps/treasury/views.py:412 msgid "You are not able to see the treasury interface." msgstr "Sie können die Quaestor-App nicht sehen." @@ -2452,1484 +2583,655 @@ msgstr "Überweisung bearbeiten" msgid "Attach a transaction to a remittance" msgstr "Fügen Sie einer Überweisung eine Transaktion hinzu" -#: env/lib/python3.11/site-packages/django/contrib/messages/apps.py:15 -msgid "Messages" +#: apps/treasury/views.py:404 +msgid "List of credits from the Société générale" +msgstr "Kreditliste von Société générale" + +#: apps/treasury/views.py:449 +msgid "Manage credits from the Société générale" +msgstr "Krediten von der Société générale handeln" + +#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51 +#: apps/wei/models.py:62 apps/wei/models.py:180 +#: note_kfet/templates/base.html:102 +msgid "WEI" +msgstr "WEI" + +#: apps/wei/forms/registration.py:35 +msgid "The selected user is not validated. Please validate its account first" msgstr "" -#: env/lib/python3.11/site-packages/django/contrib/sitemaps/apps.py:8 -msgid "Site Maps" -msgstr "" +#: apps/wei/forms/registration.py:59 apps/wei/models.py:126 +#: apps/wei/models.py:323 +msgid "bus" +msgstr "Bus" -#: env/lib/python3.11/site-packages/django/contrib/staticfiles/apps.py:9 -msgid "Static Files" -msgstr "" - -#: env/lib/python3.11/site-packages/django/contrib/syndication/apps.py:7 -#, fuzzy -#| msgid "Invitation" -msgid "Syndication" -msgstr "Einladung" - -#. Translators: String used to replace omitted page numbers in elided page -#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. -#: env/lib/python3.11/site-packages/django/core/paginator.py:30 -msgid "…" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:50 -msgid "That page number is not an integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:52 -msgid "That page number is less than 1" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:54 -#, fuzzy -#| msgid "There is no results." -msgid "That page contains no results" -msgstr "Es gibt keine Ergebnisse." - -#: env/lib/python3.11/site-packages/django/core/validators.py:22 -msgid "Enter a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:104 -#: env/lib/python3.11/site-packages/django/forms/fields.py:752 -msgid "Enter a valid URL." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:165 -msgid "Enter a valid integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:176 -msgid "Enter a valid email address." -msgstr "" - -#. Translators: "letters" means latin letters: a-z and A-Z. -#: env/lib/python3.11/site-packages/django/core/validators.py:259 +#: apps/wei/forms/registration.py:60 msgid "" -"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +"This choice is not definitive. The WEI organizers are free to attribute for " +"you a bus and a team, in particular if you are a free eletron." msgstr "" +"Diese Wahl ist nicht endgültig. Den WEI-Organisatoren steht es frei, Ihnen " +"einen Bus und ein Team zuzuweisen, insbesondere wenn Sie ein freies Elektron " +"sind." -#: env/lib/python3.11/site-packages/django/core/validators.py:267 +#: apps/wei/forms/registration.py:67 +msgid "Team" +msgstr "Team" + +#: apps/wei/forms/registration.py:69 msgid "" -"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " -"hyphens." +"Leave this field empty if you won't be in a team (staff, bus chief, free " +"electron)" msgstr "" +"Lassen Sie dieses Feld leer, wenn Sie nicht in einem Team sind (Mitarbeiter, " +"Buschef, freies Elektron)" -#: env/lib/python3.11/site-packages/django/core/validators.py:279 -#: env/lib/python3.11/site-packages/django/core/validators.py:287 -#: env/lib/python3.11/site-packages/django/core/validators.py:316 -msgid "Enter a valid IPv4 address." -msgstr "" +#: apps/wei/forms/registration.py:75 apps/wei/forms/registration.py:85 +#: apps/wei/models.py:161 +msgid "WEI Roles" +msgstr "WEI Rollen" -#: env/lib/python3.11/site-packages/django/core/validators.py:296 -#: env/lib/python3.11/site-packages/django/core/validators.py:317 -msgid "Enter a valid IPv6 address." -msgstr "" +#: apps/wei/forms/registration.py:76 +msgid "Select the roles that you are interested in." +msgstr "Wählen Sie die Rollen aus, an denen Sie interessiert sind." -#: env/lib/python3.11/site-packages/django/core/validators.py:308 -#: env/lib/python3.11/site-packages/django/core/validators.py:315 -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "" +#: apps/wei/forms/registration.py:122 +msgid "This team doesn't belong to the given bus." +msgstr "Dieses Team gehört nicht zum angegebenen Bus." -#: env/lib/python3.11/site-packages/django/core/validators.py:351 -msgid "Enter only digits separated by commas." -msgstr "" +#: apps/wei/forms/surveys/wei2021.py:35 apps/wei/forms/surveys/wei2022.py:35 +msgid "Choose a word:" +msgstr "Wählen Sie ein Wort:" -#: env/lib/python3.11/site-packages/django/core/validators.py:357 -#, python-format -msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "" +#: apps/wei/models.py:25 apps/wei/templates/wei/base.html:36 +msgid "year" +msgstr "Jahr" -#: env/lib/python3.11/site-packages/django/core/validators.py:392 -#, python-format -msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:29 apps/wei/templates/wei/base.html:30 +msgid "date start" +msgstr "Anfangsdatum" -#: env/lib/python3.11/site-packages/django/core/validators.py:401 -#, python-format -msgid "Ensure this value is greater than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:33 apps/wei/templates/wei/base.html:33 +msgid "date end" +msgstr "Abschlussdatum" -#: env/lib/python3.11/site-packages/django/core/validators.py:410 -#, python-format -msgid "Ensure this value is a multiple of step size %(limit_value)s." -msgstr "" +#: apps/wei/models.py:71 apps/wei/tables.py:305 +#, fuzzy +#| msgid "The user joined the bus" +msgid "seat count in the bus" +msgstr "Der Benutzer ist dem Bus beigetreten" -#: env/lib/python3.11/site-packages/django/core/validators.py:420 -#, python-format +#: apps/wei/models.py:83 +msgid "survey information" +msgstr "Umfrage Infos" + +#: apps/wei/models.py:84 +msgid "Information about the survey for new members, encoded in JSON" +msgstr "Informationen zur Umfrage für neue Mitglieder, codiert in JSON" + +#: apps/wei/models.py:113 +msgid "Bus" +msgstr "Bus" + +#: apps/wei/models.py:114 apps/wei/templates/wei/weiclub_detail.html:51 +msgid "Buses" +msgstr "Buses" + +#: apps/wei/models.py:135 +msgid "color" +msgstr "Farbe" + +#: apps/wei/models.py:136 +msgid "The color of the T-Shirt, stored with its number equivalent" +msgstr "Die Farbe des T-Shirts, gespeichert mit der entsprechenden Nummer" + +#: apps/wei/models.py:150 +msgid "Bus team" +msgstr "Bus Team" + +#: apps/wei/models.py:151 +msgid "Bus teams" +msgstr "Bus Teams" + +#: apps/wei/models.py:160 +msgid "WEI Role" +msgstr "WEI Rolle" + +#: apps/wei/models.py:185 +msgid "Credit from Société générale" +msgstr "Kredit von der Société générale" + +#: apps/wei/models.py:190 +msgid "Caution check given" +msgstr "Caution check given" + +#: apps/wei/models.py:194 apps/wei/templates/wei/weimembership_form.html:64 +msgid "birth date" +msgstr "Geburtsdatum" + +#: apps/wei/models.py:200 apps/wei/models.py:210 +msgid "Male" +msgstr "Männlich" + +#: apps/wei/models.py:201 apps/wei/models.py:211 +msgid "Female" +msgstr "Weiblich" + +#: apps/wei/models.py:202 +msgid "Non binary" +msgstr "Nicht binär" + +#: apps/wei/models.py:204 apps/wei/templates/wei/attribute_bus_1A.html:22 +#: apps/wei/templates/wei/weimembership_form.html:55 +msgid "gender" +msgstr "Geschlecht" + +#: apps/wei/models.py:213 apps/wei/templates/wei/weimembership_form.html:58 +msgid "clothing cut" +msgstr "Kleidung Schnitt" + +#: apps/wei/models.py:226 apps/wei/templates/wei/weimembership_form.html:61 +msgid "clothing size" +msgstr "Kleidergröße" + +#: apps/wei/models.py:232 apps/wei/templates/wei/attribute_bus_1A.html:28 +#: apps/wei/templates/wei/weimembership_form.html:67 +msgid "health issues" +msgstr "Gesundheitsprobleme" + +#: apps/wei/models.py:237 apps/wei/templates/wei/weimembership_form.html:70 +msgid "emergency contact name" +msgstr "Notfall-Kontakt" + +#: apps/wei/models.py:242 apps/wei/templates/wei/weimembership_form.html:73 +msgid "emergency contact phone" +msgstr "Notfallkontakttelefon" + +#: apps/wei/models.py:247 apps/wei/templates/wei/weimembership_form.html:52 +msgid "first year" +msgstr "Erste Jahr" + +#: apps/wei/models.py:248 +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:253 +msgid "registration information" +msgstr "Registrierung Detailen" + +#: apps/wei/models.py:254 msgid "" -"Ensure this value has at least %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at least %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" +"Information about the registration (buses for old members, survey for the " +"new members), encoded in JSON" +msgstr "" +"Informationen zur Registrierung (Busse für alte Mitglieder, Umfrage für neue " +"Mitglieder), verschlüsselt in JSON" -#: env/lib/python3.11/site-packages/django/core/validators.py:438 -#, python-format +#: apps/wei/models.py:312 +msgid "WEI User" +msgstr "WEI User" + +#: apps/wei/models.py:313 +msgid "WEI Users" +msgstr "WEI Users" + +#: apps/wei/models.py:333 +msgid "team" +msgstr "Team" + +#: apps/wei/models.py:343 +msgid "WEI registration" +msgstr "WEI Registrierung" + +#: apps/wei/models.py:347 +msgid "WEI membership" +msgstr "WEI Mitgliedschaft" + +#: apps/wei/models.py:348 +msgid "WEI memberships" +msgstr "WEI Mitgliedschaften" + +#: apps/wei/tables.py:105 +msgid "The user does not have enough money." +msgstr "" + +#: apps/wei/tables.py:108 msgid "" -"Ensure this value has at most %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at most %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:461 -#: env/lib/python3.11/site-packages/django/forms/fields.py:347 -#: env/lib/python3.11/site-packages/django/forms/fields.py:386 -#, fuzzy -#| msgid "phone number" -msgid "Enter a number." -msgstr "Telefonnummer" - -#: env/lib/python3.11/site-packages/django/core/validators.py:463 -#, python-format -msgid "Ensure that there are no more than %(max)s digit in total." -msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:468 -#, python-format -msgid "Ensure that there are no more than %(max)s decimal place." -msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:473 -#, python-format -msgid "" -"Ensure that there are no more than %(max)s digit before the decimal point." -msgid_plural "" -"Ensure that there are no more than %(max)s digits before the decimal point." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:544 -#, python-format -msgid "" -"File extension “%(extension)s” is not allowed. Allowed extensions are: " -"%(allowed_extensions)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:605 -msgid "Null characters are not allowed." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1423 -#: env/lib/python3.11/site-packages/django/forms/models.py:893 -#, fuzzy -#| msgid "add" -msgid "and" -msgstr "hinzufügen" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1425 -#, fuzzy, python-format -#| msgid "A template with this name already exist" -msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "Eine Vorlage mit diesem Namen ist bereits vorhanden" - -#: env/lib/python3.11/site-packages/django/db/models/constraints.py:17 -#, python-format -msgid "Constraint “%(name)s” is violated." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:128 -#, python-format -msgid "Value %(value)r is not a valid choice." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:129 -#, fuzzy -#| msgid "This image cannot be loaded." -msgid "This field cannot be null." -msgstr "Dieses Bild kann nicht geladen werden." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:130 -#, fuzzy -#| msgid "This image cannot be loaded." -msgid "This field cannot be blank." -msgstr "Dieses Bild kann nicht geladen werden." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:131 -#, fuzzy, python-format -#| msgid "A template with this name already exist" -msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "Eine Vorlage mit diesem Namen ist bereits vorhanden" - -#. Translators: The 'lookup_type' is one of 'date', 'year' or -#. 'month'. Eg: "Title must be unique for pub_date year" -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:135 -#, python-format -msgid "" -"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:173 -#, python-format -msgid "Field of type: %(field_type)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1094 -#, python-format -msgid "“%(value)s” value must be either True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1095 -#, python-format -msgid "“%(value)s” value must be either True, False, or None." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1097 -msgid "Boolean (Either True or False)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1147 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1149 -msgid "String (unlimited)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1253 -msgid "Comma-separated integers" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1354 -#, python-format -msgid "" -"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1358 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1493 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " -"date." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1362 -msgid "Date (without time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1489 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." -"uuuuuu]][TZ] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1497 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" -"[TZ]) but it is an invalid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1502 -msgid "Date (with time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1626 -#, python-format -msgid "“%(value)s” value must be a decimal number." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1628 -#, fuzzy -#| msgid "phone number" -msgid "Decimal number" -msgstr "Telefonnummer" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1789 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." -"uuuuuu] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1793 -#, fuzzy -#| msgid "action" -msgid "Duration" -msgstr "Aktion" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1845 -#, fuzzy -#| msgid "address" -msgid "Email address" -msgstr "Adresse" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1870 -msgid "File path" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1948 -#, python-format -msgid "“%(value)s” value must be a float." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1950 -#, fuzzy -#| msgid "phone number" -msgid "Floating point number" -msgstr "Telefonnummer" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1990 -#, python-format -msgid "“%(value)s” value must be an integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1992 -msgid "Integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2088 -msgid "Big (8 byte) integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2105 -msgid "Small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2113 -#, fuzzy -#| msgid "IP Address" -msgid "IPv4 address" -msgstr "IP Adresse" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2144 -#, fuzzy -#| msgid "IP Address" -msgid "IP address" -msgstr "IP Adresse" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2237 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2238 -#, python-format -msgid "“%(value)s” value must be either None, True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2240 -msgid "Boolean (Either True, False or None)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2291 -msgid "Positive big integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2306 -msgid "Positive integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2321 -msgid "Positive small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2337 -#, python-format -msgid "Slug (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2373 -msgid "Text" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2448 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2452 -#, python-format -msgid "" -"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " -"invalid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2456 -msgid "Time" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2564 -msgid "URL" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2588 -msgid "Raw binary data" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2653 -#, python-format -msgid "“%(value)s” is not a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2655 -#, fuzzy -#| msgid "Invoice identifier" -msgid "Universally unique identifier" -msgstr "Rechnungskennung" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:232 -msgid "File" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:393 -msgid "Image" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:26 -#, fuzzy -#| msgid "Object" -msgid "A JSON object" -msgstr "Objekt" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:28 -#, fuzzy -#| msgid "This address must be valid." -msgid "Value must be valid JSON." -msgstr "Diese Adresse muss gültig sein." - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:919 -#, python-format -msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:921 -msgid "Foreign Key (type determined by related field)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1212 -msgid "One-to-one relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1269 -#, python-format -msgid "%(from)s-%(to)s relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1271 -#, python-format -msgid "%(from)s-%(to)s relationships" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1319 -msgid "Many-to-many relationship" -msgstr "" - -#. Translators: If found as last label character, these punctuation -#. characters will prevent the default label_suffix to be appended to the label -#: env/lib/python3.11/site-packages/django/forms/boundfield.py:184 -msgid ":?.!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:298 -#, fuzzy -#| msgid "phone number" -msgid "Enter a whole number." -msgstr "Telefonnummer" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:467 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1241 -msgid "Enter a valid date." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:490 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1242 -msgid "Enter a valid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:517 -msgid "Enter a valid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:551 -#, fuzzy -#| msgid "Email validation" -msgid "Enter a valid duration." -msgstr "Email validierung" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:552 -#, python-brace-format -msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:621 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:622 -msgid "No file was submitted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:623 -msgid "The submitted file is empty." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:625 -#, python-format -msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." -msgid_plural "" -"Ensure this filename has at most %(max)d characters (it has %(length)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:630 -msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:694 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:857 -#: env/lib/python3.11/site-packages/django/forms/fields.py:949 -#: env/lib/python3.11/site-packages/django/forms/models.py:1566 -#, python-format -msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:951 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1070 -#: env/lib/python3.11/site-packages/django/forms/models.py:1564 -msgid "Enter a list of values." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1071 -msgid "Enter a complete value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1310 -msgid "Enter a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1340 -msgid "Enter a valid JSON." -msgstr "" - -#. Translators: This is the default suffix added to form field labels -#: env/lib/python3.11/site-packages/django/forms/forms.py:98 -msgid ":" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/forms.py:244 -#: env/lib/python3.11/site-packages/django/forms/forms.py:328 -#, python-format -msgid "(Hidden field %(name)s) %(error)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:63 -#, python-format -msgid "" -"ManagementForm data is missing or has been tampered with. Missing fields: " -"%(field_names)s. You may need to file a bug report if the issue persists." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:67 -#, python-format -msgid "Please submit at most %(num)d form." -msgid_plural "Please submit at most %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:72 -#, python-format -msgid "Please submit at least %(num)d form." -msgid_plural "Please submit at least %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:484 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:491 -msgid "Order" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:886 -#, python-format -msgid "Please correct the duplicate data for %(field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:891 -#, python-format -msgid "Please correct the duplicate data for %(field)s, which must be unique." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:898 -#, python-format -msgid "" -"Please correct the duplicate data for %(field_name)s which must be unique " -"for the %(lookup)s in %(date_field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:907 -msgid "Please correct the duplicate values below." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1338 -msgid "The inline value did not match the parent instance." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1429 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1568 -#, python-format -msgid "“%(pk)s” is not a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/utils.py:226 -#, python-format -msgid "" -"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " -"may be ambiguous or it may not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:463 -msgid "Clear" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:464 -#, fuzzy -#| msgid "Current activity" -msgid "Currently" -msgstr "Aktuelle Veranstaltung" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:465 -#, fuzzy -#| msgid "change" -msgid "Change" -msgstr "bearbeiten" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:794 -msgid "Unknown" -msgstr "" - -#. Translators: Please do not add spaces around commas. -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:861 -msgid "yes,no,maybe" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:891 -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:908 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:910 -#, python-format -msgid "%s KB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:912 -#, python-format -msgid "%s MB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:914 -#, python-format -msgid "%s GB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:916 -#, python-format -msgid "%s TB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:918 -#, python-format -msgid "%s PB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:73 -msgid "p.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:74 -msgid "a.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:79 -msgid "PM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:80 -msgid "AM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:152 -msgid "midnight" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:154 -msgid "noon" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:7 -msgid "Monday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:8 -msgid "Tuesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:9 -msgid "Wednesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:10 -msgid "Thursday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:11 -msgid "Friday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:12 -msgid "Saturday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:13 -msgid "Sunday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:16 -msgid "Mon" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:17 -msgid "Tue" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:18 -msgid "Wed" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:19 -msgid "Thu" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:20 -msgid "Fri" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:21 -msgid "Sat" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:22 -msgid "Sun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:25 -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:26 -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:27 -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:28 -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:29 -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:30 -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:31 -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:32 -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:33 -#, fuzzy -#| msgid "member" -msgid "September" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:34 -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:35 -#, fuzzy -#| msgid "member" -msgid "November" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:36 -#, fuzzy -#| msgid "member" -msgid "December" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:39 -msgid "jan" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:40 -#, fuzzy -#| msgid "fee" -msgid "feb" -msgstr "Preis" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:41 -msgid "mar" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:42 -msgid "apr" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:43 -msgid "may" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:44 -msgid "jun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:45 -msgid "jul" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:46 -msgid "aug" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:47 -msgid "sep" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:48 -#, fuzzy -#| msgid "product" -msgid "oct" -msgstr "Produkt" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:49 -msgid "nov" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:50 -msgid "dec" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:53 -msgctxt "abbrev. month" -msgid "Jan." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:54 -msgctxt "abbrev. month" -msgid "Feb." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:55 -msgctxt "abbrev. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:56 -msgctxt "abbrev. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:57 -msgctxt "abbrev. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:58 -msgctxt "abbrev. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:59 -msgctxt "abbrev. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:60 -msgctxt "abbrev. month" -msgid "Aug." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:61 -msgctxt "abbrev. month" -msgid "Sept." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:62 -msgctxt "abbrev. month" -msgid "Oct." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:63 -msgctxt "abbrev. month" -msgid "Nov." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:64 -msgctxt "abbrev. month" -msgid "Dec." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:67 -msgctxt "alt. month" -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:68 -msgctxt "alt. month" -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:69 -msgctxt "alt. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:70 -msgctxt "alt. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:71 -msgctxt "alt. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:72 -msgctxt "alt. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:73 -msgctxt "alt. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:74 -msgctxt "alt. month" -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:75 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "September" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:76 -msgctxt "alt. month" -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:77 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "November" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:78 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "December" -msgstr "Mitglied" - -#: env/lib/python3.11/site-packages/django/utils/ipv6.py:8 -#, fuzzy -#| msgid "This activity is not validated yet." -msgid "This is not a valid IPv6 address." -msgstr "Diese Veranstaltung ist noch nicht bestätigt." - -#: env/lib/python3.11/site-packages/django/utils/text.py:84 -#, python-format -msgctxt "String to return when truncating text" -msgid "%(truncated_text)s…" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/text.py:269 -msgid "or" -msgstr "" - -#. Translators: This string is used as a separator between list elements -#: env/lib/python3.11/site-packages/django/utils/text.py:288 -#: env/lib/python3.11/site-packages/django/utils/timesince.py:135 -msgid ", " -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:8 -#, python-format -msgid "%(num)d year" -msgid_plural "%(num)d years" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:9 -#, python-format -msgid "%(num)d month" -msgid_plural "%(num)d months" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:10 -#, python-format -msgid "%(num)d week" -msgid_plural "%(num)d weeks" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:11 -#, python-format -msgid "%(num)d day" -msgid_plural "%(num)d days" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:12 -#, python-format -msgid "%(num)d hour" -msgid_plural "%(num)d hours" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:13 -#, python-format -msgid "%(num)d minute" -msgid_plural "%(num)d minutes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:111 -msgid "Forbidden" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:112 -msgid "CSRF verification failed. Request aborted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:116 -msgid "" -"You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your web browser, but none was sent. This header is " -"required for security reasons, to ensure that your browser is not being " -"hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:122 -msgid "" -"If you have configured your browser to disable “Referer” headers, please re-" -"enable them, at least for this site, or for HTTPS connections, or for “same-" -"origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:127 -msgid "" -"If you are using the tag or " -"including the “Referrer-Policy: no-referrer” header, please remove them. The " -"CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:136 -msgid "" -"You are seeing this message because this site requires a CSRF cookie when " -"submitting forms. This cookie is required for security reasons, to ensure " -"that your browser is not being hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:142 -msgid "" -"If you have configured your browser to disable cookies, please re-enable " -"them, at least for this site, or for “same-origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:148 -msgid "More information is available with DEBUG=True." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:44 -#, fuzzy -#| msgid "No reason specified" -msgid "No year specified" -msgstr "Kein Grund gegeben" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:64 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:115 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:214 -msgid "Date out of range" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:94 -#, fuzzy -#| msgid "No reason specified" -msgid "No month specified" -msgstr "Kein Grund gegeben" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:147 -#, fuzzy -#| msgid "No reason specified" -msgid "No day specified" -msgstr "Kein Grund gegeben" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:194 -#, fuzzy -#| msgid "No reason specified" -msgid "No week specified" -msgstr "Kein Grund gegeben" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:349 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:380 -#, python-format -msgid "No %(verbose_name_plural)s available" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:652 -#, python-format -msgid "" -"Future %(verbose_name_plural)s not available because %(class_name)s." -"allow_future is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:692 -#, python-format -msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/detail.py:56 -#, python-format -msgid "No %(verbose_name)s found matching the query" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:70 -msgid "Page is not “last”, nor can it be converted to an int." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:77 -#, python-format -msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:169 -#, python-format -msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:38 -msgid "Directory indexes are not allowed here." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:40 -#, python-format -msgid "“%(path)s” does not exist" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:79 -#, python-format -msgid "Index of %(directory)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:7 -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:220 -msgid "The install worked successfully! Congratulations!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:206 -#, python-format -msgid "" -"View release notes for Django %(version)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:221 -#, python-format -msgid "" -"You are seeing this page because DEBUG=True is in your settings file and you have not " -"configured any URLs." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:229 -msgid "Django Documentation" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:230 -msgid "Topics, references, & how-to’s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:238 -msgid "Tutorial: A Polling App" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:239 -msgid "Get started with Django" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:247 -msgid "Django Community" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:248 -msgid "Connect, get help, or contribute" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:69 -msgid "Confidential" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:70 -msgid "Public" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:79 -msgid "Authorization code" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:80 -msgid "Implicit" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:81 -#, fuzzy -#| msgid "Reset my password" -msgid "Resource owner password-based" -msgstr "Mein Passwort zurücksetzen" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:82 -msgid "Client credentials" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:83 -msgid "OpenID connect hybrid" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:90 -msgid "No OIDC support" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:91 -msgid "RSA with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:92 -msgid "HMAC with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:107 -msgid "Allowed URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:111 -msgid "Allowed Post Logout URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:120 -msgid "Hashed on Save. Copy it now if this is a new secret." -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:190 -#, python-brace-format -msgid "Unauthorized redirect scheme: {scheme}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:194 -#, python-brace-format -msgid "redirect_uris cannot be empty with grant_type {grant_type}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:200 -msgid "You must set OIDC_RSA_PRIVATE_KEY to use RSA algorithm" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:209 -msgid "You cannot use HS256 with public grants or clients" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:211 -#, fuzzy -#| msgid "This address must be valid." -msgid "The access token is invalid." -msgstr "Diese Adresse muss gültig sein." - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:218 -msgid "The access token has expired." -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:225 -msgid "The access token is valid but does not have enough scope." +"The user is in first year. You may validate the credit, the algorithm will " +"run later." msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:6 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 +#: apps/wei/tables.py:111 #, fuzzy #| msgid "" -#| "Are you sure you want to delete this invoice? This action can't be undone." -msgid "Are you sure to delete the application" +#| "The note has enough money (%(pretty_fee)s required), the registration is " +#| "possible." +msgid "The user has enough money, you can validate the registration." msgstr "" -"Möchten Sie diese Rechnung wirklich löschen? Diese Aktion kann nicht " -"rückgängig gemacht werden." +"Die Note hat genug Geld (%(pretty_fee)s erforderlich), die Registrierung ist " +"möglich." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:12 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:29 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 -#: note_kfet/templates/oauth2_provider/authorize.html:28 +#: apps/wei/tables.py:143 +msgid "Year" +msgstr "Jahr" + +#: apps/wei/tables.py:180 apps/wei/templates/wei/weimembership_form.html:102 +msgid "preferred bus" +msgstr "bevorzugter Bus" + +#: apps/wei/tables.py:210 apps/wei/templates/wei/bus_detail.html:32 +#: apps/wei/templates/wei/busteam_detail.html:50 +msgid "Teams" +msgstr "Teams" + +#: apps/wei/tables.py:219 apps/wei/tables.py:260 +msgid "Members count" +msgstr "Anzahl Mitgliedern" + +#: apps/wei/tables.py:226 apps/wei/tables.py:257 +msgid "members" +msgstr "Mitglieder" + +#: apps/wei/tables.py:287 #, fuzzy -#| msgid "Balance" -msgid "Cancel" -msgstr "Kontostand" +#| msgid "first year" +msgid "suggested first year" +msgstr "Erste Jahr" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:10 -#: note_kfet/templates/oauth2_provider/application_detail.html:11 -msgid "Client id" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:15 -#: note_kfet/templates/oauth2_provider/application_detail.html:14 -msgid "Client secret" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:20 -#: note_kfet/templates/oauth2_provider/application_detail.html:17 +#: apps/wei/tables.py:293 #, fuzzy -#| msgid "Credit type" -msgid "Client type" -msgstr "Kredittype" +#| msgid "first year" +msgid "validated first year" +msgstr "Erste Jahr" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:25 -#: note_kfet/templates/oauth2_provider/application_detail.html:20 -msgid "Authorization Grant Type" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:30 -#: note_kfet/templates/oauth2_provider/application_detail.html:23 -msgid "Redirect Uris" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:36 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:35 -#: note_kfet/templates/oauth2_provider/application_detail.html:37 -#: note_kfet/templates/oauth2_provider/application_form.html:23 -msgid "Go Back" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:9 -#: note_kfet/templates/oauth2_provider/application_form.html:12 +#: apps/wei/tables.py:299 #, fuzzy -#| msgid "Email validation" -msgid "Edit application" -msgstr "Email validierung" +#| msgid "Unvalidated registrations" +msgid "validated staff" +msgstr "Unvalidierte Registrierungen" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:37 -msgid "Save" +#: apps/wei/tables.py:310 +msgid "free seats" msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:6 -#: note_kfet/templates/oauth2_provider/application_list.html:7 -msgid "Your applications" +#: apps/wei/templates/wei/1A_list.html:9 +msgid "Attribute first year members into buses" msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:14 -#: note_kfet/templates/oauth2_provider/application_list.html:30 +#: apps/wei/templates/wei/1A_list.html:15 +msgid "Start attribution!" +msgstr "" + +#: apps/wei/templates/wei/attribute_bus_1A.html:8 +msgid "Bus attribution" +msgstr "" + +#: apps/wei/templates/wei/attribute_bus_1A.html:31 +msgid "suggested bus" +msgstr "" + +#: apps/wei/templates/wei/attribute_bus_1A.html:37 #, fuzzy -#| msgid "location" -msgid "New Application" -msgstr "Ort" +#| msgid "Raw survey information" +msgid "View raw survey information" +msgstr "Rohe Umfrageinformationen" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_registration_form.html:5 -#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 +#: apps/wei/templates/wei/attribute_bus_1A.html:57 #, fuzzy -#| msgid "Registrations" -msgid "Register a new application" -msgstr "Anmeldung" +#| msgid "Buttons list" +msgid "Back to main list" +msgstr "Tastenliste" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:8 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:30 -#: note_kfet/templates/oauth2_provider/authorize.html:9 -#: note_kfet/templates/oauth2_provider/authorize.html:29 -msgid "Authorize" +#: apps/wei/templates/wei/base.html:44 +msgid "WEI fee (paid students)" +msgstr "WEI Preis (bezahlte Studenten)" + +#: apps/wei/templates/wei/base.html:47 apps/wei/templates/wei/base.html:54 +msgid "The BDE membership is included in the WEI registration." +msgstr "Die BDE-Mitgliedschaft ist in der WEI-Registrierung enthalten." + +#: apps/wei/templates/wei/base.html:51 +msgid "WEI fee (unpaid students)" +msgstr "WEI Preis (unbezahlte Studenten)" + +#: apps/wei/templates/wei/base.html:76 +msgid "WEI list" +msgstr "WEI Liste" + +#: apps/wei/templates/wei/base.html:81 apps/wei/views.py:528 +msgid "Register 1A" +msgstr "1A Registrieren" + +#: apps/wei/templates/wei/base.html:85 apps/wei/views.py:614 +msgid "Register 2A+" +msgstr "2A+ Registrieren" + +#: apps/wei/templates/wei/base.html:93 +msgid "Add bus" +msgstr "Neue Bus" + +#: apps/wei/templates/wei/base.html:97 +msgid "View WEI" +msgstr "WEI schauen" + +#: apps/wei/templates/wei/bus_detail.html:22 +#: apps/wei/templates/wei/busteam_detail.html:22 +msgid "Add team" +msgstr "Neue Team" + +#: apps/wei/templates/wei/bus_detail.html:45 +msgid "Members" +msgstr "Mitglied" + +#: apps/wei/templates/wei/bus_detail.html:54 +#: apps/wei/templates/wei/busteam_detail.html:60 +#: apps/wei/templates/wei/weimembership_list.html:31 +msgid "View as PDF" +msgstr "Als PDF schauen" + +#: apps/wei/templates/wei/survey.html:11 +#: apps/wei/templates/wei/survey_closed.html:11 +#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1028 +#: apps/wei/views.py:1083 apps/wei/views.py:1093 +msgid "Survey WEI" +msgstr "WEI Umfrage" + +#: apps/wei/templates/wei/survey.html:23 +msgid "Next" +msgstr "Weiter" + +#: apps/wei/templates/wei/survey_closed.html:15 +msgid "The inscription for this WEI are now closed." +msgstr "Die Inschrift für diese WEI ist nun geschlossen." + +#: apps/wei/templates/wei/survey_closed.html:19 +msgid "Return to WEI detail" +msgstr "Zurück zur WEI Detaillen" + +#: apps/wei/templates/wei/survey_end.html:15 +msgid "The survey is now ended. Your answers have been saved." +msgstr "Die Umfrage ist nun beendet. Ihre Antworten wurden gespeichert." + +#: apps/wei/templates/wei/weiclub_detail.html:32 +msgid "Register to the WEI! – 1A" +msgstr "1A Registrieren" + +#: apps/wei/templates/wei/weiclub_detail.html:36 +msgid "Register to the WEI! – 2A+" +msgstr "2A+ Registrieren" + +#: apps/wei/templates/wei/weiclub_detail.html:40 +msgid "Update my registration" +msgstr "Meine Registrierung bearbeiten" + +#: apps/wei/templates/wei/weiclub_detail.html:63 +msgid "Members of the WEI" +msgstr "Mitglied der WEI" + +#: apps/wei/templates/wei/weiclub_detail.html:89 +msgid "Unvalidated registrations" +msgstr "Unvalidierte Registrierungen" + +#: apps/wei/templates/wei/weiclub_detail.html:99 +msgid "Attribute buses" msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:17 -msgid "Application requires the following permissions" +#: apps/wei/templates/wei/weiclub_list.html:14 apps/wei/views.py:79 +msgid "Create WEI" +msgstr "Neue WEI" + +#: apps/wei/templates/wei/weiclub_list.html:22 +msgid "WEI listing" +msgstr "WEI List" + +#: apps/wei/templates/wei/weimembership_form.html:10 +msgid "Review registration" +msgstr "Registrierung schauen" + +#: apps/wei/templates/wei/weimembership_form.html:35 +msgid "ENS year" +msgstr "ENS Jahr" + +#: apps/wei/templates/wei/weimembership_form.html:76 +msgid "Payment from Société générale" +msgstr "Kredit von der Société générale" + +#: apps/wei/templates/wei/weimembership_form.html:80 +msgid "Suggested bus from the survey:" +msgstr "Vorgeschlagener Bus aus der Umfrage:" + +#: apps/wei/templates/wei/weimembership_form.html:85 +msgid "Raw survey information" +msgstr "Rohe Umfrageinformationen" + +#: apps/wei/templates/wei/weimembership_form.html:95 +msgid "The algorithm didn't run." +msgstr "Der Algorithmus wurde nicht ausgeführt." + +#: apps/wei/templates/wei/weimembership_form.html:98 +msgid "caution check given" +msgstr "Vorsichtsprüfung gegeben" + +#: apps/wei/templates/wei/weimembership_form.html:105 +msgid "preferred team" +msgstr "bevorzugtes Team" + +#: apps/wei/templates/wei/weimembership_form.html:108 +msgid "preferred roles" +msgstr "bevorzugte Rollen" + +#: apps/wei/templates/wei/weimembership_form.html:115 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:30 +msgid "Update registration" +msgstr "Registrierung aktualisieren" + +#: apps/wei/templates/wei/weimembership_form.html:131 +msgid "The registration is already validated and can't be unvalidated." +msgstr "" +"Die Registrierung ist bereits validiert und kann nicht ungültig gemacht " +"werden." + +#: apps/wei/templates/wei/weimembership_form.html:132 +msgid "The user joined the bus" +msgstr "Der Benutzer ist dem Bus beigetreten" + +#: apps/wei/templates/wei/weimembership_form.html:133 +msgid "in the team" +msgstr "In der Team" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "in no team (staff)" +msgstr "In keinem Team (staff)" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "with the following roles:" +msgstr "mit den folgenden Rollen:" + +#: apps/wei/templates/wei/weimembership_form.html:139 +msgid "" +"The WEI will be paid by Société générale. The membership will be created " +"even if the bank didn't pay the BDE yet. The membership transaction will be " +"created but will be invalid. You will have to validate it once the bank " +"validated the creation of the account, or to change the payment method." +msgstr "" +"Das WEI wird von der Société générale bezahlt. Die Mitgliedschaft wird auch " +"dann erstellt, wenn die Bank die BDE noch nicht bezahlt hat. Die " +"Mitgliedschaftstransaktion wird erstellt, ist jedoch ungültig. Sie müssen es " +"validieren, sobald die Bank die Erstellung des Kontos validiert hat, oder " +"die Zahlungsmethode ändern." + +#: apps/wei/templates/wei/weimembership_form.html:149 +#, python-format +msgid "" +"The note don't have enough money (%(balance)s, %(pretty_fee)s required). The " +"registration may fail if you don't credit the note now." +msgstr "" +"Die Note hat nicht genug Geld (%(balance)s,%(pretty_fee)s erforderlich). Die " +"Registrierung kann fehlschlagen, wenn Sie die Note jetzt nicht gutschreiben." + +#: apps/wei/templates/wei/weimembership_form.html:157 +#, python-format +msgid "" +"The note has enough money (%(pretty_fee)s required), the registration is " +"possible." +msgstr "" +"Die Note hat genug Geld (%(pretty_fee)s erforderlich), die Registrierung ist " +"möglich." + +#: apps/wei/templates/wei/weimembership_form.html:166 +msgid "The user didn't give her/his caution check." +msgstr "Der User hat nicht sein Vorsichtsprüfung gegeben." + +#: apps/wei/templates/wei/weimembership_form.html:174 +msgid "" +"This user is not a member of the Kfet club for the coming year. The " +"membership will be processed automatically, the WEI registration includes " +"the membership fee." +msgstr "" +"Dieser Benutzer ist für das kommende Jahr kein Mitglied des Kfet-Clubs. Die " +"Mitgliedschaft wird automatisch bearbeitet, die WEI-Registrierung beinhaltet " +"den Mitgliedsbeitrag." + +#: apps/wei/templates/wei/weimembership_list.html:27 +msgid "View unvalidated registrations..." +msgstr "Nicht validierte Registrierungen anzeigen ..." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:16 +msgid "This registration is already validated and can't be deleted." +msgstr "" +"Diese Registrierung ist bereits validiert und kann nicht gelöscht werden." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:23 +#, python-format +msgid "" +"Are you sure you want to delete the registration of %(user)s for the WEI " +"%(wei_name)s? This action can't be undone." +msgstr "" +"Möchten Sie die Registrierung von %(user)s für die WEI %(wei_name)s wirklich " +"löschen? Diese Aktion kann nicht rückgängig gemacht werden." + +#: apps/wei/templates/wei/weiregistration_list.html:19 +msgid "There is no pre-registration found with this pattern." +msgstr "Bei diesem Muster wurde keine Vorregistrierung gefunden." + +#: apps/wei/templates/wei/weiregistration_list.html:27 +msgid "View validated memberships..." +msgstr "Validierte Mitgliedschaften anzeigen ..." + +#: apps/wei/views.py:58 +msgid "Search WEI" +msgstr "WEI finden" + +#: apps/wei/views.py:109 +msgid "WEI Detail" +msgstr "WEI Infos" + +#: apps/wei/views.py:208 +msgid "View members of the WEI" +msgstr "Mitglied der WEI schauen" + +#: apps/wei/views.py:236 +msgid "Find WEI Membership" +msgstr "WEI Mitgliedschaft finden" + +#: apps/wei/views.py:246 +msgid "View registrations to the WEI" +msgstr "Mitglied der WEI schauen" + +#: apps/wei/views.py:270 +msgid "Find WEI Registration" +msgstr "WEI Registrierung finden" + +#: apps/wei/views.py:281 +msgid "Update the WEI" +msgstr "WEI bearbeiten" + +#: apps/wei/views.py:302 +msgid "Create new bus" +msgstr "Neue Bus" + +#: apps/wei/views.py:340 +msgid "Update bus" +msgstr "Bus bearbeiten" + +#: apps/wei/views.py:372 +msgid "Manage bus" +msgstr "Bus ändern" + +#: apps/wei/views.py:399 +msgid "Create new team" +msgstr "Neue Bus Team" + +#: apps/wei/views.py:439 +msgid "Update team" +msgstr "Team bearbeiten" + +#: apps/wei/views.py:470 +msgid "Manage WEI team" +msgstr "WEI Team bearbeiten" + +#: apps/wei/views.py:492 +msgid "Register first year student to the WEI" +msgstr "Registrieren Sie den Erstsemester beim WEI" + +#: apps/wei/views.py:550 apps/wei/views.py:649 +msgid "This user is already registered to this WEI." +msgstr "Dieser Benutzer ist bereits bei dieser WEI registriert." + +#: apps/wei/views.py:555 +msgid "" +"This user can't be in her/his first year since he/she has already " +"participated to a WEI." +msgstr "" +"Dieser Benutzer kann nicht in seinem ersten Jahr sein, da er bereits an " +"einer WEI teilgenommen hat." + +#: apps/wei/views.py:578 +msgid "Register old student to the WEI" +msgstr "Registrieren Sie einen alten Studenten beim WEI" + +#: apps/wei/views.py:633 apps/wei/views.py:721 +msgid "You already opened an account in the Société générale." +msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." + +#: apps/wei/views.py:685 +msgid "Update WEI Registration" +msgstr "WEI Registrierung aktualisieren" + +#: apps/wei/views.py:795 +msgid "Delete WEI registration" +msgstr "WEI Registrierung löschen" + +#: apps/wei/views.py:806 +msgid "You don't have the right to delete this WEI registration." +msgstr "Sie haben nicht das Recht, diese WEI-Registrierung zu löschen." + +#: apps/wei/views.py:824 +msgid "Validate WEI registration" +msgstr "Überprüfen Sie die WEI-Registrierung" + +#: apps/wei/views.py:1186 +msgid "Attribute buses to first year members" msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:6 -#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 -#, fuzzy -#| msgid "" -#| "Are you sure you want to delete this invoice? This action can't be undone." -msgid "Are you sure you want to delete this token?" -msgstr "" -"Möchten Sie diese Rechnung wirklich löschen? Diese Aktion kann nicht " -"rückgängig gemacht werden." - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:6 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 -#, fuzzy -#| msgid "Token" -msgid "Tokens" -msgstr "Token" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:11 -msgid "revoke" +#: apps/wei/views.py:1211 +msgid "Attribute bus" msgstr "" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:19 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 -#, fuzzy -#| msgid "There is no closed remittance yet." -msgid "There are no authorized tokens yet." -msgstr "Es gibt noch keine geschlossene Überweisung." - -#: note_kfet/settings/base.py:173 +#: note_kfet/settings/base.py:172 msgid "German" msgstr "Deutsch" -#: note_kfet/settings/base.py:174 +#: note_kfet/settings/base.py:173 msgid "English" msgstr "English" -#: note_kfet/settings/base.py:175 +#: note_kfet/settings/base.py:174 msgid "Spanish" msgstr "Spanisch" -#: note_kfet/settings/base.py:176 +#: note_kfet/settings/base.py:175 msgid "French" msgstr "Französich" @@ -4001,26 +3303,26 @@ msgstr "Users" msgid "Clubs" msgstr "Clubs" -#: note_kfet/templates/base.html:107 +#: note_kfet/templates/base.html:113 msgid "Admin" msgstr "Admin" -#: note_kfet/templates/base.html:121 +#: note_kfet/templates/base.html:127 msgid "My account" msgstr "Mein Konto" -#: note_kfet/templates/base.html:124 +#: note_kfet/templates/base.html:130 msgid "Log out" msgstr "Abmelden" -#: note_kfet/templates/base.html:132 +#: note_kfet/templates/base.html:138 #: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:28 msgid "Sign up" msgstr "Registrieren" -#: note_kfet/templates/base.html:139 +#: note_kfet/templates/base.html:145 #: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:38 @@ -4028,7 +3330,13 @@ msgstr "Registrieren" msgid "Log in" msgstr "Anmelden" -#: note_kfet/templates/base.html:153 +#: note_kfet/templates/base.html:159 +msgid "" +"You are not a BDE member anymore. Please renew your membership if you want " +"to use the note." +msgstr "" + +#: note_kfet/templates/base.html:165 msgid "" "Your e-mail address is not validated. Please check your mail inbox and click " "on the validation link." @@ -4037,10 +3345,19 @@ msgstr "" "Posteingang und klicken Sie auf den Validierungslink." #: note_kfet/templates/base.html:171 +msgid "" +"You declared that you opened a bank account in the Société générale. The " +"bank did not validate the creation of the account to the BDE, so the " +"membership and the WEI are not paid yet. This verification procedure may " +"last a few days. Please make sure that you go to the end of the account " +"creation." +msgstr "" + +#: note_kfet/templates/base.html:194 msgid "Contact us" msgstr "Kontakt" -#: note_kfet/templates/base.html:173 +#: note_kfet/templates/base.html:196 msgid "Technical Support" msgstr "" @@ -4052,6 +3369,44 @@ msgstr "Suche nach Attributen wie Name…" msgid "There is no results." msgstr "Es gibt keine Ergebnisse." +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 +#, fuzzy +#| msgid "" +#| "Are you sure you want to delete this invoice? This action can't be undone." +msgid "Are you sure to delete the application" +msgstr "" +"Möchten Sie diese Rechnung wirklich löschen? Diese Aktion kann nicht " +"rückgängig gemacht werden." + +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 +#: note_kfet/templates/oauth2_provider/authorize.html:28 +#, fuzzy +#| msgid "Balance" +msgid "Cancel" +msgstr "Kontostand" + +#: note_kfet/templates/oauth2_provider/application_detail.html:11 +msgid "Client id" +msgstr "" + +#: note_kfet/templates/oauth2_provider/application_detail.html:14 +msgid "Client secret" +msgstr "" + +#: note_kfet/templates/oauth2_provider/application_detail.html:17 +#, fuzzy +#| msgid "Credit type" +msgid "Client type" +msgstr "Kredittype" + +#: note_kfet/templates/oauth2_provider/application_detail.html:20 +msgid "Authorization Grant Type" +msgstr "" + +#: note_kfet/templates/oauth2_provider/application_detail.html:23 +msgid "Redirect Uris" +msgstr "" + #: note_kfet/templates/oauth2_provider/application_detail.html:29 #, python-format msgid "" @@ -4060,16 +3415,48 @@ msgid "" "that you want to grant for your application." msgstr "" +#: note_kfet/templates/oauth2_provider/application_detail.html:37 +#: note_kfet/templates/oauth2_provider/application_form.html:23 +msgid "Go Back" +msgstr "" + +#: note_kfet/templates/oauth2_provider/application_form.html:12 +#, fuzzy +#| msgid "Email validation" +msgid "Edit application" +msgstr "Email validierung" + +#: note_kfet/templates/oauth2_provider/application_list.html:7 +msgid "Your applications" +msgstr "" + #: note_kfet/templates/oauth2_provider/application_list.html:11 msgid "" "You can find on this page the list of the applications that you already " "registered." msgstr "" +#: note_kfet/templates/oauth2_provider/application_list.html:30 +#, fuzzy +#| msgid "location" +msgid "New Application" +msgstr "Ort" + #: note_kfet/templates/oauth2_provider/application_list.html:31 msgid "Authorized Tokens" msgstr "" +#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 +#, fuzzy +#| msgid "Registrations" +msgid "Register a new application" +msgstr "Anmeldung" + +#: note_kfet/templates/oauth2_provider/authorize.html:9 +#: note_kfet/templates/oauth2_provider/authorize.html:29 +msgid "Authorize" +msgstr "" + #: note_kfet/templates/oauth2_provider/authorize.html:14 msgid "Application requires following permissions:" msgstr "" @@ -4087,6 +3474,27 @@ msgstr "" msgid "Please return to your application and enter this code:" msgstr "" +#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 +#, fuzzy +#| msgid "" +#| "Are you sure you want to delete this invoice? This action can't be undone." +msgid "Are you sure you want to delete this token?" +msgstr "" +"Möchten Sie diese Rechnung wirklich löschen? Diese Aktion kann nicht " +"rückgängig gemacht werden." + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 +#, fuzzy +#| msgid "Token" +msgid "Tokens" +msgstr "Token" + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 +#, fuzzy +#| msgid "There is no closed remittance yet." +msgid "There are no authorized tokens yet." +msgstr "Es gibt noch keine geschlossene Überweisung." + #: note_kfet/templates/registration/logged_out.html:13 msgid "Thanks for spending some quality time with the Web site today." msgstr "" @@ -4188,17 +3596,11 @@ msgid "Reset my password" msgstr "Mein Passwort zurücksetzen" #: note_kfet/templates/registration/signup.html:15 -#, fuzzy -#| msgid "" -#| "If you already signed up, your registration is taken into account. The " -#| "BDE must validate your account before your can log in. You have to go to " -#| "the Kfet and pay the registration fee. You must also validate your email " -#| "address by following the link you received." msgid "" "If you already signed up, your registration is taken into account. The BDE " -"must validate your account before your can log in. You have to pay the " -"registration fee. You must also validate your email address by following the " -"link you received." +"must validate your account before your can log in. You have to go to the " +"Kfet and pay the registration fee. You must also validate your email address " +"by following the link you received." msgstr "" "Wenn Sie sich bereits registriert haben, wird Ihre Registrierung " "berücksichtigt. Die BDE muss Ihr Konto validieren, bevor Sie sich anmelden " @@ -4206,589 +3608,6 @@ msgstr "" "müssen Ihre E-Mail-Adresse auch überprüfen, indem Sie dem Link folgen, den " "Sie erhalten haben." -#~ msgid "Inscription paid by Société Générale" -#~ msgstr "Mitgliedschaft von der Société Générale bezahlt" - -#~ msgid "Check this case if the Société Générale paid the inscription." -#~ msgstr "Die Société Générale die Mitgliedschaft bezahlt." - -#~ msgid "Bank" -#~ msgstr "Bank" - -#~ msgid "Physics (A2)" -#~ msgstr "Physik (A2)" - -#~ msgid "Applied physics (A'2)" -#~ msgstr "Angewandte Physik (A'2)" - -#~ msgid "Chemistry (A''2)" -#~ msgstr "Chemie (A''2)" - -#~ msgid "Biology (A3)" -#~ msgstr "Biologie (A3)" - -#~ msgid "SAPHIRE (B1234)" -#~ msgstr "SAPHIRE (B1234)" - -#~ msgid "Mechanics (B1)" -#~ msgstr "Mechanik (B1)" - -#~ msgid "Civil engineering (B2)" -#~ msgstr "Bauingenieur (B2)" - -#~ msgid "Mechanical engineering (B3)" -#~ msgstr "Mechanikingenieur (B3)" - -#~ msgid "EEA (B4)" -#~ msgstr "Electrotechnik (B4)" - -#~ msgid "Design (C)" -#~ msgstr "Design (C)" - -#~ msgid "Social sciences (D3)" -#~ msgstr "Sozialwissenschaften (D3)" - -#~ msgid "English (E)" -#~ msgstr "English (E)" - -#~ msgid "External (EXT)" -#~ msgstr "Extern (EXT)" - -#~ msgid "Yes (receive them in french)" -#~ msgstr "Ja (auf Fränzosich)" - -#~ msgid "Yes (receive them in english)" -#~ msgstr "Ja (auf English)" - -#, python-format -#~ msgid "" -#~ "The user is not a member of the club·s %(clubs)s. An additional fee of " -#~ "%(pretty_fee)s will be charged to renew automatically the membership in " -#~ "this/these club·s." -#~ msgstr "" -#~ "Dieser User ist noch nicht Mitglied von den Urclub %(clubs)s. Ein extra " -#~ "Beitrag von %(pretty_fee)s wurde bezahlt um die Mitgliedschaft von dieser/" -#~ "diesen Club zu erneuern." - -#, python-format -#~ msgid "" -#~ "This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will " -#~ "be charged to adhere automatically to this/these club·s." -#~ msgstr "" -#~ "Dieses Club hat %(clubs)s als Urclub. Eine extra Beitrag von " -#~ "%(pretty_fee)s wurde bezahlt um Mitglied von dieser/diesen Club zu werden." - -#~ msgid "bank" -#~ msgstr "Bank" - -#~ msgid "Superusers have all rights on everything, to manage the website." -#~ msgstr "Superuser haben alle Berechtigung, um das Website zu handeln." - -#~ msgid "Superusers" -#~ msgstr "Superusers" - -#, fuzzy -#~| msgid "You already opened an account in the Société générale." -#~ msgid "" -#~ "I declare that I opened or I will open soon a bank account in the Société " -#~ "générale with the BDE partnership." -#~ msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." - -#~ msgid "Register to the WEI" -#~ msgstr "Zu WEI anmelden" - -#~ 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." -#~ msgstr "" -#~ "Überprüfen Sie diesen Fall, wenn Sie sich beim WEI registrieren möchten. " -#~ "falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im " -#~ "Kfet registrieren." - -#~ msgid "Join Kfet Club" -#~ msgstr "Kfet Mitglieder werden" - -#~ msgid "You must also go to the Kfet to pay your membership." -#~ msgstr "Sie müssen auch zum Kfet gehen, um Ihre Mitgliedschaft zu bezahlen." - -#, fuzzy -#~| msgid "You already opened an account in the Société générale." -#~ msgid "" -#~ "The user declared that he/she opened a bank account in the Société " -#~ "générale." -#~ msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." - -#~ msgid "You must join the BDE." -#~ msgstr "Sie müssen die BDE beitreten." - -#~ msgid "credit transaction" -#~ msgstr "Kredit Transaktion" - -#~ msgid "" -#~ "This user doesn't have enough money to pay the memberships with its note. " -#~ "Please ask her/him to credit the note before invalidating this credit." -#~ msgstr "" -#~ "Dieser Benutzer hat nicht genug Geld, um die Mitgliedschaften mit seiner " -#~ "Note zu bezahlen." - -#~ msgid "Credits from the Société générale" -#~ msgstr "Krediten von der Société générale" - -#, python-brace-format -#~ msgid "Soge credit for {user}" -#~ msgstr "Kredit von der Société générale für {user}" - -#~ msgid "List of credits from the Société générale" -#~ msgstr "Kreditliste von Société générale" - -#~ msgid "Manage credits from the Société générale" -#~ msgstr "Krediten von der Société générale handeln" - -#~ msgid "WEI" -#~ msgstr "WEI" - -#~ msgid "bus" -#~ msgstr "Bus" - -#~ msgid "" -#~ "This choice is not definitive. The WEI organizers are free to attribute " -#~ "for you a bus and a team, in particular if you are a free eletron." -#~ msgstr "" -#~ "Diese Wahl ist nicht endgültig. Den WEI-Organisatoren steht es frei, " -#~ "Ihnen einen Bus und ein Team zuzuweisen, insbesondere wenn Sie ein freies " -#~ "Elektron sind." - -#~ msgid "Team" -#~ msgstr "Team" - -#~ msgid "" -#~ "Leave this field empty if you won't be in a team (staff, bus chief, free " -#~ "electron)" -#~ msgstr "" -#~ "Lassen Sie dieses Feld leer, wenn Sie nicht in einem Team sind " -#~ "(Mitarbeiter, Buschef, freies Elektron)" - -#~ msgid "WEI Roles" -#~ msgstr "WEI Rollen" - -#~ msgid "Select the roles that you are interested in." -#~ msgstr "Wählen Sie die Rollen aus, an denen Sie interessiert sind." - -#~ msgid "This team doesn't belong to the given bus." -#~ msgstr "Dieses Team gehört nicht zum angegebenen Bus." - -#~ msgid "Choose a word:" -#~ msgstr "Wählen Sie ein Wort:" - -#~ msgid "year" -#~ msgstr "Jahr" - -#~ msgid "date start" -#~ msgstr "Anfangsdatum" - -#~ msgid "date end" -#~ msgstr "Abschlussdatum" - -#, fuzzy -#~| msgid "The user joined the bus" -#~ msgid "seat count in the bus" -#~ msgstr "Der Benutzer ist dem Bus beigetreten" - -#~ msgid "survey information" -#~ msgstr "Umfrage Infos" - -#~ msgid "Information about the survey for new members, encoded in JSON" -#~ msgstr "Informationen zur Umfrage für neue Mitglieder, codiert in JSON" - -#~ msgid "Bus" -#~ msgstr "Bus" - -#~ msgid "Buses" -#~ msgstr "Buses" - -#~ msgid "color" -#~ msgstr "Farbe" - -#~ msgid "The color of the T-Shirt, stored with its number equivalent" -#~ msgstr "Die Farbe des T-Shirts, gespeichert mit der entsprechenden Nummer" - -#~ msgid "Bus team" -#~ msgstr "Bus Team" - -#~ msgid "Bus teams" -#~ msgstr "Bus Teams" - -#~ msgid "WEI Role" -#~ msgstr "WEI Rolle" - -#~ msgid "Credit from Société générale" -#~ msgstr "Kredit von der Société générale" - -#~ msgid "Caution check given" -#~ msgstr "Caution check given" - -#~ msgid "birth date" -#~ msgstr "Geburtsdatum" - -#~ msgid "Male" -#~ msgstr "Männlich" - -#~ msgid "Female" -#~ msgstr "Weiblich" - -#~ msgid "Non binary" -#~ msgstr "Nicht binär" - -#~ msgid "gender" -#~ msgstr "Geschlecht" - -#~ msgid "clothing cut" -#~ msgstr "Kleidung Schnitt" - -#~ msgid "clothing size" -#~ msgstr "Kleidergröße" - -#~ msgid "health issues" -#~ msgstr "Gesundheitsprobleme" - -#~ msgid "emergency contact name" -#~ msgstr "Notfall-Kontakt" - -#~ msgid "emergency contact phone" -#~ msgstr "Notfallkontakttelefon" - -#~ msgid "first year" -#~ msgstr "Erste Jahr" - -#~ msgid "Tells if the user is new in the school." -#~ msgstr "Gibt an, ob der USer neu in der Schule ist." - -#~ msgid "registration information" -#~ msgstr "Registrierung Detailen" - -#~ msgid "" -#~ "Information about the registration (buses for old members, survey for the " -#~ "new members), encoded in JSON" -#~ msgstr "" -#~ "Informationen zur Registrierung (Busse für alte Mitglieder, Umfrage für " -#~ "neue Mitglieder), verschlüsselt in JSON" - -#~ msgid "WEI User" -#~ msgstr "WEI User" - -#~ msgid "WEI Users" -#~ msgstr "WEI Users" - -#~ msgid "team" -#~ msgstr "Team" - -#~ msgid "WEI registration" -#~ msgstr "WEI Registrierung" - -#~ msgid "WEI membership" -#~ msgstr "WEI Mitgliedschaft" - -#~ msgid "WEI memberships" -#~ msgstr "WEI Mitgliedschaften" - -#, fuzzy -#~| msgid "" -#~| "The note has enough money (%(pretty_fee)s required), the registration is " -#~| "possible." -#~ msgid "The user has enough money, you can validate the registration." -#~ msgstr "" -#~ "Die Note hat genug Geld (%(pretty_fee)s erforderlich), die Registrierung " -#~ "ist möglich." - -#~ msgid "Year" -#~ msgstr "Jahr" - -#~ msgid "preferred bus" -#~ msgstr "bevorzugter Bus" - -#~ msgid "Teams" -#~ msgstr "Teams" - -#~ msgid "Members count" -#~ msgstr "Anzahl Mitgliedern" - -#~ msgid "members" -#~ msgstr "Mitglieder" - -#, fuzzy -#~| msgid "first year" -#~ msgid "suggested first year" -#~ msgstr "Erste Jahr" - -#, fuzzy -#~| msgid "first year" -#~ msgid "validated first year" -#~ msgstr "Erste Jahr" - -#, fuzzy -#~| msgid "Unvalidated registrations" -#~ msgid "validated staff" -#~ msgstr "Unvalidierte Registrierungen" - -#, fuzzy -#~| msgid "Raw survey information" -#~ msgid "View raw survey information" -#~ msgstr "Rohe Umfrageinformationen" - -#, fuzzy -#~| msgid "Buttons list" -#~ msgid "Back to main list" -#~ msgstr "Tastenliste" - -#~ msgid "WEI fee (paid students)" -#~ msgstr "WEI Preis (bezahlte Studenten)" - -#~ msgid "The BDE membership is included in the WEI registration." -#~ msgstr "Die BDE-Mitgliedschaft ist in der WEI-Registrierung enthalten." - -#~ msgid "WEI fee (unpaid students)" -#~ msgstr "WEI Preis (unbezahlte Studenten)" - -#~ msgid "WEI list" -#~ msgstr "WEI Liste" - -#~ msgid "Register 1A" -#~ msgstr "1A Registrieren" - -#~ msgid "Register 2A+" -#~ msgstr "2A+ Registrieren" - -#~ msgid "Add bus" -#~ msgstr "Neue Bus" - -#~ msgid "View WEI" -#~ msgstr "WEI schauen" - -#~ msgid "Add team" -#~ msgstr "Neue Team" - -#~ msgid "Members" -#~ msgstr "Mitglied" - -#~ msgid "View as PDF" -#~ msgstr "Als PDF schauen" - -#~ msgid "Survey WEI" -#~ msgstr "WEI Umfrage" - -#~ msgid "Next" -#~ msgstr "Weiter" - -#~ msgid "The inscription for this WEI are now closed." -#~ msgstr "Die Inschrift für diese WEI ist nun geschlossen." - -#~ msgid "Return to WEI detail" -#~ msgstr "Zurück zur WEI Detaillen" - -#~ msgid "The survey is now ended. Your answers have been saved." -#~ msgstr "Die Umfrage ist nun beendet. Ihre Antworten wurden gespeichert." - -#~ msgid "Register to the WEI! – 1A" -#~ msgstr "1A Registrieren" - -#~ msgid "Register to the WEI! – 2A+" -#~ msgstr "2A+ Registrieren" - -#~ msgid "Update my registration" -#~ msgstr "Meine Registrierung bearbeiten" - -#~ msgid "Members of the WEI" -#~ msgstr "Mitglied der WEI" - -#~ msgid "Unvalidated registrations" -#~ msgstr "Unvalidierte Registrierungen" - -#~ msgid "Create WEI" -#~ msgstr "Neue WEI" - -#~ msgid "WEI listing" -#~ msgstr "WEI List" - -#~ msgid "Review registration" -#~ msgstr "Registrierung schauen" - -#~ msgid "ENS year" -#~ msgstr "ENS Jahr" - -#~ msgid "Payment from Société générale" -#~ msgstr "Kredit von der Société générale" - -#~ msgid "Suggested bus from the survey:" -#~ msgstr "Vorgeschlagener Bus aus der Umfrage:" - -#~ msgid "Raw survey information" -#~ msgstr "Rohe Umfrageinformationen" - -#~ msgid "The algorithm didn't run." -#~ msgstr "Der Algorithmus wurde nicht ausgeführt." - -#~ msgid "caution check given" -#~ msgstr "Vorsichtsprüfung gegeben" - -#~ msgid "preferred team" -#~ msgstr "bevorzugtes Team" - -#~ msgid "preferred roles" -#~ msgstr "bevorzugte Rollen" - -#~ msgid "Update registration" -#~ msgstr "Registrierung aktualisieren" - -#~ msgid "The registration is already validated and can't be unvalidated." -#~ msgstr "" -#~ "Die Registrierung ist bereits validiert und kann nicht ungültig gemacht " -#~ "werden." - -#~ msgid "The user joined the bus" -#~ msgstr "Der Benutzer ist dem Bus beigetreten" - -#~ msgid "in the team" -#~ msgstr "In der Team" - -#~ msgid "in no team (staff)" -#~ msgstr "In keinem Team (staff)" - -#~ msgid "with the following roles:" -#~ msgstr "mit den folgenden Rollen:" - -#~ msgid "" -#~ "The WEI will be paid by Société générale. The membership will be created " -#~ "even if the bank didn't pay the BDE yet. The membership transaction will " -#~ "be created but will be invalid. You will have to validate it once the " -#~ "bank validated the creation of the account, or to change the payment " -#~ "method." -#~ msgstr "" -#~ "Das WEI wird von der Société générale bezahlt. Die Mitgliedschaft wird " -#~ "auch dann erstellt, wenn die Bank die BDE noch nicht bezahlt hat. Die " -#~ "Mitgliedschaftstransaktion wird erstellt, ist jedoch ungültig. Sie müssen " -#~ "es validieren, sobald die Bank die Erstellung des Kontos validiert hat, " -#~ "oder die Zahlungsmethode ändern." - -#, python-format -#~ msgid "" -#~ "The note don't have enough money (%(balance)s, %(pretty_fee)s required). " -#~ "The registration may fail if you don't credit the note now." -#~ msgstr "" -#~ "Die Note hat nicht genug Geld (%(balance)s,%(pretty_fee)s erforderlich). " -#~ "Die Registrierung kann fehlschlagen, wenn Sie die Note jetzt nicht " -#~ "gutschreiben." - -#, python-format -#~ msgid "" -#~ "The note has enough money (%(pretty_fee)s required), the registration is " -#~ "possible." -#~ msgstr "" -#~ "Die Note hat genug Geld (%(pretty_fee)s erforderlich), die Registrierung " -#~ "ist möglich." - -#~ msgid "The user didn't give her/his caution check." -#~ msgstr "Der User hat nicht sein Vorsichtsprüfung gegeben." - -#~ msgid "" -#~ "This user is not a member of the Kfet club for the coming year. The " -#~ "membership will be processed automatically, the WEI registration includes " -#~ "the membership fee." -#~ msgstr "" -#~ "Dieser Benutzer ist für das kommende Jahr kein Mitglied des Kfet-Clubs. " -#~ "Die Mitgliedschaft wird automatisch bearbeitet, die WEI-Registrierung " -#~ "beinhaltet den Mitgliedsbeitrag." - -#~ msgid "View unvalidated registrations..." -#~ msgstr "Nicht validierte Registrierungen anzeigen ..." - -#~ msgid "This registration is already validated and can't be deleted." -#~ msgstr "" -#~ "Diese Registrierung ist bereits validiert und kann nicht gelöscht werden." - -#, python-format -#~ msgid "" -#~ "Are you sure you want to delete the registration of %(user)s for the WEI " -#~ "%(wei_name)s? This action can't be undone." -#~ msgstr "" -#~ "Möchten Sie die Registrierung von %(user)s für die WEI %(wei_name)s " -#~ "wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden." - -#~ msgid "There is no pre-registration found with this pattern." -#~ msgstr "Bei diesem Muster wurde keine Vorregistrierung gefunden." - -#~ msgid "View validated memberships..." -#~ msgstr "Validierte Mitgliedschaften anzeigen ..." - -#~ msgid "Search WEI" -#~ msgstr "WEI finden" - -#~ msgid "WEI Detail" -#~ msgstr "WEI Infos" - -#~ msgid "View members of the WEI" -#~ msgstr "Mitglied der WEI schauen" - -#~ msgid "Find WEI Membership" -#~ msgstr "WEI Mitgliedschaft finden" - -#~ msgid "View registrations to the WEI" -#~ msgstr "Mitglied der WEI schauen" - -#~ msgid "Find WEI Registration" -#~ msgstr "WEI Registrierung finden" - -#~ msgid "Update the WEI" -#~ msgstr "WEI bearbeiten" - -#~ msgid "Create new bus" -#~ msgstr "Neue Bus" - -#~ msgid "Update bus" -#~ msgstr "Bus bearbeiten" - -#~ msgid "Manage bus" -#~ msgstr "Bus ändern" - -#~ msgid "Create new team" -#~ msgstr "Neue Bus Team" - -#~ msgid "Update team" -#~ msgstr "Team bearbeiten" - -#~ msgid "Manage WEI team" -#~ msgstr "WEI Team bearbeiten" - -#~ msgid "Register first year student to the WEI" -#~ msgstr "Registrieren Sie den Erstsemester beim WEI" - -#~ msgid "This user is already registered to this WEI." -#~ msgstr "Dieser Benutzer ist bereits bei dieser WEI registriert." - -#~ msgid "" -#~ "This user can't be in her/his first year since he/she has already " -#~ "participated to a WEI." -#~ msgstr "" -#~ "Dieser Benutzer kann nicht in seinem ersten Jahr sein, da er bereits an " -#~ "einer WEI teilgenommen hat." - -#~ msgid "Register old student to the WEI" -#~ msgstr "Registrieren Sie einen alten Studenten beim WEI" - -#~ msgid "You already opened an account in the Société générale." -#~ msgstr "Sie haben bereits ein Konto in der Société générale eröffnet." - -#~ msgid "Update WEI Registration" -#~ msgstr "WEI Registrierung aktualisieren" - -#~ msgid "Delete WEI registration" -#~ msgstr "WEI Registrierung löschen" - -#~ msgid "You don't have the right to delete this WEI registration." -#~ msgstr "Sie haben nicht das Recht, diese WEI-Registrierung zu löschen." - -#~ msgid "Validate WEI registration" -#~ msgstr "Überprüfen Sie die WEI-Registrierung" - #~ msgid "This user didn't give her/his caution check." #~ msgstr "Dieser User hat seine / ihre Vorsicht nicht überprüft." diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 32ae54f..4f03a2c 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-08 10:30+0100\n" +"POT-Creation-Date: 2022-04-10 22:34+0200\n" "PO-Revision-Date: 2022-04-11 23:12+0200\n" "Last-Translator: elkmaennchen \n" "Language-Team: \n" @@ -52,13 +52,16 @@ 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:182 +#: 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 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301 #: apps/permission/models.py:330 #: apps/registration/templates/registration/future_profile_detail.html:16 +#: apps/wei/models.py:67 apps/wei/models.py:131 apps/wei/tables.py:282 +#: apps/wei/templates/wei/base.html:26 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "name" msgstr "nombre" @@ -91,7 +94,7 @@ msgstr "tipos de actividad" #: apps/activity/models.py:68 #: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/note/models/transactions.py:81 apps/permission/models.py:110 -#: apps/permission/models.py:189 +#: apps/permission/models.py:189 apps/wei/models.py:78 apps/wei/models.py:142 msgid "description" msgstr "descripción" @@ -100,9 +103,7 @@ msgid "location" msgstr "ubicación" #: apps/activity/models.py:76 -#, fuzzy -#| msgid "Place where the activity is organized, eg. Kfet." -msgid "Place where the activity is organized, eg. BDE." +msgid "Place where the activity is organized, eg. Kfet." msgstr "Lugar donde se organiza la actividad, por ejemplo la Kfet." #: apps/activity/models.py:83 @@ -112,8 +113,10 @@ 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:290 -#: apps/note/models/notes.py:148 +#: 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:285 +#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13 +#: apps/wei/templates/wei/survey.html:15 msgid "user" msgstr "usuario" @@ -134,9 +137,7 @@ msgid "attendees club" msgstr "club esperado" #: apps/activity/models.py:105 -#, fuzzy -#| msgid "Club that is authorized to join the activity. Mostly the Kfet club." -msgid "Club that is authorized to join the activity." +msgid "Club that is authorized to join the activity. Mostly the Kfet club." msgstr "Club permitido unirse a la actividad. Generalmente el club Kfet." #: apps/activity/models.py:109 @@ -207,6 +208,7 @@ msgstr "El saldo es negativo." #: apps/activity/models.py:240 #: apps/treasury/templates/treasury/sogecredit_detail.html:14 +#: apps/wei/templates/wei/attribute_bus_1A.html:16 msgid "last name" msgstr "apellido" @@ -214,6 +216,8 @@ msgstr "apellido" #: apps/member/templates/member/includes/profile_info.html:4 #: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/treasury/templates/treasury/sogecredit_detail.html:17 +#: apps/wei/templates/wei/attribute_bus_1A.html:19 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "first name" msgstr "nombre" @@ -253,18 +257,20 @@ msgstr "Entrado el " msgid "remove" msgstr "quitar" -#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:196 +#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:199 msgid "Type" msgstr "Tipo" -#: apps/activity/tables.py:84 apps/member/forms.py:180 -#: apps/registration/forms.py:68 apps/treasury/forms.py:131 +#: apps/activity/tables.py:84 apps/member/forms.py:186 +#: apps/registration/forms.py:91 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:185 +#: apps/activity/tables.py:86 apps/member/forms.py:191 #: apps/note/templates/note/transaction_form.html:138 -#: apps/registration/forms.py:73 apps/treasury/forms.py:133 +#: apps/registration/forms.py:96 apps/treasury/forms.py:133 +#: apps/wei/forms/registration.py:109 msgid "First name" msgstr "Nombre" @@ -287,19 +293,19 @@ msgstr "Invitados suprimidos" #: apps/activity/templates/activity/activity_entry.html:14 #: apps/note/models/transactions.py:257 #: apps/note/templates/note/transaction_form.html:17 -#: apps/note/templates/note/transaction_form.html:146 +#: apps/note/templates/note/transaction_form.html:152 #: note_kfet/templates/base.html:72 msgid "Transfer" msgstr "Transferencia" #: apps/activity/templates/activity/activity_entry.html:18 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:22 msgid "Credit" msgstr "Crédito" #: apps/activity/templates/activity/activity_entry.html:21 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:26 msgid "Debit" msgstr "Débito" @@ -315,9 +321,7 @@ msgstr "Regresar a la página de la actividad" #: apps/activity/templates/activity/activity_entry.html:94 #: apps/activity/templates/activity/activity_entry.html:129 -#, fuzzy -#| msgid "Entry done, but caution: the user is not a Kfet member." -msgid "Entry done, but caution: the user is not a member." +msgid "Entry done, but caution: the user is not a Kfet member." msgstr "Entrada echa, pero cuidado : el usuario no es un miembro de la Kfet." #: apps/activity/templates/activity/activity_entry.html:132 @@ -325,11 +329,15 @@ msgid "Entry done!" msgstr "Entrada echa !" #: apps/activity/templates/activity/activity_form.html:16 -#: apps/member/templates/member/add_members.html:32 +#: apps/member/templates/member/add_members.html:46 #: apps/member/templates/member/club_form.html:16 #: apps/note/templates/note/transactiontemplate_form.html:18 -#: apps/treasury/forms.py:89 apps/treasury/forms.py:141 +#: apps/treasury/forms.py:89 apps/treasury/forms.py:143 #: apps/treasury/templates/treasury/invoice_form.html:74 +#: apps/wei/templates/wei/bus_form.html:17 +#: apps/wei/templates/wei/busteam_form.html:17 +#: apps/wei/templates/wei/weiclub_form.html:17 +#: apps/wei/templates/wei/weiregistration_form.html:18 msgid "Submit" msgstr "Enviar" @@ -366,9 +374,6 @@ msgid "Entry page" msgstr "Página de las entradas" #: apps/activity/templates/activity/includes/activity_info.html:65 -#: env/lib/python3.11/site-packages/bootstrap4/components.py:17 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/form_errors.html:3 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/messages.html:4 msgid "close" msgstr "cerrado" @@ -461,7 +466,7 @@ msgstr "crear" #: apps/logs/models.py:65 apps/note/tables.py:166 apps/note/tables.py:190 #: apps/note/tables.py:237 apps/permission/models.py:127 -#: apps/treasury/tables.py:38 +#: apps/treasury/tables.py:38 apps/wei/tables.py:74 msgid "delete" msgstr "suprimir" @@ -490,25 +495,25 @@ msgstr "diario de cambios" msgid "Changelog of type \"{action}\" for model {model} at {timestamp}" msgstr "" -#: apps/member/admin.py:50 apps/member/models.py:209 +#: 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:214 +#: 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:302 +#: apps/member/admin.py:65 apps/member/models.py:319 msgid "roles" msgstr "papel" -#: apps/member/admin.py:66 apps/member/models.py:316 +#: apps/member/admin.py:66 apps/member/models.py:333 msgid "fee" msgstr "pago" -#: apps/member/apps.py:14 +#: apps/member/apps.py:14 apps/wei/tables.py:226 apps/wei/tables.py:257 msgid "member" msgstr "miembro" @@ -541,31 +546,48 @@ 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:33 apps/registration/views.py:252 +#: apps/registration/forms.py:33 apps/registration/views.py:262 msgid "An alias with a similar name already exists." msgstr "Un alias similar ya existe." -#: apps/member/forms.py:166 apps/registration/forms.py:55 +#: apps/member/forms.py:165 apps/registration/forms.py:71 +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/registration/forms.py:73 +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:78 +#: apps/wei/forms/registration.py:91 msgid "Credit type" msgstr "Tipo de crédito" -#: apps/member/forms.py:167 apps/registration/forms.py:56 +#: apps/member/forms.py:173 apps/registration/forms.py:79 +#: apps/wei/forms/registration.py:92 msgid "No credit" msgstr "No crédito" -#: apps/member/forms.py:169 +#: 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:173 apps/registration/forms.py:61 +#: apps/member/forms.py:179 apps/registration/forms.py:84 +#: apps/wei/forms/registration.py:97 msgid "Credit amount" msgstr "Valor del crédito" -#: apps/member/forms.py:212 +#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144 +#: apps/registration/forms.py:101 apps/treasury/forms.py:135 +#: apps/wei/forms/registration.py:114 +msgid "Bank" +msgstr "Banco" + +#: apps/member/forms.py:223 msgid "User" msgstr "Usuario" -#: apps/member/forms.py:226 +#: apps/member/forms.py:237 msgid "Roles" msgstr "Papeles" @@ -588,12 +610,14 @@ msgstr "hash" #: apps/member/models.py:38 #: apps/member/templates/member/includes/profile_info.html:43 #: apps/registration/templates/registration/future_profile_detail.html:40 +#: apps/wei/templates/wei/weimembership_form.html:44 msgid "phone number" msgstr "número de teléfono" #: apps/member/models.py:45 #: apps/member/templates/member/includes/profile_info.html:37 #: apps/registration/templates/registration/future_profile_detail.html:34 +#: apps/wei/templates/wei/weimembership_form.html:38 msgid "section" msgstr "sección" @@ -601,79 +625,114 @@ msgstr "sección" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "i.e. \"1A0\", \"9A♥\", \"SAPHIRE\"" -#: apps/member/models.py:54 +#: apps/member/models.py:54 apps/wei/templates/wei/attribute_bus_1A.html:25 +#: apps/wei/templates/wei/weimembership_form.html:32 msgid "department" msgstr "departamento" #: apps/member/models.py:56 -#, fuzzy -#| msgid "Informatics (A0)" -msgid "Informatique" +msgid "Informatics (A0)" msgstr "Informática (A0)" #: apps/member/models.py:57 -#, fuzzy -#| msgid "Mathematics (A1)" -msgid "Mathématiques" +msgid "Mathematics (A1)" msgstr "Matemáticas (A1)" #: apps/member/models.py:58 -#, fuzzy -#| msgid "Economy-management (D2)" -msgid "Droit - économie - management" -msgstr "Economía-gestión (D2)" +msgid "Physics (A2)" +msgstr "Física (A2)" #: apps/member/models.py:59 -msgid "Mécatronique" -msgstr "" +msgid "Applied physics (A'2)" +msgstr "Física aplicada (A'2)" #: apps/member/models.py:60 -msgid "Sciences du sport et éducation physique" -msgstr "" +msgid "Chemistry (A''2)" +msgstr "Química (A''2)" #: apps/member/models.py:61 -msgid "Sciences pour l’Environnement" -msgstr "" +msgid "Biology (A3)" +msgstr "Biología (A3)" #: apps/member/models.py:62 -msgid "Externe" -msgstr "" +msgid "SAPHIRE (B1234)" +msgstr "SAPHIRE (B1234)" + +#: apps/member/models.py:63 +msgid "Mechanics (B1)" +msgstr "Mecánica (B1)" + +#: apps/member/models.py:64 +msgid "Civil engineering (B2)" +msgstr "Ingeniería civil (B2)" + +#: apps/member/models.py:65 +msgid "Mechanical engineering (B3)" +msgstr "Ingeniería mecánica (B3)" + +#: apps/member/models.py:66 +msgid "EEA (B4)" +msgstr "EEA (B4)" + +#: apps/member/models.py:67 +msgid "Design (C)" +msgstr "Design (C)" + +#: apps/member/models.py:68 +msgid "Economy-management (D2)" +msgstr "Economía-gestión (D2)" #: apps/member/models.py:69 +msgid "Social sciences (D3)" +msgstr "Ciencias sociales (D3)" + +#: apps/member/models.py:70 +msgid "English (E)" +msgstr "Inglés (E)" + +#: apps/member/models.py:71 +msgid "External (EXT)" +msgstr "Extern@ (EXT)" + +#: apps/member/models.py:78 msgid "promotion" msgstr "promoción" -#: apps/member/models.py:70 +#: apps/member/models.py:79 msgid "Year of entry to the school (None if not ENS student)" msgstr "Año de ingreso en la escuela (None si no un alumn@ ENS)" -#: apps/member/models.py:74 +#: apps/member/models.py:83 #: apps/member/templates/member/includes/profile_info.html:47 #: apps/registration/templates/registration/future_profile_detail.html:37 +#: apps/wei/templates/wei/weimembership_form.html:41 msgid "address" msgstr "dirección" -#: apps/member/models.py:81 +#: apps/member/models.py:90 #: apps/member/templates/member/includes/profile_info.html:50 #: apps/registration/templates/registration/future_profile_detail.html:43 +#: apps/wei/templates/wei/weimembership_form.html:47 msgid "paid" msgstr "pagado" -#: apps/member/models.py:82 +#: apps/member/models.py:91 msgid "Tells if the user receive a salary." msgstr "Indica si el usuario percibe un salario." -#: apps/member/models.py:91 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:796 +#: apps/member/models.py:100 apps/treasury/tables.py:143 msgid "No" msgstr "No" -#: apps/member/models.py:92 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:795 -msgid "Yes" -msgstr "Sí" +#: apps/member/models.py:101 +msgid "Yes (receive them in french)" +msgstr "Si (recibirles en francés)" -#: apps/member/models.py:94 +#: apps/member/models.py:102 +msgid "Yes (receive them in english)" +msgstr "Si (recibirles en inglés)" + +#: apps/member/models.py:104 msgid "" "Register on the mailing list to stay informed of the events of the campus (1 " "mail/week)" @@ -681,7 +740,7 @@ msgstr "" "Registrar el la lista de difusión de correo electrónico para quedarse " "informado de los eventos del campus (1 correo por semana)" -#: apps/member/models.py:99 +#: apps/member/models.py:109 msgid "" "Register on the mailing list to stay informed of the sport events of the " "campus (1 mail/week)" @@ -689,7 +748,7 @@ msgstr "" "Registrar el la lista de difusión de correo electrónico para quedarse " "informado de los eventos deportivos del campus (1 correo por semana)" -#: apps/member/models.py:104 +#: apps/member/models.py:114 msgid "" "Register on the mailing list to stay informed of the art events of the " "campus (1 mail/week)" @@ -697,120 +756,120 @@ msgstr "" "Registrar el la lista de difusión de correo electrónico para quedarse " "informado de los eventos artísticos del campus (1 correo por semana)" -#: apps/member/models.py:108 +#: apps/member/models.py:118 msgid "report frequency (in days)" msgstr "frecuencia de los informes (en días)" -#: apps/member/models.py:113 +#: apps/member/models.py:123 msgid "last report date" msgstr "fecha del último informe" -#: apps/member/models.py:118 +#: apps/member/models.py:128 msgid "email confirmed" msgstr "correo electrónico confirmado" -#: apps/member/models.py:123 +#: apps/member/models.py:133 msgid "registration valid" msgstr "registración valida" -#: apps/member/models.py:145 apps/member/models.py:146 +#: apps/member/models.py:162 apps/member/models.py:163 msgid "user profile" msgstr "perfil usuario" -#: apps/member/models.py:156 -#, fuzzy -#| msgid "Activate your Note Kfet account" -msgid "Activate your Note Ker Lann account" +#: apps/member/models.py:173 +msgid "Activate your Note Kfet account" msgstr "Active su cuenta Note Kfet" -#: apps/member/models.py:187 +#: 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 +#: apps/wei/templates/wei/base.html:70 +#: apps/wei/templates/wei/weimembership_form.html:20 msgid "email" msgstr "correo electrónico" -#: apps/member/models.py:194 +#: apps/member/models.py:211 msgid "parent club" msgstr "club pariente" -#: apps/member/models.py:203 +#: apps/member/models.py:220 msgid "require memberships" msgstr "necesita afiliaciones" -#: apps/member/models.py:204 +#: 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:220 +#: 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:221 +#: 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:228 +#: 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:229 +#: 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:235 +#: 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:236 +#: 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:271 apps/member/models.py:296 +#: apps/member/models.py:288 apps/member/models.py:313 #: apps/note/models/notes.py:176 msgid "club" msgstr "club" -#: apps/member/models.py:272 +#: apps/member/models.py:289 msgid "clubs" msgstr "clubs" -#: apps/member/models.py:307 +#: apps/member/models.py:324 msgid "membership starts on" msgstr "afiliación empezá el" -#: apps/member/models.py:311 +#: apps/member/models.py:328 msgid "membership ends on" msgstr "afiliación termina el" -#: apps/member/models.py:404 +#: 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:413 apps/member/views.py:672 +#: 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:425 apps/member/views.py:681 +#: 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:459 +#: 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:462 apps/note/models/transactions.py:380 +#: apps/member/models.py:507 apps/note/models/transactions.py:389 msgid "membership" msgstr "afiliación" -#: apps/member/models.py:463 +#: apps/member/models.py:508 msgid "memberships" msgstr "afiliaciones" @@ -818,7 +877,18 @@ msgstr "afiliaciones" msgid "Renew" msgstr "Prorrogar" -#: apps/member/templates/member/add_members.html:16 +#: apps/member/templates/member/add_members.html:17 +#, python-format +msgid "" +"The user is not a member of the club·s %(clubs)s. An additional fee of " +"%(pretty_fee)s will be charged to renew automatically the membership in this/" +"these club·s." +msgstr "" +"El usuario no está miembro del/de los club·s parientes %(clubs)s. Un pago " +"adicional de %(pretty_fee)s sera cargado para prorrogar automáticamente la " +"afiliación a este/os club·s." + +#: apps/member/templates/member/add_members.html:22 #, python-format msgid "" "The user is not a member of the club·s %(clubs)s. Please create the required " @@ -827,7 +897,16 @@ msgstr "" "El usuario no está miembro del/de los club·s parientes %(clubs)s. Por favor " "crear la·s afiliación·es requerida·s, si no la afiliación fallará." -#: apps/member/templates/member/add_members.html:21 +#: apps/member/templates/member/add_members.html:29 +#, python-format +msgid "" +"This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will be " +"charged to adhere automatically to this/these club·s." +msgstr "" +"Este club tiene come pariente %(clubs)s. Un pago adicional de %(pretty_fee)s " +"sera cargado para registrar automáticamente a este/os club·s." + +#: apps/member/templates/member/add_members.html:34 #, python-format msgid "" "This club has parents %(clubs)s. Please make sure that the user is a member " @@ -844,6 +923,7 @@ msgstr "Cuenta n°" #: apps/member/templates/member/base.html:48 #: apps/member/templates/member/base.html:62 apps/member/views.py:60 #: apps/registration/templates/registration/future_profile_detail.html:48 +#: apps/wei/templates/wei/weimembership_form.html:117 msgid "Update Profile" msgstr "Modificar el perfil" @@ -917,7 +997,7 @@ msgid "Add" msgstr "Añadir" #: apps/member/templates/member/club_detail.html:13 -#: apps/permission/templates/permission/all_rights.html:77 +#: apps/permission/templates/permission/all_rights.html:32 msgid "Club managers" msgstr "Gerentes del club" @@ -927,6 +1007,7 @@ msgstr "Miembros del club" #: apps/member/templates/member/club_detail.html:40 #: apps/member/templates/member/profile_detail.html:32 +#: apps/wei/templates/wei/weiclub_detail.html:75 msgid "Transaction history" msgstr "Historial de las transacciones" @@ -943,6 +1024,7 @@ msgid "Filter roles:" msgstr "Filtrar los papeles :" #: apps/member/templates/member/club_members.html:36 +#: apps/wei/templates/wei/weimembership_list.html:19 msgid "There is no membership found with this pattern." msgstr "No hay afiliación encontrada con esta entrada." @@ -955,18 +1037,20 @@ msgid "days" msgstr "días" #: apps/member/templates/member/includes/club_info.html:31 +#: apps/wei/templates/wei/base.html:40 msgid "membership fee" msgstr "pago de afiliación" #: apps/member/templates/member/includes/club_info.html:43 #: apps/member/templates/member/includes/profile_info.html:55 #: apps/treasury/templates/treasury/sogecredit_detail.html:24 +#: apps/wei/templates/wei/base.html:60 msgid "balance" msgstr "saldo de la cuenta" #: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/profile_info.html:20 -#: apps/note/models/notes.py:287 +#: apps/note/models/notes.py:287 apps/wei/templates/wei/base.html:66 msgid "aliases" msgstr "alias" @@ -978,6 +1062,7 @@ msgstr "Gestionar los alias" #: apps/member/templates/member/includes/profile_info.html:7 #: apps/registration/templates/registration/future_profile_detail.html:19 #: apps/treasury/templates/treasury/sogecredit_detail.html:20 +#: apps/wei/templates/wei/weimembership_form.html:17 msgid "username" msgstr "nombre de usuario" @@ -1056,11 +1141,13 @@ msgstr "Podar y subir" #: apps/member/templates/member/profile_detail.html:11 #: apps/registration/templates/registration/future_profile_detail.html:28 +#: apps/wei/templates/wei/weimembership_form.html:26 msgid "This user doesn't have confirmed his/her e-mail address." msgstr "Este usuario no confirmó su correo electrónico." #: apps/member/templates/member/profile_detail.html:13 #: apps/registration/templates/registration/future_profile_detail.html:29 +#: apps/wei/templates/wei/weimembership_form.html:27 msgid "Click here to resend a validation link." msgstr "Hacer clic aquí para reenviar un enlace de validación." @@ -1073,17 +1160,10 @@ msgid "Note friendships" msgstr "Amistades de note" #: apps/member/templates/member/profile_trust.html:28 -#, fuzzy -#| msgid "" -#| "Adding someone as a friend enables them to initiate transactions coming " -#| "from your account (while keeping your balance positive). This is designed " -#| "to simplify using note kfet transfers to transfer money between users. " -#| "The intent is that one person can make all transfers for a group of " -#| "friends without needing additional rights among them." msgid "" "Adding someone as a friend enables them to initiate transactions coming from " "your account (while keeping your balance positive). This is designed to " -"simplify using note ker lann transfers to transfer money between users. The " +"simplify using note kfet transfers to transfer money between users. The " "intent is that one person can make all transfers for a group of friends " "without needing additional rights among them." msgstr "" @@ -1136,11 +1216,11 @@ msgstr "Detalles del club" msgid "Update club" msgstr "Modificar el club" -#: apps/member/views.py:569 +#: apps/member/views.py:574 msgid "Add new member to the club" msgstr "Añadir un nuevo miembro al club" -#: apps/member/views.py:663 +#: apps/member/views.py:703 apps/wei/views.py:973 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." @@ -1148,19 +1228,19 @@ msgstr "" "Este usuario no tiene suficiente dinero para unirse a este club, y no puede " "tener un saldo negativo." -#: apps/member/views.py:685 +#: apps/member/views.py:725 msgid "The membership must start after {:%m-%d-%Y}." msgstr "La afiliación tiene que empezar después del {:%d-%m-%Y}." -#: apps/member/views.py:690 +#: apps/member/views.py:730 msgid "The membership must begin before {:%m-%d-%Y}." msgstr "La afiliación tiene que empezar antes del {:%d-%m-%Y}." -#: apps/member/views.py:797 +#: apps/member/views.py:876 msgid "Manage roles of an user in the club" msgstr "Gestionar los papeles de un usuario en el club" -#: apps/member/views.py:821 +#: apps/member/views.py:901 msgid "Members of the club" msgstr "Miembros del club" @@ -1199,7 +1279,7 @@ msgstr "Destino" msgid "Reason" msgstr "Motivo" -#: apps/note/forms.py:79 +#: apps/note/forms.py:79 apps/treasury/tables.py:136 msgid "Valid" msgstr "Valido" @@ -1447,7 +1527,11 @@ msgstr "" msgid "first_name" msgstr "nombre" -#: apps/note/models/transactions.py:323 +#: apps/note/models/transactions.py:311 +msgid "bank" +msgstr "banco" + +#: apps/note/models/transactions.py:328 msgid "" "A special transaction is only possible between a Note associated to a " "payment method and a User or a Club" @@ -1455,24 +1539,25 @@ msgstr "" "Una transacción especial solo esta disponible entre una note de un modo de " "pago y un usuario o un club" -#: apps/note/models/transactions.py:349 apps/note/models/transactions.py:352 -#: env/lib/python3.11/site-packages/django/forms/fields.py:91 +#: apps/note/models/transactions.py:355 apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:361 apps/wei/views.py:978 +#: apps/wei/views.py:982 msgid "This field is required." msgstr "Este campo es obligatorio." -#: apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:367 msgid "Special transaction" msgstr "Transacción especial" -#: apps/note/models/transactions.py:359 +#: apps/note/models/transactions.py:368 msgid "Special transactions" msgstr "Transacciones especiales" -#: apps/note/models/transactions.py:375 +#: apps/note/models/transactions.py:384 msgid "membership transaction" msgstr "transacción de afiliación" -#: apps/note/models/transactions.py:376 +#: apps/note/models/transactions.py:385 apps/treasury/models.py:292 msgid "membership transactions" msgstr "transacciones de afiliación" @@ -1492,10 +1577,8 @@ msgstr "Ningún motivo dado" #: apps/treasury/tables.py:39 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:30 #: apps/treasury/templates/treasury/sogecredit_detail.html:65 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:499 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:13 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:38 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:7 +#: apps/wei/tables.py:75 apps/wei/tables.py:118 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:31 #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:18 #: note_kfet/templates/oauth2_provider/application_detail.html:39 #: note_kfet/templates/oauth2_provider/authorized-token-delete.html:12 @@ -1503,7 +1586,11 @@ msgid "Delete" msgstr "Suprimir" #: apps/note/tables.py:222 apps/note/templates/note/conso_form.html:132 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:37 +#: apps/wei/tables.py:49 apps/wei/tables.py:50 +#: apps/wei/templates/wei/base.html:89 +#: apps/wei/templates/wei/bus_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:40 #: note_kfet/templates/oauth2_provider/application_detail.html:38 msgid "Edit" msgstr "Editar" @@ -1548,28 +1635,23 @@ msgid "Double consumptions" msgstr "Consumiciones dobles" #: apps/note/templates/note/conso_form.html:154 -#: apps/note/templates/note/transaction_form.html:157 +#: apps/note/templates/note/transaction_form.html:163 msgid "Recent transactions history" msgstr "Historial de las transacciones recientes" #: apps/note/templates/note/mails/negative_balance.html:43 +#: apps/note/templates/note/mails/negative_balance.txt:25 #: apps/note/templates/note/mails/negative_notes_report.html:46 +#: apps/note/templates/note/mails/negative_notes_report.txt:13 #: apps/note/templates/note/mails/weekly_report.html:51 +#: apps/note/templates/note/mails/weekly_report.txt:32 #: apps/registration/templates/registration/mails/email_validation_email.html:40 #: apps/registration/templates/registration/mails/email_validation_email.txt:16 -#, fuzzy -#| msgid "Mail generated by the Note Kfet on the" -msgid "Mail generated by the Note Ker Lann on the" -msgstr "Correo electrónico enviado por la Note Kfet el" - -#: apps/note/templates/note/mails/negative_balance.txt:25 -#: apps/note/templates/note/mails/negative_notes_report.txt:13 -#: apps/note/templates/note/mails/weekly_report.txt:32 msgid "Mail generated by the Note Kfet on the" msgstr "Correo electrónico enviado por la Note Kfet el" #: apps/note/templates/note/transaction_form.html:58 -#: apps/note/templates/note/transaction_form.html:172 +#: apps/note/templates/note/transaction_form.html:178 msgid "Select emitters" msgstr "Elegir los remitentes" @@ -1578,7 +1660,7 @@ msgid "I am the emitter" msgstr "Estoy la fuente" #: apps/note/templates/note/transaction_form.html:85 -#: apps/note/templates/note/transaction_form.html:174 +#: apps/note/templates/note/transaction_form.html:180 msgid "Select receivers" msgstr "Elegir destinatarios" @@ -1587,25 +1669,26 @@ msgid "Action" msgstr "Acción" #: apps/note/templates/note/transaction_form.html:116 -#: apps/treasury/forms.py:135 apps/treasury/tables.py:67 +#: apps/treasury/forms.py:137 apps/treasury/tables.py:67 +#: apps/treasury/tables.py:132 #: apps/treasury/templates/treasury/remittance_form.html:23 msgid "Amount" msgstr "Monto" #: apps/note/templates/note/transaction_form.html:132 -#: apps/treasury/models.py:51 +#: apps/treasury/models.py:54 msgid "Name" msgstr "Nombre" -#: apps/note/templates/note/transaction_form.html:171 +#: apps/note/templates/note/transaction_form.html:177 msgid "Select emitter" msgstr "Elegir el remitente" -#: apps/note/templates/note/transaction_form.html:173 +#: apps/note/templates/note/transaction_form.html:179 msgid "Select receiver" msgstr "Elegir destinatario" -#: apps/note/templates/note/transaction_form.html:175 +#: apps/note/templates/note/transaction_form.html:181 msgid "Transfer type" msgstr "Tipo de transferencia" @@ -1740,7 +1823,7 @@ msgstr "" "terminó." #: apps/permission/models.py:183 -#: apps/permission/templates/permission/all_rights.html:56 +#: apps/permission/templates/permission/all_rights.html:89 msgid "permanent" msgstr "permanente" @@ -1793,56 +1876,63 @@ msgstr "" "Usted no tiene permiso a suprimir este instance of model {app_label}." "{model_name}." -#: apps/permission/templates/permission/all_rights.html:13 +#: apps/permission/templates/permission/all_rights.html:12 +msgid "Users that have surnormal rights" +msgstr "Lista de los usuarios poseyendo permisos majores" + +#: apps/permission/templates/permission/all_rights.html:16 +msgid "Superusers have all rights on everything, to manage the website." +msgstr "" +"Super-usuarios tienen todos los permisos sobre todo para gestionar el " +"sistema." + +#: apps/permission/templates/permission/all_rights.html:21 +msgid "Superusers" +msgstr "Super-usuarios" + +#: apps/permission/templates/permission/all_rights.html:45 msgid "Roles description" msgstr "Descripción de todos los papeles" -#: apps/permission/templates/permission/all_rights.html:20 +#: apps/permission/templates/permission/all_rights.html:52 msgid "Filter with roles that I have in at least one club" msgstr "Filtrar los papeles que tengo en al menos un club" -#: apps/permission/templates/permission/all_rights.html:36 +#: apps/permission/templates/permission/all_rights.html:69 msgid "Owned" msgstr "Tenido" -#: apps/permission/templates/permission/all_rights.html:47 +#: apps/permission/templates/permission/all_rights.html:80 msgid "Own this role in the clubs" msgstr "Tiene este papel en los clubs" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Mask:" msgstr "Antifaz :" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Query:" msgstr "Consulta :" -#: apps/permission/templates/permission/all_rights.html:59 +#: apps/permission/templates/permission/all_rights.html:92 msgid "No associated permission" msgstr "No hay permiso relacionado" -#: apps/permission/templates/permission/all_rights.html:71 -msgid "Users that have surnormal rights" -msgstr "Lista de los usuarios poseyendo permisos majores" - #: apps/permission/templates/permission/scopes.html:8 msgid "Available scopes" msgstr "" #: apps/permission/templates/permission/scopes.html:42 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:24 msgid "No applications defined" msgstr "Ninguna aplicación definida" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "Click here" msgstr "Pulsar aquí" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "if you want to register a new one" msgstr "si quiere crear una nueva" @@ -1861,7 +1951,7 @@ msgid "" "with these parameters. Please correct your data and retry." msgstr "" -#: apps/permission/views.py:112 note_kfet/templates/base.html:102 +#: apps/permission/views.py:112 note_kfet/templates/base.html:108 msgid "Rights" msgstr "Permisos" @@ -1877,21 +1967,41 @@ msgstr "afiliación" msgid "This email address is already used." msgstr "Este correo electrónico ya esta utilizado." -#: apps/registration/forms.py:78 +#: apps/registration/forms.py:49 +msgid "" +"I declare that I opened or I will open soon a bank account in the Société " +"générale with the BDE partnership." +msgstr "" +"Declaro que ya abrió una cuenta a la Société Générale en colaboración con el " +"BDE." + +#: apps/registration/forms.py:51 +msgid "" +"Warning: this engages you to open your bank account. If you finally decides " +"to don't open your account, you will have to pay the BDE membership." +msgstr "" +"Cuidado : esto le obliga abrir su cuenta bancaria. Si cambia de idea y no " +"abre su cuenta bancaria, tendrá que pagar su afiliación al BDE." + +#: apps/registration/forms.py:59 +msgid "Register to the WEI" +msgstr "Registrarse en el WEI" + +#: apps/registration/forms.py:61 +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." +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:106 msgid "Join BDE Club" msgstr "Afiliarse al club BDE" -#: apps/registration/forms.py:84 -#, fuzzy -#| msgid "Join BDE Club" -msgid "Join BDA Club" -msgstr "Afiliarse al club BDE" - -#: apps/registration/forms.py:90 -#, fuzzy -#| msgid "Join BDE Club" -msgid "Join BDS Club" -msgstr "Afiliarse al club BDE" +#: apps/registration/forms.py:113 +msgid "Join Kfet Club" +msgstr "Afiliarse al club Kfet" #: apps/registration/templates/registration/email_validation_complete.html:15 msgid "Your email have successfully been validated." @@ -1903,11 +2013,8 @@ msgid "You can now log in." msgstr "Puede desde ahora conectarse." #: apps/registration/templates/registration/email_validation_complete.html:23 -#, fuzzy -#| msgid "" -#| "You must pay now your membership in the Kfet to complete your " -#| "registration." -msgid "You must pay now your membership to complete your registration." +msgid "" +"You must pay now your membership in the Kfet to complete your registration." msgstr "Tiene que pagar su afiliación a la Kfet para acabar con su afiliación." #: apps/registration/templates/registration/email_validation_complete.html:28 @@ -1930,16 +2037,13 @@ msgstr "" "activar su cuenta." #: apps/registration/templates/registration/email_validation_email_sent.html:17 -#, fuzzy -#| msgid "" -#| "You must pay now your membership in the Kfet to complete your " -#| "registration." -msgid "" -"You must also pay your membership. A administrator will then activate your " -"account" -msgstr "Tiene que pagar su afiliación a la Kfet para acabar con su afiliación." +msgid "You must also go to the Kfet to pay your membership." +msgstr "" +"También tendrá que ir en la Kfet para pagar su afiliación. La afiliación al " +"WEI incluye una afiliación al BDE." #: apps/registration/templates/registration/future_profile_detail.html:49 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:11 msgid "Delete registration" msgstr "Suprimir afiliación" @@ -1947,7 +2051,14 @@ msgstr "Suprimir afiliación" msgid "Validate account" msgstr "Validar la cuenta" -#: apps/registration/templates/registration/future_profile_detail.html:65 +#: apps/registration/templates/registration/future_profile_detail.html:62 +msgid "" +"The user declared that he/she opened a bank account in the Société générale." +msgstr "El usuario declara que ya abrió una cuenta a la Société Générale." + +#: apps/registration/templates/registration/future_profile_detail.html:71 +#: apps/wei/templates/wei/weimembership_form.html:127 +#: apps/wei/templates/wei/weimembership_form.html:186 msgid "Validate registration" msgstr "Validar la afiliación" @@ -1955,12 +2066,6 @@ msgstr "Validar la afiliación" msgid "New user" msgstr "Nuevo usuario" -#: apps/registration/templates/registration/mails/email_validation_email.html:7 -#, fuzzy -#| msgid "Activate your Note Kfet account" -msgid "Activation of your Note Ker Lann account" -msgstr "Active su cuenta Note Kfet" - #: apps/registration/templates/registration/mails/email_validation_email.html:12 #: apps/registration/templates/registration/mails/email_validation_email.txt:3 msgid "Hi" @@ -1968,13 +2073,9 @@ msgstr "Hola" #: apps/registration/templates/registration/mails/email_validation_email.html:16 #: apps/registration/templates/registration/mails/email_validation_email.txt:5 -#, fuzzy -#| msgid "" -#| "You recently registered on the Note Kfet. Please click on the link below " -#| "to confirm your registration." msgid "" -"You recently registered on the Note Ker Lann. Please click on the link below " -"to confirm your registration." +"You recently registered on the Note Kfet. Please click on the link below to " +"confirm your registration." msgstr "" "Usted registró recientemente a la Note Kfet. Por favor haga clic en el " "enlace más abajo para validar sur afiliación." @@ -1989,13 +2090,9 @@ msgstr "" #: apps/registration/templates/registration/mails/email_validation_email.html:30 #: apps/registration/templates/registration/mails/email_validation_email.txt:11 -#, fuzzy -#| msgid "" -#| "After that, you'll have to wait that someone validates your account " -#| "before you can log in. You will need to pay your membership in the Kfet." msgid "" "After that, you'll have to wait that someone validates your account before " -"you can log in. You will need to pay your membership." +"you can log in. You will need to pay your membership in the Kfet." msgstr "" "Después de esto, tendrá que esperar que alguien validará su cuenta antes que " "usted pueda conectarse. Tendrá que pagar su afiliación en la Kfet. La " @@ -2008,55 +2105,57 @@ msgstr "Gracias" #: apps/registration/templates/registration/mails/email_validation_email.html:39 #: apps/registration/templates/registration/mails/email_validation_email.txt:15 -#, fuzzy -#| msgid "The Note Kfet team." -msgid "The Note Ker Lann team." +msgid "The Note Kfet team." msgstr "El equipo Note Kfet." -#: apps/registration/views.py:39 +#: apps/registration/views.py:40 msgid "Register new user" msgstr "Registrar un nuevo usuario" -#: apps/registration/views.py:89 +#: apps/registration/views.py:98 msgid "Email validation" msgstr "Validación del correo electrónico" -#: apps/registration/views.py:91 +#: apps/registration/views.py:100 msgid "Validate email" msgstr "Validar el correo electrónico" -#: apps/registration/views.py:135 +#: apps/registration/views.py:144 msgid "Email validation unsuccessful" msgstr "La validación del correo electrónico fracasó" -#: apps/registration/views.py:146 +#: apps/registration/views.py:155 msgid "Email validation email sent" msgstr "Correo de validación enviado" -#: apps/registration/views.py:154 +#: apps/registration/views.py:163 msgid "Resend email validation link" msgstr "Reenviar el enlace de validación" -#: apps/registration/views.py:172 +#: apps/registration/views.py:181 msgid "Pre-registered users list" msgstr "Lista de los usuarios con afiliación pendiente" -#: apps/registration/views.py:196 +#: apps/registration/views.py:205 msgid "Unregistered users" msgstr "Usuarios con afiliación pendiente" -#: apps/registration/views.py:209 +#: apps/registration/views.py:218 msgid "Registration detail" msgstr "Detalles de la afiliación" -#: apps/registration/views.py:281 +#: apps/registration/views.py:282 +msgid "You must join the BDE." +msgstr "Usted tiene que afiliarse al BDE." + +#: apps/registration/views.py:306 msgid "" "The entered amount is not enough for the memberships, should be at least {}" msgstr "" "El monto dado no es suficiente para las afiliaciones, tiene que ser al menos " "{}" -#: apps/registration/views.py:335 +#: apps/registration/views.py:387 msgid "Invalidate pre-registration" msgstr "Invalidar la afiliación" @@ -2064,7 +2163,7 @@ msgstr "Invalidar la afiliación" msgid "Treasury" msgstr "Tesorería" -#: apps/treasury/forms.py:26 apps/treasury/models.py:90 +#: apps/treasury/forms.py:26 apps/treasury/models.py:93 #: apps/treasury/templates/treasury/invoice_form.html:22 msgid "This invoice is locked and can no longer be edited." msgstr "Esta factura esta bloqueada y no puede ser modificada." @@ -2077,7 +2176,7 @@ msgstr "El descuento ya esta cerrado." msgid "You can't change the type of the remittance." msgstr "No puede cambiar el tipo de descuento." -#: apps/treasury/forms.py:125 apps/treasury/models.py:264 +#: apps/treasury/forms.py:125 apps/treasury/models.py:267 #: apps/treasury/tables.py:97 apps/treasury/tables.py:105 #: apps/treasury/templates/treasury/invoice_list.html:16 #: apps/treasury/templates/treasury/remittance_list.html:16 @@ -2093,113 +2192,138 @@ msgstr "No hay descuento relacionado" msgid "Invoice identifier" msgstr "Numero de factura" -#: apps/treasury/models.py:37 -#, fuzzy -#| msgid "BDE" -msgid "BD?" +#: apps/treasury/models.py:40 +msgid "BDE" msgstr "BDE" -#: apps/treasury/models.py:42 +#: apps/treasury/models.py:45 msgid "Object" msgstr "Asunto" -#: apps/treasury/models.py:46 +#: apps/treasury/models.py:49 msgid "Description" msgstr "Descripción" -#: apps/treasury/models.py:55 +#: apps/treasury/models.py:58 msgid "Address" msgstr "Dirección" -#: apps/treasury/models.py:60 apps/treasury/models.py:190 +#: apps/treasury/models.py:63 apps/treasury/models.py:193 msgid "Date" msgstr "Fecha" -#: apps/treasury/models.py:64 +#: apps/treasury/models.py:67 msgid "Acquitted" msgstr "Pagada" -#: apps/treasury/models.py:69 +#: apps/treasury/models.py:72 msgid "Locked" msgstr "Bloqueada" -#: apps/treasury/models.py:70 +#: apps/treasury/models.py:73 msgid "An invoice can't be edited when it is locked." msgstr "Une factura no puede ser modificada cuando esta bloqueada." -#: apps/treasury/models.py:76 +#: apps/treasury/models.py:79 msgid "tex source" msgstr "código fuente TeX" -#: apps/treasury/models.py:110 apps/treasury/models.py:126 +#: apps/treasury/models.py:113 apps/treasury/models.py:129 msgid "invoice" msgstr "factura" -#: apps/treasury/models.py:111 +#: apps/treasury/models.py:114 msgid "invoices" msgstr "facturas" -#: apps/treasury/models.py:114 +#: apps/treasury/models.py:117 #, python-brace-format msgid "Invoice #{id}" msgstr "Factura n°{id}" -#: apps/treasury/models.py:131 +#: apps/treasury/models.py:134 msgid "Designation" msgstr "Designación" -#: apps/treasury/models.py:137 +#: apps/treasury/models.py:140 msgid "Quantity" msgstr "Cantidad" -#: apps/treasury/models.py:142 +#: apps/treasury/models.py:145 msgid "Unit price" msgstr "Precio unitario" -#: apps/treasury/models.py:158 +#: apps/treasury/models.py:161 msgid "product" msgstr "producto" -#: apps/treasury/models.py:159 +#: apps/treasury/models.py:162 msgid "products" msgstr "productos" -#: apps/treasury/models.py:179 +#: apps/treasury/models.py:182 msgid "remittance type" msgstr "tipo de descuento" -#: apps/treasury/models.py:180 +#: apps/treasury/models.py:183 msgid "remittance types" msgstr "tipos de descuentos" -#: apps/treasury/models.py:201 +#: apps/treasury/models.py:204 msgid "Comment" msgstr "Comentario" -#: apps/treasury/models.py:206 +#: apps/treasury/models.py:209 msgid "Closed" msgstr "Cerrada" -#: apps/treasury/models.py:210 +#: apps/treasury/models.py:213 msgid "remittance" msgstr "descuento" -#: apps/treasury/models.py:211 +#: apps/treasury/models.py:214 msgid "remittances" msgstr "descuentos" -#: apps/treasury/models.py:244 +#: apps/treasury/models.py:247 msgid "Remittance #{:d}: {}" msgstr "Descuento n°{:d} : {}" -#: apps/treasury/models.py:268 +#: apps/treasury/models.py:271 msgid "special transaction proxy" msgstr "proxy de transacción especial" -#: apps/treasury/models.py:269 +#: apps/treasury/models.py:272 msgid "special transaction proxies" msgstr "proxys de transacciones especiales" +#: apps/treasury/models.py:298 +msgid "credit transaction" +msgstr "transacción de crédito" + +#: apps/treasury/models.py:430 +msgid "" +"This user doesn't have enough money to pay the memberships with its note. " +"Please ask her/him to credit the note before invalidating this credit." +msgstr "" +"Este usuario no tiene suficiente dinero en su note para pagar las " +"afiliaciones. Por favor pídelo acreditar su note antes de invalidar este " +"crédito." + +#: apps/treasury/models.py:451 +#: apps/treasury/templates/treasury/sogecredit_detail.html:10 +msgid "Credit from the Société générale" +msgstr "Crédito de la Société Générale" + +#: apps/treasury/models.py:452 +msgid "Credits from the Société générale" +msgstr "Créditos de la Société Générale" + +#: apps/treasury/models.py:455 +#, python-brace-format +msgid "Soge credit for {user}" +msgstr "Crédito de la Société Générale para {user}" + #: apps/treasury/tables.py:20 msgid "Invoice #{:d}" msgstr "Factura n°{:d}" @@ -2219,6 +2343,10 @@ msgstr "Cantidad de transacciones" msgid "View" msgstr "Ver" +#: apps/treasury/tables.py:143 +msgid "Yes" +msgstr "Sí" + #: apps/treasury/templates/treasury/invoice_confirm_delete.html:10 #: apps/treasury/views.py:180 msgid "Delete invoice" @@ -2256,7 +2384,13 @@ msgstr "Añadir un producto" msgid "Remove product" msgstr "Quitar un producto" -#: apps/treasury/templates/treasury/invoice_list.html:28 +#: apps/treasury/templates/treasury/invoice_list.html:19 +#: apps/treasury/templates/treasury/remittance_list.html:19 +#: apps/treasury/templates/treasury/sogecredit_list.html:20 +msgid "Société générale credits" +msgstr "Créditos de la Société Générale" + +#: apps/treasury/templates/treasury/invoice_list.html:31 msgid "New invoice" msgstr "Nueva factura" @@ -2276,46 +2410,42 @@ msgstr "Transacciones vinculadas" msgid "There is no transaction linked with this remittance." msgstr "No hay transacción vinculada con este descuento." -#: apps/treasury/templates/treasury/remittance_list.html:24 +#: apps/treasury/templates/treasury/remittance_list.html:27 msgid "Opened remittances" msgstr "Descuentos abiertos" -#: apps/treasury/templates/treasury/remittance_list.html:31 +#: apps/treasury/templates/treasury/remittance_list.html:34 msgid "There is no opened remittance." msgstr "No hay descuento abierto." -#: apps/treasury/templates/treasury/remittance_list.html:36 +#: apps/treasury/templates/treasury/remittance_list.html:39 msgid "New remittance" msgstr "Nuevo descuento" -#: apps/treasury/templates/treasury/remittance_list.html:42 +#: apps/treasury/templates/treasury/remittance_list.html:45 msgid "Transfers without remittances" msgstr "Transacciones sin descuento" -#: apps/treasury/templates/treasury/remittance_list.html:49 +#: apps/treasury/templates/treasury/remittance_list.html:52 msgid "There is no transaction without any linked remittance." msgstr "No hay transacción sin descuento vinculado." -#: apps/treasury/templates/treasury/remittance_list.html:57 +#: apps/treasury/templates/treasury/remittance_list.html:60 msgid "Transfers with opened remittances" msgstr "Transacciones con un descuento abierto" -#: apps/treasury/templates/treasury/remittance_list.html:64 +#: apps/treasury/templates/treasury/remittance_list.html:67 msgid "There is no transaction with an opened linked remittance." msgstr "No hay transacción con un descuento abierto." -#: apps/treasury/templates/treasury/remittance_list.html:72 +#: apps/treasury/templates/treasury/remittance_list.html:75 msgid "Closed remittances" msgstr "Descuentos cerrados" -#: apps/treasury/templates/treasury/remittance_list.html:79 +#: apps/treasury/templates/treasury/remittance_list.html:82 msgid "There is no closed remittance yet." msgstr "Por ahora no hay descuentos cerrados." -#: apps/treasury/templates/treasury/sogecredit_detail.html:10 -msgid "Credit from the Société générale" -msgstr "Crédito de la Société Générale" - #: apps/treasury/templates/treasury/sogecredit_detail.html:35 msgid "total amount" msgstr "monto total" @@ -2366,6 +2496,7 @@ msgstr "" "Por favor pide al usuario acreditar su note antes de suprimir este crédito." #: apps/treasury/templates/treasury/sogecredit_detail.html:63 +#: apps/wei/tables.py:60 apps/wei/tables.py:102 msgid "Validate" msgstr "Validar" @@ -2373,10 +2504,6 @@ msgstr "Validar" msgid "Return to credit list" msgstr "Regresar a la lista de los créditos" -#: apps/treasury/templates/treasury/sogecredit_list.html:20 -msgid "Société générale credits" -msgstr "Créditos de la Société Générale" - #: apps/treasury/templates/treasury/sogecredit_list.html:40 msgid "Filter with unvalidated credits only" msgstr "Filtrar con créditos invalidados unicamente" @@ -2403,6 +2530,7 @@ msgid "Invoices list" msgstr "Lista de las facturas" #: apps/treasury/views.py:112 apps/treasury/views.py:286 +#: apps/treasury/views.py:412 msgid "You are not able to see the treasury interface." msgstr "Usted no tiene derecho a ver la interfaz de tesorería." @@ -2426,1472 +2554,635 @@ msgstr "Modificar un descuento" msgid "Attach a transaction to a remittance" msgstr "Unir una transacción con un descuento" -#: env/lib/python3.11/site-packages/django/contrib/messages/apps.py:15 -msgid "Messages" +#: apps/treasury/views.py:404 +msgid "List of credits from the Société générale" +msgstr "Lista de los créditos de la Société Générale" + +#: apps/treasury/views.py:449 +msgid "Manage credits from the Société générale" +msgstr "Gestionar los créditos de la Société Générale" + +#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51 +#: apps/wei/models.py:62 apps/wei/models.py:180 +#: note_kfet/templates/base.html:102 +msgid "WEI" +msgstr "WEI" + +#: apps/wei/forms/registration.py:35 +msgid "The selected user is not validated. Please validate its account first" msgstr "" +"El usuario seleccionado no ha sido validado. Validar esta cuenta primero" -#: env/lib/python3.11/site-packages/django/contrib/sitemaps/apps.py:8 -msgid "Site Maps" -msgstr "" +#: apps/wei/forms/registration.py:59 apps/wei/models.py:126 +#: apps/wei/models.py:323 +msgid "bus" +msgstr "bus" -#: env/lib/python3.11/site-packages/django/contrib/staticfiles/apps.py:9 -msgid "Static Files" -msgstr "" - -#: env/lib/python3.11/site-packages/django/contrib/syndication/apps.py:7 -#, fuzzy -#| msgid "Invitation" -msgid "Syndication" -msgstr "Invitación" - -#. Translators: String used to replace omitted page numbers in elided page -#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. -#: env/lib/python3.11/site-packages/django/core/paginator.py:30 -msgid "…" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:50 -msgid "That page number is not an integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:52 -msgid "That page number is less than 1" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:54 -#, fuzzy -#| msgid "There is no results." -msgid "That page contains no results" -msgstr "No hay resultado." - -#: env/lib/python3.11/site-packages/django/core/validators.py:22 -msgid "Enter a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:104 -#: env/lib/python3.11/site-packages/django/forms/fields.py:752 -msgid "Enter a valid URL." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:165 -msgid "Enter a valid integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:176 -msgid "Enter a valid email address." -msgstr "" - -#. Translators: "letters" means latin letters: a-z and A-Z. -#: env/lib/python3.11/site-packages/django/core/validators.py:259 +#: apps/wei/forms/registration.py:60 msgid "" -"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +"This choice is not definitive. The WEI organizers are free to attribute for " +"you a bus and a team, in particular if you are a free eletron." msgstr "" +"Esta elección no es definitiva. Los organizadores del WEI se quedan con el " +"derecho de imponer su bus y su equipo, en particular para los electrones " +"libres." -#: env/lib/python3.11/site-packages/django/core/validators.py:267 +#: apps/wei/forms/registration.py:67 +msgid "Team" +msgstr "Equipo" + +#: apps/wei/forms/registration.py:69 msgid "" -"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " -"hyphens." +"Leave this field empty if you won't be in a team (staff, bus chief, free " +"electron)" msgstr "" +"Deje este campo vacío si no quiere estar en un equipo (staff, jefe de bus, " +"electrón libre)" -#: env/lib/python3.11/site-packages/django/core/validators.py:279 -#: env/lib/python3.11/site-packages/django/core/validators.py:287 -#: env/lib/python3.11/site-packages/django/core/validators.py:316 -msgid "Enter a valid IPv4 address." +#: apps/wei/forms/registration.py:75 apps/wei/forms/registration.py:85 +#: apps/wei/models.py:161 +msgid "WEI Roles" +msgstr "Papeles en el WEI" + +#: apps/wei/forms/registration.py:76 +msgid "Select the roles that you are interested in." +msgstr "Elegir los papeles que le interesa." + +#: apps/wei/forms/registration.py:122 +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:35 +msgid "Choose a word:" +msgstr "Elegir una palabra :" + +#: apps/wei/models.py:25 apps/wei/templates/wei/base.html:36 +msgid "year" +msgstr "año" + +#: apps/wei/models.py:29 apps/wei/templates/wei/base.html:30 +msgid "date start" +msgstr "fecha de inicio" + +#: apps/wei/models.py:33 apps/wei/templates/wei/base.html:33 +msgid "date end" +msgstr "fecha de fin" + +#: apps/wei/models.py:71 apps/wei/tables.py:305 +msgid "seat count in the bus" +msgstr "cantidad de asientos en el bus" + +#: apps/wei/models.py:83 +msgid "survey information" +msgstr "informaciones sobre el cuestionario" + +#: apps/wei/models.py:84 +msgid "Information about the survey for new members, encoded in JSON" msgstr "" +"Informaciones sobre el cuestionario para los nuevos miembros, registrado en " +"JSON" -#: env/lib/python3.11/site-packages/django/core/validators.py:296 -#: env/lib/python3.11/site-packages/django/core/validators.py:317 -msgid "Enter a valid IPv6 address." -msgstr "" +#: apps/wei/models.py:113 +msgid "Bus" +msgstr "Bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:308 -#: env/lib/python3.11/site-packages/django/core/validators.py:315 -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "" +#: apps/wei/models.py:114 apps/wei/templates/wei/weiclub_detail.html:51 +msgid "Buses" +msgstr "Bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:351 -msgid "Enter only digits separated by commas." -msgstr "" +#: apps/wei/models.py:135 +msgid "color" +msgstr "color" -#: env/lib/python3.11/site-packages/django/core/validators.py:357 -#, python-format -msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "" +#: apps/wei/models.py:136 +msgid "The color of the T-Shirt, stored with its number equivalent" +msgstr "El color de la camiseta, registrado con su número equivalente" -#: env/lib/python3.11/site-packages/django/core/validators.py:392 -#, python-format -msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:150 +msgid "Bus team" +msgstr "Equipo de bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:401 -#, python-format -msgid "Ensure this value is greater than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:151 +msgid "Bus teams" +msgstr "Equipos de bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:410 -#, python-format -msgid "Ensure this value is a multiple of step size %(limit_value)s." -msgstr "" +#: apps/wei/models.py:160 +msgid "WEI Role" +msgstr "Papeles en el WEI" -#: env/lib/python3.11/site-packages/django/core/validators.py:420 -#, python-format +#: apps/wei/models.py:185 +msgid "Credit from Société générale" +msgstr "Crédito de la Société Générale" + +#: apps/wei/models.py:190 +msgid "Caution check given" +msgstr "Cheque de garantía dado" + +#: apps/wei/models.py:194 apps/wei/templates/wei/weimembership_form.html:64 +msgid "birth date" +msgstr "fecha de nacimiento" + +#: apps/wei/models.py:200 apps/wei/models.py:210 +msgid "Male" +msgstr "Hombre" + +#: apps/wei/models.py:201 apps/wei/models.py:211 +msgid "Female" +msgstr "Mujer" + +#: apps/wei/models.py:202 +msgid "Non binary" +msgstr "No binari@" + +#: apps/wei/models.py:204 apps/wei/templates/wei/attribute_bus_1A.html:22 +#: apps/wei/templates/wei/weimembership_form.html:55 +msgid "gender" +msgstr "género" + +#: apps/wei/models.py:213 apps/wei/templates/wei/weimembership_form.html:58 +msgid "clothing cut" +msgstr "forma de ropa" + +#: apps/wei/models.py:226 apps/wei/templates/wei/weimembership_form.html:61 +msgid "clothing size" +msgstr "medida de ropa" + +#: apps/wei/models.py:232 apps/wei/templates/wei/attribute_bus_1A.html:28 +#: apps/wei/templates/wei/weimembership_form.html:67 +msgid "health issues" +msgstr "problemas de salud" + +#: apps/wei/models.py:237 apps/wei/templates/wei/weimembership_form.html:70 +msgid "emergency contact name" +msgstr "nombre del contacto de emergencia" + +#: apps/wei/models.py:242 apps/wei/templates/wei/weimembership_form.html:73 +msgid "emergency contact phone" +msgstr "teléfono del contacto de emergencia" + +#: apps/wei/models.py:247 apps/wei/templates/wei/weimembership_form.html:52 +msgid "first year" +msgstr "primer año" + +#: apps/wei/models.py:248 +msgid "Tells if the user is new in the school." +msgstr "Indica si el usuario es nuevo en la escuela." + +#: apps/wei/models.py:253 +msgid "registration information" +msgstr "informaciones sobre la afiliación" + +#: apps/wei/models.py:254 msgid "" -"Ensure this value has at least %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at least %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:438 -#, python-format -msgid "" -"Ensure this value has at most %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at most %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:461 -#: env/lib/python3.11/site-packages/django/forms/fields.py:347 -#: env/lib/python3.11/site-packages/django/forms/fields.py:386 -#, fuzzy -#| msgid "phone number" -msgid "Enter a number." -msgstr "número de teléfono" - -#: env/lib/python3.11/site-packages/django/core/validators.py:463 -#, python-format -msgid "Ensure that there are no more than %(max)s digit in total." -msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:468 -#, python-format -msgid "Ensure that there are no more than %(max)s decimal place." -msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:473 -#, python-format -msgid "" -"Ensure that there are no more than %(max)s digit before the decimal point." -msgid_plural "" -"Ensure that there are no more than %(max)s digits before the decimal point." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:544 -#, python-format -msgid "" -"File extension “%(extension)s” is not allowed. Allowed extensions are: " -"%(allowed_extensions)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:605 -msgid "Null characters are not allowed." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1423 -#: env/lib/python3.11/site-packages/django/forms/models.py:893 -#, fuzzy -#| msgid "add" -msgid "and" -msgstr "añadir" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1425 -#, fuzzy, python-format -#| msgid "A template with this name already exist" -msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "Un plantilla de transacción con un nombre similar ya existe" - -#: env/lib/python3.11/site-packages/django/db/models/constraints.py:17 -#, python-format -msgid "Constraint “%(name)s” is violated." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:128 -#, python-format -msgid "Value %(value)r is not a valid choice." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:129 -#, fuzzy -#| msgid "This image cannot be loaded." -msgid "This field cannot be null." -msgstr "Esta imagen no puede ser cargada." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:130 -#, fuzzy -#| msgid "This image cannot be loaded." -msgid "This field cannot be blank." -msgstr "Esta imagen no puede ser cargada." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:131 -#, fuzzy, python-format -#| msgid "A template with this name already exist" -msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "Un plantilla de transacción con un nombre similar ya existe" - -#. Translators: The 'lookup_type' is one of 'date', 'year' or -#. 'month'. Eg: "Title must be unique for pub_date year" -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:135 -#, python-format -msgid "" -"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:173 -#, python-format -msgid "Field of type: %(field_type)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1094 -#, python-format -msgid "“%(value)s” value must be either True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1095 -#, python-format -msgid "“%(value)s” value must be either True, False, or None." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1097 -msgid "Boolean (Either True or False)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1147 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1149 -msgid "String (unlimited)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1253 -msgid "Comma-separated integers" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1354 -#, python-format -msgid "" -"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1358 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1493 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " -"date." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1362 -msgid "Date (without time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1489 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." -"uuuuuu]][TZ] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1497 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" -"[TZ]) but it is an invalid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1502 -msgid "Date (with time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1626 -#, python-format -msgid "“%(value)s” value must be a decimal number." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1628 -#, fuzzy -#| msgid "phone number" -msgid "Decimal number" -msgstr "número de teléfono" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1789 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." -"uuuuuu] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1793 -#, fuzzy -#| msgid "action" -msgid "Duration" -msgstr "acción" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1845 -#, fuzzy -#| msgid "address" -msgid "Email address" -msgstr "dirección" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1870 -msgid "File path" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1948 -#, python-format -msgid "“%(value)s” value must be a float." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1950 -#, fuzzy -#| msgid "phone number" -msgid "Floating point number" -msgstr "número de teléfono" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1990 -#, python-format -msgid "“%(value)s” value must be an integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1992 -msgid "Integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2088 -msgid "Big (8 byte) integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2105 -msgid "Small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2113 -#, fuzzy -#| msgid "IP Address" -msgid "IPv4 address" -msgstr "Dirección IP" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2144 -#, fuzzy -#| msgid "IP Address" -msgid "IP address" -msgstr "Dirección IP" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2237 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2238 -#, python-format -msgid "“%(value)s” value must be either None, True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2240 -msgid "Boolean (Either True, False or None)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2291 -msgid "Positive big integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2306 -msgid "Positive integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2321 -msgid "Positive small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2337 -#, python-format -msgid "Slug (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2373 -msgid "Text" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2448 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2452 -#, python-format -msgid "" -"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " -"invalid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2456 -msgid "Time" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2564 -msgid "URL" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2588 -msgid "Raw binary data" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2653 -#, python-format -msgid "“%(value)s” is not a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2655 -#, fuzzy -#| msgid "Invoice identifier" -msgid "Universally unique identifier" -msgstr "Numero de factura" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:232 -msgid "File" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:393 -msgid "Image" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:26 -#, fuzzy -#| msgid "Object" -msgid "A JSON object" -msgstr "Asunto" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:28 -#, fuzzy -#| msgid "This address must be valid." -msgid "Value must be valid JSON." -msgstr "Este correo tiene que ser valido." - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:919 -#, python-format -msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:921 -msgid "Foreign Key (type determined by related field)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1212 -msgid "One-to-one relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1269 -#, python-format -msgid "%(from)s-%(to)s relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1271 -#, python-format -msgid "%(from)s-%(to)s relationships" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1319 -msgid "Many-to-many relationship" -msgstr "" - -#. Translators: If found as last label character, these punctuation -#. characters will prevent the default label_suffix to be appended to the label -#: env/lib/python3.11/site-packages/django/forms/boundfield.py:184 -msgid ":?.!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:298 -#, fuzzy -#| msgid "phone number" -msgid "Enter a whole number." -msgstr "número de teléfono" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:467 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1241 -#, fuzzy -#| msgid "invalidate" -msgid "Enter a valid date." -msgstr "invalidar" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:490 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1242 -msgid "Enter a valid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:517 -msgid "Enter a valid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:551 -#, fuzzy -#| msgid "Email validation" -msgid "Enter a valid duration." -msgstr "Validación del correo electrónico" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:552 -#, python-brace-format -msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:621 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:622 -msgid "No file was submitted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:623 -msgid "The submitted file is empty." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:625 -#, python-format -msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." -msgid_plural "" -"Ensure this filename has at most %(max)d characters (it has %(length)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:630 -msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:694 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:857 -#: env/lib/python3.11/site-packages/django/forms/fields.py:949 -#: env/lib/python3.11/site-packages/django/forms/models.py:1566 -#, python-format -msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:951 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1070 -#: env/lib/python3.11/site-packages/django/forms/models.py:1564 -msgid "Enter a list of values." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1071 -msgid "Enter a complete value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1310 -msgid "Enter a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1340 -msgid "Enter a valid JSON." -msgstr "" - -#. Translators: This is the default suffix added to form field labels -#: env/lib/python3.11/site-packages/django/forms/forms.py:98 -msgid ":" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/forms.py:244 -#: env/lib/python3.11/site-packages/django/forms/forms.py:328 -#, python-format -msgid "(Hidden field %(name)s) %(error)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:63 -#, python-format -msgid "" -"ManagementForm data is missing or has been tampered with. Missing fields: " -"%(field_names)s. You may need to file a bug report if the issue persists." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:67 -#, python-format -msgid "Please submit at most %(num)d form." -msgid_plural "Please submit at most %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:72 -#, python-format -msgid "Please submit at least %(num)d form." -msgid_plural "Please submit at least %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:484 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:491 -msgid "Order" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:886 -#, python-format -msgid "Please correct the duplicate data for %(field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:891 -#, python-format -msgid "Please correct the duplicate data for %(field)s, which must be unique." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:898 -#, python-format -msgid "" -"Please correct the duplicate data for %(field_name)s which must be unique " -"for the %(lookup)s in %(date_field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:907 -msgid "Please correct the duplicate values below." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1338 -msgid "The inline value did not match the parent instance." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1429 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1568 -#, python-format -msgid "“%(pk)s” is not a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/utils.py:226 -#, python-format -msgid "" -"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " -"may be ambiguous or it may not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:463 -msgid "Clear" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:464 -#, fuzzy -#| msgid "Current activity" -msgid "Currently" -msgstr "Actividad actual" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:465 -#, fuzzy -#| msgid "change" -msgid "Change" -msgstr "cambiar" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:794 -msgid "Unknown" -msgstr "" - -#. Translators: Please do not add spaces around commas. -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:861 -msgid "yes,no,maybe" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:891 -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:908 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:910 -#, python-format -msgid "%s KB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:912 -#, python-format -msgid "%s MB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:914 -#, python-format -msgid "%s GB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:916 -#, python-format -msgid "%s TB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:918 -#, python-format -msgid "%s PB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:73 -msgid "p.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:74 -msgid "a.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:79 -msgid "PM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:80 -msgid "AM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:152 -msgid "midnight" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:154 -msgid "noon" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:7 -msgid "Monday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:8 -msgid "Tuesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:9 -msgid "Wednesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:10 -msgid "Thursday" +"Information about the registration (buses for old members, survey for the " +"new members), encoded in JSON" msgstr "" +"Informaciones sobre la afiliacion (bus para miembros ancianos, cuestionario " +"para los nuevos miembros), registrado en JSON" -#: env/lib/python3.11/site-packages/django/utils/dates.py:11 -msgid "Friday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:12 -msgid "Saturday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:13 -msgid "Sunday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:16 -msgid "Mon" -msgstr "" +#: apps/wei/models.py:312 +msgid "WEI User" +msgstr "Participante WEI" -#: env/lib/python3.11/site-packages/django/utils/dates.py:17 -msgid "Tue" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:18 -msgid "Wed" -msgstr "" +#: apps/wei/models.py:313 +msgid "WEI Users" +msgstr "Participantes WEI" -#: env/lib/python3.11/site-packages/django/utils/dates.py:19 -msgid "Thu" -msgstr "" +#: apps/wei/models.py:333 +msgid "team" +msgstr "equipo" -#: env/lib/python3.11/site-packages/django/utils/dates.py:20 -msgid "Fri" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:21 -msgid "Sat" -msgstr "" +#: apps/wei/models.py:343 +msgid "WEI registration" +msgstr "Apuntación al WEI" -#: env/lib/python3.11/site-packages/django/utils/dates.py:22 -msgid "Sun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:25 -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:26 -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:27 -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:28 -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:29 -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:30 -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:31 -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:32 -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:33 -#, fuzzy -#| msgid "member" -msgid "September" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:34 -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:35 -#, fuzzy -#| msgid "member" -msgid "November" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:36 -#, fuzzy -#| msgid "member" -msgid "December" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:39 -msgid "jan" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:40 -#, fuzzy -#| msgid "fee" -msgid "feb" -msgstr "pago" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:41 -msgid "mar" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:42 -msgid "apr" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:43 -msgid "may" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:44 -msgid "jun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:45 -msgid "jul" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:46 -msgid "aug" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:47 -msgid "sep" -msgstr "" +#: apps/wei/models.py:347 +msgid "WEI membership" +msgstr "Afiliación al WEI" -#: env/lib/python3.11/site-packages/django/utils/dates.py:48 -#, fuzzy -#| msgid "product" -msgid "oct" -msgstr "producto" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:49 -msgid "nov" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:50 -msgid "dec" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:53 -msgctxt "abbrev. month" -msgid "Jan." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:54 -msgctxt "abbrev. month" -msgid "Feb." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:55 -msgctxt "abbrev. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:56 -msgctxt "abbrev. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:57 -msgctxt "abbrev. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:58 -msgctxt "abbrev. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:59 -msgctxt "abbrev. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:60 -msgctxt "abbrev. month" -msgid "Aug." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:61 -msgctxt "abbrev. month" -msgid "Sept." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:62 -msgctxt "abbrev. month" -msgid "Oct." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:63 -msgctxt "abbrev. month" -msgid "Nov." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:64 -msgctxt "abbrev. month" -msgid "Dec." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:67 -msgctxt "alt. month" -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:68 -msgctxt "alt. month" -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:69 -msgctxt "alt. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:70 -msgctxt "alt. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:71 -msgctxt "alt. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:72 -msgctxt "alt. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:73 -msgctxt "alt. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:74 -msgctxt "alt. month" -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:75 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "September" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:76 -msgctxt "alt. month" -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:77 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "November" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:78 -#, fuzzy -#| msgid "member" -msgctxt "alt. month" -msgid "December" -msgstr "miembro" - -#: env/lib/python3.11/site-packages/django/utils/ipv6.py:8 -#, fuzzy -#| msgid "This activity is not validated yet." -msgid "This is not a valid IPv6 address." -msgstr "Esta actividad no fue validada por ahora." - -#: env/lib/python3.11/site-packages/django/utils/text.py:84 -#, python-format -msgctxt "String to return when truncating text" -msgid "%(truncated_text)s…" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/text.py:269 -msgid "or" -msgstr "" - -#. Translators: This string is used as a separator between list elements -#: env/lib/python3.11/site-packages/django/utils/text.py:288 -#: env/lib/python3.11/site-packages/django/utils/timesince.py:135 -msgid ", " -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:8 -#, python-format -msgid "%(num)d year" -msgid_plural "%(num)d years" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:9 -#, python-format -msgid "%(num)d month" -msgid_plural "%(num)d months" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:10 -#, python-format -msgid "%(num)d week" -msgid_plural "%(num)d weeks" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:11 -#, python-format -msgid "%(num)d day" -msgid_plural "%(num)d days" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:12 -#, python-format -msgid "%(num)d hour" -msgid_plural "%(num)d hours" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:13 -#, python-format -msgid "%(num)d minute" -msgid_plural "%(num)d minutes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:111 -msgid "Forbidden" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:112 -msgid "CSRF verification failed. Request aborted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:116 -msgid "" -"You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your web browser, but none was sent. This header is " -"required for security reasons, to ensure that your browser is not being " -"hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:122 -msgid "" -"If you have configured your browser to disable “Referer” headers, please re-" -"enable them, at least for this site, or for HTTPS connections, or for “same-" -"origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:127 -msgid "" -"If you are using the tag or " -"including the “Referrer-Policy: no-referrer” header, please remove them. The " -"CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:136 -msgid "" -"You are seeing this message because this site requires a CSRF cookie when " -"submitting forms. This cookie is required for security reasons, to ensure " -"that your browser is not being hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:142 -msgid "" -"If you have configured your browser to disable cookies, please re-enable " -"them, at least for this site, or for “same-origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:148 -msgid "More information is available with DEBUG=True." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:44 -#, fuzzy -#| msgid "No reason specified" -msgid "No year specified" -msgstr "Ningún motivo dado" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:64 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:115 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:214 -msgid "Date out of range" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:94 -#, fuzzy -#| msgid "No reason specified" -msgid "No month specified" -msgstr "Ningún motivo dado" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:147 -#, fuzzy -#| msgid "No reason specified" -msgid "No day specified" -msgstr "Ningún motivo dado" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:194 -#, fuzzy -#| msgid "No reason specified" -msgid "No week specified" -msgstr "Ningún motivo dado" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:349 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:380 -#, python-format -msgid "No %(verbose_name_plural)s available" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:652 -#, python-format -msgid "" -"Future %(verbose_name_plural)s not available because %(class_name)s." -"allow_future is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:692 -#, python-format -msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/detail.py:56 -#, python-format -msgid "No %(verbose_name)s found matching the query" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:70 -msgid "Page is not “last”, nor can it be converted to an int." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:77 -#, python-format -msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:169 -#, python-format -msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:38 -msgid "Directory indexes are not allowed here." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:40 -#, python-format -msgid "“%(path)s” does not exist" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:79 -#, python-format -msgid "Index of %(directory)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:7 -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:220 -msgid "The install worked successfully! Congratulations!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:206 -#, python-format -msgid "" -"View release notes for Django %(version)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:221 -#, python-format -msgid "" -"You are seeing this page because DEBUG=True is in your settings file and you have not " -"configured any URLs." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:229 -msgid "Django Documentation" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:230 -msgid "Topics, references, & how-to’s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:238 -msgid "Tutorial: A Polling App" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:239 -msgid "Get started with Django" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:247 -msgid "Django Community" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:248 -msgid "Connect, get help, or contribute" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:69 -msgid "Confidential" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:70 -msgid "Public" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:79 -#, fuzzy -#| msgid "Authorization:" -msgid "Authorization code" -msgstr "Autorizaciones :" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:80 -msgid "Implicit" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:81 -#, fuzzy -#| msgid "Reset my password" -msgid "Resource owner password-based" -msgstr "Reiniciar mi contraseña" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:82 -#, fuzzy -#| msgid "Client secret" -msgid "Client credentials" -msgstr "Secreto cliente" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:83 -msgid "OpenID connect hybrid" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:90 -msgid "No OIDC support" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:91 -msgid "RSA with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:92 -msgid "HMAC with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:107 -msgid "Allowed URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:111 -msgid "Allowed Post Logout URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:120 -msgid "Hashed on Save. Copy it now if this is a new secret." -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:190 -#, python-brace-format -msgid "Unauthorized redirect scheme: {scheme}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:194 -#, python-brace-format -msgid "redirect_uris cannot be empty with grant_type {grant_type}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:200 -msgid "You must set OIDC_RSA_PRIVATE_KEY to use RSA algorithm" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:209 -msgid "You cannot use HS256 with public grants or clients" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:211 -#, fuzzy -#| msgid "This address must be valid." -msgid "The access token is invalid." -msgstr "Este correo tiene que ser valido." - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:218 -msgid "The access token has expired." -msgstr "" +#: apps/wei/models.py:348 +msgid "WEI memberships" +msgstr "Afiliaciones al WEI" -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:225 -#, fuzzy -#| msgid "The user does not have enough money." -msgid "The access token is valid but does not have enough scope." +#: apps/wei/tables.py:105 +msgid "The user does not have enough money." msgstr "El usuario no tiene suficientemente dinero." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:6 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 -msgid "Are you sure to delete the application" +#: apps/wei/tables.py:108 +msgid "" +"The user is in first year. You may validate the credit, the algorithm will " +"run later." msgstr "" -"¿ Usted está seguro de querer suprimir esta aplicación ? Este acto es " -"definitivo" +"El usuario esta en primer año. Puede validar el crédito, el algoritmo se " +"ejecutara más tarde." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:12 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:29 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 -#: note_kfet/templates/oauth2_provider/authorize.html:28 -msgid "Cancel" -msgstr "Anular" +#: apps/wei/tables.py:111 +msgid "The user has enough money, you can validate the registration." +msgstr "La note tiene suficiente dinero, la afiliación es posible." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:10 -#: note_kfet/templates/oauth2_provider/application_detail.html:11 -msgid "Client id" -msgstr "ID cliente" +#: apps/wei/tables.py:143 +msgid "Year" +msgstr "Año" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:15 -#: note_kfet/templates/oauth2_provider/application_detail.html:14 -msgid "Client secret" -msgstr "Secreto cliente" +#: apps/wei/tables.py:180 apps/wei/templates/wei/weimembership_form.html:102 +msgid "preferred bus" +msgstr "bus preferido" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:20 -#: note_kfet/templates/oauth2_provider/application_detail.html:17 -msgid "Client type" -msgstr "Tipo de cliente" +#: apps/wei/tables.py:210 apps/wei/templates/wei/bus_detail.html:32 +#: apps/wei/templates/wei/busteam_detail.html:50 +msgid "Teams" +msgstr "Equipos" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:25 -#: note_kfet/templates/oauth2_provider/application_detail.html:20 -msgid "Authorization Grant Type" -msgstr "Tipo de autorización" +#: apps/wei/tables.py:219 apps/wei/tables.py:260 +msgid "Members count" +msgstr "Número de miembros" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:30 -#: note_kfet/templates/oauth2_provider/application_detail.html:23 -msgid "Redirect Uris" -msgstr "URL de redirecto" +#: apps/wei/tables.py:226 apps/wei/tables.py:257 +msgid "members" +msgstr "miembros" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:36 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:35 -#: note_kfet/templates/oauth2_provider/application_detail.html:37 -#: note_kfet/templates/oauth2_provider/application_form.html:23 -msgid "Go Back" -msgstr "Volver" +#: apps/wei/tables.py:287 +msgid "suggested first year" +msgstr "primer año sugerido" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:9 -#: note_kfet/templates/oauth2_provider/application_form.html:12 -msgid "Edit application" -msgstr "Editar la aplicación" +#: apps/wei/tables.py:293 +msgid "validated first year" +msgstr "primer año validado" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:37 -msgid "Save" +#: apps/wei/tables.py:299 +msgid "validated staff" +msgstr "staff validado" + +#: apps/wei/tables.py:310 +msgid "free seats" +msgstr "asientos libres" + +#: apps/wei/templates/wei/1A_list.html:9 +msgid "Attribute first year members into buses" +msgstr "Repartir los primer años en los buses" + +#: apps/wei/templates/wei/1A_list.html:15 +msgid "Start attribution!" +msgstr "Empezar repartición !" + +#: apps/wei/templates/wei/attribute_bus_1A.html:8 +msgid "Bus attribution" +msgstr "Repartición de los buses" + +#: apps/wei/templates/wei/attribute_bus_1A.html:31 +msgid "suggested bus" +msgstr "bus sugerido" + +#: apps/wei/templates/wei/attribute_bus_1A.html:37 +msgid "View raw survey information" +msgstr "Ver las informaciones crudas del cuestionario" + +#: apps/wei/templates/wei/attribute_bus_1A.html:57 +msgid "Back to main list" +msgstr "Volver a la lista principal" + +#: apps/wei/templates/wei/base.html:44 +msgid "WEI fee (paid students)" +msgstr "Pago de entrada del WEI (estudiantes pagados)" + +#: apps/wei/templates/wei/base.html:47 apps/wei/templates/wei/base.html:54 +msgid "The BDE membership is included in the WEI registration." +msgstr "La afiliación al BDE esta incluida en la afiliación WEI." + +#: apps/wei/templates/wei/base.html:51 +msgid "WEI fee (unpaid students)" +msgstr "Pago de entrada del WEI (estudiantes no pagados)" + +#: apps/wei/templates/wei/base.html:76 +msgid "WEI list" +msgstr "Lista de los WEI" + +#: apps/wei/templates/wei/base.html:81 apps/wei/views.py:528 +msgid "Register 1A" +msgstr "Apuntar un 1A" + +#: apps/wei/templates/wei/base.html:85 apps/wei/views.py:614 +msgid "Register 2A+" +msgstr "Apuntar un 2A+" + +#: apps/wei/templates/wei/base.html:93 +msgid "Add bus" +msgstr "Añadir un bus" + +#: apps/wei/templates/wei/base.html:97 +msgid "View WEI" +msgstr "Ver un WEI" + +#: apps/wei/templates/wei/bus_detail.html:22 +#: apps/wei/templates/wei/busteam_detail.html:22 +msgid "Add team" +msgstr "Añadir un equipo" + +#: apps/wei/templates/wei/bus_detail.html:45 +msgid "Members" +msgstr "Miembros" + +#: apps/wei/templates/wei/bus_detail.html:54 +#: apps/wei/templates/wei/busteam_detail.html:60 +#: apps/wei/templates/wei/weimembership_list.html:31 +msgid "View as PDF" +msgstr "Descargar un PDF" + +#: apps/wei/templates/wei/survey.html:11 +#: apps/wei/templates/wei/survey_closed.html:11 +#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1028 +#: apps/wei/views.py:1083 apps/wei/views.py:1093 +msgid "Survey WEI" +msgstr "Cuestionario WEI" + +#: apps/wei/templates/wei/survey.html:23 +msgid "Next" +msgstr "Siguiente" + +#: apps/wei/templates/wei/survey_closed.html:15 +msgid "The inscription for this WEI are now closed." +msgstr "La inscripción a este WEI esta cerrada por el momento." + +#: apps/wei/templates/wei/survey_closed.html:19 +msgid "Return to WEI detail" +msgstr "Regresar a los detalles del WEI" + +#: apps/wei/templates/wei/survey_end.html:15 +msgid "The survey is now ended. Your answers have been saved." +msgstr "El cuestionario se acabó. Sus repuestas fueron guardadas." + +#: apps/wei/templates/wei/weiclub_detail.html:32 +msgid "Register to the WEI! – 1A" +msgstr "¡ Apuntar al WEI ! – 1A" + +#: apps/wei/templates/wei/weiclub_detail.html:36 +msgid "Register to the WEI! – 2A+" +msgstr "¡ Apuntar al WEI ! – 2A+" + +#: apps/wei/templates/wei/weiclub_detail.html:40 +msgid "Update my registration" +msgstr "Modificar mi inscripción" + +#: apps/wei/templates/wei/weiclub_detail.html:63 +msgid "Members of the WEI" +msgstr "Miembros del WEI" + +#: apps/wei/templates/wei/weiclub_detail.html:89 +msgid "Unvalidated registrations" +msgstr "Inscripciones sin validación" + +#: apps/wei/templates/wei/weiclub_detail.html:99 +msgid "Attribute buses" +msgstr "Repartición en los buses" + +#: apps/wei/templates/wei/weiclub_list.html:14 apps/wei/views.py:79 +msgid "Create WEI" +msgstr "Crear un WEI" + +#: apps/wei/templates/wei/weiclub_list.html:22 +msgid "WEI listing" +msgstr "Lista de los WEI" + +#: apps/wei/templates/wei/weimembership_form.html:10 +msgid "Review registration" +msgstr "Revisar la inscripción" + +#: apps/wei/templates/wei/weimembership_form.html:35 +msgid "ENS year" +msgstr "Año en la ENS" + +#: apps/wei/templates/wei/weimembership_form.html:76 +msgid "Payment from Société générale" +msgstr "Pago de la Société Générale" + +#: apps/wei/templates/wei/weimembership_form.html:80 +msgid "Suggested bus from the survey:" +msgstr "Bus sugerido por el cuestionario :" + +#: apps/wei/templates/wei/weimembership_form.html:85 +msgid "Raw survey information" +msgstr "Informaciones crudas del cuestionario" + +#: apps/wei/templates/wei/weimembership_form.html:95 +msgid "The algorithm didn't run." +msgstr "El algoritmo no funcionó." + +#: apps/wei/templates/wei/weimembership_form.html:98 +msgid "caution check given" +msgstr "cheque de garantía dado" + +#: apps/wei/templates/wei/weimembership_form.html:105 +msgid "preferred team" +msgstr "equipo preferido" + +#: apps/wei/templates/wei/weimembership_form.html:108 +msgid "preferred roles" +msgstr "papales preferidos" + +#: apps/wei/templates/wei/weimembership_form.html:115 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:30 +msgid "Update registration" +msgstr "Modificar la inscripción" + +#: apps/wei/templates/wei/weimembership_form.html:131 +msgid "The registration is already validated and can't be unvalidated." +msgstr "La inscripción ya fue validada y no puede ser invalidada." + +#: apps/wei/templates/wei/weimembership_form.html:132 +msgid "The user joined the bus" +msgstr "El usuario se queda con el bus" + +#: apps/wei/templates/wei/weimembership_form.html:133 +msgid "in the team" +msgstr "en el equipo" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "in no team (staff)" +msgstr "en ningún equipo (staff)" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "with the following roles:" +msgstr "con los papeles :" + +#: apps/wei/templates/wei/weimembership_form.html:139 +msgid "" +"The WEI will be paid by Société générale. The membership will be created " +"even if the bank didn't pay the BDE yet. The membership transaction will be " +"created but will be invalid. You will have to validate it once the bank " +"validated the creation of the account, or to change the payment method." msgstr "" +"El WEI será pagado por la Société Générale. La afiliación será creada aunque " +"el banco no pago el BDE ya. La transacción de afiliación será creada pero " +"resultará invalida. Tendrá que validarla una vez que el banco confirmará la " +"creación de la cuenta, o cambiará el método de pago." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:6 -#: note_kfet/templates/oauth2_provider/application_list.html:7 -msgid "Your applications" -msgstr "Sus aplicaciones" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:14 -#: note_kfet/templates/oauth2_provider/application_list.html:30 -msgid "New Application" -msgstr "Nueva aplicación" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_registration_form.html:5 -#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 -msgid "Register a new application" -msgstr "Registrar una nueva aplicación" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:8 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:30 -#: note_kfet/templates/oauth2_provider/authorize.html:9 -#: note_kfet/templates/oauth2_provider/authorize.html:29 -msgid "Authorize" -msgstr "Autorizar" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:17 -#, fuzzy -#| msgid "Application requires following permissions:" -msgid "Application requires the following permissions" -msgstr "La aplicación necesita los derechos siguientes :" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:6 -#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 -msgid "Are you sure you want to delete this token?" -msgstr "¿ Usted está seguro de querer suprimir este token ?" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:6 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 -msgid "Tokens" -msgstr "Tokens" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:11 -msgid "revoke" +#: apps/wei/templates/wei/weimembership_form.html:149 +#, python-format +msgid "" +"The note don't have enough money (%(balance)s, %(pretty_fee)s required). The " +"registration may fail if you don't credit the note now." msgstr "" +"La note no tiene suficiente dinero (%(balance)s, %(pretty_fee)s pedidos). La " +"afiliación puede fallar si usted no acredita la note ahora." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:19 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 -msgid "There are no authorized tokens yet." -msgstr "Por ahora no hay ningún token autorizado." +#: apps/wei/templates/wei/weimembership_form.html:157 +#, python-format +msgid "" +"The note has enough money (%(pretty_fee)s required), the registration is " +"possible." +msgstr "" +"La note tiene suficiente dinero (%(pretty_fee)s pedidos), la afiliación es " +"posible." -#: note_kfet/settings/base.py:173 +#: apps/wei/templates/wei/weimembership_form.html:166 +msgid "The user didn't give her/his caution check." +msgstr "El usuario no dio su cheque de garantía." + +#: apps/wei/templates/wei/weimembership_form.html:174 +msgid "" +"This user is not a member of the Kfet club for the coming year. The " +"membership will be processed automatically, the WEI registration includes " +"the membership fee." +msgstr "" +"Este usuario no es miembro del club Kfet por el año que viene. La afiliación " +"será hecha automáticamente, la afiliación al WEI incluye el pago de los dos." + +#: apps/wei/templates/wei/weimembership_list.html:27 +msgid "View unvalidated registrations..." +msgstr "Ver las inscripciones no validadas..." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:16 +msgid "This registration is already validated and can't be deleted." +msgstr "La inscripción ya fue validada y no puede ser suprimida." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:23 +#, python-format +msgid "" +"Are you sure you want to delete the registration of %(user)s for the WEI " +"%(wei_name)s? This action can't be undone." +msgstr "" +"¿ Usted está seguro que quiere suprimir la inscripción de %(user)s para el " +"WEI %(wei_name)s ? Este acto es definitivo." + +#: apps/wei/templates/wei/weiregistration_list.html:19 +msgid "There is no pre-registration found with this pattern." +msgstr "No hay pre-inscripción encontrada con esta entrada." + +#: apps/wei/templates/wei/weiregistration_list.html:27 +msgid "View validated memberships..." +msgstr "Ver las inscripciones validadas..." + +#: apps/wei/views.py:58 +msgid "Search WEI" +msgstr "Buscar un WEI" + +#: apps/wei/views.py:109 +msgid "WEI Detail" +msgstr "Detalles del WEI" + +#: apps/wei/views.py:208 +msgid "View members of the WEI" +msgstr "Ver los miembros del WEI" + +#: apps/wei/views.py:236 +msgid "Find WEI Membership" +msgstr "Buscar una afiliación al WEI" + +#: apps/wei/views.py:246 +msgid "View registrations to the WEI" +msgstr "Ver las inscripciones al WEI" + +#: apps/wei/views.py:270 +msgid "Find WEI Registration" +msgstr "Buscar una inscripción al WEI" + +#: apps/wei/views.py:281 +msgid "Update the WEI" +msgstr "Modificar el WEI" + +#: apps/wei/views.py:302 +msgid "Create new bus" +msgstr "Añadir un bus" + +#: apps/wei/views.py:340 +msgid "Update bus" +msgstr "Modificar el bus" + +#: apps/wei/views.py:372 +msgid "Manage bus" +msgstr "Gestionar el bus" + +#: apps/wei/views.py:399 +msgid "Create new team" +msgstr "Añadir un equipo" + +#: apps/wei/views.py:439 +msgid "Update team" +msgstr "Modificar el equipo" + +#: apps/wei/views.py:470 +msgid "Manage WEI team" +msgstr "Gestionar el equipo" + +#: apps/wei/views.py:492 +msgid "Register first year student to the WEI" +msgstr "Registrar un 1A al WEI" + +#: apps/wei/views.py:550 apps/wei/views.py:649 +msgid "This user is already registered to this WEI." +msgstr "Este usuario ya afilió a este WEI." + +#: apps/wei/views.py:555 +msgid "" +"This user can't be in her/his first year since he/she has already " +"participated to a WEI." +msgstr "Este usuario no puede ser un 1A porque ya participó en un WEI." + +#: apps/wei/views.py:578 +msgid "Register old student to the WEI" +msgstr "Registrar un 2A+ al WEI" + +#: apps/wei/views.py:633 apps/wei/views.py:721 +msgid "You already opened an account in the Société générale." +msgstr "Usted ya abrió una cuenta a la Société Générale." + +#: apps/wei/views.py:685 +msgid "Update WEI Registration" +msgstr "Modificar la inscripción WEI" + +#: apps/wei/views.py:795 +msgid "Delete WEI registration" +msgstr "Suprimir la inscripción WEI" + +#: apps/wei/views.py:806 +msgid "You don't have the right to delete this WEI registration." +msgstr "Usted no tiene derecho a suprimir esta inscripción WEI." + +#: apps/wei/views.py:824 +msgid "Validate WEI registration" +msgstr "Validar la inscripción WEI" + +#: apps/wei/views.py:1186 +msgid "Attribute buses to first year members" +msgstr "Repartir los primer años en los buses" + +#: apps/wei/views.py:1211 +msgid "Attribute bus" +msgstr "Repartir en un bus" + +#: note_kfet/settings/base.py:172 msgid "German" msgstr "Alemán" -#: note_kfet/settings/base.py:174 +#: note_kfet/settings/base.py:173 msgid "English" msgstr "Ingles" -#: note_kfet/settings/base.py:175 +#: note_kfet/settings/base.py:174 msgid "Spanish" msgstr "Español" -#: note_kfet/settings/base.py:176 +#: note_kfet/settings/base.py:175 msgid "French" msgstr "Francés" @@ -3961,26 +3252,26 @@ msgstr "Usuarios" msgid "Clubs" msgstr "Clubs" -#: note_kfet/templates/base.html:107 +#: note_kfet/templates/base.html:113 msgid "Admin" msgstr "" -#: note_kfet/templates/base.html:121 +#: note_kfet/templates/base.html:127 msgid "My account" msgstr "Mi cuenta" -#: note_kfet/templates/base.html:124 +#: note_kfet/templates/base.html:130 msgid "Log out" msgstr "Desconectarse" -#: note_kfet/templates/base.html:132 +#: note_kfet/templates/base.html:138 #: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:28 msgid "Sign up" msgstr "Registrar" -#: note_kfet/templates/base.html:139 +#: note_kfet/templates/base.html:145 #: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:38 @@ -3988,7 +3279,15 @@ msgstr "Registrar" msgid "Log in" msgstr "Conectarse" -#: note_kfet/templates/base.html:153 +#: note_kfet/templates/base.html:159 +msgid "" +"You are not a BDE member anymore. Please renew your membership if you want " +"to use the note." +msgstr "" +"Usted ya no está miembro del BDE. Por favor renueva su afiliación si quiere " +"usar la note." + +#: note_kfet/templates/base.html:165 msgid "" "Your e-mail address is not validated. Please check your mail inbox and click " "on the validation link." @@ -3997,10 +3296,23 @@ msgstr "" "clic en el enlace de validación." #: note_kfet/templates/base.html:171 +msgid "" +"You declared that you opened a bank account in the Société générale. The " +"bank did not validate the creation of the account to the BDE, so the " +"membership and the WEI are not paid yet. This verification procedure may " +"last a few days. Please make sure that you go to the end of the account " +"creation." +msgstr "" +"Usted declaró que abrió una cuenta bancaria a la Société Générale. El banco " +"no convalidó la cuenta al BDE, así que la afiliación y el WEI no están " +"pagados. El proceso de convalidación puede durar unos días. Por favor " +"comprueba que fue hasta el final de la creación de la cuenta." + +#: note_kfet/templates/base.html:194 msgid "Contact us" msgstr "Contactarnos" -#: note_kfet/templates/base.html:173 +#: note_kfet/templates/base.html:196 msgid "Technical Support" msgstr "Soporte técnico" @@ -4012,6 +3324,37 @@ msgstr "Buscar con atributo, como el nombre…" msgid "There is no results." msgstr "No hay resultado." +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 +msgid "Are you sure to delete the application" +msgstr "" +"¿ Usted está seguro de querer suprimir esta aplicación ? Este acto es " +"definitivo" + +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 +#: note_kfet/templates/oauth2_provider/authorize.html:28 +msgid "Cancel" +msgstr "Anular" + +#: note_kfet/templates/oauth2_provider/application_detail.html:11 +msgid "Client id" +msgstr "ID cliente" + +#: note_kfet/templates/oauth2_provider/application_detail.html:14 +msgid "Client secret" +msgstr "Secreto cliente" + +#: note_kfet/templates/oauth2_provider/application_detail.html:17 +msgid "Client type" +msgstr "Tipo de cliente" + +#: note_kfet/templates/oauth2_provider/application_detail.html:20 +msgid "Authorization Grant Type" +msgstr "Tipo de autorización" + +#: note_kfet/templates/oauth2_provider/application_detail.html:23 +msgid "Redirect Uris" +msgstr "URL de redirecto" + #: note_kfet/templates/oauth2_provider/application_detail.html:29 #, python-format msgid "" @@ -4020,6 +3363,19 @@ msgid "" "that you want to grant for your application." msgstr "" +#: note_kfet/templates/oauth2_provider/application_detail.html:37 +#: note_kfet/templates/oauth2_provider/application_form.html:23 +msgid "Go Back" +msgstr "Volver" + +#: note_kfet/templates/oauth2_provider/application_form.html:12 +msgid "Edit application" +msgstr "Editar la aplicación" + +#: note_kfet/templates/oauth2_provider/application_list.html:7 +msgid "Your applications" +msgstr "Sus aplicaciones" + #: note_kfet/templates/oauth2_provider/application_list.html:11 msgid "" "You can find on this page the list of the applications that you already " @@ -4027,10 +3383,23 @@ msgid "" msgstr "" "Puede encontrar en esta pagina la lista de la aplicaciones que ya registró." +#: note_kfet/templates/oauth2_provider/application_list.html:30 +msgid "New Application" +msgstr "Nueva aplicación" + #: note_kfet/templates/oauth2_provider/application_list.html:31 msgid "Authorized Tokens" msgstr "Tokens autorizados" +#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 +msgid "Register a new application" +msgstr "Registrar una nueva aplicación" + +#: note_kfet/templates/oauth2_provider/authorize.html:9 +#: note_kfet/templates/oauth2_provider/authorize.html:29 +msgid "Authorize" +msgstr "Autorizar" + #: note_kfet/templates/oauth2_provider/authorize.html:14 msgid "Application requires following permissions:" msgstr "La aplicación necesita los derechos siguientes :" @@ -4048,6 +3417,18 @@ msgstr "Éxito" msgid "Please return to your application and enter this code:" msgstr "Volver a su aplicación y entrar este código :" +#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 +msgid "Are you sure you want to delete this token?" +msgstr "¿ Usted está seguro de querer suprimir este token ?" + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 +msgid "Tokens" +msgstr "Tokens" + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 +msgid "There are no authorized tokens yet." +msgstr "Por ahora no hay ningún token autorizado." + #: note_kfet/templates/registration/logged_out.html:13 msgid "Thanks for spending some quality time with the Web site today." msgstr "Gracias por usar la Note Kfet." @@ -4145,649 +3526,17 @@ msgid "Reset my password" msgstr "Reiniciar mi contraseña" #: note_kfet/templates/registration/signup.html:15 -#, fuzzy -#| msgid "" -#| "If you already signed up, your registration is taken into account. The " -#| "BDE must validate your account before your can log in. You have to go to " -#| "the Kfet and pay the registration fee. You must also validate your email " -#| "address by following the link you received." msgid "" "If you already signed up, your registration is taken into account. The BDE " -"must validate your account before your can log in. You have to pay the " -"registration fee. You must also validate your email address by following the " -"link you received." +"must validate your account before your can log in. You have to go to the " +"Kfet and pay the registration fee. You must also validate your email address " +"by following the link you received." msgstr "" "Si ya registró, se procesa su inscripción. El BDE tiene que validar su " "cuenta antes que usted pueda conectarse. Usted tiene que ir en la Kfet para " "pagar su afiliación. Tambien tiene que validar su correo electronico con el " "enlace que recibió." -#~ msgid "Inscription paid by Société Générale" -#~ msgstr "Registración pagadas por Société Générale" - -#~ 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." - -#~ msgid "Bank" -#~ msgstr "Banco" - -#~ msgid "Physics (A2)" -#~ msgstr "Física (A2)" - -#~ msgid "Applied physics (A'2)" -#~ msgstr "Física aplicada (A'2)" - -#~ msgid "Chemistry (A''2)" -#~ msgstr "Química (A''2)" - -#~ msgid "Biology (A3)" -#~ msgstr "Biología (A3)" - -#~ msgid "SAPHIRE (B1234)" -#~ msgstr "SAPHIRE (B1234)" - -#~ msgid "Mechanics (B1)" -#~ msgstr "Mecánica (B1)" - -#~ msgid "Civil engineering (B2)" -#~ msgstr "Ingeniería civil (B2)" - -#~ msgid "Mechanical engineering (B3)" -#~ msgstr "Ingeniería mecánica (B3)" - -#~ msgid "EEA (B4)" -#~ msgstr "EEA (B4)" - -#~ msgid "Design (C)" -#~ msgstr "Design (C)" - -#~ msgid "Social sciences (D3)" -#~ msgstr "Ciencias sociales (D3)" - -#~ msgid "English (E)" -#~ msgstr "Inglés (E)" - -#~ msgid "External (EXT)" -#~ msgstr "Extern@ (EXT)" - -#~ msgid "Yes (receive them in french)" -#~ msgstr "Si (recibirles en francés)" - -#~ msgid "Yes (receive them in english)" -#~ msgstr "Si (recibirles en inglés)" - -#, python-format -#~ msgid "" -#~ "The user is not a member of the club·s %(clubs)s. An additional fee of " -#~ "%(pretty_fee)s will be charged to renew automatically the membership in " -#~ "this/these club·s." -#~ msgstr "" -#~ "El usuario no está miembro del/de los club·s parientes %(clubs)s. Un pago " -#~ "adicional de %(pretty_fee)s sera cargado para prorrogar automáticamente " -#~ "la afiliación a este/os club·s." - -#, python-format -#~ msgid "" -#~ "This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will " -#~ "be charged to adhere automatically to this/these club·s." -#~ msgstr "" -#~ "Este club tiene come pariente %(clubs)s. Un pago adicional de " -#~ "%(pretty_fee)s sera cargado para registrar automáticamente a este/os " -#~ "club·s." - -#~ msgid "bank" -#~ msgstr "banco" - -#~ msgid "Superusers have all rights on everything, to manage the website." -#~ msgstr "" -#~ "Super-usuarios tienen todos los permisos sobre todo para gestionar el " -#~ "sistema." - -#~ msgid "Superusers" -#~ msgstr "Super-usuarios" - -#~ msgid "" -#~ "I declare that I opened or I will open soon a bank account in the Société " -#~ "générale with the BDE partnership." -#~ msgstr "" -#~ "Declaro que ya abrió una cuenta a la Société Générale en colaboración con " -#~ "el BDE." - -#~ msgid "" -#~ "Warning: this engages you to open your bank account. If you finally " -#~ "decides to don't open your account, you will have to pay the BDE " -#~ "membership." -#~ msgstr "" -#~ "Cuidado : esto le obliga abrir su cuenta bancaria. Si cambia de idea y no " -#~ "abre su cuenta bancaria, tendrá que pagar su afiliación al BDE." - -#~ msgid "Register to the WEI" -#~ msgstr "Registrarse en el WEI" - -#~ 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." -#~ 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." - -#~ msgid "Join Kfet Club" -#~ msgstr "Afiliarse al club Kfet" - -#~ msgid "You must also go to the Kfet to pay your membership." -#~ msgstr "" -#~ "También tendrá que ir en la Kfet para pagar su afiliación. La afiliación " -#~ "al WEI incluye una afiliación al BDE." - -#~ msgid "" -#~ "The user declared that he/she opened a bank account in the Société " -#~ "générale." -#~ msgstr "El usuario declara que ya abrió una cuenta a la Société Générale." - -#~ msgid "You must join the BDE." -#~ msgstr "Usted tiene que afiliarse al BDE." - -#~ msgid "credit transaction" -#~ msgstr "transacción de crédito" - -#~ msgid "" -#~ "This user doesn't have enough money to pay the memberships with its note. " -#~ "Please ask her/him to credit the note before invalidating this credit." -#~ msgstr "" -#~ "Este usuario no tiene suficiente dinero en su note para pagar las " -#~ "afiliaciones. Por favor pídelo acreditar su note antes de invalidar este " -#~ "crédito." - -#~ msgid "Credits from the Société générale" -#~ msgstr "Créditos de la Société Générale" - -#, python-brace-format -#~ msgid "Soge credit for {user}" -#~ msgstr "Crédito de la Société Générale para {user}" - -#~ msgid "List of credits from the Société générale" -#~ msgstr "Lista de los créditos de la Société Générale" - -#~ msgid "Manage credits from the Société générale" -#~ msgstr "Gestionar los créditos de la Société Générale" - -#~ msgid "WEI" -#~ msgstr "WEI" - -#~ msgid "" -#~ "The selected user is not validated. Please validate its account first" -#~ msgstr "" -#~ "El usuario seleccionado no ha sido validado. Validar esta cuenta primero" - -#~ msgid "bus" -#~ msgstr "bus" - -#~ msgid "" -#~ "This choice is not definitive. The WEI organizers are free to attribute " -#~ "for you a bus and a team, in particular if you are a free eletron." -#~ msgstr "" -#~ "Esta elección no es definitiva. Los organizadores del WEI se quedan con " -#~ "el derecho de imponer su bus y su equipo, en particular para los " -#~ "electrones libres." - -#~ msgid "Team" -#~ msgstr "Equipo" - -#~ msgid "" -#~ "Leave this field empty if you won't be in a team (staff, bus chief, free " -#~ "electron)" -#~ msgstr "" -#~ "Deje este campo vacío si no quiere estar en un equipo (staff, jefe de " -#~ "bus, electrón libre)" - -#~ msgid "WEI Roles" -#~ msgstr "Papeles en el WEI" - -#~ msgid "Select the roles that you are interested in." -#~ msgstr "Elegir los papeles que le interesa." - -#~ msgid "This team doesn't belong to the given bus." -#~ msgstr "Este equipo no pertenece al bus dado." - -#~ msgid "Choose a word:" -#~ msgstr "Elegir una palabra :" - -#~ msgid "year" -#~ msgstr "año" - -#~ msgid "date start" -#~ msgstr "fecha de inicio" - -#~ msgid "date end" -#~ msgstr "fecha de fin" - -#~ msgid "seat count in the bus" -#~ msgstr "cantidad de asientos en el bus" - -#~ msgid "survey information" -#~ msgstr "informaciones sobre el cuestionario" - -#~ msgid "Information about the survey for new members, encoded in JSON" -#~ msgstr "" -#~ "Informaciones sobre el cuestionario para los nuevos miembros, registrado " -#~ "en JSON" - -#~ msgid "Bus" -#~ msgstr "Bus" - -#~ msgid "Buses" -#~ msgstr "Bus" - -#~ msgid "color" -#~ msgstr "color" - -#~ msgid "The color of the T-Shirt, stored with its number equivalent" -#~ msgstr "El color de la camiseta, registrado con su número equivalente" - -#~ msgid "Bus team" -#~ msgstr "Equipo de bus" - -#~ msgid "Bus teams" -#~ msgstr "Equipos de bus" - -#~ msgid "WEI Role" -#~ msgstr "Papeles en el WEI" - -#~ msgid "Credit from Société générale" -#~ msgstr "Crédito de la Société Générale" - -#~ msgid "Caution check given" -#~ msgstr "Cheque de garantía dado" - -#~ msgid "birth date" -#~ msgstr "fecha de nacimiento" - -#~ msgid "Male" -#~ msgstr "Hombre" - -#~ msgid "Female" -#~ msgstr "Mujer" - -#~ msgid "Non binary" -#~ msgstr "No binari@" - -#~ msgid "gender" -#~ msgstr "género" - -#~ msgid "clothing cut" -#~ msgstr "forma de ropa" - -#~ msgid "clothing size" -#~ msgstr "medida de ropa" - -#~ msgid "health issues" -#~ msgstr "problemas de salud" - -#~ msgid "emergency contact name" -#~ msgstr "nombre del contacto de emergencia" - -#~ msgid "emergency contact phone" -#~ msgstr "teléfono del contacto de emergencia" - -#~ msgid "first year" -#~ msgstr "primer año" - -#~ msgid "Tells if the user is new in the school." -#~ msgstr "Indica si el usuario es nuevo en la escuela." - -#~ msgid "registration information" -#~ msgstr "informaciones sobre la afiliación" - -#~ msgid "" -#~ "Information about the registration (buses for old members, survey for the " -#~ "new members), encoded in JSON" -#~ msgstr "" -#~ "Informaciones sobre la afiliacion (bus para miembros ancianos, " -#~ "cuestionario para los nuevos miembros), registrado en JSON" - -#~ msgid "WEI User" -#~ msgstr "Participante WEI" - -#~ msgid "WEI Users" -#~ msgstr "Participantes WEI" - -#~ msgid "team" -#~ msgstr "equipo" - -#~ msgid "WEI registration" -#~ msgstr "Apuntación al WEI" - -#~ msgid "WEI membership" -#~ msgstr "Afiliación al WEI" - -#~ msgid "WEI memberships" -#~ msgstr "Afiliaciones al WEI" - -#~ msgid "" -#~ "The user is in first year. You may validate the credit, the algorithm " -#~ "will run later." -#~ msgstr "" -#~ "El usuario esta en primer año. Puede validar el crédito, el algoritmo se " -#~ "ejecutara más tarde." - -#~ msgid "The user has enough money, you can validate the registration." -#~ msgstr "La note tiene suficiente dinero, la afiliación es posible." - -#~ msgid "Year" -#~ msgstr "Año" - -#~ msgid "preferred bus" -#~ msgstr "bus preferido" - -#~ msgid "Teams" -#~ msgstr "Equipos" - -#~ msgid "Members count" -#~ msgstr "Número de miembros" - -#~ msgid "members" -#~ msgstr "miembros" - -#~ msgid "suggested first year" -#~ msgstr "primer año sugerido" - -#~ msgid "validated first year" -#~ msgstr "primer año validado" - -#~ msgid "validated staff" -#~ msgstr "staff validado" - -#~ msgid "free seats" -#~ msgstr "asientos libres" - -#~ msgid "Attribute first year members into buses" -#~ msgstr "Repartir los primer años en los buses" - -#~ msgid "Start attribution!" -#~ msgstr "Empezar repartición !" - -#~ msgid "Bus attribution" -#~ msgstr "Repartición de los buses" - -#~ msgid "suggested bus" -#~ msgstr "bus sugerido" - -#~ msgid "View raw survey information" -#~ msgstr "Ver las informaciones crudas del cuestionario" - -#~ msgid "Back to main list" -#~ msgstr "Volver a la lista principal" - -#~ msgid "WEI fee (paid students)" -#~ msgstr "Pago de entrada del WEI (estudiantes pagados)" - -#~ msgid "The BDE membership is included in the WEI registration." -#~ msgstr "La afiliación al BDE esta incluida en la afiliación WEI." - -#~ msgid "WEI fee (unpaid students)" -#~ msgstr "Pago de entrada del WEI (estudiantes no pagados)" - -#~ msgid "WEI list" -#~ msgstr "Lista de los WEI" - -#~ msgid "Register 1A" -#~ msgstr "Apuntar un 1A" - -#~ msgid "Register 2A+" -#~ msgstr "Apuntar un 2A+" - -#~ msgid "Add bus" -#~ msgstr "Añadir un bus" - -#~ msgid "View WEI" -#~ msgstr "Ver un WEI" - -#~ msgid "Add team" -#~ msgstr "Añadir un equipo" - -#~ msgid "Members" -#~ msgstr "Miembros" - -#~ msgid "View as PDF" -#~ msgstr "Descargar un PDF" - -#~ msgid "Survey WEI" -#~ msgstr "Cuestionario WEI" - -#~ msgid "Next" -#~ msgstr "Siguiente" - -#~ msgid "The inscription for this WEI are now closed." -#~ msgstr "La inscripción a este WEI esta cerrada por el momento." - -#~ msgid "Return to WEI detail" -#~ msgstr "Regresar a los detalles del WEI" - -#~ msgid "The survey is now ended. Your answers have been saved." -#~ msgstr "El cuestionario se acabó. Sus repuestas fueron guardadas." - -#~ msgid "Register to the WEI! – 1A" -#~ msgstr "¡ Apuntar al WEI ! – 1A" - -#~ msgid "Register to the WEI! – 2A+" -#~ msgstr "¡ Apuntar al WEI ! – 2A+" - -#~ msgid "Update my registration" -#~ msgstr "Modificar mi inscripción" - -#~ msgid "Members of the WEI" -#~ msgstr "Miembros del WEI" - -#~ msgid "Unvalidated registrations" -#~ msgstr "Inscripciones sin validación" - -#~ msgid "Attribute buses" -#~ msgstr "Repartición en los buses" - -#~ msgid "Create WEI" -#~ msgstr "Crear un WEI" - -#~ msgid "WEI listing" -#~ msgstr "Lista de los WEI" - -#~ msgid "Review registration" -#~ msgstr "Revisar la inscripción" - -#~ msgid "ENS year" -#~ msgstr "Año en la ENS" - -#~ msgid "Payment from Société générale" -#~ msgstr "Pago de la Société Générale" - -#~ msgid "Suggested bus from the survey:" -#~ msgstr "Bus sugerido por el cuestionario :" - -#~ msgid "Raw survey information" -#~ msgstr "Informaciones crudas del cuestionario" - -#~ msgid "The algorithm didn't run." -#~ msgstr "El algoritmo no funcionó." - -#~ msgid "caution check given" -#~ msgstr "cheque de garantía dado" - -#~ msgid "preferred team" -#~ msgstr "equipo preferido" - -#~ msgid "preferred roles" -#~ msgstr "papales preferidos" - -#~ msgid "Update registration" -#~ msgstr "Modificar la inscripción" - -#~ msgid "The registration is already validated and can't be unvalidated." -#~ msgstr "La inscripción ya fue validada y no puede ser invalidada." - -#~ msgid "The user joined the bus" -#~ msgstr "El usuario se queda con el bus" - -#~ msgid "in the team" -#~ msgstr "en el equipo" - -#~ msgid "in no team (staff)" -#~ msgstr "en ningún equipo (staff)" - -#~ msgid "with the following roles:" -#~ msgstr "con los papeles :" - -#~ msgid "" -#~ "The WEI will be paid by Société générale. The membership will be created " -#~ "even if the bank didn't pay the BDE yet. The membership transaction will " -#~ "be created but will be invalid. You will have to validate it once the " -#~ "bank validated the creation of the account, or to change the payment " -#~ "method." -#~ msgstr "" -#~ "El WEI será pagado por la Société Générale. La afiliación será creada " -#~ "aunque el banco no pago el BDE ya. La transacción de afiliación será " -#~ "creada pero resultará invalida. Tendrá que validarla una vez que el banco " -#~ "confirmará la creación de la cuenta, o cambiará el método de pago." - -#, python-format -#~ msgid "" -#~ "The note don't have enough money (%(balance)s, %(pretty_fee)s required). " -#~ "The registration may fail if you don't credit the note now." -#~ msgstr "" -#~ "La note no tiene suficiente dinero (%(balance)s, %(pretty_fee)s pedidos). " -#~ "La afiliación puede fallar si usted no acredita la note ahora." - -#, python-format -#~ msgid "" -#~ "The note has enough money (%(pretty_fee)s required), the registration is " -#~ "possible." -#~ msgstr "" -#~ "La note tiene suficiente dinero (%(pretty_fee)s pedidos), la afiliación " -#~ "es posible." - -#~ msgid "The user didn't give her/his caution check." -#~ msgstr "El usuario no dio su cheque de garantía." - -#~ msgid "" -#~ "This user is not a member of the Kfet club for the coming year. The " -#~ "membership will be processed automatically, the WEI registration includes " -#~ "the membership fee." -#~ msgstr "" -#~ "Este usuario no es miembro del club Kfet por el año que viene. La " -#~ "afiliación será hecha automáticamente, la afiliación al WEI incluye el " -#~ "pago de los dos." - -#~ msgid "View unvalidated registrations..." -#~ msgstr "Ver las inscripciones no validadas..." - -#~ msgid "This registration is already validated and can't be deleted." -#~ msgstr "La inscripción ya fue validada y no puede ser suprimida." - -#, python-format -#~ msgid "" -#~ "Are you sure you want to delete the registration of %(user)s for the WEI " -#~ "%(wei_name)s? This action can't be undone." -#~ msgstr "" -#~ "¿ Usted está seguro que quiere suprimir la inscripción de %(user)s para " -#~ "el WEI %(wei_name)s ? Este acto es definitivo." - -#~ msgid "There is no pre-registration found with this pattern." -#~ msgstr "No hay pre-inscripción encontrada con esta entrada." - -#~ msgid "View validated memberships..." -#~ msgstr "Ver las inscripciones validadas..." - -#~ msgid "Search WEI" -#~ msgstr "Buscar un WEI" - -#~ msgid "WEI Detail" -#~ msgstr "Detalles del WEI" - -#~ msgid "View members of the WEI" -#~ msgstr "Ver los miembros del WEI" - -#~ msgid "Find WEI Membership" -#~ msgstr "Buscar una afiliación al WEI" - -#~ msgid "View registrations to the WEI" -#~ msgstr "Ver las inscripciones al WEI" - -#~ msgid "Find WEI Registration" -#~ msgstr "Buscar una inscripción al WEI" - -#~ msgid "Update the WEI" -#~ msgstr "Modificar el WEI" - -#~ msgid "Create new bus" -#~ msgstr "Añadir un bus" - -#~ msgid "Update bus" -#~ msgstr "Modificar el bus" - -#~ msgid "Manage bus" -#~ msgstr "Gestionar el bus" - -#~ msgid "Create new team" -#~ msgstr "Añadir un equipo" - -#~ msgid "Update team" -#~ msgstr "Modificar el equipo" - -#~ msgid "Manage WEI team" -#~ msgstr "Gestionar el equipo" - -#~ msgid "Register first year student to the WEI" -#~ msgstr "Registrar un 1A al WEI" - -#~ msgid "This user is already registered to this WEI." -#~ msgstr "Este usuario ya afilió a este WEI." - -#~ msgid "" -#~ "This user can't be in her/his first year since he/she has already " -#~ "participated to a WEI." -#~ msgstr "Este usuario no puede ser un 1A porque ya participó en un WEI." - -#~ msgid "Register old student to the WEI" -#~ msgstr "Registrar un 2A+ al WEI" - -#~ msgid "You already opened an account in the Société générale." -#~ msgstr "Usted ya abrió una cuenta a la Société Générale." - -#~ msgid "Update WEI Registration" -#~ msgstr "Modificar la inscripción WEI" - -#~ msgid "Delete WEI registration" -#~ msgstr "Suprimir la inscripción WEI" - -#~ msgid "You don't have the right to delete this WEI registration." -#~ msgstr "Usted no tiene derecho a suprimir esta inscripción WEI." - -#~ msgid "Validate WEI registration" -#~ msgstr "Validar la inscripción WEI" - -#~ msgid "Attribute buses to first year members" -#~ msgstr "Repartir los primer años en los buses" - -#~ msgid "Attribute bus" -#~ msgstr "Repartir en un bus" - -#~ msgid "" -#~ "You are not a BDE member anymore. Please renew your membership if you " -#~ "want to use the note." -#~ msgstr "" -#~ "Usted ya no está miembro del BDE. Por favor renueva su afiliación si " -#~ "quiere usar la note." - -#~ msgid "" -#~ "You declared that you opened a bank account in the Société générale. The " -#~ "bank did not validate the creation of the account to the BDE, so the " -#~ "membership and the WEI are not paid yet. This verification procedure may " -#~ "last a few days. Please make sure that you go to the end of the account " -#~ "creation." -#~ msgstr "" -#~ "Usted declaró que abrió una cuenta bancaria a la Société Générale. El " -#~ "banco no convalidó la cuenta al BDE, así que la afiliación y el WEI no " -#~ "están pagados. El proceso de convalidación puede durar unos días. Por " -#~ "favor comprueba que fue hasta el final de la creación de la cuenta." - #~ msgid "You are not a Kfet member, so you can't use your note account." #~ msgstr "Usted no es un miembro de la Kfet, no puede usar su cuenta note." diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 0a82c31..65fd606 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-08 10:23+0100\n" -"PO-Revision-Date: 2023-11-08 10:48+0100\n" +"POT-Creation-Date: 2022-04-10 22:34+0200\n" +"PO-Revision-Date: 2022-04-11 22:05+0200\n" "Last-Translator: elkmaennchen \n" "Language-Team: French \n" "Language: fr\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.0\n" #: apps/activity/apps.py:10 apps/activity/models.py:151 #: apps/activity/models.py:167 @@ -53,13 +53,16 @@ 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:182 +#: 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 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301 #: apps/permission/models.py:330 #: apps/registration/templates/registration/future_profile_detail.html:16 +#: apps/wei/models.py:67 apps/wei/models.py:131 apps/wei/tables.py:282 +#: apps/wei/templates/wei/base.html:26 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "name" msgstr "nom" @@ -92,7 +95,7 @@ msgstr "types d'activité" #: apps/activity/models.py:68 #: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/note/models/transactions.py:81 apps/permission/models.py:110 -#: apps/permission/models.py:189 +#: apps/permission/models.py:189 apps/wei/models.py:78 apps/wei/models.py:142 msgid "description" msgstr "description" @@ -101,8 +104,8 @@ msgid "location" msgstr "lieu" #: apps/activity/models.py:76 -msgid "Place where the activity is organized, eg. BDE." -msgstr "Lieu où l'activité est organisée, par exemple à Ker Lann." +msgid "Place where the activity is organized, eg. Kfet." +msgstr "Lieu où l'activité est organisée, par exemple la Kfet." #: apps/activity/models.py:83 #: apps/activity/templates/activity/includes/activity_info.html:22 @@ -111,8 +114,10 @@ msgstr "Lieu où l'activité est organisée, par exemple à Ker Lann." msgid "type" msgstr "type" -#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:290 -#: apps/note/models/notes.py:148 +#: 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:285 +#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13 +#: apps/wei/templates/wei/survey.html:15 msgid "user" msgstr "utilisateur" @@ -132,8 +137,9 @@ msgid "attendees club" msgstr "club attendu" #: apps/activity/models.py:105 -msgid "Club that is authorized to join the activity." -msgstr "Club qui est autorisé à rejoindre l'activité." +msgid "Club that is authorized to join the activity. Mostly the Kfet club." +msgstr "" +"Club qui est autorisé à rejoindre l'activité. Très souvent le club Kfet." #: apps/activity/models.py:109 #: apps/activity/templates/activity/includes/activity_info.html:25 @@ -203,6 +209,7 @@ msgstr "La note est en négatif." #: apps/activity/models.py:240 #: apps/treasury/templates/treasury/sogecredit_detail.html:14 +#: apps/wei/templates/wei/attribute_bus_1A.html:16 msgid "last name" msgstr "nom de famille" @@ -210,6 +217,8 @@ msgstr "nom de famille" #: apps/member/templates/member/includes/profile_info.html:4 #: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/treasury/templates/treasury/sogecredit_detail.html:17 +#: apps/wei/templates/wei/attribute_bus_1A.html:19 +#: apps/wei/templates/wei/weimembership_form.html:14 msgid "first name" msgstr "prénom" @@ -249,18 +258,20 @@ msgstr "Entré le " msgid "remove" msgstr "supprimer" -#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:196 +#: apps/activity/tables.py:82 apps/note/forms.py:68 apps/treasury/models.py:199 msgid "Type" msgstr "Type" -#: apps/activity/tables.py:84 apps/member/forms.py:180 -#: apps/registration/forms.py:68 apps/treasury/forms.py:131 +#: apps/activity/tables.py:84 apps/member/forms.py:186 +#: apps/registration/forms.py:91 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:185 +#: apps/activity/tables.py:86 apps/member/forms.py:191 #: apps/note/templates/note/transaction_form.html:138 -#: apps/registration/forms.py:73 apps/treasury/forms.py:133 +#: apps/registration/forms.py:96 apps/treasury/forms.py:133 +#: apps/wei/forms/registration.py:109 msgid "First name" msgstr "Prénom" @@ -283,19 +294,19 @@ msgstr "Invité supprimé" #: apps/activity/templates/activity/activity_entry.html:14 #: apps/note/models/transactions.py:257 #: apps/note/templates/note/transaction_form.html:17 -#: apps/note/templates/note/transaction_form.html:146 +#: apps/note/templates/note/transaction_form.html:152 #: note_kfet/templates/base.html:72 msgid "Transfer" msgstr "Virement" #: apps/activity/templates/activity/activity_entry.html:18 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:22 msgid "Credit" msgstr "Crédit" #: apps/activity/templates/activity/activity_entry.html:21 -#: apps/note/models/transactions.py:312 +#: apps/note/models/transactions.py:317 #: apps/note/templates/note/transaction_form.html:26 msgid "Debit" msgstr "Débit" @@ -311,19 +322,24 @@ msgstr "Retour à la page de l'activité" #: apps/activity/templates/activity/activity_entry.html:94 #: apps/activity/templates/activity/activity_entry.html:129 -msgid "Entry done, but caution: the user is not a member." -msgstr "Entrée effectuée, mais attention : la personne n'est pas un membre." +msgid "Entry done, but caution: the user is not a Kfet member." +msgstr "" +"Entrée effectuée, mais attention : la personne n'est pas un adhérent Kfet." #: apps/activity/templates/activity/activity_entry.html:132 msgid "Entry done!" msgstr "Entrée effectuée !" #: apps/activity/templates/activity/activity_form.html:16 -#: apps/member/templates/member/add_members.html:32 +#: apps/member/templates/member/add_members.html:46 #: apps/member/templates/member/club_form.html:16 #: apps/note/templates/note/transactiontemplate_form.html:18 -#: apps/treasury/forms.py:89 apps/treasury/forms.py:141 +#: apps/treasury/forms.py:89 apps/treasury/forms.py:143 #: apps/treasury/templates/treasury/invoice_form.html:74 +#: apps/wei/templates/wei/bus_form.html:17 +#: apps/wei/templates/wei/busteam_form.html:17 +#: apps/wei/templates/wei/weiclub_form.html:17 +#: apps/wei/templates/wei/weiregistration_form.html:18 msgid "Submit" msgstr "Envoyer" @@ -360,9 +376,6 @@ msgid "Entry page" msgstr "Page des entrées" #: apps/activity/templates/activity/includes/activity_info.html:65 -#: env/lib/python3.11/site-packages/bootstrap4/components.py:17 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/form_errors.html:3 -#: env/lib/python3.11/site-packages/bootstrap4/templates/bootstrap4/messages.html:4 msgid "close" msgstr "fermer" @@ -455,7 +468,7 @@ msgstr "créer" #: apps/logs/models.py:65 apps/note/tables.py:166 apps/note/tables.py:190 #: apps/note/tables.py:237 apps/permission/models.py:127 -#: apps/treasury/tables.py:38 +#: apps/treasury/tables.py:38 apps/wei/tables.py:74 msgid "delete" msgstr "supprimer" @@ -484,25 +497,25 @@ 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:209 +#: 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:214 +#: 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:302 +#: apps/member/admin.py:65 apps/member/models.py:319 msgid "roles" msgstr "rôles" -#: apps/member/admin.py:66 apps/member/models.py:316 +#: apps/member/admin.py:66 apps/member/models.py:333 msgid "fee" msgstr "cotisation" -#: apps/member/apps.py:14 +#: apps/member/apps.py:14 apps/wei/tables.py:226 apps/wei/tables.py:257 msgid "member" msgstr "adhérent" @@ -535,31 +548,48 @@ 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:33 apps/registration/views.py:252 +#: apps/registration/forms.py:33 apps/registration/views.py:262 msgid "An alias with a similar name already exists." msgstr "Un alias avec un nom similaire existe déjà." -#: apps/member/forms.py:166 apps/registration/forms.py:55 +#: apps/member/forms.py:165 apps/registration/forms.py:71 +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/registration/forms.py:73 +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:78 +#: apps/wei/forms/registration.py:91 msgid "Credit type" msgstr "Type de rechargement" -#: apps/member/forms.py:167 apps/registration/forms.py:56 +#: apps/member/forms.py:173 apps/registration/forms.py:79 +#: apps/wei/forms/registration.py:92 msgid "No credit" msgstr "Pas de rechargement" -#: apps/member/forms.py:169 +#: 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:173 apps/registration/forms.py:61 +#: apps/member/forms.py:179 apps/registration/forms.py:84 +#: apps/wei/forms/registration.py:97 msgid "Credit amount" msgstr "Montant à créditer" -#: apps/member/forms.py:212 +#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:144 +#: apps/registration/forms.py:101 apps/treasury/forms.py:135 +#: apps/wei/forms/registration.py:114 +msgid "Bank" +msgstr "Banque" + +#: apps/member/forms.py:223 msgid "User" msgstr "Utilisateur" -#: apps/member/forms.py:226 +#: apps/member/forms.py:237 msgid "Roles" msgstr "Rôles" @@ -582,12 +612,14 @@ msgstr "haché" #: apps/member/models.py:38 #: apps/member/templates/member/includes/profile_info.html:43 #: apps/registration/templates/registration/future_profile_detail.html:40 +#: apps/wei/templates/wei/weimembership_form.html:44 msgid "phone number" msgstr "numéro de téléphone" #: apps/member/models.py:45 #: apps/member/templates/member/includes/profile_info.html:37 #: apps/registration/templates/registration/future_profile_detail.html:34 +#: apps/wei/templates/wei/weimembership_form.html:38 msgid "section" msgstr "section" @@ -595,73 +627,114 @@ msgstr "section" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" -#: apps/member/models.py:54 +#: apps/member/models.py:54 apps/wei/templates/wei/attribute_bus_1A.html:25 +#: apps/wei/templates/wei/weimembership_form.html:32 msgid "department" msgstr "département" #: apps/member/models.py:56 -msgid "Informatique" -msgstr "Informatique" +msgid "Informatics (A0)" +msgstr "Informatique (A0)" #: apps/member/models.py:57 -msgid "Mathématiques" -msgstr "Mathématiques" +msgid "Mathematics (A1)" +msgstr "Mathématiques (A1)" #: apps/member/models.py:58 -msgid "Droit - économie - management" -msgstr "Économie-gestion" +msgid "Physics (A2)" +msgstr "Physique (A2)" #: apps/member/models.py:59 -msgid "Mécatronique" -msgstr "" +msgid "Applied physics (A'2)" +msgstr "Physique appliquée (A'2)" #: apps/member/models.py:60 -msgid "Sciences du sport et éducation physique" -msgstr "" +msgid "Chemistry (A''2)" +msgstr "Chimie (A''2)" #: apps/member/models.py:61 -msgid "Sciences pour l’Environnement" -msgstr "" +msgid "Biology (A3)" +msgstr "Biologie (A3)" #: apps/member/models.py:62 -msgid "Externe" -msgstr "" +msgid "SAPHIRE (B1234)" +msgstr "SAPHIRE (B1234)" + +#: apps/member/models.py:63 +msgid "Mechanics (B1)" +msgstr "Mécanique (B1)" + +#: apps/member/models.py:64 +msgid "Civil engineering (B2)" +msgstr "Génie civil (B2)" + +#: apps/member/models.py:65 +msgid "Mechanical engineering (B3)" +msgstr "Génie mécanique (B3)" + +#: apps/member/models.py:66 +msgid "EEA (B4)" +msgstr "EEA (B4)" + +#: apps/member/models.py:67 +msgid "Design (C)" +msgstr "Design (C)" + +#: apps/member/models.py:68 +msgid "Economy-management (D2)" +msgstr "Économie-gestion (D2)" #: apps/member/models.py:69 +msgid "Social sciences (D3)" +msgstr "Sciences sociales (D3)" + +#: apps/member/models.py:70 +msgid "English (E)" +msgstr "Anglais (E)" + +#: apps/member/models.py:71 +msgid "External (EXT)" +msgstr "Externe (EXT)" + +#: apps/member/models.py:78 msgid "promotion" msgstr "promotion" -#: apps/member/models.py:70 +#: apps/member/models.py:79 msgid "Year of entry to the school (None if not ENS student)" msgstr "Année d'entrée dans l'école (None si non-étudiant·e de l'ENS)" -#: apps/member/models.py:74 +#: apps/member/models.py:83 #: apps/member/templates/member/includes/profile_info.html:47 #: apps/registration/templates/registration/future_profile_detail.html:37 +#: apps/wei/templates/wei/weimembership_form.html:41 msgid "address" msgstr "adresse" -#: apps/member/models.py:81 +#: apps/member/models.py:90 #: apps/member/templates/member/includes/profile_info.html:50 #: apps/registration/templates/registration/future_profile_detail.html:43 +#: apps/wei/templates/wei/weimembership_form.html:47 msgid "paid" msgstr "payé" -#: apps/member/models.py:82 +#: apps/member/models.py:91 msgid "Tells if the user receive a salary." msgstr "Indique si l'utilisateur perçoit un salaire." -#: apps/member/models.py:91 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:796 +#: apps/member/models.py:100 apps/treasury/tables.py:143 msgid "No" msgstr "Non" -#: apps/member/models.py:92 -#: env/lib/python3.11/site-packages/django/forms/widgets.py:795 -msgid "Yes" -msgstr "Oui" +#: apps/member/models.py:101 +msgid "Yes (receive them in french)" +msgstr "Oui (les recevoir en français)" -#: apps/member/models.py:94 +#: apps/member/models.py:102 +msgid "Yes (receive them in english)" +msgstr "Oui (les recevoir en anglais)" + +#: apps/member/models.py:104 msgid "" "Register on the mailing list to stay informed of the events of the campus (1 " "mail/week)" @@ -669,7 +742,7 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des événements sur " "le campus (1 mail par semaine)" -#: apps/member/models.py:99 +#: apps/member/models.py:109 msgid "" "Register on the mailing list to stay informed of the sport events of the " "campus (1 mail/week)" @@ -677,7 +750,7 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des actualités " "sportives sur le campus (1 mail par semaine)" -#: apps/member/models.py:104 +#: apps/member/models.py:114 msgid "" "Register on the mailing list to stay informed of the art events of the " "campus (1 mail/week)" @@ -685,119 +758,121 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des actualités " "artistiques sur le campus (1 mail par semaine)" -#: apps/member/models.py:108 +#: apps/member/models.py:118 msgid "report frequency (in days)" msgstr "fréquence des rapports (en jours)" -#: apps/member/models.py:113 +#: apps/member/models.py:123 msgid "last report date" msgstr "date de dernier rapport" -#: apps/member/models.py:118 +#: apps/member/models.py:128 msgid "email confirmed" msgstr "adresse email confirmée" -#: apps/member/models.py:123 +#: apps/member/models.py:133 msgid "registration valid" msgstr "inscription valide" -#: apps/member/models.py:145 apps/member/models.py:146 +#: apps/member/models.py:162 apps/member/models.py:163 msgid "user profile" msgstr "profil utilisateur" -#: apps/member/models.py:156 -msgid "Activate your Note Ker Lann account" -msgstr "Activez votre compte Note Ker Lann" +#: apps/member/models.py:173 +msgid "Activate your Note Kfet account" +msgstr "Activez votre compte Note Kfet" -#: apps/member/models.py:187 +#: 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 +#: apps/wei/templates/wei/base.html:70 +#: apps/wei/templates/wei/weimembership_form.html:20 msgid "email" msgstr "courriel" -#: apps/member/models.py:194 +#: apps/member/models.py:211 msgid "parent club" msgstr "club parent" -#: apps/member/models.py:203 +#: apps/member/models.py:220 msgid "require memberships" msgstr "nécessite des adhésions" -#: apps/member/models.py:204 +#: 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:220 +#: 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:221 +#: 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:228 +#: 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:229 +#: 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:235 +#: 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:236 +#: 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:271 apps/member/models.py:296 +#: apps/member/models.py:288 apps/member/models.py:313 #: apps/note/models/notes.py:176 msgid "club" msgstr "club" -#: apps/member/models.py:272 +#: apps/member/models.py:289 msgid "clubs" msgstr "clubs" -#: apps/member/models.py:307 +#: apps/member/models.py:324 msgid "membership starts on" msgstr "l'adhésion commence le" -#: apps/member/models.py:311 +#: apps/member/models.py:328 msgid "membership ends on" msgstr "l'adhésion finit le" -#: apps/member/models.py:404 +#: 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:413 apps/member/views.py:672 +#: 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:425 apps/member/views.py:681 +#: 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:459 +#: 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:462 apps/note/models/transactions.py:380 +#: apps/member/models.py:507 apps/note/models/transactions.py:389 msgid "membership" msgstr "adhésion" -#: apps/member/models.py:463 +#: apps/member/models.py:508 msgid "memberships" msgstr "adhésions" @@ -805,7 +880,18 @@ msgstr "adhésions" msgid "Renew" msgstr "Renouveler" -#: apps/member/templates/member/add_members.html:16 +#: apps/member/templates/member/add_members.html:17 +#, python-format +msgid "" +"The user is not a member of the club·s %(clubs)s. An additional fee of " +"%(pretty_fee)s will be charged to renew automatically the membership in this/" +"these club·s." +msgstr "" +"Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Un " +"montant supplémentaire de %(pretty_fee)s sera débité afin de renouveler " +"automatiquement l'adhésion dans ce·s club·s." + +#: apps/member/templates/member/add_members.html:22 #, python-format msgid "" "The user is not a member of the club·s %(clubs)s. Please create the required " @@ -814,7 +900,16 @@ msgstr "" "Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Merci de " "d'abord créer l'adhésion requise, sinon cette adhésion va échouer." -#: apps/member/templates/member/add_members.html:21 +#: apps/member/templates/member/add_members.html:29 +#, python-format +msgid "" +"This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will be " +"charged to adhere automatically to this/these club·s." +msgstr "" +"Ce club a pour parent·s %(clubs)s. Un coût supplémentaire de %(pretty_fee)s " +"peut être ajouté pour adhérer automatiquement à ce·s club·s." + +#: apps/member/templates/member/add_members.html:34 #, python-format msgid "" "This club has parents %(clubs)s. Please make sure that the user is a member " @@ -831,6 +926,7 @@ msgstr "Compte n°" #: apps/member/templates/member/base.html:48 #: apps/member/templates/member/base.html:62 apps/member/views.py:60 #: apps/registration/templates/registration/future_profile_detail.html:48 +#: apps/wei/templates/wei/weimembership_form.html:117 msgid "Update Profile" msgstr "Modifier le profil" @@ -904,7 +1000,7 @@ msgid "Add" msgstr "Ajouter" #: apps/member/templates/member/club_detail.html:13 -#: apps/permission/templates/permission/all_rights.html:77 +#: apps/permission/templates/permission/all_rights.html:32 msgid "Club managers" msgstr "Bureau du club" @@ -914,6 +1010,7 @@ msgstr "Membres du club" #: apps/member/templates/member/club_detail.html:40 #: apps/member/templates/member/profile_detail.html:32 +#: apps/wei/templates/wei/weiclub_detail.html:75 msgid "Transaction history" msgstr "Historique des transactions" @@ -930,6 +1027,7 @@ msgid "Filter roles:" msgstr "Filtrer par rôle :" #: apps/member/templates/member/club_members.html:36 +#: apps/wei/templates/wei/weimembership_list.html:19 msgid "There is no membership found with this pattern." msgstr "Il n'y a pas d'adhésion trouvée avec cette entrée." @@ -942,18 +1040,20 @@ msgid "days" msgstr "jours" #: apps/member/templates/member/includes/club_info.html:31 +#: apps/wei/templates/wei/base.html:40 msgid "membership fee" msgstr "cotisation pour adhérer" #: apps/member/templates/member/includes/club_info.html:43 #: apps/member/templates/member/includes/profile_info.html:55 #: apps/treasury/templates/treasury/sogecredit_detail.html:24 +#: apps/wei/templates/wei/base.html:60 msgid "balance" msgstr "solde du compte" #: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/profile_info.html:20 -#: apps/note/models/notes.py:287 +#: apps/note/models/notes.py:287 apps/wei/templates/wei/base.html:66 msgid "aliases" msgstr "alias" @@ -965,6 +1065,7 @@ msgstr "Gérer les alias" #: apps/member/templates/member/includes/profile_info.html:7 #: apps/registration/templates/registration/future_profile_detail.html:19 #: apps/treasury/templates/treasury/sogecredit_detail.html:20 +#: apps/wei/templates/wei/weimembership_form.html:17 msgid "username" msgstr "pseudo" @@ -1043,11 +1144,13 @@ msgstr "Recadrer et envoyer" #: apps/member/templates/member/profile_detail.html:11 #: apps/registration/templates/registration/future_profile_detail.html:28 +#: apps/wei/templates/wei/weimembership_form.html:26 msgid "This user doesn't have confirmed his/her e-mail address." msgstr "Cet utilisateur n'a pas encore confirmé son adresse e-mail." #: apps/member/templates/member/profile_detail.html:13 #: apps/registration/templates/registration/future_profile_detail.html:29 +#: apps/wei/templates/wei/weimembership_form.html:27 msgid "Click here to resend a validation link." msgstr "Cliquez ici pour renvoyer un lien de validation." @@ -1060,17 +1163,10 @@ msgid "Note friendships" msgstr "Amitiés note" #: apps/member/templates/member/profile_trust.html:28 -#, fuzzy -#| msgid "" -#| "Adding someone as a friend enables them to initiate transactions coming " -#| "from your account (while keeping your balance positive). This is designed " -#| "to simplify using note kfet transfers to transfer money between users. " -#| "The intent is that one person can make all transfers for a group of " -#| "friends without needing additional rights among them." msgid "" "Adding someone as a friend enables them to initiate transactions coming from " "your account (while keeping your balance positive). This is designed to " -"simplify using note ker lann transfers to transfer money between users. The " +"simplify using note kfet transfers to transfer money between users. The " "intent is that one person can make all transfers for a group of friends " "without needing additional rights among them." msgstr "" @@ -1123,11 +1219,11 @@ msgstr "Détails du club" msgid "Update club" msgstr "Modifier le club" -#: apps/member/views.py:569 +#: apps/member/views.py:574 msgid "Add new member to the club" msgstr "Ajouter un nouveau membre au club" -#: apps/member/views.py:663 +#: apps/member/views.py:703 apps/wei/views.py:973 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." @@ -1135,19 +1231,19 @@ msgstr "" "Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas " "avoir un solde négatif." -#: apps/member/views.py:685 +#: apps/member/views.py:725 msgid "The membership must start after {:%m-%d-%Y}." msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}." -#: apps/member/views.py:690 +#: apps/member/views.py:730 msgid "The membership must begin before {:%m-%d-%Y}." msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}." -#: apps/member/views.py:797 +#: apps/member/views.py:876 msgid "Manage roles of an user in the club" msgstr "Gérer les rôles d'un utilisateur dans le club" -#: apps/member/views.py:821 +#: apps/member/views.py:901 msgid "Members of the club" msgstr "Membres du club" @@ -1186,7 +1282,7 @@ msgstr "Destination" msgid "Reason" msgstr "Raison" -#: apps/note/forms.py:79 +#: apps/note/forms.py:79 apps/treasury/tables.py:136 msgid "Valid" msgstr "Valide" @@ -1437,7 +1533,11 @@ msgstr "transactions issues de boutons" msgid "first_name" msgstr "prénom" -#: apps/note/models/transactions.py:323 +#: apps/note/models/transactions.py:311 +msgid "bank" +msgstr "banque" + +#: apps/note/models/transactions.py:328 msgid "" "A special transaction is only possible between a Note associated to a " "payment method and a User or a Club" @@ -1445,24 +1545,25 @@ msgstr "" "Une transaction spéciale n'est possible que entre une note associée à un " "mode de paiement et un utilisateur ou un club" -#: apps/note/models/transactions.py:349 apps/note/models/transactions.py:352 -#: env/lib/python3.11/site-packages/django/forms/fields.py:91 +#: apps/note/models/transactions.py:355 apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:361 apps/wei/views.py:978 +#: apps/wei/views.py:982 msgid "This field is required." msgstr "Ce champ est requis." -#: apps/note/models/transactions.py:358 +#: apps/note/models/transactions.py:367 msgid "Special transaction" msgstr "Transaction de crédit/retrait" -#: apps/note/models/transactions.py:359 +#: apps/note/models/transactions.py:368 msgid "Special transactions" msgstr "Transactions de crédit/retrait" -#: apps/note/models/transactions.py:375 +#: apps/note/models/transactions.py:384 msgid "membership transaction" msgstr "transaction d'adhésion" -#: apps/note/models/transactions.py:376 +#: apps/note/models/transactions.py:385 apps/treasury/models.py:292 msgid "membership transactions" msgstr "transactions d'adhésion" @@ -1482,10 +1583,8 @@ msgstr "Pas de motif spécifié" #: apps/treasury/tables.py:39 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:30 #: apps/treasury/templates/treasury/sogecredit_detail.html:65 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:499 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:13 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:38 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:7 +#: apps/wei/tables.py:75 apps/wei/tables.py:118 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:31 #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:18 #: note_kfet/templates/oauth2_provider/application_detail.html:39 #: note_kfet/templates/oauth2_provider/authorized-token-delete.html:12 @@ -1493,7 +1592,11 @@ msgid "Delete" msgstr "Supprimer" #: apps/note/tables.py:222 apps/note/templates/note/conso_form.html:132 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:37 +#: apps/wei/tables.py:49 apps/wei/tables.py:50 +#: apps/wei/templates/wei/base.html:89 +#: apps/wei/templates/wei/bus_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:20 +#: apps/wei/templates/wei/busteam_detail.html:40 #: note_kfet/templates/oauth2_provider/application_detail.html:38 msgid "Edit" msgstr "Éditer" @@ -1538,26 +1641,23 @@ msgid "Double consumptions" msgstr "Consommations doubles" #: apps/note/templates/note/conso_form.html:154 -#: apps/note/templates/note/transaction_form.html:157 +#: apps/note/templates/note/transaction_form.html:163 msgid "Recent transactions history" msgstr "Historique des transactions récentes" #: apps/note/templates/note/mails/negative_balance.html:43 +#: apps/note/templates/note/mails/negative_balance.txt:25 #: apps/note/templates/note/mails/negative_notes_report.html:46 +#: apps/note/templates/note/mails/negative_notes_report.txt:13 #: apps/note/templates/note/mails/weekly_report.html:51 +#: apps/note/templates/note/mails/weekly_report.txt:32 #: apps/registration/templates/registration/mails/email_validation_email.html:40 #: apps/registration/templates/registration/mails/email_validation_email.txt:16 -msgid "Mail generated by the Note Ker Lann on the" -msgstr "Mail généré par la Note Ker Lann le" - -#: apps/note/templates/note/mails/negative_balance.txt:25 -#: apps/note/templates/note/mails/negative_notes_report.txt:13 -#: apps/note/templates/note/mails/weekly_report.txt:32 msgid "Mail generated by the Note Kfet on the" msgstr "Mail généré par la Note Kfet le" #: apps/note/templates/note/transaction_form.html:58 -#: apps/note/templates/note/transaction_form.html:172 +#: apps/note/templates/note/transaction_form.html:178 msgid "Select emitters" msgstr "Sélection des émetteurs" @@ -1566,7 +1666,7 @@ msgid "I am the emitter" msgstr "Je suis l'émetteur" #: apps/note/templates/note/transaction_form.html:85 -#: apps/note/templates/note/transaction_form.html:174 +#: apps/note/templates/note/transaction_form.html:180 msgid "Select receivers" msgstr "Sélection des destinataires" @@ -1575,25 +1675,26 @@ msgid "Action" msgstr "Action" #: apps/note/templates/note/transaction_form.html:116 -#: apps/treasury/forms.py:135 apps/treasury/tables.py:67 +#: apps/treasury/forms.py:137 apps/treasury/tables.py:67 +#: apps/treasury/tables.py:132 #: apps/treasury/templates/treasury/remittance_form.html:23 msgid "Amount" msgstr "Montant" #: apps/note/templates/note/transaction_form.html:132 -#: apps/treasury/models.py:51 +#: apps/treasury/models.py:54 msgid "Name" msgstr "Nom" -#: apps/note/templates/note/transaction_form.html:171 +#: apps/note/templates/note/transaction_form.html:177 msgid "Select emitter" msgstr "Sélection de l'émetteur" -#: apps/note/templates/note/transaction_form.html:173 +#: apps/note/templates/note/transaction_form.html:179 msgid "Select receiver" msgstr "Sélection du destinataire" -#: apps/note/templates/note/transaction_form.html:175 +#: apps/note/templates/note/transaction_form.html:181 msgid "Transfer type" msgstr "Type de transfert" @@ -1728,7 +1829,7 @@ msgstr "" "l'utilisateur est expirée." #: apps/permission/models.py:183 -#: apps/permission/templates/permission/all_rights.html:56 +#: apps/permission/templates/permission/all_rights.html:89 msgid "permanent" msgstr "permanent" @@ -1781,56 +1882,62 @@ msgstr "" "Vous n'avez pas la permission de supprimer cette instance du modèle " "{app_label}.{model_name}." -#: apps/permission/templates/permission/all_rights.html:13 +#: apps/permission/templates/permission/all_rights.html:12 +msgid "Users that have surnormal rights" +msgstr "Liste des utilisateurs ayant des droits surnormaux" + +#: apps/permission/templates/permission/all_rights.html:16 +msgid "Superusers have all rights on everything, to manage the website." +msgstr "" +"Les super-utilisateurs ont tous les droits sur tout, afin de gérer le site." + +#: apps/permission/templates/permission/all_rights.html:21 +msgid "Superusers" +msgstr "Super-utilisateurs" + +#: apps/permission/templates/permission/all_rights.html:45 msgid "Roles description" msgstr "Description de tous les rôles" -#: apps/permission/templates/permission/all_rights.html:20 +#: apps/permission/templates/permission/all_rights.html:52 msgid "Filter with roles that I have in at least one club" msgstr "Filtrer les rôles que je possède dans au moins un club" -#: apps/permission/templates/permission/all_rights.html:36 +#: apps/permission/templates/permission/all_rights.html:69 msgid "Owned" msgstr "Possédé" -#: apps/permission/templates/permission/all_rights.html:47 +#: apps/permission/templates/permission/all_rights.html:80 msgid "Own this role in the clubs" msgstr "Possède ce rôle dans les clubs" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Mask:" msgstr "Masque :" -#: apps/permission/templates/permission/all_rights.html:53 +#: apps/permission/templates/permission/all_rights.html:86 msgid "Query:" msgstr "Requête :" -#: apps/permission/templates/permission/all_rights.html:59 +#: apps/permission/templates/permission/all_rights.html:92 msgid "No associated permission" msgstr "Pas de permission associée" -#: apps/permission/templates/permission/all_rights.html:71 -msgid "Users that have surnormal rights" -msgstr "Liste des utilisateurs ayant des droits surnormaux" - #: apps/permission/templates/permission/scopes.html:8 msgid "Available scopes" msgstr "Scopes disponibles" #: apps/permission/templates/permission/scopes.html:42 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:24 msgid "No applications defined" msgstr "Pas d'application définie" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "Click here" msgstr "Cliquez ici" #: apps/permission/templates/permission/scopes.html:43 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:17 #: note_kfet/templates/oauth2_provider/application_list.html:25 msgid "if you want to register a new one" msgstr "si vous voulez en enregistrer une nouvelle" @@ -1853,7 +1960,7 @@ msgstr "" "Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » " "avec ces paramètres. Merci de les corriger et de réessayer." -#: apps/permission/views.py:112 note_kfet/templates/base.html:102 +#: apps/permission/views.py:112 note_kfet/templates/base.html:108 msgid "Rights" msgstr "Droits" @@ -1869,17 +1976,42 @@ msgstr "inscription" msgid "This email address is already used." msgstr "Cet email est déjà pris." -#: apps/registration/forms.py:78 +#: apps/registration/forms.py:49 +msgid "" +"I declare that I opened or I will open soon a bank account in the Société " +"générale with the BDE partnership." +msgstr "" +"Je déclare avoir ouvert ou ouvrir prochainement un compte à la société " +"générale avec le partenariat du BDE." + +#: apps/registration/forms.py:51 +msgid "" +"Warning: this engages you to open your bank account. If you finally decides " +"to don't open your account, you will have to pay the BDE membership." +msgstr "" +"Attention : cocher cette case vous engage à ouvrir votre compte. Si vous " +"décidez de ne pas le faire, vous devrez payer l'adhésion au BDE." + +#: apps/registration/forms.py:59 +msgid "Register to the WEI" +msgstr "S'inscrire au WEI" + +#: apps/registration/forms.py:61 +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." +msgstr "" +"Cochez cette case si vous voulez vous inscrire au WEI. Si vous hésitez, vous " +"pourrez toujours vous inscrire plus tard, après avoir validé votre compte à " +"la Kfet." + +#: apps/registration/forms.py:106 msgid "Join BDE Club" -msgstr "Adhérer au BDE" +msgstr "Adhérer au club BDE" -#: apps/registration/forms.py:84 -msgid "Join BDA Club" -msgstr "Adhérer au BDA" - -#: apps/registration/forms.py:90 -msgid "Join BDS Club" -msgstr "Adhérer au BDS" +#: apps/registration/forms.py:113 +msgid "Join Kfet Club" +msgstr "Adhérer au club Kfet" #: apps/registration/templates/registration/email_validation_complete.html:15 msgid "Your email have successfully been validated." @@ -1891,9 +2023,11 @@ msgid "You can now log in." msgstr "Vous pouvez désormais vous connecter." #: apps/registration/templates/registration/email_validation_complete.html:23 -msgid "You must pay now your membership to complete your registration." +msgid "" +"You must pay now your membership in the Kfet to complete your registration." msgstr "" -"Vous devez désormais payer votre adhésion pour compléter votre inscription." +"Vous devez désormais payer votre adhésion à la Kfet pour compléter votre " +"inscription." #: apps/registration/templates/registration/email_validation_complete.html:28 msgid "" @@ -1915,14 +2049,11 @@ msgstr "" "validation pour activer votre compte." #: apps/registration/templates/registration/email_validation_email_sent.html:17 -msgid "" -"You must also pay your membership. A administrator will then activate your " -"account" -msgstr "" -"Vous devez désormais payer votre adhésion pour compléter votre inscription. " -"Un administrateur activera ensuite votre compte" +msgid "You must also go to the Kfet to pay your membership." +msgstr "Vous devrez également vous rendre à la Kfet pour payer votre adhésion." #: apps/registration/templates/registration/future_profile_detail.html:49 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:11 msgid "Delete registration" msgstr "Supprimer l'inscription" @@ -1930,7 +2061,14 @@ msgstr "Supprimer l'inscription" msgid "Validate account" msgstr "Valider le compte" -#: apps/registration/templates/registration/future_profile_detail.html:65 +#: apps/registration/templates/registration/future_profile_detail.html:62 +msgid "" +"The user declared that he/she opened a bank account in the Société générale." +msgstr "L'utilisateur a déclaré avoir ouvert un compte à la société générale." + +#: apps/registration/templates/registration/future_profile_detail.html:71 +#: apps/wei/templates/wei/weimembership_form.html:127 +#: apps/wei/templates/wei/weimembership_form.html:186 msgid "Validate registration" msgstr "Valider l'inscription" @@ -1938,10 +2076,6 @@ msgstr "Valider l'inscription" msgid "New user" msgstr "Nouvel utilisateur" -#: apps/registration/templates/registration/mails/email_validation_email.html:7 -msgid "Activation of your Note Ker Lann account" -msgstr "Activez votre compte Note Ker Lann" - #: apps/registration/templates/registration/mails/email_validation_email.html:12 #: apps/registration/templates/registration/mails/email_validation_email.txt:3 msgid "Hi" @@ -1950,11 +2084,11 @@ msgstr "Bonjour" #: apps/registration/templates/registration/mails/email_validation_email.html:16 #: apps/registration/templates/registration/mails/email_validation_email.txt:5 msgid "" -"You recently registered on the Note Ker Lann. Please click on the link below " -"to confirm your registration." +"You recently registered on the Note Kfet. Please click on the link below to " +"confirm your registration." msgstr "" -"Vous vous êtes inscrit·e récemment sur la Note Ker Lann. Merci de cliquer " -"sur le lien ci-dessous pour confirmer votre adresse email." +"Vous vous êtes inscrit·e récemment sur la Note Kfet. Merci de cliquer sur le " +"lien ci-dessous pour confirmer votre adresse email." #: apps/registration/templates/registration/mails/email_validation_email.html:26 #: apps/registration/templates/registration/mails/email_validation_email.txt:9 @@ -1967,10 +2101,10 @@ msgstr "Ce lien n'est valide que pendant quelques jours." #: apps/registration/templates/registration/mails/email_validation_email.txt:11 msgid "" "After that, you'll have to wait that someone validates your account before " -"you can log in. You will need to pay your membership." +"you can log in. You will need to pay your membership in the Kfet." msgstr "" "Après cela, vous devrez attendre que quelqu'un valide votre compte avant de " -"pouvoir vous connecter. Vous devrez payer votre adhésion." +"pouvoir vous connecter. Vous devrez payer votre adhésion à la Kfet." #: apps/registration/templates/registration/mails/email_validation_email.html:34 #: apps/registration/templates/registration/mails/email_validation_email.txt:13 @@ -1979,53 +2113,57 @@ msgstr "Merci" #: apps/registration/templates/registration/mails/email_validation_email.html:39 #: apps/registration/templates/registration/mails/email_validation_email.txt:15 -msgid "The Note Ker Lann team." -msgstr "L'équipe de la Note Ker Lann." +msgid "The Note Kfet team." +msgstr "L'équipe de la Note Kfet." -#: apps/registration/views.py:39 +#: apps/registration/views.py:40 msgid "Register new user" msgstr "Enregistrer un nouvel utilisateur" -#: apps/registration/views.py:89 +#: apps/registration/views.py:98 msgid "Email validation" msgstr "Validation de l'adresse mail" -#: apps/registration/views.py:91 +#: apps/registration/views.py:100 msgid "Validate email" msgstr "Valider l'adresse e-mail" -#: apps/registration/views.py:135 +#: apps/registration/views.py:144 msgid "Email validation unsuccessful" msgstr "La validation de l'adresse mail a échoué" -#: apps/registration/views.py:146 +#: apps/registration/views.py:155 msgid "Email validation email sent" msgstr "L'email de vérification de l'adresse email a bien été envoyé" -#: apps/registration/views.py:154 +#: apps/registration/views.py:163 msgid "Resend email validation link" msgstr "Renvoyer le lien de validation" -#: apps/registration/views.py:172 +#: apps/registration/views.py:181 msgid "Pre-registered users list" msgstr "Liste des utilisateurs en attente d'inscription" -#: apps/registration/views.py:196 +#: apps/registration/views.py:205 msgid "Unregistered users" msgstr "Utilisateurs en attente d'inscription" -#: apps/registration/views.py:209 +#: apps/registration/views.py:218 msgid "Registration detail" msgstr "Détails de l'inscription" -#: apps/registration/views.py:281 +#: apps/registration/views.py:282 +msgid "You must join the BDE." +msgstr "Vous devez adhérer au BDE." + +#: apps/registration/views.py:306 msgid "" "The entered amount is not enough for the memberships, should be at least {}" msgstr "" "Le montant crédité est trop faible pour adhérer, il doit être au minimum de " "{}" -#: apps/registration/views.py:335 +#: apps/registration/views.py:387 msgid "Invalidate pre-registration" msgstr "Invalider l'inscription" @@ -2033,7 +2171,7 @@ msgstr "Invalider l'inscription" msgid "Treasury" msgstr "Trésorerie" -#: apps/treasury/forms.py:26 apps/treasury/models.py:90 +#: apps/treasury/forms.py:26 apps/treasury/models.py:93 #: apps/treasury/templates/treasury/invoice_form.html:22 msgid "This invoice is locked and can no longer be edited." msgstr "Cette facture est verrouillée et ne peut plus être éditée." @@ -2046,7 +2184,7 @@ msgstr "La remise est déjà fermée." msgid "You can't change the type of the remittance." msgstr "Vous ne pouvez pas changer le type de la remise." -#: apps/treasury/forms.py:125 apps/treasury/models.py:264 +#: apps/treasury/forms.py:125 apps/treasury/models.py:267 #: apps/treasury/tables.py:97 apps/treasury/tables.py:105 #: apps/treasury/templates/treasury/invoice_list.html:16 #: apps/treasury/templates/treasury/remittance_list.html:16 @@ -2062,111 +2200,137 @@ msgstr "Pas de remise associée" msgid "Invoice identifier" msgstr "Numéro de facture" -#: apps/treasury/models.py:37 -msgid "BD?" -msgstr "BD?" +#: apps/treasury/models.py:40 +msgid "BDE" +msgstr "BDE" -#: apps/treasury/models.py:42 +#: apps/treasury/models.py:45 msgid "Object" msgstr "Objet" -#: apps/treasury/models.py:46 +#: apps/treasury/models.py:49 msgid "Description" msgstr "Description" -#: apps/treasury/models.py:55 +#: apps/treasury/models.py:58 msgid "Address" msgstr "Adresse" -#: apps/treasury/models.py:60 apps/treasury/models.py:190 +#: apps/treasury/models.py:63 apps/treasury/models.py:193 msgid "Date" msgstr "Date" -#: apps/treasury/models.py:64 +#: apps/treasury/models.py:67 msgid "Acquitted" msgstr "Acquittée" -#: apps/treasury/models.py:69 +#: apps/treasury/models.py:72 msgid "Locked" msgstr "Verrouillée" -#: apps/treasury/models.py:70 +#: apps/treasury/models.py:73 msgid "An invoice can't be edited when it is locked." msgstr "Une facture ne peut plus être modifiée si elle est verrouillée." -#: apps/treasury/models.py:76 +#: apps/treasury/models.py:79 msgid "tex source" msgstr "fichier TeX source" -#: apps/treasury/models.py:110 apps/treasury/models.py:126 +#: apps/treasury/models.py:113 apps/treasury/models.py:129 msgid "invoice" msgstr "facture" -#: apps/treasury/models.py:111 +#: apps/treasury/models.py:114 msgid "invoices" msgstr "factures" -#: apps/treasury/models.py:114 +#: apps/treasury/models.py:117 #, python-brace-format msgid "Invoice #{id}" msgstr "Facture n°{id}" -#: apps/treasury/models.py:131 +#: apps/treasury/models.py:134 msgid "Designation" msgstr "Désignation" -#: apps/treasury/models.py:137 +#: apps/treasury/models.py:140 msgid "Quantity" msgstr "Quantité" -#: apps/treasury/models.py:142 +#: apps/treasury/models.py:145 msgid "Unit price" msgstr "Prix unitaire" -#: apps/treasury/models.py:158 +#: apps/treasury/models.py:161 msgid "product" msgstr "produit" -#: apps/treasury/models.py:159 +#: apps/treasury/models.py:162 msgid "products" msgstr "produits" -#: apps/treasury/models.py:179 +#: apps/treasury/models.py:182 msgid "remittance type" msgstr "type de remise" -#: apps/treasury/models.py:180 +#: apps/treasury/models.py:183 msgid "remittance types" msgstr "types de remises" -#: apps/treasury/models.py:201 +#: apps/treasury/models.py:204 msgid "Comment" msgstr "Commentaire" -#: apps/treasury/models.py:206 +#: apps/treasury/models.py:209 msgid "Closed" msgstr "Fermée" -#: apps/treasury/models.py:210 +#: apps/treasury/models.py:213 msgid "remittance" msgstr "remise" -#: apps/treasury/models.py:211 +#: apps/treasury/models.py:214 msgid "remittances" msgstr "remises" -#: apps/treasury/models.py:244 +#: apps/treasury/models.py:247 msgid "Remittance #{:d}: {}" msgstr "Remise n°{:d} : {}" -#: apps/treasury/models.py:268 +#: apps/treasury/models.py:271 msgid "special transaction proxy" msgstr "proxy de transaction spéciale" -#: apps/treasury/models.py:269 +#: apps/treasury/models.py:272 msgid "special transaction proxies" msgstr "proxys de transactions spéciales" +#: apps/treasury/models.py:298 +msgid "credit transaction" +msgstr "transaction de crédit" + +#: apps/treasury/models.py:430 +msgid "" +"This user doesn't have enough money to pay the memberships with its note. " +"Please ask her/him to credit the note before invalidating this credit." +msgstr "" +"Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa " +"note. Merci de lui demander de recharger sa note avant d'invalider ce crédit." + +#: apps/treasury/models.py:451 +#: apps/treasury/templates/treasury/sogecredit_detail.html:10 +msgid "Credit from the Société générale" +msgstr "Crédit de la Société générale" + +#: apps/treasury/models.py:452 +msgid "Credits from the Société générale" +msgstr "Crédits de la Société générale" + +#: apps/treasury/models.py:455 +#, python-brace-format +msgid "Soge credit for {user}" +msgstr "Crédit de la société générale pour l'utilisateur {user}" + #: apps/treasury/tables.py:20 msgid "Invoice #{:d}" msgstr "Facture n°{:d}" @@ -2186,6 +2350,10 @@ msgstr "Nombre de transactions" msgid "View" msgstr "Voir" +#: apps/treasury/tables.py:143 +msgid "Yes" +msgstr "Oui" + #: apps/treasury/templates/treasury/invoice_confirm_delete.html:10 #: apps/treasury/views.py:180 msgid "Delete invoice" @@ -2224,7 +2392,13 @@ msgstr "Ajouter produit" msgid "Remove product" msgstr "Retirer produit" -#: apps/treasury/templates/treasury/invoice_list.html:28 +#: apps/treasury/templates/treasury/invoice_list.html:19 +#: apps/treasury/templates/treasury/remittance_list.html:19 +#: apps/treasury/templates/treasury/sogecredit_list.html:20 +msgid "Société générale credits" +msgstr "Crédits de la Société générale" + +#: apps/treasury/templates/treasury/invoice_list.html:31 msgid "New invoice" msgstr "Nouvelle facture" @@ -2244,46 +2418,42 @@ msgstr "Transactions liées" msgid "There is no transaction linked with this remittance." msgstr "Il n'y a pas de transaction liée à cette remise." -#: apps/treasury/templates/treasury/remittance_list.html:24 +#: apps/treasury/templates/treasury/remittance_list.html:27 msgid "Opened remittances" msgstr "Remises ouvertes" -#: apps/treasury/templates/treasury/remittance_list.html:31 +#: apps/treasury/templates/treasury/remittance_list.html:34 msgid "There is no opened remittance." msgstr "Il n'y a pas de remise ouverte." -#: apps/treasury/templates/treasury/remittance_list.html:36 +#: apps/treasury/templates/treasury/remittance_list.html:39 msgid "New remittance" msgstr "Nouvelle remise" -#: apps/treasury/templates/treasury/remittance_list.html:42 +#: apps/treasury/templates/treasury/remittance_list.html:45 msgid "Transfers without remittances" msgstr "Transactions sans remise associée" -#: apps/treasury/templates/treasury/remittance_list.html:49 +#: apps/treasury/templates/treasury/remittance_list.html:52 msgid "There is no transaction without any linked remittance." msgstr "Il n'y a pas de transactions sans remise associée." -#: apps/treasury/templates/treasury/remittance_list.html:57 +#: apps/treasury/templates/treasury/remittance_list.html:60 msgid "Transfers with opened remittances" msgstr "Transactions associées à une remise ouverte" -#: apps/treasury/templates/treasury/remittance_list.html:64 +#: apps/treasury/templates/treasury/remittance_list.html:67 msgid "There is no transaction with an opened linked remittance." msgstr "Il n'y a pas de transaction associée à une remise ouverte." -#: apps/treasury/templates/treasury/remittance_list.html:72 +#: apps/treasury/templates/treasury/remittance_list.html:75 msgid "Closed remittances" msgstr "Remises fermées" -#: apps/treasury/templates/treasury/remittance_list.html:79 +#: apps/treasury/templates/treasury/remittance_list.html:82 msgid "There is no closed remittance yet." msgstr "Il n'y a pas encore de remise fermée." -#: apps/treasury/templates/treasury/sogecredit_detail.html:10 -msgid "Credit from the Société générale" -msgstr "Crédit de la Société générale" - #: apps/treasury/templates/treasury/sogecredit_detail.html:35 msgid "total amount" msgstr "montant total" @@ -2336,6 +2506,7 @@ msgstr "" "demande de crédit." #: apps/treasury/templates/treasury/sogecredit_detail.html:63 +#: apps/wei/tables.py:60 apps/wei/tables.py:102 msgid "Validate" msgstr "Valider" @@ -2343,10 +2514,6 @@ msgstr "Valider" msgid "Return to credit list" msgstr "Retour à la liste des crédits" -#: apps/treasury/templates/treasury/sogecredit_list.html:20 -msgid "Société générale credits" -msgstr "Crédits de la Société générale" - #: apps/treasury/templates/treasury/sogecredit_list.html:40 msgid "Filter with unvalidated credits only" msgstr "Filtrer avec uniquement les crédits non valides" @@ -2374,6 +2541,7 @@ msgid "Invoices list" msgstr "Liste des factures" #: apps/treasury/views.py:112 apps/treasury/views.py:286 +#: apps/treasury/views.py:412 msgid "You are not able to see the treasury interface." msgstr "Vous n'êtes pas autorisé à voir l'interface de trésorerie." @@ -2397,1394 +2565,639 @@ msgstr "Modifier la remise" msgid "Attach a transaction to a remittance" msgstr "Joindre une transaction à une remise" -#: env/lib/python3.11/site-packages/django/contrib/messages/apps.py:15 -msgid "Messages" +#: apps/treasury/views.py:404 +msgid "List of credits from the Société générale" +msgstr "Liste des crédits de la Société générale" + +#: apps/treasury/views.py:449 +msgid "Manage credits from the Société générale" +msgstr "Gérer les crédits de la Société générale" + +#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51 +#: apps/wei/models.py:62 apps/wei/models.py:180 +#: note_kfet/templates/base.html:102 +msgid "WEI" +msgstr "WEI" + +#: apps/wei/forms/registration.py:35 +msgid "The selected user is not validated. Please validate its account first" msgstr "" +"L'utilisateur sélectionné n'est pas validé. Merci de d'abord valider son " +"compte" -#: env/lib/python3.11/site-packages/django/contrib/sitemaps/apps.py:8 -msgid "Site Maps" -msgstr "" +#: apps/wei/forms/registration.py:59 apps/wei/models.py:126 +#: apps/wei/models.py:323 +msgid "bus" +msgstr "bus" -#: env/lib/python3.11/site-packages/django/contrib/staticfiles/apps.py:9 -msgid "Static Files" -msgstr "" - -#: env/lib/python3.11/site-packages/django/contrib/syndication/apps.py:7 -msgid "Syndication" -msgstr "Invitation" - -#. Translators: String used to replace omitted page numbers in elided page -#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. -#: env/lib/python3.11/site-packages/django/core/paginator.py:30 -msgid "…" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:50 -msgid "That page number is not an integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:52 -msgid "That page number is less than 1" -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/paginator.py:54 -msgid "That page contains no results" -msgstr "Il n'y a pas de résultat" - -#: env/lib/python3.11/site-packages/django/core/validators.py:22 -msgid "Enter a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:104 -#: env/lib/python3.11/site-packages/django/forms/fields.py:752 -msgid "Enter a valid URL." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:165 -msgid "Enter a valid integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:176 -msgid "Enter a valid email address." -msgstr "" - -#. Translators: "letters" means latin letters: a-z and A-Z. -#: env/lib/python3.11/site-packages/django/core/validators.py:259 +#: apps/wei/forms/registration.py:60 msgid "" -"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +"This choice is not definitive. The WEI organizers are free to attribute for " +"you a bus and a team, in particular if you are a free eletron." msgstr "" +"Ce choix n'est pas définitif. Les organisateurs du WEI sont libres de vous " +"attribuer un bus et une équipe, en particulier si vous êtes un électron " +"libre." -#: env/lib/python3.11/site-packages/django/core/validators.py:267 +#: apps/wei/forms/registration.py:67 +msgid "Team" +msgstr "Équipe" + +#: apps/wei/forms/registration.py:69 msgid "" -"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " -"hyphens." +"Leave this field empty if you won't be in a team (staff, bus chief, free " +"electron)" msgstr "" +"Laissez ce champ vide si vous ne serez pas dans une équipe (staff, chef de " +"bus ou électron libre)" -#: env/lib/python3.11/site-packages/django/core/validators.py:279 -#: env/lib/python3.11/site-packages/django/core/validators.py:287 -#: env/lib/python3.11/site-packages/django/core/validators.py:316 -msgid "Enter a valid IPv4 address." +#: apps/wei/forms/registration.py:75 apps/wei/forms/registration.py:85 +#: apps/wei/models.py:161 +msgid "WEI Roles" +msgstr "Rôles au WEI" + +#: apps/wei/forms/registration.py:76 +msgid "Select the roles that you are interested in." +msgstr "Sélectionnez les rôles qui vous intéressent." + +#: apps/wei/forms/registration.py:122 +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:35 +msgid "Choose a word:" +msgstr "Choisissez un mot :" + +#: apps/wei/models.py:25 apps/wei/templates/wei/base.html:36 +msgid "year" +msgstr "année" + +#: apps/wei/models.py:29 apps/wei/templates/wei/base.html:30 +msgid "date start" +msgstr "début" + +#: apps/wei/models.py:33 apps/wei/templates/wei/base.html:33 +msgid "date end" +msgstr "fin" + +#: apps/wei/models.py:71 apps/wei/tables.py:305 +msgid "seat count in the bus" +msgstr "nombre de sièges dans le bus" + +#: apps/wei/models.py:83 +msgid "survey information" +msgstr "informations sur le questionnaire" + +#: apps/wei/models.py:84 +msgid "Information about the survey for new members, encoded in JSON" msgstr "" +"Informations sur le sondage pour les nouveaux membres, encodées en JSON" -#: env/lib/python3.11/site-packages/django/core/validators.py:296 -#: env/lib/python3.11/site-packages/django/core/validators.py:317 -msgid "Enter a valid IPv6 address." +#: apps/wei/models.py:113 +msgid "Bus" +msgstr "Bus" + +#: apps/wei/models.py:114 apps/wei/templates/wei/weiclub_detail.html:51 +msgid "Buses" +msgstr "Bus" + +#: apps/wei/models.py:135 +msgid "color" +msgstr "couleur" + +#: apps/wei/models.py:136 +msgid "The color of the T-Shirt, stored with its number equivalent" msgstr "" +"La couleur du T-Shirt, stocké sous la forme de son équivalent numérique" -#: env/lib/python3.11/site-packages/django/core/validators.py:308 -#: env/lib/python3.11/site-packages/django/core/validators.py:315 -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "" +#: apps/wei/models.py:150 +msgid "Bus team" +msgstr "Équipe de bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:351 -msgid "Enter only digits separated by commas." -msgstr "" +#: apps/wei/models.py:151 +msgid "Bus teams" +msgstr "Équipes de bus" -#: env/lib/python3.11/site-packages/django/core/validators.py:357 -#, python-format -msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "" +#: apps/wei/models.py:160 +msgid "WEI Role" +msgstr "Rôle au WEI" -#: env/lib/python3.11/site-packages/django/core/validators.py:392 -#, python-format -msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:185 +msgid "Credit from Société générale" +msgstr "Crédit de la Société générale" -#: env/lib/python3.11/site-packages/django/core/validators.py:401 -#, python-format -msgid "Ensure this value is greater than or equal to %(limit_value)s." -msgstr "" +#: apps/wei/models.py:190 +msgid "Caution check given" +msgstr "Chèque de caution donné" -#: env/lib/python3.11/site-packages/django/core/validators.py:410 -#, python-format -msgid "Ensure this value is a multiple of step size %(limit_value)s." -msgstr "" +#: apps/wei/models.py:194 apps/wei/templates/wei/weimembership_form.html:64 +msgid "birth date" +msgstr "date de naissance" -#: env/lib/python3.11/site-packages/django/core/validators.py:420 -#, python-format +#: apps/wei/models.py:200 apps/wei/models.py:210 +msgid "Male" +msgstr "Homme" + +#: apps/wei/models.py:201 apps/wei/models.py:211 +msgid "Female" +msgstr "Femme" + +#: apps/wei/models.py:202 +msgid "Non binary" +msgstr "Non-binaire" + +#: apps/wei/models.py:204 apps/wei/templates/wei/attribute_bus_1A.html:22 +#: apps/wei/templates/wei/weimembership_form.html:55 +msgid "gender" +msgstr "genre" + +#: apps/wei/models.py:213 apps/wei/templates/wei/weimembership_form.html:58 +msgid "clothing cut" +msgstr "coupe de vêtement" + +#: apps/wei/models.py:226 apps/wei/templates/wei/weimembership_form.html:61 +msgid "clothing size" +msgstr "taille de vêtement" + +#: apps/wei/models.py:232 apps/wei/templates/wei/attribute_bus_1A.html:28 +#: apps/wei/templates/wei/weimembership_form.html:67 +msgid "health issues" +msgstr "problèmes de santé" + +#: apps/wei/models.py:237 apps/wei/templates/wei/weimembership_form.html:70 +msgid "emergency contact name" +msgstr "nom du contact en cas d'urgence" + +#: apps/wei/models.py:242 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:247 apps/wei/templates/wei/weimembership_form.html:52 +msgid "first year" +msgstr "première année" + +#: apps/wei/models.py:248 +msgid "Tells if the user is new in the school." +msgstr "Indique si l'utilisateur est nouveau dans l'école." + +#: apps/wei/models.py:253 +msgid "registration information" +msgstr "informations sur l'inscription" + +#: apps/wei/models.py:254 msgid "" -"Ensure this value has at least %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at least %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:438 -#, python-format -msgid "" -"Ensure this value has at most %(limit_value)d character (it has " -"%(show_value)d)." -msgid_plural "" -"Ensure this value has at most %(limit_value)d characters (it has " -"%(show_value)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:461 -#: env/lib/python3.11/site-packages/django/forms/fields.py:347 -#: env/lib/python3.11/site-packages/django/forms/fields.py:386 -msgid "Enter a number." -msgstr "Entrez un numéro de téléphone" - -#: env/lib/python3.11/site-packages/django/core/validators.py:463 -#, python-format -msgid "Ensure that there are no more than %(max)s digit in total." -msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:468 -#, python-format -msgid "Ensure that there are no more than %(max)s decimal place." -msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:473 -#, python-format -msgid "" -"Ensure that there are no more than %(max)s digit before the decimal point." -msgid_plural "" -"Ensure that there are no more than %(max)s digits before the decimal point." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:544 -#, python-format -msgid "" -"File extension “%(extension)s” is not allowed. Allowed extensions are: " -"%(allowed_extensions)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/core/validators.py:605 -msgid "Null characters are not allowed." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1423 -#: env/lib/python3.11/site-packages/django/forms/models.py:893 -msgid "and" -msgstr "ajouter" - -#: env/lib/python3.11/site-packages/django/db/models/base.py:1425 -#, python-format -msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "" -"Un modèle (%(model_name)s) de transaction avec un nom similaire " -"(%(field_labels)s) existe déjà" - -#: env/lib/python3.11/site-packages/django/db/models/constraints.py:17 -#, python-format -msgid "Constraint “%(name)s” is violated." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:128 -#, python-format -msgid "Value %(value)r is not a valid choice." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:129 -msgid "This field cannot be null." -msgstr "Ce champs ne peut pas être chargée." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:130 -msgid "This field cannot be blank." -msgstr "Ce champs ne peut pas etre vide." - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:131 -#, python-format -msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "" -"Un modèle de transaction (%(model_name)s) avec un nom similaire " -"(%(field_label)s) existe déjà" - -#. Translators: The 'lookup_type' is one of 'date', 'year' or -#. 'month'. Eg: "Title must be unique for pub_date year" -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:135 -#, python-format -msgid "" -"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:173 -#, python-format -msgid "Field of type: %(field_type)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1094 -#, python-format -msgid "“%(value)s” value must be either True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1095 -#, python-format -msgid "“%(value)s” value must be either True, False, or None." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1097 -msgid "Boolean (Either True or False)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1147 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1149 -msgid "String (unlimited)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1253 -msgid "Comma-separated integers" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1354 -#, python-format -msgid "" -"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1358 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1493 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " -"date." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1362 -msgid "Date (without time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1489 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." -"uuuuuu]][TZ] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1497 -#, python-format -msgid "" -"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" -"[TZ]) but it is an invalid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1502 -msgid "Date (with time)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1626 -#, python-format -msgid "“%(value)s” value must be a decimal number." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1628 -msgid "Decimal number" -msgstr "Nombre décimal" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1789 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." -"uuuuuu] format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1793 -msgid "Duration" -msgstr "Durée" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1845 -msgid "Email address" -msgstr "Adresse Mail" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1870 -msgid "File path" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1948 -#, python-format -msgid "“%(value)s” value must be a float." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1950 -msgid "Floating point number" -msgstr "Nombre à virgule flottante" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1990 -#, python-format -msgid "“%(value)s” value must be an integer." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1992 -msgid "Integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2088 -msgid "Big (8 byte) integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2105 -msgid "Small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2113 -msgid "IPv4 address" -msgstr "Adresse IPv4" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2144 -msgid "IP address" -msgstr "Adresse IP" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2237 -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2238 -#, python-format -msgid "“%(value)s” value must be either None, True or False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2240 -msgid "Boolean (Either True, False or None)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2291 -msgid "Positive big integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2306 -msgid "Positive integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2321 -msgid "Positive small integer" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2337 -#, python-format -msgid "Slug (up to %(max_length)s)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2373 -msgid "Text" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2448 -#, python-format -msgid "" -"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " -"format." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2452 -#, python-format -msgid "" -"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " -"invalid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2456 -msgid "Time" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2564 -msgid "URL" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2588 -msgid "Raw binary data" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2653 -#, python-format -msgid "“%(value)s” is not a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2655 -msgid "Universally unique identifier" -msgstr "Numéro de facture" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:232 -msgid "File" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/files.py:393 -msgid "Image" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:26 -msgid "A JSON object" -msgstr "Objet JSON" - -#: env/lib/python3.11/site-packages/django/db/models/fields/json.py:28 -msgid "Value must be valid JSON." -msgstr "Cette adresse doit être valide." - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:919 -#, python-format -msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:921 -msgid "Foreign Key (type determined by related field)" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1212 -msgid "One-to-one relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1269 -#, python-format -msgid "%(from)s-%(to)s relationship" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1271 -#, python-format -msgid "%(from)s-%(to)s relationships" -msgstr "" - -#: env/lib/python3.11/site-packages/django/db/models/fields/related.py:1319 -msgid "Many-to-many relationship" -msgstr "" - -#. Translators: If found as last label character, these punctuation -#. characters will prevent the default label_suffix to be appended to the label -#: env/lib/python3.11/site-packages/django/forms/boundfield.py:184 -msgid ":?.!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:298 -msgid "Enter a whole number." -msgstr "Entrez un nombre entier" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:467 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1241 -msgid "Enter a valid date." -msgstr "Entrez une date valide." - -#: env/lib/python3.11/site-packages/django/forms/fields.py:490 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1242 -msgid "Enter a valid time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:517 -msgid "Enter a valid date/time." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:551 -msgid "Enter a valid duration." -msgstr "Entrez une durée valide." - -#: env/lib/python3.11/site-packages/django/forms/fields.py:552 -#, python-brace-format -msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:621 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:622 -msgid "No file was submitted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:623 -msgid "The submitted file is empty." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:625 -#, python-format -msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." -msgid_plural "" -"Ensure this filename has at most %(max)d characters (it has %(length)d)." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:630 -msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:694 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:857 -#: env/lib/python3.11/site-packages/django/forms/fields.py:949 -#: env/lib/python3.11/site-packages/django/forms/models.py:1566 -#, python-format -msgid "Select a valid choice. %(value)s is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:951 -#: env/lib/python3.11/site-packages/django/forms/fields.py:1070 -#: env/lib/python3.11/site-packages/django/forms/models.py:1564 -msgid "Enter a list of values." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1071 -msgid "Enter a complete value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1310 -msgid "Enter a valid UUID." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/fields.py:1340 -msgid "Enter a valid JSON." -msgstr "" - -#. Translators: This is the default suffix added to form field labels -#: env/lib/python3.11/site-packages/django/forms/forms.py:98 -msgid ":" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/forms.py:244 -#: env/lib/python3.11/site-packages/django/forms/forms.py:328 -#, python-format -msgid "(Hidden field %(name)s) %(error)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:63 -#, python-format -msgid "" -"ManagementForm data is missing or has been tampered with. Missing fields: " -"%(field_names)s. You may need to file a bug report if the issue persists." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:67 -#, python-format -msgid "Please submit at most %(num)d form." -msgid_plural "Please submit at most %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:72 -#, python-format -msgid "Please submit at least %(num)d form." -msgid_plural "Please submit at least %(num)d forms." -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/forms/formsets.py:484 -#: env/lib/python3.11/site-packages/django/forms/formsets.py:491 -msgid "Order" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:886 -#, python-format -msgid "Please correct the duplicate data for %(field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:891 -#, python-format -msgid "Please correct the duplicate data for %(field)s, which must be unique." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:898 -#, python-format -msgid "" -"Please correct the duplicate data for %(field_name)s which must be unique " -"for the %(lookup)s in %(date_field)s." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:907 -msgid "Please correct the duplicate values below." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1338 -msgid "The inline value did not match the parent instance." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1429 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/models.py:1568 -#, python-format -msgid "“%(pk)s” is not a valid value." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/utils.py:226 -#, python-format -msgid "" -"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " -"may be ambiguous or it may not exist." -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:463 -msgid "Clear" -msgstr "" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:464 -msgid "Currently" -msgstr "Activité en cours" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:465 -msgid "Change" -msgstr "Modifier" - -#: env/lib/python3.11/site-packages/django/forms/widgets.py:794 -msgid "Unknown" -msgstr "" - -#. Translators: Please do not add spaces around commas. -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:861 -msgid "yes,no,maybe" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:891 -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:908 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:910 -#, python-format -msgid "%s KB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:912 -#, python-format -msgid "%s MB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:914 -#, python-format -msgid "%s GB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:916 -#, python-format -msgid "%s TB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/template/defaultfilters.py:918 -#, python-format -msgid "%s PB" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:73 -msgid "p.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:74 -msgid "a.m." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:79 -msgid "PM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:80 -msgid "AM" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:152 -msgid "midnight" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dateformat.py:154 -msgid "noon" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:7 -msgid "Monday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:8 -msgid "Tuesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:9 -msgid "Wednesday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:10 -msgid "Thursday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:11 -msgid "Friday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:12 -msgid "Saturday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:13 -msgid "Sunday" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:16 -msgid "Mon" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:17 -msgid "Tue" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:18 -msgid "Wed" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:19 -msgid "Thu" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:20 -msgid "Fri" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:21 -msgid "Sat" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:22 -msgid "Sun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:25 -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:26 -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:27 -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:28 -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:29 -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:30 -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:31 -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:32 -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:33 -msgid "September" -msgstr "Septembre" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:34 -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:35 -msgid "November" -msgstr "Novembre" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:36 -msgid "December" -msgstr "Décembre" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:39 -msgid "jan" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:40 -msgid "feb" -msgstr "feb" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:41 -msgid "mar" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:42 -msgid "apr" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:43 -msgid "may" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:44 -msgid "jun" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:45 -msgid "jul" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:46 -msgid "aug" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:47 -msgid "sep" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:48 -msgid "oct" -msgstr "oct" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:49 -msgid "nov" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:50 -msgid "dec" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:53 -msgctxt "abbrev. month" -msgid "Jan." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:54 -msgctxt "abbrev. month" -msgid "Feb." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:55 -msgctxt "abbrev. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:56 -msgctxt "abbrev. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:57 -msgctxt "abbrev. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:58 -msgctxt "abbrev. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:59 -msgctxt "abbrev. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:60 -msgctxt "abbrev. month" -msgid "Aug." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:61 -msgctxt "abbrev. month" -msgid "Sept." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:62 -msgctxt "abbrev. month" -msgid "Oct." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:63 -msgctxt "abbrev. month" -msgid "Nov." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:64 -msgctxt "abbrev. month" -msgid "Dec." -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:67 -msgctxt "alt. month" -msgid "January" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:68 -msgctxt "alt. month" -msgid "February" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:69 -msgctxt "alt. month" -msgid "March" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:70 -msgctxt "alt. month" -msgid "April" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:71 -msgctxt "alt. month" -msgid "May" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:72 -msgctxt "alt. month" -msgid "June" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:73 -msgctxt "alt. month" -msgid "July" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:74 -msgctxt "alt. month" -msgid "August" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:75 -msgctxt "alt. month" -msgid "September" -msgstr "Septembre" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:76 -msgctxt "alt. month" -msgid "October" -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:77 -msgctxt "alt. month" -msgid "November" -msgstr "Novembre" - -#: env/lib/python3.11/site-packages/django/utils/dates.py:78 -msgctxt "alt. month" -msgid "December" -msgstr "Décembre" - -#: env/lib/python3.11/site-packages/django/utils/ipv6.py:8 -msgid "This is not a valid IPv6 address." -msgstr "Cette activité n'est pas encore validée." - -#: env/lib/python3.11/site-packages/django/utils/text.py:84 -#, python-format -msgctxt "String to return when truncating text" -msgid "%(truncated_text)s…" +"Information about the registration (buses for old members, survey for the " +"new members), encoded in JSON" msgstr "" +"Informations sur l'inscription (bus pour les 2A+, questionnaire pour les " +"1A), encodées en JSON" -#: env/lib/python3.11/site-packages/django/utils/text.py:269 -msgid "or" -msgstr "" - -#. Translators: This string is used as a separator between list elements -#: env/lib/python3.11/site-packages/django/utils/text.py:288 -#: env/lib/python3.11/site-packages/django/utils/timesince.py:135 -msgid ", " -msgstr "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:8 -#, python-format -msgid "%(num)d year" -msgid_plural "%(num)d years" -msgstr[0] "" -msgstr[1] "" +#: apps/wei/models.py:312 +msgid "WEI User" +msgstr "Participant au WEI" -#: env/lib/python3.11/site-packages/django/utils/timesince.py:9 -#, python-format -msgid "%(num)d month" -msgid_plural "%(num)d months" -msgstr[0] "" -msgstr[1] "" +#: apps/wei/models.py:313 +msgid "WEI Users" +msgstr "Participants au WEI" -#: env/lib/python3.11/site-packages/django/utils/timesince.py:10 -#, python-format -msgid "%(num)d week" -msgid_plural "%(num)d weeks" -msgstr[0] "" -msgstr[1] "" +#: apps/wei/models.py:333 +msgid "team" +msgstr "équipe" -#: env/lib/python3.11/site-packages/django/utils/timesince.py:11 -#, python-format -msgid "%(num)d day" -msgid_plural "%(num)d days" -msgstr[0] "" -msgstr[1] "" +#: apps/wei/models.py:343 +msgid "WEI registration" +msgstr "Inscription au WEI" -#: env/lib/python3.11/site-packages/django/utils/timesince.py:12 -#, python-format -msgid "%(num)d hour" -msgid_plural "%(num)d hours" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/utils/timesince.py:13 -#, python-format -msgid "%(num)d minute" -msgid_plural "%(num)d minutes" -msgstr[0] "" -msgstr[1] "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:111 -msgid "Forbidden" -msgstr "" +#: apps/wei/models.py:347 +msgid "WEI membership" +msgstr "Adhésion au WEI" -#: env/lib/python3.11/site-packages/django/views/csrf.py:112 -msgid "CSRF verification failed. Request aborted." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:116 -msgid "" -"You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your web browser, but none was sent. This header is " -"required for security reasons, to ensure that your browser is not being " -"hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:122 -msgid "" -"If you have configured your browser to disable “Referer” headers, please re-" -"enable them, at least for this site, or for HTTPS connections, or for “same-" -"origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:127 -msgid "" -"If you are using the tag or " -"including the “Referrer-Policy: no-referrer” header, please remove them. The " -"CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:136 -msgid "" -"You are seeing this message because this site requires a CSRF cookie when " -"submitting forms. This cookie is required for security reasons, to ensure " -"that your browser is not being hijacked by third parties." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:142 -msgid "" -"If you have configured your browser to disable cookies, please re-enable " -"them, at least for this site, or for “same-origin” requests." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/csrf.py:148 -msgid "More information is available with DEBUG=True." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:44 -msgid "No year specified" -msgstr "Pas de motif spécifié" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:64 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:115 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:214 -msgid "Date out of range" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:94 -msgid "No month specified" -msgstr "Pas de motif spécifié" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:147 -msgid "No day specified" -msgstr "Pas de motif spécifié" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:194 -msgid "No week specified" -msgstr "Pas de motif spécifié" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:349 -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:380 -#, python-format -msgid "No %(verbose_name_plural)s available" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:652 -#, python-format -msgid "" -"Future %(verbose_name_plural)s not available because %(class_name)s." -"allow_future is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/dates.py:692 -#, python-format -msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/detail.py:56 -#, python-format -msgid "No %(verbose_name)s found matching the query" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:70 -msgid "Page is not “last”, nor can it be converted to an int." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:77 -#, python-format -msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/generic/list.py:169 -#, python-format -msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:38 -msgid "Directory indexes are not allowed here." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:40 -#, python-format -msgid "“%(path)s” does not exist" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/static.py:79 -#, python-format -msgid "Index of %(directory)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:7 -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:220 -msgid "The install worked successfully! Congratulations!" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:206 -#, python-format -msgid "" -"View release notes for Django %(version)s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:221 -#, python-format -msgid "" -"You are seeing this page because DEBUG=True is in your settings file and you have not " -"configured any URLs." -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:229 -msgid "Django Documentation" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:230 -msgid "Topics, references, & how-to’s" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:238 -msgid "Tutorial: A Polling App" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:239 -msgid "Get started with Django" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:247 -msgid "Django Community" -msgstr "" - -#: env/lib/python3.11/site-packages/django/views/templates/default_urlconf.html:248 -msgid "Connect, get help, or contribute" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:69 -msgid "Confidential" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:70 -msgid "Public" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:79 -msgid "Authorization code" -msgstr "Autorisation" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:80 -msgid "Implicit" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:81 -msgid "Resource owner password-based" -msgstr "Réinitialiser mon mot de passe" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:82 -msgid "Client credentials" -msgstr "Secret client" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:83 -msgid "OpenID connect hybrid" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:90 -msgid "No OIDC support" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:91 -msgid "RSA with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:92 -msgid "HMAC with SHA-2 256" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:107 -msgid "Allowed URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:111 -msgid "Allowed Post Logout URIs list, space separated" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:120 -msgid "Hashed on Save. Copy it now if this is a new secret." -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:190 -#, python-brace-format -msgid "Unauthorized redirect scheme: {scheme}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:194 -#, python-brace-format -msgid "redirect_uris cannot be empty with grant_type {grant_type}" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:200 -msgid "You must set OIDC_RSA_PRIVATE_KEY to use RSA algorithm" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/models.py:209 -msgid "You cannot use HS256 with public grants or clients" -msgstr "" - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:211 -msgid "The access token is invalid." -msgstr "Cette adresse doit être valide." - -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:218 -msgid "The access token has expired." -msgstr "" +#: apps/wei/models.py:348 +msgid "WEI memberships" +msgstr "Adhésions au WEI" -#: env/lib/python3.11/site-packages/oauth2_provider/oauth2_validators.py:225 -msgid "The access token is valid but does not have enough scope." +#: apps/wei/tables.py:105 +msgid "The user does not have enough money." msgstr "L'utilisateur n'a pas assez d'argent." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:6 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 -msgid "Are you sure to delete the application" -msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_confirm_delete.html:12 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:29 -#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 -#: note_kfet/templates/oauth2_provider/authorize.html:28 -msgid "Cancel" -msgstr "Annuler" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:10 -#: note_kfet/templates/oauth2_provider/application_detail.html:11 -msgid "Client id" -msgstr "ID client" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:15 -#: note_kfet/templates/oauth2_provider/application_detail.html:14 -msgid "Client secret" -msgstr "Secret client" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:20 -#: note_kfet/templates/oauth2_provider/application_detail.html:17 -msgid "Client type" -msgstr "Type de client" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:25 -#: note_kfet/templates/oauth2_provider/application_detail.html:20 -msgid "Authorization Grant Type" -msgstr "Type d'autorisation" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:30 -#: note_kfet/templates/oauth2_provider/application_detail.html:23 -msgid "Redirect Uris" -msgstr "URIs de redirection" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_detail.html:36 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:35 -#: note_kfet/templates/oauth2_provider/application_detail.html:37 -#: note_kfet/templates/oauth2_provider/application_form.html:23 -msgid "Go Back" -msgstr "Retour en arrière" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:9 -#: note_kfet/templates/oauth2_provider/application_form.html:12 -msgid "Edit application" -msgstr "Modifier l'application" - -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_form.html:37 -msgid "Save" +#: apps/wei/tables.py:108 +msgid "" +"The user is in first year. You may validate the credit, the algorithm will " +"run later." msgstr "" +"L'utilisateur est en première année, vous pouvez valider le crédit, " +"l'algorithme tournera plus tard." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:6 -#: note_kfet/templates/oauth2_provider/application_list.html:7 -msgid "Your applications" -msgstr "Vos applications" +#: apps/wei/tables.py:111 +msgid "The user has enough money, you can validate the registration." +msgstr "L'utilisateur a assez d'argent, l'inscription est possible." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_list.html:14 -#: note_kfet/templates/oauth2_provider/application_list.html:30 -msgid "New Application" -msgstr "Nouvelle application" +#: apps/wei/tables.py:143 +msgid "Year" +msgstr "Année" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/application_registration_form.html:5 -#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 -msgid "Register a new application" -msgstr "Enregistrer une nouvelle application" +#: apps/wei/tables.py:180 apps/wei/templates/wei/weimembership_form.html:102 +msgid "preferred bus" +msgstr "bus préféré" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:8 -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:30 -#: note_kfet/templates/oauth2_provider/authorize.html:9 -#: note_kfet/templates/oauth2_provider/authorize.html:29 -msgid "Authorize" -msgstr "Autoriser" +#: apps/wei/tables.py:210 apps/wei/templates/wei/bus_detail.html:32 +#: apps/wei/templates/wei/busteam_detail.html:50 +msgid "Teams" +msgstr "Équipes" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorize.html:17 -msgid "Application requires the following permissions" -msgstr "L'application requiert les permissions suivantes" +#: apps/wei/tables.py:219 apps/wei/tables.py:260 +msgid "Members count" +msgstr "Nombre de membres" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-token-delete.html:6 -#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 -msgid "Are you sure you want to delete this token?" -msgstr "Êtes-vous sûr⋅e de vouloir supprimer ce jeton ?" +#: apps/wei/tables.py:226 apps/wei/tables.py:257 +msgid "members" +msgstr "adhérents" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:6 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 -msgid "Tokens" -msgstr "Jetons" +#: apps/wei/tables.py:287 +msgid "suggested first year" +msgstr "1A suggérés" -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:11 -msgid "revoke" +#: apps/wei/tables.py:293 +msgid "validated first year" +msgstr "1A validés" + +#: apps/wei/tables.py:299 +msgid "validated staff" +msgstr "2A+ validés" + +#: apps/wei/tables.py:310 +msgid "free seats" +msgstr "sièges libres" + +#: apps/wei/templates/wei/1A_list.html:9 +msgid "Attribute first year members into buses" +msgstr "Attribuer les 1A dans les bus" + +#: apps/wei/templates/wei/1A_list.html:15 +msgid "Start attribution!" +msgstr "Démarrer l'attribution !" + +#: apps/wei/templates/wei/attribute_bus_1A.html:8 +msgid "Bus attribution" +msgstr "Répartition des bus" + +#: apps/wei/templates/wei/attribute_bus_1A.html:31 +msgid "suggested bus" +msgstr "bus suggéré" + +#: apps/wei/templates/wei/attribute_bus_1A.html:37 +msgid "View raw survey information" +msgstr "Voir les informations brutes du sondage" + +#: apps/wei/templates/wei/attribute_bus_1A.html:57 +msgid "Back to main list" +msgstr "Retour à la liste principale" + +#: apps/wei/templates/wei/base.html:44 +msgid "WEI fee (paid students)" +msgstr "Prix du WEI (élèves)" + +#: apps/wei/templates/wei/base.html:47 apps/wei/templates/wei/base.html:54 +msgid "The BDE membership is included in the WEI registration." +msgstr "L'adhésion au BDE est offerte avec l'inscription au WEI." + +#: apps/wei/templates/wei/base.html:51 +msgid "WEI fee (unpaid students)" +msgstr "Prix du WEI (étudiants)" + +#: apps/wei/templates/wei/base.html:76 +msgid "WEI list" +msgstr "Liste des WEI" + +#: apps/wei/templates/wei/base.html:81 apps/wei/views.py:528 +msgid "Register 1A" +msgstr "Inscrire un 1A" + +#: apps/wei/templates/wei/base.html:85 apps/wei/views.py:614 +msgid "Register 2A+" +msgstr "Inscrire un 2A+" + +#: apps/wei/templates/wei/base.html:93 +msgid "Add bus" +msgstr "Ajouter un bus" + +#: apps/wei/templates/wei/base.html:97 +msgid "View WEI" +msgstr "Voir le WEI" + +#: apps/wei/templates/wei/bus_detail.html:22 +#: apps/wei/templates/wei/busteam_detail.html:22 +msgid "Add team" +msgstr "Ajouter une équipe" + +#: apps/wei/templates/wei/bus_detail.html:45 +msgid "Members" +msgstr "Membres" + +#: apps/wei/templates/wei/bus_detail.html:54 +#: apps/wei/templates/wei/busteam_detail.html:60 +#: apps/wei/templates/wei/weimembership_list.html:31 +msgid "View as PDF" +msgstr "Télécharger au format PDF" + +#: apps/wei/templates/wei/survey.html:11 +#: apps/wei/templates/wei/survey_closed.html:11 +#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1028 +#: apps/wei/views.py:1083 apps/wei/views.py:1093 +msgid "Survey WEI" +msgstr "Questionnaire WEI" + +#: apps/wei/templates/wei/survey.html:23 +msgid "Next" +msgstr "Suivant" + +#: apps/wei/templates/wei/survey_closed.html:15 +msgid "The inscription for this WEI are now closed." +msgstr "Les inscriptions pour le WEI sont fermées." + +#: apps/wei/templates/wei/survey_closed.html:19 +msgid "Return to WEI detail" +msgstr "Retour aux détails du WEI" + +#: apps/wei/templates/wei/survey_end.html:15 +msgid "The survey is now ended. Your answers have been saved." msgstr "" +"Le sondage est désormais terminé, vos réponses ont bien été enregistrées." -#: env/lib/python3.11/site-packages/oauth2_provider/templates/oauth2_provider/authorized-tokens.html:19 -#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 -msgid "There are no authorized tokens yet." -msgstr "Il n'y a pas encore de jeton autorisé." +#: apps/wei/templates/wei/weiclub_detail.html:32 +msgid "Register to the WEI! – 1A" +msgstr "M'inscrire au WEI ! – 1A" -#: note_kfet/settings/base.py:173 +#: apps/wei/templates/wei/weiclub_detail.html:36 +msgid "Register to the WEI! – 2A+" +msgstr "M'inscrire au WEI ! – 2A+" + +#: apps/wei/templates/wei/weiclub_detail.html:40 +msgid "Update my registration" +msgstr "Modifier mon inscription" + +#: apps/wei/templates/wei/weiclub_detail.html:63 +msgid "Members of the WEI" +msgstr "Membres du WEI" + +#: apps/wei/templates/wei/weiclub_detail.html:89 +msgid "Unvalidated registrations" +msgstr "Inscriptions non validées" + +#: apps/wei/templates/wei/weiclub_detail.html:99 +msgid "Attribute buses" +msgstr "Répartition dans les bus" + +#: apps/wei/templates/wei/weiclub_list.html:14 apps/wei/views.py:79 +msgid "Create WEI" +msgstr "Créer un WEI" + +#: apps/wei/templates/wei/weiclub_list.html:22 +msgid "WEI listing" +msgstr "Liste des WEI" + +#: apps/wei/templates/wei/weimembership_form.html:10 +msgid "Review registration" +msgstr "Vérifier l'inscription" + +#: apps/wei/templates/wei/weimembership_form.html:35 +msgid "ENS year" +msgstr "Année à l'ENS" + +#: apps/wei/templates/wei/weimembership_form.html:76 +msgid "Payment from Société générale" +msgstr "Paiement de la Société générale" + +#: apps/wei/templates/wei/weimembership_form.html:80 +msgid "Suggested bus from the survey:" +msgstr "Bus suggéré par le sondage :" + +#: apps/wei/templates/wei/weimembership_form.html:85 +msgid "Raw survey information" +msgstr "Informations brutes du sondage" + +#: apps/wei/templates/wei/weimembership_form.html:95 +msgid "The algorithm didn't run." +msgstr "L'algorithme n'a pas été exécuté." + +#: apps/wei/templates/wei/weimembership_form.html:98 +msgid "caution check given" +msgstr "chèque de caution donné" + +#: apps/wei/templates/wei/weimembership_form.html:105 +msgid "preferred team" +msgstr "équipe préférée" + +#: apps/wei/templates/wei/weimembership_form.html:108 +msgid "preferred roles" +msgstr "rôles préférés" + +#: apps/wei/templates/wei/weimembership_form.html:115 +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:30 +msgid "Update registration" +msgstr "Modifier l'inscription" + +#: apps/wei/templates/wei/weimembership_form.html:131 +msgid "The registration is already validated and can't be unvalidated." +msgstr "L'inscription a déjà été validée et ne peut pas être dévalidée." + +#: apps/wei/templates/wei/weimembership_form.html:132 +msgid "The user joined the bus" +msgstr "L'utilisateur a rejoint le bus" + +#: apps/wei/templates/wei/weimembership_form.html:133 +msgid "in the team" +msgstr "dans l'équipe" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "in no team (staff)" +msgstr "dans aucune équipe (staff)" + +#: apps/wei/templates/wei/weimembership_form.html:134 +msgid "with the following roles:" +msgstr "avec les rôles suivants :" + +#: apps/wei/templates/wei/weimembership_form.html:139 +msgid "" +"The WEI will be paid by Société générale. The membership will be created " +"even if the bank didn't pay the BDE yet. The membership transaction will be " +"created but will be invalid. You will have to validate it once the bank " +"validated the creation of the account, or to change the payment method." +msgstr "" +"Le WEI va être payé par la Société générale. L'adhésion sera créée même si " +"la banque n'a pas encore payé le BDE. La transaction d'adhésion sera créée " +"mais invalide. Vous devrez la valider une fois que la banque aura validé la " +"création du compte, ou bien changer de moyen de paiement." + +#: apps/wei/templates/wei/weimembership_form.html:149 +#, python-format +msgid "" +"The note don't have enough money (%(balance)s, %(pretty_fee)s required). The " +"registration may fail if you don't credit the note now." +msgstr "" +"La note n'a pas assez d'argent (%(balance)s, %(pretty_fee)s requis). " +"L'inscription peut échouer si vous ne rechargez pas la note dès maintenant." + +#: apps/wei/templates/wei/weimembership_form.html:157 +#, python-format +msgid "" +"The note has enough money (%(pretty_fee)s required), the registration is " +"possible." +msgstr "" +"La note a assez d'argent (%(pretty_fee)s requis), l'inscription est possible." + +#: apps/wei/templates/wei/weimembership_form.html:166 +msgid "The user didn't give her/his caution check." +msgstr "L'utilisateur n'a pas donné son chèque de caution." + +#: apps/wei/templates/wei/weimembership_form.html:174 +msgid "" +"This user is not a member of the Kfet club for the coming year. The " +"membership will be processed automatically, the WEI registration includes " +"the membership fee." +msgstr "" +"Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. " +"L'adhésion va être faite automatiquement, l'inscription au WEI inclut le " +"coût d'adhésion." + +#: apps/wei/templates/wei/weimembership_list.html:27 +msgid "View unvalidated registrations..." +msgstr "Voir les inscriptions non validées ..." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:16 +msgid "This registration is already validated and can't be deleted." +msgstr "L'inscription a déjà été validée et ne peut pas être supprimée." + +#: apps/wei/templates/wei/weiregistration_confirm_delete.html:23 +#, python-format +msgid "" +"Are you sure you want to delete the registration of %(user)s for the WEI " +"%(wei_name)s? This action can't be undone." +msgstr "" +"Êtes-vous sûr⋅e de vouloir supprimer l'inscription de %(user)s pour le WEI " +"%(wei_name)s ? Cette action ne pourra pas être annulée." + +#: apps/wei/templates/wei/weiregistration_list.html:19 +msgid "There is no pre-registration found with this pattern." +msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée." + +#: apps/wei/templates/wei/weiregistration_list.html:27 +msgid "View validated memberships..." +msgstr "Voir les adhésions validées ..." + +#: apps/wei/views.py:58 +msgid "Search WEI" +msgstr "Chercher un WEI" + +#: apps/wei/views.py:109 +msgid "WEI Detail" +msgstr "Détails du WEI" + +#: apps/wei/views.py:208 +msgid "View members of the WEI" +msgstr "Voir les membres du WEI" + +#: apps/wei/views.py:236 +msgid "Find WEI Membership" +msgstr "Trouver une adhésion au WEI" + +#: apps/wei/views.py:246 +msgid "View registrations to the WEI" +msgstr "Voir les inscriptions au WEI" + +#: apps/wei/views.py:270 +msgid "Find WEI Registration" +msgstr "Trouver une inscription au WEI" + +#: apps/wei/views.py:281 +msgid "Update the WEI" +msgstr "Modifier le WEI" + +#: apps/wei/views.py:302 +msgid "Create new bus" +msgstr "Ajouter un nouveau bus" + +#: apps/wei/views.py:340 +msgid "Update bus" +msgstr "Modifier le bus" + +#: apps/wei/views.py:372 +msgid "Manage bus" +msgstr "Gérer le bus" + +#: apps/wei/views.py:399 +msgid "Create new team" +msgstr "Créer une nouvelle équipe" + +#: apps/wei/views.py:439 +msgid "Update team" +msgstr "Modifier l'équipe" + +#: apps/wei/views.py:470 +msgid "Manage WEI team" +msgstr "Gérer l'équipe WEI" + +#: apps/wei/views.py:492 +msgid "Register first year student to the WEI" +msgstr "Inscrire un 1A au WEI" + +#: apps/wei/views.py:550 apps/wei/views.py:649 +msgid "This user is already registered to this WEI." +msgstr "Cette personne est déjà inscrite au WEI." + +#: apps/wei/views.py:555 +msgid "" +"This user can't be in her/his first year since he/she has already " +"participated to a WEI." +msgstr "" +"Cet utilisateur ne peut pas être en première année puisqu'il a déjà " +"participé à un WEI." + +#: apps/wei/views.py:578 +msgid "Register old student to the WEI" +msgstr "Inscrire un 2A+ au WEI" + +#: apps/wei/views.py:633 apps/wei/views.py:721 +msgid "You already opened an account in the Société générale." +msgstr "Vous avez déjà ouvert un compte auprès de la société générale." + +#: apps/wei/views.py:685 +msgid "Update WEI Registration" +msgstr "Modifier l'inscription WEI" + +#: apps/wei/views.py:795 +msgid "Delete WEI registration" +msgstr "Supprimer l'inscription WEI" + +#: apps/wei/views.py:806 +msgid "You don't have the right to delete this WEI registration." +msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI." + +#: apps/wei/views.py:824 +msgid "Validate WEI registration" +msgstr "Valider l'inscription WEI" + +#: apps/wei/views.py:1186 +msgid "Attribute buses to first year members" +msgstr "Répartir les 1A dans les bus" + +#: apps/wei/views.py:1211 +msgid "Attribute bus" +msgstr "Attribuer un bus" + +#: note_kfet/settings/base.py:172 msgid "German" msgstr "Allemand" -#: note_kfet/settings/base.py:174 +#: note_kfet/settings/base.py:173 msgid "English" msgstr "Anglais" -#: note_kfet/settings/base.py:175 +#: note_kfet/settings/base.py:174 msgid "Spanish" msgstr "Espagnol" -#: note_kfet/settings/base.py:176 +#: note_kfet/settings/base.py:175 msgid "French" msgstr "Français" @@ -3857,26 +3270,26 @@ msgstr "Utilisateurs" msgid "Clubs" msgstr "Clubs" -#: note_kfet/templates/base.html:107 +#: note_kfet/templates/base.html:113 msgid "Admin" msgstr "Admin" -#: note_kfet/templates/base.html:121 +#: note_kfet/templates/base.html:127 msgid "My account" msgstr "Mon compte" -#: note_kfet/templates/base.html:124 +#: note_kfet/templates/base.html:130 msgid "Log out" msgstr "Se déconnecter" -#: note_kfet/templates/base.html:132 +#: note_kfet/templates/base.html:138 #: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:28 msgid "Sign up" msgstr "Inscription" -#: note_kfet/templates/base.html:139 +#: note_kfet/templates/base.html:145 #: note_kfet/templates/registration/login.html:6 #: note_kfet/templates/registration/login.html:15 #: note_kfet/templates/registration/login.html:38 @@ -3884,7 +3297,15 @@ msgstr "Inscription" msgid "Log in" msgstr "Se connecter" -#: note_kfet/templates/base.html:153 +#: note_kfet/templates/base.html:159 +msgid "" +"You are not a BDE member anymore. Please renew your membership if you want " +"to use the note." +msgstr "" +"Vous n'êtes plus adhérent BDE. Merci de réadhérer si vous voulez profiter de " +"la note." + +#: note_kfet/templates/base.html:165 msgid "" "Your e-mail address is not validated. Please check your mail inbox and click " "on the validation link." @@ -3893,10 +3314,24 @@ msgstr "" "et de cliquer sur le lien de validation." #: note_kfet/templates/base.html:171 +msgid "" +"You declared that you opened a bank account in the Société générale. The " +"bank did not validate the creation of the account to the BDE, so the " +"membership and the WEI are not paid yet. This verification procedure may " +"last a few days. Please make sure that you go to the end of the account " +"creation." +msgstr "" +"Vous avez déclaré que vous avez ouvert un compte bancaire à la société " +"générale. La banque n'a pas encore validé la création du compte auprès du " +"BDE, l'adhésion et le WEI ne sont donc pas encore payés. Cette procédure de " +"vérification peut durer quelques jours. Merci de vous assurer de bien aller " +"au bout de vos démarches." + +#: note_kfet/templates/base.html:194 msgid "Contact us" msgstr "Nous contacter" -#: note_kfet/templates/base.html:173 +#: note_kfet/templates/base.html:196 msgid "Technical Support" msgstr "Support technique" @@ -3908,6 +3343,35 @@ msgstr "Chercher par un attribut tel que le nom …" msgid "There is no results." msgstr "Il n'y a pas de résultat." +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:8 +msgid "Are you sure to delete the application" +msgstr "Êtes-vous sûr⋅e de vouloir supprimer l'application" + +#: note_kfet/templates/oauth2_provider/application_confirm_delete.html:17 +#: note_kfet/templates/oauth2_provider/authorize.html:28 +msgid "Cancel" +msgstr "Annuler" + +#: note_kfet/templates/oauth2_provider/application_detail.html:11 +msgid "Client id" +msgstr "ID client" + +#: note_kfet/templates/oauth2_provider/application_detail.html:14 +msgid "Client secret" +msgstr "Secret client" + +#: note_kfet/templates/oauth2_provider/application_detail.html:17 +msgid "Client type" +msgstr "Type de client" + +#: note_kfet/templates/oauth2_provider/application_detail.html:20 +msgid "Authorization Grant Type" +msgstr "Type d'autorisation" + +#: note_kfet/templates/oauth2_provider/application_detail.html:23 +msgid "Redirect Uris" +msgstr "URIs de redirection" + #: note_kfet/templates/oauth2_provider/application_detail.html:29 #, python-format msgid "" @@ -3920,6 +3384,19 @@ msgstr "" "de scopes avec les permissions que vous souhaitez attribuer à votre " "application." +#: note_kfet/templates/oauth2_provider/application_detail.html:37 +#: note_kfet/templates/oauth2_provider/application_form.html:23 +msgid "Go Back" +msgstr "Retour en arrière" + +#: note_kfet/templates/oauth2_provider/application_form.html:12 +msgid "Edit application" +msgstr "Modifier l'application" + +#: note_kfet/templates/oauth2_provider/application_list.html:7 +msgid "Your applications" +msgstr "Vos applications" + #: note_kfet/templates/oauth2_provider/application_list.html:11 msgid "" "You can find on this page the list of the applications that you already " @@ -3928,10 +3405,23 @@ msgstr "" "Vous pouvez trouver sur cette page la liste des applications que vous avez " "déjà enregistrées." +#: note_kfet/templates/oauth2_provider/application_list.html:30 +msgid "New Application" +msgstr "Nouvelle application" + #: note_kfet/templates/oauth2_provider/application_list.html:31 msgid "Authorized Tokens" msgstr "Jetons autorisés" +#: note_kfet/templates/oauth2_provider/application_registration_form.html:5 +msgid "Register a new application" +msgstr "Enregistrer une nouvelle application" + +#: note_kfet/templates/oauth2_provider/authorize.html:9 +#: note_kfet/templates/oauth2_provider/authorize.html:29 +msgid "Authorize" +msgstr "Autoriser" + #: note_kfet/templates/oauth2_provider/authorize.html:14 msgid "Application requires following permissions:" msgstr "L'application requiert les permissions suivantes :" @@ -3949,6 +3439,18 @@ msgstr "Succès" msgid "Please return to your application and enter this code:" msgstr "Merci de retourner à votre application et entrez ce code :" +#: note_kfet/templates/oauth2_provider/authorized-token-delete.html:9 +msgid "Are you sure you want to delete this token?" +msgstr "Êtes-vous sûr⋅e de vouloir supprimer ce jeton ?" + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:7 +msgid "Tokens" +msgstr "Jetons" + +#: note_kfet/templates/oauth2_provider/authorized-tokens.html:22 +msgid "There are no authorized tokens yet." +msgstr "Il n'y a pas encore de jeton autorisé." + #: note_kfet/templates/registration/logged_out.html:13 msgid "Thanks for spending some quality time with the Web site today." msgstr "Merci d'avoir utilisé la Note Kfet." @@ -4051,645 +3553,12 @@ msgstr "Réinitialiser mon mot de passe" #: note_kfet/templates/registration/signup.html:15 msgid "" "If you already signed up, your registration is taken into account. The BDE " -"must validate your account before your can log in. You have to pay the " -"registration fee. You must also validate your email address by following the " -"link you received." +"must validate your account before your can log in. You have to go to the " +"Kfet and pay the registration fee. You must also validate your email address " +"by following the link you received." msgstr "" "Si vous vous êtes déjà inscrits, votre inscription a bien été prise en " -"compte. Un bureau doit d'abord valider votre compte avant que vous puissiez " -"vous connecter. Vous devez payer les frais d'adhésion. Vous devez également " -"valider votre adresse email en suivant le lien que vous avez reçu." - -#~ msgid "Inscription paid by Société Générale" -#~ msgstr "Inscription payée par la Société générale" - -#~ 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." - -#~ msgid "Bank" -#~ msgstr "Banque" - -#~ msgid "Physics (A2)" -#~ msgstr "Physique (A2)" - -#~ msgid "Applied physics (A'2)" -#~ msgstr "Physique appliquée (A'2)" - -#~ msgid "Chemistry (A''2)" -#~ msgstr "Chimie (A''2)" - -#~ msgid "Biology (A3)" -#~ msgstr "Biologie (A3)" - -#~ msgid "SAPHIRE (B1234)" -#~ msgstr "SAPHIRE (B1234)" - -#~ msgid "Mechanics (B1)" -#~ msgstr "Mécanique (B1)" - -#~ msgid "Civil engineering (B2)" -#~ msgstr "Génie civil (B2)" - -#~ msgid "Mechanical engineering (B3)" -#~ msgstr "Génie mécanique (B3)" - -#~ msgid "EEA (B4)" -#~ msgstr "EEA (B4)" - -#~ msgid "Design (C)" -#~ msgstr "Design (C)" - -#~ msgid "Social sciences (D3)" -#~ msgstr "Sciences sociales (D3)" - -#~ msgid "English (E)" -#~ msgstr "Anglais (E)" - -#~ msgid "External (EXT)" -#~ msgstr "Externe (EXT)" - -#~ msgid "Yes (receive them in french)" -#~ msgstr "Oui (les recevoir en français)" - -#~ msgid "Yes (receive them in english)" -#~ msgstr "Oui (les recevoir en anglais)" - -#, python-format -#~ msgid "" -#~ "The user is not a member of the club·s %(clubs)s. An additional fee of " -#~ "%(pretty_fee)s will be charged to renew automatically the membership in " -#~ "this/these club·s." -#~ msgstr "" -#~ "Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Un " -#~ "montant supplémentaire de %(pretty_fee)s sera débité afin de renouveler " -#~ "automatiquement l'adhésion dans ce·s club·s." - -#, python-format -#~ msgid "" -#~ "This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will " -#~ "be charged to adhere automatically to this/these club·s." -#~ msgstr "" -#~ "Ce club a pour parent·s %(clubs)s. Un coût supplémentaire de " -#~ "%(pretty_fee)s peut être ajouté pour adhérer automatiquement à ce·s " -#~ "club·s." - -#~ msgid "bank" -#~ msgstr "banque" - -#~ msgid "Superusers have all rights on everything, to manage the website." -#~ msgstr "" -#~ "Les super-utilisateurs ont tous les droits sur tout, afin de gérer le " -#~ "site." - -#~ msgid "Superusers" -#~ msgstr "Super-utilisateurs" - -#~ msgid "" -#~ "I declare that I opened or I will open soon a bank account in the Société " -#~ "générale with the BDE partnership." -#~ msgstr "" -#~ "Je déclare avoir ouvert ou ouvrir prochainement un compte à la société " -#~ "générale avec le partenariat du BDE." - -#~ msgid "" -#~ "Warning: this engages you to open your bank account. If you finally " -#~ "decides to don't open your account, you will have to pay the BDE " -#~ "membership." -#~ msgstr "" -#~ "Attention : cocher cette case vous engage à ouvrir votre compte. Si vous " -#~ "décidez de ne pas le faire, vous devrez payer l'adhésion au BDE." - -#~ msgid "Register to the WEI" -#~ msgstr "S'inscrire au WEI" - -#~ 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." -#~ msgstr "" -#~ "Cochez cette case si vous voulez vous inscrire au WEI. Si vous hésitez, " -#~ "vous pourrez toujours vous inscrire plus tard, après avoir validé votre " -#~ "compte à la Kfet." - -#~ msgid "Join Kfet Club" -#~ msgstr "Adhérer au club Kfet" - -#~ msgid "You must also go to the Kfet to pay your membership." -#~ msgstr "" -#~ "Vous devrez également vous rendre à la Kfet pour payer votre adhésion." - -#~ msgid "" -#~ "The user declared that he/she opened a bank account in the Société " -#~ "générale." -#~ msgstr "" -#~ "L'utilisateur a déclaré avoir ouvert un compte à la société générale." - -#~ msgid "You must join the BDE." -#~ msgstr "Vous devez adhérer au BDE." - -#~ msgid "credit transaction" -#~ msgstr "transaction de crédit" - -#~ msgid "" -#~ "This user doesn't have enough money to pay the memberships with its note. " -#~ "Please ask her/him to credit the note before invalidating this credit." -#~ msgstr "" -#~ "Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa " -#~ "note. Merci de lui demander de recharger sa note avant d'invalider ce " -#~ "crédit." - -#~ msgid "Credits from the Société générale" -#~ msgstr "Crédits de la Société générale" - -#, python-brace-format -#~ msgid "Soge credit for {user}" -#~ msgstr "Crédit de la société générale pour l'utilisateur {user}" - -#~ msgid "List of credits from the Société générale" -#~ msgstr "Liste des crédits de la Société générale" - -#~ msgid "Manage credits from the Société générale" -#~ msgstr "Gérer les crédits de la Société générale" - -#~ msgid "WEI" -#~ msgstr "WEI" - -#~ msgid "" -#~ "The selected user is not validated. Please validate its account first" -#~ msgstr "" -#~ "L'utilisateur sélectionné n'est pas validé. Merci de d'abord valider son " -#~ "compte" - -#~ msgid "bus" -#~ msgstr "bus" - -#~ msgid "" -#~ "This choice is not definitive. The WEI organizers are free to attribute " -#~ "for you a bus and a team, in particular if you are a free eletron." -#~ msgstr "" -#~ "Ce choix n'est pas définitif. Les organisateurs du WEI sont libres de " -#~ "vous attribuer un bus et une équipe, en particulier si vous êtes un " -#~ "électron libre." - -#~ msgid "Team" -#~ msgstr "Équipe" - -#~ msgid "" -#~ "Leave this field empty if you won't be in a team (staff, bus chief, free " -#~ "electron)" -#~ msgstr "" -#~ "Laissez ce champ vide si vous ne serez pas dans une équipe (staff, chef " -#~ "de bus ou électron libre)" - -#~ msgid "WEI Roles" -#~ msgstr "Rôles au WEI" - -#~ msgid "Select the roles that you are interested in." -#~ msgstr "Sélectionnez les rôles qui vous intéressent." - -#~ msgid "This team doesn't belong to the given bus." -#~ msgstr "Cette équipe n'appartient pas à ce bus." - -#~ msgid "Choose a word:" -#~ msgstr "Choisissez un mot :" - -#~ msgid "year" -#~ msgstr "année" - -#~ msgid "date start" -#~ msgstr "début" - -#~ msgid "date end" -#~ msgstr "fin" - -#~ msgid "seat count in the bus" -#~ msgstr "nombre de sièges dans le bus" - -#~ msgid "survey information" -#~ msgstr "informations sur le questionnaire" - -#~ msgid "Information about the survey for new members, encoded in JSON" -#~ msgstr "" -#~ "Informations sur le sondage pour les nouveaux membres, encodées en JSON" - -#~ msgid "Bus" -#~ msgstr "Bus" - -#~ msgid "Buses" -#~ msgstr "Bus" - -#~ msgid "color" -#~ msgstr "couleur" - -#~ msgid "The color of the T-Shirt, stored with its number equivalent" -#~ msgstr "" -#~ "La couleur du T-Shirt, stocké sous la forme de son équivalent numérique" - -#~ msgid "Bus team" -#~ msgstr "Équipe de bus" - -#~ msgid "Bus teams" -#~ msgstr "Équipes de bus" - -#~ msgid "WEI Role" -#~ msgstr "Rôle au WEI" - -#~ msgid "Credit from Société générale" -#~ msgstr "Crédit de la Société générale" - -#~ msgid "Caution check given" -#~ msgstr "Chèque de caution donné" - -#~ msgid "birth date" -#~ msgstr "date de naissance" - -#~ msgid "Male" -#~ msgstr "Homme" - -#~ msgid "Female" -#~ msgstr "Femme" - -#~ msgid "Non binary" -#~ msgstr "Non-binaire" - -#~ msgid "gender" -#~ msgstr "genre" - -#~ msgid "clothing cut" -#~ msgstr "coupe de vêtement" - -#~ msgid "clothing size" -#~ msgstr "taille de vêtement" - -#~ msgid "health issues" -#~ msgstr "problèmes de santé" - -#~ msgid "emergency contact name" -#~ msgstr "nom du contact en cas d'urgence" - -#~ msgid "emergency contact phone" -#~ msgstr "téléphone du contact en cas d'urgence" - -#~ msgid "first year" -#~ msgstr "première année" - -#~ msgid "Tells if the user is new in the school." -#~ msgstr "Indique si l'utilisateur est nouveau dans l'école." - -#~ msgid "registration information" -#~ msgstr "informations sur l'inscription" - -#~ msgid "" -#~ "Information about the registration (buses for old members, survey for the " -#~ "new members), encoded in JSON" -#~ msgstr "" -#~ "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les " -#~ "1A), encodées en JSON" - -#~ msgid "WEI User" -#~ msgstr "Participant au WEI" - -#~ msgid "WEI Users" -#~ msgstr "Participants au WEI" - -#~ msgid "team" -#~ msgstr "équipe" - -#~ msgid "WEI registration" -#~ msgstr "Inscription au WEI" - -#~ msgid "WEI membership" -#~ msgstr "Adhésion au WEI" - -#~ msgid "WEI memberships" -#~ msgstr "Adhésions au WEI" - -#~ msgid "" -#~ "The user is in first year. You may validate the credit, the algorithm " -#~ "will run later." -#~ msgstr "" -#~ "L'utilisateur est en première année, vous pouvez valider le crédit, " -#~ "l'algorithme tournera plus tard." - -#~ msgid "The user has enough money, you can validate the registration." -#~ msgstr "L'utilisateur a assez d'argent, l'inscription est possible." - -#~ msgid "Year" -#~ msgstr "Année" - -#~ msgid "preferred bus" -#~ msgstr "bus préféré" - -#~ msgid "Teams" -#~ msgstr "Équipes" - -#~ msgid "Members count" -#~ msgstr "Nombre de membres" - -#~ msgid "members" -#~ msgstr "adhérents" - -#~ msgid "suggested first year" -#~ msgstr "1A suggérés" - -#~ msgid "validated first year" -#~ msgstr "1A validés" - -#~ msgid "validated staff" -#~ msgstr "2A+ validés" - -#~ msgid "free seats" -#~ msgstr "sièges libres" - -#~ msgid "Attribute first year members into buses" -#~ msgstr "Attribuer les 1A dans les bus" - -#~ msgid "Start attribution!" -#~ msgstr "Démarrer l'attribution !" - -#~ msgid "Bus attribution" -#~ msgstr "Répartition des bus" - -#~ msgid "suggested bus" -#~ msgstr "bus suggéré" - -#~ msgid "View raw survey information" -#~ msgstr "Voir les informations brutes du sondage" - -#~ msgid "Back to main list" -#~ msgstr "Retour à la liste principale" - -#~ msgid "WEI fee (paid students)" -#~ msgstr "Prix du WEI (élèves)" - -#~ msgid "The BDE membership is included in the WEI registration." -#~ msgstr "L'adhésion au BDE est offerte avec l'inscription au WEI." - -#~ msgid "WEI fee (unpaid students)" -#~ msgstr "Prix du WEI (étudiants)" - -#~ msgid "WEI list" -#~ msgstr "Liste des WEI" - -#~ msgid "Register 1A" -#~ msgstr "Inscrire un 1A" - -#~ msgid "Register 2A+" -#~ msgstr "Inscrire un 2A+" - -#~ msgid "Add bus" -#~ msgstr "Ajouter un bus" - -#~ msgid "View WEI" -#~ msgstr "Voir le WEI" - -#~ msgid "Add team" -#~ msgstr "Ajouter une équipe" - -#~ msgid "Members" -#~ msgstr "Membres" - -#~ msgid "View as PDF" -#~ msgstr "Télécharger au format PDF" - -#~ msgid "Survey WEI" -#~ msgstr "Questionnaire WEI" - -#~ msgid "Next" -#~ msgstr "Suivant" - -#~ msgid "The inscription for this WEI are now closed." -#~ msgstr "Les inscriptions pour le WEI sont fermées." - -#~ msgid "Return to WEI detail" -#~ msgstr "Retour aux détails du WEI" - -#~ msgid "The survey is now ended. Your answers have been saved." -#~ msgstr "" -#~ "Le sondage est désormais terminé, vos réponses ont bien été enregistrées." - -#~ msgid "Register to the WEI! – 1A" -#~ msgstr "M'inscrire au WEI ! – 1A" - -#~ msgid "Register to the WEI! – 2A+" -#~ msgstr "M'inscrire au WEI ! – 2A+" - -#~ msgid "Update my registration" -#~ msgstr "Modifier mon inscription" - -#~ msgid "Members of the WEI" -#~ msgstr "Membres du WEI" - -#~ msgid "Unvalidated registrations" -#~ msgstr "Inscriptions non validées" - -#~ msgid "Attribute buses" -#~ msgstr "Répartition dans les bus" - -#~ msgid "Create WEI" -#~ msgstr "Créer un WEI" - -#~ msgid "WEI listing" -#~ msgstr "Liste des WEI" - -#~ msgid "Review registration" -#~ msgstr "Vérifier l'inscription" - -#~ msgid "ENS year" -#~ msgstr "Année à l'ENS" - -#~ msgid "Payment from Société générale" -#~ msgstr "Paiement de la Société générale" - -#~ msgid "Suggested bus from the survey:" -#~ msgstr "Bus suggéré par le sondage :" - -#~ msgid "Raw survey information" -#~ msgstr "Informations brutes du sondage" - -#~ msgid "The algorithm didn't run." -#~ msgstr "L'algorithme n'a pas été exécuté." - -#~ msgid "caution check given" -#~ msgstr "chèque de caution donné" - -#~ msgid "preferred team" -#~ msgstr "équipe préférée" - -#~ msgid "preferred roles" -#~ msgstr "rôles préférés" - -#~ msgid "Update registration" -#~ msgstr "Modifier l'inscription" - -#~ msgid "The registration is already validated and can't be unvalidated." -#~ msgstr "L'inscription a déjà été validée et ne peut pas être dévalidée." - -#~ msgid "The user joined the bus" -#~ msgstr "L'utilisateur a rejoint le bus" - -#~ msgid "in the team" -#~ msgstr "dans l'équipe" - -#~ msgid "in no team (staff)" -#~ msgstr "dans aucune équipe (staff)" - -#~ msgid "with the following roles:" -#~ msgstr "avec les rôles suivants :" - -#~ msgid "" -#~ "The WEI will be paid by Société générale. The membership will be created " -#~ "even if the bank didn't pay the BDE yet. The membership transaction will " -#~ "be created but will be invalid. You will have to validate it once the " -#~ "bank validated the creation of the account, or to change the payment " -#~ "method." -#~ msgstr "" -#~ "Le WEI va être payé par la Société générale. L'adhésion sera créée même " -#~ "si la banque n'a pas encore payé le BDE. La transaction d'adhésion sera " -#~ "créée mais invalide. Vous devrez la valider une fois que la banque aura " -#~ "validé la création du compte, ou bien changer de moyen de paiement." - -#, python-format -#~ msgid "" -#~ "The note don't have enough money (%(balance)s, %(pretty_fee)s required). " -#~ "The registration may fail if you don't credit the note now." -#~ msgstr "" -#~ "La note n'a pas assez d'argent (%(balance)s, %(pretty_fee)s requis). " -#~ "L'inscription peut échouer si vous ne rechargez pas la note dès " -#~ "maintenant." - -#, python-format -#~ msgid "" -#~ "The note has enough money (%(pretty_fee)s required), the registration is " -#~ "possible." -#~ msgstr "" -#~ "La note a assez d'argent (%(pretty_fee)s requis), l'inscription est " -#~ "possible." - -#~ msgid "The user didn't give her/his caution check." -#~ msgstr "L'utilisateur n'a pas donné son chèque de caution." - -#~ msgid "" -#~ "This user is not a member of the Kfet club for the coming year. The " -#~ "membership will be processed automatically, the WEI registration includes " -#~ "the membership fee." -#~ msgstr "" -#~ "Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. " -#~ "L'adhésion va être faite automatiquement, l'inscription au WEI inclut le " -#~ "coût d'adhésion." - -#~ msgid "View unvalidated registrations..." -#~ msgstr "Voir les inscriptions non validées ..." - -#~ msgid "This registration is already validated and can't be deleted." -#~ msgstr "L'inscription a déjà été validée et ne peut pas être supprimée." - -#, python-format -#~ msgid "" -#~ "Are you sure you want to delete the registration of %(user)s for the WEI " -#~ "%(wei_name)s? This action can't be undone." -#~ msgstr "" -#~ "Êtes-vous sûr⋅e de vouloir supprimer l'inscription de %(user)s pour le " -#~ "WEI %(wei_name)s ? Cette action ne pourra pas être annulée." - -#~ msgid "There is no pre-registration found with this pattern." -#~ msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée." - -#~ msgid "View validated memberships..." -#~ msgstr "Voir les adhésions validées ..." - -#~ msgid "Search WEI" -#~ msgstr "Chercher un WEI" - -#~ msgid "WEI Detail" -#~ msgstr "Détails du WEI" - -#~ msgid "View members of the WEI" -#~ msgstr "Voir les membres du WEI" - -#~ msgid "Find WEI Membership" -#~ msgstr "Trouver une adhésion au WEI" - -#~ msgid "View registrations to the WEI" -#~ msgstr "Voir les inscriptions au WEI" - -#~ msgid "Find WEI Registration" -#~ msgstr "Trouver une inscription au WEI" - -#~ msgid "Update the WEI" -#~ msgstr "Modifier le WEI" - -#~ msgid "Create new bus" -#~ msgstr "Ajouter un nouveau bus" - -#~ msgid "Update bus" -#~ msgstr "Modifier le bus" - -#~ msgid "Manage bus" -#~ msgstr "Gérer le bus" - -#~ msgid "Create new team" -#~ msgstr "Créer une nouvelle équipe" - -#~ msgid "Update team" -#~ msgstr "Modifier l'équipe" - -#~ msgid "Manage WEI team" -#~ msgstr "Gérer l'équipe WEI" - -#~ msgid "Register first year student to the WEI" -#~ msgstr "Inscrire un 1A au WEI" - -#~ msgid "This user is already registered to this WEI." -#~ msgstr "Cette personne est déjà inscrite au WEI." - -#~ msgid "" -#~ "This user can't be in her/his first year since he/she has already " -#~ "participated to a WEI." -#~ msgstr "" -#~ "Cet utilisateur ne peut pas être en première année puisqu'il a déjà " -#~ "participé à un WEI." - -#~ msgid "Register old student to the WEI" -#~ msgstr "Inscrire un 2A+ au WEI" - -#~ msgid "You already opened an account in the Société générale." -#~ msgstr "Vous avez déjà ouvert un compte auprès de la société générale." - -#~ msgid "Update WEI Registration" -#~ msgstr "Modifier l'inscription WEI" - -#~ msgid "Delete WEI registration" -#~ msgstr "Supprimer l'inscription WEI" - -#~ msgid "You don't have the right to delete this WEI registration." -#~ msgstr "" -#~ "Vous n'avez pas la permission de supprimer cette inscription au WEI." - -#~ msgid "Validate WEI registration" -#~ msgstr "Valider l'inscription WEI" - -#~ msgid "Attribute buses to first year members" -#~ msgstr "Répartir les 1A dans les bus" - -#~ msgid "Attribute bus" -#~ msgstr "Attribuer un bus" - -#~ msgid "" -#~ "You are not a BDE member anymore. Please renew your membership if you " -#~ "want to use the note." -#~ msgstr "" -#~ "Vous n'êtes plus adhérent BDE. Merci de réadhérer si vous voulez profiter " -#~ "de la note." - -#~ msgid "" -#~ "You declared that you opened a bank account in the Société générale. The " -#~ "bank did not validate the creation of the account to the BDE, so the " -#~ "membership and the WEI are not paid yet. This verification procedure may " -#~ "last a few days. Please make sure that you go to the end of the account " -#~ "creation." -#~ msgstr "" -#~ "Vous avez déclaré que vous avez ouvert un compte bancaire à la société " -#~ "générale. La banque n'a pas encore validé la création du compte auprès du " -#~ "BDE, l'adhésion et le WEI ne sont donc pas encore payés. Cette procédure " -#~ "de vérification peut durer quelques jours. Merci de vous assurer de bien " -#~ "aller au bout de vos démarches." +"compte. Le BDE doit d'abord valider votre compte avant que vous puissiez " +"vous connecter. Vous devez vous rendre à la Kfet et payer les frais " +"d'adhésion. Vous devez également valider votre adresse email en suivant le " +"lien que vous avez reçu." diff --git a/note_kfet/admin.py b/note_kfet/admin.py index 9e187f8..dc209c6 100644 --- a/note_kfet/admin.py +++ b/note_kfet/admin.py @@ -25,14 +25,19 @@ admin_site.register(Site, SiteAdmin) # Add external apps model if "oauth2_provider" in settings.INSTALLED_APPS: - from oauth2_provider.models import Application, Grant, AccessToken, RefreshToken - from oauth2_provider.admin import ApplicationAdmin, \ - GrantAdmin, AccessTokenAdmin, RefreshTokenAdmin + from oauth2_provider.admin import Application, ApplicationAdmin, Grant, \ + GrantAdmin, AccessToken, AccessTokenAdmin, RefreshToken, RefreshTokenAdmin admin_site.register(Application, ApplicationAdmin) admin_site.register(Grant, GrantAdmin) admin_site.register(AccessToken, AccessTokenAdmin) admin_site.register(RefreshToken, RefreshTokenAdmin) +if "django_htcpcp_tea" in settings.INSTALLED_APPS: + from django_htcpcp_tea.admin import * + from django_htcpcp_tea.models import * + admin_site.register(Pot, PotAdmin) + admin_site.register(TeaType, TeaTypeAdmin) + admin_site.register(Addition, AdditionAdmin) if "mailer" in settings.INSTALLED_APPS: from mailer.admin import * diff --git a/note_kfet/fixtures/initial.json b/note_kfet/fixtures/initial.json index b05cf3f..5d54f3e 100644 --- a/note_kfet/fixtures/initial.json +++ b/note_kfet/fixtures/initial.json @@ -4,7 +4,7 @@ "pk": 1, "fields": { "domain": "note.crans.org", - "name": "Notes Ker Lann" + "name": "La Note Kfet \ud83c\udf7b" } } ] diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 9184072..549399d 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -40,15 +40,13 @@ INSTALLED_APPS = [ # External apps 'bootstrap_datepicker_plus', 'colorfield', - 'bootstrap4', - 'crispy_bootstrap4', 'crispy_forms', + 'django_htcpcp_tea', 'django_tables2', 'mailer', 'phonenumber_field', 'polymorphic', 'oauth2_provider', - 'qr_code', # Django contrib # Django Admin will autodiscover our apps for our custom admin site. @@ -78,6 +76,7 @@ INSTALLED_APPS = [ 'registration', 'scripts', 'treasury', + 'wei', ] MIDDLEWARE = [ @@ -91,6 +90,7 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', + 'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware', 'note_kfet.middlewares.SessionMiddleware', 'note_kfet.middlewares.LoginByIPMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware', @@ -221,10 +221,9 @@ MEDIA_URL = '/media/' # Use mailer in production to place emails in a queue before sending them to avoid spam EMAIL_BACKEND = 'mailer.backend.DbBackend' MAILER_EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_USE_SSL = (os.getenv('EMAIL_USE_SSL', "False")=="True") -EMAIL_USE_TLS = (os.getenv('EMAIL_USE_TLS', "True")=="True") +EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL', False) EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.example.org') -EMAIL_PORT = os.getenv('EMAIL_PORT', 587) +EMAIL_PORT = os.getenv('EMAIL_PORT', 25) EMAIL_HOST_USER = os.getenv('EMAIL_USER', None) EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD', None) @@ -237,7 +236,7 @@ DEFAULT_FROM_EMAIL = "NoteKfet2020 <" + SERVER_EMAIL + ">" cache_address = os.getenv("CACHE_ADDRESS", "127.0.0.1:11211") CACHES = { 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': cache_address, } } @@ -296,5 +295,3 @@ PHONENUMBER_DEFAULT_REGION = 'FR' # We add custom information to CAS, in order to give a normalized name to other services CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' - -DEFAULT_AUTO_FIELD='django.db.models.AutoField' diff --git a/note_kfet/templates/autocomplete_model.html b/note_kfet/templates/autocomplete_model.html index 0502742..20c8041 100644 --- a/note_kfet/templates/autocomplete_model.html +++ b/note_kfet/templates/autocomplete_model.html @@ -7,13 +7,8 @@ SPDX-License-Identifier: GPL-3.0-or-later {% if widget.resetable %} diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html index aab51ad..0466360 100644 --- a/note_kfet/templates/base.html +++ b/note_kfet/templates/base.html @@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% block title %}{{ title }}{% endblock title %} - {{ request.site.name }} - + {# Favicon #} @@ -36,7 +36,6 @@ SPDX-License-Identifier: GPL-3.0-or-later - {# Translation in javascript files #} @@ -67,7 +66,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% trans 'Consumptions' %} {% endif %} - {% if user.is_authenticated and user|is_member:"Sinfonie" %} + {% if user.is_authenticated and user|is_member:"Kfet" %} {% endif %} + {% if "wei.weiclub"|not_empty_model_list %} + + {% endif %} {% if request.user.is_authenticated %}