8
0
Fork 0
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:
Hugo LEVY-FALK 2018-07-02 21:13:13 +02:00
parent 4da804bfe7
commit cc4815c82c
13 changed files with 198 additions and 62 deletions

View file

@ -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

View file

@ -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),
] ]

View file

@ -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),
),
]

View file

@ -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

View file

@ -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

View file

@ -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']

View file

@ -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()

View file

@ -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

View file

@ -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='',

View 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

View 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)

View file

@ -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 : &nbsp; var template = `Article : &nbsp;
{% bootstrap_form articlesformset.empty_form label_class='sr-only' %} {% bootstrap_form articlesformset.empty_form label_class='sr-only' %}
&nbsp; &nbsp;
@ -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 %}

View file

@ -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)