Compare commits

...

4 Commits

Author SHA1 Message Date
Yohann D'ANELLO 8409ee4cc4 Display "Create WEI" button only for people that can create a WEI, see #53 2020-07-31 17:15:31 +02:00
Yohann D'ANELLO 9008baad3a Better alias research, closes #51 2020-07-31 17:07:14 +02:00
Yohann D'ANELLO fd705adb05 Filter members 2020-07-31 17:01:52 +02:00
Yohann D'ANELLO bd35e4e21e Separate club members in a dedicated page (WIP) 2020-07-31 13:17:16 +02:00
11 changed files with 326 additions and 101 deletions

View File

@ -130,3 +130,31 @@ class MembershipTable(tables.Table):
template_name = 'django_tables2/bootstrap4.html' template_name = 'django_tables2/bootstrap4.html'
fields = ('user', 'club', 'date_start', 'date_end', 'roles', 'fee', ) fields = ('user', 'club', 'date_start', 'date_end', 'roles', 'fee', )
model = Membership model = Membership
class ClubManagerTable(tables.Table):
"""
List managers of a club.
"""
def render_user(self, value):
# If the user has the right, link the displayed user with the page of its detail.
s = value.username
if PermissionBackend.check_perm(get_current_authenticated_user(), "auth.view_user", value):
s = format_html("<a href={url}>{name}</a>",
url=reverse_lazy('member:user_detail', kwargs={"pk": value.pk}), name=s)
return s
def render_roles(self, record):
roles = record.roles.all()
return ", ".join(str(role) for role in roles)
class Meta:
attrs = {
'class': 'table table-condensed table-striped table-hover',
'style': 'table-layout: fixed;'
}
template_name = 'django_tables2/bootstrap4.html'
fields = ('user', 'user.first_name', 'user.last_name', 'roles', )
model = Membership

View File

@ -16,6 +16,7 @@ urlpatterns = [
path('club/<int:pk>/update/', views.ClubUpdateView.as_view(), name="club_update"), path('club/<int:pk>/update/', views.ClubUpdateView.as_view(), name="club_update"),
path('club/<int:pk>/update_pic/', views.ClubPictureUpdateView.as_view(), name="club_update_pic"), path('club/<int:pk>/update_pic/', views.ClubPictureUpdateView.as_view(), name="club_update_pic"),
path('club/<int:pk>/aliases/', views.ClubAliasView.as_view(), name="club_alias"), path('club/<int:pk>/aliases/', views.ClubAliasView.as_view(), name="club_alias"),
path('club/<int:pk>/members/', views.ClubMembersListView.as_view(), name="club_members"),
path('user/', views.UserListView.as_view(), name="user_list"), path('user/', views.UserListView.as_view(), name="user_list"),
path('user/<int:pk>/', views.UserDetailView.as_view(), name="user_detail"), path('user/<int:pk>/', views.UserDetailView.as_view(), name="user_detail"),

View File

@ -13,6 +13,7 @@ from django.contrib.auth.views import LoginView
from django.db.models import Q from django.db.models import Q
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, UpdateView, TemplateView from django.views.generic import CreateView, DetailView, UpdateView, TemplateView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
@ -29,7 +30,7 @@ from permission.views import ProtectQuerysetMixin
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm
from .models import Club, Membership from .models import Club, Membership
from .tables import ClubTable, UserTable, MembershipTable from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable
class CustomLoginView(LoginView): class CustomLoginView(LoginView):
@ -337,6 +338,10 @@ 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 = Membership.objects.filter(club=self.object, roles__name="Bureau de club")\
.order_by('user__last_name').all()
context["managers"] = ClubManagerTable(data=managers, prefix="managers-")
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\ club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\ .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\
.order_by('-created_at') .order_by('-created_at')
@ -349,7 +354,7 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
).filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")) ).filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view"))
membership_table = MembershipTable(data=club_member, prefix="membership-") membership_table = MembershipTable(data=club_member, prefix="membership-")
membership_table.paginate(per_page=20, page=self.request.GET.get('membership-page', 1)) membership_table.paginate(per_page=5, page=self.request.GET.get('membership-page', 1))
context['member_list'] = membership_table context['member_list'] = membership_table
# Check if the user has the right to create a membership, to display the button. # Check if the user has the right to create a membership, to display the button.
@ -652,3 +657,52 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
def get_success_url(self): def get_success_url(self):
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id}) return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})
class ClubMembersListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
model = Membership
table_class = MembershipTable
template_name = "member/club_members.html"
extra_context = {"title": _("Members of the club")}
def get_queryset(self, **kwargs):
qs = super().get_queryset().filter(club_id=self.kwargs["pk"])
if 'search' in self.request.GET:
pattern = self.request.GET['search']
qs = qs.filter(
Q(user__first_name__iregex='^' + pattern) |
Q(user__last_name__iregex='^' + pattern) |
Q(user__note__alias__normalized_name__iregex='^' + Alias.normalize(pattern))
)
only_active = "only_active" not in self.request.GET or self.request.GET["only_active"] != '0'
if only_active:
qs = qs.filter(date_start__lte=timezone.now().today(), date_end__gte=timezone.now().today())
if "roles" in self.request.GET:
if not self.request.GET["roles"]:
return qs.none()
roles_str = self.request.GET["roles"].replace(' ', '').split(',')
roles_int = map(int, roles_str)
qs = qs.filter(roles__in=roles_int)
qs = qs.order_by('-date_start', 'user__username')
return qs.distinct()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
club = Club.objects.filter(
PermissionBackend.filter_queryset(self.request.user, Club, "view")
).get(pk=self.kwargs["pk"])
context["club"] = club
applicable_roles = Role.objects.filter(Q(weirole__isnull=not hasattr(club, 'weiclub'))
& (Q(for_club__isnull=True) | Q(for_club=club))).all()
context["applicable_roles"] = applicable_roles
context["only_active"] = "only_active" not in self.request.GET or self.request.GET["only_active"] != '0'
return context

