1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-06-21 09:58:23 +02:00

Restructurate memberships, closes #16

This commit is contained in:
Yohann D'ANELLO
2020-03-31 23:54:14 +02:00
parent e98693b214
commit bf9789bd9e
10 changed files with 231 additions and 224 deletions

View File

@ -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"
}
}
]

View File

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

View File

@ -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:

View File

@ -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})