diff --git a/apps/member/models.py b/apps/member/models.py index 46051fe1..9f1b341b 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -230,6 +230,7 @@ class Membership(models.Model): ) date_start = models.DateField( + default=datetime.date.today, verbose_name=_('membership starts on'), ) diff --git a/apps/note/admin.py b/apps/note/admin.py index 7b4ba870..dc6470d2 100644 --- a/apps/note/admin.py +++ b/apps/note/admin.py @@ -8,7 +8,7 @@ from polymorphic.admin import PolymorphicChildModelAdmin, \ from .models.notes import Alias, Note, NoteClub, NoteSpecial, NoteUser from .models.transactions import Transaction, TemplateCategory, TransactionTemplate, \ - RecurrentTransaction, MembershipTransaction + RecurrentTransaction, MembershipTransaction, SpecialTransaction class AliasInlines(admin.TabularInline): @@ -102,7 +102,7 @@ class TransactionAdmin(PolymorphicParentModelAdmin): """ Admin customisation for Transaction """ - child_models = (RecurrentTransaction, MembershipTransaction) + child_models = (RecurrentTransaction, MembershipTransaction, SpecialTransaction) list_display = ('created_at', 'poly_source', 'poly_destination', 'quantity', 'amount', 'valid') list_filter = ('valid',) @@ -141,7 +141,14 @@ class TransactionAdmin(PolymorphicParentModelAdmin): @admin.register(MembershipTransaction) class MembershipTransactionAdmin(PolymorphicChildModelAdmin): """ - Admin customisation for Transaction + Admin customisation for MembershipTransaction + """ + + +@admin.register(SpecialTransaction) +class SpecialTransactionAdmin(PolymorphicChildModelAdmin): + """ + Admin customisation for SpecialTransaction """ diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 3f4063d5..656f2243 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -1,9 +1,12 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ +from note.models import NoteSpecial +from note_kfet.inputs import AmountInput class SignUpForm(UserCreationForm): @@ -19,3 +22,46 @@ class SignUpForm(UserCreationForm): class Meta: model = User fields = ('first_name', 'last_name', 'username', 'email', ) + + +class ValidationForm(forms.Form): + credit_type = forms.ModelChoiceField( + queryset=NoteSpecial.objects, + label=_("Credit type"), + empty_label=_("No credit"), + required=False, + ) + + credit_amount = forms.IntegerField( + label=_("Credit amount"), + required=False, + initial=0, + widget=AmountInput(), + ) + + last_name = forms.CharField( + label=_("Last name"), + required=False, + ) + + first_name = forms.CharField( + label=_("First name"), + required=False, + ) + + bank = forms.CharField( + label=_("Bank"), + required=False, + ) + + join_BDE = forms.BooleanField( + label=_("Join BDE"), + required=False, + initial=True, + ) + + join_Kfet = forms.BooleanField( + label=_("Join Kfet"), + required=False, + initial=True, + ) diff --git a/apps/registration/views.py b/apps/registration/views.py index 7f06f92f..0f09cda4 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -12,14 +12,16 @@ from django.utils.http import urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ from django.views import View from django.views.decorators.csrf import csrf_protect -from django.views.generic import CreateView, TemplateView, DetailView +from django.views.generic import CreateView, TemplateView, DetailView, FormView from django_tables2 import SingleTableView from member.forms import ProfileForm -from member.models import Profile +from member.models import Membership, Club +from note.models import SpecialTransaction +from note.templatetags.pretty_money import pretty_money from permission.backends import PermissionBackend from permission.views import ProtectQuerysetMixin -from .forms import SignUpForm +from .forms import SignUpForm, ValidationForm from .tables import FutureUserTable from .tokens import account_activation_token @@ -138,11 +140,12 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi return context -class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): +class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView, FormView): """ Affiche les informations sur un utilisateur, sa note, ses clubs... """ model = User + form_class = ValidationForm context_object_name = "user_object" template_name = "registration/future_profile_detail.html" @@ -152,6 +155,92 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView) """ return super().get_queryset().filter(profile__registration_valid=False) + def get_form(self, form_class=None): + form = super().get_form(form_class) + user = self.get_object() + form.fields["last_name"].initial = user.last_name + form.fields["first_name"].initial = user.first_name + return form + + def form_valid(self, form): + user = self.object = self.get_object() + + print(form.cleaned_data) + credit_type = form.cleaned_data["credit_type"] + credit_amount = form.cleaned_data["credit_amount"] + last_name = form.cleaned_data["last_name"] + first_name = form.cleaned_data["first_name"] + bank = form.cleaned_data["bank"] + join_BDE = form.cleaned_data["join_BDE"] + join_Kfet = form.cleaned_data["join_Kfet"] + + fee = 0 + bde = Club.objects.get(name="BDE") + bde_fee = bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid + if join_BDE: + fee += bde_fee + kfet = Club.objects.get(name="Kfet") + kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid + if join_Kfet: + fee += kfet_fee + + if join_Kfet and not join_BDE: + form.add_error('join_Kfet', _("You must join BDE club before joining Kfet club.")) + + if fee > credit_amount: + form.add_error('credit_type', + _("The entered amount is not enough for the memberships, should be at least {}") + .format(pretty_money(fee))) + return self.form_invalid(form) + + 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: + form.add_error('last_name', _("This field is required.")) + if not first_name: + form.add_error('first_name', _("This field is required.")) + if not bank: + form.add_error('bank', _("This field is required.")) + return self.form_invalid(form) + + ret = super().form_valid(form) + user.is_active = True + user.profile.registration_valid = True + user.save() + user.profile.save() + + if credit_type is not None and credit_amount > 0: + SpecialTransaction.objects.create( + source=credit_type, + destination=user.note, + quantity=1, + amount=credit_amount, + reason="Crédit " + credit_type.special_type + " (Inscription)", + last_name=last_name, + first_name=first_name, + bank=bank, + valid=True, + ) + + if join_BDE: + Membership.objects.create( + club=bde, + user=user, + fee=bde_fee, + ) + + if join_Kfet: + Membership.objects.create( + club=kfet, + user=user, + fee=kfet_fee, + ) + + return ret + + def get_success_url(self): + return reverse_lazy('member:user_detail', args=(self.get_object().pk, )) + class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View): """ diff --git a/note_kfet/inputs.py b/note_kfet/inputs.py index ecd758e0..b3cccbce 100644 --- a/note_kfet/inputs.py +++ b/note_kfet/inputs.py @@ -13,7 +13,7 @@ class AmountInput(NumberInput): template_name = "note/amount_input.html" def format_value(self, value): - return None if value is None or value == "" else "{:.02f}".format(value / 100, ) + return None if value is None or value == "" else "{:.02f}".format(int(value) / 100, ) def value_from_datadict(self, data, files, name): val = super().value_from_datadict(data, files, name) diff --git a/templates/registration/future_profile_detail.html b/templates/registration/future_profile_detail.html index 9b7449e2..2172749a 100644 --- a/templates/registration/future_profile_detail.html +++ b/templates/registration/future_profile_detail.html @@ -1,54 +1,65 @@ {% extends "base.html" %} {% load static %} {% load i18n %} -{% load render_table from django_tables2 %} +{% load crispy_forms_tags %} {% load pretty_money %} {% block content %} +