Merge branch 'beta' into JS_translations

# Conflicts:
#	apps/note/static/note/js/consos.js
#	locale/de/LC_MESSAGES/django.po
#	locale/es/LC_MESSAGES/django.po
#	locale/fr/LC_MESSAGES/django.po
This commit is contained in:
Yohann D'ANELLO 2020-11-16 00:59:26 +01:00
commit 8434c0062c
53 changed files with 1121 additions and 684 deletions

View File

@ -16,8 +16,8 @@ py37-django22:
apt-get install --no-install-recommends -t buster-backports -y apt-get install --no-install-recommends -t buster-backports -y
python3-django python3-django-crispy-forms python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-cas-server python3-psycopg2 python3-pil python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py37-django22 script: tox -e py37-django22
@ -33,8 +33,8 @@ py38-django22:
apt-get install --no-install-recommends -y apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-cas-server python3-psycopg2 python3-pil python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py38-django22 script: tox -e py38-django22

View File

@ -8,8 +8,8 @@ RUN apt-get update && \
apt-get install --no-install-recommends -t buster-backports -y \ apt-get install --no-install-recommends -t buster-backports -y \
python3-django python3-django-crispy-forms \ python3-django python3-django-crispy-forms \
python3-django-extensions python3-django-filters python3-django-polymorphic \ python3-django-extensions python3-django-filters python3-django-polymorphic \
python3-djangorestframework python3-django-cas-server python3-psycopg2 python3-pil \ python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil \
python3-babel python3-lockfile python3-pip python3-phonenumbers ipython3 \ python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache ipython3 \
python3-bs4 python3-setuptools \ python3-bs4 python3-setuptools \
uwsgi uwsgi-plugin-python3 \ uwsgi uwsgi-plugin-python3 \
texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome && \ texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome && \

View File

@ -93,10 +93,10 @@ Sinon vous pouvez suivre les étapes décrites ci-dessous.
$ sudo apt install --no-install-recommends -t buster-backports -y \ $ sudo apt install --no-install-recommends -t buster-backports -y \
python3-django python3-django-crispy-forms \ python3-django python3-django-crispy-forms \
python3-django-extensions python3-django-filters python3-django-polymorphic \ python3-django-extensions python3-django-filters python3-django-polymorphic \
python3-djangorestframework python3-django-cas-server python3-psycopg2 python3-pil \ python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil \
python3-babel python3-lockfile python3-pip python3-phonenumbers ipython3 \ python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache ipython3 \
python3-bs4 python3-setuptools \ python3-bs4 python3-setuptools python3-docutils \
uwsgi uwsgi-plugin-python3 \ memcached uwsgi uwsgi-plugin-python3 \
texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome \ texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome \
nginx python3-venv git acl nginx python3-venv git acl
``` ```

View File

@ -23,13 +23,14 @@
- python3-babel - python3-babel
- python3-bs4 - python3-bs4
- python3-django - python3-django
- python3-django-cas-server
- python3-django-crispy-forms - python3-django-crispy-forms
- python3-django-extensions - python3-django-extensions
- python3-django-filters - python3-django-filters
- python3-django-oauth-toolkit
- python3-django-polymorphic - python3-django-polymorphic
- python3-djangorestframework - python3-djangorestframework
- python3-lockfile - python3-lockfile
- python3-memcache
- python3-phonenumbers - python3-phonenumbers
- python3-pil - python3-pil
- python3-pip - python3-pip
@ -40,6 +41,9 @@
# LaTeX (PDF generation) # LaTeX (PDF generation)
- texlive-xetex - texlive-xetex
# Cache server
- memcached
# WSGI server # WSGI server
- uwsgi - uwsgi
- uwsgi-plugin-python3 - uwsgi-plugin-python3

View File

@ -12,8 +12,10 @@ from django.db.models import F, Q
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views import View from django.views import View
from django.views.decorators.cache import cache_page
from django.views.generic import DetailView, TemplateView, UpdateView from django.views.generic import DetailView, TemplateView, UpdateView
from django_tables2.views import SingleTableView from django_tables2.views import SingleTableView
from note.models import Alias, NoteSpecial, NoteUser from note.models import Alias, NoteSpecial, NoteUser
@ -288,6 +290,8 @@ class ActivityEntryView(LoginRequiredMixin, TemplateView):
return context return context
# Cache for 1 hour
@method_decorator(cache_page(60 * 60), name='dispatch')
class CalendarView(View): class CalendarView(View):
""" """
Render an ICS calendar with all valid activities. Render an ICS calendar with all valid activities.

View File

@ -150,6 +150,7 @@ class ClubForm(forms.ModelForm):
"membership_fee_unpaid": AmountInput(), "membership_fee_unpaid": AmountInput(),
"parent_club": Autocomplete( "parent_club": Autocomplete(
Club, Club,
resetable=True,
attrs={ attrs={
'api_url': '/api/members/club/', 'api_url': '/api/members/club/',
} }

View File

@ -7,6 +7,7 @@ def create_bde_and_kfet(apps, schema_editor):
""" """
Club = apps.get_model("member", "club") Club = apps.get_model("member", "club")
NoteClub = apps.get_model("note", "noteclub") NoteClub = apps.get_model("note", "noteclub")
Alias = apps.get_model("note", "alias")
ContentType = apps.get_model('contenttypes', 'ContentType') ContentType = apps.get_model('contenttypes', 'ContentType')
polymorphic_ctype_id = ContentType.objects.get_for_model(NoteClub).id polymorphic_ctype_id = ContentType.objects.get_for_model(NoteClub).id
@ -45,6 +46,19 @@ def create_bde_and_kfet(apps, schema_editor):
polymorphic_ctype_id=polymorphic_ctype_id, 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): class Migration(migrations.Migration):
dependencies = [ dependencies = [

View File

@ -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),
]

View File

@ -43,8 +43,24 @@ class UserTable(tables.Table):
section = tables.Column(accessor='profile__section') section = tables.Column(accessor='profile__section')
# Override the column to let replace the URL
email = tables.EmailColumn(linkify=lambda record: "mailto:{}".format(record.email))
balance = tables.Column(accessor='note__balance', verbose_name=_("Balance")) balance = tables.Column(accessor='note__balance', verbose_name=_("Balance"))
def render_email(self, record, value):
# Replace the email by a dash if the user can't see the profile detail
# Replace also the URL
if not PermissionBackend.check_perm(get_current_authenticated_user(), "member.view_profile", record.profile):
value = ""
record.email = value
return value
def render_section(self, record, value):
return value \
if PermissionBackend.check_perm(get_current_authenticated_user(), "member.view_profile", record.profile) \
else ""
def render_balance(self, record, value): def render_balance(self, record, value):
return pretty_money(value)\ return pretty_money(value)\
if PermissionBackend.check_perm(get_current_authenticated_user(), "note.view_note", record.note) else "" if PermissionBackend.check_perm(get_current_authenticated_user(), "note.view_note", record.note) else ""
@ -112,7 +128,7 @@ class MembershipTable(tables.Table):
fee=0, fee=0,
) )
if PermissionBackend.check_perm(get_current_authenticated_user(), if PermissionBackend.check_perm(get_current_authenticated_user(),
"member:add_membership", empty_membership): # If the user has right "member.add_membership", empty_membership): # If the user has right
renew_url = reverse_lazy('member:club_renew_membership', renew_url = reverse_lazy('member:club_renew_membership',
kwargs={"pk": record.pk}) kwargs={"pk": record.pk})
t = format_html( t = format_html(

View File

@ -25,25 +25,27 @@
</a> </a>
</dd> </dd>
<dt class="col-xl-6">{% trans 'section'|capfirst %}</dt> {% if "member.view_profile"|has_perm:user_object.profile %}
<dd class="col-xl-6">{{ user_object.profile.section }}</dd> <dt class="col-xl-6">{% trans 'section'|capfirst %}</dt>
<dd class="col-xl-6">{{ user_object.profile.section }}</dd>
<dt class="col-xl-6">{% trans 'email'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'email'|capfirst %}</dt>
<dd class="col-xl-6"><a href="mailto:{{ user_object.email }}">{{ user_object.email }}</a></dd> <dd class="col-xl-6"><a href="mailto:{{ user_object.email }}">{{ user_object.email }}</a></dd>
<dt class="col-xl-6">{% trans 'phone number'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'phone number'|capfirst %}</dt>
<dd class="col-xl-6"><a href="tel:{{ user_object.profile.phone_number }}">{{ user_object.profile.phone_number }}</a> <dd class="col-xl-6"><a href="tel:{{ user_object.profile.phone_number }}">{{ user_object.profile.phone_number }}</a>
</dd> </dd>
<dt class="col-xl-6">{% trans 'address'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'address'|capfirst %}</dt>
<dd class="col-xl-6">{{ user_object.profile.address }}</dd> <dd class="col-xl-6">{{ user_object.profile.address }}</dd>
{% if user_object.note and "note.view_note"|has_perm:user_object.note %} {% if user_object.note and "note.view_note"|has_perm:user_object.note %}
<dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt>
<dd class="col-xl-6">{{ user_object.note.balance | pretty_money }}</dd> <dd class="col-xl-6">{{ user_object.note.balance | pretty_money }}</dd>
<dt class="col-xl-6">{% trans 'paid'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'paid'|capfirst %}</dt>
<dd class="col-xl-6">{{ user_object.profile.paid|yesno }}</dd> <dd class="col-xl-6">{{ user_object.profile.paid|yesno }}</dd>
{% endif %}
{% endif %} {% endif %}
</dl> </dl>

View File

@ -5,7 +5,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% load i18n perms %} {% load i18n perms %}
{% block content %} {% block content %}
{% if "member.change_profile_registration_valid"|has_perm:user %} {% if can_manage_registrations %}
<a class="btn btn-block btn-secondary mb-3" href="{% url 'registration:future_user_list' %}"> <a class="btn btn-block btn-secondary mb-3" href="{% url 'registration:future_user_list' %}">
<i class="fa fa-user-plus"></i> {% trans "Registrations" %} <i class="fa fa-user-plus"></i> {% trans "Registrations" %}
</a> </a>

View File

View File

@ -0,0 +1,22 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date
from django import template
from django.contrib.auth.models import User
from ..models import Club, Membership
def is_member(user, club):
if isinstance(user, str):
club = User.objects.get(username=user)
if isinstance(club, str):
club = Club.objects.get(name=club)
return Membership.objects\
.filter(user=user, club=club, date_start__lte=date.today(), date_end__gte=date.today()).exists()
register = template.Library()
register.filter("is_member", is_member)

View File

@ -41,7 +41,7 @@ class TemplateLoggedInTests(TestCase):
password="adminadmin", password="adminadmin",
permission_mask=3, permission_mask=3,
)) ))
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL, 302, 200) self.assertRedirects(response, settings.LOGIN_REDIRECT_URL, 302, 302)
def test_logout(self): def test_logout(self):
response = self.client.get(reverse("logout")) response = self.client.get(reverse("logout"))

View File

@ -205,7 +205,7 @@ class TestMemberships(TestCase):
first_name="Toto", first_name="Toto",
bank="Le matelas", bank="Le matelas",
)) ))
self.assertRedirects(response, club.get_absolute_url(), 302, 200) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
self.assertTrue(Membership.objects.filter(user=user, club=club).exists()) self.assertTrue(Membership.objects.filter(user=user, club=club).exists())
@ -244,9 +244,9 @@ class TestMemberships(TestCase):
first_name="Toto", first_name="Toto",
bank="Bank", bank="Bank",
)) ))
self.assertRedirects(response, club.get_absolute_url(), 302, 200) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
response = self.client.get(user.profile.get_absolute_url()) response = self.client.get(club.get_absolute_url())
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_auto_join_kfet_when_join_bde_with_soge(self): def test_auto_join_kfet_when_join_bde_with_soge(self):
@ -273,7 +273,7 @@ class TestMemberships(TestCase):
first_name="Toto", first_name="Toto",
bank="Société générale", bank="Société générale",
)) ))
self.assertRedirects(response, bde.get_absolute_url(), 302, 200) self.assertRedirects(response, user.profile.get_absolute_url(), 302, 200)
self.assertTrue(Membership.objects.filter(user=user, club=bde).exists()) self.assertTrue(Membership.objects.filter(user=user, club=bde).exists())
self.assertTrue(Membership.objects.filter(user=user, club=kfet).exists()) self.assertTrue(Membership.objects.filter(user=user, club=kfet).exists())

View File

@ -70,10 +70,11 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
form.fields['email'].required = True form.fields['email'].required = True
form.fields['email'].help_text = _("This address must be valid.") form.fields['email'].help_text = _("This address must be valid.")
context['profile_form'] = self.profile_form(instance=context['user_object'].profile, if PermissionBackend.check_perm(self.request.user, "member.change_profile", context['user_object'].profile):
data=self.request.POST if self.request.POST else None) context['profile_form'] = self.profile_form(instance=context['user_object'].profile,
if not self.object.profile.report_frequency: data=self.request.POST if self.request.POST else None)
del context['profile_form'].fields["last_report"] if not self.object.profile.report_frequency:
del context['profile_form'].fields["last_report"]
return context return context
@ -157,8 +158,12 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
history_table.paginate(per_page=20, page=self.request.GET.get("transaction-page", 1)) history_table.paginate(per_page=20, page=self.request.GET.get("transaction-page", 1))
context['history_list'] = history_table context['history_list'] = history_table
club_list = Membership.objects.filter(user=user, date_end__gte=date.today())\ club_list = Membership.objects.filter(user=user, date_end__gte=date.today() - timedelta(days=15))\
.filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")) .filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view"))\
.order_by("club__name", "-date_start")
# Display only the most recent membership
club_list = club_list.distinct("club__name")\
if settings.DATABASES["default"]["ENGINE"] == 'django.db.backends.postgresql' else club_list
membership_table = MembershipTable(data=club_list, prefix='membership-') membership_table = MembershipTable(data=club_list, prefix='membership-')
membership_table.paginate(per_page=10, page=self.request.GET.get("membership-page", 1)) membership_table.paginate(per_page=10, page=self.request.GET.get("membership-page", 1))
context['club_list'] = membership_table context['club_list'] = membership_table
@ -166,6 +171,8 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
# Check permissions to see if the authenticated user can lock/unlock the note # Check permissions to see if the authenticated user can lock/unlock the note
with transaction.atomic(): with transaction.atomic():
modified_note = NoteUser.objects.get(pk=user.note.pk) modified_note = NoteUser.objects.get(pk=user.note.pk)
# Don't log these tests
modified_note._no_signal = True
modified_note.is_active = True modified_note.is_active = True
modified_note.inactivity_reason = 'manual' modified_note.inactivity_reason = 'manual'
context["can_lock_note"] = user.note.is_active and PermissionBackend\ context["can_lock_note"] = user.note.is_active and PermissionBackend\
@ -178,6 +185,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context["can_force_lock"] = user.note.is_active and PermissionBackend\ context["can_force_lock"] = user.note.is_active and PermissionBackend\
.check_perm(self.request.user, "note.change_note_is_active", modified_note) .check_perm(self.request.user, "note.change_note_is_active", modified_note)
old_note._force_save = True old_note._force_save = True
old_note._no_signal = True
old_note.save() old_note.save()
modified_note.refresh_from_db() modified_note.refresh_from_db()
modified_note.is_active = True modified_note.is_active = True
@ -227,6 +235,13 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
return qs return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pre_registered_users = User.objects.filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))\
.filter(profile__registration_valid=False)
context["can_manage_registrations"] = pre_registered_users.exists()
return context
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
""" """
@ -240,8 +255,8 @@ class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
note = context['object'].note note = context['object'].note
context["aliases"] = AliasTable(note.alias_set.filter(PermissionBackend context["aliases"] = AliasTable(
.filter_queryset(self.request.user, Alias, "view")).all()) note.alias_set.filter(PermissionBackend.filter_queryset(self.request.user, Alias, "view")).distinct().all())
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias( context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
note=context["object"].note, note=context["object"].note,
name="", name="",
@ -392,7 +407,8 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
if PermissionBackend.check_perm(self.request.user, "member.change_club_membership_start", club): if PermissionBackend.check_perm(self.request.user, "member.change_club_membership_start", club):
club.update_membership_dates() club.update_membership_dates()
# managers list # managers list
managers = Membership.objects.filter(club=self.object, roles__name="Bureau de club")\ 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() .order_by('user__last_name').all()
context["managers"] = ClubManagerTable(data=managers, prefix="managers-") context["managers"] = ClubManagerTable(data=managers, prefix="managers-")
# transaction history # transaction history
@ -405,8 +421,12 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
# member list # member list
club_member = Membership.objects.filter( club_member = Membership.objects.filter(
club=club, club=club,
date_end__gte=date.today(), date_end__gte=date.today() - timedelta(days=15),
).filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")) ).filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view"))\
.order_by("user__username", "-date_start")
# Display only the most recent membership
club_member = club_member.distinct("user__username")\
if settings.DATABASES["default"]["ENGINE"] == 'django.db.backends.postgresql' else club_member
membership_table = MembershipTable(data=club_member, prefix="membership-") membership_table = MembershipTable(data=club_member, prefix="membership-")
membership_table.paginate(per_page=5, page=self.request.GET.get('membership-page', 1)) membership_table.paginate(per_page=5, page=self.request.GET.get('membership-page', 1))
@ -438,8 +458,8 @@ class ClubAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
note = context['object'].note note = context['object'].note
context["aliases"] = AliasTable(note.alias_set.filter(PermissionBackend context["aliases"] = AliasTable(note.alias_set.filter(
.filter_queryset(self.request.user, Alias, "view")).all()) PermissionBackend.filter_queryset(self.request.user, Alias, "view")).distinct().all())
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias( context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
note=context["object"].note, note=context["object"].note,
name="", name="",
@ -638,8 +658,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
if club.name != "Kfet" and 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, user=form.instance.user,
club=club.parent_club, club=club.parent_club,
date_start__lte=club.parent_club.membership_start, date_start__gte=club.parent_club.membership_start,
date_end__gte=club.parent_club.membership_end, date_end__lte=club.parent_club.membership_end,
).exists(): ).exists():
form.add_error('user', _('User is not a member of the parent club') + ' ' + club.parent_club.name) form.add_error('user', _('User is not a member of the parent club') + ' ' + club.parent_club.name)
error = True error = True
@ -658,11 +678,13 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"): if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
if not last_name: if not last_name:
form.add_error('last_name', _("This field is required.")) form.add_error('last_name', _("This field is required."))
error = True
if not first_name: if not first_name:
form.add_error('first_name', _("This field is required.")) form.add_error('first_name', _("This field is required."))
error = True
if not bank and credit_type.special_type == "Chèque": if not bank and credit_type.special_type == "Chèque":
form.add_error('bank', _("This field is required.")) form.add_error('bank', _("This field is required."))
return self.form_invalid(form) error = True
return not error return not error
@ -676,6 +698,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view")) \ club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view")) \
.get(pk=self.kwargs["club_pk"]) .get(pk=self.kwargs["club_pk"])
user = form.instance.user user = form.instance.user
old_membership = None
else: # get from url for renewal else: # get from url for renewal
old_membership = self.get_queryset().get(pk=self.kwargs["pk"]) old_membership = self.get_queryset().get(pk=self.kwargs["pk"])
club = old_membership.club club = old_membership.club
@ -750,6 +773,9 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
member_role = Role.objects.filter(Q(name="Adhérent BDE") | Q(name="Membre de club")).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 == "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() 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())
form.instance.roles.set(member_role) form.instance.roles.set(member_role)
form.instance._force_save = True form.instance._force_save = True
form.instance.save() form.instance.save()
@ -787,7 +813,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
return ret return ret
def get_success_url(self): def get_success_url(self):
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.club.id}) return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})
class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):

View File