View File

@ -106,7 +106,10 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet):
queryset = super().get_queryset() queryset = super().get_queryset()
alias = self.request.query_params.get("alias", ".*") alias = self.request.query_params.get("alias", ".*")
queryset = queryset.filter(normalized_name__iregex="^" + Alias.normalize(alias))\ queryset = queryset.filter(
Q(name__regex="^" + alias)
| Q(normalized_name__regex="^" + Alias.normalize(alias))
| Q(normalized_name__regex="^" + alias.lower()))\
.order_by('name').prefetch_related('note') .order_by('name').prefetch_related('note')
return queryset return queryset

View File

@ -54,6 +54,11 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
ordering = '-year' ordering = '-year'
extra_context = {"title": _("Search WEI")} extra_context = {"title": _("Search WEI")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["can_create_wei"] = PermissionBackend.check_perm(self.request.user, "wei.add_weiclub", WEIClub())
return context
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
""" """

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-30 17:22+0200\n" "POT-Creation-Date: 2020-07-31 17:00+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"
@ -186,12 +186,12 @@ msgstr ""
msgid "Type" msgid "Type"
msgstr "" msgstr ""
#: apps/activity/tables.py:77 apps/member/forms.py:104 #: apps/activity/tables.py:77 apps/member/forms.py:102
#: apps/registration/forms.py:64 apps/treasury/forms.py:120 #: 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:109 #: apps/activity/tables.py:79 apps/member/forms.py:107
#: apps/registration/forms.py:69 apps/treasury/forms.py:122 #: 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"
@ -261,12 +261,12 @@ msgstr ""
msgid "create" msgid "create"
msgstr "" msgstr ""
#: apps/logs/models.py:61 apps/note/tables.py:143 #: apps/logs/models.py:61 apps/note/tables.py:161
#: templates/activity/activity_detail.html:67 #: templates/activity/activity_detail.html:67
msgid "edit" msgid "edit"
msgstr "" msgstr ""
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:148 #: apps/logs/models.py:62 apps/note/tables.py:138 apps/note/tables.py:166
#: apps/wei/tables.py:65 #: apps/wei/tables.py:65
msgid "delete" msgid "delete"
msgstr "" msgstr ""
@ -295,39 +295,47 @@ msgstr ""
msgid "member" msgid "member"
msgstr "" msgstr ""
#: apps/member/forms.py:58 apps/member/views.py:81 #: apps/member/forms.py:58 apps/member/views.py:82
msgid "An alias with a similar name already exists." msgid "An alias with a similar name already exists."
msgstr "" msgstr ""
#: apps/member/forms.py:83 apps/registration/forms.py:44 #: apps/member/forms.py:81 apps/registration/forms.py:44
msgid "Inscription paid by Société Générale" msgid "Inscription paid by Société Générale"
msgstr "" msgstr ""
#: apps/member/forms.py:85 apps/registration/forms.py:46 #: apps/member/forms.py:83 apps/registration/forms.py:46
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 "" msgstr ""
#: apps/member/forms.py:90 apps/registration/forms.py:51 #: apps/member/forms.py:88 apps/registration/forms.py:51
msgid "Credit type" msgid "Credit type"
msgstr "" msgstr ""
#: apps/member/forms.py:91 apps/registration/forms.py:52 #: apps/member/forms.py:89 apps/registration/forms.py:52
msgid "No credit" msgid "No credit"
msgstr "" msgstr ""
#: apps/member/forms.py:93 #: apps/member/forms.py:91
msgid "You can credit the note of the user." msgid "You can credit the note of the user."
msgstr "" msgstr ""
#: apps/member/forms.py:97 apps/registration/forms.py:57 #: apps/member/forms.py:95 apps/registration/forms.py:57
msgid "Credit amount" msgid "Credit amount"
msgstr "" msgstr ""
#: apps/member/forms.py:114 apps/registration/forms.py:74 #: apps/member/forms.py:112 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:132 #: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank" msgid "Bank"
msgstr "" msgstr ""
#: apps/member/forms.py:138
msgid "User"
msgstr ""
#: apps/member/forms.py:152
msgid "Roles"
msgstr ""
#: apps/member/models.py:34 #: apps/member/models.py:34
#: templates/registration/future_profile_detail.html:40 #: templates/registration/future_profile_detail.html:40
#: templates/wei/weimembership_form.html:48 #: templates/wei/weimembership_form.html:48
@ -525,7 +533,7 @@ msgstr ""
msgid "fee" msgid "fee"
msgstr "" msgstr ""
#: apps/member/models.py:303 apps/member/views.py:535 apps/wei/views.py:787 #: apps/member/models.py:303 apps/member/views.py:534 apps/wei/views.py:787
msgid "User is not a member of the parent club" msgid "User is not a member of the parent club"
msgstr "" msgstr ""
@ -534,7 +542,7 @@ msgstr ""
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "" msgstr ""
#: apps/member/models.py:321 apps/member/views.py:544 #: apps/member/models.py:321 apps/member/views.py:543
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "" msgstr ""
@ -555,80 +563,84 @@ msgstr ""
msgid "Renew" msgid "Renew"
msgstr "" msgstr ""
#: apps/member/views.py:56 templates/member/profile_info.html:47 #: apps/member/views.py:57 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:130 #: templates/wei/weimembership_form.html:130
msgid "Update Profile" msgid "Update Profile"
msgstr "" msgstr ""
#: apps/member/views.py:69 apps/registration/forms.py:23 #: apps/member/views.py:70 apps/registration/forms.py:23
msgid "This address must be valid." msgid "This address must be valid."
msgstr "" msgstr ""
#: apps/member/views.py:126 #: apps/member/views.py:127
msgid "Profile detail" msgid "Profile detail"
msgstr "" msgstr ""
#: apps/member/views.py:160 #: apps/member/views.py:161
msgid "Search user" msgid "Search user"
msgstr "" msgstr ""
#: apps/member/views.py:194 apps/member/views.py:376 #: apps/member/views.py:195 apps/member/views.py:381
msgid "Note aliases" msgid "Note aliases"
msgstr "" msgstr ""
#: apps/member/views.py:208 #: apps/member/views.py:209
msgid "Update note picture" msgid "Update note picture"
msgstr "" msgstr ""
#: apps/member/views.py:266 templates/member/profile_info.html:43 #: apps/member/views.py:267 templates/member/profile_info.html:43
msgid "Manage auth token" msgid "Manage auth token"
msgstr "" msgstr ""
#: apps/member/views.py:294 #: apps/member/views.py:295
msgid "Create new club" msgid "Create new club"
msgstr "" msgstr ""
#: apps/member/views.py:306 #: apps/member/views.py:307
msgid "Search club" msgid "Search club"
msgstr "" msgstr ""
#: apps/member/views.py:331 #: apps/member/views.py:332
msgid "Club detail" msgid "Club detail"
msgstr "" msgstr ""
#: apps/member/views.py:393 #: apps/member/views.py:398
msgid "Update club" msgid "Update club"
msgstr "" msgstr ""
#: apps/member/views.py:427 #: apps/member/views.py:432
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "" msgstr ""
#: apps/member/views.py:530 apps/wei/views.py:778 #: apps/member/views.py:529 apps/wei/views.py:778
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:548 #: apps/member/views.py:547
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:553 #: apps/member/views.py:552
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:570 apps/member/views.py:572 apps/member/views.py:574 #: apps/member/views.py:569 apps/member/views.py:571 apps/member/views.py:573
#: apps/registration/views.py:295 apps/registration/views.py:297 #: apps/registration/views.py:295 apps/registration/views.py:297
#: apps/registration/views.py:299 #: apps/registration/views.py:299
msgid "This field is required." msgid "This field is required."
msgstr "" msgstr ""
#: apps/member/views.py:634 #: apps/member/views.py:641
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "" msgstr ""
#: apps/member/views.py:666
msgid "Members of the club"
msgstr ""
#: apps/note/admin.py:121 apps/note/models/transactions.py:106 #: apps/note/admin.py:121 apps/note/models/transactions.py:106
msgid "source" msgid "source"
msgstr "" msgstr ""
@ -784,7 +796,7 @@ msgid "transaction templates"
msgstr "" msgstr ""
#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125 #: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
#: apps/note/tables.py:33 apps/note/tables.py:42 #: apps/note/tables.py:35 apps/note/tables.py:44
msgid "used alias" msgid "used alias"
msgstr "" msgstr ""
@ -796,7 +808,7 @@ msgstr ""
msgid "reason" msgid "reason"
msgstr "" msgstr ""
#: apps/note/models/transactions.py:151 apps/note/tables.py:95 #: apps/note/models/transactions.py:151 apps/note/tables.py:113
msgid "invalidity reason" msgid "invalidity reason"
msgstr "" msgstr ""
@ -858,25 +870,25 @@ msgstr ""
msgid "membership transactions" msgid "membership transactions"
msgstr "" msgstr ""
#: apps/note/tables.py:57 #: apps/note/tables.py:63
msgid "Click to invalidate" msgid "Click to invalidate"
msgstr "" msgstr ""
#: apps/note/tables.py:57 #: apps/note/tables.py:63
msgid "Click to validate" msgid "Click to validate"
msgstr "" msgstr ""
#: apps/note/tables.py:93 #: apps/note/tables.py:111
msgid "No reason specified" msgid "No reason specified"
msgstr "" msgstr ""
#: apps/note/tables.py:122 apps/note/tables.py:150 apps/wei/tables.py:66 #: apps/note/tables.py:140 apps/note/tables.py:168 apps/wei/tables.py:66
#: templates/treasury/sogecredit_detail.html:59 #: templates/treasury/sogecredit_detail.html:59
#: templates/wei/weiregistration_confirm_delete.html:32 #: templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
#: apps/note/tables.py:145 apps/wei/tables.py:42 apps/wei/tables.py:43 #: apps/note/tables.py:163 apps/wei/tables.py:42 apps/wei/tables.py:43
#: templates/member/club_info.html:67 templates/note/conso_form.html:128 #: templates/member/club_info.html:67 templates/note/conso_form.html:128
#: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
#: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
@ -1828,11 +1840,28 @@ msgstr ""
msgid "Club listing" msgid "Club listing"
msgstr "" msgstr ""
#: templates/member/club_tables.html:7 #: templates/member/club_members.html:16
msgid "Member of the Club" msgid "Display only active memberships"
msgstr "" msgstr ""
#: templates/member/club_tables.html:20 templates/member/profile_tables.html:28 #: templates/member/club_members.html:21
msgid "Filter roles:"
msgstr ""
#: templates/member/club_members.html:37
#: templates/wei/weimembership_list.html:18
msgid "There is no membership found with this pattern."
msgstr ""
#: templates/member/club_tables.html:7
msgid "Club managers"
msgstr ""
#: templates/member/club_tables.html:20
msgid "Club members"
msgstr ""
#: templates/member/club_tables.html:33 templates/member/profile_tables.html:28
#: templates/wei/weiclub_tables.html:105 #: templates/wei/weiclub_tables.html:105
msgid "Transaction history" msgid "Transaction history"
msgstr "" msgstr ""
@ -2469,10 +2498,6 @@ msgid ""
" " " "
msgstr "" msgstr ""
#: templates/wei/weimembership_list.html:18
msgid "There is no membership found with this pattern."
msgstr ""
#: templates/wei/weimembership_list.html:24 #: templates/wei/weimembership_list.html:24
msgid "View unvalidated registrations..." msgid "View unvalidated registrations..."
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-30 17:22+0200\n" "POT-Creation-Date: 2020-07-31 17:00+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"
@ -187,12 +187,12 @@ msgstr "supprimer"
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#: apps/activity/tables.py:77 apps/member/forms.py:104 #: apps/activity/tables.py:77 apps/member/forms.py:102
#: apps/registration/forms.py:64 apps/treasury/forms.py:120 #: 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:109 #: apps/activity/tables.py:79 apps/member/forms.py:107
#: apps/registration/forms.py:69 apps/treasury/forms.py:122 #: 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"
@ -262,12 +262,12 @@ msgstr "Nouvelles données"
msgid "create" msgid "create"
msgstr "Créer" msgstr "Créer"
#: apps/logs/models.py:61 apps/note/tables.py:143 #: apps/logs/models.py:61 apps/note/tables.py:161
#: templates/activity/activity_detail.html:67 #: templates/activity/activity_detail.html:67
msgid "edit" msgid "edit"
msgstr "Modifier" msgstr "Modifier"
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:148 #: apps/logs/models.py:62 apps/note/tables.py:138 apps/note/tables.py:166
#: apps/wei/tables.py:65 #: apps/wei/tables.py:65
msgid "delete" msgid "delete"
msgstr "Supprimer" msgstr "Supprimer"
@ -296,39 +296,47 @@ msgstr "journaux de modifications"
msgid "member" msgid "member"
msgstr "adhérent" msgstr "adhérent"
#: apps/member/forms.py:58 apps/member/views.py:81 #: apps/member/forms.py:58 apps/member/views.py:82
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:83 apps/registration/forms.py:44 #: apps/member/forms.py:81 apps/registration/forms.py:44
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:85 apps/registration/forms.py:46 #: apps/member/forms.py:83 apps/registration/forms.py:46
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."
#: apps/member/forms.py:90 apps/registration/forms.py:51 #: apps/member/forms.py:88 apps/registration/forms.py:51
msgid "Credit type" msgid "Credit type"
msgstr "Type de rechargement" msgstr "Type de rechargement"
#: apps/member/forms.py:91 apps/registration/forms.py:52 #: apps/member/forms.py:89 apps/registration/forms.py:52
msgid "No credit" msgid "No credit"
msgstr "Pas de rechargement" msgstr "Pas de rechargement"
#: apps/member/forms.py:93 #: apps/member/forms.py:91
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'utisateur avant l'adhésion." msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion."
#: apps/member/forms.py:97 apps/registration/forms.py:57 #: apps/member/forms.py:95 apps/registration/forms.py:57
msgid "Credit amount" msgid "Credit amount"
msgstr "Montant à créditer" msgstr "Montant à créditer"
#: apps/member/forms.py:114 apps/registration/forms.py:74 #: apps/member/forms.py:112 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 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"
#: apps/member/forms.py:138
msgid "User"
msgstr "Utilisateur"
#: apps/member/forms.py:152
msgid "Roles"
msgstr "Rôles"
#: apps/member/models.py:34 #: apps/member/models.py:34
#: templates/registration/future_profile_detail.html:40 #: templates/registration/future_profile_detail.html:40
#: templates/wei/weimembership_form.html:48 #: templates/wei/weimembership_form.html:48
@ -530,7 +538,7 @@ msgstr "l'adhésion finit le"
msgid "fee" msgid "fee"
msgstr "cotisation" msgstr "cotisation"
#: apps/member/models.py:303 apps/member/views.py:535 apps/wei/views.py:787 #: apps/member/models.py:303 apps/member/views.py:534 apps/wei/views.py:787
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"
@ -539,7 +547,7 @@ msgstr "L'utilisateur n'est pas membre du club parent"
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:321 apps/member/views.py:544 #: apps/member/models.py:321 apps/member/views.py:543
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"
@ -560,57 +568,57 @@ msgstr "adhésions"
msgid "Renew" msgid "Renew"
msgstr "Renouveler" msgstr "Renouveler"
#: apps/member/views.py:56 templates/member/profile_info.html:47 #: apps/member/views.py:57 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:130 #: templates/wei/weimembership_form.html:130
msgid "Update Profile" msgid "Update Profile"
msgstr "Modifier le profil" msgstr "Modifier le profil"
#: apps/member/views.py:69 apps/registration/forms.py:23 #: apps/member/views.py:70 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:126 #: apps/member/views.py:127
msgid "Profile detail" msgid "Profile detail"
msgstr "Détails de l'utilisateur" msgstr "Détails de l'utilisateur"
#: apps/member/views.py:160 #: apps/member/views.py:161
msgid "Search user" msgid "Search user"
msgstr "Chercher un utilisateur" msgstr "Chercher un utilisateur"
#: apps/member/views.py:194 apps/member/views.py:376 #: apps/member/views.py:195 apps/member/views.py:381
msgid "Note aliases" msgid "Note aliases"
msgstr "Alias de la note" msgstr "Alias de la note"
#: apps/member/views.py:208 #: apps/member/views.py:209
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:266 templates/member/profile_info.html:43 #: apps/member/views.py:267 templates/member/profile_info.html:43
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:294 #: apps/member/views.py:295
msgid "Create new club" msgid "Create new club"
msgstr "Créer un nouveau club" msgstr "Créer un nouveau club"
#: apps/member/views.py:306 #: apps/member/views.py:307
msgid "Search club" msgid "Search club"
msgstr "Chercher un club" msgstr "Chercher un club"
#: apps/member/views.py:331 #: apps/member/views.py:332
msgid "Club detail" msgid "Club detail"
msgstr "Détails du club" msgstr "Détails du club"
#: apps/member/views.py:393 #: apps/member/views.py:398
msgid "Update club" msgid "Update club"
msgstr "Modifier le club" msgstr "Modifier le club"
#: apps/member/views.py:427 #: apps/member/views.py:432
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:530 apps/wei/views.py:778 #: apps/member/views.py:529 apps/wei/views.py:778
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."
@ -618,24 +626,28 @@ 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:548 #: apps/member/views.py:547
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:553 #: apps/member/views.py:552
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:570 apps/member/views.py:572 apps/member/views.py:574 #: apps/member/views.py:569 apps/member/views.py:571 apps/member/views.py:573
#: apps/registration/views.py:295 apps/registration/views.py:297 #: apps/registration/views.py:295 apps/registration/views.py:297
#: apps/registration/views.py:299 #: apps/registration/views.py:299
msgid "This field is required." msgid "This field is required."
msgstr "Ce champ est requis." msgstr "Ce champ est requis."
#: apps/member/views.py:634 #: apps/member/views.py:641
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:666
msgid "Members of the club"
msgstr "Membres du club"
#: apps/note/admin.py:121 apps/note/models/transactions.py:106 #: apps/note/admin.py:121 apps/note/models/transactions.py:106
msgid "source" msgid "source"
msgstr "source" msgstr "source"
@ -792,7 +804,7 @@ msgid "transaction templates"
msgstr "modèles de transaction" msgstr "modèles de transaction"
#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125 #: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
#: apps/note/tables.py:33 apps/note/tables.py:42 #: apps/note/tables.py:35 apps/note/tables.py:44
msgid "used alias" msgid "used alias"
msgstr "alias utilisé" msgstr "alias utilisé"
@ -804,7 +816,7 @@ msgstr "quantité"
msgid "reason" msgid "reason"
msgstr "raison" msgstr "raison"
#: apps/note/models/transactions.py:151 apps/note/tables.py:95 #: apps/note/models/transactions.py:151 apps/note/tables.py:113
msgid "invalidity reason" msgid "invalidity reason"
msgstr "Motif d'invalidité" msgstr "Motif d'invalidité"
@ -870,25 +882,25 @@ msgstr "Transaction d'adhésion"
msgid "membership transactions" msgid "membership transactions"
msgstr "Transactions d'adhésion" msgstr "Transactions d'adhésion"
#: apps/note/tables.py:57 #: apps/note/tables.py:63
msgid "Click to invalidate" msgid "Click to invalidate"
msgstr "Cliquez pour dévalider" msgstr "Cliquez pour dévalider"
#: apps/note/tables.py:57 #: apps/note/tables.py:63
msgid "Click to validate" msgid "Click to validate"
msgstr "Cliquez pour valider" msgstr "Cliquez pour valider"
#: apps/note/tables.py:93 #: apps/note/tables.py:111
msgid "No reason specified" msgid "No reason specified"
msgstr "Pas de motif spécifié" msgstr "Pas de motif spécifié"
#: apps/note/tables.py:122 apps/note/tables.py:150 apps/wei/tables.py:66 #: apps/note/tables.py:140 apps/note/tables.py:168 apps/wei/tables.py:66
#: templates/treasury/sogecredit_detail.html:59 #: templates/treasury/sogecredit_detail.html:59
#: templates/wei/weiregistration_confirm_delete.html:32 #: templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: apps/note/tables.py:145 apps/wei/tables.py:42 apps/wei/tables.py:43 #: apps/note/tables.py:163 apps/wei/tables.py:42 apps/wei/tables.py:43
#: templates/member/club_info.html:67 templates/note/conso_form.html:128 #: templates/member/club_info.html:67 templates/note/conso_form.html:128
#: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
#: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
@ -1888,11 +1900,28 @@ msgstr "Créer un club"
msgid "Club listing" msgid "Club listing"
msgstr "Liste des clubs" msgstr "Liste des clubs"
#: templates/member/club_tables.html:7 #: templates/member/club_members.html:16
msgid "Member of the Club" msgid "Display only active memberships"
msgstr "Membre du club" msgstr "N'afficher que les adhésions encore valides"
#: templates/member/club_tables.html:20 templates/member/profile_tables.html:28 #: templates/member/club_members.html:21
msgid "Filter roles:"
msgstr "Filtrer par rôle :"
#: templates/member/club_members.html:37
#: templates/wei/weimembership_list.html:18
msgid "There is no membership found with this pattern."
msgstr "Il n'y a pas d'adhésion trouvée avec cette entrée."
#: templates/member/club_tables.html:7
msgid "Club managers"
msgstr "Bureau du club"
#: templates/member/club_tables.html:20
msgid "Club members"
msgstr "Membres du club"
#: templates/member/club_tables.html:33 templates/member/profile_tables.html:28
#: templates/wei/weiclub_tables.html:105 #: templates/wei/weiclub_tables.html:105
msgid "Transaction history" msgid "Transaction history"
msgstr "Historique des transactions" msgstr "Historique des transactions"
@ -2591,10 +2620,6 @@ msgstr ""
"l'inscription au WEI.\n" "l'inscription au WEI.\n"
" " " "
#: templates/wei/weimembership_list.html:18
msgid "There is no membership found with this pattern."
msgstr "Il n'y a pas d'adhésion trouvée avec cette entrée."
#: templates/wei/weimembership_list.html:24 #: templates/wei/weimembership_list.html:24
msgid "View unvalidated registrations..." msgid "View unvalidated registrations..."
msgstr "Voir les inscriptions non validées ..." msgstr "Voir les inscriptions non validées ..."

View File

@ -11,7 +11,7 @@
<div class="card-body" id="profile_infos"> <div class="card-body" id="profile_infos">
<dl class="row"> <dl class="row">
<dt class="col-xl-6">{% trans 'name'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'name'|capfirst %}</dt>
<dd class="col-xl-6">{{ club.name}}</dd> <dd class="col-xl-6">{{ club.name }}</dd>
{% if club.parent_club %} {% if club.parent_club %}
<dt class="col-xl-6"><a href="{% url 'member:club_detail' club.parent_club.pk %}">{% trans 'Club Parent'|capfirst %}</a></dt> <dt class="col-xl-6"><a href="{% url 'member:club_detail' club.parent_club.pk %}">{% trans 'Club Parent'|capfirst %}</a></dt>

View File

@ -0,0 +1,69 @@
{% extends "member/noteowner_detail.html" %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block profile_info %}
{% include "member/club_info.html" %}
{% endblock %}
{% block profile_content %}
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
<div class="form-group">
<div class="form-check">
<label class="form-check-label" for="only_active">
<input type="checkbox" class="checkboxinput form-check-input" id="only_active"
{% if only_active %}checked{% endif %}>
{% trans "Display only active memberships" %}
</label>
</div>
</div>
<div id="div_id_roles" class="form-group">
<label for="id_roles" class="col-form-label">{% trans "Filter roles:" %}</label>
<div class="">
<select name="roles" class="selectmultiple form-control" id="roles" multiple="">
{% for role in applicable_roles %}
<option value="{{ role.id }}" selected>{{ role.name }}</option>
{% endfor %}
</select>
</div>
</div>
<hr>
<div id="memberships_table">
{% if table.data %}
{% render_table table %}
{% else %}
<div class="alert alert-warning">
{% trans "There is no membership found with this pattern." %}
</div>
{% endif %}
</div>
{% endblock %}
{% block extrajavascript %}
<script type="text/javascript">
$(document).ready(function () {
let searchbar_obj = $("#searchbar");
let only_active_obj = $("#only_active");
let roles_obj = $("#roles");
function reloadTable() {
let pattern = searchbar_obj.val();
let roles = [];
$("#roles option:selected").each(function() {
roles.push($(this).val());
});
let roles_str = roles.join(',');
$("#memberships_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20")
+ "&only_active=" + (only_active_obj.is(':checked') ? '1' : '0')
+ "&roles=" + roles_str + " #memberships_table");
}
searchbar_obj.keyup(reloadTable);
only_active_obj.change(reloadTable);
roles_obj.change(reloadTable);
});
</script>
{% endblock %}

