From dbe582238fb52b465219d67c4b24e68a37b21eb7 Mon Sep 17 00:00:00 2001 From: Hugo LEVY-FALK Date: Tue, 3 Jul 2018 19:30:31 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20possibilit=C3=A9=20de=20recha?= =?UTF-8?q?rger=20son=20solde.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cotisations/forms.py | 29 ++++--- .../migrations/0037_auto_20180703_1202.py | 35 +++++++++ cotisations/payment_methods/balance/models.py | 7 ++ .../templates/cotisations/payment.html | 2 + cotisations/views.py | 21 +----- users/templates/users/profil.html | 2 +- users/views.py | 75 ++++++++++--------- 7 files changed, 105 insertions(+), 66 deletions(-) create mode 100644 cotisations/migrations/0037_auto_20180703_1202.py diff --git a/cotisations/forms.py b/cotisations/forms.py index 9d638221..b59eb6c3 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -42,10 +42,10 @@ from django.core.validators import MinValueValidator from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy as _l -from preferences.models import OptionalUser from re2o.field_permissions import FieldPermissionFormMixin from re2o.mixins import FormRevMixin from .models import Article, Paiement, Facture, Banque +from .payment_methods import balance class NewFactureForm(FormRevMixin, ModelForm): @@ -362,34 +362,41 @@ class RechargeForm(FormRevMixin, Form): min_value=0.01, validators=[] ) + payment = forms.ModelChoiceField( + queryset=Paiement.objects.none(), + label=_l("Payment method") + ) def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') super(RechargeForm, self).__init__(*args, **kwargs) + self.fields['payment'].empty_label = \ + _("Select a payment method") + self.fields['payment'].queryset = Paiement.objects.filter( + pk__in=map(lambda x: x.pk, + Paiement.find_allowed_payments(self.user)) + ) def clean_value(self): """ - Returns a cleaned vlaue from the received form by validating + Returns a cleaned value from the received form by validating the value is well inside the possible limits """ value = self.cleaned_data['value'] - if value < OptionalUser.get_cached_value('min_online_payment'): + balance_method, _created = balance.PaymentMethod\ + .objects.get_or_create() + if value < balance_method.minimum_balance: raise forms.ValidationError( _("Requested amount is too small. Minimum amount possible : \ %(min_online_amount)s €.") % { - 'min_online_amount': OptionalUser.get_cached_value( - 'min_online_payment' - ) + 'min_online_amount': balance_method.minimum_balance } ) - if value + self.user.solde > \ - OptionalUser.get_cached_value('max_solde'): + if value + self.user.solde > balance_method.maximum_balance: raise forms.ValidationError( _("Requested amount is too high. Your balance can't exceed \ %(max_online_balance)s €.") % { - 'max_online_balance': OptionalUser.get_cached_value( - 'max_solde' - ) + 'max_online_balance': balance_method.maximum_balance } ) return value diff --git a/cotisations/migrations/0037_auto_20180703_1202.py b/cotisations/migrations/0037_auto_20180703_1202.py new file mode 100644 index 00000000..3860ef87 --- /dev/null +++ b/cotisations/migrations/0037_auto_20180703_1202.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-07-03 17:02 +from __future__ import unicode_literals + +from django.db import migrations, models + +def create_max_balance(apps, schema_editor): + OptionalUser = apps.get_model('preferences', 'OptionalUser') + Payment = apps.get_model('cotisations', 'Paiement') + + balance, _created = Payment.objects.get_or_create(moyen='solde') + options, _created = OptionalUser.objects.get_or_create() + + balance.maximum_balance = options.max_solde + balance.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('cotisations', '0036_auto_20180703_1056'), + ] + + operations = [ + migrations.AlterModelOptions( + name='paiement', + options={'permissions': (('view_paiement', "Can see a payement's details"), ('use_every_payment', 'Can use every payement')), 'verbose_name': 'Payment method', 'verbose_name_plural': 'Payment methods'}, + ), + migrations.AddField( + model_name='balancepayment', + name='maximum_balance', + field=models.DecimalField(decimal_places=2, default=50, help_text='The maximal amount of money allowed for the balance.', max_digits=5, verbose_name='Maximum balance'), + ), + migrations.RunPython(create_max_balance) + ] diff --git a/cotisations/payment_methods/balance/models.py b/cotisations/payment_methods/balance/models.py index b2ff96cc..957244d7 100644 --- a/cotisations/payment_methods/balance/models.py +++ b/cotisations/payment_methods/balance/models.py @@ -28,6 +28,13 @@ class BalancePayment(PaymentMethodMixin, models.Model): max_digits=5, decimal_places=2, ) + maximum_balance = models.DecimalField( + verbose_name=_l("Maximum balance"), + help_text=_l("The maximal amount of money allowed for the balance."), + max_digits=5, + decimal_places=2, + default=50 + ) def end_payment(self, invoice, request): user = invoice.user diff --git a/cotisations/templates/cotisations/payment.html b/cotisations/templates/cotisations/payment.html index 57940485..577ca64f 100644 --- a/cotisations/templates/cotisations/payment.html +++ b/cotisations/templates/cotisations/payment.html @@ -37,7 +37,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{{ content | safe }} + {% if form %} {% bootstrap_form form %} + {% endif %} {% trans "Pay" as tr_pay %} {% bootstrap_button tr_pay button_type='submit' icon='piggy-bank' %}
diff --git a/cotisations/views.py b/cotisations/views.py index 40b09303..dc906686 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -821,24 +821,11 @@ def recharge(request): """ View used to refill the balance by using online payment. """ - if AssoOption.get_cached_value('payment') == 'NONE': - messages.error( - request, - _("Online payment is disabled.") - ) - return redirect(reverse( - 'users:profil', - kwargs={'userid': request.user.id} - )) refill_form = RechargeForm(request.POST or None, user=request.user) if refill_form.is_valid(): invoice = Facture(user=request.user) - payment, _created = Paiement.objects.get_or_create( - moyen='Rechargement en ligne' - ) - invoice.paiement = payment + invoice.paiement = refill_form.cleaned_data['payment'] invoice.valid = False - invoice.save() purchase = Vente.objects.create( facture=invoice, name='solde', @@ -846,10 +833,8 @@ def recharge(request): number=1 ) purchase.save() - # content = online_payment.PAYMENT_SYSTEM[ - # AssoOption.get_cached_value('payment') - # ](invoice, request) - return render(request, 'cotisations/payment.html', content) + invoice.save() + return invoice.paiement.end_payment(invoice, request) return form({ 'rechargeform': refill_form, 'solde': request.user.solde diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 6acc633a..72491b68 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -166,7 +166,7 @@ non adhérent{% endif %} et votre connexion est {% if users.has_access %} Solde {{ users.solde }} € - {% if user_solde and allow_online_payment %} + {% if user_solde %} Recharger diff --git a/users/views.py b/users/views.py index a125124c..8911c85e 100644 --- a/users/views.py +++ b/users/views.py @@ -49,9 +49,9 @@ from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer from reversion import revisions as reversion -from cotisations.models import Facture +from cotisations.models import Facture, Paiement from machines.models import Machine -from preferences.models import OptionalUser, GeneralOption, AssoOption +from preferences.models import GeneralOption from re2o.views import form from re2o.utils import ( all_has_access, @@ -246,7 +246,8 @@ def state(request, user, userid): @can_edit(User, 'groups') def groups(request, user, userid): """ View to edit the groups of a user """ - group_form = GroupForm(request.POST or None, instance=user, user=request.user) + group_form = GroupForm(request.POST or None, + instance=user, user=request.user) if group_form.is_valid(): if group_form.changed_data: group_form.save() @@ -404,23 +405,23 @@ def edit_ban(request, ban_instance, **_kwargs): request ) + @login_required @can_delete(Ban) def del_ban(request, ban, **_kwargs): - """ Supprime un banissement""" - if request.method == "POST": - ban.delete() - messages.success(request, "Le banissement a été supprimé") - return redirect(reverse( - 'users:profil', - kwargs={'userid': str(ban.user.id)} - )) - return form( - {'objet': ban, 'objet_name': 'ban'}, - 'users/delete.html', - request - ) - + """ Supprime un banissement""" + if request.method == "POST": + ban.delete() + messages.success(request, "Le banissement a été supprimé") + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(ban.user.id)} + )) + return form( + {'objet': ban, 'objet_name': 'ban'}, + 'users/delete.html', + request + ) @login_required @@ -481,19 +482,20 @@ def edit_whitelist(request, whitelist_instance, **_kwargs): @login_required @can_delete(Whitelist) def del_whitelist(request, whitelist, **_kwargs): - """ Supprime un acces gracieux""" - if request.method == "POST": - whitelist.delete() - messages.success(request, "L'accés gracieux a été supprimé") - return redirect(reverse( - 'users:profil', - kwargs={'userid': str(whitelist.user.id)} - )) - return form( - {'objet': whitelist, 'objet_name': 'whitelist'}, - 'users/delete.html', - request - ) + """ Supprime un acces gracieux""" + if request.method == "POST": + whitelist.delete() + messages.success(request, "L'accés gracieux a été supprimé") + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(whitelist.user.id)} + )) + return form( + {'objet': whitelist, 'objet_name': 'whitelist'}, + 'users/delete.html', + request + ) + @login_required @can_create(School) @@ -814,7 +816,7 @@ def index_listright(request): 'users/index_listright.html', { 'listright_list': listright_list, - 'superuser_right' : superuser_right, + 'superuser_right': superuser_right, } ) @@ -837,7 +839,7 @@ def mon_profil(request): return redirect(reverse( 'users:profil', kwargs={'userid': str(request.user.id)} - )) + )) @login_required @@ -881,20 +883,20 @@ def profil(request, users, **_kwargs): request.GET.get('order'), SortTable.USERS_INDEX_WHITE ) - user_solde = OptionalUser.get_cached_value('user_solde') - allow_online_payment = True# TODO : AssoOption.get_cached_value('payment') != 'NONE' + balance, _created = Paiement.objects.get_or_create(moyen="solde") + user_solde = Facture.can_create(request.user) \ + and balance.can_use_payment(request.user) return render( request, 'users/profil.html', { 'users': users, 'machines_list': machines, - 'nb_machines' : nb_machines, + 'nb_machines': nb_machines, 'facture_list': factures, 'ban_list': bans, 'white_list': whitelists, 'user_solde': user_solde, - 'allow_online_payment': allow_online_payment, } ) @@ -959,6 +961,7 @@ def process_passwd(request, req): class JSONResponse(HttpResponse): """ Framework Rest """ + def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'application/json'