@ -3,7 +3,7 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.conf import settings from django.conf import settings
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import pre_delete, pre_save, post_save
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from . import signals from . import signals
@ -17,6 +17,15 @@ class NoteConfig(AppConfig):
""" """
Define app internal signals to interact with other apps Define app internal signals to interact with other apps
""" """
pre_save.connect(
signals.pre_save_note,
sender="note.noteuser",
)
pre_save.connect(
signals.pre_save_note,
sender="note.noteclub",
)
post_save.connect( post_save.connect(
signals.save_user_note, signals.save_user_note,
sender=settings.AUTH_USER_MODEL, sender=settings.AUTH_USER_MODEL,

View File

@ -159,20 +159,6 @@ class NoteUser(Note):
def pretty(self): def pretty(self):
return _("%(user)s's note") % {'user': str(self.user)} return _("%(user)s's note") % {'user': str(self.user)}
@transaction.atomic
def save(self, *args, **kwargs):
if self.pk and self.balance < 0:
old_note = NoteUser.objects.get(pk=self.pk)
super().save(*args, **kwargs)
if old_note.balance >= 0:
# Passage en négatif
self.last_negative = timezone.now()
self._force_save = True
self.save(*args, **kwargs)
self.send_mail_negative_balance()
else:
super().save(*args, **kwargs)
def send_mail_negative_balance(self): def send_mail_negative_balance(self):
plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=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)) html = render_to_string("note/mails/negative_balance.html", dict(note=self))
@ -201,20 +187,6 @@ class NoteClub(Note):
def pretty(self): def pretty(self):
return _("Note of %(club)s club") % {'club': str(self.club)} return _("Note of %(club)s club") % {'club': str(self.club)}
@transaction.atomic
def save(self, *args, **kwargs):
if self.pk and self.balance < 0:
old_note = NoteClub.objects.get(pk=self.pk)
super().save(*args, **kwargs)
if old_note.balance >= 0:
# Passage en négatif
self.last_negative = timezone.now()
self._force_save = True
self.save(*args, **kwargs)
self.send_mail_negative_balance()
else:
super().save(*args, **kwargs)
def send_mail_negative_balance(self): def send_mail_negative_balance(self):
plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=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)) html = render_to_string("note/mails/negative_balance.html", dict(note=self))

View File

@ -217,6 +217,9 @@ class Transaction(PolymorphicModel):
# When source == destination, no money is transferred and no transaction is created # When source == destination, no money is transferred and no transaction is created
return return
self.source = Note.objects.select_for_update().get(pk=self.source_id)
self.destination = Note.objects.select_for_update().get(pk=self.destination_id)
# Check that the amounts stay between big integer bounds # Check that the amounts stay between big integer bounds
diff_source, diff_dest = self.validate() diff_source, diff_dest = self.validate()

View File

@ -1,6 +1,8 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.utils import timezone
def save_user_note(instance, raw, **_kwargs): def save_user_note(instance, raw, **_kwargs):
""" """
@ -25,6 +27,16 @@ def save_club_note(instance, raw, **_kwargs):
instance.note.save() instance.note.save()
def pre_save_note(instance, raw, **_kwargs):
if not raw and instance.pk and not hasattr(instance, "_no_signal") and instance.balance < 0:
from note.models import Note
old_note = Note.objects.get(pk=instance.pk)
if old_note.balance >= 0:
# Passage en négatif
instance.last_negative = timezone.now()
instance.send_mail_negative_balance()
def delete_transaction(instance, **_kwargs): def delete_transaction(instance, **_kwargs):
""" """
Whenever we want to delete a transaction (caution with this), we ensure the transaction is invalid first. Whenever we want to delete a transaction (caution with this), we ensure the transaction is invalid first.

View File

@ -67,7 +67,11 @@ $(document).ready(function () {
last.quantity = 1 last.quantity = 1
if (!last.note.user) { if (last.note.club) {
$('#last_name').val(last.note.name)
$('#first_name').val(last.note.name)
}
else if (!last.note.user) {
$.getJSON('/api/note/note/' + last.note.id + '/?format=json', function (note) { $.getJSON('/api/note/note/' + last.note.id + '/?format=json', function (note) {
last.note.user = note.user last.note.user = note.user
$.getJSON('/api/user/' + last.note.user + '/', function (user) { $.getJSON('/api/user/' + last.note.user + '/', function (user) {
@ -246,7 +250,7 @@ $('#btn_transfer').click(function () {
error = true error = true
} }
if (!reason_field.val()) { if (!reason_field.val() && $('#type_transfer').is(':checked')) {
reason_field.addClass('is-invalid') reason_field.addClass('is-invalid')
$('#reason-required').html('<strong>' + gettext('This field is required.') + '</strong>') $('#reason-required').html('<strong>' + gettext('This field is required.') + '</strong>')
error = true error = true
@ -377,7 +381,7 @@ $('#btn_transfer').click(function () {
alias = sources_notes_display[0].name alias = sources_notes_display[0].name
source_id = user_note.id source_id = user_note.id
dest_id = special_note dest_id = special_note
reason = 'Retrait ' + $('#credit_type option:selected').text().toLowerCase() reason = 'Retrait ' + $('#debit_type option:selected').text().toLowerCase()
if (given_reason.length > 0) { reason += ' (' + given_reason + ')' } if (given_reason.length > 0) { reason += ' (' + given_reason + ')' }
} }
$.post('/api/note/transaction/transaction/', $.post('/api/note/transaction/transaction/',

View File

@ -159,7 +159,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endblock %} {% endblock %}
{% block extrajavascript %} {% block extrajavascript %}
<script type="text/javascript" src="{% static "note/js/consos.js" 'javascript-catalog' %}"></script> <script type="text/javascript" src="{% static "note/js/consos.js" %}"></script>
<script type="text/javascript"> <script type="text/javascript">
{% for button in highlighted %} {% for button in highlighted %}
{% if button.display %} {% if button.display %}

View File

@ -115,7 +115,7 @@
"type": "view", "type": "view",
"mask": 1, "mask": 1,
"field": "", "field": "",
"permanent": true, "permanent": false,
"description": "Voir les aliases des notes des clubs et des adhérents du club Kfet" "description": "Voir les aliases des notes des clubs et des adhérents du club Kfet"
} }
}, },
@ -799,12 +799,12 @@
"member", "member",
"membership" "membership"
], ],
"query": "{\"club\": [\"club\"]}", "query": "{}",
"type": "change", "type": "change",
"mask": 3, "mask": 3,
"field": "roles", "field": "roles",
"permanent": false, "permanent": false,
"description": "Modifier les rôles d'un adhérent d'un club" "description": "Modifier les rôles d'une adhésion"
} }
}, },
{ {
@ -2081,7 +2081,7 @@
], ],
"query": "{}", "query": "{}",
"type": "change", "type": "change",
"mask": 1, "mask": 2,
"field": "invalidity_reason", "field": "invalidity_reason",
"permanent": false, "permanent": false,
"description": "Modifier la raison d'invalidité d'une transaction" "description": "Modifier la raison d'invalidité d'une transaction"
@ -2791,6 +2791,86 @@
"description": "Voir tous les alias, y compris ceux des non adhérents" "description": "Voir tous les alias, y compris ceux des non adhérents"
} }
}, },
{
"model": "permission.permission",
"pk": 179,
"fields": {
"model": [
"note",
"alias"
],
"query": "{\"note__noteuser__user\": [\"user\"]}",
"type": "view",
"mask": 1,
"field": "",
"permanent": true,
"description": "Voir ses propres alias, pour toujours"
}
},
{
"model": "permission.permission",
"pk": 180,
"fields": {
"model": [
"auth",
"user"
],
"query": "{\"profile__registration_valid\": false}",
"type": "view",
"mask": 2,
"field": "",
"permanent": false,
"description": "Voir n'importe quel utilisateur non encore inscrit"
}
},
{
"model": "permission.permission",
"pk": 181,
"fields": {
"model": [
"member",
"profile"
],
"query": "{\"registration_valid\": false}",
"type": "view",
"mask": 2,
"field": "",
"permanent": false,
"description": "Voir n'importe quel profil non encore inscrit"
}
},
{
"model": "permission.permission",
"pk": 182,
"fields": {
"model": [
"auth",
"user"
],
"query": "{\"memberships__club__name\": \"BDE\", \"memberships__roles__name\": \"Adhérent BDE\", \"memberships__date_start__lte\": [\"today\"], \"memberships__date_end__gte\": [\"today\"]}",
"type": "view",
"mask": 2,
"field": "",
"permanent": false,
"description": "Voir n'importe quel utilisateur qui est adhérent BDE"
}
},
{
"model": "permission.permission",
"pk": 183,
"fields": {
"model": [
"note",
"note"
],
"query": "{}",
"type": "change",
"mask": 1,
"field": "display_image",
"permanent": false,
"description": "Changer l'image de n'importe quelle note"
}
},
{ {
"model": "permission.role", "model": "permission.role",
"pk": 1, "pk": 1,
@ -2861,7 +2941,8 @@
157, 157,
158, 158,
159, 159,
160 160,
179
] ]
} }
}, },
@ -2922,14 +3003,14 @@
62, 62,
127, 127,
133, 133,
135,
136, 136,
141, 141,
142, 142,
150, 150,
166, 166,
167, 167,
168 168,
182
] ]
} }
}, },
@ -2965,6 +3046,7 @@
31, 31,
32, 32,
33, 33,
51,
53, 53,
54, 54,
55, 55,
@ -2988,6 +3070,7 @@
137, 137,
138, 138,
139, 139,
140,
143, 143,
146, 146,
147, 147,
@ -3003,7 +3086,8 @@
175, 175,
176, 176,
177, 177,
178 178,
183
] ]
} }
}, },
@ -3186,7 +3270,12 @@
175, 175,
176, 176,
177, 177,
178 178,
179,
180,
181,
182,
183
] ]
} }
}, },
@ -3220,7 +3309,12 @@
170, 170,
171, 171,
176, 176,
177 177,
178,
179,
180,
181,
182
] ]
} }
}, },
@ -3383,7 +3477,6 @@
135, 135,
136, 136,
137, 137,
138,
139, 139,
140, 140,
143, 143,
@ -3396,6 +3489,41 @@
] ]
} }
}, },
{
"model": "permission.role",
"pk": 20,
"fields": {
"for_club": 2,
"name": "PC Kfet",
"permissions": [
6,
22,
24,
25,
26,
27,
30,
49,
50,
55,
56,
57,
58,
137,
143,
147,
150,
166,
167,
168,
176,
177,
180,
181,
182
]
}
},
{ {
"model": "wei.weirole", "model": "wei.weirole",
"pk": 12, "pk": 12,

View File

@ -43,7 +43,9 @@ class InstancedPermission:
obj = copy(obj) obj = copy(obj)
obj.pk = 0 obj.pk = 0
with transaction.atomic(): with transaction.atomic():
sid = transaction.savepoint()
for o in self.model.model_class().objects.filter(pk=0).all(): for o in self.model.model_class().objects.filter(pk=0).all():
o._no_signal = True
o._force_delete = True o._force_delete = True
Model.delete(o) Model.delete(o)
# An object with pk 0 wouldn't deleted. That's not normal, we alert admins. # An object with pk 0 wouldn't deleted. That's not normal, we alert admins.
@ -61,9 +63,7 @@ class InstancedPermission:
obj._no_signal = True obj._no_signal = True
Model.save(obj, force_insert=True) Model.save(obj, force_insert=True)
ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists() ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
# Delete testing object transaction.savepoint_rollback(sid)
obj._force_delete = True
Model.delete(obj)
return ret return ret

View File

@ -51,8 +51,10 @@ class ProtectQuerysetMixin:
# No worry if the user change the hidden fields: a 403 error will be performed if the user tries to make # No worry if the user change the hidden fields: a 403 error will be performed if the user tries to make
# a custom request. # a custom request.
# We could also delete the field, but some views might be affected. # We could also delete the field, but some views might be affected.
meta = form.instance._meta
for key in form.base_fields: for key in form.base_fields:
if not PermissionBackend.check_perm(self.request.user, "wei.change_weiregistration_" + key, self.object): if not PermissionBackend.check_perm(self.request.user,
f"{meta.app_label}.change_{meta.model_name}_" + key, self.object):
form.fields[key].widget = HiddenInput() form.fields[key].widget = HiddenInput()
return form return form

View File

@ -44,6 +44,15 @@ class SignUpForm(UserCreationForm):
fields = ('first_name', 'last_name', 'username', 'email', ) fields = ('first_name', 'last_name', 'username', 'email', )
class DeclareSogeAccountOpenedForm(forms.Form):
soge_account = forms.BooleanField(
label=_("I declare that I opened a bank account in the Société générale with the BDE partnership."),
help_text=_("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."),
required=False,
)
class WEISignupForm(forms.Form): class WEISignupForm(forms.Form):
wei_registration = forms.BooleanField( wei_registration = forms.BooleanField(
label=_("Register to the WEI"), label=_("Register to the WEI"),

View File

@ -4,6 +4,8 @@
import django_tables2 as tables import django_tables2 as tables
from django.contrib.auth.models import User from django.contrib.auth.models import User
from treasury.models import SogeCredit
class FutureUserTable(tables.Table): class FutureUserTable(tables.Table):
""" """
@ -21,6 +23,7 @@ class FutureUserTable(tables.Table):
fields = ('last_name', 'first_name', 'username', 'email', ) fields = ('last_name', 'first_name', 'username', 'email', )
model = User model = User
row_attrs = { row_attrs = {
'class': 'table-row', 'class': lambda record: 'table-row'
+ (' bg-warning' if SogeCredit.objects.filter(user=record).exists() else ''),
'data-href': lambda record: record.pk 'data-href': lambda record: record.pk
} }

View File

@ -56,6 +56,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div class="card-header text-center" > <div class="card-header text-center" >
<h4> {% trans "Validate account" %}</h4> <h4> {% trans "Validate account" %}</h4>
</div> </div>
{% if declare_soge_account %}
<div class="alert alert-info">
{% trans "The user declared that he/she opened a bank account in the Société générale." %}
</div>
{% endif %}
<div class="card-body" id="profile_infos"> <div class="card-body" id="profile_infos">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
@ -104,7 +111,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
soge_field.change(fillFields); soge_field.change(fillFields);
{% if object.profile.soge %} {% if declare_soge_account %}
soge_field.attr('checked', true); soge_field.attr('checked', true);
fillFields(); fillFields();
{% endif %} {% endif %}

View File

@ -24,7 +24,7 @@ from permission.models import Role
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
from treasury.models import SogeCredit from treasury.models import SogeCredit
from .forms import SignUpForm, ValidationForm from .forms import SignUpForm, ValidationForm, DeclareSogeAccountOpenedForm
from .tables import FutureUserTable from .tables import FutureUserTable
from .tokens import email_validation_token from .tokens import email_validation_token
@ -42,6 +42,7 @@ class UserCreateView(CreateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["profile_form"] = self.second_form(self.request.POST if self.request.POST else None) context["profile_form"] = self.second_form(self.request.POST if self.request.POST else None)
context["soge_form"] = DeclareSogeAccountOpenedForm(self.request.POST if self.request.POST else None)
del context["profile_form"].fields["section"] del context["profile_form"].fields["section"]
del context["profile_form"].fields["report_frequency"] del context["profile_form"].fields["report_frequency"]
del context["profile_form"].fields["last_report"] del context["profile_form"].fields["last_report"]
@ -72,6 +73,13 @@ class UserCreateView(CreateView):
user.profile.send_email_validation_link() user.profile.send_email_validation_link()
soge_form = DeclareSogeAccountOpenedForm(self.request.POST)
if "soge_account" in soge_form.data and soge_form.data["soge_account"]:
# If the user declares that a bank account got opened, prepare the soge credit to warn treasurers
soge_credit = SogeCredit(user=user)
soge_credit._force_save = True
soge_credit.save()
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self): def get_success_url(self):
@ -182,7 +190,7 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
| Q(username__iregex="^" + pattern) | Q(username__iregex="^" + pattern)
) )
return qs[:20] return qs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -227,6 +235,8 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
fee += 8000 fee += 8000
ctx["total_fee"] = "{:.02f}".format(fee / 100, ) ctx["total_fee"] = "{:.02f}".format(fee / 100, )
ctx["declare_soge_account"] = SogeCredit.objects.filter(user=user).exists()
return ctx return ctx
def get_form(self, form_class=None): def get_form(self, form_class=None):
@ -307,6 +317,13 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user.profile.save() user.profile.save()
user.refresh_from_db() user.refresh_from_db()
if not soge and SogeCredit.objects.filter(user=user).exists():
# If the user declared that a bank account was opened but in the validation form the SoGé case was
# unchecked, delete the associated credit
soge_credit = SogeCredit.objects.get(user=user)
soge_credit._force_delete = True
soge_credit.delete()
if credit_type is not None and credit_amount > 0: if credit_type is not None and credit_amount > 0:
# Credit the note # Credit the note
SpecialTransaction.objects.create( SpecialTransaction.objects.create(
@ -373,6 +390,8 @@ class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View):
user = User.objects.filter(profile__registration_valid=False)\ user = User.objects.filter(profile__registration_valid=False)\
.filter(PermissionBackend.filter_queryset(request.user, User, "change", "is_valid"))\ .filter(PermissionBackend.filter_queryset(request.user, User, "change", "is_valid"))\
.get(pk=self.kwargs["pk"]) .get(pk=self.kwargs["pk"])
# Delete associated soge credits before
SogeCredit.objects.filter(user=user).delete()
user.delete() user.delete()

View File

@ -28,6 +28,8 @@ class TreasuryConfig(AppConfig):
source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)), source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
specialtransactionproxy=None, specialtransactionproxy=None,
): ):
SpecialTransactionProxy.objects.create(transaction=transaction, remittance=None) proxy = SpecialTransactionProxy(transaction=transaction, remittance=None)
proxy._force_save = True
proxy.save()
post_migrate.connect(setup_specialtransactions_proxies, sender=SpecialTransactionProxy) post_migrate.connect(setup_specialtransactions_proxies, sender=SpecialTransactionProxy)

View File

