mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-23 20:03:11 +00:00
Permet la création et l'édition de moyen de paiement personnalisés.
This commit is contained in:
parent
4da804bfe7
commit
cc4815c82c
13 changed files with 198 additions and 62 deletions
|
@ -242,17 +242,12 @@ class PaiementForm(FormRevMixin, ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Paiement
|
model = Paiement
|
||||||
# TODO : change moyen to method and type_paiement to payment_type
|
# TODO : change moyen to method and type_paiement to payment_type
|
||||||
fields = ['moyen', 'type_paiement', 'allow_self_subscription']
|
fields = ['moyen', 'allow_self_subscription']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(PaiementForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(PaiementForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['moyen'].label = _("Payment method name")
|
self.fields['moyen'].label = _("Payment method name")
|
||||||
self.fields['type_paiement'].label = _("Payment type")
|
|
||||||
self.fields['type_paiement'].help_text = \
|
|
||||||
_("The payement type is used for specific behaviour.\
|
|
||||||
The \"cheque\" type means a cheque number and a bank name\
|
|
||||||
may be added when using this payment method.")
|
|
||||||
|
|
||||||
|
|
||||||
# TODO : change paiement to payment
|
# TODO : change paiement to payment
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.7 on 2018-06-28 17:28
|
# Generated by Django 1.10.7 on 2018-07-02 18:56
|
||||||
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
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ def add_comnpay(apps, schema_editor):
|
||||||
comnpay.payment_pass = options.payment_pass
|
comnpay.payment_pass = options.payment_pass
|
||||||
comnpay.payment = payment
|
comnpay.payment = payment
|
||||||
comnpay.save()
|
comnpay.save()
|
||||||
|
payment.moyen = "ComnPay"
|
||||||
|
payment.save()
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -42,18 +45,20 @@ class Migration(migrations.Migration):
|
||||||
name='ChequePayment',
|
name='ChequePayment',
|
||||||
fields=[
|
fields=[
|
||||||
('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(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),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ComnpayPayment',
|
name='ComnpayPayment',
|
||||||
fields=[
|
fields=[
|
||||||
('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_user', models.CharField(blank=True, default='', max_length=255)),
|
('payment_credential', models.CharField(blank=True, default='', max_length=255)),
|
||||||
('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(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),
|
||||||
),
|
),
|
||||||
migrations.RunPython(add_cheque),
|
|
||||||
migrations.RunPython(add_comnpay),
|
migrations.RunPython(add_comnpay),
|
||||||
|
migrations.RunPython(add_cheque),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.10.7 on 2018-06-28 19:57
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('cotisations', '0032_chequepayment_comnpaypayment'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='comnpaypayment',
|
|
||||||
name='payment_id',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=255),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
|
||||||
from . import comnpay, cheque
|
from . import comnpay, cheque
|
||||||
|
|
||||||
|
@ -7,3 +8,18 @@ urlpatterns = [
|
||||||
url(r'^comnpay/', include(comnpay.urls, namespace='comnpay')),
|
url(r'^comnpay/', include(comnpay.urls, namespace='comnpay')),
|
||||||
url(r'^cheque/', include(cheque.urls, namespace='cheque')),
|
url(r'^cheque/', include(cheque.urls, namespace='cheque')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
PAYMENT_METHODS = [
|
||||||
|
comnpay,
|
||||||
|
cheque,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def find_payment_method(payment):
|
||||||
|
for method in PAYMENT_METHODS:
|
||||||
|
try:
|
||||||
|
o = method.PaymentMethod.objects.get(payment=payment)
|
||||||
|
return o
|
||||||
|
except method.PaymentMethod.DoesNotExist:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
|
@ -4,4 +4,4 @@ This module contains a method to pay online using cheque.
|
||||||
from . import models, urls, views
|
from . import models, urls, views
|
||||||
NAME = "CHEQUE"
|
NAME = "CHEQUE"
|
||||||
|
|
||||||
Payment = models.ChequePayment
|
PaymentMethod = models.ChequePayment
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _l
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
|
||||||
from cotisations.models import Banque as Bank
|
from re2o.mixins import FormRevMixin
|
||||||
|
from cotisations.models import Facture as Invoice
|
||||||
|
|
||||||
|
|
||||||
class ChequeForm(forms.Form):
|
class InvoiceForm(FormRevMixin, forms.ModelForm):
|
||||||
"""A simple form to get the bank a the cheque number."""
|
"""A simple form to get the bank a the cheque number."""
|
||||||
bank = forms.ModelChoiceField(Bank.objects.all(), label=_l("Bank"))
|
class Meta:
|
||||||
number = forms.CharField(label=_l("Cheque number"))
|
model = Invoice
|
||||||
|
fields = ['banque', 'cheque']
|
||||||
|
|
|
@ -2,16 +2,19 @@ from django.db import models
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from cotisations.models import Paiement as BasePayment
|
from cotisations.models import Paiement
|
||||||
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
||||||
|
|
||||||
class ChequePayment(models.Model):
|
class ChequePayment(PaymentMethodMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
The model allowing you to pay with a cheque. It redefines post_payment
|
The model allowing you to pay with a cheque.
|
||||||
method. See `cotisations.models.Paiement for further details.
|
|
||||||
"""
|
"""
|
||||||
payment = models.OneToOneField(BasePayment, related_name='payment_method')
|
payment = models.OneToOneField(
|
||||||
|
Paiement,
|
||||||
|
related_name='payment_method',
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
def end_payment(self, invoice, request):
|
def end_payment(self, invoice, request):
|
||||||
invoice.valid = False
|
invoice.valid = False
|
||||||
invoice.save()
|
invoice.save()
|
||||||
|
|
|
@ -3,4 +3,4 @@ This module contains a method to pay online using comnpay.
|
||||||
"""
|
"""
|
||||||
from . import models, urls, views
|
from . import models, urls, views
|
||||||
NAME = "COMNPAY"
|
NAME = "COMNPAY"
|
||||||
Payment = models.ComnpayPayment
|
PaymentMethod = models.ComnpayPayment
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from cotisations.models import Paiement as BasePayment
|
from cotisations.models import Paiement
|
||||||
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
||||||
from .aes_field import AESEncryptedField
|
from .aes_field import AESEncryptedField
|
||||||
from .views import comnpay
|
from .views import comnpay
|
||||||
|
|
||||||
|
|
||||||
class ComnpayPayment(models.Model):
|
class ComnpayPayment(PaymentMethodMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
The model allowing you to pay with COMNPAY. It redefines post_payment
|
The model allowing you to pay with COMNPAY.
|
||||||
method. See `cotisations.models.Paiement for further details.
|
|
||||||
"""
|
"""
|
||||||
payment = models.OneToOneField(BasePayment, related_name='payment_method')
|
payment = models.OneToOneField(
|
||||||
|
Paiement,
|
||||||
|
related_name='payment_method',
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
payment_credential = models.CharField(
|
payment_credential = models.CharField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
default='',
|
default='',
|
||||||
|
|
59
cotisations/payment_methods/forms.py
Normal file
59
cotisations/payment_methods/forms.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
|
||||||
|
from . import PAYMENT_METHODS, find_payment_method
|
||||||
|
|
||||||
|
|
||||||
|
def payment_method_factory(payment, *args, **kwargs):
|
||||||
|
payment_method = kwargs.pop('instance', find_payment_method(payment))
|
||||||
|
if payment_method is not None:
|
||||||
|
return forms.modelform_factory(type(payment_method), fields='__all__')(
|
||||||
|
*args,
|
||||||
|
instance=payment_method,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
return PaymentMethodForm(payment_method, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentMethodForm(forms.Form):
|
||||||
|
"""A special form which allows you to add a payment method to a `Payment`
|
||||||
|
objects if it hasn't one yet, or to edit the existing payment method.
|
||||||
|
|
||||||
|
To do so it replaces itself with a `modelform_factory`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
payment_method = forms.ChoiceField(
|
||||||
|
label=_l("Special payment method"),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, payment_method, *args, **kwargs):
|
||||||
|
super(PaymentMethodForm, self).__init__(*args, **kwargs)
|
||||||
|
if payment_method is None:
|
||||||
|
prefix = kwargs.get('prefix', None)
|
||||||
|
self.fields['payment_method'].choices = [(i,p.NAME) for (i,p) in enumerate(PAYMENT_METHODS)]
|
||||||
|
self.fields['payment_method'].choices.insert(0, ('', _l('no')))
|
||||||
|
self.fields['payment_method'].widget.attrs = {
|
||||||
|
'id': 'paymentMethodSelect'
|
||||||
|
}
|
||||||
|
self.templates = [
|
||||||
|
forms.modelform_factory(p.PaymentMethod, fields='__all__')(prefix=prefix)
|
||||||
|
for p in PAYMENT_METHODS
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.fields = {}
|
||||||
|
|
||||||
|
def save(self, *args, payment=None, **kwargs):
|
||||||
|
commit = kwargs.pop('commit', True)
|
||||||
|
choice = self.cleaned_data['payment_method']
|
||||||
|
if choice=='':
|
||||||
|
return
|
||||||
|
choice = int(choice)
|
||||||
|
model = PAYMENT_METHODS[choice].PaymentMethod
|
||||||
|
form = forms.modelform_factory(model, fields='__all__')(self.data, prefix=self.prefix)
|
||||||
|
payment_method = form.save(commit=False)
|
||||||
|
payment_method.payment = payment
|
||||||
|
if commit:
|
||||||
|
payment_method.save()
|
||||||
|
return payment_method
|
21
cotisations/payment_methods/mixins.py
Normal file
21
cotisations/payment_methods/mixins.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from cotisations.models import Paiement
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentMethodMixin:
|
||||||
|
"""The base class for payment models. They should inherit from this."""
|
||||||
|
payment = models.OneToOneField(
|
||||||
|
Paiement,
|
||||||
|
related_name='payment_method',
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def end_payment(self, invoice, request):
|
||||||
|
"""Redefine this method in order to get a different ending to the
|
||||||
|
payment session if you whish.
|
||||||
|
|
||||||
|
Must return a HttpResponse-like object.
|
||||||
|
"""
|
||||||
|
return self.payment.end_payment(
|
||||||
|
invoice, request, use_payment_method=False)
|
|
@ -57,16 +57,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% bootstrap_form factureform %}
|
{% bootstrap_form factureform %}
|
||||||
|
{% if payment_method %}
|
||||||
|
{% bootstrap_form payment_method %}
|
||||||
|
<div id="paymentMethod"></div>
|
||||||
|
{% endif %}
|
||||||
{% bootstrap_button action_name button_type='submit' icon='star' %}
|
{% bootstrap_button action_name button_type='submit' icon='star' %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if articlesformset %}
|
{% if articlesformset or payment_method%}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
{% if articlesformset %}
|
||||||
var prices = {};
|
var prices = {};
|
||||||
{% for article in articles %}
|
{% for article in articles %}
|
||||||
prices[{{ article.id|escapejs }}] = {{ article.prix }};
|
prices[{{ article.id|escapejs }}] = {{ article.prix }};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
var template = `Article :
|
var template = `Article :
|
||||||
{% bootstrap_form articlesformset.empty_form label_class='sr-only' %}
|
{% bootstrap_form articlesformset.empty_form label_class='sr-only' %}
|
||||||
|
|
||||||
|
@ -134,6 +139,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
}
|
}
|
||||||
update_price();
|
update_price();
|
||||||
});
|
});
|
||||||
|
{% endif %}
|
||||||
|
{% if payment_method.templates %}
|
||||||
|
var TEMPLATES = [
|
||||||
|
"",
|
||||||
|
{% for t in payment_method.templates %}
|
||||||
|
{% if t %}
|
||||||
|
`{% bootstrap_form t %}`,
|
||||||
|
{% else %}
|
||||||
|
"",
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
];
|
||||||
|
function update_payment_method_form(){
|
||||||
|
var method = document.getElementById('paymentMethodSelect').value;
|
||||||
|
if(method==""){
|
||||||
|
method=0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
method = Number(method);
|
||||||
|
method += 1;
|
||||||
|
}
|
||||||
|
console.log(method);
|
||||||
|
var html = TEMPLATES[method];
|
||||||
|
|
||||||
|
document.getElementById('paymentMethod').innerHTML = html;
|
||||||
|
}
|
||||||
|
document.getElementById("paymentMethodSelect").addEventListener("change", update_payment_method_form);
|
||||||
|
{% endif %}
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ from .forms import (
|
||||||
RechargeForm
|
RechargeForm
|
||||||
)
|
)
|
||||||
from .tex import render_invoice
|
from .tex import render_invoice
|
||||||
|
from .payment_methods.forms import payment_method_factory
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -473,9 +474,15 @@ def add_paiement(request):
|
||||||
"""
|
"""
|
||||||
View used to add a payment method.
|
View used to add a payment method.
|
||||||
"""
|
"""
|
||||||
payment = PaiementForm(request.POST or None)
|
payment = PaiementForm(request.POST or None, prefix='payment')
|
||||||
if payment.is_valid():
|
payment_method = payment_method_factory(
|
||||||
payment.save()
|
payment.instance,
|
||||||
|
request.POST or None,
|
||||||
|
prefix='payment_method'
|
||||||
|
)
|
||||||
|
if payment.is_valid() and payment_method.is_valid():
|
||||||
|
payment = payment.save()
|
||||||
|
payment_method.save(payment=payment)
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_("The payment method has been successfully created.")
|
_("The payment method has been successfully created.")
|
||||||
|
@ -483,6 +490,7 @@ def add_paiement(request):
|
||||||
return redirect(reverse('cotisations:index-paiement'))
|
return redirect(reverse('cotisations:index-paiement'))
|
||||||
return form({
|
return form({
|
||||||
'factureform': payment,
|
'factureform': payment,
|
||||||
|
'payment_method': payment_method,
|
||||||
'action_name': _("Add")
|
'action_name': _("Add")
|
||||||
}, 'cotisations/facture.html', request)
|
}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
@ -494,17 +502,28 @@ def edit_paiement(request, paiement_instance, **_kwargs):
|
||||||
"""
|
"""
|
||||||
View used to edit a payment method.
|
View used to edit a payment method.
|
||||||
"""
|
"""
|
||||||
payment = PaiementForm(request.POST or None, instance=paiement_instance)
|
payment = PaiementForm(
|
||||||
if payment.is_valid():
|
request.POST or None,
|
||||||
if payment.changed_data:
|
instance=paiement_instance,
|
||||||
payment.save()
|
prefix="payment"
|
||||||
messages.success(
|
)
|
||||||
request,
|
payment_method = payment_method_factory(
|
||||||
_("The payement method has been successfully edited.")
|
paiement_instance,
|
||||||
)
|
request.POST or None,
|
||||||
|
prefix='payment_method'
|
||||||
|
)
|
||||||
|
|
||||||
|
if payment.is_valid() and payment_method.is_valid():
|
||||||
|
payment.save()
|
||||||
|
payment_method.save()
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The payement method has been successfully edited.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-paiement'))
|
return redirect(reverse('cotisations:index-paiement'))
|
||||||
return form({
|
return form({
|
||||||
'factureform': payment,
|
'factureform': payment,
|
||||||
|
'payment_method': payment_method,
|
||||||
'action_name': _("Edit")
|
'action_name': _("Edit")
|
||||||
}, 'cotisations/facture.html', request)
|
}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue