mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-23 20:03:11 +00:00
Passage du paiement par solde en paiement personnalisé.
This commit is contained in:
parent
3e18ebb7fb
commit
692b3b70b6
9 changed files with 128 additions and 61 deletions
|
@ -3,7 +3,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import cotisations.payment_methods.comnpay.aes_field
|
import cotisations.payment_methods.comnpay.aes_field
|
||||||
import cotisations.payment_methods.models
|
import cotisations.payment_methods.mixins
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
|
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
|
||||||
],
|
],
|
||||||
bases=(cotisations.payment_methods.models.PaymentMethodMixin, models.Model),
|
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ComnpayPayment',
|
name='ComnpayPayment',
|
||||||
|
@ -57,7 +57,7 @@ class Migration(migrations.Migration):
|
||||||
('payment_pass', cotisations.payment_methods.comnpay.aes_field.AESEncryptedField(blank=True, max_length=255, null=True)),
|
('payment_pass', cotisations.payment_methods.comnpay.aes_field.AESEncryptedField(blank=True, max_length=255, null=True)),
|
||||||
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
|
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
|
||||||
],
|
],
|
||||||
bases=(cotisations.payment_methods.models.PaymentMethodMixin, models.Model),
|
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||||
),
|
),
|
||||||
migrations.RunPython(add_comnpay),
|
migrations.RunPython(add_comnpay),
|
||||||
migrations.RunPython(add_cheque),
|
migrations.RunPython(add_cheque),
|
||||||
|
|
41
cotisations/migrations/0033_balancepayment.py
Normal file
41
cotisations/migrations/0033_balancepayment.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2018-07-03 13:53
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import cotisations.payment_methods.mixins
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
def add_solde(apps, schema_editor):
|
||||||
|
OptionalUser = apps.get_model('preferences', 'OptionalUser')
|
||||||
|
options, _created = OptionalUser.objects.get_or_create()
|
||||||
|
|
||||||
|
Payment = apps.get_model('cotisations', 'Paiement')
|
||||||
|
BalancePayment = apps.get_model('cotisations', 'BalancePayment')
|
||||||
|
|
||||||
|
solde, _created = Payment.objects.get_or_create(moyen="solde")
|
||||||
|
balance = BalancePayment()
|
||||||
|
balance.payment = solde
|
||||||
|
balance.minimum_balance = options.solde_negatif
|
||||||
|
balance.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cotisations', '0032_chequepayment_comnpaypayment'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='BalancePayment',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('minimum_balance', models.DecimalField(decimal_places=2, help_text='The minimal amount of money allowed for the balance at the end of a payment. You can specify negative amount.', max_digits=5, verbose_name='Minimum balance')),
|
||||||
|
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
|
||||||
|
],
|
||||||
|
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.RunPython(add_solde)
|
||||||
|
]
|
|
@ -668,7 +668,7 @@ class Paiement(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': request.user.pk}
|
kwargs={'userid': invoice.user.pk}
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from . import comnpay, cheque, urls
|
from . import comnpay, cheque, balance, urls
|
||||||
|
|
||||||
PAYMENT_METHODS = [
|
PAYMENT_METHODS = [
|
||||||
comnpay,
|
comnpay,
|
||||||
cheque,
|
cheque,
|
||||||
|
balance,
|
||||||
]
|
]
|
||||||
|
|
BIN
cotisations/payment_methods/balance/.views.py.swo
Normal file
BIN
cotisations/payment_methods/balance/.views.py.swo
Normal file
Binary file not shown.
7
cotisations/payment_methods/balance/__init__.py
Normal file
7
cotisations/payment_methods/balance/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
This module contains a method to pay online using user balance.
|
||||||
|
"""
|
||||||
|
from . import models
|
||||||
|
NAME = "BALANCE"
|
||||||
|
|
||||||
|
PaymentMethod = models.BalancePayment
|
50
cotisations/payment_methods/balance/models.py
Normal file
50
cotisations/payment_methods/balance/models.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
from django.contrib import messages
|
||||||
|
|
||||||
|
|
||||||
|
from cotisations.models import Paiement
|
||||||
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
||||||
|
|
||||||
|
class BalancePayment(PaymentMethodMixin, models.Model):
|
||||||
|
"""
|
||||||
|
The model allowing you to pay with a cheque.
|
||||||
|
"""
|
||||||
|
payment = models.OneToOneField(
|
||||||
|
Paiement,
|
||||||
|
related_name='payment_method',
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
|
minimum_balance = models.DecimalField(
|
||||||
|
verbose_name=_l("Minimum balance"),
|
||||||
|
help_text=_l("The minimal amount of money allowed for the balance"
|
||||||
|
" at the end of a payment. You can specify negative "
|
||||||
|
"amount."
|
||||||
|
),
|
||||||
|
max_digits=5,
|
||||||
|
decimal_places=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
def end_payment(self, invoice, request):
|
||||||
|
user = invoice.user
|
||||||
|
total_price = invoice.prix_total()
|
||||||
|
if float(user.solde) - float(total_price) < self.minimum_balance:
|
||||||
|
invoice.valid = False
|
||||||
|
invoice.save()
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_("Your balance is too low for this operation.")
|
||||||
|
)
|
||||||
|
return redirect(reverse(
|
||||||
|
'users:profil',
|
||||||
|
kwargs={'userid': user.id}
|
||||||
|
))
|
||||||
|
return invoice.paiement.end_payment(
|
||||||
|
invoice,
|
||||||
|
request,
|
||||||
|
use_payment_method=False
|
||||||
|
)
|
|
@ -139,33 +139,6 @@ def new_facture(request, user, userid):
|
||||||
articles = article_formset
|
articles = article_formset
|
||||||
# Check if at leat one article has been selected
|
# Check if at leat one article has been selected
|
||||||
if any(art.cleaned_data for art in articles):
|
if any(art.cleaned_data for art in articles):
|
||||||
user_balance = OptionalUser.get_cached_value('user_solde')
|
|
||||||
negative_balance = OptionalUser.get_cached_value('solde_negatif')
|
|
||||||
# If the paiement using balance has been activated,
|
|
||||||
# checking that the total price won't get the user under
|
|
||||||
# the authorized minimum (negative_balance)
|
|
||||||
if user_balance:
|
|
||||||
# TODO : change Paiement to Payment
|
|
||||||
if new_invoice_instance.paiement == (
|
|
||||||
Paiement.objects.get_or_create(moyen='solde')[0]
|
|
||||||
):
|
|
||||||
total_price = 0
|
|
||||||
for art_item in articles:
|
|
||||||
if art_item.cleaned_data:
|
|
||||||
total_price += (
|
|
||||||
art_item.cleaned_data['article'].prix *
|
|
||||||
art_item.cleaned_data['quantity']
|
|
||||||
)
|
|
||||||
if (float(user.solde) - float(total_price)
|
|
||||||
< negative_balance):
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_("Your balance is too low for this operation.")
|
|
||||||
)
|
|
||||||
return redirect(reverse(
|
|
||||||
'users:profil',
|
|
||||||
kwargs={'userid': userid}
|
|
||||||
))
|
|
||||||
new_invoice_instance.save()
|
new_invoice_instance.save()
|
||||||
|
|
||||||
# Building a purchase for each article sold
|
# Building a purchase for each article sold
|
||||||
|
|
|
@ -426,36 +426,31 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def solde(self):
|
def solde(self):
|
||||||
""" Renvoie le solde d'un user. Vérifie que l'option solde est
|
""" Renvoie le solde d'un user.
|
||||||
activé, retourne 0 sinon.
|
|
||||||
Somme les crédits de solde et retire les débit payés par solde"""
|
Somme les crédits de solde et retire les débit payés par solde"""
|
||||||
user_solde = OptionalUser.get_cached_value('user_solde')
|
solde_objects = Paiement.objects.filter(moyen='solde')
|
||||||
if user_solde:
|
somme_debit = Vente.objects.filter(
|
||||||
solde_objects = Paiement.objects.filter(moyen='Solde')
|
facture__in=Facture.objects.filter(
|
||||||
somme_debit = Vente.objects.filter(
|
user=self,
|
||||||
facture__in=Facture.objects.filter(
|
paiement__in=solde_objects,
|
||||||
user=self,
|
valid=True
|
||||||
paiement__in=solde_objects,
|
)
|
||||||
valid=True
|
).aggregate(
|
||||||
)
|
total=models.Sum(
|
||||||
).aggregate(
|
models.F('prix')*models.F('number'),
|
||||||
total=models.Sum(
|
output_field=models.FloatField()
|
||||||
models.F('prix')*models.F('number'),
|
)
|
||||||
output_field=models.FloatField()
|
)['total'] or 0
|
||||||
)
|
somme_credit = Vente.objects.filter(
|
||||||
)['total'] or 0
|
facture__in=Facture.objects.filter(user=self, valid=True),
|
||||||
somme_credit = Vente.objects.filter(
|
name="solde"
|
||||||
facture__in=Facture.objects.filter(user=self, valid=True),
|
).aggregate(
|
||||||
name="solde"
|
total=models.Sum(
|
||||||
).aggregate(
|
models.F('prix')*models.F('number'),
|
||||||
total=models.Sum(
|
output_field=models.FloatField()
|
||||||
models.F('prix')*models.F('number'),
|
)
|
||||||
output_field=models.FloatField()
|
)['total'] or 0
|
||||||
)
|
return somme_credit - somme_debit
|
||||||
)['total'] or 0
|
|
||||||
return somme_credit - somme_debit
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def user_interfaces(self, active=True):
|
def user_interfaces(self, active=True):
|
||||||
""" Renvoie toutes les interfaces dont les machines appartiennent à
|
""" Renvoie toutes les interfaces dont les machines appartiennent à
|
||||||
|
|
Loading…
Reference in a new issue