mirror of https://gitlab.crans.org/bde/nk20
Credit note for membership renewals
This commit is contained in:
parent
515edc4459
commit
c513759515
|
@ -5,7 +5,6 @@ from django import forms
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
from django.contrib.auth.models import User
|
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
|
||||||
|
|
|
@ -10,9 +10,9 @@ urlpatterns = [
|
||||||
path('club/', views.ClubListView.as_view(), name="club_list"),
|
path('club/', views.ClubListView.as_view(), name="club_list"),
|
||||||
path('club/create/', views.ClubCreateView.as_view(), name="club_create"),
|
path('club/create/', views.ClubCreateView.as_view(), name="club_create"),
|
||||||
path('club/<int:pk>/', views.ClubDetailView.as_view(), name="club_detail"),
|
path('club/<int:pk>/', views.ClubDetailView.as_view(), name="club_detail"),
|
||||||
path('club/<int:pk>/add_member/', views.ClubAddMemberView.as_view(), name="club_add_member"),
|
path('club/<int:club_pk>/add_member/', views.ClubAddMemberView.as_view(), name="club_add_member"),
|
||||||
path('club/manage_roles/<int:pk>/', views.ClubManageRolesView.as_view(), name="club_manage_roles"),
|
path('club/manage_roles/<int:pk>/', views.ClubManageRolesView.as_view(), name="club_manage_roles"),
|
||||||
path('club/renew_membership/<int:pk>/', views.ClubRenewMembershipView.as_view(), name="club_renew_membership"),
|
path('club/renew_membership/<int:pk>/', views.ClubAddMemberView.as_view(), name="club_renew_membership"),
|
||||||
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"),
|
||||||
|
|
|
@ -9,14 +9,11 @@ from django.conf import settings
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.views import LoginView
|
from django.contrib.auth.views import LoginView
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.forms import HiddenInput
|
|
||||||
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.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.base import View
|
|
||||||
from django.views.generic.edit import FormMixin
|
from django.views.generic.edit import FormMixin
|
||||||
from django_tables2.views import SingleTableView
|
from django_tables2.views import SingleTableView
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
|
@ -351,18 +348,40 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
template_name = 'member/add_members.html'
|
template_name = 'member/add_members.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
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 = super().get_context_data(**kwargs)
|
||||||
|
form = context['form']
|
||||||
|
|
||||||
|
if "club_pk" in self.kwargs:
|
||||||
|
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
||||||
|
.get(pk=self.kwargs["club_pk"])
|
||||||
|
form.fields['credit_amount'].initial = club.membership_fee_paid
|
||||||
|
else:
|
||||||
|
old_membership = self.get_queryset().get(pk=self.kwargs["pk"])
|
||||||
|
club = old_membership.club
|
||||||
|
user = old_membership.user
|
||||||
|
form.fields['user'].initial = user
|
||||||
|
form.fields['user'].disabled = True
|
||||||
|
form.fields['roles'].initial = old_membership.roles.all()
|
||||||
|
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 \
|
||||||
|
else club.membership_fee_unpaid
|
||||||
|
form.fields['last_name'].initial = user.last_name
|
||||||
|
form.fields['first_name'].initial = user.first_name
|
||||||
|
|
||||||
context['club'] = club
|
context['club'] = club
|
||||||
context['form'].fields['credit_amount'].initial = club.membership_fee_paid
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
|
if "club_pk" in self.kwargs:
|
||||||
.get(pk=self.kwargs["pk"])
|
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view")) \
|
||||||
user = form.instance.user
|
.get(pk=self.kwargs["club_pk"])
|
||||||
|
user = form.instance.user
|
||||||
|
else:
|
||||||
|
old_membership = self.get_queryset().get(pk=self.kwargs["pk"])
|
||||||
|
club = old_membership.club
|
||||||
|
user = old_membership.user
|
||||||
|
|
||||||
form.instance.club = club
|
form.instance.club = club
|
||||||
|
|
||||||
credit_type = form.cleaned_data["credit_type"]
|
credit_type = form.cleaned_data["credit_type"]
|
||||||
|
@ -405,23 +424,23 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
|
||||||
form.add_error('user', _('User is already a member of the club'))
|
form.add_error('user', _('User is already a member of the club'))
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
if form.instance.club.membership_start and form.instance.date_start < form.instance.club.membership_start:
|
if club.membership_start and form.instance.date_start < club.membership_start:
|
||||||
form.add_error('user', _("The membership must start after {:%m-%d-%Y}.")
|
form.add_error('user', _("The membership must start after {:%m-%d-%Y}.")
|
||||||
.format(form.instance.club.membership_start))
|
.format(form.instance.club.membership_start))
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
if form.instance.club.membership_end and form.instance.date_start > form.instance.club.membership_end:
|
if club.membership_end and form.instance.date_start > club.membership_end:
|
||||||
form.add_error('user', _("The membership must begin before {:%m-%d-%Y}.")
|
form.add_error('user', _("The membership must begin before {:%m-%d-%Y}.")
|
||||||
.format(form.instance.club.membership_start))
|
.format(form.instance.club.membership_start))
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
if credit_amount > 0:
|
if credit_amount > 0:
|
||||||
if not last_name or not first_name or not bank:
|
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
|
||||||
if not last_name:
|
if not last_name:
|
||||||
form.add_error('last_name', _("This field is required."))
|
form.add_error('last_name', _("This field is required."))
|
||||||
if not first_name:
|
if not first_name:
|
||||||
form.add_error('first_name', _("This field is required."))
|
form.add_error('first_name', _("This field is required."))
|
||||||
if not bank:
|
if not bank and credit_type.special_type == "Chèque":
|
||||||
form.add_error('bank', _("This field is required."))
|
form.add_error('bank', _("This field is required."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
@ -452,49 +471,18 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
club = self.object.club
|
club = self.object.club
|
||||||
context['club'] = club
|
context['club'] = club
|
||||||
form = context['form']
|
|
||||||
form.fields['user'].disabled = True
|
|
||||||
form.fields['date_start'].widget = HiddenInput()
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def get_form(self, form_class=None):
|
||||||
if form.instance.club.membership_start and form.instance.date_start < form.instance.club.membership_start:
|
form = super().get_form(form_class)
|
||||||
form.add_error('user', _("The membership must start after {:%m-%d-%Y}.")
|
form.fields['user'].disabled = True
|
||||||
.format(form.instance.club.membership_start))
|
del form.fields['date_start']
|
||||||
return super().form_invalid(form)
|
del form.fields['credit_type']
|
||||||
|
del form.fields['credit_amount']
|
||||||
if form.instance.club.membership_end and form.instance.date_start > form.instance.club.membership_end:
|
del form.fields['last_name']
|
||||||
form.add_error('user', _("The membership must begin before {:%m-%d-%Y}.")
|
del form.fields['first_name']
|
||||||
.format(form.instance.club.membership_start))
|
del form.fields['bank']
|
||||||
return super().form_invalid(form)
|
return form
|
||||||
|
|
||||||
return super().form_valid(form)
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.club.id})
|
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.club.id})
|
||||||
|
|
||||||
|
|
||||||
class ClubRenewMembershipView(ProtectQuerysetMixin, LoginRequiredMixin, View):
|
|
||||||
def get(self, *args, **kwargs):
|
|
||||||
user = self.request.user
|
|
||||||
membership = Membership.objects.filter(PermissionBackend.filter_queryset(user, Membership, "change"))\
|
|
||||||
.filter(pk=self.kwargs["pk"]).get()
|
|
||||||
|
|
||||||
if Membership.objects.filter(
|
|
||||||
club=membership.club,
|
|
||||||
user=membership.user,
|
|
||||||
date_start__gte=membership.club.membership_start,
|
|
||||||
date_end__lte=membership.club.membership_end,
|
|
||||||
).exists():
|
|
||||||
raise ValidationError(_("This membership is already renewed"))
|
|
||||||
|
|
||||||
new_membership = Membership.objects.create(
|
|
||||||
user=user,
|
|
||||||
club=membership.club,
|
|
||||||
date_start=membership.date_end + timedelta(days=1),
|
|
||||||
)
|
|
||||||
new_membership.roles.set(membership.roles.all())
|
|
||||||
new_membership.save()
|
|
||||||
|
|
||||||
return redirect(reverse_lazy('member:club_detail', kwargs={'pk': membership.club.pk}))
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
table_class = HistoryTable
|
table_class = HistoryTable
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
def get_queryset(self, **kwargs):
|
||||||
return super().get_queryset(**kwargs).order_by("-id").all()[:50]
|
return super().get_queryset(**kwargs).order_by("-id").all()[:20]
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -232,12 +232,12 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
if credit_type is not None and credit_amount > 0:
|
if credit_type is not None and credit_amount > 0:
|
||||||
if not last_name or not first_name or not bank:
|
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
|
||||||
if not last_name:
|
if not last_name:
|
||||||
form.add_error('last_name', _("This field is required."))
|
form.add_error('last_name', _("This field is required."))
|
||||||
if not first_name:
|
if not first_name:
|
||||||
form.add_error('first_name', _("This field is required."))
|
form.add_error('first_name', _("This field is required."))
|
||||||
if not bank:
|
if not bank and credit_type.special_type == "Chèque":
|
||||||
form.add_error('bank', _("This field is required."))
|
form.add_error('bank', _("This field is required."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer text-center">
|
<div class="card-footer text-center">
|
||||||
{% if can_add_members %}
|
{% if can_add_members %}
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_add_member' pk=club.pk %}"> {% trans "Add member" %}</a>
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_add_member' club_pk=club.pk %}"> {% trans "Add member" %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if ".change_"|has_perm:club %}
|
{% if ".change_"|has_perm:club %}
|
||||||
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_update' pk=club.pk %}"> {% trans "Edit" %}</a>
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_update' pk=club.pk %}"> {% trans "Edit" %}</a>
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -34,7 +34,7 @@ commands =
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
# Ignore too many errors, should be reduced in the future
|
# Ignore too many errors, should be reduced in the future
|
||||||
ignore = D203, W503, E203, I100, I101
|
ignore = D203, W503, E203, I100, I101, C901
|
||||||
exclude =
|
exclude =
|
||||||
.tox,
|
.tox,
|
||||||
.git,
|
.git,
|
||||||
|
|
Loading…
Reference in New Issue