Compare commits

..

11 Commits

Author SHA1 Message Date
Yohann D'ANELLO 8cde94c5f5 Import remittances 2020-07-26 01:01:21 +02:00
Yohann D'ANELLO ab5d5a6e94 Display the associated club of the role in the permission page 2020-07-25 20:15:26 +02:00
Yohann D'ANELLO 4c29d855d2 Fix RolePermissions merge 2020-07-25 20:07:45 +02:00
Yohann D'ANELLO 55bc288deb Some roles can only be given in some clubs 2020-07-25 19:59:04 +02:00
Yohann D'ANELLO fb5e2578af Merge Role and RolePermissions 2020-07-25 19:40:30 +02:00
Yohann D'ANELLO 0b6cb4ef19 Production is not debug 2020-07-25 19:14:27 +02:00
Yohann D'ANELLO 18bdc8044b 🐛 Minor fixes 2020-07-25 18:26:18 +02:00
Yohann D'ANELLO f0bca69825 🐛 Minor fixes 2020-07-25 18:18:53 +02:00
Yohann D'ANELLO b2e1777fe0 Update Django CAS Server 2020-07-25 17:44:38 +02:00
Yohann D'ANELLO afb35d7ae0 Fix linters 2020-07-25 17:42:44 +02:00
Yohann D'ANELLO b212bf4093 Fix linters 2020-07-25 17:42:32 +02:00
29 changed files with 434 additions and 510 deletions

View File

@ -6,7 +6,7 @@ from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .forms import ProfileForm from .forms import ProfileForm
from .models import Club, Membership, Profile, Role from .models import Club, Membership, Profile
class ProfileInline(admin.StackedInline): class ProfileInline(admin.StackedInline):
@ -39,4 +39,3 @@ admin.site.register(User, CustomUserAdmin)
# Add other models # Add other models
admin.site.register(Club) admin.site.register(Club)
admin.site.register(Membership) admin.site.register(Membership)
admin.site.register(Role)

View File

@ -3,7 +3,7 @@
from rest_framework import serializers from rest_framework import serializers
from ..models import Profile, Club, Role, Membership from ..models import Profile, Club, Membership
class ProfileSerializer(serializers.ModelSerializer): class ProfileSerializer(serializers.ModelSerializer):
@ -29,17 +29,6 @@ class ClubSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class RoleSerializer(serializers.ModelSerializer):
"""
REST API Serializer for Roles.
The djangorestframework plugin will analyse the model `Role` and parse all fields in the API.
"""
class Meta:
model = Role
fields = '__all__'
class MembershipSerializer(serializers.ModelSerializer): class MembershipSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for Memberships. REST API Serializer for Memberships.

View File

@ -1,7 +1,7 @@
# 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 .views import ProfileViewSet, ClubViewSet, RoleViewSet, MembershipViewSet from .views import ProfileViewSet, ClubViewSet, MembershipViewSet
def register_members_urls(router, path): def register_members_urls(router, path):
@ -10,5 +10,4 @@ def register_members_urls(router, path):
""" """
router.register(path + '/profile', ProfileViewSet) router.register(path + '/profile', ProfileViewSet)
router.register(path + '/club', ClubViewSet) router.register(path + '/club', ClubViewSet)
router.register(path + '/role', RoleViewSet)
router.register(path + '/membership', MembershipViewSet) router.register(path + '/membership', MembershipViewSet)

View File

@ -4,8 +4,8 @@
from rest_framework.filters import SearchFilter from rest_framework.filters import SearchFilter
from api.viewsets import ReadProtectedModelViewSet from api.viewsets import ReadProtectedModelViewSet
from .serializers import ProfileSerializer, ClubSerializer, RoleSerializer, MembershipSerializer from .serializers import ProfileSerializer, ClubSerializer, MembershipSerializer
from ..models import Profile, Club, Role, Membership from ..models import Profile, Club, Membership
class ProfileViewSet(ReadProtectedModelViewSet): class ProfileViewSet(ReadProtectedModelViewSet):
@ -30,18 +30,6 @@ class ClubViewSet(ReadProtectedModelViewSet):
search_fields = ['$name', ] search_fields = ['$name', ]
class RoleViewSet(ReadProtectedModelViewSet):
"""
REST API View set.
The djangorestframework plugin will get all `Role` objects, serialize it to JSON with the given serializer,
then render it on /api/members/role/
"""
queryset = Role.objects.all()
serializer_class = RoleSerializer
filter_backends = [SearchFilter]
search_fields = ['$name', ]
class MembershipViewSet(ReadProtectedModelViewSet): class MembershipViewSet(ReadProtectedModelViewSet):
""" """
REST API View set. REST API View set.

View File

@ -7,9 +7,9 @@ from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial from note.models import NoteSpecial
from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput
from permission.models import PermissionMask from permission.models import PermissionMask, Role
from .models import Profile, Club, Membership, Role from .models import Profile, Club, Membership
class CustomAuthenticationForm(AuthenticationForm): class CustomAuthenticationForm(AuthenticationForm):

View File

