Handle payments from the Société Générale, closes #15

This commit is contained in:
Yohann D'ANELLO 2020-04-05 15:31:39 +02:00
parent 3516b1fa04
commit f286f99ced
5 changed files with 152 additions and 71 deletions

View File

@ -26,7 +26,7 @@ class ProfileForm(forms.ModelForm):
class Meta: class Meta:
model = Profile model = Profile
fields = '__all__' fields = '__all__'
exclude = ('user', 'email_confirmed', 'registration_valid', ) exclude = ('user', 'email_confirmed', 'registration_valid', 'soge', )
class ClubForm(forms.ModelForm): class ClubForm(forms.ModelForm):

View File

@ -53,13 +53,19 @@ class Profile(models.Model):
default=False, default=False,
) )
email_confirmed = models.BooleanField(
verbose_name=_("email confirmed"),
default=False,
)
registration_valid = models.BooleanField( registration_valid = models.BooleanField(
verbose_name=_("registration valid"), verbose_name=_("registration valid"),
default=False, default=False,
) )
email_confirmed = models.BooleanField( soge = models.BooleanField(
verbose_name=_("email confirmed"), verbose_name=_("Société générale"),
help_text=_("Has the user ever be paid by the Société générale?"),
default=False, default=False,
) )

View File

@ -25,6 +25,12 @@ class SignUpForm(UserCreationForm):
class ValidationForm(forms.Form): class ValidationForm(forms.Form):
soge = forms.BooleanField(
label=_("Inscription paid by Société Générale"),
required=False,
help_text=_("Check this case is the Société Générale paid the inscription."),
)
credit_type = forms.ModelChoiceField( credit_type = forms.ModelChoiceField(
queryset=NoteSpecial.objects, queryset=NoteSpecial.objects,
label=_("Credit type"), label=_("Credit type"),
@ -55,13 +61,13 @@ class ValidationForm(forms.Form):
) )
join_BDE = forms.BooleanField( join_BDE = forms.BooleanField(
label=_("Join BDE"), label=_("Join BDE Club"),
required=False, required=False,
initial=True, initial=True,
) )
join_Kfet = forms.BooleanField( join_Kfet = forms.BooleanField(
label=_("Join Kfet"), label=_("Join Kfet Club"),
required=False, required=False,
initial=True, initial=True,
) )

View File

@ -16,7 +16,7 @@ from django.views.generic import CreateView, TemplateView, DetailView, FormView
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from member.forms import ProfileForm from member.forms import ProfileForm
from member.models import Membership, Club from member.models import Membership, Club
from note.models import SpecialTransaction, Transaction from note.models import SpecialTransaction, NoteSpecial
from note.templatetags.pretty_money import pretty_money from note.templatetags.pretty_money import pretty_money
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
@ -66,7 +66,7 @@ class UserCreateView(CreateView):
return super().form_valid(form) return super().form_valid(form)
class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): class UserValidateView(TemplateView):
title = _("Account Activation") title = _("Account Activation")
template_name = 'registration/email_validation_complete.html' template_name = 'registration/email_validation_complete.html'
@ -89,6 +89,7 @@ class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView):
user.is_active = True user.is_active = True
user.profile.email_confirmed = True user.profile.email_confirmed = True
user.save() user.save()
user.profile.save()
return super().dispatch(*args, **kwargs) return super().dispatch(*args, **kwargs)
else: else:
# Display the "Account Activation unsuccessful" page. # Display the "Account Activation unsuccessful" page.
@ -116,7 +117,7 @@ class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView):
return context return context
class UserValidationEmailSentView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): class UserValidationEmailSentView(TemplateView):
template_name = 'registration/email_validation_email_sent.html' template_name = 'registration/email_validation_email_sent.html'
title = _('Account activation email sent') title = _('Account activation email sent')
@ -170,6 +171,19 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
""" """
return super().get_queryset().filter(profile__registration_valid=False) return super().get_queryset().filter(profile__registration_valid=False)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
user = self.get_object()
fee = 0
bde = Club.objects.get(name="BDE")
fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid
kfet = Club.objects.get(name="Kfet")
fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
return ctx
def get_form(self, form_class=None): def get_form(self, form_class=None):
form = super().get_form(form_class) form = super().get_form(form_class)
user = self.get_object() user = self.get_object()
@ -180,7 +194,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
def form_valid(self, form): def form_valid(self, form):
user = self.object = self.get_object() user = self.object = self.get_object()
print(form.cleaned_data) soge = form.cleaned_data["soge"]
credit_type = form.cleaned_data["credit_type"] credit_type = form.cleaned_data["credit_type"]
credit_amount = form.cleaned_data["credit_amount"] credit_amount = form.cleaned_data["credit_amount"]
last_name = form.cleaned_data["last_name"] last_name = form.cleaned_data["last_name"]
@ -189,6 +203,10 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
join_BDE = form.cleaned_data["join_BDE"] join_BDE = form.cleaned_data["join_BDE"]
join_Kfet = form.cleaned_data["join_Kfet"] join_Kfet = form.cleaned_data["join_Kfet"]
if soge:
join_BDE = True
join_Kfet = True
fee = 0 fee = 0
bde = Club.objects.get(name="BDE") bde = Club.objects.get(name="BDE")
bde_fee = bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid bde_fee = bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid
@ -199,6 +217,11 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
if join_Kfet: if join_Kfet:
fee += kfet_fee fee += kfet_fee
if soge:
credit_type = NoteSpecial.objects.get(special_type="Virement bancaire")
credit_amount = fee
bank = "Société générale"
if join_Kfet and not join_BDE: if join_Kfet and not join_BDE:
form.add_error('join_Kfet', _("You must join BDE club before joining Kfet club.")) form.add_error('join_Kfet', _("You must join BDE club before joining Kfet club."))
@ -221,6 +244,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
ret = super().form_valid(form) ret = super().form_valid(form)
user.is_active = True user.is_active = True
user.profile.registration_valid = True user.profile.registration_valid = True
user.profile.soge = soge
user.save() user.save()
user.profile.save() user.profile.save()
@ -230,7 +254,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView,
destination=user.note, destination=user.note,
quantity=1, quantity=1,
amount=credit_amount, amount=credit_amount,
reason="Crédit " + credit_type.special_type + " (Inscription)", reason="Crédit " + ("Société générale" if soge else credit_type.special_type) + " (Inscription)",
last_name=last_name, last_name=last_name,
first_name=first_name, first_name=first_name,
bank=bank, bank=bank,

