mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-12-22 15:32:22 +00:00
parent
b1cd46bf7d
commit
fbc25240e6
@ -230,6 +230,7 @@ class Membership(models.Model):
|
||||
)
|
||||
|
||||
date_start = models.DateField(
|
||||
default=datetime.date.today,
|
||||
verbose_name=_('membership starts on'),
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
"""
|
||||
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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 %}
|
||||
<div class="card bg-light shadow">
|
||||
<div class="card-header text-center" >
|
||||
<h4> {% trans "Account #" %} {{ object.pk }}</h4>
|
||||
</div>
|
||||
<div class="card-body" id="profile_infos">
|
||||
<dl class="row">
|
||||
<dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt>
|
||||
<dd class="col-xl-6">{{ object.last_name }} {{ object.first_name }}</dd>
|
||||
|
||||
<div class="card bg-light shadow">
|
||||
<div class="card-header text-center" >
|
||||
<h4> {% trans "Account #" %} {{ object.pk }}</h4>
|
||||
<dt class="col-xl-6">{% trans 'username'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.username }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'email'|capfirst %}</dt>
|
||||
<dd class="col-xl-6"><a href="mailto:{{ object.email }}">{{ object.email }}</a></dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'password'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">
|
||||
<a class="small" href="{% url 'password_change' %}">
|
||||
{% trans 'Change password' %}
|
||||
</a>
|
||||
</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'section'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.section }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'address'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.address }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'phone number'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.phone_number }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'paid'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.paid|yesno }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<a class="btn btn-primary btn-sm" href="{% url 'member:user_update_profile' object.pk %}">{% trans 'Update Profile' %}</a>
|
||||
<a class="btn btn-danger btn-sm" href="{% url 'registration:future_user_invalidate' object.pk %}">{% trans 'Delete registration' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" id="profile_infos">
|
||||
<dl class="row">
|
||||
<dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt>
|
||||
<dd class="col-xl-6">{{ object.last_name }} {{ object.first_name }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'username'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.username }}</dd>
|
||||
<hr>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'email'|capfirst %}</dt>
|
||||
<dd class="col-xl-6"><a href="mailto:{{ object.email }}">{{ object.email }}</a></dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'password'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">
|
||||
<a class="small" href="{% url 'password_change' %}">
|
||||
{% trans 'Change password' %}
|
||||
</a>
|
||||
</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'section'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.section }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'address'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.address }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'phone number'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.phone_number }}</dd>
|
||||
|
||||
<dt class="col-xl-6">{% trans 'paid'|capfirst %}</dt>
|
||||
<dd class="col-xl-6">{{ object.profile.paid|yesno }}</dd>
|
||||
</dl>
|
||||
|
||||
{% if object.pk == user.pk %}
|
||||
<a class="small" href="{% url 'member:auth_token' %}">{% trans 'Manage auth token' %}</a>
|
||||
{% endif %}
|
||||
<div class="card bg-light shadow">
|
||||
<form method="post">
|
||||
<div class="card-header text-center" >
|
||||
<h4> {% trans "Validate account" %}</h4>
|
||||
</div>
|
||||
<div class="card-body" id="profile_infos">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<button class="btn btn-success btn-sm">{% trans 'Validate registration' %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<a class="btn btn-primary btn-sm" href="{% url 'member:user_update_profile' object.pk %}">{% trans 'Update Profile' %}</a>
|
||||
<a class="btn btn-danger btn-sm" href="{% url 'registration:future_user_invalidate' object.pk %}">{% trans 'Delete registration' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user