From f286f99ced381cb982a34feff1c7f9ba1ec70d83 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO <yohann.danello@gmail.com> Date: Sun, 5 Apr 2020 15:31:39 +0200 Subject: [PATCH] =?UTF-8?q?Handle=20payments=20from=20the=20Soci=C3=A9t?= =?UTF-8?q?=C3=A9=20G=C3=A9n=C3=A9rale,=20closes=20#15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/member/forms.py | 2 +- apps/member/models.py | 10 +- apps/registration/forms.py | 10 +- apps/registration/views.py | 34 +++- .../registration/future_profile_detail.html | 167 +++++++++++------- 5 files changed, 152 insertions(+), 71 deletions(-) diff --git a/apps/member/forms.py b/apps/member/forms.py index 70ffcf5e..5c060f58 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -26,7 +26,7 @@ class ProfileForm(forms.ModelForm): class Meta: model = Profile fields = '__all__' - exclude = ('user', 'email_confirmed', 'registration_valid', ) + exclude = ('user', 'email_confirmed', 'registration_valid', 'soge', ) class ClubForm(forms.ModelForm): diff --git a/apps/member/models.py b/apps/member/models.py index 2cbb71eb..80681824 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -53,13 +53,19 @@ class Profile(models.Model): default=False, ) + email_confirmed = models.BooleanField( + verbose_name=_("email confirmed"), + default=False, + ) + registration_valid = models.BooleanField( verbose_name=_("registration valid"), default=False, ) - email_confirmed = models.BooleanField( - verbose_name=_("email confirmed"), + soge = models.BooleanField( + verbose_name=_("Société générale"), + help_text=_("Has the user ever be paid by the Société générale?"), default=False, ) diff --git a/apps/registration/forms.py b/apps/registration/forms.py index 656f2243..3bd1cbbf 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -25,6 +25,12 @@ class SignUpForm(UserCreationForm): 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( queryset=NoteSpecial.objects, label=_("Credit type"), @@ -55,13 +61,13 @@ class ValidationForm(forms.Form): ) join_BDE = forms.BooleanField( - label=_("Join BDE"), + label=_("Join BDE Club"), required=False, initial=True, ) join_Kfet = forms.BooleanField( - label=_("Join Kfet"), + label=_("Join Kfet Club"), required=False, initial=True, ) diff --git a/apps/registration/views.py b/apps/registration/views.py index 2ce349c4..f154b3e0 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -16,7 +16,7 @@ from django.views.generic import CreateView, TemplateView, DetailView, FormView from django_tables2 import SingleTableView from member.forms import ProfileForm 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 permission.backends import PermissionBackend from permission.views import ProtectQuerysetMixin @@ -66,7 +66,7 @@ class UserCreateView(CreateView): return super().form_valid(form) -class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): +class UserValidateView(TemplateView): title = _("Account Activation") template_name = 'registration/email_validation_complete.html' @@ -89,6 +89,7 @@ class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): user.is_active = True user.profile.email_confirmed = True user.save() + user.profile.save() return super().dispatch(*args, **kwargs) else: # Display the "Account Activation unsuccessful" page. @@ -116,7 +117,7 @@ class UserValidateView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): return context -class UserValidationEmailSentView(LoginRequiredMixin, ProtectQuerysetMixin, TemplateView): +class UserValidationEmailSentView(TemplateView): template_name = 'registration/email_validation_email_sent.html' title = _('Account activation email sent') @@ -170,6 +171,19 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView, """ 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): form = super().get_form(form_class) user = self.get_object() @@ -180,7 +194,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView, def form_valid(self, form): user = self.object = self.get_object() - print(form.cleaned_data) + soge = form.cleaned_data["soge"] credit_type = form.cleaned_data["credit_type"] credit_amount = form.cleaned_data["credit_amount"] last_name = form.cleaned_data["last_name"] @@ -189,6 +203,10 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView, join_BDE = form.cleaned_data["join_BDE"] join_Kfet = form.cleaned_data["join_Kfet"] + if soge: + join_BDE = True + join_Kfet = True + fee = 0 bde = Club.objects.get(name="BDE") 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: 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: 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) user.is_active = True user.profile.registration_valid = True + user.profile.soge = soge user.save() user.profile.save() @@ -230,7 +254,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView, destination=user.note, quantity=1, 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, first_name=first_name, bank=bank, diff --git a/templates/registration/future_profile_detail.html b/templates/registration/future_profile_detail.html index d422aec4..8c78fb8d 100644 --- a/templates/registration/future_profile_detail.html +++ b/templates/registration/future_profile_detail.html @@ -5,70 +5,115 @@ {% load perms %} {% 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> - - <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 class="row mt-4"> + <div class="col-md-3 mb-4"> + <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> - <hr> + <dt class="col-xl-6">{% trans 'username'|capfirst %}</dt> + <dd class="col-xl-6">{{ object.username }}</dd> - <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 }} + <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 class="card-footer text-center"> - <button class="btn btn-success btn-sm">{% trans 'Validate registration' %}</button> + </div> + <div class="col-md-9"> + <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> - </form> + </div> </div> +{% endblock %} + +{% block extrajavascript %} + <script> + soge_field = $("#id_soge"); + + function fillFields() { + let checked = soge_field.is(':checked'); + if (!checked) { + $("input").attr('disabled', false); + $("select").attr('disabled', false); + return; + } + + let credit_type = $("#id_credit_type"); + credit_type.attr('disabled', true); + credit_type.val(4); + + let credit_amount = $("#id_credit_amount"); + 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 %} \ No newline at end of file -- GitLab