@ -10,7 +10,7 @@ from django.db.models import Q
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, SpecialTransaction, MembershipTransaction from note.models import NoteSpecial, SpecialTransaction, MembershipTransaction, NoteUser
class Invoice(models.Model): class Invoice(models.Model):
@ -335,6 +335,11 @@ class SogeCredit(models.Model):
@transaction.atomic @transaction.atomic
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# This is a pre-registered user that declared that a SoGé account was opened.
# No note exists yet.
if not NoteUser.objects.filter(user=self.user).exists():
return super().save(*args, **kwargs)
if not self.credit_transaction: if not self.credit_transaction:
credit_transaction = SpecialTransaction( credit_transaction = SpecialTransaction(
source=NoteSpecial.objects.get(special_type="Virement bancaire"), source=NoteSpecial.objects.get(special_type="Virement bancaire"),

View File

@ -10,9 +10,8 @@ def save_special_transaction(instance, created, **kwargs):
""" """
if not hasattr(instance, "_no_signal"): if not hasattr(instance, "_no_signal"):
if instance.is_credit(): if created and RemittanceType.objects.filter(
if created and RemittanceType.objects.filter(note=instance.source).exists(): note=instance.source if instance.is_credit() else instance.destination).exists():
SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save() proxy = SpecialTransactionProxy(transaction=instance, remittance=None)
else: proxy._force_save = True
if created and RemittanceType.objects.filter(note=instance.destination).exists(): proxy.save()
SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()

View File

@ -147,4 +147,4 @@ class SogeCreditTable(tables.Table):
class Meta: class Meta:
model = SogeCredit model = SogeCredit
fields = ('user', 'amount', 'valid', ) fields = ('user', 'user__last_name', 'user__first_name', 'amount', 'valid', )

View File

@ -11,8 +11,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div> </div>
<div class="card-body"> <div class="card-body">
<dl class="row"> <dl class="row">
<dt class="col-xl-6 text-right">{% trans 'user'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'last name'|capfirst %}</dt>
<dd class="col-xl-6"><a href="{% url 'member:user_detail' pk=object.user.pk %}">{{ object.user }}</a></dd> <dd class="col-xl-6">{{ object.user.last_name }}</dd>
<dt class="col-xl-6 text-right">{% trans 'first name'|capfirst %}</dt>
<dd class="col-xl-6">{{ object.user.first_name }}</dd>
<dt class="col-xl-6 text-right">{% trans 'username'|capfirst %}</dt>
<dd class="col-xl-6"><a href="{% url 'member:user_detail' pk=object.user.pk %}">{{ object.user.username }}</a></dd>
{% if "note.view_note_balance"|has_perm:object.user.note %} {% if "note.view_note_balance"|has_perm:object.user.note %}
<dt class="col-xl-6 text-right">{% trans 'balance'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'balance'|capfirst %}</dt>

View File

@ -60,7 +60,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
let pattern = searchbar_obj.val(); let pattern = searchbar_obj.val();
$("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + ( $("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + (
invalid_only_obj.is(':checked') ? "&valid=false" : "") + " #credits_table"); invalid_only_obj.is(':checked') ? "" : "&valid=1") + " #credits_table");
$(".table-row").click(function () { $(".table-row").click(function () {
window.document.location = $(this).data("href"); window.document.location = $(this).data("href");

View File

@ -431,7 +431,7 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
if "valid" not in self.request.GET or not self.request.GET["valid"]: if "valid" not in self.request.GET or not self.request.GET["valid"]:
qs = qs.filter(credit_transaction__valid=False) qs = qs.filter(credit_transaction__valid=False)
return qs[:20] return qs
class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormView, DetailView): class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormView, DetailView):

View File

@ -52,9 +52,9 @@ msgstr "Sie dürfen höchstens 3 Leute zu dieser Veranstaltung einladen."
#: apps/member/models.py:199 #: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4 #: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4 #: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:260 apps/note/models/transactions.py:26 #: apps/note/models/notes.py:232 apps/note/models/transactions.py:26
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:297 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:300
#: apps/permission/models.py:330 #: apps/permission/models.py:333
#: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118 #: apps/wei/models.py:66 apps/wei/models.py:118
#: apps/wei/templates/wei/base.html:26 #: apps/wei/templates/wei/base.html:26
@ -90,8 +90,8 @@ msgstr "Vearnstaltungarte"
#: apps/activity/models.py:68 #: apps/activity/models.py:68
#: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/activity/templates/activity/includes/activity_info.html:19
#: apps/note/models/transactions.py:81 apps/permission/models.py:110 #: apps/note/models/transactions.py:81 apps/permission/models.py:113
#: apps/permission/models.py:189 apps/wei/models.py:72 apps/wei/models.py:129 #: apps/permission/models.py:192 apps/wei/models.py:72 apps/wei/models.py:129
msgid "description" msgid "description"
msgstr "Beschreibung" msgstr "Beschreibung"
@ -105,8 +105,8 @@ msgstr "Wo findet die Veranstaltung statt ? (z.B Kfet)"
#: apps/activity/models.py:83 #: apps/activity/models.py:83
#: apps/activity/templates/activity/includes/activity_info.html:22 #: apps/activity/templates/activity/includes/activity_info.html:22
#: apps/note/models/notes.py:236 apps/note/models/transactions.py:66 #: apps/note/models/notes.py:208 apps/note/models/transactions.py:66
#: apps/permission/models.py:164 #: apps/permission/models.py:167
msgid "type" msgid "type"
msgstr "Type" msgstr "Type"
@ -254,15 +254,15 @@ msgstr "entfernen"
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#: apps/activity/tables.py:82 apps/member/forms.py:185 #: apps/activity/tables.py:82 apps/member/forms.py:186
#: apps/registration/forms.py:81 apps/treasury/forms.py:130 #: apps/registration/forms.py:90 apps/treasury/forms.py:130
#: apps/wei/forms/registration.py:96 #: apps/wei/forms/registration.py:96
msgid "Last name" msgid "Last name"
msgstr "Nachname" msgstr "Nachname"
#: apps/activity/tables.py:84 apps/member/forms.py:190 #: apps/activity/tables.py:84 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:134 #: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:86 apps/treasury/forms.py:132 #: apps/registration/forms.py:95 apps/treasury/forms.py:132
#: apps/wei/forms/registration.py:101 #: apps/wei/forms/registration.py:101
msgid "First name" msgid "First name"
msgstr "Vorname" msgstr "Vorname"
@ -286,7 +286,7 @@ msgid "Guest deleted"
msgstr "Gastliste" msgstr "Gastliste"
#: apps/activity/templates/activity/activity_entry.html:14 #: apps/activity/templates/activity/activity_entry.html:14
#: apps/note/models/transactions.py:253 #: apps/note/models/transactions.py:256
#: apps/note/templates/note/transaction_form.html:16 #: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148 #: apps/note/templates/note/transaction_form.html:148
#: note_kfet/templates/base.html:73 #: note_kfet/templates/base.html:73
@ -294,13 +294,13 @@ msgid "Transfer"
msgstr "Überweisen" msgstr "Überweisen"
#: apps/activity/templates/activity/activity_entry.html:18 #: apps/activity/templates/activity/activity_entry.html:18
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:21 #: apps/note/templates/note/transaction_form.html:21
msgid "Credit" msgid "Credit"
msgstr "Kredit" msgstr "Kredit"
#: apps/activity/templates/activity/activity_entry.html:21 #: apps/activity/templates/activity/activity_entry.html:21
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:25 #: apps/note/templates/note/transaction_form.html:25
msgid "Debit" msgid "Debit"
msgstr "Soll" msgstr "Soll"
@ -391,39 +391,39 @@ msgstr "bearbeiten"
msgid "Invite" msgid "Invite"
msgstr "Einladen" msgstr "Einladen"
#: apps/activity/views.py:34 #: apps/activity/views.py:36
msgid "Create new activity" msgid "Create new activity"
msgstr "Neue Veranstaltung schaffen" msgstr "Neue Veranstaltung schaffen"
#: apps/activity/views.py:65 note_kfet/templates/base.html:91 #: apps/activity/views.py:67 note_kfet/templates/base.html:91
msgid "Activities" msgid "Activities"
msgstr "Veranstaltungen" msgstr "Veranstaltungen"
#: apps/activity/views.py:93 #: apps/activity/views.py:95
msgid "Activity detail" msgid "Activity detail"
msgstr "Veranstaltunginfo" msgstr "Veranstaltunginfo"
#: apps/activity/views.py:113 #: apps/activity/views.py:115
msgid "Update activity" msgid "Update activity"
msgstr "Veranstaltung bearbeiten" msgstr "Veranstaltung bearbeiten"
#: apps/activity/views.py:140 #: apps/activity/views.py:142
msgid "Invite guest to the activity \"{}\"" msgid "Invite guest to the activity \"{}\""
msgstr "Gast zur Veranstaltung \"{}\" einladen" msgstr "Gast zur Veranstaltung \"{}\" einladen"
#: apps/activity/views.py:175 #: apps/activity/views.py:177
msgid "You are not allowed to display the entry interface for this activity." msgid "You are not allowed to display the entry interface for this activity."
msgstr "Sie haben nicht das Recht diese Seite zu benuzten." msgstr "Sie haben nicht das Recht diese Seite zu benuzten."
#: apps/activity/views.py:178 #: apps/activity/views.py:180
msgid "This activity does not support activity entries." msgid "This activity does not support activity entries."
msgstr "Diese Veranstaltung braucht nicht Eintritt." msgstr "Diese Veranstaltung braucht nicht Eintritt."
#: apps/activity/views.py:181 #: apps/activity/views.py:183
msgid "This activity is closed." msgid "This activity is closed."
msgstr "Diese Veranstaltung ist geschlossen." msgstr "Diese Veranstaltung ist geschlossen."
#: apps/activity/views.py:277 #: apps/activity/views.py:279
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "Eintritt zur Veranstaltung \"{}\"" msgstr "Eintritt zur Veranstaltung \"{}\""
@ -439,7 +439,7 @@ msgstr "Logs"
msgid "IP Address" msgid "IP Address"
msgstr "IP Adresse" msgstr "IP Adresse"
#: apps/logs/models.py:36 apps/permission/models.py:134 #: apps/logs/models.py:36 apps/permission/models.py:137
msgid "model" msgid "model"
msgstr "Model" msgstr "Model"
@ -460,7 +460,7 @@ msgid "create"
msgstr "schaffen" msgstr "schaffen"
#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201 #: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
#: apps/permission/models.py:127 apps/treasury/tables.py:38 #: apps/permission/models.py:130 apps/treasury/tables.py:38
#: apps/wei/tables.py:75 #: apps/wei/tables.py:75
msgid "delete" msgid "delete"
msgstr "entfernen" msgstr "entfernen"
@ -541,48 +541,48 @@ msgid "This image cannot be loaded."
msgstr "Dieses Bild kann nicht geladen werden." msgstr "Dieses Bild kann nicht geladen werden."
#: apps/member/forms.py:141 apps/member/views.py:100 #: apps/member/forms.py:141 apps/member/views.py:100
#: apps/registration/forms.py:33 apps/registration/views.py:244 #: apps/registration/forms.py:33 apps/registration/views.py:254
msgid "An alias with a similar name already exists." msgid "An alias with a similar name already exists."
msgstr "Ein ähnliches Alias ist schon benutzt." msgstr "Ein ähnliches Alias ist schon benutzt."
#: apps/member/forms.py:164 apps/registration/forms.py:61 #: apps/member/forms.py:165 apps/registration/forms.py:70
msgid "Inscription paid by Société Générale" msgid "Inscription paid by Société Générale"
msgstr "Mitgliedschaft von der Société Générale bezahlt" msgstr "Mitgliedschaft von der Société Générale bezahlt"
#: apps/member/forms.py:166 apps/registration/forms.py:63 #: apps/member/forms.py:167 apps/registration/forms.py:72
msgid "Check this case if the Société Générale paid the inscription." msgid "Check this case if the Société Générale paid the inscription."
msgstr "Die Société Générale die Mitgliedschaft bezahlt." msgstr "Die Société Générale die Mitgliedschaft bezahlt."
#: apps/member/forms.py:171 apps/registration/forms.py:68 #: apps/member/forms.py:172 apps/registration/forms.py:77
#: apps/wei/forms/registration.py:83 #: apps/wei/forms/registration.py:83
msgid "Credit type" msgid "Credit type"
msgstr "Kredittype" msgstr "Kredittype"
#: apps/member/forms.py:172 apps/registration/forms.py:69 #: apps/member/forms.py:173 apps/registration/forms.py:78
#: apps/wei/forms/registration.py:84 #: apps/wei/forms/registration.py:84
msgid "No credit" msgid "No credit"
msgstr "Kein Kredit" msgstr "Kein Kredit"
#: apps/member/forms.py:174 #: apps/member/forms.py:175
msgid "You can credit the note of the user." msgid "You can credit the note of the user."
msgstr "Sie dûrfen diese Note kreditieren." msgstr "Sie dûrfen diese Note kreditieren."
#: apps/member/forms.py:178 apps/registration/forms.py:74 #: apps/member/forms.py:179 apps/registration/forms.py:83
#: apps/wei/forms/registration.py:89 #: apps/wei/forms/registration.py:89
msgid "Credit amount" msgid "Credit amount"
msgstr "Kreditanzahl" msgstr "Kreditanzahl"
#: apps/member/forms.py:195 apps/note/templates/note/transaction_form.html:140 #: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:91 apps/treasury/forms.py:134 #: apps/registration/forms.py:100 apps/treasury/forms.py:134
#: apps/wei/forms/registration.py:106 #: apps/wei/forms/registration.py:106
msgid "Bank" msgid "Bank"
msgstr "Bank" msgstr "Bank"
#: apps/member/forms.py:222 #: apps/member/forms.py:223
msgid "User" msgid "User"
msgstr "User" msgstr "User"
#: apps/member/forms.py:236 #: apps/member/forms.py:237
msgid "Roles" msgid "Roles"
msgstr "Rollen" msgstr "Rollen"
@ -810,7 +810,7 @@ msgstr ""
"Maximales Datum einer Mitgliedschaft, nach dem Mitglieder es erneuern müssen." "Maximales Datum einer Mitgliedschaft, nach dem Mitglieder es erneuern müssen."
#: apps/member/models.py:286 apps/member/models.py:311 #: apps/member/models.py:286 apps/member/models.py:311
#: apps/note/models/notes.py:191 #: apps/note/models/notes.py:177
msgid "club" msgid "club"
msgstr "Club" msgstr "Club"
@ -831,11 +831,11 @@ msgstr "Mitgliedschaft endet am"
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "Die Rolle {role} ist nicht erlaubt für das Club {club}." msgstr "Die Rolle {role} ist nicht erlaubt für das Club {club}."
#: apps/member/models.py:430 apps/member/views.py:634 #: apps/member/models.py:430 apps/member/views.py:646
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "User ist schon ein Mitglied dieser club" msgstr "User ist schon ein Mitglied dieser club"
#: apps/member/models.py:442 apps/member/views.py:644 #: apps/member/models.py:442 apps/member/views.py:656
msgid "User is not a member of the parent club" msgid "User is not a member of the parent club"
msgstr "User ist noch nicht Mitglied des Urclubs" msgstr "User ist noch nicht Mitglied des Urclubs"
@ -844,7 +844,7 @@ msgstr "User ist noch nicht Mitglied des Urclubs"
msgid "Membership of {user} for the club {club}" msgid "Membership of {user} for the club {club}"
msgstr "Mitgliedschaft von {user} für das Club {club}" msgstr "Mitgliedschaft von {user} für das Club {club}"
#: apps/member/models.py:498 apps/note/models/transactions.py:355 #: apps/member/models.py:498 apps/note/models/transactions.py:358
msgid "membership" msgid "membership"
msgstr "Mitgliedschaft" msgstr "Mitgliedschaft"
@ -963,8 +963,8 @@ msgstr ""
"erlaubt." "erlaubt."
#: apps/member/templates/member/club_alias.html:10 #: apps/member/templates/member/club_alias.html:10
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:238 #: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:245
#: apps/member/views.py:436 #: apps/member/views.py:448
msgid "Note aliases" msgid "Note aliases"
msgstr "Note Aliases" msgstr "Note Aliases"
@ -1028,7 +1028,7 @@ msgstr "Kontostand"
#: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/club_info.html:47
#: apps/member/templates/member/includes/profile_info.html:20 #: apps/member/templates/member/includes/profile_info.html:20
#: apps/note/models/notes.py:283 apps/wei/templates/wei/base.html:66 #: apps/note/models/notes.py:255 apps/wei/templates/wei/base.html:66
msgid "aliases" msgid "aliases"
msgstr "Aliases" msgstr "Aliases"
@ -1107,39 +1107,39 @@ msgstr "Diese Adresse muss gültig sein."
msgid "Profile detail" msgid "Profile detail"
msgstr "Profile detail" msgstr "Profile detail"
#: apps/member/views.py:197 #: apps/member/views.py:204
msgid "Search user" msgid "Search user"
msgstr "User finden" msgstr "User finden"
#: apps/member/views.py:258 #: apps/member/views.py:265
msgid "Update note picture" msgid "Update note picture"
msgstr "Notebild ändern" msgstr "Notebild ändern"
#: apps/member/views.py:304 #: apps/member/views.py:311
msgid "Manage auth token" msgid "Manage auth token"
msgstr "Auth token bearbeiten" msgstr "Auth token bearbeiten"
#: apps/member/views.py:331 #: apps/member/views.py:338
msgid "Create new club" msgid "Create new club"
msgstr "Neue Club" msgstr "Neue Club"
#: apps/member/views.py:350 #: apps/member/views.py:357
msgid "Search club" msgid "Search club"
msgstr "Club finden" msgstr "Club finden"
#: apps/member/views.py:383 #: apps/member/views.py:390
msgid "Club detail" msgid "Club detail"
msgstr "Club Details" msgstr "Club Details"
#: apps/member/views.py:459 #: apps/member/views.py:471
msgid "Update club" msgid "Update club"
msgstr "Club bearbeiten" msgstr "Club bearbeiten"
#: apps/member/views.py:493 #: apps/member/views.py:505
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "Neue Mitglieder" msgstr "Neue Mitglieder"
#: apps/member/views.py:625 apps/wei/views.py:928 #: apps/member/views.py:637 apps/wei/views.py:928
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
@ -1147,25 +1147,25 @@ msgstr ""
"Diese User hat nicht genug Geld um Mitglied zu werden, und darf nich im Rot " "Diese User hat nicht genug Geld um Mitglied zu werden, und darf nich im Rot "
"sein." "sein."
#: apps/member/views.py:648 #: apps/member/views.py:660
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "Die Mitgliedschaft muss nach {:%m-%d-Y} anfängen." msgstr "Die Mitgliedschaft muss nach {:%m-%d-Y} anfängen."
#: apps/member/views.py:653 #: apps/member/views.py:665
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "Die Mitgliedschaft muss vor {:%m-%d-Y} anfängen." msgstr "Die Mitgliedschaft muss vor {:%m-%d-Y} anfängen."
#: apps/member/views.py:660 apps/member/views.py:662 apps/member/views.py:664 #: apps/member/views.py:672 apps/member/views.py:674 apps/member/views.py:676
#: apps/registration/views.py:294 apps/registration/views.py:296 #: apps/registration/views.py:304 apps/registration/views.py:306
#: apps/registration/views.py:298 apps/wei/views.py:933 apps/wei/views.py:937 #: apps/registration/views.py:308 apps/wei/views.py:933 apps/wei/views.py:937
msgid "This field is required." msgid "This field is required."
msgstr "Dies ist ein Pflichtfeld." msgstr "Dies ist ein Pflichtfeld."
#: apps/member/views.py:800 #: apps/member/views.py:816
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "Rollen in diesen Club bearbeiten" msgstr "Rollen in diesen Club bearbeiten"
#: apps/member/views.py:825 #: apps/member/views.py:841
msgid "Members of the club" msgid "Members of the club"
msgstr "Mitlglieder dieses Club" msgstr "Mitlglieder dieses Club"
@ -1184,7 +1184,7 @@ msgid "amount"
msgstr "Anzahl" msgstr "Anzahl"
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189 #: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
#: apps/note/models/transactions.py:224 #: apps/note/models/transactions.py:227
msgid "" msgid ""
"The transaction can't be saved since the source note or the destination note " "The transaction can't be saved since the source note or the destination note "
"is not active." "is not active."
@ -1293,51 +1293,51 @@ msgstr "User Note"
msgid "%(user)s's note" msgid "%(user)s's note"
msgstr "%(user)s's note" msgstr "%(user)s's note"
#: apps/note/models/notes.py:195 #: apps/note/models/notes.py:181
msgid "club note" msgid "club note"
msgstr "Club Note" msgstr "Club Note"
#: apps/note/models/notes.py:196 #: apps/note/models/notes.py:182
msgid "clubs notes" msgid "clubs notes"
msgstr "Club Notes" msgstr "Club Notes"
#: apps/note/models/notes.py:202 #: apps/note/models/notes.py:188
#, python-format #, python-format
msgid "Note of %(club)s club" msgid "Note of %(club)s club"
msgstr "%(club)s Note" msgstr "%(club)s Note"
#: apps/note/models/notes.py:242 #: apps/note/models/notes.py:214
msgid "special note" msgid "special note"
msgstr "Sondernote" msgstr "Sondernote"
#: apps/note/models/notes.py:243 #: apps/note/models/notes.py:215
msgid "special notes" msgid "special notes"
msgstr "Sondernoten" msgstr "Sondernoten"
#: apps/note/models/notes.py:266 #: apps/note/models/notes.py:238
msgid "Invalid alias" msgid "Invalid alias"
msgstr "Unerlaublt Alias" msgstr "Unerlaublt Alias"
#: apps/note/models/notes.py:282 #: apps/note/models/notes.py:254
msgid "alias" msgid "alias"
msgstr "Alias" msgstr "Alias"
#: apps/note/models/notes.py:306 #: apps/note/models/notes.py:278
msgid "Alias is too long." msgid "Alias is too long."
msgstr "Alias ist zu lang." msgstr "Alias ist zu lang."
#: apps/note/models/notes.py:309 #: apps/note/models/notes.py:281
msgid "" msgid ""
"This alias contains only complex character. Please use a more simple alias." "This alias contains only complex character. Please use a more simple alias."
msgstr "" msgstr ""
"Dieser Alias enthält nur komplexe Zeichen. Bitte verwenden Sie einen " "Dieser Alias enthält nur komplexe Zeichen. Bitte verwenden Sie einen "
"einfacheren Alias." "einfacheren Alias."
#: apps/note/models/notes.py:313 #: apps/note/models/notes.py:285
msgid "An alias with a similar name already exists: {} " msgid "An alias with a similar name already exists: {} "
msgstr "Ein Alias mit einem ähnlichen Namen existiert bereits: {} " msgstr "Ein Alias mit einem ähnlichen Namen existiert bereits: {} "
#: apps/note/models/notes.py:327 #: apps/note/models/notes.py:299
msgid "You can't delete your main alias." msgid "You can't delete your main alias."
msgstr "Sie können Ihren Hauptalias nicht löschen." msgstr "Sie können Ihren Hauptalias nicht löschen."
@ -1412,34 +1412,34 @@ msgstr ""
"Die Notenguthaben müssen zwischen - 92 233 720 368 547 758,08 € und 92 233 " "Die Notenguthaben müssen zwischen - 92 233 720 368 547 758,08 € und 92 233 "
"720 368 547 758,07 € liegen." "720 368 547 758,07 € liegen."
#: apps/note/models/transactions.py:273 #: apps/note/models/transactions.py:276
msgid "" msgid ""
"The destination of this transaction must equal to the destination of the " "The destination of this transaction must equal to the destination of the "
"template." "template."
msgstr "" msgstr ""
"Der Empfänger dieser Transaktion muss dem Empfänger der Vorlage entsprechen." "Der Empfänger dieser Transaktion muss dem Empfänger der Vorlage entsprechen."
#: apps/note/models/transactions.py:283 #: apps/note/models/transactions.py:286
msgid "Template" msgid "Template"
msgstr "Vorlage" msgstr "Vorlage"
#: apps/note/models/transactions.py:286 #: apps/note/models/transactions.py:289
msgid "recurrent transaction" msgid "recurrent transaction"
msgstr "wiederkehrende Transaktion" msgstr "wiederkehrende Transaktion"
#: apps/note/models/transactions.py:287 #: apps/note/models/transactions.py:290
msgid "recurrent transactions" msgid "recurrent transactions"
msgstr "wiederkehrende Transaktionen" msgstr "wiederkehrende Transaktionen"
#: apps/note/models/transactions.py:302 #: apps/note/models/transactions.py:305
msgid "first_name" msgid "first_name"
msgstr "Vorname" msgstr "Vorname"
#: apps/note/models/transactions.py:307 #: apps/note/models/transactions.py:310
msgid "bank" msgid "bank"
msgstr "Bank" msgstr "Bank"
#: apps/note/models/transactions.py:324 #: apps/note/models/transactions.py:327
msgid "" msgid ""
"A special transaction is only possible between a Note associated to a " "A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club" "payment method and a User or a Club"
@ -1447,19 +1447,19 @@ msgstr ""
"Eine Sondertransaktion ist nur zwischen einer Note, die einer " "Eine Sondertransaktion ist nur zwischen einer Note, die einer "
"Zahlungsmethode zugeordnet ist, und einem User oder einem Club möglich" "Zahlungsmethode zugeordnet ist, und einem User oder einem Club möglich"
#: apps/note/models/transactions.py:333 #: apps/note/models/transactions.py:336
msgid "Special transaction" msgid "Special transaction"
msgstr "Sondertransaktion" msgstr "Sondertransaktion"
#: apps/note/models/transactions.py:334 #: apps/note/models/transactions.py:337
msgid "Special transactions" msgid "Special transactions"
msgstr "Sondertranskationen" msgstr "Sondertranskationen"
#: apps/note/models/transactions.py:350 #: apps/note/models/transactions.py:353
msgid "membership transaction" msgid "membership transaction"
msgstr "Mitgliedschafttransaktion" msgstr "Mitgliedschafttransaktion"
#: apps/note/models/transactions.py:351 apps/treasury/models.py:284 #: apps/note/models/transactions.py:354 apps/treasury/models.py:284
msgid "membership transactions" msgid "membership transactions"
msgstr "Mitgliedschaftttransaktionen" msgstr "Mitgliedschaftttransaktionen"
@ -1649,53 +1649,53 @@ msgstr "Sie können keine Taste sehen."
msgid "Search transactions" msgid "Search transactions"
msgstr "Transaktion finden" msgstr "Transaktion finden"
#: apps/permission/models.py:89 #: apps/permission/models.py:92
#, python-brace-format #, python-brace-format
msgid "Can {type} {model}.{field} in {query}" msgid "Can {type} {model}.{field} in {query}"
msgstr "Kann {type} {model}.{field} in {query}" msgstr "Kann {type} {model}.{field} in {query}"
#: apps/permission/models.py:91 #: apps/permission/models.py:94
#, python-brace-format #, python-brace-format
msgid "Can {type} {model} in {query}" msgid "Can {type} {model} in {query}"
msgstr "Kann {type} {model} in {query}" msgstr "Kann {type} {model} in {query}"
#: apps/permission/models.py:104 #: apps/permission/models.py:107
msgid "rank" msgid "rank"
msgstr "Rank" msgstr "Rank"
#: apps/permission/models.py:117 #: apps/permission/models.py:120
msgid "permission mask" msgid "permission mask"
msgstr "Berechtigungsmaske" msgstr "Berechtigungsmaske"
#: apps/permission/models.py:118 #: apps/permission/models.py:121
msgid "permission masks" msgid "permission masks"
msgstr "Berechtigungsmasken" msgstr "Berechtigungsmasken"
#: apps/permission/models.py:124 #: apps/permission/models.py:127
msgid "add" msgid "add"
msgstr "hinzufügen" msgstr "hinzufügen"
#: apps/permission/models.py:125 #: apps/permission/models.py:128
msgid "view" msgid "view"
msgstr "Schauen" msgstr "Schauen"
#: apps/permission/models.py:126 #: apps/permission/models.py:129
msgid "change" msgid "change"
msgstr "bearbeiten" msgstr "bearbeiten"
#: apps/permission/models.py:158 #: apps/permission/models.py:161
msgid "query" msgid "query"
msgstr "Abfrage" msgstr "Abfrage"
#: apps/permission/models.py:171 #: apps/permission/models.py:174
msgid "mask" msgid "mask"
msgstr "Maske" msgstr "Maske"
#: apps/permission/models.py:177 #: apps/permission/models.py:180
msgid "field" msgid "field"
msgstr "Feld" msgstr "Feld"
#: apps/permission/models.py:182 #: apps/permission/models.py:185
msgid "" msgid ""
"Tells if the permission should be granted even if the membership of the user " "Tells if the permission should be granted even if the membership of the user "
"is expired." "is expired."
@ -1703,28 +1703,28 @@ msgstr ""
"Gibt an, ob die Berechtigung auch erteilt werden soll, wenn die " "Gibt an, ob die Berechtigung auch erteilt werden soll, wenn die "
"Mitgliedschaft des Benutzers abgelaufen ist." "Mitgliedschaft des Benutzers abgelaufen ist."
#: apps/permission/models.py:183 #: apps/permission/models.py:186
#: apps/permission/templates/permission/all_rights.html:89 #: apps/permission/templates/permission/all_rights.html:89
msgid "permanent" msgid "permanent"
msgstr "permanent" msgstr "permanent"
#: apps/permission/models.py:194 #: apps/permission/models.py:197
msgid "permission" msgid "permission"
msgstr "Berechtigung" msgstr "Berechtigung"
#: apps/permission/models.py:195 apps/permission/models.py:335 #: apps/permission/models.py:198 apps/permission/models.py:338
msgid "permissions" msgid "permissions"
msgstr "Berechtigungen" msgstr "Berechtigungen"
#: apps/permission/models.py:200 #: apps/permission/models.py:203
msgid "Specifying field applies only to view and change permission types." msgid "Specifying field applies only to view and change permission types."
msgstr "Angabefeld gilt nur zum Anzeigen und Ändern von Berechtigungstypen." msgstr "Angabefeld gilt nur zum Anzeigen und Ändern von Berechtigungstypen."
#: apps/permission/models.py:340 #: apps/permission/models.py:343
msgid "for club" msgid "for club"
msgstr "Für Club" msgstr "Für Club"
#: apps/permission/models.py:350 apps/permission/models.py:351 #: apps/permission/models.py:353 apps/permission/models.py:354
msgid "role permissions" msgid "role permissions"
msgstr "Berechtigung Rollen" msgstr "Berechtigung Rollen"
@ -1832,10 +1832,24 @@ msgid "This email address is already used."
msgstr "Diese email adresse ist schon benutzt." msgstr "Diese email adresse ist schon benutzt."
#: apps/registration/forms.py:49 #: 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 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:50
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:58
msgid "Register to the WEI" msgid "Register to the WEI"
msgstr "Zu WEI anmelden" msgstr "Zu WEI anmelden"
#: apps/registration/forms.py:51 #: apps/registration/forms.py:60
msgid "" msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you " "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." "will be able to register later, after validating your account in the Kfet."
@ -1844,11 +1858,11 @@ msgstr ""
"falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im Kfet " "falls Zweifel, können Sie sich später nach Bestätigung Ihres Kontos im Kfet "
"registrieren." "registrieren."
#: apps/registration/forms.py:96 #: apps/registration/forms.py:105
msgid "Join BDE Club" msgid "Join BDE Club"
msgstr "BDE Mitglieder werden" msgstr "BDE Mitglieder werden"
#: apps/registration/forms.py:103 #: apps/registration/forms.py:112
msgid "Join Kfet Club" msgid "Join Kfet Club"
msgstr "Kfet Mitglieder werden" msgstr "Kfet Mitglieder werden"
@ -1900,7 +1914,14 @@ msgstr "Registrierung löschen"
msgid "Validate account" msgid "Validate account"
msgstr "Konto validieren" msgstr "Konto validieren"
#: apps/registration/templates/registration/future_profile_detail.html:64 #: 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:127
#: apps/wei/templates/wei/weimembership_form.html:186 #: apps/wei/templates/wei/weimembership_form.html:186
msgid "Validate registration" msgid "Validate registration"
@ -1956,50 +1977,50 @@ msgstr "Die NoteKfet Team."
msgid "Register new user" msgid "Register new user"
msgstr "Neuen User registrieren" msgstr "Neuen User registrieren"
#: apps/registration/views.py:85 #: apps/registration/views.py:93
msgid "Email validation" msgid "Email validation"
msgstr "Email validierung" msgstr "Email validierung"
#: apps/registration/views.py:87 #: apps/registration/views.py:95
msgid "Validate email" msgid "Validate email"
msgstr "Email validieren" msgstr "Email validieren"
#: apps/registration/views.py:129 #: apps/registration/views.py:137
msgid "Email validation unsuccessful" msgid "Email validation unsuccessful"
msgstr "Email validierung unerfolgreich" msgstr "Email validierung unerfolgreich"
#: apps/registration/views.py:140 #: apps/registration/views.py:148
msgid "Email validation email sent" msgid "Email validation email sent"
msgstr "Validierungsemail wurde gesendet" msgstr "Validierungsemail wurde gesendet"
#: apps/registration/views.py:148 #: apps/registration/views.py:156
msgid "Resend email validation link" msgid "Resend email validation link"
msgstr "E-Mail-Validierungslink erneut senden" msgstr "E-Mail-Validierungslink erneut senden"
#: apps/registration/views.py:166 #: apps/registration/views.py:174
msgid "Pre-registered users list" msgid "Pre-registered users list"
msgstr "Vorregistrierte Userliste" msgstr "Vorregistrierte Userliste"
#: apps/registration/views.py:190 #: apps/registration/views.py:198
msgid "Unregistered users" msgid "Unregistered users"
msgstr "Unregistrierte Users" msgstr "Unregistrierte Users"
#: apps/registration/views.py:203 #: apps/registration/views.py:211
msgid "Registration detail" msgid "Registration detail"
msgstr "Registrierung Detailen" msgstr "Registrierung Detailen"
#: apps/registration/views.py:263 #: apps/registration/views.py:273
msgid "You must join the BDE." msgid "You must join the BDE."
msgstr "Sie müssen die BDE beitreten." msgstr "Sie müssen die BDE beitreten."
#: apps/registration/views.py:287 #: apps/registration/views.py:297
msgid "" msgid ""
"The entered amount is not enough for the memberships, should be at least {}" "The entered amount is not enough for the memberships, should be at least {}"
msgstr "" msgstr ""
"Der eingegebene Betrag reicht für die Mitgliedschaft nicht aus, sollte " "Der eingegebene Betrag reicht für die Mitgliedschaft nicht aus, sollte "
"mindestens {} betragen" "mindestens {} betragen"
#: apps/registration/views.py:367 #: apps/registration/views.py:384
msgid "Invalidate pre-registration" msgid "Invalidate pre-registration"
msgstr "Ungültige Vorregistrierung" msgstr "Ungültige Vorregistrierung"
@ -2145,7 +2166,7 @@ msgstr "spezielle Transaktion Proxies"
msgid "credit transaction" msgid "credit transaction"
msgstr "Kredit Transaktion" msgstr "Kredit Transaktion"
#: apps/treasury/models.py:369 #: apps/treasury/models.py:374
msgid "" msgid ""
"This user doesn't have enough money to pay the memberships with its note. " "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." "Please ask her/him to credit the note before invalidating this credit."
@ -2153,16 +2174,16 @@ msgstr ""
"Dieser Benutzer hat nicht genug Geld, um die Mitgliedschaften mit seiner " "Dieser Benutzer hat nicht genug Geld, um die Mitgliedschaften mit seiner "
"Note zu bezahlen." "Note zu bezahlen."
#: apps/treasury/models.py:384 #: apps/treasury/models.py:389
#: apps/treasury/templates/treasury/sogecredit_detail.html:10 #: apps/treasury/templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale" msgid "Credit from the Société générale"
msgstr "Kredit von der Société générale" msgstr "Kredit von der Société générale"
#: apps/treasury/models.py:385 #: apps/treasury/models.py:390
msgid "Credits from the Société générale" msgid "Credits from the Société générale"
msgstr "Krediten von der Société générale" msgstr "Krediten von der Société générale"
#: apps/treasury/models.py:388 #: apps/treasury/models.py:393
#, python-brace-format #, python-brace-format
msgid "Soge credit for {user}" msgid "Soge credit for {user}"
msgstr "Kredit von der Société générale für {user}" msgstr "Kredit von der Société générale für {user}"
@ -2941,19 +2962,19 @@ msgstr "Überprüfen Sie die WEI-Registrierung"
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "Dieser User hat seine / ihre Vorsicht nicht überprüft." msgstr "Dieser User hat seine / ihre Vorsicht nicht überprüft."
#: note_kfet/settings/base.py:155 #: note_kfet/settings/base.py:157
msgid "German" msgid "German"
msgstr "Deutsch" msgstr "Deutsch"
#: note_kfet/settings/base.py:156 #: note_kfet/settings/base.py:158
msgid "English" msgid "English"
msgstr "English" msgstr "English"
#: note_kfet/settings/base.py:157 #: note_kfet/settings/base.py:159
msgid "Spanish" msgid "Spanish"
msgstr "Spanisch" msgstr "Spanisch"
#: note_kfet/settings/base.py:158 #: note_kfet/settings/base.py:160
msgid "French" msgid "French"
msgstr "Französich" msgstr "Französich"
@ -3040,7 +3061,7 @@ msgstr "Abmelden"
#: note_kfet/templates/base.html:139 #: note_kfet/templates/base.html:139
#: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:6
#: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:11
#: note_kfet/templates/registration/signup.html:27 #: note_kfet/templates/registration/signup.html:28
msgid "Sign up" msgid "Sign up"
msgstr "Registrieren" msgstr "Registrieren"
@ -3052,7 +3073,17 @@ msgstr "Registrieren"
msgid "Log in" msgid "Log in"
msgstr "Anmelden" msgstr "Anmelden"
#: note_kfet/templates/base.html:158 #: note_kfet/templates/base.html:156
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:160
msgid "You are not a Kfet member, so you can't use your note account."
msgstr ""
#: note_kfet/templates/base.html:166
msgid "" msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click " "Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link." "on the validation link."
@ -3060,7 +3091,16 @@ msgstr ""
"Ihre E-Mail-Adresse ist nicht validiert. Bitte überprüfen Sie Ihren " "Ihre E-Mail-Adresse ist nicht validiert. Bitte überprüfen Sie Ihren "
"Posteingang und klicken Sie auf den Validierungslink." "Posteingang und klicken Sie auf den Validierungslink."
#: note_kfet/templates/base.html:175 #: 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 "
"registration bonus of 80 € is not credited and the membership is 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" msgid "Contact us"
msgstr "Kontakt" msgstr "Kontakt"
@ -3072,21 +3112,6 @@ msgstr "Suche nach Attributen wie Name…"
msgid "There is no results." msgid "There is no results."
msgstr "Es gibt keine Ergebnisse." msgstr "Es gibt keine Ergebnisse."
#: note_kfet/templates/cas_server/base.html:7
msgid "Central Authentication Service"
msgstr "Central Authentication Service"
#: note_kfet/templates/cas_server/base.html:43
#, python-format
msgid ""
"A new version of the application is available. This instance runs "
"%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
"upgrading."
msgstr ""
"Eine neue Version der Anwendung ist verfügbar. Diese Instanz führt "
"%(VERSION) s aus und die letzte Version ist %(LAST_VERSION) s. Bitte erwägen "
"Sie ein Upgrade."
#: note_kfet/templates/registration/logged_out.html:13 #: note_kfet/templates/registration/logged_out.html:13
msgid "Thanks for spending some quality time with the Web site today." msgid "Thanks for spending some quality time with the Web site today."
msgstr "" msgstr ""
@ -3200,5 +3225,18 @@ msgstr ""
"müssen Ihre E-Mail-Adresse auch überprüfen, indem Sie dem Link folgen, den " "müssen Ihre E-Mail-Adresse auch überprüfen, indem Sie dem Link folgen, den "
"Sie erhalten haben." "Sie erhalten haben."
#~ msgid "Central Authentication Service"
#~ msgstr "Central Authentication Service"
#, python-format
#~ msgid ""
#~ "A new version of the application is available. This instance runs "
#~ "%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
#~ "upgrading."
#~ msgstr ""
#~ "Eine neue Version der Anwendung ist verfügbar. Diese Instanz führt "
#~ "%(VERSION) s aus und die letzte Version ist %(LAST_VERSION) s. Bitte "
#~ "erwägen Sie ein Upgrade."
#~ msgid "Check this case is the Société Générale paid the inscription." #~ msgid "Check this case is the Société Générale paid the inscription."
#~ msgstr "Die Société Générale die Mitgliedschaft bezahlt." #~ msgstr "Die Société Générale die Mitgliedschaft bezahlt."

View File

@ -51,9 +51,9 @@ msgstr "Usted no puede invitar más de 3 persona a esta actividad."
#: apps/member/models.py:199 #: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4 #: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4 #: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:260 apps/note/models/transactions.py:26 #: apps/note/models/notes.py:232 apps/note/models/transactions.py:26
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:297 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:300
#: apps/permission/models.py:330 #: apps/permission/models.py:333
#: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118 #: apps/wei/models.py:66 apps/wei/models.py:118
#: apps/wei/templates/wei/base.html:26 #: apps/wei/templates/wei/base.html:26
@ -89,8 +89,8 @@ msgstr "tipos de actividad"
#: apps/activity/models.py:68 #: apps/activity/models.py:68
#: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/activity/templates/activity/includes/activity_info.html:19
#: apps/note/models/transactions.py:81 apps/permission/models.py:110 #: apps/note/models/transactions.py:81 apps/permission/models.py:113
#: apps/permission/models.py:189 apps/wei/models.py:72 apps/wei/models.py:129 #: apps/permission/models.py:192 apps/wei/models.py:72 apps/wei/models.py:129
msgid "description" msgid "description"
msgstr "descripción" msgstr "descripción"
@ -104,8 +104,8 @@ msgstr "Lugar donde se organiza la actividad, por ejemplo la Kfet."
#: apps/activity/models.py:83 #: apps/activity/models.py:83
#: apps/activity/templates/activity/includes/activity_info.html:22 #: apps/activity/templates/activity/includes/activity_info.html:22
#: apps/note/models/notes.py:236 apps/note/models/transactions.py:66 #: apps/note/models/notes.py:208 apps/note/models/transactions.py:66
#: apps/permission/models.py:164 #: apps/permission/models.py:167
msgid "type" msgid "type"
msgstr "tipo" msgstr "tipo"
@ -253,15 +253,15 @@ msgstr "quitar"
msgid "Type" msgid "Type"
msgstr "Tipo" msgstr "Tipo"
#: apps/activity/tables.py:82 apps/member/forms.py:185 #: apps/activity/tables.py:82 apps/member/forms.py:186
#: apps/registration/forms.py:81 apps/treasury/forms.py:130 #: apps/registration/forms.py:90 apps/treasury/forms.py:130
#: apps/wei/forms/registration.py:96 #: apps/wei/forms/registration.py:96
msgid "Last name" msgid "Last name"
msgstr "Apellido" msgstr "Apellido"
#: apps/activity/tables.py:84 apps/member/forms.py:190 #: apps/activity/tables.py:84 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:134 #: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:86 apps/treasury/forms.py:132 #: apps/registration/forms.py:95 apps/treasury/forms.py:132
#: apps/wei/forms/registration.py:101 #: apps/wei/forms/registration.py:101
msgid "First name" msgid "First name"
msgstr "Nombre" msgstr "Nombre"
@ -285,7 +285,7 @@ msgid "Guest deleted"
msgstr "Lista de los invitados" msgstr "Lista de los invitados"
#: apps/activity/templates/activity/activity_entry.html:14 #: apps/activity/templates/activity/activity_entry.html:14
#: apps/note/models/transactions.py:253 #: apps/note/models/transactions.py:256
#: apps/note/templates/note/transaction_form.html:16 #: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148 #: apps/note/templates/note/transaction_form.html:148
#: note_kfet/templates/base.html:73 #: note_kfet/templates/base.html:73
@ -293,13 +293,13 @@ msgid "Transfer"
msgstr "Transferencia" msgstr "Transferencia"
#: apps/activity/templates/activity/activity_entry.html:18 #: apps/activity/templates/activity/activity_entry.html:18
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:21 #: apps/note/templates/note/transaction_form.html:21
msgid "Credit" msgid "Credit"
msgstr "Crédito" msgstr "Crédito"
#: apps/activity/templates/activity/activity_entry.html:21 #: apps/activity/templates/activity/activity_entry.html:21
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:25 #: apps/note/templates/note/transaction_form.html:25
msgid "Debit" msgid "Debit"
msgstr "Débito" msgstr "Débito"
@ -390,41 +390,41 @@ msgstr "modificar"
msgid "Invite" msgid "Invite"
msgstr "Invitar" msgstr "Invitar"
#: apps/activity/views.py:34 #: apps/activity/views.py:36
msgid "Create new activity" msgid "Create new activity"
msgstr "Crear una nueva actividad" msgstr "Crear una nueva actividad"
#: apps/activity/views.py:65 note_kfet/templates/base.html:91 #: apps/activity/views.py:67 note_kfet/templates/base.html:91
msgid "Activities" msgid "Activities"
msgstr "Actividades" msgstr "Actividades"
#: apps/activity/views.py:93 #: apps/activity/views.py:95
msgid "Activity detail" msgid "Activity detail"
msgstr "Detalles de la actividad" msgstr "Detalles de la actividad"
#: apps/activity/views.py:113 #: apps/activity/views.py:115
msgid "Update activity" msgid "Update activity"
msgstr "Modificar la actividad" msgstr "Modificar la actividad"
#: apps/activity/views.py:140 #: apps/activity/views.py:142
msgid "Invite guest to the activity \"{}\"" msgid "Invite guest to the activity \"{}\""
msgstr "Invitar alguien para la actividad \"{}\"" msgstr "Invitar alguien para la actividad \"{}\""
#: apps/activity/views.py:175 #: apps/activity/views.py:177
msgid "You are not allowed to display the entry interface for this activity." msgid "You are not allowed to display the entry interface for this activity."
msgstr "" msgstr ""
"Usted no tiene derecho a mostrar la interfaz de las entradas para esta " "Usted no tiene derecho a mostrar la interfaz de las entradas para esta "
"actividad." "actividad."
#: apps/activity/views.py:178 #: apps/activity/views.py:180
msgid "This activity does not support activity entries." msgid "This activity does not support activity entries."
msgstr "Esta actividad no necesita entradas." msgstr "Esta actividad no necesita entradas."
#: apps/activity/views.py:181 #: apps/activity/views.py:183
msgid "This activity is closed." msgid "This activity is closed."
msgstr "Esta actividad esta cerrada." msgstr "Esta actividad esta cerrada."
#: apps/activity/views.py:277 #: apps/activity/views.py:279
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "Entradas para la actividad \"{}\"" msgstr "Entradas para la actividad \"{}\""
@ -440,7 +440,7 @@ msgstr "Logs"
msgid "IP Address" msgid "IP Address"
msgstr "Dirección IP" msgstr "Dirección IP"
#: apps/logs/models.py:36 apps/permission/models.py:134 #: apps/logs/models.py:36 apps/permission/models.py:137
msgid "model" msgid "model"
msgstr "modelo" msgstr "modelo"
@ -461,7 +461,7 @@ msgid "create"
msgstr "crear" msgstr "crear"
#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201 #: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
#: apps/permission/models.py:127 apps/treasury/tables.py:38 #: apps/permission/models.py:130 apps/treasury/tables.py:38
#: apps/wei/tables.py:75 #: apps/wei/tables.py:75
msgid "delete" msgid "delete"
msgstr "suprimir" msgstr "suprimir"
@ -542,48 +542,48 @@ msgid "This image cannot be loaded."
msgstr "Esta imagen no puede ser cargada." msgstr "Esta imagen no puede ser cargada."
#: apps/member/forms.py:141 apps/member/views.py:100 #: apps/member/forms.py:141 apps/member/views.py:100
#: apps/registration/forms.py:33 apps/registration/views.py:244 #: apps/registration/forms.py:33 apps/registration/views.py:254
msgid "An alias with a similar name already exists." msgid "An alias with a similar name already exists."
msgstr "Un alias similar ya existe." msgstr "Un alias similar ya existe."
#: apps/member/forms.py:164 apps/registration/forms.py:61 #: apps/member/forms.py:165 apps/registration/forms.py:70
msgid "Inscription paid by Société Générale" msgid "Inscription paid by Société Générale"
msgstr "Registración pagadas por Société Générale" msgstr "Registración pagadas por Société Générale"
#: apps/member/forms.py:166 apps/registration/forms.py:63 #: apps/member/forms.py:167 apps/registration/forms.py:72
msgid "Check this case if the Société Générale paid the inscription." 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." msgstr "Marcar esta casilla si Société Générale pagó la registración."
#: apps/member/forms.py:171 apps/registration/forms.py:68 #: apps/member/forms.py:172 apps/registration/forms.py:77
#: apps/wei/forms/registration.py:83 #: apps/wei/forms/registration.py:83
msgid "Credit type" msgid "Credit type"
msgstr "Tipo de crédito" msgstr "Tipo de crédito"
#: apps/member/forms.py:172 apps/registration/forms.py:69 #: apps/member/forms.py:173 apps/registration/forms.py:78
#: apps/wei/forms/registration.py:84 #: apps/wei/forms/registration.py:84
msgid "No credit" msgid "No credit"
msgstr "No crédito" msgstr "No crédito"
#: apps/member/forms.py:174 #: apps/member/forms.py:175
msgid "You can credit the note of the user." msgid "You can credit the note of the user."
msgstr "Usted puede acreditar la note del usuario." msgstr "Usted puede acreditar la note del usuario."
#: apps/member/forms.py:178 apps/registration/forms.py:74 #: apps/member/forms.py:179 apps/registration/forms.py:83
#: apps/wei/forms/registration.py:89 #: apps/wei/forms/registration.py:89
msgid "Credit amount" msgid "Credit amount"
msgstr "Valor del crédito" msgstr "Valor del crédito"
#: apps/member/forms.py:195 apps/note/templates/note/transaction_form.html:140 #: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:91 apps/treasury/forms.py:134 #: apps/registration/forms.py:100 apps/treasury/forms.py:134
#: apps/wei/forms/registration.py:106 #: apps/wei/forms/registration.py:106
msgid "Bank" msgid "Bank"
msgstr "Banco" msgstr "Banco"
#: apps/member/forms.py:222 #: apps/member/forms.py:223
msgid "User" msgid "User"
msgstr "Usuario" msgstr "Usuario"
#: apps/member/forms.py:236 #: apps/member/forms.py:237
msgid "Roles" msgid "Roles"
msgstr "Papeles" msgstr "Papeles"
@ -810,7 +810,7 @@ msgstr ""
"prorrogarla." "prorrogarla."
#: apps/member/models.py:286 apps/member/models.py:311 #: apps/member/models.py:286 apps/member/models.py:311
#: apps/note/models/notes.py:191 #: apps/note/models/notes.py:177
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -831,11 +831,11 @@ msgstr "afiliación termina el"
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "El papel {role} no se encuentra en el club {club}." msgstr "El papel {role} no se encuentra en el club {club}."
#: apps/member/models.py:430 apps/member/views.py:634 #: apps/member/models.py:430 apps/member/views.py:646
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "Usuario ya esta un miembro del club" msgstr "Usuario ya esta un miembro del club"
#: apps/member/models.py:442 apps/member/views.py:644 #: apps/member/models.py:442 apps/member/views.py:656
msgid "User is not a member of the parent club" msgid "User is not a member of the parent club"
msgstr "Usuario no es un miembro del club pariente" msgstr "Usuario no es un miembro del club pariente"
@ -844,7 +844,7 @@ msgstr "Usuario no es un miembro del club pariente"
msgid "Membership of {user} for the club {club}" msgid "Membership of {user} for the club {club}"
msgstr "Afiliación of {user} for the club {club}" msgstr "Afiliación of {user} for the club {club}"
#: apps/member/models.py:498 apps/note/models/transactions.py:355 #: apps/member/models.py:498 apps/note/models/transactions.py:358
msgid "membership" msgid "membership"
msgstr "afiliación" msgstr "afiliación"
@ -960,8 +960,8 @@ msgstr ""
"nuevo posibles." "nuevo posibles."
#: apps/member/templates/member/club_alias.html:10 #: apps/member/templates/member/club_alias.html:10
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:238 #: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:245
#: apps/member/views.py:436 #: apps/member/views.py:448
msgid "Note aliases" msgid "Note aliases"
msgstr "Alias de la note" msgstr "Alias de la note"
@ -1025,7 +1025,7 @@ msgstr "saldo de la cuenta"
#: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/club_info.html:47
#: apps/member/templates/member/includes/profile_info.html:20 #: apps/member/templates/member/includes/profile_info.html:20
#: apps/note/models/notes.py:283 apps/wei/templates/wei/base.html:66 #: apps/note/models/notes.py:255 apps/wei/templates/wei/base.html:66
msgid "aliases" msgid "aliases"
msgstr "alias" msgstr "alias"
@ -1104,39 +1104,39 @@ msgstr "Este correo tiene que ser valido."
msgid "Profile detail" msgid "Profile detail"
msgstr "Detalles del usuario" msgstr "Detalles del usuario"
#: apps/member/views.py:197 #: apps/member/views.py:204
msgid "Search user" msgid "Search user"
msgstr "Buscar un usuario" msgstr "Buscar un usuario"
#: apps/member/views.py:258 #: apps/member/views.py:265
msgid "Update note picture" msgid "Update note picture"
msgstr "Modificar la imagen de la note" msgstr "Modificar la imagen de la note"
#: apps/member/views.py:304 #: apps/member/views.py:311
msgid "Manage auth token" msgid "Manage auth token"
msgstr "Gestionar los token de autentificación" msgstr "Gestionar los token de autentificación"
#: apps/member/views.py:331 #: apps/member/views.py:338
msgid "Create new club" msgid "Create new club"
msgstr "Crear un nuevo club" msgstr "Crear un nuevo club"
#: apps/member/views.py:350 #: apps/member/views.py:357
msgid "Search club" msgid "Search club"
msgstr "Buscar un club" msgstr "Buscar un club"
#: apps/member/views.py:383 #: apps/member/views.py:390
msgid "Club detail" msgid "Club detail"
msgstr "Detalles del club" msgstr "Detalles del club"
#: apps/member/views.py:459 #: apps/member/views.py:471
msgid "Update club" msgid "Update club"
msgstr "Modificar el club" msgstr "Modificar el club"
#: apps/member/views.py:493 #: apps/member/views.py:505
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "Añadir un nuevo miembro al club" msgstr "Añadir un nuevo miembro al club"
#: apps/member/views.py:625 apps/wei/views.py:928 #: apps/member/views.py:637 apps/wei/views.py:928
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
@ -1144,25 +1144,25 @@ msgstr ""
"Este usuario no tiene suficiente dinero para unirse a este club, y no puede " "Este usuario no tiene suficiente dinero para unirse a este club, y no puede "
"tener un saldo negativo." "tener un saldo negativo."
#: apps/member/views.py:648 #: apps/member/views.py:660
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "La afiliación tiene que empezar después del {:%d-%m-%Y}." msgstr "La afiliación tiene que empezar después del {:%d-%m-%Y}."
#: apps/member/views.py:653 #: apps/member/views.py:665
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "La afiliación tiene que empezar antes del {:%d-%m-%Y}." msgstr "La afiliación tiene que empezar antes del {:%d-%m-%Y}."
#: apps/member/views.py:660 apps/member/views.py:662 apps/member/views.py:664 #: apps/member/views.py:672 apps/member/views.py:674 apps/member/views.py:676
#: apps/registration/views.py:294 apps/registration/views.py:296 #: apps/registration/views.py:304 apps/registration/views.py:306
#: apps/registration/views.py:298 apps/wei/views.py:933 apps/wei/views.py:937 #: apps/registration/views.py:308 apps/wei/views.py:933 apps/wei/views.py:937
msgid "This field is required." msgid "This field is required."
msgstr "Este campo es obligatorio." msgstr "Este campo es obligatorio."
#: apps/member/views.py:800 #: apps/member/views.py:816
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "Gestionar los papeles de un usuario en el club" msgstr "Gestionar los papeles de un usuario en el club"
#: apps/member/views.py:825 #: apps/member/views.py:841
msgid "Members of the club" msgid "Members of the club"
msgstr "Miembros del club" msgstr "Miembros del club"
@ -1181,7 +1181,7 @@ msgid "amount"
msgstr "monto" msgstr "monto"
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189 #: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
#: apps/note/models/transactions.py:224 #: apps/note/models/transactions.py:227
msgid "" msgid ""
"The transaction can't be saved since the source note or the destination note " "The transaction can't be saved since the source note or the destination note "
"is not active." "is not active."
@ -1291,51 +1291,51 @@ msgstr "notes de los usuarios"
msgid "%(user)s's note" msgid "%(user)s's note"
msgstr "Note de %(user)s" msgstr "Note de %(user)s"
#: apps/note/models/notes.py:195 #: apps/note/models/notes.py:181
msgid "club note" msgid "club note"
msgstr "note de un club" msgstr "note de un club"
#: apps/note/models/notes.py:196 #: apps/note/models/notes.py:182
msgid "clubs notes" msgid "clubs notes"
msgstr "notes de los clubs" msgstr "notes de los clubs"
#: apps/note/models/notes.py:202 #: apps/note/models/notes.py:188
#, python-format #, python-format
msgid "Note of %(club)s club" msgid "Note of %(club)s club"
msgstr "Note del club %(club)s" msgstr "Note del club %(club)s"
#: apps/note/models/notes.py:242 #: apps/note/models/notes.py:214
msgid "special note" msgid "special note"
msgstr "note especial" msgstr "note especial"
#: apps/note/models/notes.py:243 #: apps/note/models/notes.py:215
msgid "special notes" msgid "special notes"
msgstr "notes especiales" msgstr "notes especiales"
#: apps/note/models/notes.py:266 #: apps/note/models/notes.py:238
msgid "Invalid alias" msgid "Invalid alias"
msgstr "Alias inválido" msgstr "Alias inválido"
#: apps/note/models/notes.py:282 #: apps/note/models/notes.py:254
msgid "alias" msgid "alias"
msgstr "alias" msgstr "alias"
#: apps/note/models/notes.py:306 #: apps/note/models/notes.py:278
msgid "Alias is too long." msgid "Alias is too long."
msgstr "El alias es demasiado largo." msgstr "El alias es demasiado largo."
#: apps/note/models/notes.py:309 #: apps/note/models/notes.py:281
msgid "" msgid ""
"This alias contains only complex character. Please use a more simple alias." "This alias contains only complex character. Please use a more simple alias."
msgstr "" msgstr ""
"Este alias solo contiene caracteres complejos. Por favor usa un alias más " "Este alias solo contiene caracteres complejos. Por favor usa un alias más "
"sencillo." "sencillo."
#: apps/note/models/notes.py:313 #: apps/note/models/notes.py:285
msgid "An alias with a similar name already exists: {} " msgid "An alias with a similar name already exists: {} "
msgstr "Un alias parecido ya existe : {} " msgstr "Un alias parecido ya existe : {} "
#: apps/note/models/notes.py:327 #: apps/note/models/notes.py:299
msgid "You can't delete your main alias." msgid "You can't delete your main alias."
msgstr "No puede suprimir su alias principal." msgstr "No puede suprimir su alias principal."
@ -1410,33 +1410,33 @@ msgstr ""
"El saldo de la note tiene que ser entre - 92 233 720 368 547 758.08 € y 92 " "El saldo de la note tiene que ser entre - 92 233 720 368 547 758.08 € y 92 "
"233 720 368 547 758.07 €." "233 720 368 547 758.07 €."
#: apps/note/models/transactions.py:273 #: apps/note/models/transactions.py:276
msgid "" msgid ""
"The destination of this transaction must equal to the destination of the " "The destination of this transaction must equal to the destination of the "
"template." "template."
msgstr "" msgstr ""
#: apps/note/models/transactions.py:283 #: apps/note/models/transactions.py:286
msgid "Template" msgid "Template"
msgstr "" msgstr ""
#: apps/note/models/transactions.py:286 #: apps/note/models/transactions.py:289
msgid "recurrent transaction" msgid "recurrent transaction"
msgstr "" msgstr ""
#: apps/note/models/transactions.py:287 #: apps/note/models/transactions.py:290
msgid "recurrent transactions" msgid "recurrent transactions"
msgstr "" msgstr ""
#: apps/note/models/transactions.py:302 #: apps/note/models/transactions.py:305
msgid "first_name" msgid "first_name"
msgstr "nombre" msgstr "nombre"
#: apps/note/models/transactions.py:307 #: apps/note/models/transactions.py:310
msgid "bank" msgid "bank"
msgstr "banco" msgstr "banco"
#: apps/note/models/transactions.py:324 #: apps/note/models/transactions.py:327
msgid "" msgid ""
"A special transaction is only possible between a Note associated to a " "A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club" "payment method and a User or a Club"
@ -1444,19 +1444,19 @@ msgstr ""
"Una transacción especial solo esta disponible entre una note de un modo de " "Una transacción especial solo esta disponible entre una note de un modo de "
"pago y un usuario o un club" "pago y un usuario o un club"
#: apps/note/models/transactions.py:333 #: apps/note/models/transactions.py:336
msgid "Special transaction" msgid "Special transaction"
msgstr "Transacción especial" msgstr "Transacción especial"
#: apps/note/models/transactions.py:334 #: apps/note/models/transactions.py:337
msgid "Special transactions" msgid "Special transactions"
msgstr "Transacciones especiales" msgstr "Transacciones especiales"
#: apps/note/models/transactions.py:350 #: apps/note/models/transactions.py:353
msgid "membership transaction" msgid "membership transaction"
msgstr "transacción de afiliación" msgstr "transacción de afiliación"
#: apps/note/models/transactions.py:351 apps/treasury/models.py:284 #: apps/note/models/transactions.py:354 apps/treasury/models.py:284
msgid "membership transactions" msgid "membership transactions"
msgstr "transacciones de afiliación" msgstr "transacciones de afiliación"
@ -1646,53 +1646,53 @@ msgstr "Usted no puede ver ningún botón."
msgid "Search transactions" msgid "Search transactions"
msgstr "Buscar transacciones" msgstr "Buscar transacciones"
#: apps/permission/models.py:89 #: apps/permission/models.py:92
#, python-brace-format #, python-brace-format
msgid "Can {type} {model}.{field} in {query}" msgid "Can {type} {model}.{field} in {query}"
msgstr "" msgstr ""
#: apps/permission/models.py:91 #: apps/permission/models.py:94
#, python-brace-format #, python-brace-format
msgid "Can {type} {model} in {query}" msgid "Can {type} {model} in {query}"
msgstr "" msgstr ""
#: apps/permission/models.py:104 #: apps/permission/models.py:107
msgid "rank" msgid "rank"
msgstr "posición" msgstr "posición"
#: apps/permission/models.py:117 #: apps/permission/models.py:120
msgid "permission mask" msgid "permission mask"
msgstr "antifaz de permisos" msgstr "antifaz de permisos"
#: apps/permission/models.py:118 #: apps/permission/models.py:121
msgid "permission masks" msgid "permission masks"
msgstr "antifaces de permisos" msgstr "antifaces de permisos"
#: apps/permission/models.py:124 #: apps/permission/models.py:127
msgid "add" msgid "add"
msgstr "añadir" msgstr "añadir"
#: apps/permission/models.py:125 #: apps/permission/models.py:128
msgid "view" msgid "view"
msgstr "ver" msgstr "ver"
#: apps/permission/models.py:126 #: apps/permission/models.py:129
msgid "change" msgid "change"
msgstr "cambiar" msgstr "cambiar"
#: apps/permission/models.py:158 #: apps/permission/models.py:161
msgid "query" msgid "query"
msgstr "consulta" msgstr "consulta"
#: apps/permission/models.py:171 #: apps/permission/models.py:174
msgid "mask" msgid "mask"
msgstr "antifaz" msgstr "antifaz"
#: apps/permission/models.py:177 #: apps/permission/models.py:180
msgid "field" msgid "field"
msgstr "campo" msgstr "campo"
#: apps/permission/models.py:182 #: apps/permission/models.py:185
msgid "" msgid ""
"Tells if the permission should be granted even if the membership of the user " "Tells if the permission should be granted even if the membership of the user "
"is expired." "is expired."
@ -1700,30 +1700,30 @@ msgstr ""
"Indica si el permiso tiene que ser dado aunque la afiliación del usuario " "Indica si el permiso tiene que ser dado aunque la afiliación del usuario "
"terminó." "terminó."
#: apps/permission/models.py:183 #: apps/permission/models.py:186
#: apps/permission/templates/permission/all_rights.html:89 #: apps/permission/templates/permission/all_rights.html:89
msgid "permanent" msgid "permanent"
msgstr "permanente" msgstr "permanente"
#: apps/permission/models.py:194 #: apps/permission/models.py:197
msgid "permission" msgid "permission"
msgstr "permiso" msgstr "permiso"
#: apps/permission/models.py:195 apps/permission/models.py:335 #: apps/permission/models.py:198 apps/permission/models.py:338
msgid "permissions" msgid "permissions"
msgstr "permisos" msgstr "permisos"
#: apps/permission/models.py:200 #: apps/permission/models.py:203
msgid "Specifying field applies only to view and change permission types." msgid "Specifying field applies only to view and change permission types."
msgstr "" msgstr ""
"Especifica el campo interesado, solo funciona para los permisos view y " "Especifica el campo interesado, solo funciona para los permisos view y "
"change." "change."
#: apps/permission/models.py:340 #: apps/permission/models.py:343
msgid "for club" msgid "for club"
msgstr "interesa el club" msgstr "interesa el club"
#: apps/permission/models.py:350 apps/permission/models.py:351 #: apps/permission/models.py:353 apps/permission/models.py:354
msgid "role permissions" msgid "role permissions"
msgstr "permisos por papeles" msgstr "permisos por papeles"
@ -1827,10 +1827,24 @@ msgid "This email address is already used."
msgstr "Este correo electrónico ya esta utilizado." msgstr "Este correo electrónico ya esta utilizado."
#: apps/registration/forms.py:49 #: 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 a bank account in the Société générale with the BDE "
"partnership."
msgstr "Usted ya abrió una cuenta a la Société Générale."
#: apps/registration/forms.py:50
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:58
msgid "Register to the WEI" msgid "Register to the WEI"
msgstr "Registrarse en el WEI" msgstr "Registrarse en el WEI"
#: apps/registration/forms.py:51 #: apps/registration/forms.py:60
msgid "" msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you " "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." "will be able to register later, after validating your account in the Kfet."
@ -1838,11 +1852,11 @@ msgstr ""
"Marcar esta casilla si usted quiere registrarse en el WEI. Si duda, podrá " "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." "registrarse más tarde, después de validar su cuenta Note Kfet."
#: apps/registration/forms.py:96 #: apps/registration/forms.py:105
msgid "Join BDE Club" msgid "Join BDE Club"
msgstr "Afiliarse al club BDE" msgstr "Afiliarse al club BDE"
#: apps/registration/forms.py:103 #: apps/registration/forms.py:112
msgid "Join Kfet Club" msgid "Join Kfet Club"
msgstr "Afiliarse al club Kfet" msgstr "Afiliarse al club Kfet"
@ -1894,7 +1908,14 @@ msgstr "Suprimir afiliación"
msgid "Validate account" msgid "Validate account"
msgstr "Validar la cuenta" msgstr "Validar la cuenta"
#: apps/registration/templates/registration/future_profile_detail.html:64 #: 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 "Usted 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:127
#: apps/wei/templates/wei/weimembership_form.html:186 #: apps/wei/templates/wei/weimembership_form.html:186
msgid "Validate registration" msgid "Validate registration"
@ -1950,50 +1971,50 @@ msgstr "El equipo Note Kfet."
msgid "Register new user" msgid "Register new user"
msgstr "Registrar un nuevo usuario" msgstr "Registrar un nuevo usuario"
#: apps/registration/views.py:85 #: apps/registration/views.py:93
msgid "Email validation" msgid "Email validation"
msgstr "Validación del correo electrónico" msgstr "Validación del correo electrónico"
#: apps/registration/views.py:87 #: apps/registration/views.py:95
msgid "Validate email" msgid "Validate email"
msgstr "Validar el correo electrónico" msgstr "Validar el correo electrónico"
#: apps/registration/views.py:129 #: apps/registration/views.py:137
msgid "Email validation unsuccessful" msgid "Email validation unsuccessful"
msgstr "La validación del correo electrónico fracasó" msgstr "La validación del correo electrónico fracasó"
#: apps/registration/views.py:140 #: apps/registration/views.py:148
msgid "Email validation email sent" msgid "Email validation email sent"
msgstr "Correo de validación enviado" msgstr "Correo de validación enviado"
#: apps/registration/views.py:148 #: apps/registration/views.py:156
msgid "Resend email validation link" msgid "Resend email validation link"
msgstr "Reenviar el enlace de validación" msgstr "Reenviar el enlace de validación"
#: apps/registration/views.py:166 #: apps/registration/views.py:174
msgid "Pre-registered users list" msgid "Pre-registered users list"
msgstr "Lista de los usuarios con afiliación pendiente" msgstr "Lista de los usuarios con afiliación pendiente"
#: apps/registration/views.py:190 #: apps/registration/views.py:198
msgid "Unregistered users" msgid "Unregistered users"
msgstr "Usuarios con afiliación pendiente" msgstr "Usuarios con afiliación pendiente"
#: apps/registration/views.py:203 #: apps/registration/views.py:211
msgid "Registration detail" msgid "Registration detail"
msgstr "Detalles de la afiliación" msgstr "Detalles de la afiliación"
#: apps/registration/views.py:263 #: apps/registration/views.py:273
msgid "You must join the BDE." msgid "You must join the BDE."
msgstr "Usted tiene que afiliarse al BDE." msgstr "Usted tiene que afiliarse al BDE."
#: apps/registration/views.py:287 #: apps/registration/views.py:297
msgid "" msgid ""
"The entered amount is not enough for the memberships, should be at least {}" "The entered amount is not enough for the memberships, should be at least {}"
msgstr "" msgstr ""
"El monto dado no es suficiente para las afiliaciones, tiene que ser al menos " "El monto dado no es suficiente para las afiliaciones, tiene que ser al menos "
"{}" "{}"
#: apps/registration/views.py:367 #: apps/registration/views.py:384
msgid "Invalidate pre-registration" msgid "Invalidate pre-registration"
msgstr "Invalidar la afiliación" msgstr "Invalidar la afiliación"
@ -2139,7 +2160,7 @@ msgstr "proxys de transacciones especiales"
msgid "credit transaction" msgid "credit transaction"
msgstr "transacción de crédito" msgstr "transacción de crédito"
#: apps/treasury/models.py:369 #: apps/treasury/models.py:374
msgid "" msgid ""
"This user doesn't have enough money to pay the memberships with its note. " "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." "Please ask her/him to credit the note before invalidating this credit."
@ -2148,16 +2169,16 @@ msgstr ""
"afiliaciones. Por favor pídelo acreditar su note antes de invalidar este " "afiliaciones. Por favor pídelo acreditar su note antes de invalidar este "
"crédito." "crédito."
#: apps/treasury/models.py:384 #: apps/treasury/models.py:389
#: apps/treasury/templates/treasury/sogecredit_detail.html:10 #: apps/treasury/templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale" msgid "Credit from the Société générale"
msgstr "Crédito de la Société Générale" msgstr "Crédito de la Société Générale"
#: apps/treasury/models.py:385 #: apps/treasury/models.py:390
msgid "Credits from the Société générale" msgid "Credits from the Société générale"
msgstr "Créditos de la Société Générale" msgstr "Créditos de la Société Générale"
#: apps/treasury/models.py:388 #: apps/treasury/models.py:393
#, python-brace-format #, python-brace-format
msgid "Soge credit for {user}" msgid "Soge credit for {user}"
msgstr "Crédito de la Société Générale para {user}" msgstr "Crédito de la Société Générale para {user}"
@ -2925,19 +2946,19 @@ msgstr "Validar la inscripción WEI"
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "Este usuario no dio su cheque de garantía." msgstr "Este usuario no dio su cheque de garantía."
#: note_kfet/settings/base.py:155 #: note_kfet/settings/base.py:157
msgid "German" msgid "German"
msgstr "Alemán" msgstr "Alemán"
#: note_kfet/settings/base.py:156 #: note_kfet/settings/base.py:158
msgid "English" msgid "English"
msgstr "Ingles" msgstr "Ingles"
#: note_kfet/settings/base.py:157 #: note_kfet/settings/base.py:159
msgid "Spanish" msgid "Spanish"
msgstr "Español" msgstr "Español"
#: note_kfet/settings/base.py:158 #: note_kfet/settings/base.py:160
msgid "French" msgid "French"
msgstr "Francés" msgstr "Francés"
@ -3022,7 +3043,7 @@ msgstr "Desconectarse"
#: note_kfet/templates/base.html:139 #: note_kfet/templates/base.html:139
#: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:6
#: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:11
#: note_kfet/templates/registration/signup.html:27 #: note_kfet/templates/registration/signup.html:28
msgid "Sign up" msgid "Sign up"
msgstr "Registrar" msgstr "Registrar"
@ -3034,7 +3055,17 @@ msgstr "Registrar"
msgid "Log in" msgid "Log in"
msgstr "Conectarse" msgstr "Conectarse"
#: note_kfet/templates/base.html:158 #: note_kfet/templates/base.html:156
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:160
msgid "You are not a Kfet member, so you can't use your note account."
msgstr ""
#: note_kfet/templates/base.html:166
msgid "" msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click " "Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link." "on the validation link."
@ -3042,7 +3073,16 @@ msgstr ""
"Su correo electrónico no fue validado. Por favor mire en sus correos y haga " "Su correo electrónico no fue validado. Por favor mire en sus correos y haga "
"clic en el enlace de validación." "clic en el enlace de validación."
#: note_kfet/templates/base.html:175 #: 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 "
"registration bonus of 80 € is not credited and the membership is 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" msgid "Contact us"
msgstr "Contactarnos" msgstr "Contactarnos"
@ -3054,20 +3094,6 @@ msgstr "Buscar con atributo, como el nombre…"
msgid "There is no results." msgid "There is no results."
msgstr "No hay resultado." msgstr "No hay resultado."
#: note_kfet/templates/cas_server/base.html:7
msgid "Central Authentication Service"
msgstr "Servicio Central de Autentificación"
#: note_kfet/templates/cas_server/base.html:43
#, python-format
msgid ""
"A new version of the application is available. This instance runs "
"%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
"upgrading."
msgstr ""
"Una nueva versión es disponible. Se está usando %(VERSION)s y la ultima "
"versión está %(LAST_VERSION)s. Piensa en actualizar."
#: note_kfet/templates/registration/logged_out.html:13 #: note_kfet/templates/registration/logged_out.html:13
msgid "Thanks for spending some quality time with the Web site today." msgid "Thanks for spending some quality time with the Web site today."
msgstr "Gracias por usar la Note Kfet." msgstr "Gracias por usar la Note Kfet."
@ -3176,6 +3202,18 @@ msgstr ""
"pagar su afiliación. Tambien tiene que validar su correo electronico con el " "pagar su afiliación. Tambien tiene que validar su correo electronico con el "
"enlace que recibió." "enlace que recibió."
#~ msgid "Central Authentication Service"
#~ msgstr "Servicio Central de Autentificación"
#, python-format
#~ msgid ""
#~ "A new version of the application is available. This instance runs "
#~ "%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
#~ "upgrading."
#~ msgstr ""
#~ "Una nueva versión es disponible. Se está usando %(VERSION)s y la ultima "
#~ "versión está %(LAST_VERSION)s. Piensa en actualizar."
#~ msgid "Check this case is the Société Générale paid the inscription." #~ msgid "Check this case is the Société Générale paid the inscription."
#~ msgstr "Marcar esta casilla si Société Générale pagó la registración." #~ msgstr "Marcar esta casilla si Société Générale pagó la registración."

View File

@ -52,9 +52,9 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/member/models.py:199 #: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4 #: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4 #: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:260 apps/note/models/transactions.py:26 #: apps/note/models/notes.py:232 apps/note/models/transactions.py:26
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:297 #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:300
#: apps/permission/models.py:330 #: apps/permission/models.py:333
#: apps/registration/templates/registration/future_profile_detail.html:16 #: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118 #: apps/wei/models.py:66 apps/wei/models.py:118
#: apps/wei/templates/wei/base.html:26 #: apps/wei/templates/wei/base.html:26
@ -90,8 +90,8 @@ msgstr "types d'activité"
#: apps/activity/models.py:68 #: apps/activity/models.py:68
#: apps/activity/templates/activity/includes/activity_info.html:19 #: apps/activity/templates/activity/includes/activity_info.html:19
#: apps/note/models/transactions.py:81 apps/permission/models.py:110 #: apps/note/models/transactions.py:81 apps/permission/models.py:113
#: apps/permission/models.py:189 apps/wei/models.py:72 apps/wei/models.py:129 #: apps/permission/models.py:192 apps/wei/models.py:72 apps/wei/models.py:129
msgid "description" msgid "description"
msgstr "description" msgstr "description"
@ -105,8 +105,8 @@ msgstr "Lieu où l'activité est organisée, par exemple la Kfet."
#: apps/activity/models.py:83 #: apps/activity/models.py:83
#: apps/activity/templates/activity/includes/activity_info.html:22 #: apps/activity/templates/activity/includes/activity_info.html:22
#: apps/note/models/notes.py:236 apps/note/models/transactions.py:66 #: apps/note/models/notes.py:208 apps/note/models/transactions.py:66
#: apps/permission/models.py:164 #: apps/permission/models.py:167
msgid "type" msgid "type"
msgstr "type" msgstr "type"
@ -254,15 +254,15 @@ msgstr "supprimer"
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#: apps/activity/tables.py:82 apps/member/forms.py:185 #: apps/activity/tables.py:82 apps/member/forms.py:186
#: apps/registration/forms.py:81 apps/treasury/forms.py:130 #: apps/registration/forms.py:90 apps/treasury/forms.py:130
#: apps/wei/forms/registration.py:96 #: apps/wei/forms/registration.py:96
msgid "Last name" msgid "Last name"
msgstr "Nom de famille" msgstr "Nom de famille"
#: apps/activity/tables.py:84 apps/member/forms.py:190 #: apps/activity/tables.py:84 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:134 #: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:86 apps/treasury/forms.py:132 #: apps/registration/forms.py:95 apps/treasury/forms.py:132
#: apps/wei/forms/registration.py:101 #: apps/wei/forms/registration.py:101
msgid "First name" msgid "First name"
msgstr "Prénom" msgstr "Prénom"
@ -284,7 +284,7 @@ msgid "Guest deleted"
msgstr "Invité supprimé" msgstr "Invité supprimé"
#: apps/activity/templates/activity/activity_entry.html:14 #: apps/activity/templates/activity/activity_entry.html:14
#: apps/note/models/transactions.py:253 #: apps/note/models/transactions.py:256
#: apps/note/templates/note/transaction_form.html:16 #: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148 #: apps/note/templates/note/transaction_form.html:148
#: note_kfet/templates/base.html:73 #: note_kfet/templates/base.html:73
@ -292,13 +292,13 @@ msgid "Transfer"
msgstr "Virement" msgstr "Virement"
#: apps/activity/templates/activity/activity_entry.html:18 #: apps/activity/templates/activity/activity_entry.html:18
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:21 #: apps/note/templates/note/transaction_form.html:21
msgid "Credit" msgid "Credit"
msgstr "Crédit" msgstr "Crédit"
#: apps/activity/templates/activity/activity_entry.html:21 #: apps/activity/templates/activity/activity_entry.html:21
#: apps/note/models/transactions.py:313 #: apps/note/models/transactions.py:316
#: apps/note/templates/note/transaction_form.html:25 #: apps/note/templates/note/transaction_form.html:25
msgid "Debit" msgid "Debit"
msgstr "Débit" msgstr "Débit"
@ -388,41 +388,41 @@ msgstr "modifier"
msgid "Invite" msgid "Invite"
msgstr "Inviter" msgstr "Inviter"
#: apps/activity/views.py:34 #: apps/activity/views.py:36
msgid "Create new activity" msgid "Create new activity"
msgstr "Créer une nouvelle activité" msgstr "Créer une nouvelle activité"
#: apps/activity/views.py:65 note_kfet/templates/base.html:91 #: apps/activity/views.py:67 note_kfet/templates/base.html:91
msgid "Activities" msgid "Activities"
msgstr "Activités" msgstr "Activités"
#: apps/activity/views.py:93 #: apps/activity/views.py:95
msgid "Activity detail" msgid "Activity detail"
msgstr "Détails de l'activité" msgstr "Détails de l'activité"
#: apps/activity/views.py:113 #: apps/activity/views.py:115
msgid "Update activity" msgid "Update activity"
msgstr "Modifier l'activité" msgstr "Modifier l'activité"
#: apps/activity/views.py:140 #: apps/activity/views.py:142
msgid "Invite guest to the activity \"{}\"" msgid "Invite guest to the activity \"{}\""
msgstr "Invitation pour l'activité « {} »" msgstr "Invitation pour l'activité « {} »"
#: apps/activity/views.py:175 #: apps/activity/views.py:177
msgid "You are not allowed to display the entry interface for this activity." msgid "You are not allowed to display the entry interface for this activity."
msgstr "" msgstr ""
"Vous n'êtes pas autorisé à afficher l'interface des entrées pour cette " "Vous n'êtes pas autorisé à afficher l'interface des entrées pour cette "
"activité." "activité."
#: apps/activity/views.py:178 #: apps/activity/views.py:180
msgid "This activity does not support activity entries." msgid "This activity does not support activity entries."
msgstr "Cette activité ne requiert pas d'entrées." msgstr "Cette activité ne requiert pas d'entrées."
#: apps/activity/views.py:181 #: apps/activity/views.py:183
msgid "This activity is closed." msgid "This activity is closed."
msgstr "Cette activité est fermée." msgstr "Cette activité est fermée."
#: apps/activity/views.py:277 #: apps/activity/views.py:279
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "Entrées pour l'activité « {} »" msgstr "Entrées pour l'activité « {} »"
@ -438,7 +438,7 @@ msgstr "Logs"
msgid "IP Address" msgid "IP Address"
msgstr "Adresse IP" msgstr "Adresse IP"
#: apps/logs/models.py:36 apps/permission/models.py:134 #: apps/logs/models.py:36 apps/permission/models.py:137
msgid "model" msgid "model"
msgstr "modèle" msgstr "modèle"
@ -459,7 +459,7 @@ msgid "create"
msgstr "créer" msgstr "créer"
#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201 #: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
#: apps/permission/models.py:127 apps/treasury/tables.py:38 #: apps/permission/models.py:130 apps/treasury/tables.py:38
#: apps/wei/tables.py:75 #: apps/wei/tables.py:75
msgid "delete" msgid "delete"
msgstr "supprimer" msgstr "supprimer"
@ -540,48 +540,48 @@ msgid "This image cannot be loaded."
msgstr "Cette image ne peut pas être chargée." msgstr "Cette image ne peut pas être chargée."
#: apps/member/forms.py:141 apps/member/views.py:100 #: apps/member/forms.py:141 apps/member/views.py:100
#: apps/registration/forms.py:33 apps/registration/views.py:244 #: apps/registration/forms.py:33 apps/registration/views.py:254
msgid "An alias with a similar name already exists." msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà." msgstr "Un alias avec un nom similaire existe déjà."
#: apps/member/forms.py:164 apps/registration/forms.py:61 #: apps/member/forms.py:165 apps/registration/forms.py:70
msgid "Inscription paid by Société Générale" msgid "Inscription paid by Société Générale"
msgstr "Inscription payée par la Société générale" msgstr "Inscription payée par la Société générale"
#: apps/member/forms.py:166 apps/registration/forms.py:63 #: apps/member/forms.py:167 apps/registration/forms.py:72
msgid "Check this case if the Société Générale paid the inscription." 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." msgstr "Cochez cette case si la Société Générale a payé l'inscription."
#: apps/member/forms.py:171 apps/registration/forms.py:68 #: apps/member/forms.py:172 apps/registration/forms.py:77
#: apps/wei/forms/registration.py:83 #: apps/wei/forms/registration.py:83
msgid "Credit type" msgid "Credit type"
msgstr "Type de rechargement" msgstr "Type de rechargement"
#: apps/member/forms.py:172 apps/registration/forms.py:69 #: apps/member/forms.py:173 apps/registration/forms.py:78
#: apps/wei/forms/registration.py:84 #: apps/wei/forms/registration.py:84
msgid "No credit" msgid "No credit"
msgstr "Pas de rechargement" msgstr "Pas de rechargement"
#: apps/member/forms.py:174 #: apps/member/forms.py:175
msgid "You can credit the note of the user." msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utilisateur avant l'adhésion." msgstr "Vous pouvez créditer la note de l'utilisateur avant l'adhésion."
#: apps/member/forms.py:178 apps/registration/forms.py:74 #: apps/member/forms.py:179 apps/registration/forms.py:83
#: apps/wei/forms/registration.py:89 #: apps/wei/forms/registration.py:89
msgid "Credit amount" msgid "Credit amount"
msgstr "Montant à créditer" msgstr "Montant à créditer"
#: apps/member/forms.py:195 apps/note/templates/note/transaction_form.html:140 #: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:91 apps/treasury/forms.py:134 #: apps/registration/forms.py:100 apps/treasury/forms.py:134
#: apps/wei/forms/registration.py:106 #: apps/wei/forms/registration.py:106
msgid "Bank" msgid "Bank"
msgstr "Banque" msgstr "Banque"
#: apps/member/forms.py:222 #: apps/member/forms.py:223
msgid "User" msgid "User"
msgstr "Utilisateur" msgstr "Utilisateur"
#: apps/member/forms.py:236 #: apps/member/forms.py:237
msgid "Roles" msgid "Roles"
msgstr "Rôles" msgstr "Rôles"
@ -809,7 +809,7 @@ msgstr ""
"renouveler." "renouveler."
#: apps/member/models.py:286 apps/member/models.py:311 #: apps/member/models.py:286 apps/member/models.py:311
#: apps/note/models/notes.py:191 #: apps/note/models/notes.py:177
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -830,11 +830,11 @@ msgstr "l'adhésion finit le"
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}." msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:430 apps/member/views.py:634 #: apps/member/models.py:430 apps/member/views.py:646
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club" msgstr "L'utilisateur est déjà membre du club"
#: apps/member/models.py:442 apps/member/views.py:644 #: apps/member/models.py:442 apps/member/views.py:656
msgid "User is not a member of the parent club" msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent" msgstr "L'utilisateur n'est pas membre du club parent"
@ -843,7 +843,7 @@ msgstr "L'utilisateur n'est pas membre du club parent"
msgid "Membership of {user} for the club {club}" msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}" msgstr "Adhésion de {user} pour le club {club}"
#: apps/member/models.py:498 apps/note/models/transactions.py:355 #: apps/member/models.py:498 apps/note/models/transactions.py:358
msgid "membership" msgid "membership"
msgstr "adhésion" msgstr "adhésion"
@ -959,8 +959,8 @@ msgstr ""
"à nouveau possible." "à nouveau possible."
#: apps/member/templates/member/club_alias.html:10 #: apps/member/templates/member/club_alias.html:10
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:238 #: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:245
#: apps/member/views.py:436 #: apps/member/views.py:448
msgid "Note aliases" msgid "Note aliases"
msgstr "Alias de la note" msgstr "Alias de la note"
@ -1024,7 +1024,7 @@ msgstr "solde du compte"
#: apps/member/templates/member/includes/club_info.html:47 #: apps/member/templates/member/includes/club_info.html:47
#: apps/member/templates/member/includes/profile_info.html:20 #: apps/member/templates/member/includes/profile_info.html:20
#: apps/note/models/notes.py:283 apps/wei/templates/wei/base.html:66 #: apps/note/models/notes.py:255 apps/wei/templates/wei/base.html:66
msgid "aliases" msgid "aliases"
msgstr "alias" msgstr "alias"
@ -1103,39 +1103,39 @@ msgstr "Cette adresse doit être valide."
msgid "Profile detail" msgid "Profile detail"
msgstr "Détails de l'utilisateur" msgstr "Détails de l'utilisateur"
#: apps/member/views.py:197 #: apps/member/views.py:204
msgid "Search user" msgid "Search user"
msgstr "Chercher un utilisateur" msgstr "Chercher un utilisateur"
#: apps/member/views.py:258 #: apps/member/views.py:265
msgid "Update note picture" msgid "Update note picture"
msgstr "Modifier la photo de la note" msgstr "Modifier la photo de la note"
#: apps/member/views.py:304 #: apps/member/views.py:311
msgid "Manage auth token" msgid "Manage auth token"
msgstr "Gérer les jetons d'authentification" msgstr "Gérer les jetons d'authentification"
#: apps/member/views.py:331 #: apps/member/views.py:338
msgid "Create new club" msgid "Create new club"
msgstr "Créer un nouveau club" msgstr "Créer un nouveau club"
#: apps/member/views.py:350 #: apps/member/views.py:357
msgid "Search club" msgid "Search club"
msgstr "Chercher un club" msgstr "Chercher un club"
#: apps/member/views.py:383 #: apps/member/views.py:390
msgid "Club detail" msgid "Club detail"
msgstr "Détails du club" msgstr "Détails du club"
#: apps/member/views.py:459 #: apps/member/views.py:471
msgid "Update club" msgid "Update club"
msgstr "Modifier le club" msgstr "Modifier le club"
#: apps/member/views.py:493 #: apps/member/views.py:505
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club" msgstr "Ajouter un nouveau membre au club"
#: apps/member/views.py:625 apps/wei/views.py:928 #: apps/member/views.py:637 apps/wei/views.py:928
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
@ -1143,25 +1143,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas " "Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif." "avoir un solde négatif."
#: apps/member/views.py:648 #: apps/member/views.py:660
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
#: apps/member/views.py:653 #: apps/member/views.py:665
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:660 apps/member/views.py:662 apps/member/views.py:664 #: apps/member/views.py:672 apps/member/views.py:674 apps/member/views.py:676
#: apps/registration/views.py:294 apps/registration/views.py:296 #: apps/registration/views.py:304 apps/registration/views.py:306
#: apps/registration/views.py:298 apps/wei/views.py:933 apps/wei/views.py:937 #: apps/registration/views.py:308 apps/wei/views.py:933 apps/wei/views.py:937
msgid "This field is required." msgid "This field is required."
msgstr "Ce champ est requis." msgstr "Ce champ est requis."
#: apps/member/views.py:800 #: apps/member/views.py:816
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club" msgstr "Gérer les rôles d'un utilisateur dans le club"
#: apps/member/views.py:825 #: apps/member/views.py:841
msgid "Members of the club" msgid "Members of the club"
msgstr "Membres du club" msgstr "Membres du club"
@ -1180,7 +1180,7 @@ msgid "amount"
msgstr "montant" msgstr "montant"
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189 #: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
#: apps/note/models/transactions.py:224 #: apps/note/models/transactions.py:227
msgid "" msgid ""
"The transaction can't be saved since the source note or the destination note " "The transaction can't be saved since the source note or the destination note "
"is not active." "is not active."
@ -1290,51 +1290,51 @@ msgstr "notes des utilisateurs"
msgid "%(user)s's note" msgid "%(user)s's note"
msgstr "Note de %(user)s" msgstr "Note de %(user)s"
#: apps/note/models/notes.py:195 #: apps/note/models/notes.py:181
msgid "club note" msgid "club note"
msgstr "note d'un club" msgstr "note d'un club"
#: apps/note/models/notes.py:196 #: apps/note/models/notes.py:182
msgid "clubs notes" msgid "clubs notes"
msgstr "notes des clubs" msgstr "notes des clubs"
#: apps/note/models/notes.py:202 #: apps/note/models/notes.py:188
#, python-format #, python-format
msgid "Note of %(club)s club" msgid "Note of %(club)s club"
msgstr "Note du club %(club)s" msgstr "Note du club %(club)s"
#: apps/note/models/notes.py:242 #: apps/note/models/notes.py:214
msgid "special note" msgid "special note"
msgstr "note spéciale" msgstr "note spéciale"
#: apps/note/models/notes.py:243 #: apps/note/models/notes.py:215
msgid "special notes" msgid "special notes"
msgstr "notes spéciales" msgstr "notes spéciales"
#: apps/note/models/notes.py:266 #: apps/note/models/notes.py:238
msgid "Invalid alias" msgid "Invalid alias"
msgstr "Alias invalide" msgstr "Alias invalide"
#: apps/note/models/notes.py:282 #: apps/note/models/notes.py:254
msgid "alias" msgid "alias"
msgstr "alias" msgstr "alias"
#: apps/note/models/notes.py:306 #: apps/note/models/notes.py:278
msgid "Alias is too long." msgid "Alias is too long."
msgstr "L'alias est trop long." msgstr "L'alias est trop long."
#: apps/note/models/notes.py:309 #: apps/note/models/notes.py:281
msgid "" msgid ""
"This alias contains only complex character. Please use a more simple alias." "This alias contains only complex character. Please use a more simple alias."
msgstr "" msgstr ""
"Cet alias ne contient que des caractères complexes. Merci d'utiliser un " "Cet alias ne contient que des caractères complexes. Merci d'utiliser un "
"alias plus simple." "alias plus simple."
#: apps/note/models/notes.py:313 #: apps/note/models/notes.py:285
msgid "An alias with a similar name already exists: {} " msgid "An alias with a similar name already exists: {} "
msgstr "Un alias avec un nom similaire existe déjà : {} " msgstr "Un alias avec un nom similaire existe déjà : {} "
#: apps/note/models/notes.py:327 #: apps/note/models/notes.py:299
msgid "You can't delete your main alias." msgid "You can't delete your main alias."
msgstr "Vous ne pouvez pas supprimer votre alias principal." msgstr "Vous ne pouvez pas supprimer votre alias principal."
@ -1410,7 +1410,7 @@ msgstr ""
"€ et 92 233 720 368 547 758.07 €. Ne cherchez pas à capitaliser l'argent du " "€ et 92 233 720 368 547 758.07 €. Ne cherchez pas à capitaliser l'argent du "
"BDE." "BDE."
#: apps/note/models/transactions.py:273 #: apps/note/models/transactions.py:276
msgid "" msgid ""
"The destination of this transaction must equal to the destination of the " "The destination of this transaction must equal to the destination of the "
"template." "template."
@ -1418,27 +1418,27 @@ msgstr ""
"Le destinataire de cette transaction doit être identique à celui du bouton " "Le destinataire de cette transaction doit être identique à celui du bouton "
"utilisé." "utilisé."
#: apps/note/models/transactions.py:283 #: apps/note/models/transactions.py:286
msgid "Template" msgid "Template"
msgstr "Bouton" msgstr "Bouton"
#: apps/note/models/transactions.py:286 #: apps/note/models/transactions.py:289
msgid "recurrent transaction" msgid "recurrent transaction"
msgstr "transaction issue de bouton" msgstr "transaction issue de bouton"
#: apps/note/models/transactions.py:287 #: apps/note/models/transactions.py:290
msgid "recurrent transactions" msgid "recurrent transactions"
msgstr "transactions issues de boutons" msgstr "transactions issues de boutons"
#: apps/note/models/transactions.py:302 #: apps/note/models/transactions.py:305
msgid "first_name" msgid "first_name"
msgstr "prénom" msgstr "prénom"
#: apps/note/models/transactions.py:307 #: apps/note/models/transactions.py:310
msgid "bank" msgid "bank"
msgstr "banque" msgstr "banque"
#: apps/note/models/transactions.py:324 #: apps/note/models/transactions.py:327
msgid "" msgid ""
"A special transaction is only possible between a Note associated to a " "A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club" "payment method and a User or a Club"
@ -1446,19 +1446,19 @@ msgstr ""
"Une transaction spéciale n'est possible que entre une note associée à un " "Une transaction spéciale n'est possible que entre une note associée à un "
"mode de paiement et un utilisateur ou un club" "mode de paiement et un utilisateur ou un club"
#: apps/note/models/transactions.py:333 #: apps/note/models/transactions.py:336
msgid "Special transaction" msgid "Special transaction"
msgstr "Transaction de crédit/retrait" msgstr "Transaction de crédit/retrait"
#: apps/note/models/transactions.py:334 #: apps/note/models/transactions.py:337
msgid "Special transactions" msgid "Special transactions"
msgstr "Transactions de crédit/retrait" msgstr "Transactions de crédit/retrait"
#: apps/note/models/transactions.py:350 #: apps/note/models/transactions.py:353
msgid "membership transaction" msgid "membership transaction"
msgstr "transaction d'adhésion" msgstr "transaction d'adhésion"
#: apps/note/models/transactions.py:351 apps/treasury/models.py:284 #: apps/note/models/transactions.py:354 apps/treasury/models.py:284
msgid "membership transactions" msgid "membership transactions"
msgstr "transactions d'adhésion" msgstr "transactions d'adhésion"
@ -1648,53 +1648,53 @@ msgstr "Vous ne pouvez pas voir le moindre bouton."
msgid "Search transactions" msgid "Search transactions"
msgstr "Rechercher des transactions" msgstr "Rechercher des transactions"
#: apps/permission/models.py:89 #: apps/permission/models.py:92
#, python-brace-format #, python-brace-format
msgid "Can {type} {model}.{field} in {query}" msgid "Can {type} {model}.{field} in {query}"
msgstr "Can {type} {model}.{field} in {query}" msgstr "Can {type} {model}.{field} in {query}"
#: apps/permission/models.py:91 #: apps/permission/models.py:94
#, python-brace-format #, python-brace-format
msgid "Can {type} {model} in {query}" msgid "Can {type} {model} in {query}"
msgstr "Can {type} {model} in {query}" msgstr "Can {type} {model} in {query}"
#: apps/permission/models.py:104 #: apps/permission/models.py:107
msgid "rank" msgid "rank"
msgstr "rang" msgstr "rang"
#: apps/permission/models.py:117 #: apps/permission/models.py:120
msgid "permission mask" msgid "permission mask"
msgstr "masque de permissions" msgstr "masque de permissions"
#: apps/permission/models.py:118 #: apps/permission/models.py:121
msgid "permission masks" msgid "permission masks"
msgstr "masques de permissions" msgstr "masques de permissions"
#: apps/permission/models.py:124 #: apps/permission/models.py:127
msgid "add" msgid "add"
msgstr "ajouter" msgstr "ajouter"
#: apps/permission/models.py:125 #: apps/permission/models.py:128
msgid "view" msgid "view"
msgstr "voir" msgstr "voir"
#: apps/permission/models.py:126 #: apps/permission/models.py:129
msgid "change" msgid "change"
msgstr "modifier" msgstr "modifier"
#: apps/permission/models.py:158 #: apps/permission/models.py:161
msgid "query" msgid "query"
msgstr "requête" msgstr "requête"
#: apps/permission/models.py:171 #: apps/permission/models.py:174
msgid "mask" msgid "mask"
msgstr "masque" msgstr "masque"
#: apps/permission/models.py:177 #: apps/permission/models.py:180
msgid "field" msgid "field"
msgstr "champ" msgstr "champ"
#: apps/permission/models.py:182 #: apps/permission/models.py:185
msgid "" msgid ""
"Tells if the permission should be granted even if the membership of the user " "Tells if the permission should be granted even if the membership of the user "
"is expired." "is expired."
@ -1702,30 +1702,30 @@ msgstr ""
"Indique si la permission doit être attribuée même si l'adhésion de " "Indique si la permission doit être attribuée même si l'adhésion de "
"l'utilisateur est expirée." "l'utilisateur est expirée."
#: apps/permission/models.py:183 #: apps/permission/models.py:186
#: apps/permission/templates/permission/all_rights.html:89 #: apps/permission/templates/permission/all_rights.html:89
msgid "permanent" msgid "permanent"
msgstr "permanent" msgstr "permanent"
#: apps/permission/models.py:194 #: apps/permission/models.py:197
msgid "permission" msgid "permission"
msgstr "permission" msgstr "permission"
#: apps/permission/models.py:195 apps/permission/models.py:335 #: apps/permission/models.py:198 apps/permission/models.py:338
msgid "permissions" msgid "permissions"
msgstr "permissions" msgstr "permissions"
#: apps/permission/models.py:200 #: apps/permission/models.py:203
msgid "Specifying field applies only to view and change permission types." msgid "Specifying field applies only to view and change permission types."
msgstr "" msgstr ""
"Spécifie le champ concerné, ne fonctionne que pour les permissions view et " "Spécifie le champ concerné, ne fonctionne que pour les permissions view et "
"change." "change."
#: apps/permission/models.py:340 #: apps/permission/models.py:343
msgid "for club" msgid "for club"
msgstr "s'applique au club" msgstr "s'applique au club"
#: apps/permission/models.py:350 apps/permission/models.py:351 #: apps/permission/models.py:353 apps/permission/models.py:354
msgid "role permissions" msgid "role permissions"
msgstr "permissions par rôles" msgstr "permissions par rôles"
@ -1832,10 +1832,26 @@ msgid "This email address is already used."
msgstr "Cet email est déjà pris." msgstr "Cet email est déjà pris."
#: apps/registration/forms.py:49 #: apps/registration/forms.py:49
msgid ""
"I declare that I opened a bank account in the Société générale with the BDE "
"partnership."
msgstr ""
"Je déclare avoir ouvert un compte à la société générale avec le partenariat "
"du BDE."
#: apps/registration/forms.py:50
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:58
msgid "Register to the WEI" msgid "Register to the WEI"
msgstr "S'inscrire au WEI" msgstr "S'inscrire au WEI"
#: apps/registration/forms.py:51 #: apps/registration/forms.py:60
msgid "" msgid ""
"Check this case if you want to register to the WEI. If you hesitate, you " "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." "will be able to register later, after validating your account in the Kfet."
@ -1844,11 +1860,11 @@ msgstr ""
"pourrez toujours vous inscrire plus tard, après avoir validé votre compte à " "pourrez toujours vous inscrire plus tard, après avoir validé votre compte à "
"la Kfet." "la Kfet."
#: apps/registration/forms.py:96 #: apps/registration/forms.py:105
msgid "Join BDE Club" msgid "Join BDE Club"
msgstr "Adhérer au club BDE" msgstr "Adhérer au club BDE"
#: apps/registration/forms.py:103 #: apps/registration/forms.py:112
msgid "Join Kfet Club" msgid "Join Kfet Club"
msgstr "Adhérer au club Kfet" msgstr "Adhérer au club Kfet"
@ -1900,7 +1916,12 @@ msgstr "Supprimer l'inscription"
msgid "Validate account" msgid "Validate account"
msgstr "Valider le compte" msgstr "Valider le compte"
#: apps/registration/templates/registration/future_profile_detail.html:64 #: 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:127
#: apps/wei/templates/wei/weimembership_form.html:186 #: apps/wei/templates/wei/weimembership_form.html:186
msgid "Validate registration" msgid "Validate registration"
@ -1954,50 +1975,50 @@ msgstr "L'équipe de la Note Kfet."
msgid "Register new user" msgid "Register new user"
msgstr "Enregistrer un nouvel utilisateur" msgstr "Enregistrer un nouvel utilisateur"
#: apps/registration/views.py:85 #: apps/registration/views.py:93
msgid "Email validation" msgid "Email validation"
msgstr "Validation de l'adresse mail" msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:87 #: apps/registration/views.py:95
msgid "Validate email" msgid "Validate email"
msgstr "Valider l'adresse e-mail" msgstr "Valider l'adresse e-mail"
#: apps/registration/views.py:129 #: apps/registration/views.py:137
msgid "Email validation unsuccessful" msgid "Email validation unsuccessful"
msgstr "La validation de l'adresse mail a échoué" msgstr "La validation de l'adresse mail a échoué"
#: apps/registration/views.py:140 #: apps/registration/views.py:148
msgid "Email validation email sent" msgid "Email validation email sent"
msgstr "L'email de vérification de l'adresse email a bien été envoyé" msgstr "L'email de vérification de l'adresse email a bien été envoyé"
#: apps/registration/views.py:148 #: apps/registration/views.py:156
msgid "Resend email validation link" msgid "Resend email validation link"
msgstr "Renvoyer le lien de validation" msgstr "Renvoyer le lien de validation"
#: apps/registration/views.py:166 #: apps/registration/views.py:174
msgid "Pre-registered users list" msgid "Pre-registered users list"
msgstr "Liste des utilisateurs en attente d'inscription" msgstr "Liste des utilisateurs en attente d'inscription"
#: apps/registration/views.py:190 #: apps/registration/views.py:198
msgid "Unregistered users" msgid "Unregistered users"
msgstr "Utilisateurs en attente d'inscription" msgstr "Utilisateurs en attente d'inscription"
#: apps/registration/views.py:203 #: apps/registration/views.py:211
msgid "Registration detail" msgid "Registration detail"
msgstr "Détails de l'inscription" msgstr "Détails de l'inscription"
#: apps/registration/views.py:263 #: apps/registration/views.py:273
msgid "You must join the BDE." msgid "You must join the BDE."
msgstr "Vous devez adhérer au BDE." msgstr "Vous devez adhérer au BDE."
#: apps/registration/views.py:287 #: apps/registration/views.py:297
msgid "" msgid ""
"The entered amount is not enough for the memberships, should be at least {}" "The entered amount is not enough for the memberships, should be at least {}"
msgstr "" msgstr ""
"Le montant crédité est trop faible pour adhérer, il doit être au minimum de " "Le montant crédité est trop faible pour adhérer, il doit être au minimum de "
"{}" "{}"
#: apps/registration/views.py:367 #: apps/registration/views.py:384
msgid "Invalidate pre-registration" msgid "Invalidate pre-registration"
msgstr "Invalider l'inscription" msgstr "Invalider l'inscription"
@ -2143,7 +2164,7 @@ msgstr "proxys de transactions spéciales"
msgid "credit transaction" msgid "credit transaction"
msgstr "transaction de crédit" msgstr "transaction de crédit"
#: apps/treasury/models.py:369 #: apps/treasury/models.py:374
msgid "" msgid ""
"This user doesn't have enough money to pay the memberships with its note. " "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." "Please ask her/him to credit the note before invalidating this credit."
@ -2151,16 +2172,16 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa " "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." "note. Merci de lui demander de recharger sa note avant d'invalider ce crédit."
#: apps/treasury/models.py:384 #: apps/treasury/models.py:389
#: apps/treasury/templates/treasury/sogecredit_detail.html:10 #: apps/treasury/templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale" msgid "Credit from the Société générale"
msgstr "Crédit de la Société générale" msgstr "Crédit de la Société générale"
#: apps/treasury/models.py:385 #: apps/treasury/models.py:390
msgid "Credits from the Société générale" msgid "Credits from the Société générale"
msgstr "Crédits de la Société générale" msgstr "Crédits de la Société générale"
#: apps/treasury/models.py:388 #: apps/treasury/models.py:393
#, python-brace-format #, python-brace-format
msgid "Soge credit for {user}" msgid "Soge credit for {user}"
msgstr "Crédit de la société générale pour l'utilisateur {user}" msgstr "Crédit de la société générale pour l'utilisateur {user}"
@ -2936,19 +2957,19 @@ msgstr "Valider l'inscription WEI"
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "Cet utilisateur n'a pas donné son chèque de caution." msgstr "Cet utilisateur n'a pas donné son chèque de caution."
#: note_kfet/settings/base.py:155 #: note_kfet/settings/base.py:157
msgid "German" msgid "German"
msgstr "Allemand" msgstr "Allemand"
#: note_kfet/settings/base.py:156 #: note_kfet/settings/base.py:158
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: note_kfet/settings/base.py:157 #: note_kfet/settings/base.py:159
msgid "Spanish" msgid "Spanish"
msgstr "Espagnol" msgstr "Espagnol"
#: note_kfet/settings/base.py:158 #: note_kfet/settings/base.py:160
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"
@ -3036,7 +3057,7 @@ msgstr "Se déconnecter"
#: note_kfet/templates/base.html:139 #: note_kfet/templates/base.html:139
#: note_kfet/templates/registration/signup.html:6 #: note_kfet/templates/registration/signup.html:6
#: note_kfet/templates/registration/signup.html:11 #: note_kfet/templates/registration/signup.html:11
#: note_kfet/templates/registration/signup.html:27 #: note_kfet/templates/registration/signup.html:28
msgid "Sign up" msgid "Sign up"
msgstr "Inscription" msgstr "Inscription"
@ -3048,7 +3069,21 @@ msgstr "Inscription"
msgid "Log in" msgid "Log in"
msgstr "Se connecter" msgstr "Se connecter"
#: note_kfet/templates/base.html:158 #: note_kfet/templates/base.html:156
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:160
msgid "You are not a Kfet member, so you can't use your note account."
msgstr ""
"Vous n'êtes pas adhérent Kfet, vous ne pouvez par conséquent pas utiliser "
"votre compte note."
#: note_kfet/templates/base.html:166
msgid "" msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click " "Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link." "on the validation link."
@ -3056,7 +3091,22 @@ msgstr ""
"Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail " "Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail "
"et de cliquer sur le lien de validation." "et de cliquer sur le lien de validation."
#: note_kfet/templates/base.html:175 #: 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 "
"registration bonus of 80 € is not credited and the membership is 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, le bonus d'inscription de 80 € n'a donc pas encore été créditée et "
"l'adhésion n'est pas encore payée. 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" msgid "Contact us"
msgstr "Nous contacter" msgstr "Nous contacter"
@ -3068,21 +3118,6 @@ msgstr "Chercher par un attribut tel que le nom …"
msgid "There is no results." msgid "There is no results."
msgstr "Il n'y a pas de résultat." msgstr "Il n'y a pas de résultat."
#: note_kfet/templates/cas_server/base.html:7
msgid "Central Authentication Service"
msgstr "Service Central d'Authentification"
#: note_kfet/templates/cas_server/base.html:43
#, python-format
msgid ""
"A new version of the application is available. This instance runs "
"%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
"upgrading."
msgstr ""
"Une nouvelle version de l'application est disponible. Cette instance utilise "
"la version %(VERSION)s et la dernière version est %(LAST_VERSION)s. Merci de "
"vous mettre à jour."
#: note_kfet/templates/registration/logged_out.html:13 #: note_kfet/templates/registration/logged_out.html:13
msgid "Thanks for spending some quality time with the Web site today." msgid "Thanks for spending some quality time with the Web site today."
msgstr "Merci d'avoir utilisé la Note Kfet." msgstr "Merci d'avoir utilisé la Note Kfet."
@ -3195,5 +3230,18 @@ msgstr ""
"d'adhésion. Vous devez également valider votre adresse email en suivant le " "d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu." "lien que vous avez reçu."
#~ msgid "Central Authentication Service"
#~ msgstr "Service Central d'Authentification"
#, python-format
#~ msgid ""
#~ "A new version of the application is available. This instance runs "
#~ "%(VERSION)s and the last version is %(LAST_VERSION)s. Please consider "
#~ "upgrading."
#~ msgstr ""
#~ "Une nouvelle version de l'application est disponible. Cette instance "
#~ "utilise la version %(VERSION)s et la dernière version est "
#~ "%(LAST_VERSION)s. Merci de vous mettre à jour."
#~ msgid "Check this case is the Société Générale paid the inscription." #~ msgid "Check this case is the Société Générale paid the inscription."
#~ msgstr "Cochez cette case si la Société Générale a payé l'inscription." #~ msgstr "Cochez cette case si la Société Générale a payé l'inscription."