View File

@ -5,70 +5,115 @@
{% load perms %} {% load perms %}
{% block content %} {% block content %}
<div class="card bg-light shadow"> <div class="row mt-4">
<div class="card-header text-center" > <div class="col-md-3 mb-4">
<h4> {% trans "Account #" %} {{ object.pk }}</h4> <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>
<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>
{% if not object.profile.email_confirmed and "member.change_profile_email_confirmed"|has_perm:object.profile %}
<dd class="col-xl-12">
<div class="alert alert-warning">
{% trans "This user doesn't have confirmed his/her e-mail address." %}
<a href="{% url "registration:email_validation_resend" pk=object.pk %}">{% trans "Click here to resend a validation link." %}</a>
</div>
</dd>
{% endif %}
<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> </div>
<div class="card-body" id="profile_infos"> <div class="col-md-9">
<dl class="row"> <div class="card bg-light shadow">
<dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt> <form method="post">
<dd class="col-xl-6">{{ object.last_name }} {{ object.first_name }}</dd> <div class="card-header text-center" >
<h4> {% trans "Validate account" %}</h4>
<dt class="col-xl-6">{% trans 'username'|capfirst %}</dt> </div>
<dd class="col-xl-6">{{ object.username }}</dd> <div class="card-body" id="profile_infos">
{% csrf_token %}
<dt class="col-xl-6">{% trans 'email'|capfirst %}</dt> {{ form|crispy }}
<dd class="col-xl-6"><a href="mailto:{{ object.email }}">{{ object.email }}</a></dd> </div>
<div class="card-footer text-center">
{% if not object.profile.email_confirmed and "member.change_profile_email_confirmed"|has_perm:object.profile %} <button class="btn btn-success btn-sm">{% trans 'Validate registration' %}</button>
<dd class="col-xl-12"> </div>
<div class="alert alert-warning"> </form>
{% trans "This user doesn't have confirmed his/her e-mail address." %} </div>
<a href="{% url "registration:email_validation_resend" pk=object.pk %}">{% trans "Click here to resend a validation link." %}</a>
</div>
</dd>
{% endif %}
<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> </div>
{% endblock %}
<hr> {% block extrajavascript %}
<script>
soge_field = $("#id_soge");
<div class="card bg-light shadow"> function fillFields() {
<form method="post"> let checked = soge_field.is(':checked');
<div class="card-header text-center" > if (!checked) {
<h4> {% trans "Validate account" %}</h4> $("input").attr('disabled', false);
</div> $("select").attr('disabled', false);
<div class="card-body" id="profile_infos"> return;
{% csrf_token %} }
{{ form|crispy }}
</div> let credit_type = $("#id_credit_type");
<div class="card-footer text-center"> credit_type.attr('disabled', true);
<button class="btn btn-success btn-sm">{% trans 'Validate registration' %}</button> credit_type.val(4);
</div>
</form> let credit_amount = $("#id_credit_amount");
</div> credit_amount.attr('disabled', true);
credit_amount.val('{{ total_fee }}');
let bank = $("#id_bank");
bank.attr('disabled', true);
bank.val('Société générale');
let join_BDE = $("#id_join_BDE");
join_BDE.attr('disabled', true);
join_BDE.attr('checked', 'checked');
let join_Kfet = $("#id_join_Kfet");
join_Kfet.attr('disabled', true);
join_Kfet.attr('checked', 'checked');
}
soge_field.change(fillFields);
{% if object.profile.soge %}
soge_field.attr('checked', true);
fillFields();
{% endif %}
</script>
{% endblock %} {% endblock %}