@ -247,24 +247,6 @@ class Club(models.Model):
return reverse_lazy('member:club_detail', args=(self.pk,)) return reverse_lazy('member:club_detail', args=(self.pk,))
class Role(models.Model):
"""
Role that an :model:`auth.User` can have in a :model:`member.Club`
"""
name = models.CharField(
verbose_name=_('name'),
max_length=255,
unique=True,
)
class Meta:
verbose_name = _('role')
verbose_name_plural = _('roles')
def __str__(self):
return str(self.name)
class Membership(models.Model): class Membership(models.Model):
""" """
Register the membership of a user to a club, including roles and membership duration. Register the membership of a user to a club, including roles and membership duration.
@ -284,7 +266,7 @@ class Membership(models.Model):
) )
roles = models.ManyToManyField( roles = models.ManyToManyField(
Role, "permission.Role",
verbose_name=_("roles"), verbose_name=_("roles"),
) )
@ -302,6 +284,7 @@ class Membership(models.Model):
verbose_name=_('fee'), verbose_name=_('fee'),
) )
@property
def valid(self): def valid(self):
""" """
A membership is valid if today is between the start and the end date. A membership is valid if today is between the start and the end date.
@ -319,6 +302,13 @@ class Membership(models.Model):
if not Membership.objects.filter(user=self.user, club=self.club.parent_club).exists(): if not Membership.objects.filter(user=self.user, club=self.club.parent_club).exists():
raise ValidationError(_('User is not a member of the parent club') + ' ' + self.club.parent_club.name) raise ValidationError(_('User is not a member of the parent club') + ' ' + self.club.parent_club.name)
for role in self.roles.all():
club = role.for_club
if club is not None:
if club.pk != self.club_id:
raise ValidationError(_('The role {role} does not apply to the club {club}.')
.format(role=role.name, club=club.name))
created = not self.pk created = not self.pk
if created: if created:
if Membership.objects.filter( if Membership.objects.filter(

View File

@ -22,10 +22,12 @@ from note.models import Alias, NoteUser
from note.models.transactions import Transaction, SpecialTransaction from note.models.transactions import Transaction, SpecialTransaction
from note.tables import HistoryTable, AliasTable from note.tables import HistoryTable, AliasTable
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
from wei.models import WEIClub
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm
from .models import Club, Membership, Role from .models import Club, Membership
from .tables import ClubTable, UserTable, MembershipTable from .tables import ClubTable, UserTable, MembershipTable
@ -303,7 +305,7 @@ class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
""" """
Filter the user list with the given pattern. Filter the user list with the given pattern.
""" """
qs = super().get_queryset().filter() qs = super().get_queryset().distinct()
if "search" in self.request.GET: if "search" in self.request.GET:
pattern = self.request.GET["search"] pattern = self.request.GET["search"]
@ -425,6 +427,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
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"], weiclub=None) .get(pk=self.kwargs["club_pk"], weiclub=None)
form.fields['credit_amount'].initial = club.membership_fee_paid form.fields['credit_amount'].initial = club.membership_fee_paid
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not isinstance(club, WEIClub))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
form.fields['roles'].initial = Role.objects.filter(name="Membre de club").all() form.fields['roles'].initial = Role.objects.filter(name="Membre de club").all()
# If the concerned club is the BDE, then we add the option that Société générale pays the membership. # If the concerned club is the BDE, then we add the option that Société générale pays the membership.
@ -444,6 +448,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
user = old_membership.user user = old_membership.user
form.fields['user'].initial = user form.fields['user'].initial = user
form.fields['user'].disabled = True form.fields['user'].disabled = True
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=not isinstance(club, WEIClub))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
form.fields['roles'].initial = old_membership.roles.all() form.fields['roles'].initial = old_membership.roles.all()
form.fields['date_start'].initial = old_membership.date_end + timedelta(days=1) form.fields['date_start'].initial = old_membership.date_end + timedelta(days=1)
form.fields['credit_amount'].initial = club.membership_fee_paid if user.profile.paid \ form.fields['credit_amount'].initial = club.membership_fee_paid if user.profile.paid \
@ -634,6 +640,11 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
del form.fields['last_name'] del form.fields['last_name']
del form.fields['first_name'] del form.fields['first_name']
del form.fields['bank'] del form.fields['bank']
club = self.object.club
form.fields['roles'].queryset = Role.objects.filter(Q(weirole__isnull=isinstance(club, WEIClub))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
return form return form
def get_success_url(self): def get_success_url(self):

View File

@ -3,7 +3,7 @@
from django.contrib import admin from django.contrib import admin
from .models import Permission, PermissionMask, RolePermissions from .models import Permission, PermissionMask, Role
@admin.register(PermissionMask) @admin.register(PermissionMask)
@ -22,9 +22,9 @@ class PermissionAdmin(admin.ModelAdmin):
list_display = ('type', 'model', 'field', 'mask', 'description', ) list_display = ('type', 'model', 'field', 'mask', 'description', )
@admin.register(RolePermissions) @admin.register(Role)
class RolePermissionsAdmin(admin.ModelAdmin): class RoleAdmin(admin.ModelAdmin):
""" """
Admin customisation for RolePermissions Admin customisation for Role
""" """
list_display = ('role', ) list_display = ('name', )

View File

@ -3,7 +3,7 @@
from rest_framework import serializers from rest_framework import serializers
from ..models import Permission, RolePermissions from ..models import Permission, Role
class PermissionSerializer(serializers.ModelSerializer): class PermissionSerializer(serializers.ModelSerializer):
@ -17,12 +17,12 @@ class PermissionSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class RolePermissionsSerializer(serializers.ModelSerializer): class RoleSerializer(serializers.ModelSerializer):
""" """
REST API Serializer for RolePermissions types. REST API Serializer for Role types.
The djangorestframework plugin will analyse the model `RolePermissions` and parse all fields in the API. The djangorestframework plugin will analyse the model `Role` and parse all fields in the API.
""" """
class Meta: class Meta:
model = RolePermissions model = Role
fields = '__all__' fields = '__all__'

View File

@ -1,7 +1,7 @@
# 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 .views import PermissionViewSet, RolePermissionsViewSet from .views import PermissionViewSet, RoleViewSet
def register_permission_urls(router, path): def register_permission_urls(router, path):
@ -9,4 +9,4 @@ def register_permission_urls(router, path):
Configure router for permission REST API. Configure router for permission REST API.
""" """
router.register(path + "/permission", PermissionViewSet) router.register(path + "/permission", PermissionViewSet)
router.register(path + "/roles", RolePermissionsViewSet) router.register(path + "/roles", RoleViewSet)

View File

@ -4,8 +4,8 @@
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from api.viewsets import ReadOnlyProtectedModelViewSet from api.viewsets import ReadOnlyProtectedModelViewSet
from .serializers import PermissionSerializer, RolePermissionsSerializer from .serializers import PermissionSerializer, RoleSerializer
from ..models import Permission, RolePermissions from ..models import Permission, Role
class PermissionViewSet(ReadOnlyProtectedModelViewSet): class PermissionViewSet(ReadOnlyProtectedModelViewSet):
@ -20,13 +20,13 @@ class PermissionViewSet(ReadOnlyProtectedModelViewSet):
filterset_fields = ['model', 'type', ] filterset_fields = ['model', 'type', ]
class RolePermissionsViewSet(ReadOnlyProtectedModelViewSet): class RoleViewSet(ReadOnlyProtectedModelViewSet):
""" """
REST API View set. REST API View set.
The djangorestframework plugin will get all `RolePermission` objects, serialize it to JSON with the given serializer The djangorestframework plugin will get all `RolePermission` objects, serialize it to JSON with the given serializer
then render it on /api/permission/roles/ then render it on /api/permission/roles/
""" """
queryset = RolePermissions.objects.all() queryset = Role.objects.all()
serializer_class = RolePermissionsSerializer serializer_class = RoleSerializer
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ['role', ] filterset_fields = ['role', ]

View File

@ -37,17 +37,17 @@ class PermissionBackend(ModelBackend):
return Permission.objects.none() return Permission.objects.none()
qs = Permission.objects.annotate( qs = Permission.objects.annotate(
club=F("rolepermissions__role__membership__club"), club=F("role__membership__club"),
membership=F("rolepermissions__role__membership"), membership=F("role__membership"),
).filter( ).filter(
( (
Q( Q(
rolepermissions__role__membership__date_start__lte=timezone.now().today(), role__membership__date_start__lte=timezone.now().today(),
rolepermissions__role__membership__date_end__gte=timezone.now().today(), role__membership__date_end__gte=timezone.now().today(),
) )
| Q(permanent=True) | Q(permanent=True)
) )
& Q(rolepermissions__role__membership__user=user) & Q(role__membership__user=user)
& Q(type=t) & Q(type=t)
& Q(mask__rank__lte=get_current_session().get("permission_mask", 0)) & Q(mask__rank__lte=get_current_session().get("permission_mask", 0))
) )

View File

@ -1,165 +1,4 @@
[ [
{
"model": "member.role",
"pk": 1,
"fields": {
"name": "Adh\u00e9rent BDE"
}
},
{
"model": "member.role",
"pk": 2,
"fields": {
"name": "Adh\u00e9rent Kfet"
}
},
{
"model": "member.role",
"pk": 3,
"fields": {
"name": "Membre de club"
}
},
{
"model": "member.role",
"pk": 4,
"fields": {
"name": "Bureau de club"
}
},
{
"model": "member.role",
"pk": 5,
"fields": {
"name": "Pr\u00e9sident\u00b7e de club"
}
},
{
"model": "member.role",
"pk": 6,
"fields": {
"name": "Tr\u00e9sorier\u00b7\u00e8re de club"
}
},
{
"model": "member.role",
"pk": 7,
"fields": {
"name": "Pr\u00e9sident\u00b7e BDE"
}
},
{
"model": "member.role",
"pk": 8,
"fields": {
"name": "Tr\u00e9sorier\u00b7\u00e8re BDE"
}
},
{
"model": "member.role",
"pk": 9,
"fields": {
"name": "Respo info"
}
},
{
"model": "member.role",
"pk": 10,
"fields": {
"name": "GC Kfet"
}
},
{
"model": "member.role",
"pk": 11,
"fields": {
"name": "Res[pot]"
}
},
{
"model": "member.role",
"pk": 12,
"fields": {
"name": "GC WEI"
}
},
{
"model": "member.role",
"pk": 13,
"fields": {
"name": "Chef de bus"
}
},
{
"model": "member.role",
"pk": 14,
"fields": {
"name": "Chef d'\u00e9quipe"
}
},
{
"model": "member.role",
"pk": 15,
"fields": {
"name": "\u00c9lectron libre"
}
},
{
"model": "member.role",
"pk": 16,
"fields": {
"name": "\u00c9lectron libre (avec perm)"
}
},
{
"model": "member.role",
"pk": 17,
"fields": {
"name": "1A"
}
},
{
"model": "member.role",
"pk": 18,
"fields": {
"name": "Adhérent WEI"
}
},
{
"model": "wei.weirole",
"pk": 12,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 13,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 14,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 15,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 16,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 17,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 18,
"fields": {}
},
{ {
"model": "permission.permissionmask", "model": "permission.permissionmask",
"pk": 1, "pk": 1,
@ -2217,10 +2056,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 1, "pk": 1,
"fields": { "fields": {
"role": 1, "for_club": 1,
"name": "Adh\u00e9rent BDE",
"permissions": [ "permissions": [
1, 1,
2, 2,
@ -2241,10 +2081,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 2, "pk": 2,
"fields": { "fields": {
"role": 2, "for_club": 2,
"name": "Adh\u00e9rent Kfet",
"permissions": [ "permissions": [
34, 34,
35, 35,
@ -2267,10 +2108,20 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 3,
"fields": {
"for_club": null,
"name": "Membre de club",
"permissions": []
}
},
{
"model": "permission.role",
"pk": 4, "pk": 4,
"fields": { "fields": {
"role": 4, "for_club": null,
"name": "Bureau de club",
"permissions": [ "permissions": [
22, 22,
47, 47,
@ -2279,10 +2130,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 5, "pk": 5,
"fields": { "fields": {
"role": 5, "for_club": null,
"name": "Pr\u00e9sident\u00b7e de club",
"permissions": [ "permissions": [
50, 50,
51, 51,
@ -2291,10 +2143,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 6, "pk": 6,
"fields": { "fields": {
"role": 6, "for_club": null,
"name": "Tr\u00e9sorier\u00b7\u00e8re de club",
"permissions": [ "permissions": [
59, 59,
19, 19,
@ -2309,10 +2162,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 7, "pk": 7,
"fields": { "fields": {
"role": 7, "for_club": 1,
"name": "Pr\u00e9sident\u00b7e BDE",
"permissions": [ "permissions": [
24, 24,
25, 25,
@ -2323,10 +2177,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 8, "pk": 8,
"fields": { "fields": {
"role": 8, "for_club": 1,
"name": "Tr\u00e9sorier\u00b7\u00e8re BDE",
"permissions": [ "permissions": [
23, 23,
24, 24,
@ -2359,10 +2214,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 9, "pk": 9,
"fields": { "fields": {
"role": 9, "for_club": 1,
"name": "Respo info",
"permissions": [ "permissions": [
1, 1,
2, 2,
@ -2494,10 +2350,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 10, "pk": 10,
"fields": { "fields": {
"role": 10, "for_club": 2,
"name": "GC Kfet",
"permissions": [ "permissions": [
32, 32,
33, 33,
@ -2521,10 +2378,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 11, "pk": 11,
"fields": { "fields": {
"role": 11, "for_club": 2,
"name": "Res[pot]",
"permissions": [ "permissions": [
37, 37,
38, 38,
@ -2538,10 +2396,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 12, "pk": 12,
"fields": { "fields": {
"role": 12, "for_club": null,
"name": "GC WEI",
"permissions": [ "permissions": [
76, 76,
80, 80,
@ -2571,10 +2430,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 13, "pk": 13,
"fields": { "fields": {
"role": 13, "for_club": null,
"name": "Chef de bus",
"permissions": [ "permissions": [
117, 117,
118, 118,
@ -2586,10 +2446,11 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 14, "pk": 14,
"fields": { "fields": {
"role": 14, "for_club": null,
"name": "Chef d'\u00e9quipe",
"permissions": [ "permissions": [
116, 116,
123, 123,
@ -2599,10 +2460,38 @@
} }
}, },
{ {
"model": "permission.rolepermissions", "model": "permission.role",
"pk": 15,
"fields": {
"for_club": null,
"name": "\u00c9lectron libre",
"permissions": []
}
},
{
"model": "permission.role",
"pk": 16, "pk": 16,
"fields": { "fields": {
"role": 18, "for_club": null,
"name": "\u00c9lectron libre (avec perm)",
"permissions": []
}
},
{
"model": "permission.role",
"pk": 17,
"fields": {
"for_club": null,
"name": "1A",
"permissions": []
}
},
{
"model": "permission.role",
"pk": 18,
"fields": {
"for_club": null,
"name": "Adhérent WEI",
"permissions": [ "permissions": [
97, 97,
99, 99,
@ -2618,5 +2507,40 @@
95 95
] ]
} }
},
{
"model": "wei.weirole",
"pk": 12,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 13,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 14,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 15,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 16,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 17,
"fields": {}
},
{
"model": "wei.weirole",
"pk": 18,
"fields": {}
} }
] ]

View File

@ -10,7 +10,6 @@ from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.db.models import F, Q, Model from django.db.models import F, Q, Model
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from member.models import Role
class InstancedPermission: class InstancedPermission:
@ -307,23 +306,30 @@ class Permission(models.Model):
return self.description return self.description
class RolePermissions(models.Model): class Role(models.Model):
""" """
Permissions associated with a Role Permissions associated with a Role
""" """
role = models.OneToOneField( name = models.CharField(
Role, max_length=255,
on_delete=models.PROTECT, verbose_name=_("name"),
related_name='permissions',
verbose_name=_('role'),
) )
permissions = models.ManyToManyField( permissions = models.ManyToManyField(
Permission, Permission,
verbose_name=_("permissions"), verbose_name=_("permissions"),
) )
for_club = models.ForeignKey(
"member.Club",
verbose_name=_("for club"),
on_delete=models.PROTECT,
null=True,
default=None,
)
def __str__(self): def __str__(self):
return str(self.role) return self.name
class Meta: class Meta:
verbose_name = _("role permissions") verbose_name = _("role permissions")

View File

@ -5,9 +5,10 @@ from datetime import date
from django.forms import HiddenInput from django.forms import HiddenInput
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView, TemplateView from django.views.generic import UpdateView, TemplateView
from member.models import Role, Membership from member.models import Membership
from .backends import PermissionBackend from .backends import PermissionBackend
from .models import Role
class ProtectQuerysetMixin: class ProtectQuerysetMixin:

View File

@ -15,10 +15,11 @@ from django.views.generic import CreateView, TemplateView, DetailView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from member.forms import ProfileForm from member.forms import ProfileForm
from member.models import Membership, Club, Role from member.models import Membership, Club
from note.models import SpecialTransaction from note.models import SpecialTransaction
from note.templatetags.pretty_money import pretty_money from note.templatetags.pretty_money import pretty_money
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
from .forms import SignUpForm, ValidationForm from .forms import SignUpForm, ValidationForm
@ -164,7 +165,7 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
:param kwargs: :param kwargs:
:return: :return:
""" """
qs = super().get_queryset().filter(profile__registration_valid=False) qs = super().get_queryset().distinct().filter(profile__registration_valid=False)
if "search" in self.request.GET: if "search" in self.request.GET:
pattern = self.request.GET["search"] pattern = self.request.GET["search"]

@ -1 +1 @@
Subproject commit 580948fe1da1904ba6418daafb48a0a64824a11b Subproject commit 85568dd4f5e24770fb2e3321100aeddcc28580a7

View File

@ -8,7 +8,6 @@ from crispy_forms.layout import Submit
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import DatePickerInput, AmountInput from note_kfet.inputs import DatePickerInput, AmountInput
from permission.backends import PermissionBackend
from .models import Invoice, Product, Remittance, SpecialTransactionProxy from .models import Invoice, Product, Remittance, SpecialTransactionProxy

View File

@ -241,7 +241,7 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
no_remittance_tr = SpecialTransactionTable( no_remittance_tr = SpecialTransactionTable(
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)), data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
specialtransactionproxy__remittance=None).filter( specialtransactionproxy__remittance=None).filter(
PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(), PermissionBackend.filter_queryset(self.request.user, Remittance, "view")).all(),
exclude=('remittance_remove', ), exclude=('remittance_remove', ),
prefix="no-remittance-", prefix="no-remittance-",
) )

View File

@ -96,7 +96,7 @@ class WEIMembershipForm(forms.ModelForm):
class BusForm(forms.ModelForm): class BusForm(forms.ModelForm):
class Meta: class Meta:
model = Bus model = Bus
fields = '__all__' exclude = ('information_json',)
widgets = { widgets = {
"wei": Autocomplete( "wei": Autocomplete(
WEIClub, WEIClub,

View File

@ -8,8 +8,9 @@ from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from member.models import Role, Club, Membership from member.models import Club, Membership
from note.models import MembershipTransaction from note.models import MembershipTransaction
from permission.models import Role
class WEIClub(Club): class WEIClub(Club):
@ -113,6 +114,7 @@ class BusTeam(models.Model):
name = models.CharField( name = models.CharField(
max_length=255, max_length=255,
verbose_name=_("name"),
) )
color = models.PositiveIntegerField( # Use a color picker to get the hexa code color = models.PositiveIntegerField( # Use a color picker to get the hexa code

View File

@ -144,10 +144,10 @@ class BusTable(tables.Table):
) )
def render_teams(self, value): def render_teams(self, value):
return ", ".join(team.name for team in value.all()) return ", ".join(team.name for team in value.order_by('name').all())
def render_count(self, value): def render_count(self, value):
return str(value) + " " + (str(_("members")) if value > 0 else str(_("member"))) return str(value) + " " + (str(_("members")) if value > 1 else str(_("member")))
class Meta: class Meta:
attrs = { attrs = {
@ -178,7 +178,7 @@ class BusTeamTable(tables.Table):
) )
def render_count(self, value): def render_count(self, value):
return str(value) + " " + (str(_("members")) if value > 0 else str(_("member"))) return str(value) + " " + (str(_("members")) if value > 1 else str(_("member")))
count = tables.Column( count = tables.Column(
verbose_name=_("Members count"), verbose_name=_("Members count"),

View File

@ -177,7 +177,7 @@ class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs).filter(club=self.club) qs = super().get_queryset(**kwargs).filter(club=self.club).distinct()
pattern = self.request.GET.get("search", "") pattern = self.request.GET.get("search", "")
@ -214,7 +214,7 @@ class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTable
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None) qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None).distinct()
pattern = self.request.GET.get("search", "") pattern = self.request.GET.get("search", "")
@ -330,7 +330,7 @@ class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
bus = self.object bus = self.object
teams = BusTeam.objects.filter(PermissionBackend.filter_queryset(self.request.user, BusTeam, "view")) \ teams = BusTeam.objects.filter(PermissionBackend.filter_queryset(self.request.user, BusTeam, "view")) \
.filter(bus=bus).annotate(count=Count("memberships")) .filter(bus=bus).annotate(count=Count("memberships")).order_by("name")
teams_table = BusTeamTable(data=teams, prefix="team-") teams_table = BusTeamTable(data=teams, prefix="team-")
context["teams"] = teams_table context["teams"] = teams_table

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-25 16:50+0200\n" "POT-Creation-Date: 2020-07-25 19:55+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -44,11 +44,11 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "" msgstr ""
#: apps/activity/models.py:23 apps/activity/models.py:48 #: apps/activity/models.py:23 apps/activity/models.py:48
#: apps/member/models.py:151 apps/member/models.py:255 #: apps/member/models.py:151 apps/note/models/notes.py:188
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:261 #: apps/note/models/transactions.py:261 apps/permission/models.py:315
#: apps/wei/models.py:64 templates/member/club_info.html:13 #: apps/wei/models.py:65 apps/wei/models.py:117
#: templates/member/profile_info.html:14 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16 #: templates/registration/future_profile_detail.html:16
#: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18
msgid "name" msgid "name"
@ -71,21 +71,21 @@ msgid "activity types"
msgstr "" msgstr ""
#: apps/activity/models.py:53 apps/note/models/transactions.py:81 #: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:103 apps/permission/models.py:182 #: apps/permission/models.py:102 apps/permission/models.py:181
#: apps/wei/models.py:70 apps/wei/models.py:126 #: apps/wei/models.py:71 apps/wei/models.py:128
#: templates/activity/activity_detail.html:16 #: templates/activity/activity_detail.html:16
msgid "description" msgid "description"
msgstr "" msgstr ""
#: apps/activity/models.py:60 apps/note/models/notes.py:164 #: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:66 apps/permission/models.py:157 #: apps/note/models/transactions.py:66 apps/permission/models.py:156
#: templates/activity/activity_detail.html:19 #: templates/activity/activity_detail.html:19
msgid "type" msgid "type"
msgstr "" msgstr ""
#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:277 #: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:259
#: apps/note/models/notes.py:117 apps/treasury/models.py:221 #: apps/note/models/notes.py:117 apps/treasury/models.py:221
#: apps/wei/models.py:157 templates/treasury/sogecredit_detail.html:14 #: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14
#: templates/wei/survey.html:16 #: templates/wei/survey.html:16
msgid "user" msgid "user"
msgstr "" msgstr ""
@ -187,12 +187,12 @@ msgid "Type"
msgstr "" msgstr ""
#: apps/activity/tables.py:77 apps/member/forms.py:83 #: apps/activity/tables.py:77 apps/member/forms.py:83
#: apps/registration/forms.py:64 apps/treasury/forms.py:121 #: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name" msgid "Last name"
msgstr "" msgstr ""
#: apps/activity/tables.py:79 apps/member/forms.py:88 #: apps/activity/tables.py:79 apps/member/forms.py:88
#: apps/registration/forms.py:69 apps/treasury/forms.py:123 #: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126 #: templates/note/transaction_form.html:126
msgid "First name" msgid "First name"
msgstr "" msgstr ""
@ -225,7 +225,7 @@ msgstr ""
msgid "IP Address" msgid "IP Address"
msgstr "" msgstr ""
#: apps/logs/models.py:35 apps/permission/models.py:127 #: apps/logs/models.py:35 apps/permission/models.py:126
msgid "model" msgid "model"
msgstr "" msgstr ""
@ -304,7 +304,7 @@ msgid "Credit amount"
msgstr "" msgstr ""
#: apps/member/forms.py:93 apps/registration/forms.py:74 #: apps/member/forms.py:93 apps/registration/forms.py:74
#: apps/treasury/forms.py:125 templates/note/transaction_form.html:132 #: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank" msgid "Bank"
msgstr "" msgstr ""
@ -480,7 +480,7 @@ msgid ""
"members can renew their membership." "members can renew their membership."
msgstr "" msgstr ""
#: apps/member/models.py:240 apps/member/models.py:283 #: apps/member/models.py:240 apps/member/models.py:265
#: apps/note/models/notes.py:139 #: apps/note/models/notes.py:139
msgid "club" msgid "club"
msgstr "" msgstr ""
@ -489,44 +489,45 @@ msgstr ""
msgid "clubs" msgid "clubs"
msgstr "" msgstr ""
#: apps/member/models.py:261 apps/permission/models.py:318 #: apps/member/models.py:270
msgid "role"
msgstr ""
#: apps/member/models.py:262 apps/member/models.py:288
msgid "roles" msgid "roles"
msgstr "" msgstr ""
#: apps/member/models.py:293 #: apps/member/models.py:275
msgid "membership starts on" msgid "membership starts on"
msgstr "" msgstr ""
#: apps/member/models.py:297 #: apps/member/models.py:279
msgid "membership ends on" msgid "membership ends on"
msgstr "" msgstr ""
#: apps/member/models.py:302 #: apps/member/models.py:284
msgid "fee" msgid "fee"
msgstr "" msgstr ""
#: apps/member/models.py:320 apps/member/views.py:521 apps/wei/views.py:768 #: apps/member/models.py:303 apps/member/views.py:527 apps/wei/views.py:768
msgid "User is not a member of the parent club" msgid "User is not a member of the parent club"
msgstr "" msgstr ""
#: apps/member/models.py:330 apps/member/views.py:530 #: apps/member/models.py:309
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr ""
#: apps/member/models.py:320 apps/member/views.py:536
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "" msgstr ""
#: apps/member/models.py:381 #: apps/member/models.py:371
#, python-brace-format #, python-brace-format
msgid "Membership of {user} for the club {club}" msgid "Membership of {user} for the club {club}"
msgstr "" msgstr ""
#: apps/member/models.py:384 #: apps/member/models.py:374
msgid "membership" msgid "membership"
msgstr "" msgstr ""
#: apps/member/models.py:385 #: apps/member/models.py:375
msgid "memberships" msgid "memberships"
msgstr "" msgstr ""
@ -534,41 +535,41 @@ msgstr ""
msgid "Renew" msgid "Renew"
msgstr "" msgstr ""
#: apps/member/views.py:62 apps/registration/forms.py:23 #: apps/member/views.py:64 apps/registration/forms.py:23
msgid "This address must be valid." msgid "This address must be valid."
msgstr "" msgstr ""
#: apps/member/views.py:65 templates/member/profile_info.html:47 #: apps/member/views.py:67 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48 #: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:124 #: templates/wei/weimembership_form.html:124
msgid "Update Profile" msgid "Update Profile"
msgstr "" msgstr ""
#: apps/member/views.py:75 #: apps/member/views.py:77
msgid "An alias with a similar name already exists." msgid "An alias with a similar name already exists."
msgstr "" msgstr ""
#: apps/member/views.py:181 #: apps/member/views.py:183
msgid "Search user" msgid "Search user"
msgstr "" msgstr ""
#: apps/member/views.py:516 apps/wei/views.py:759 #: apps/member/views.py:522 apps/wei/views.py:759
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."
msgstr "" msgstr ""
#: apps/member/views.py:534 #: apps/member/views.py:540
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:539 #: apps/member/views.py:545
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:556 apps/member/views.py:558 apps/member/views.py:560 #: apps/member/views.py:562 apps/member/views.py:564 apps/member/views.py:566
#: apps/registration/views.py:289 apps/registration/views.py:291 #: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:293 #: apps/registration/views.py:294
msgid "This field is required." msgid "This field is required."
msgstr "" msgstr ""
@ -834,63 +835,67 @@ msgstr ""
msgid "Consumptions" msgid "Consumptions"
msgstr "" msgstr ""
#: apps/permission/models.py:82 #: apps/permission/models.py:81
#, 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:84 #: apps/permission/models.py:83
#, python-brace-format #, python-brace-format
msgid "Can {type} {model} in {query}" msgid "Can {type} {model} in {query}"
msgstr "" msgstr ""
#: apps/permission/models.py:97 #: apps/permission/models.py:96
msgid "rank" msgid "rank"
msgstr "" msgstr ""
#: apps/permission/models.py:110 #: apps/permission/models.py:109
msgid "permission mask" msgid "permission mask"
msgstr "" msgstr ""
#: apps/permission/models.py:111 #: apps/permission/models.py:110
msgid "permission masks" msgid "permission masks"
msgstr "" msgstr ""
#: apps/permission/models.py:151 #: apps/permission/models.py:150
msgid "query" msgid "query"
msgstr "" msgstr ""
#: apps/permission/models.py:164 #: apps/permission/models.py:163
msgid "mask" msgid "mask"
msgstr "" msgstr ""
#: apps/permission/models.py:170 #: apps/permission/models.py:169
msgid "field" msgid "field"
msgstr "" msgstr ""
#: apps/permission/models.py:175 #: apps/permission/models.py:174
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."
msgstr "" msgstr ""
#: apps/permission/models.py:176 templates/permission/all_rights.html:26 #: apps/permission/models.py:175 templates/permission/all_rights.html:26
msgid "permanent" msgid "permanent"
msgstr "" msgstr ""
#: apps/permission/models.py:187 #: apps/permission/models.py:186
msgid "permission" msgid "permission"
msgstr "" msgstr ""
#: apps/permission/models.py:188 apps/permission/models.py:322 #: apps/permission/models.py:187 apps/permission/models.py:320
msgid "permissions" msgid "permissions"
msgstr "" msgstr ""
#: apps/permission/models.py:193 #: apps/permission/models.py:192
msgid "Specifying field applies only to view and change permission types." msgid "Specifying field applies only to view and change permission types."
msgstr "" msgstr ""
#: apps/permission/models.py:329 apps/permission/models.py:330 #: apps/permission/models.py:325
msgid "for club"
msgstr ""
#: apps/permission/models.py:335 apps/permission/models.py:336
msgid "role permissions" msgid "role permissions"
msgstr "" msgstr ""
@ -915,7 +920,7 @@ msgid ""
"{model_name}." "{model_name}."
msgstr "" msgstr ""
#: apps/permission/views.py:47 #: apps/permission/views.py:48
msgid "All rights" msgid "All rights"
msgstr "" msgstr ""
@ -941,31 +946,31 @@ msgstr ""
msgid "Join Kfet Club" msgid "Join Kfet Club"
msgstr "" msgstr ""
#: apps/registration/views.py:78 #: apps/registration/views.py:79
msgid "Email validation" msgid "Email validation"
msgstr "" msgstr ""
#: apps/registration/views.py:124 #: apps/registration/views.py:125
msgid "Email validation unsuccessful" msgid "Email validation unsuccessful"
msgstr "" msgstr ""
#: apps/registration/views.py:135 #: apps/registration/views.py:136
msgid "Email validation email sent" msgid "Email validation email sent"
msgstr "" msgstr ""
#: apps/registration/views.py:188 #: apps/registration/views.py:189
msgid "Unregistered users" msgid "Unregistered users"
msgstr "" msgstr ""
#: apps/registration/views.py:255 #: apps/registration/views.py:256
msgid "You must join the BDE." msgid "You must join the BDE."
msgstr "" msgstr ""
#: apps/registration/views.py:277 #: apps/registration/views.py:278
msgid "You must join BDE club before joining Kfet club." msgid "You must join BDE club before joining Kfet club."
msgstr "" msgstr ""
#: apps/registration/views.py:282 #: apps/registration/views.py:283
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 ""
@ -974,7 +979,7 @@ msgstr ""
msgid "Treasury" msgid "Treasury"
msgstr "" msgstr ""
#: apps/treasury/forms.py:85 apps/treasury/forms.py:133 #: apps/treasury/forms.py:84 apps/treasury/forms.py:132
#: templates/activity/activity_form.html:9 #: templates/activity/activity_form.html:9
#: templates/activity/activity_invite.html:8 #: templates/activity/activity_invite.html:8
#: templates/django_filters/rest_framework/form.html:5 #: templates/django_filters/rest_framework/form.html:5
@ -986,19 +991,19 @@ msgstr ""
msgid "Submit" msgid "Submit"
msgstr "" msgstr ""
#: apps/treasury/forms.py:87 #: apps/treasury/forms.py:86
msgid "Close" msgid "Close"
msgstr "" msgstr ""
#: apps/treasury/forms.py:96 #: apps/treasury/forms.py:95
msgid "Remittance is already closed." msgid "Remittance is already closed."
msgstr "" msgstr ""
#: apps/treasury/forms.py:101 #: apps/treasury/forms.py:100
msgid "You can't change the type of the remittance." msgid "You can't change the type of the remittance."
msgstr "" msgstr ""
#: apps/treasury/forms.py:127 apps/treasury/tables.py:47 #: apps/treasury/forms.py:126 apps/treasury/tables.py:47
#: apps/treasury/tables.py:113 templates/note/transaction_form.html:95 #: apps/treasury/tables.py:113 templates/note/transaction_form.html:95
#: templates/treasury/remittance_form.html:18 #: templates/treasury/remittance_form.html:18
msgid "Amount" msgid "Amount"
@ -1167,13 +1172,13 @@ msgstr ""
msgid "No" msgid "No"
msgstr "" msgstr ""
#: apps/wei/apps.py:10 apps/wei/models.py:47 apps/wei/models.py:48 #: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
#: apps/wei/models.py:59 apps/wei/models.py:164 templates/base.html:130 #: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:130
msgid "WEI" msgid "WEI"
msgstr "" msgstr ""
#: apps/wei/forms/registration.py:47 apps/wei/models.py:111 #: apps/wei/forms/registration.py:47 apps/wei/models.py:112
#: apps/wei/models.py:273 #: apps/wei/models.py:275
msgid "bus" msgid "bus"
msgstr "" msgstr ""
@ -1194,7 +1199,7 @@ msgid ""
msgstr "" msgstr ""
#: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67 #: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67
#: apps/wei/models.py:145 #: apps/wei/models.py:147
msgid "WEI Roles" msgid "WEI Roles"
msgstr "" msgstr ""
@ -1206,151 +1211,151 @@ msgstr ""
msgid "This team doesn't belong to the given bus." msgid "This team doesn't belong to the given bus."
msgstr "" msgstr ""
#: apps/wei/models.py:22 templates/wei/weiclub_info.html:23 #: apps/wei/models.py:23 templates/wei/weiclub_info.html:23
msgid "year" msgid "year"
msgstr "" msgstr ""
#: apps/wei/models.py:26 templates/wei/weiclub_info.html:17 #: apps/wei/models.py:27 templates/wei/weiclub_info.html:17
msgid "date start" msgid "date start"
msgstr "" msgstr ""
#: apps/wei/models.py:30 templates/wei/weiclub_info.html:20 #: apps/wei/models.py:31 templates/wei/weiclub_info.html:20
msgid "date end" msgid "date end"
msgstr "" msgstr ""
#: apps/wei/models.py:75 #: apps/wei/models.py:76
msgid "survey information" msgid "survey information"
msgstr "" msgstr ""
#: apps/wei/models.py:76 #: apps/wei/models.py:77
msgid "Information about the survey for new members, encoded in JSON" msgid "Information about the survey for new members, encoded in JSON"
msgstr "" msgstr ""
#: apps/wei/models.py:98 #: apps/wei/models.py:99
msgid "Bus" msgid "Bus"
msgstr "" msgstr ""
#: apps/wei/models.py:99 templates/wei/weiclub_tables.html:79 #: apps/wei/models.py:100 templates/wei/weiclub_tables.html:79
msgid "Buses" msgid "Buses"
msgstr "" msgstr ""
#: apps/wei/models.py:119 #: apps/wei/models.py:121
msgid "color" msgid "color"
msgstr "" msgstr ""
#: apps/wei/models.py:120 #: apps/wei/models.py:122
msgid "The color of the T-Shirt, stored with its number equivalent" msgid "The color of the T-Shirt, stored with its number equivalent"
msgstr "" msgstr ""
#: apps/wei/models.py:134 #: apps/wei/models.py:136
msgid "Bus team" msgid "Bus team"
msgstr "" msgstr ""
#: apps/wei/models.py:135 #: apps/wei/models.py:137
msgid "Bus teams" msgid "Bus teams"
msgstr "" msgstr ""
#: apps/wei/models.py:144 #: apps/wei/models.py:146
msgid "WEI Role" msgid "WEI Role"
msgstr "" msgstr ""
#: apps/wei/models.py:169 #: apps/wei/models.py:171
msgid "Credit from Société générale" msgid "Credit from Société générale"
msgstr "" msgstr ""
#: apps/wei/models.py:174 #: apps/wei/models.py:176
msgid "Caution check given" msgid "Caution check given"
msgstr "" msgstr ""
#: apps/wei/models.py:178 templates/wei/weimembership_form.html:62 #: apps/wei/models.py:180 templates/wei/weimembership_form.html:62
msgid "birth date" msgid "birth date"
msgstr "" msgstr ""
#: apps/wei/models.py:184 #: apps/wei/models.py:186
msgid "Male" msgid "Male"
msgstr "" msgstr ""
#: apps/wei/models.py:185 #: apps/wei/models.py:187
msgid "Female" msgid "Female"
msgstr "" msgstr ""
#: apps/wei/models.py:186 #: apps/wei/models.py:188
msgid "Non binary" msgid "Non binary"
msgstr "" msgstr ""
#: apps/wei/models.py:188 templates/wei/weimembership_form.html:59 #: apps/wei/models.py:190 templates/wei/weimembership_form.html:59
msgid "gender" msgid "gender"
msgstr "" msgstr ""
#: apps/wei/models.py:194 templates/wei/weimembership_form.html:65 #: apps/wei/models.py:196 templates/wei/weimembership_form.html:65
msgid "health issues" msgid "health issues"
msgstr "" msgstr ""
#: apps/wei/models.py:199 templates/wei/weimembership_form.html:68 #: apps/wei/models.py:201 templates/wei/weimembership_form.html:68
msgid "emergency contact name" msgid "emergency contact name"
msgstr "" msgstr ""
#: apps/wei/models.py:204 templates/wei/weimembership_form.html:71 #: apps/wei/models.py:206 templates/wei/weimembership_form.html:71
msgid "emergency contact phone" msgid "emergency contact phone"
msgstr "" msgstr ""
#: apps/wei/models.py:209 templates/wei/weimembership_form.html:74 #: apps/wei/models.py:211 templates/wei/weimembership_form.html:74
msgid "" msgid ""
"Register on the mailing list to stay informed of the events of the campus (1 " "Register on the mailing list to stay informed of the events of the campus (1 "
"mail/week)" "mail/week)"
msgstr "" msgstr ""
#: apps/wei/models.py:214 templates/wei/weimembership_form.html:77 #: apps/wei/models.py:216 templates/wei/weimembership_form.html:77
msgid "" msgid ""
"Register on the mailing list to stay informed of the sport events of the " "Register on the mailing list to stay informed of the sport events of the "
"campus (1 mail/week)" "campus (1 mail/week)"
msgstr "" msgstr ""
#: apps/wei/models.py:219 templates/wei/weimembership_form.html:80 #: apps/wei/models.py:221 templates/wei/weimembership_form.html:80
msgid "" msgid ""
"Register on the mailing list to stay informed of the art events of the " "Register on the mailing list to stay informed of the art events of the "
"campus (1 mail/week)" "campus (1 mail/week)"
msgstr "" msgstr ""
#: apps/wei/models.py:224 templates/wei/weimembership_form.html:56 #: apps/wei/models.py:226 templates/wei/weimembership_form.html:56
msgid "first year" msgid "first year"
msgstr "" msgstr ""
#: apps/wei/models.py:225 #: apps/wei/models.py:227
msgid "Tells if the user is new in the school." msgid "Tells if the user is new in the school."
msgstr "" msgstr ""
#: apps/wei/models.py:230 #: apps/wei/models.py:232
msgid "registration information" msgid "registration information"
msgstr "" msgstr ""
#: apps/wei/models.py:231 #: apps/wei/models.py:233
msgid "" msgid ""
"Information about the registration (buses for old members, survey fot the " "Information about the registration (buses for old members, survey fot the "
"new members), encoded in JSON" "new members), encoded in JSON"
msgstr "" msgstr ""
#: apps/wei/models.py:262 #: apps/wei/models.py:264
msgid "WEI User" msgid "WEI User"
msgstr "" msgstr ""
#: apps/wei/models.py:263 #: apps/wei/models.py:265
msgid "WEI Users" msgid "WEI Users"
msgstr "" msgstr ""
#: apps/wei/models.py:283 #: apps/wei/models.py:285
msgid "team" msgid "team"
msgstr "" msgstr ""
#: apps/wei/models.py:293 #: apps/wei/models.py:295
msgid "WEI registration" msgid "WEI registration"
msgstr "" msgstr ""
#: apps/wei/models.py:297 #: apps/wei/models.py:299
msgid "WEI membership" msgid "WEI membership"
msgstr "" msgstr ""
#: apps/wei/models.py:298 #: apps/wei/models.py:300
msgid "WEI memberships" msgid "WEI memberships"
msgstr "" msgstr ""
@ -1420,15 +1425,15 @@ msgstr ""
msgid "Survey WEI" msgid "Survey WEI"
msgstr "" msgstr ""
#: note_kfet/settings/base.py:154 #: note_kfet/settings/base.py:155
msgid "German" msgid "German"
msgstr "" msgstr ""
#: note_kfet/settings/base.py:155 #: note_kfet/settings/base.py:156
msgid "English" msgid "English"
msgstr "" msgstr ""
#: note_kfet/settings/base.py:156 #: note_kfet/settings/base.py:157
msgid "French" msgid "French"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-25 16:50+0200\n" "POT-Creation-Date: 2020-07-25 19:55+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -45,11 +45,11 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité." msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/activity/models.py:23 apps/activity/models.py:48 #: apps/activity/models.py:23 apps/activity/models.py:48
#: apps/member/models.py:151 apps/member/models.py:255 #: apps/member/models.py:151 apps/note/models/notes.py:188
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:261 #: apps/note/models/transactions.py:261 apps/permission/models.py:315
#: apps/wei/models.py:64 templates/member/club_info.html:13 #: apps/wei/models.py:65 apps/wei/models.py:117
#: templates/member/profile_info.html:14 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
#: templates/registration/future_profile_detail.html:16 #: templates/registration/future_profile_detail.html:16
#: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18
msgid "name" msgid "name"
@ -72,21 +72,21 @@ msgid "activity types"
msgstr "types d'activité" msgstr "types d'activité"
#: apps/activity/models.py:53 apps/note/models/transactions.py:81 #: apps/activity/models.py:53 apps/note/models/transactions.py:81
#: apps/permission/models.py:103 apps/permission/models.py:182 #: apps/permission/models.py:102 apps/permission/models.py:181
#: apps/wei/models.py:70 apps/wei/models.py:126 #: apps/wei/models.py:71 apps/wei/models.py:128
#: templates/activity/activity_detail.html:16 #: templates/activity/activity_detail.html:16
msgid "description" msgid "description"
msgstr "description" msgstr "description"
#: apps/activity/models.py:60 apps/note/models/notes.py:164 #: apps/activity/models.py:60 apps/note/models/notes.py:164
#: apps/note/models/transactions.py:66 apps/permission/models.py:157 #: apps/note/models/transactions.py:66 apps/permission/models.py:156
#: templates/activity/activity_detail.html:19 #: templates/activity/activity_detail.html:19
msgid "type" msgid "type"
msgstr "type" msgstr "type"
#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:277 #: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:259
#: apps/note/models/notes.py:117 apps/treasury/models.py:221 #: apps/note/models/notes.py:117 apps/treasury/models.py:221
#: apps/wei/models.py:157 templates/treasury/sogecredit_detail.html:14 #: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14
#: templates/wei/survey.html:16 #: templates/wei/survey.html:16
msgid "user" msgid "user"
msgstr "utilisateur" msgstr "utilisateur"
@ -188,12 +188,12 @@ msgid "Type"
msgstr "Type" msgstr "Type"
#: apps/activity/tables.py:77 apps/member/forms.py:83 #: apps/activity/tables.py:77 apps/member/forms.py:83
#: apps/registration/forms.py:64 apps/treasury/forms.py:121 #: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name" msgid "Last name"
msgstr "Nom de famille" msgstr "Nom de famille"
#: apps/activity/tables.py:79 apps/member/forms.py:88 #: apps/activity/tables.py:79 apps/member/forms.py:88
#: apps/registration/forms.py:69 apps/treasury/forms.py:123 #: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126 #: templates/note/transaction_form.html:126
msgid "First name" msgid "First name"
msgstr "Prénom" msgstr "Prénom"
@ -226,7 +226,7 @@ msgstr "Logs"
msgid "IP Address" msgid "IP Address"
msgstr "Adresse IP" msgstr "Adresse IP"
#: apps/logs/models.py:35 apps/permission/models.py:127 #: apps/logs/models.py:35 apps/permission/models.py:126
msgid "model" msgid "model"
msgstr "Modèle" msgstr "Modèle"
@ -305,7 +305,7 @@ msgid "Credit amount"
msgstr "Montant à créditer" msgstr "Montant à créditer"
#: apps/member/forms.py:93 apps/registration/forms.py:74 #: apps/member/forms.py:93 apps/registration/forms.py:74
#: apps/treasury/forms.py:125 templates/note/transaction_form.html:132 #: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank" msgid "Bank"
msgstr "Banque" msgstr "Banque"
@ -485,7 +485,7 @@ msgstr ""
"Combien de temps l'adhésion peut durer après le 1er Janvier de l'année " "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année "
"suivante avant que les adhérents peuvent renouveler leur adhésion." "suivante avant que les adhérents peuvent renouveler leur adhésion."
#: apps/member/models.py:240 apps/member/models.py:283 #: apps/member/models.py:240 apps/member/models.py:265
#: apps/note/models/notes.py:139 #: apps/note/models/notes.py:139
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -494,44 +494,45 @@ msgstr "club"
msgid "clubs" msgid "clubs"
msgstr "clubs" msgstr "clubs"
#: apps/member/models.py:261 apps/permission/models.py:318 #: apps/member/models.py:270
msgid "role"
msgstr "rôle"
#: apps/member/models.py:262 apps/member/models.py:288
msgid "roles" msgid "roles"
msgstr "rôles" msgstr "rôles"
#: apps/member/models.py:293 #: apps/member/models.py:275
msgid "membership starts on" msgid "membership starts on"
msgstr "l'adhésion commence le" msgstr "l'adhésion commence le"
#: apps/member/models.py:297 #: apps/member/models.py:279
msgid "membership ends on" msgid "membership ends on"
msgstr "l'adhésion finit le" msgstr "l'adhésion finit le"
#: apps/member/models.py:302 #: apps/member/models.py:284
msgid "fee" msgid "fee"
msgstr "cotisation" msgstr "cotisation"
#: apps/member/models.py:320 apps/member/views.py:521 apps/wei/views.py:768 #: apps/member/models.py:303 apps/member/views.py:527 apps/wei/views.py:768
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"
#: apps/member/models.py:330 apps/member/views.py:530 #: apps/member/models.py:309
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:320 apps/member/views.py:536
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:381 #: apps/member/models.py:371
#, python-brace-format #, python-brace-format
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:384 #: apps/member/models.py:374
msgid "membership" msgid "membership"
msgstr "adhésion" msgstr "adhésion"
#: apps/member/models.py:385 #: apps/member/models.py:375
msgid "memberships" msgid "memberships"
msgstr "adhésions" msgstr "adhésions"
@ -539,25 +540,25 @@ msgstr "adhésions"
msgid "Renew" msgid "Renew"
msgstr "Renouveler" msgstr "Renouveler"
#: apps/member/views.py:62 apps/registration/forms.py:23 #: apps/member/views.py:64 apps/registration/forms.py:23
msgid "This address must be valid." msgid "This address must be valid."
msgstr "Cette adresse doit être valide." msgstr "Cette adresse doit être valide."
#: apps/member/views.py:65 templates/member/profile_info.html:47 #: apps/member/views.py:67 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48 #: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:124 #: templates/wei/weimembership_form.html:124
msgid "Update Profile" msgid "Update Profile"
msgstr "Modifier le profil" msgstr "Modifier le profil"
#: apps/member/views.py:75 #: apps/member/views.py:77
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/views.py:181 #: apps/member/views.py:183
msgid "Search user" msgid "Search user"
msgstr "Chercher un utilisateur" msgstr "Chercher un utilisateur"
#: apps/member/views.py:516 apps/wei/views.py:759 #: apps/member/views.py:522 apps/wei/views.py:759
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."
@ -565,17 +566,17 @@ 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:534 #: apps/member/views.py:540
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:539 #: apps/member/views.py:545
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:556 apps/member/views.py:558 apps/member/views.py:560 #: apps/member/views.py:562 apps/member/views.py:564 apps/member/views.py:566
#: apps/registration/views.py:289 apps/registration/views.py:291 #: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:293 #: apps/registration/views.py:294
msgid "This field is required." msgid "This field is required."
msgstr "Ce champ est requis." msgstr "Ce champ est requis."
@ -724,7 +725,7 @@ msgstr "afficher"
#: apps/note/models/transactions.py:77 #: apps/note/models/transactions.py:77
msgid "highlighted" msgid "highlighted"
msgstr "" msgstr "mis en avant"
#: apps/note/models/transactions.py:87 #: apps/note/models/transactions.py:87
msgid "transaction template" msgid "transaction template"
@ -765,6 +766,8 @@ 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."
msgstr "" msgstr ""
"La transaction ne peut pas être sauvegardée puisque la note source ou la note "
"de destination n'est pas active."
#: apps/note/models/transactions.py:228 #: apps/note/models/transactions.py:228
#: templates/activity/activity_entry.html:13 templates/base.html:98 #: templates/activity/activity_entry.html:13 templates/base.html:98
@ -800,6 +803,8 @@ 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"
msgstr "" msgstr ""
"Une transaction spéciale n'est possible que entre une note associée à "
"un mode de paiement et un utilisateur ou un club."
#: apps/note/models/transactions.py:305 apps/note/models/transactions.py:310 #: apps/note/models/transactions.py:305 apps/note/models/transactions.py:310
msgid "membership transaction" msgid "membership transaction"
@ -842,41 +847,41 @@ msgstr "Transférer de l'argent"
msgid "Consumptions" msgid "Consumptions"
msgstr "Consommations" msgstr "Consommations"
#: apps/permission/models.py:82 #: apps/permission/models.py:81
#, 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:84 #: apps/permission/models.py:83
#, 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:97 #: apps/permission/models.py:96
msgid "rank" msgid "rank"
msgstr "Rang" msgstr "Rang"
#: apps/permission/models.py:110 #: apps/permission/models.py:109
msgid "permission mask" msgid "permission mask"
msgstr "masque de permissions" msgstr "masque de permissions"
#: apps/permission/models.py:111 #: apps/permission/models.py:110
msgid "permission masks" msgid "permission masks"
msgstr "masques de permissions" msgstr "masques de permissions"
#: apps/permission/models.py:151 #: apps/permission/models.py:150
msgid "query" msgid "query"
msgstr "requête" msgstr "requête"
#: apps/permission/models.py:164 #: apps/permission/models.py:163
msgid "mask" msgid "mask"
msgstr "masque" msgstr "masque"
#: apps/permission/models.py:170 #: apps/permission/models.py:169
msgid "field" msgid "field"
msgstr "champ" msgstr "champ"
#: apps/permission/models.py:175 #: apps/permission/models.py:174
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."
@ -884,25 +889,29 @@ 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:176 templates/permission/all_rights.html:26 #: apps/permission/models.py:175 templates/permission/all_rights.html:26
msgid "permanent" msgid "permanent"
msgstr "permanent" msgstr "permanent"
#: apps/permission/models.py:187 #: apps/permission/models.py:186
msgid "permission" msgid "permission"
msgstr "permission" msgstr "permission"
#: apps/permission/models.py:188 apps/permission/models.py:322 #: apps/permission/models.py:187 apps/permission/models.py:320
msgid "permissions" msgid "permissions"
msgstr "permissions" msgstr "permissions"
#: apps/permission/models.py:193 #: apps/permission/models.py:192
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:329 apps/permission/models.py:330 #: apps/permission/models.py:325
msgid "for club"
msgstr "s'applique au club"
#: apps/permission/models.py:335 apps/permission/models.py:336
msgid "role permissions" msgid "role permissions"
msgstr "Permissions par rôles" msgstr "Permissions par rôles"
@ -933,7 +942,7 @@ msgstr ""
"Vous n'avez pas la permission de supprimer cette instance du modèle " "Vous n'avez pas la permission de supprimer cette instance du modèle "
"{app_label}.{model_name}." "{app_label}.{model_name}."
#: apps/permission/views.py:47 #: apps/permission/views.py:48
msgid "All rights" msgid "All rights"
msgstr "Tous les droits" msgstr "Tous les droits"
@ -962,31 +971,31 @@ msgstr "Adhérer au club BDE"
msgid "Join Kfet Club" msgid "Join Kfet Club"
msgstr "Adhérer au club Kfet" msgstr "Adhérer au club Kfet"
#: apps/registration/views.py:78 #: apps/registration/views.py:79
msgid "Email validation" msgid "Email validation"
msgstr "Validation de l'adresse mail" msgstr "Validation de l'adresse mail"
#: apps/registration/views.py:124 #: apps/registration/views.py:125
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:135 #: apps/registration/views.py:136
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:188 #: apps/registration/views.py:189
msgid "Unregistered users" msgid "Unregistered users"
msgstr "Utilisateurs en attente d'inscription" msgstr "Utilisateurs en attente d'inscription"
#: apps/registration/views.py:255 #: apps/registration/views.py:256
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:277 #: apps/registration/views.py:278
msgid "You must join BDE club before joining Kfet club." msgid "You must join BDE club before joining Kfet club."
msgstr "Vous devez adhérer au club BDE avant d'adhérer au club Kfet." msgstr "Vous devez adhérer au club BDE avant d'adhérer au club Kfet."
#: apps/registration/views.py:282 #: apps/registration/views.py:283
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 ""
@ -997,7 +1006,7 @@ msgstr ""
msgid "Treasury" msgid "Treasury"
msgstr "Trésorerie" msgstr "Trésorerie"
#: apps/treasury/forms.py:85 apps/treasury/forms.py:133 #: apps/treasury/forms.py:84 apps/treasury/forms.py:132
#: templates/activity/activity_form.html:9 #: templates/activity/activity_form.html:9
#: templates/activity/activity_invite.html:8 #: templates/activity/activity_invite.html:8
#: templates/django_filters/rest_framework/form.html:5 #: templates/django_filters/rest_framework/form.html:5
@ -1009,19 +1018,19 @@ msgstr "Trésorerie"
msgid "Submit" msgid "Submit"
msgstr "Envoyer" msgstr "Envoyer"
#: apps/treasury/forms.py:87 #: apps/treasury/forms.py:86
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
#: apps/treasury/forms.py:96 #: apps/treasury/forms.py:95
msgid "Remittance is already closed." msgid "Remittance is already closed."
msgstr "La remise est déjà fermée." msgstr "La remise est déjà fermée."
#: apps/treasury/forms.py:101 #: apps/treasury/forms.py:100
msgid "You can't change the type of the remittance." msgid "You can't change the type of the remittance."
msgstr "Vous ne pouvez pas changer le type de la remise." msgstr "Vous ne pouvez pas changer le type de la remise."
#: apps/treasury/forms.py:127 apps/treasury/tables.py:47 #: apps/treasury/forms.py:126 apps/treasury/tables.py:47
#: apps/treasury/tables.py:113 templates/note/transaction_form.html:95 #: apps/treasury/tables.py:113 templates/note/transaction_form.html:95
#: templates/treasury/remittance_form.html:18 #: templates/treasury/remittance_form.html:18
msgid "Amount" msgid "Amount"
@ -1192,13 +1201,13 @@ msgstr "Oui"
msgid "No" msgid "No"
msgstr "Non" msgstr "Non"
#: apps/wei/apps.py:10 apps/wei/models.py:47 apps/wei/models.py:48 #: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
#: apps/wei/models.py:59 apps/wei/models.py:164 templates/base.html:130 #: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:130
msgid "WEI" msgid "WEI"
msgstr "WEI" msgstr "WEI"
#: apps/wei/forms/registration.py:47 apps/wei/models.py:111 #: apps/wei/forms/registration.py:47 apps/wei/models.py:112
#: apps/wei/models.py:273 #: apps/wei/models.py:275
msgid "bus" msgid "bus"
msgstr "Bus" msgstr "Bus"
@ -1224,7 +1233,7 @@ msgstr ""
"bus ou électron libre)" "bus ou électron libre)"
#: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67 #: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67
#: apps/wei/models.py:145 #: apps/wei/models.py:147
msgid "WEI Roles" msgid "WEI Roles"
msgstr "Rôles au WEI" msgstr "Rôles au WEI"
@ -1236,97 +1245,97 @@ msgstr "Sélectionnez les rôles qui vous intéressent."
msgid "This team doesn't belong to the given bus." msgid "This team doesn't belong to the given bus."
msgstr "Cette équipe n'appartient pas à ce bus." msgstr "Cette équipe n'appartient pas à ce bus."
#: apps/wei/models.py:22 templates/wei/weiclub_info.html:23 #: apps/wei/models.py:23 templates/wei/weiclub_info.html:23
msgid "year" msgid "year"
msgstr "année" msgstr "année"
#: apps/wei/models.py:26 templates/wei/weiclub_info.html:17 #: apps/wei/models.py:27 templates/wei/weiclub_info.html:17
msgid "date start" msgid "date start"
msgstr "début" msgstr "début"
#: apps/wei/models.py:30 templates/wei/weiclub_info.html:20 #: apps/wei/models.py:31 templates/wei/weiclub_info.html:20
msgid "date end" msgid "date end"
msgstr "fin" msgstr "fin"
#: apps/wei/models.py:75 #: apps/wei/models.py:76
msgid "survey information" msgid "survey information"
msgstr "informations sur le questionnaire" msgstr "informations sur le questionnaire"
#: apps/wei/models.py:76 #: apps/wei/models.py:77
msgid "Information about the survey for new members, encoded in JSON" msgid "Information about the survey for new members, encoded in JSON"
msgstr "" msgstr ""
"Informations sur le sondage pour les nouveaux membres, encodées en JSON" "Informations sur le sondage pour les nouveaux membres, encodées en JSON"
#: apps/wei/models.py:98 #: apps/wei/models.py:99
msgid "Bus" msgid "Bus"
msgstr "Bus" msgstr "Bus"
#: apps/wei/models.py:99 templates/wei/weiclub_tables.html:79 #: apps/wei/models.py:100 templates/wei/weiclub_tables.html:79
msgid "Buses" msgid "Buses"
msgstr "Bus" msgstr "Bus"
#: apps/wei/models.py:119 #: apps/wei/models.py:121
msgid "color" msgid "color"
msgstr "couleur" msgstr "couleur"
#: apps/wei/models.py:120 #: apps/wei/models.py:122
msgid "The color of the T-Shirt, stored with its number equivalent" msgid "The color of the T-Shirt, stored with its number equivalent"
msgstr "" msgstr ""
"La couleur du T-Shirt, stocké sous la forme de son équivalent numérique" "La couleur du T-Shirt, stocké sous la forme de son équivalent numérique"
#: apps/wei/models.py:134 #: apps/wei/models.py:136
msgid "Bus team" msgid "Bus team"
msgstr "Équipe de bus" msgstr "Équipe de bus"
#: apps/wei/models.py:135 #: apps/wei/models.py:137
msgid "Bus teams" msgid "Bus teams"
msgstr "Équipes de bus" msgstr "Équipes de bus"
#: apps/wei/models.py:144 #: apps/wei/models.py:146
msgid "WEI Role" msgid "WEI Role"
msgstr "Rôle au WEI" msgstr "Rôle au WEI"
#: apps/wei/models.py:169 #: apps/wei/models.py:171
msgid "Credit from Société générale" msgid "Credit from 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/wei/models.py:174 #: apps/wei/models.py:176
msgid "Caution check given" msgid "Caution check given"
msgstr "Chèque de caution donné" msgstr "Chèque de caution donné"
#: apps/wei/models.py:178 templates/wei/weimembership_form.html:62 #: apps/wei/models.py:180 templates/wei/weimembership_form.html:62
msgid "birth date" msgid "birth date"
msgstr "date de naissance" msgstr "date de naissance"
#: apps/wei/models.py:184 #: apps/wei/models.py:186
msgid "Male" msgid "Male"
msgstr "Homme" msgstr "Homme"
#: apps/wei/models.py:185 #: apps/wei/models.py:187
msgid "Female" msgid "Female"
msgstr "Femme" msgstr "Femme"
#: apps/wei/models.py:186 #: apps/wei/models.py:188
msgid "Non binary" msgid "Non binary"
msgstr "Non-binaire" msgstr "Non-binaire"
#: apps/wei/models.py:188 templates/wei/weimembership_form.html:59 #: apps/wei/models.py:190 templates/wei/weimembership_form.html:59
msgid "gender" msgid "gender"
msgstr "genre" msgstr "genre"
#: apps/wei/models.py:194 templates/wei/weimembership_form.html:65 #: apps/wei/models.py:196 templates/wei/weimembership_form.html:65
msgid "health issues" msgid "health issues"
msgstr "problèmes de santé" msgstr "problèmes de santé"
#: apps/wei/models.py:199 templates/wei/weimembership_form.html:68 #: apps/wei/models.py:201 templates/wei/weimembership_form.html:68
msgid "emergency contact name" msgid "emergency contact name"
msgstr "Nom du contact en cas d'urgence" msgstr "Nom du contact en cas d'urgence"
#: apps/wei/models.py:204 templates/wei/weimembership_form.html:71 #: apps/wei/models.py:206 templates/wei/weimembership_form.html:71
msgid "emergency contact phone" msgid "emergency contact phone"
msgstr "Téléphone du contact en cas d'urgence" msgstr "Téléphone du contact en cas d'urgence"
#: apps/wei/models.py:209 templates/wei/weimembership_form.html:74 #: apps/wei/models.py:211 templates/wei/weimembership_form.html:74
msgid "" msgid ""
"Register on the mailing list to stay informed of the events of the campus (1 " "Register on the mailing list to stay informed of the events of the campus (1 "
"mail/week)" "mail/week)"
@ -1334,7 +1343,7 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des événements sur " "S'inscrire sur la liste de diffusion pour rester informé des événements sur "
"le campus (1 mail par semaine)" "le campus (1 mail par semaine)"
#: apps/wei/models.py:214 templates/wei/weimembership_form.html:77 #: apps/wei/models.py:216 templates/wei/weimembership_form.html:77
msgid "" msgid ""
"Register on the mailing list to stay informed of the sport events of the " "Register on the mailing list to stay informed of the sport events of the "
"campus (1 mail/week)" "campus (1 mail/week)"
@ -1342,7 +1351,7 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités " "S'inscrire sur la liste de diffusion pour rester informé des actualités "
"sportives sur le campus (1 mail par semaine)" "sportives sur le campus (1 mail par semaine)"
#: apps/wei/models.py:219 templates/wei/weimembership_form.html:80 #: apps/wei/models.py:221 templates/wei/weimembership_form.html:80
msgid "" msgid ""
"Register on the mailing list to stay informed of the art events of the " "Register on the mailing list to stay informed of the art events of the "
"campus (1 mail/week)" "campus (1 mail/week)"
@ -1350,19 +1359,19 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités " "S'inscrire sur la liste de diffusion pour rester informé des actualités "
"artistiques sur le campus (1 mail par semaine)" "artistiques sur le campus (1 mail par semaine)"
#: apps/wei/models.py:224 templates/wei/weimembership_form.html:56 #: apps/wei/models.py:226 templates/wei/weimembership_form.html:56
msgid "first year" msgid "first year"
msgstr "première année" msgstr "première année"
#: apps/wei/models.py:225 #: apps/wei/models.py:227
msgid "Tells if the user is new in the school." msgid "Tells if the user is new in the school."
msgstr "Indique si l'utilisateur est nouveau dans l'école." msgstr "Indique si l'utilisateur est nouveau dans l'école."
#: apps/wei/models.py:230 #: apps/wei/models.py:232
msgid "registration information" msgid "registration information"
msgstr "informations sur l'inscription" msgstr "informations sur l'inscription"
#: apps/wei/models.py:231 #: apps/wei/models.py:233
msgid "" msgid ""
"Information about the registration (buses for old members, survey fot the " "Information about the registration (buses for old members, survey fot the "
"new members), encoded in JSON" "new members), encoded in JSON"
@ -1370,27 +1379,27 @@ msgstr ""
"Informations sur l'inscription (bus pour les 2A+, questionnaire pour les " "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les "
"1A), encodées en JSON" "1A), encodées en JSON"
#: apps/wei/models.py:262 #: apps/wei/models.py:264
msgid "WEI User" msgid "WEI User"
msgstr "Participant au WEI" msgstr "Participant au WEI"
#: apps/wei/models.py:263 #: apps/wei/models.py:265
msgid "WEI Users" msgid "WEI Users"
msgstr "Participants au WEI" msgstr "Participants au WEI"
#: apps/wei/models.py:283 #: apps/wei/models.py:285
msgid "team" msgid "team"
msgstr "équipe" msgstr "équipe"
#: apps/wei/models.py:293 #: apps/wei/models.py:295
msgid "WEI registration" msgid "WEI registration"
msgstr "inscription au WEI" msgstr "inscription au WEI"
#: apps/wei/models.py:297 #: apps/wei/models.py:299
msgid "WEI membership" msgid "WEI membership"
msgstr "adhésion au WEI" msgstr "adhésion au WEI"
#: apps/wei/models.py:298 #: apps/wei/models.py:300
msgid "WEI memberships" msgid "WEI memberships"
msgstr "adhésions au WEI" msgstr "adhésions au WEI"
@ -1462,15 +1471,15 @@ msgstr "Cet utilisateur n'a pas donné son chèque de caution."
msgid "Survey WEI" msgid "Survey WEI"
msgstr "Questionnaire WEI" msgstr "Questionnaire WEI"
#: note_kfet/settings/base.py:154 #: note_kfet/settings/base.py:155
msgid "German" msgid "German"
msgstr "Allemand" msgstr "Allemand"
#: note_kfet/settings/base.py:155 #: note_kfet/settings/base.py:156
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: note_kfet/settings/base.py:156 #: note_kfet/settings/base.py:157
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"

View File

@ -25,7 +25,7 @@ DATABASES = {
} }
# Break it, fix it! # Break it, fix it!
DEBUG = True DEBUG = False
# Mandatory ! # Mandatory !
ALLOWED_HOSTS = [os.environ.get('NOTE_URL', 'localhost')] ALLOWED_HOSTS = [os.environ.get('NOTE_URL', 'localhost')]
@ -36,7 +36,7 @@ SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'CHANGE_ME_IN_ENV_SETTINGS')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_SSL = False EMAIL_USE_SSL = False
EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.example.org') EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.example.org')
EMAIL_PORT = os.getenv('EMAIL_PORT', 443) EMAIL_PORT = os.getenv('EMAIL_PORT', 465)
EMAIL_HOST_USER = os.getenv('EMAIL_USER', 'change_me') EMAIL_HOST_USER = os.getenv('EMAIL_USER', 'change_me')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD', 'change_me') EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD', 'change_me')

View File

@ -1 +1 @@
django-cas-server==1.1.0 django-cas-server==1.2.0

View File

@ -15,14 +15,14 @@
{% regroup active_memberships by roles as memberships_per_role %} {% regroup active_memberships by roles as memberships_per_role %}
{% for role in roles %} {% for role in roles %}
<li class="{% if not role.clubs %}no-club{% endif %}"> <li class="{% if not role.clubs %}no-club{% endif %}">
{{ role }} {% if role.weirole %}(<em>Pour le WEI</em>){% endif %} {{ role }} {% if role.weirole %}(<em>Pour le WEI</em>){% endif %} {% if role.for_club %}(<em>Pour le club {{ role.for_club }} uniquement</em>){% endif %}
{% if role.clubs %} {% if role.clubs %}
<div class="alert alert-success"> <div class="alert alert-success">
{% trans "Own this role in the clubs" %} {{ role.clubs|join:", " }} {% trans "Own this role in the clubs" %} {{ role.clubs|join:", " }}
</div> </div>
{% endif %} {% endif %}
<ul> <ul>
{% for permission in role.permissions.permissions.all %} {% for permission in role.permissions.all %}
<li data-toggle="tooltip" title="{% trans "Query:" %} {{ permission.query }}">{{ permission }} ({{ permission.type }} {{ permission.model }}{% if permission.permanent %}, {% trans "permanent" %}{% endif %})</li> <li data-toggle="tooltip" title="{% trans "Query:" %} {{ permission.query }}">{{ permission }} ({{ permission.type }} {{ permission.model }}{% if permission.permanent %}, {% trans "permanent" %}{% endif %})</li>
{% empty %} {% empty %}
<em>{% trans "No associated permission" %}</em> <em>{% trans "No associated permission" %}</em>

View File

@ -5,6 +5,7 @@
\usepackage[french]{babel} \usepackage[french]{babel}
\usepackage[margin=1.5cm]{geometry} \usepackage[margin=1.5cm]{geometry}
\usepackage{lmodern}
\usepackage{ltablex} \usepackage{ltablex}
\usepackage{tabularx} \usepackage{tabularx}