View File

@ -20,3 +20,5 @@
55 6 * * * root cd /var/www/note_kfet && env/bin/python manage.py send_reports 55 6 * * * root cd /var/www/note_kfet && env/bin/python manage.py send_reports
# Mettre à jour les boutons mis en avant # Mettre à jour les boutons mis en avant
00 9 * * * root cd /var/www/note_kfet && env/bin/python manage.py refresh_highlighted_buttons 00 9 * * * root cd /var/www/note_kfet && env/bin/python manage.py refresh_highlighted_buttons
# Vider les tokens Oauth2
00 6 * * * root cd /var/www/note_kfet && env/bin/python manage.py cleartokens

View File

@ -26,6 +26,14 @@ admin_site = StrongAdminSite()
admin_site.register(Site, SiteAdmin) admin_site.register(Site, SiteAdmin)
# Add external apps model # Add external apps model
if "oauth2_provider" in settings.INSTALLED_APPS:
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: if "django_htcpcp_tea" in settings.INSTALLED_APPS:
from django_htcpcp_tea.admin import * from django_htcpcp_tea.admin import *
from django_htcpcp_tea.models import * from django_htcpcp_tea.models import *
@ -44,9 +52,3 @@ if "rest_framework" in settings.INSTALLED_APPS:
from rest_framework.authtoken.admin import * from rest_framework.authtoken.admin import *
from rest_framework.authtoken.models import * from rest_framework.authtoken.models import *
admin_site.register(Token, TokenAdmin) admin_site.register(Token, TokenAdmin)
if "cas_server" in settings.INSTALLED_APPS:
from cas_server.admin import *
from cas_server.models import *
admin_site.register(ServicePattern, ServicePatternAdmin)
admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin)

