mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
Restructurate memberships, closes #16
This commit is contained in:
parent
e98693b214
commit
bf9789bd9e
@ -7,9 +7,9 @@
|
||||
"email": "tresorerie.bde@example.com",
|
||||
"require_memberships": true,
|
||||
"membership_fee": 500,
|
||||
"membership_duration": "396 00:00:00",
|
||||
"membership_start": "213 00:00:00",
|
||||
"membership_end": "273 00:00:00"
|
||||
"membership_duration": 396,
|
||||
"membership_start": "2019-08-31",
|
||||
"membership_end": "2020-09-30"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -20,9 +20,9 @@
|
||||
"email": "tresorerie.bde@example.com",
|
||||
"require_memberships": true,
|
||||
"membership_fee": 3500,
|
||||
"membership_duration": "396 00:00:00",
|
||||
"membership_start": "213 00:00:00",
|
||||
"membership_end": "273 00:00:00"
|
||||
"membership_duration": 396,
|
||||
"membership_start": "2019-08-31",
|
||||
"membership_end": "2020-09-30"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1,13 +1,10 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from crispy_forms.bootstrap import Div
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Layout
|
||||
from django import forms
|
||||
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
|
||||
from django.contrib.auth.models import User
|
||||
from note_kfet.inputs import Autocomplete, AmountInput
|
||||
from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput
|
||||
from permission.models import PermissionMask
|
||||
|
||||
from .models import Profile, Club, Membership
|
||||
@ -55,6 +52,8 @@ class ClubForm(forms.ModelForm):
|
||||
'api_url': '/api/members/club/',
|
||||
}
|
||||
),
|
||||
"membership_start": DatePickerInput(),
|
||||
"membership_end": DatePickerInput(),
|
||||
}
|
||||
|
||||
|
||||
@ -80,28 +79,5 @@ class MembershipForm(forms.ModelForm):
|
||||
'placeholder': 'Nom ...',
|
||||
},
|
||||
),
|
||||
'date_start': DatePickerInput(),
|
||||
}
|
||||
|
||||
|
||||
MemberFormSet = forms.modelformset_factory(
|
||||
Membership,
|
||||
form=MembershipForm,
|
||||
extra=2,
|
||||
can_delete=True,
|
||||
)
|
||||
|
||||
|
||||
class FormSetHelper(FormHelper):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_tag = False
|
||||
self.form_method = 'POST'
|
||||
self.form_class = 'form-inline'
|
||||
# self.template = 'bootstrap/table_inline_formset.html'
|
||||
self.layout = Layout(
|
||||
Div(
|
||||
Div('user', css_class='col-sm-2'),
|
||||
Div('roles', css_class='col-sm-2'),
|
||||
Div('date_start', css_class='col-sm-2'),
|
||||
css_class="row formset-row",
|
||||
))
|
||||
|
@ -83,27 +83,31 @@ class Club(models.Model):
|
||||
require_memberships = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name=_("require memberships"),
|
||||
help_text=_("Uncheck if this club don't require memberships."),
|
||||
)
|
||||
|
||||
membership_fee = models.PositiveIntegerField(
|
||||
default=0,
|
||||
verbose_name=_('membership fee'),
|
||||
)
|
||||
membership_duration = models.DurationField(
|
||||
|
||||
membership_duration = models.IntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('membership duration'),
|
||||
help_text=_('The longest time a membership can last '
|
||||
help_text=_('The longest time (in days) a membership can last '
|
||||
'(NULL = infinite).'),
|
||||
)
|
||||
membership_start = models.DurationField(
|
||||
|
||||
membership_start = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('membership start'),
|
||||
help_text=_('How long after January 1st the members can renew '
|
||||
'their membership.'),
|
||||
)
|
||||
membership_end = models.DurationField(
|
||||
|
||||
membership_end = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('membership end'),
|
||||
@ -112,6 +116,20 @@ class Club(models.Model):
|
||||
'membership.'),
|
||||
)
|
||||
|
||||
def update_membership_dates(self):
|
||||
"""
|
||||
This function is called each time the club detail view is displayed.
|
||||
Update the year of the membership dates.
|
||||
"""
|
||||
today = datetime.date.today()
|
||||
|
||||
if (today - self.membership_start).days >= 365:
|
||||
self.membership_start = datetime.date(self.membership_start.year + 1,
|
||||
self.membership_start.month, self.membership_start.day)
|
||||
self.membership_end = datetime.date(self.membership_end.year + 1,
|
||||
self.membership_end.month, self.membership_end.day)
|
||||
self.save(force_update=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if not self.require_memberships:
|
||||
@ -135,9 +153,6 @@ class Club(models.Model):
|
||||
class Role(models.Model):
|
||||
"""
|
||||
Role that an :model:`auth.User` can have in a :model:`member.Club`
|
||||
|
||||
TODO: Integrate the right management, and create some standard Roles at the
|
||||
creation of the club.
|
||||
"""
|
||||
name = models.CharField(
|
||||
verbose_name=_('name'),
|
||||
@ -162,21 +177,25 @@ class Membership(models.Model):
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
club = models.ForeignKey(
|
||||
Club,
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
roles = models.ForeignKey(
|
||||
|
||||
roles = models.ManyToManyField(
|
||||
Role,
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
date_start = models.DateField(
|
||||
verbose_name=_('membership starts on'),
|
||||
)
|
||||
|
||||
date_end = models.DateField(
|
||||
verbose_name=_('membership ends on'),
|
||||
null=True,
|
||||
)
|
||||
|
||||
fee = models.PositiveIntegerField(
|
||||
verbose_name=_('fee'),
|
||||
)
|
||||
@ -189,8 +208,16 @@ class Membership(models.Model):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.club.parent_club is not None:
|
||||
if not Membership.objects.filter(user=self.user, club=self.club.parent_club):
|
||||
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'))
|
||||
|
||||
created = not self.pk
|
||||
if created:
|
||||
self.fee = self.club.membership_fee
|
||||
self.date_end = self.date_start + datetime.timedelta(days=self.club.membership_duration)
|
||||
if self.date_end > self.club.membership_end:
|
||||
self.date_end = self.club.membership_end
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
|
@ -2,6 +2,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import io
|
||||
from datetime import datetime
|
||||
|
||||
from PIL import Image
|
||||
from django.conf import settings
|
||||
@ -24,8 +25,7 @@ from permission.backends import PermissionBackend
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
|
||||
from .filters import UserFilter, UserFilterFormHelper
|
||||
from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, MemberFormSet, FormSetHelper, \
|
||||
CustomAuthenticationForm
|
||||
from .forms import SignUpForm, ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm
|
||||
from .models import Club, Membership
|
||||
from .tables import ClubTable, UserTable
|
||||
|
||||
@ -281,13 +281,19 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
club = context["club"]
|
||||
if PermissionBackend().has_perm(self.request.user, "member.change_club_membership_start", club):
|
||||
club.update_membership_dates()
|
||||
|
||||
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
|
||||
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by('-id')
|
||||
context['history_list'] = HistoryTable(club_transactions)
|
||||
club_member = Membership.objects.filter(club=club)\
|
||||
.filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")).all()
|
||||
# TODO: consider only valid Membership
|
||||
club_member = Membership.objects.filter(
|
||||
club=club,
|
||||
date_start__lte=datetime.now().date(),
|
||||
date_end__gte=datetime.now().date(),
|
||||
).filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")).all()
|
||||
context['member_list'] = club_member
|
||||
return context
|
||||
|
||||
@ -328,31 +334,20 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||
form_class = MembershipForm
|
||||
template_name = 'member/add_members.html'
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")
|
||||
| PermissionBackend.filter_queryset(self.request.user, Membership,
|
||||
"change"))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||
.get(pk=self.kwargs["pk"])
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['formset'] = MemberFormSet()
|
||||
context['helper'] = FormSetHelper()
|
||||
context['club'] = club
|
||||
context['no_cache'] = True
|
||||
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return
|
||||
# TODO: Implement POST
|
||||
# formset = MembershipFormset(request.POST)
|
||||
# if formset.is_valid():
|
||||
# return self.form_valid(formset)
|
||||
# else:
|
||||
# return self.form_invalid(formset)
|
||||
def form_valid(self, form):
|
||||
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||
.get(pk=self.kwargs["pk"])
|
||||
form.instance.club = club
|
||||
return super().form_valid(form)
|
||||
|
||||
def form_valid(self, formset):
|
||||
formset.save()
|
||||
return super().form_valid(formset)
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.club.id})
|
||||
|
@ -32,6 +32,7 @@ class PermissionBackend(ModelBackend):
|
||||
for permission in Permission.objects.annotate(club=F("rolepermissions__role__membership__club")) \
|
||||
.filter(
|
||||
rolepermissions__role__membership__user=user,
|
||||
rolepermissions__role__membership__valid=True,
|
||||
model__app_label=model.app_label, # For polymorphic models, we don't filter on model type
|
||||
type=type,
|
||||
).all():
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-31 04:16+0200\n"
|
||||
"POT-Creation-Date: 2020-03-31 23:49+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -44,11 +44,10 @@ msgid "You can't invite more than 3 people to this activity."
|
||||
msgstr ""
|
||||
|
||||
#: apps/activity/models.py:23 apps/activity/models.py:48
|
||||
#: apps/member/models.py:64 apps/member/models.py:122
|
||||
#: apps/note/models/notes.py:186 apps/note/models/notes.py:224
|
||||
#: apps/note/models/transactions.py:24 apps/note/models/transactions.py:44
|
||||
#: apps/note/models/transactions.py:231 templates/member/club_info.html:13
|
||||
#: templates/member/profile_info.html:14
|
||||
#: apps/member/models.py:64 apps/member/models.py:158
|
||||
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
|
||||
#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231
|
||||
#: templates/member/club_info.html:13 templates/member/profile_info.html:14
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
@ -73,14 +72,14 @@ msgstr ""
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/activity/models.py:60 apps/note/models/notes.py:166
|
||||
#: apps/activity/models.py:60 apps/note/models/notes.py:164
|
||||
#: apps/note/models/transactions.py:62
|
||||
#: templates/activity/activity_detail.html:19
|
||||
msgid "type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/activity/models.py:66 apps/logs/models.py:21
|
||||
#: apps/note/models/notes.py:119
|
||||
#: apps/note/models/notes.py:117
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
@ -89,7 +88,7 @@ msgid "organizer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14
|
||||
#: apps/note/models/notes.py:60
|
||||
#: apps/note/models/notes.py:58
|
||||
msgid "note"
|
||||
msgstr ""
|
||||
|
||||
@ -179,7 +178,7 @@ msgstr ""
|
||||
msgid "First name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/activity/tables.py:81 apps/note/models/notes.py:69
|
||||
#: apps/activity/tables.py:81 apps/note/models/notes.py:67
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
@ -227,12 +226,12 @@ msgstr ""
|
||||
msgid "create"
|
||||
msgstr ""
|
||||
|
||||
#: apps/logs/models.py:61 apps/note/tables.py:160
|
||||
#: apps/logs/models.py:61 apps/note/tables.py:142
|
||||
#: templates/activity/activity_detail.html:67
|
||||
msgid "edit"
|
||||
msgstr ""
|
||||
|
||||
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:164
|
||||
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:146
|
||||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
@ -276,7 +275,7 @@ msgstr ""
|
||||
msgid "user profile"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:69 templates/member/club_info.html:36
|
||||
#: apps/member/models.py:69 templates/member/club_info.html:38
|
||||
msgid "email"
|
||||
msgstr ""
|
||||
|
||||
@ -284,90 +283,97 @@ msgstr ""
|
||||
msgid "parent club"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:81 templates/member/club_info.html:30
|
||||
msgid "membership fee"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:85 templates/member/club_info.html:27
|
||||
msgid "membership duration"
|
||||
#: apps/member/models.py:85
|
||||
msgid "require memberships"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:86
|
||||
msgid "The longest time a membership can last (NULL = infinite)."
|
||||
msgid "Uncheck if this club don't require memberships."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:91 templates/member/club_info.html:21
|
||||
msgid "membership start"
|
||||
#: apps/member/models.py:91 templates/member/club_info.html:31
|
||||
msgid "membership fee"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:92
|
||||
msgid "How long after January 1st the members can renew their membership."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:97 templates/member/club_info.html:24
|
||||
msgid "membership end"
|
||||
#: apps/member/models.py:97 templates/member/club_info.html:28
|
||||
msgid "membership duration"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:98
|
||||
msgid "The longest time (in days) a membership can last (NULL = infinite)."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:105 templates/member/club_info.html:22
|
||||
msgid "membership start"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:106
|
||||
msgid "How long after January 1st the members can renew their membership."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:113 templates/member/club_info.html:25
|
||||
msgid "membership end"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:114
|
||||
msgid ""
|
||||
"How long the membership can last after January 1st of the next year after "
|
||||
"members can renew their membership."
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:104 apps/note/models/notes.py:141
|
||||
#: apps/note/models/notes.py:195
|
||||
#: apps/member/models.py:143 apps/note/models/notes.py:139
|
||||
msgid "club"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:105
|
||||
#: apps/member/models.py:144
|
||||
msgid "clubs"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:128 apps/permission/models.py:284
|
||||
#: apps/member/models.py:164 apps/permission/models.py:284
|
||||
msgid "role"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:129
|
||||
#: apps/member/models.py:165
|
||||
msgid "roles"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:153
|
||||
#: apps/member/models.py:191
|
||||
msgid "membership starts on"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:156
|
||||
#: apps/member/models.py:195
|
||||
msgid "membership ends on"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:160
|
||||
#: apps/member/models.py:200
|
||||
msgid "fee"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:172
|
||||
#: apps/member/models.py:212
|
||||
msgid "User is not a member of the parent club"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:176
|
||||
#: apps/member/models.py:224
|
||||
msgid "membership"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/models.py:177
|
||||
#: apps/member/models.py:225
|
||||
msgid "memberships"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/views.py:78 templates/member/profile_info.html:45
|
||||
#: apps/member/views.py:77 templates/member/profile_info.html:45
|
||||
msgid "Update Profile"
|
||||
msgstr ""
|
||||
|
||||
#: apps/member/views.py:91
|
||||
#: apps/member/views.py:90
|
||||
msgid "An alias with a similar name already exists."
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/admin.py:128 apps/note/models/transactions.py:94
|
||||
#: apps/note/admin.py:120 apps/note/models/transactions.py:94
|
||||
msgid "source"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/admin.py:136 apps/note/admin.py:164
|
||||
#: apps/note/admin.py:128 apps/note/admin.py:156
|
||||
#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:107
|
||||
msgid "destination"
|
||||
msgstr ""
|
||||
@ -380,104 +386,104 @@ msgstr ""
|
||||
msgid "Maximal size: 2MB"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:29
|
||||
#: apps/note/models/notes.py:27
|
||||
msgid "account balance"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:30
|
||||
#: apps/note/models/notes.py:28
|
||||
msgid "in centimes, money credited for this instance"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:34
|
||||
#: apps/note/models/notes.py:32
|
||||
msgid "last negative date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:35
|
||||
#: apps/note/models/notes.py:33
|
||||
msgid "last time the balance was negative"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:40
|
||||
#: apps/note/models/notes.py:38
|
||||
msgid "active"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:43
|
||||
#: apps/note/models/notes.py:41
|
||||
msgid ""
|
||||
"Designates whether this note should be treated as active. Unselect this "
|
||||
"instead of deleting notes."
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:47
|
||||
#: apps/note/models/notes.py:45
|
||||
msgid "display image"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:55 apps/note/models/transactions.py:117
|
||||
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:117
|
||||
msgid "created at"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:61
|
||||
#: apps/note/models/notes.py:59
|
||||
msgid "notes"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:79 apps/note/models/notes.py:103
|
||||
#: apps/note/models/notes.py:77 apps/note/models/notes.py:101
|
||||
msgid "This alias is already taken."
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:123
|
||||
#: apps/note/models/notes.py:121
|
||||
msgid "one's note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:124
|
||||
#: apps/note/models/notes.py:122
|
||||
msgid "users note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:130
|
||||
#: apps/note/models/notes.py:128
|
||||
#, python-format
|
||||
msgid "%(user)s's note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:145
|
||||
#: apps/note/models/notes.py:143
|
||||
msgid "club note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:146
|
||||
#: apps/note/models/notes.py:144
|
||||
msgid "clubs notes"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:152
|
||||
#: apps/note/models/notes.py:150
|
||||
#, python-format
|
||||
msgid "Note of %(club)s club"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:172
|
||||
#: apps/note/models/notes.py:170
|
||||
msgid "special note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:173
|
||||
#: apps/note/models/notes.py:171
|
||||
msgid "special notes"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:230
|
||||
#: apps/note/models/notes.py:194
|
||||
msgid "Invalid alias"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:246
|
||||
#: apps/note/models/notes.py:210
|
||||
msgid "alias"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:247 templates/member/club_info.html:33
|
||||
#: apps/note/models/notes.py:211 templates/member/club_info.html:35
|
||||
#: templates/member/profile_info.html:36
|
||||
msgid "aliases"
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:269
|
||||
#: apps/note/models/notes.py:233
|
||||
msgid "Alias is too long."
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:274
|
||||
#: apps/note/models/notes.py:238
|
||||
msgid "An alias with a similar name already exists: {} "
|
||||
msgstr ""
|
||||
|
||||
#: apps/note/models/notes.py:287
|
||||
#: apps/note/models/notes.py:251
|
||||
msgid "You can't delete your main alias."
|
||||
msgstr ""
|
||||
|
||||
@ -614,7 +620,7 @@ msgstr ""
|
||||
#: templates/activity/activity_form.html:9
|
||||
#: templates/activity/activity_invite.html:8
|
||||
#: templates/django_filters/rest_framework/form.html:5
|
||||
#: templates/member/club_form.html:9
|
||||
#: templates/member/add_members.html:14 templates/member/club_form.html:9
|
||||
#: templates/treasury/invoice_form.html:46
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
@ -882,23 +888,23 @@ msgstr ""
|
||||
msgid "Club Parent"
|
||||
msgstr ""
|
||||
|
||||
#: templates/member/club_info.html:39
|
||||
msgid "linked notes"
|
||||
#: templates/member/club_info.html:29
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#: templates/member/club_info.html:44
|
||||
#: templates/member/club_info.html:43
|
||||
msgid "Add member"
|
||||
msgstr ""
|
||||
|
||||
#: templates/member/club_info.html:45 templates/note/conso_form.html:121
|
||||
#: templates/member/club_info.html:44 templates/note/conso_form.html:121
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
#: templates/member/club_info.html:46
|
||||
#: templates/member/club_info.html:45
|
||||
msgid "Add roles"
|
||||
msgstr ""
|
||||
|
||||
#: templates/member/club_info.html:49 templates/member/profile_info.html:48
|
||||
#: templates/member/club_info.html:48 templates/member/profile_info.html:48
|
||||
msgid "View Profile"
|
||||
msgstr ""
|
||||
|
||||
|
@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-31 04:16+0200\n"
|
||||
"POT-Creation-Date: 2020-03-31 23:49+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -40,11 +40,10 @@ msgid "You can't invite more than 3 people to this activity."
|
||||
msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
|
||||
|
||||
#: apps/activity/models.py:23 apps/activity/models.py:48
|
||||
#: apps/member/models.py:64 apps/member/models.py:122
|
||||
#: apps/note/models/notes.py:186 apps/note/models/notes.py:224
|
||||
#: apps/note/models/transactions.py:24 apps/note/models/transactions.py:44
|
||||
#: apps/note/models/transactions.py:231 templates/member/club_info.html:13
|
||||
#: templates/member/profile_info.html:14
|
||||
#: apps/member/models.py:64 apps/member/models.py:158
|
||||
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
|
||||
#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231
|
||||
#: templates/member/club_info.html:13 templates/member/profile_info.html:14
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
@ -69,14 +68,14 @@ msgstr "types d'activité"
|
||||
msgid "description"
|
||||
msgstr "description"
|
||||
|
||||
#: apps/activity/models.py:60 apps/note/models/notes.py:166
|
||||
#: apps/activity/models.py:60 apps/note/models/notes.py:164
|
||||
#: apps/note/models/transactions.py:62
|
||||
#: templates/activity/activity_detail.html:19
|
||||
msgid "type"
|
||||
msgstr "type"
|
||||
|
||||
#: apps/activity/models.py:66 apps/logs/models.py:21
|
||||
#: apps/note/models/notes.py:119
|
||||
#: apps/note/models/notes.py:117
|
||||
msgid "user"
|
||||
msgstr "utilisateur"
|
||||
|
||||
@ -85,7 +84,7 @@ msgid "organizer"
|
||||
msgstr "organisateur"
|
||||
|
||||
#: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14
|
||||
#: apps/note/models/notes.py:60
|
||||
#: apps/note/models/notes.py:58
|
||||
msgid "note"
|
||||
msgstr "note"
|
||||
|
||||
@ -175,7 +174,7 @@ msgstr "Nom de famille"
|
||||
msgid "First name"
|
||||
msgstr "Prénom"
|
||||
|
||||
#: apps/activity/tables.py:81 apps/note/models/notes.py:69
|
||||
#: apps/activity/tables.py:81 apps/note/models/notes.py:67
|
||||
msgid "Note"
|
||||
msgstr "Note"
|
||||
|
||||
@ -223,12 +222,12 @@ msgstr "Nouvelles données"
|
||||
msgid "create"
|
||||
msgstr "Créer"
|
||||
|
||||
#: apps/logs/models.py:61 apps/note/tables.py:160
|
||||
#: apps/logs/models.py:61 apps/note/tables.py:142
|
||||
#: templates/activity/activity_detail.html:67
|
||||
msgid "edit"
|
||||
msgstr "Modifier"
|
||||
|
||||
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:164
|
||||
#: apps/logs/models.py:62 apps/note/tables.py:120 apps/note/tables.py:146
|
||||
msgid "delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
@ -272,7 +271,7 @@ msgstr "payé"
|
||||
msgid "user profile"
|
||||
msgstr "profil utilisateur"
|
||||
|
||||
#: apps/member/models.py:69 templates/member/club_info.html:36
|
||||
#: apps/member/models.py:69 templates/member/club_info.html:38
|
||||
msgid "email"
|
||||
msgstr "courriel"
|
||||
|
||||
@ -280,33 +279,41 @@ msgstr "courriel"
|
||||
msgid "parent club"
|
||||
msgstr "club parent"
|
||||
|
||||
#: apps/member/models.py:81 templates/member/club_info.html:30
|
||||
#: apps/member/models.py:85
|
||||
msgid "require memberships"
|
||||
msgstr "nécessite des adhésions"
|
||||
|
||||
#: apps/member/models.py:86
|
||||
msgid "Uncheck if this club don't require memberships."
|
||||
msgstr "Décochez si ce club n'utilise pas d'adhésions."
|
||||
|
||||
#: apps/member/models.py:91 templates/member/club_info.html:31
|
||||
msgid "membership fee"
|
||||
msgstr "cotisation pour adhérer"
|
||||
|
||||
#: apps/member/models.py:85 templates/member/club_info.html:27
|
||||
#: apps/member/models.py:97 templates/member/club_info.html:28
|
||||
msgid "membership duration"
|
||||
msgstr "durée de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:86
|
||||
msgid "The longest time a membership can last (NULL = infinite)."
|
||||
msgstr "La durée maximale d'une adhésion (NULL = infinie)."
|
||||
#: apps/member/models.py:98
|
||||
msgid "The longest time (in days) a membership can last (NULL = infinite)."
|
||||
msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)."
|
||||
|
||||
#: apps/member/models.py:91 templates/member/club_info.html:21
|
||||
#: apps/member/models.py:105 templates/member/club_info.html:22
|
||||
msgid "membership start"
|
||||
msgstr "début de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:92
|
||||
#: apps/member/models.py:106
|
||||
msgid "How long after January 1st the members can renew their membership."
|
||||
msgstr ""
|
||||
"Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur "
|
||||
"adhésion."
|
||||
|
||||
#: apps/member/models.py:97 templates/member/club_info.html:24
|
||||
#: apps/member/models.py:113 templates/member/club_info.html:25
|
||||
msgid "membership end"
|
||||
msgstr "fin de l'adhésion"
|
||||
|
||||
#: apps/member/models.py:98
|
||||
#: apps/member/models.py:114
|
||||
msgid ""
|
||||
"How long the membership can last after January 1st of the next year after "
|
||||
"members can renew their membership."
|
||||
@ -314,60 +321,59 @@ msgstr ""
|
||||
"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."
|
||||
|
||||
#: apps/member/models.py:104 apps/note/models/notes.py:141
|
||||
#: apps/note/models/notes.py:195
|
||||
#: apps/member/models.py:143 apps/note/models/notes.py:139
|
||||
msgid "club"
|
||||
msgstr "club"
|
||||
|
||||
#: apps/member/models.py:105
|
||||
#: apps/member/models.py:144
|
||||
msgid "clubs"
|
||||
msgstr "clubs"
|
||||
|
||||
#: apps/member/models.py:128 apps/permission/models.py:284
|
||||
#: apps/member/models.py:164 apps/permission/models.py:284
|
||||
msgid "role"
|
||||
msgstr "rôle"
|
||||
|
||||
#: apps/member/models.py:129
|
||||
#: apps/member/models.py:165
|
||||
msgid "roles"
|
||||
msgstr "rôles"
|
||||
|
||||
#: apps/member/models.py:153
|
||||
#: apps/member/models.py:191
|
||||
msgid "membership starts on"
|
||||
msgstr "l'adhésion commence le"
|
||||
|
||||
#: apps/member/models.py:156
|
||||
#: apps/member/models.py:195
|
||||
msgid "membership ends on"
|
||||
msgstr "l'adhésion finie le"
|
||||
|
||||
#: apps/member/models.py:160
|
||||
#: apps/member/models.py:200
|
||||
msgid "fee"
|
||||
msgstr "cotisation"
|
||||
|
||||
#: apps/member/models.py:172
|
||||
#: apps/member/models.py:212
|
||||
msgid "User is not a member of the parent club"
|
||||
msgstr "L'utilisateur n'est pas membre du club parent"
|
||||
|
||||
#: apps/member/models.py:176
|
||||
#: apps/member/models.py:224
|
||||
msgid "membership"
|
||||
msgstr "adhésion"
|
||||
|
||||
#: apps/member/models.py:177
|
||||
#: apps/member/models.py:225
|
||||
msgid "memberships"
|
||||
msgstr "adhésions"
|
||||
|
||||
#: apps/member/views.py:78 templates/member/profile_info.html:45
|
||||
#: apps/member/views.py:77 templates/member/profile_info.html:45
|
||||
msgid "Update Profile"
|
||||
msgstr "Modifier le profil"
|
||||
|
||||
#: apps/member/views.py:91
|
||||
#: apps/member/views.py:90
|
||||
msgid "An alias with a similar name already exists."
|
||||
msgstr "Un alias avec un nom similaire existe déjà."
|
||||
|
||||
#: apps/note/admin.py:128 apps/note/models/transactions.py:94
|
||||
#: apps/note/admin.py:120 apps/note/models/transactions.py:94
|
||||
msgid "source"
|
||||
msgstr "source"
|
||||
|
||||
#: apps/note/admin.py:136 apps/note/admin.py:164
|
||||
#: apps/note/admin.py:128 apps/note/admin.py:156
|
||||
#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:107
|
||||
msgid "destination"
|
||||
msgstr "destination"
|
||||
@ -380,105 +386,105 @@ msgstr "Choisissez une image"
|
||||
msgid "Maximal size: 2MB"
|
||||
msgstr "Taille maximale : 2 Mo"
|
||||
|
||||
#: apps/note/models/notes.py:29
|
||||
#: apps/note/models/notes.py:27
|
||||
msgid "account balance"
|
||||
msgstr "solde du compte"
|
||||
|
||||
#: apps/note/models/notes.py:30
|
||||
#: apps/note/models/notes.py:28
|
||||
msgid "in centimes, money credited for this instance"
|
||||
msgstr "en centimes, argent crédité pour cette instance"
|
||||
|
||||
#: apps/note/models/notes.py:34
|
||||
#: apps/note/models/notes.py:32
|
||||
msgid "last negative date"
|
||||
msgstr "dernier date de négatif"
|
||||
|
||||
#: apps/note/models/notes.py:35
|
||||
#: apps/note/models/notes.py:33
|
||||
msgid "last time the balance was negative"
|
||||
msgstr "dernier instant où la note était en négatif"
|
||||
|
||||
#: apps/note/models/notes.py:40
|
||||
#: apps/note/models/notes.py:38
|
||||
msgid "active"
|
||||
msgstr "actif"
|
||||
|
||||
#: apps/note/models/notes.py:43
|
||||
#: apps/note/models/notes.py:41
|
||||
msgid ""
|
||||
"Designates whether this note should be treated as active. Unselect this "
|
||||
"instead of deleting notes."
|
||||
msgstr ""
|
||||
"Indique si la note est active. Désactiver cela plutôt que supprimer la note."
|
||||
|
||||
#: apps/note/models/notes.py:47
|
||||
#: apps/note/models/notes.py:45
|
||||
msgid "display image"
|
||||
msgstr "image affichée"
|
||||
|
||||
#: apps/note/models/notes.py:55 apps/note/models/transactions.py:117
|
||||
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:117
|
||||
msgid "created at"
|
||||
msgstr "créée le"
|
||||
|
||||
#: apps/note/models/notes.py:61
|
||||
#: apps/note/models/notes.py:59
|
||||
msgid "notes"
|
||||
msgstr "notes"
|
||||
|
||||
#: apps/note/models/notes.py:79 apps/note/models/notes.py:103
|
||||
#: apps/note/models/notes.py:77 apps/note/models/notes.py:101
|
||||
msgid "This alias is already taken."
|
||||
msgstr "Cet alias est déjà pris."
|
||||
|
||||
#: apps/note/models/notes.py:123
|
||||
#: apps/note/models/notes.py:121
|
||||
msgid "one's note"
|
||||
msgstr "note d'un utilisateur"
|
||||
|
||||
#: apps/note/models/notes.py:124
|
||||
#: apps/note/models/notes.py:122
|
||||
msgid "users note"
|
||||
msgstr "notes des utilisateurs"
|
||||
|
||||
#: apps/note/models/notes.py:130
|
||||
#: apps/note/models/notes.py:128
|
||||
#, python-format
|
||||
msgid "%(user)s's note"
|
||||
msgstr "Note de %(user)s"
|
||||
|
||||
#: apps/note/models/notes.py:145
|
||||
#: apps/note/models/notes.py:143
|
||||
msgid "club note"
|
||||
msgstr "note d'un club"
|
||||
|
||||
#: apps/note/models/notes.py:146
|
||||
#: apps/note/models/notes.py:144
|
||||
msgid "clubs notes"
|
||||
msgstr "notes des clubs"
|
||||
|
||||
#: apps/note/models/notes.py:152
|
||||
#: apps/note/models/notes.py:150
|
||||
#, python-format
|
||||
msgid "Note of %(club)s club"
|
||||
msgstr "Note du club %(club)s"
|
||||
|
||||
#: apps/note/models/notes.py:172
|
||||
#: apps/note/models/notes.py:170
|
||||
msgid "special note"
|
||||
msgstr "note spéciale"
|
||||
|
||||
#: apps/note/models/notes.py:173
|
||||
#: apps/note/models/notes.py:171
|
||||
msgid "special notes"
|
||||
msgstr "notes spéciales"
|
||||
|
||||
#: apps/note/models/notes.py:230
|
||||
#: apps/note/models/notes.py:194
|
||||
msgid "Invalid alias"
|
||||
msgstr "Alias invalide"
|
||||
|
||||
#: apps/note/models/notes.py:246
|
||||
#: apps/note/models/notes.py:210
|
||||
msgid "alias"
|
||||
msgstr "alias"
|
||||
|
||||
#: apps/note/models/notes.py:247 templates/member/club_info.html:33
|
||||
#: apps/note/models/notes.py:211 templates/member/club_info.html:35
|
||||
#: templates/member/profile_info.html:36
|
||||
msgid "aliases"
|
||||
msgstr "alias"
|
||||
|
||||
#: apps/note/models/notes.py:269
|
||||
#: apps/note/models/notes.py:233
|
||||
msgid "Alias is too long."
|
||||
msgstr "L'alias est trop long."
|
||||
|
||||
#: apps/note/models/notes.py:274
|
||||
#: apps/note/models/notes.py:238
|
||||
msgid "An alias with a similar name already exists: {} "
|
||||
msgstr "Un alias avec un nom similaire existe déjà : {}"
|
||||
|
||||
#: apps/note/models/notes.py:287
|
||||
#: apps/note/models/notes.py:251
|
||||
msgid "You can't delete your main alias."
|
||||
msgstr "Vous ne pouvez pas supprimer votre alias principal."
|
||||
|
||||
@ -615,7 +621,7 @@ msgstr "Trésorerie"
|
||||
#: templates/activity/activity_form.html:9
|
||||
#: templates/activity/activity_invite.html:8
|
||||
#: templates/django_filters/rest_framework/form.html:5
|
||||
#: templates/member/club_form.html:9
|
||||
#: templates/member/add_members.html:14 templates/member/club_form.html:9
|
||||
#: templates/treasury/invoice_form.html:46
|
||||
msgid "Submit"
|
||||
msgstr "Envoyer"
|
||||
@ -885,23 +891,23 @@ msgstr "Ajouter un alias"
|
||||
msgid "Club Parent"
|
||||
msgstr "Club parent"
|
||||
|
||||
#: templates/member/club_info.html:39
|
||||
msgid "linked notes"
|
||||
msgstr "notes liées"
|
||||
#: templates/member/club_info.html:29
|
||||
msgid "days"
|
||||
msgstr "jours"
|
||||
|
||||
#: templates/member/club_info.html:44
|
||||
#: templates/member/club_info.html:43
|
||||
msgid "Add member"
|
||||
msgstr "Ajouter un membre"
|
||||
|
||||
#: templates/member/club_info.html:45 templates/note/conso_form.html:121
|
||||
#: templates/member/club_info.html:44 templates/note/conso_form.html:121
|
||||
msgid "Edit"
|
||||
msgstr "Éditer"
|
||||
|
||||
#: templates/member/club_info.html:46
|
||||
#: templates/member/club_info.html:45
|
||||
msgid "Add roles"
|
||||
msgstr "Ajouter des rôles"
|
||||
|
||||
#: templates/member/club_info.html:49 templates/member/profile_info.html:48
|
||||
#: templates/member/club_info.html:48 templates/member/profile_info.html:48
|
||||
msgid "View Profile"
|
||||
msgstr "Voir le profil"
|
||||
|
||||
@ -1210,3 +1216,6 @@ msgstr "Il n'y a pas de transaction associée à une remise ouverte."
|
||||
#: templates/treasury/remittance_list.html:54
|
||||
msgid "Closed remittances"
|
||||
msgstr "Remises fermées"
|
||||
|
||||
#~ msgid "linked notes"
|
||||
#~ msgstr "notes liées"
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import datetime
|
||||
from json import dumps as json_dumps
|
||||
|
||||
from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput
|
||||
|
@ -1,29 +1,21 @@
|
||||
{% extends "member/noteowner_detail.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block profile_info %}
|
||||
{% include "member/club_info.html" %}
|
||||
{% endblock %}
|
||||
{% block profile_content %}
|
||||
|
||||
{% block profile_content %}
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{% crispy formset helper %}
|
||||
<div class="form-actions">
|
||||
<input type="submit" name="submit" value="Add Members" class="btn btn-primary" id="submit-save">
|
||||
</div>
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
<script src="{% static 'js/dynamic-formset.js' %}"></script>
|
||||
<script>
|
||||
$('.formset-row').formset({
|
||||
addText: 'add another', // Text for the add link
|
||||
deleteText: 'remove', // Text for the delete link
|
||||
addCssClass: 'btn btn-primary', // CSS class applied to the add link
|
||||
deleteCssClass: 'btn btn-danger h-50 my-auto',
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -26,7 +26,7 @@
|
||||
<dd class="col-xl-6">{{ club.membership_end }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'membership duration'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ club.membership_duration }}</dd>
|
||||
<dd class="col-xl-6">{{ club.membership_duration }} {% trans "days" %}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'membership fee'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ club.membership_fee|pretty_money }}</dd>
|
||||
|
Loading…
Reference in New Issue
Block a user