View File

@ -1,10 +1,23 @@
{% load render_table from django_tables2 %} {% load render_table from django_tables2 %}
{% load i18n %} {% load i18n %}
{% if member_list.data %} {% if managers.data %}
<div class="card"> <div class="card">
<div class="card-header position-relative" id="clubListHeading"> <div class="card-header position-relative" id="clubListHeading">
<a class="btn btn-link stretched-link font-weight-bold"> <a class="btn btn-link stretched-link font-weight-bold">
<i class="fa fa-users"></i> {% trans "Member of the Club" %} <i class="fa fa-users"></i> {% trans "Club managers" %}
</a>
</div>
{% render_table managers %}
</div>
<hr>
{% endif %}
{% if member_list.data %}
<div class="card">
<div class="card-header position-relative" id="clubListHeading">
<a class="btn btn-link stretched-link font-weight-bold" href="{% url 'member:club_members' pk=club.pk %}">
<i class="fa fa-users"></i> {% trans "Club members" %}
</a> </a>
</div> </div>
{% render_table member_list %} {% render_table member_list %}

View File

@ -5,8 +5,10 @@
<div class="row justify-content-center mb-4"> <div class="row justify-content-center mb-4">
<div class="col-md-10 text-center"> <div class="col-md-10 text-center">
<input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved()" id="search_field"/> <input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved()" id="search_field"/>
{% if can_create_wei %}
<hr> <hr>
<a class="btn btn-primary text-center my-4" href="{% url 'wei:wei_create' %}">{% trans "Create WEI" %}</a> <a class="btn btn-primary text-center my-4" href="{% url 'wei:wei_create' %}">{% trans "Create WEI" %}</a>
{% endif %}
</div> </div>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-center">