Credit note for membership renewals

This commit is contained in:
Yohann D'ANELLO 2020-04-05 21:56:56 +02:00
parent 515edc4459
commit c513759515
7 changed files with 49 additions and 62 deletions

View File

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

View File

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

View File

@ -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")) \
.get(pk=self.kwargs["club_pk"])
user = form.instance.user 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}))

View File

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

View File

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

View File

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

View File

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