View File

@ -1,11 +0,0 @@
[
{
"model": "cas_server.servicepattern",
"pk": 1,
"fields": {
"pos": 1,
"pattern": ".*",
"name": "REPLACEME"
}
}
]

View File

@ -2,12 +2,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
from django.contrib.auth import login
from django.contrib.auth.models import AnonymousUser, User from django.contrib.auth.models import AnonymousUser, User
from django.contrib.sessions.backends.db import SessionStore
from threading import local from threading import local
from django.contrib.sessions.backends.db import SessionStore
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user') USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session') SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip') IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
@ -78,6 +78,41 @@ class SessionMiddleware(object):
return response return response
class LoginByIPMiddleware(object):
"""
Allow some users to be authenticated based on their IP address.
For example, the "note" account should not be used elsewhere than the Kfet computer,
and should not have any password.
The password that is stored in database should be on the form "ipbased$my.public.ip.address".
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
"""
If the user is not authenticated, get the used IP address
and check if an user is authorized to be automatically logged with this address.
If it is the case, the logging is performed with the full rights.
"""
if not request.user.is_authenticated:
if 'HTTP_X_REAL_IP' in request.META:
ip = request.META.get('HTTP_X_REAL_IP')
elif 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0]
else:
ip = request.META.get('REMOTE_ADDR')
qs = User.objects.filter(password=f"ipbased${ip}")
if qs.exists():
login(request, qs.get())
session = request.session
session["permission_mask"] = 42
session.save()
return self.get_response(request)
class TurbolinksMiddleware(object): class TurbolinksMiddleware(object):
""" """
Send the `Turbolinks-Location` header in response to a visit that was redirected, Send the `Turbolinks-Location` header in response to a visit that was redirected,

View File

@ -49,16 +49,6 @@ try:
except ImportError: except ImportError:
pass pass
if "cas_server" in INSTALLED_APPS:
# CAS Settings
CAS_AUTO_CREATE_USER = False
CAS_LOGO_URL = "/static/img/Saperlistpopette.png"
CAS_FAVICON_URL = "/static/favicon/favicon-32x32.png"
CAS_SHOW_POWERED = False
if "logs" in INSTALLED_APPS:
MIDDLEWARE += ('note_kfet.middlewares.SessionMiddleware',)
if DEBUG: if DEBUG:
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor'] PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
if "debug_toolbar" in INSTALLED_APPS: if "debug_toolbar" in INSTALLED_APPS:

View File

@ -35,8 +35,10 @@ INSTALLED_APPS = [
'mailer', 'mailer',
'phonenumber_field', 'phonenumber_field',
'polymorphic', 'polymorphic',
'oauth2_provider',
# Django contrib # Django contrib
# Django Admin will autodiscover our apps for our custom admin site.
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs', 'django.contrib.admindocs',
'django.contrib.auth', 'django.contrib.auth',
@ -77,6 +79,8 @@ MIDDLEWARE = [
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware',
'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware', 'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware',
'note_kfet.middlewares.SessionMiddleware',
'note_kfet.middlewares.LoginByIPMiddleware',
'note_kfet.middlewares.TurbolinksMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware',
] ]
@ -214,6 +218,16 @@ EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD', None)
SERVER_EMAIL = os.getenv("NOTE_MAIL", "notekfet@example.com") SERVER_EMAIL = os.getenv("NOTE_MAIL", "notekfet@example.com")
DEFAULT_FROM_EMAIL = "NoteKfet2020 <" + SERVER_EMAIL + ">" DEFAULT_FROM_EMAIL = "NoteKfet2020 <" + SERVER_EMAIL + ">"
# Cache
# https://docs.djangoproject.com/en/2.2/topics/cache/#setting-up-the-cache
cache_address = os.getenv("CACHE_ADDRESS", "127.0.0.1:11211")
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': cache_address,
}
}
# Django REST Framework # Django REST Framework
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
@ -233,7 +247,7 @@ REST_FRAMEWORK = {
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
# After login redirect user to transfer page # After login redirect user to transfer page
LOGIN_REDIRECT_URL = '/note/transfer/' LOGIN_REDIRECT_URL = '/'
# An user session will expired after 3 hours # An user session will expired after 3 hours
SESSION_COOKIE_AGE = 60 * 60 * 3 SESSION_COOKIE_AGE = 60 * 60 * 3

View File

@ -24,6 +24,14 @@ if os.getenv("DJANGO_DEV_STORE_METHOD", "sqlite") != "postgresql":
} }
} }
# Dummy cache for development
# https://docs.djangoproject.com/en/2.2/topics/cache/#setting-up-the-cache
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
# Break it, fix it! # Break it, fix it!
DEBUG = True DEBUG = True

View File

@ -3,7 +3,6 @@
# CAS # CAS
OPTIONAL_APPS = [ OPTIONAL_APPS = [
# 'cas_server',
# 'debug_toolbar' # 'debug_toolbar'
] ]

View File

@ -1,4 +1,4 @@
{% load static i18n pretty_money static getenv perms %} {% load static i18n pretty_money static getenv perms memberinfo %}
{% comment %} {% comment %}
SPDX-License-Identifier: GPL-3.0-or-later SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %} {% endcomment %}
@ -67,7 +67,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a> <a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
</li> </li>
{% endif %} {% endif %}
{% if "note.transaction"|not_empty_model_list %} {% if user.is_authenticated and user|is_member:"Kfet" %}
<li class="nav-item"> <li class="nav-item">
{% url 'note:transfer' as url %} {% url 'note:transfer' as url %}
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-exchange"></i> {% trans 'Transfer' %} </a> <a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-exchange"></i> {% trans 'Transfer' %} </a>
@ -153,12 +153,36 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div> </div>
</nav> </nav>
<div class="{% block containertype %}container{% endblock %} my-3"> <div class="{% block containertype %}container{% endblock %} my-3">
{% if request.user.is_authenticated and not request.user.profile.email_confirmed %} <div id="messages">
<div class="alert alert-warning"> {% if user.is_authenticated %}
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %} {% if not user|is_member:"BDE" %}
</div> <div class="alert alert-danger">
{% endif %} {% trans "You are not a BDE member anymore. Please renew your membership if you want to use the note." %}
<div id="messages"></div> </div>
{% elif not user|is_member:"Kfet" %}
<div class="alert alert-warning">
{% trans "You are not a Kfet member, so you can't use your note account." %}
</div>
{% endif %}
{% if not user.profile.email_confirmed %}
<div class="alert alert-warning">
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
</div>
{% endif %}
{% endif %}
{% if user.sogecredit and not user.sogecredit.valid %}
<div class="alert alert-info">
{% blocktrans trimmed %}
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 registration bonus of 80 € is not credited and the membership is not paid yet.
This verification procedure may last a few days.
Please make sure that you go to the end of the account creation.
{% endblocktrans %}
</div>
{% endif %}
{# TODO Add banners #}
</div>
{% block content %} {% block content %}
<p>Default content...</p> <p>Default content...</p>
{% endblock %} {% endblock %}

View File

@ -1,99 +0,0 @@
{% load i18n %}{% load static %}{% get_current_language as LANGUAGE_CODE %}<!DOCTYPE html>
<html{% if LANGUAGE_CODE %} lang="{{LANGUAGE_CODE}}"{% endif %}>
<head>
<meta charset="utf-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge" /><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% trans "Central Authentication Service" %}{% endblock %}</title>
<link href="{{settings.CAS_COMPONENT_URLS.bootstrap3_css}}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="{{settings.CAS_COMPONENT_URLS.html5shiv}}"></script>
<script src="{{settings.CAS_COMPONENT_URLS.respond}}"></script>
<![endif]-->
{% if settings.CAS_FAVICON_URL %}<link rel="shortcut icon" href="{{settings.CAS_FAVICON_URL}}" />{% endif %}
<link href="{% static "cas_server/styles.css" %}" rel="stylesheet">
</head>
<body>
<div id="wrap">
<div class="container">
{% if auto_submit %}<noscript>{% endif %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h1 id="app-name">
{% if settings.CAS_LOGO_URL %}<img src="{{settings.CAS_LOGO_URL}}" alt="cas-logo" />{% endif %}
Authentification Note Kfet 2020</h1>
</div>
</div>
{% if auto_submit %}</noscript>{% endif %}
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-2 col-xs-12"></div>
<div class="col-lg-6 col-md-6 col-sm-8 col-xs-12">
{% if auto_submit %}<noscript>{% endif %}
{% for msg in CAS_INFO_RENDER %}
<div class="alert alert-{{msg.type}}{% if msg.discardable %} alert-dismissable{% endif %}">
{% if msg.discardable %}<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="info-{{msg.name}}">&#215;</button>{% endif %}
<p>{{msg.message}}</p>
</div>
{% endfor %}
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
<div class="alert alert-info alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="alert-version">&#215;</button>
<p>{% blocktrans %}A new version of the application is available. This instance runs {{VERSION}} and the last version is {{LAST_VERSION}}. Please consider upgrading.{% endblocktrans %}</p>
</div>
{% endif %}
{% block ante_messages %}{% endblock %}
{% for message in messages %}
<div {% spaceless %}
{% if message.level == message_levels.DEBUG %}
class="alert alert-warning"
{% elif message.level == message_levels.INFO %}
class="alert alert-info"
{% elif message.level == message_levels.SUCCESS %}
class="alert alert-success"
{% elif message.level == message_levels.WARNING %}
class="alert alert-warning"
{% else %}
class="alert alert-danger"
{% endif %}
{% endspaceless %}>
<p>{{message}}</p>
</div>
{% endfor %}
{% if auto_submit %}</noscript>{% endif %}
{% block content %}{% endblock %}
</div>
<div class="col-lg-3 col-md-3 col-sm-2 col-xs-0"></div>
</div>
</div> <!-- /container -->
</div>
<div style="clear: both;"></div>
{% if settings.CAS_SHOW_POWERED %}
<div id="footer">
<p><a class="text-muted" href="https://pypi.org/project/django-cas-server/">django-cas-server powered</a></p>
</div>
{% endif %}
<script src="{{settings.CAS_COMPONENT_URLS.jquery}}"></script>
<script src="{{settings.CAS_COMPONENT_URLS.bootstrap3_js}}"></script>
<script src="{% static "cas_server/functions.js" %}"></script>
<script type="text/javascript">
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
discard_and_remember("#alert-version", "cas-alert-version", "{{LAST_VERSION}}");
{% endif %}
{% for msg in CAS_INFO_RENDER %}
{% if msg.discardable %}
discard_and_remember("#info-{{msg.name}}", "cas-info-{{msg.name}}", "{{msg.hash}}");
{% endif %}
{% endfor %}
{% block javascript_inline %}{% endblock %}
</script>
{% block javascript %}{% endblock %}
</body>
</html>
<!--
Powered by django-cas-server version {{VERSION}}
Pypi: https://pypi.org/project/django-cas-server/
github: https://github.com/nitmir/django-cas-server
-->

View File

@ -23,6 +23,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
{{ profile_form|crispy }} {{ profile_form|crispy }}
{{ soge_form|crispy }}
<button class="btn btn-success" type="submit"> <button class="btn btn-success" type="submit">
{% trans "Sign up" %} {% trans "Sign up" %}
</button> </button>

View File

@ -5,15 +5,14 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.urls import path, include from django.urls import path, include
from django.views.defaults import bad_request, permission_denied, page_not_found, server_error from django.views.defaults import bad_request, permission_denied, page_not_found, server_error
from django.views.generic import RedirectView
from member.views import CustomLoginView from member.views import CustomLoginView
from .admin import admin_site from .admin import admin_site
from .views import IndexView
urlpatterns = [ urlpatterns = [
# Dev so redirect to something random # Dev so redirect to something random
path('', RedirectView.as_view(pattern_name='note:transfer'), name='index'), path('', IndexView.as_view(), name='index'),
# Include project routers # Include project routers
path('note/', include('note.urls')), path('note/', include('note.urls')),
@ -40,12 +39,11 @@ urlpatterns = [
if settings.DEBUG: if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if "oauth2_provider" in settings.INSTALLED_APPS:
if "cas_server" in settings.INSTALLED_APPS: # OAuth2 provider
urlpatterns += [ urlpatterns.append(
# Include CAS Server routers path('o/', include('oauth2_provider.urls', namespace='oauth2_provider'))
path('cas/', include('cas_server.urls', namespace="cas_server")), )
]
if "debug_toolbar" in settings.INSTALLED_APPS: if "debug_toolbar" in settings.INSTALLED_APPS:
import debug_toolbar import debug_toolbar

30
note_kfet/views.py Normal file
View File

@ -0,0 +1,30 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse
from django.views.generic import RedirectView
from note.models import Alias
from permission.backends import PermissionBackend
class IndexView(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
"""
Calculate the index page according to the roles.
A normal user will have access to the transfer page.
A non-Kfet member will have access to its user detail page.
The user "note" will display the consumption interface.
"""
user = self.request.user
# The account note will have the consumption page as default page
if not PermissionBackend.check_perm(user, "auth.view_user", user):
return reverse("note:consos")
# People that can see the alias BDE are Kfet members
if PermissionBackend.check_perm(user, "alias.view_alias", Alias.objects.get(name="BDE")):
return reverse("note:transfer")
# Non-Kfet members will don't see the transfer page, but their profile page
return reverse("member:user_detail", args=(user.pk,))

View File

@ -1,17 +1,18 @@
beautifulsoup4~=4.7.1 beautifulsoup4~=4.7.1
Django~=2.2.15 Django~=2.2.15
django-bootstrap-datepicker-plus~=3.0.5 django-bootstrap-datepicker-plus~=3.0.5
django-cas-server>=1.2.0
django-colorfield~=0.3.2 django-colorfield~=0.3.2
django-crispy-forms~=1.7.2 django-crispy-forms~=1.7.2
django-extensions~=2.1.4 django-extensions~=2.1.4
django-filter~=2.1.0 django-filter~=2.1.0
django-htcpcp-tea~=0.3.1 django-htcpcp-tea~=0.3.1
django-mailer~=2.0.1 django-mailer~=2.0.1
django-oauth-toolkit~=1.3.3
django-phonenumber-field~=5.0.0 django-phonenumber-field~=5.0.0
django-polymorphic~=2.0.3 django-polymorphic~=2.0.3
djangorestframework~=3.9.0 djangorestframework~=3.9.0
django-rest-polymorphic~=0.1.9 django-rest-polymorphic~=0.1.9
django-tables2~=2.3.1 django-tables2~=2.3.1
python-memcached~=1.59
phonenumbers~=8.9.10 phonenumbers~=8.9.10
Pillow>=5.4.1 Pillow>=5.4.1