mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-30 16:42:25 +00:00
POC des moyens de paiements sous forme de modules.
This commit is contained in:
parent
d37364ee8f
commit
e0d71ed291
20 changed files with 417 additions and 68 deletions
59
cotisations/migrations/0032_chequepayment_comnpaypayment.py
Normal file
59
cotisations/migrations/0032_chequepayment_comnpaypayment.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2018-06-28 17:28
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import cotisations.payment_methods.comnpay.aes_field
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
def add_cheque(apps, schema_editor):
|
||||||
|
ChequePayment = apps.get_model('cotisations', 'ChequePayment')
|
||||||
|
Payment = apps.get_model('cotisations', 'Paiement')
|
||||||
|
for p in Payment.objects.filter(type_paiement=1):
|
||||||
|
cheque = ChequePayment()
|
||||||
|
cheque.payment = p
|
||||||
|
cheque.save()
|
||||||
|
|
||||||
|
|
||||||
|
def add_comnpay(apps, schema_editor):
|
||||||
|
ComnpayPayment = apps.get_model('cotisations', 'ComnpayPayment')
|
||||||
|
Payment = apps.get_model('cotisations', 'Paiement')
|
||||||
|
AssoOption = apps.get_model('preferences', 'AssoOption')
|
||||||
|
options, _created = AssoOption.objects.get_or_create()
|
||||||
|
payment, _created = Payment.objects.get_or_create(
|
||||||
|
moyen='Rechargement en ligne'
|
||||||
|
)
|
||||||
|
comnpay = ComnpayPayment()
|
||||||
|
comnpay.payment_user = options.payment_id
|
||||||
|
comnpay.payment_pass = options.payment_pass
|
||||||
|
comnpay.payment = payment
|
||||||
|
comnpay.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cotisations', '0031_article_allow_self_subscription'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ChequePayment',
|
||||||
|
fields=[
|
||||||
|
('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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ComnpayPayment',
|
||||||
|
fields=[
|
||||||
|
('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_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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(add_cheque),
|
||||||
|
migrations.RunPython(add_comnpay),
|
||||||
|
]
|
20
cotisations/migrations/0033_auto_20180628_2157.py
Normal file
20
cotisations/migrations/0033_auto_20180628_2157.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- 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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -42,6 +42,9 @@ from django.core.validators import MinValueValidator
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.translation import ugettext_lazy as _l
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.contrib import messages
|
||||||
|
|
||||||
from machines.models import regen
|
from machines.models import regen
|
||||||
from re2o.field_permissions import FieldPermissionModelMixin
|
from re2o.field_permissions import FieldPermissionModelMixin
|
||||||
|
@ -629,6 +632,36 @@ class Paiement(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
super(Paiement, self).save(*args, **kwargs)
|
super(Paiement, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
def end_payment(self, invoice, request):
|
||||||
|
"""
|
||||||
|
The general way of ending a payment. You may redefine this method for custom
|
||||||
|
payment methods. Must return a HttpResponse-like object.
|
||||||
|
"""
|
||||||
|
if hasattr(self, 'payment_method'):
|
||||||
|
return self.payment_method.end_payment(invoice, request)
|
||||||
|
|
||||||
|
# In case a cotisation was bought, inform the user, the
|
||||||
|
# cotisation time has been extended too
|
||||||
|
if any(sell.type_cotisation for sell in invoice.vente_set.all()):
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The cotisation of %(member_name)s has been \
|
||||||
|
extended to %(end_date)s.") % {
|
||||||
|
'member_name': request.user.pseudo,
|
||||||
|
'end_date': request.user.end_adhesion()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Else, only tell the invoice was created
|
||||||
|
else:
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been created.")
|
||||||
|
)
|
||||||
|
return redirect(reverse(
|
||||||
|
'users:profil',
|
||||||
|
kwargs={'userid': request.user.pk}
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
class Cotisation(RevMixin, AclMixin, models.Model):
|
class Cotisation(RevMixin, AclMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
|
9
cotisations/payment_methods/__init__.py
Normal file
9
cotisations/payment_methods/__init__.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from django.conf.urls import include, url
|
||||||
|
|
||||||
|
from . import comnpay, cheque
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^comnpay/', include(comnpay.urls, namespace='comnpay')),
|
||||||
|
url(r'^cheque/', include(cheque.urls, namespace='cheque')),
|
||||||
|
]
|
7
cotisations/payment_methods/cheque/__init__.py
Normal file
7
cotisations/payment_methods/cheque/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
This module contains a method to pay online using cheque.
|
||||||
|
"""
|
||||||
|
from . import models, urls, views
|
||||||
|
NAME = "CHEQUE"
|
||||||
|
|
||||||
|
Payment = models.ChequePayment
|
10
cotisations/payment_methods/cheque/forms.py
Normal file
10
cotisations/payment_methods/cheque/forms.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _l
|
||||||
|
|
||||||
|
from cotisations.models import Banque as Bank
|
||||||
|
|
||||||
|
|
||||||
|
class ChequeForm(forms.Form):
|
||||||
|
"""A simple form to get the bank a the cheque number."""
|
||||||
|
bank = forms.ModelChoiceField(Bank.objects.all(), label=_l("Bank"))
|
||||||
|
number = forms.CharField(label=_l("Cheque number"))
|
21
cotisations/payment_methods/cheque/models.py
Normal file
21
cotisations/payment_methods/cheque/models.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from cotisations.models import Paiement as BasePayment
|
||||||
|
|
||||||
|
|
||||||
|
class ChequePayment(models.Model):
|
||||||
|
"""
|
||||||
|
The model allowing you to pay with a cheque. It redefines post_payment
|
||||||
|
method. See `cotisations.models.Paiement for further details.
|
||||||
|
"""
|
||||||
|
payment = models.OneToOneField(BasePayment, related_name='payment_method')
|
||||||
|
|
||||||
|
def end_payment(self, invoice, request):
|
||||||
|
invoice.valid = False
|
||||||
|
invoice.save()
|
||||||
|
return redirect(reverse(
|
||||||
|
'cotisations:cheque:validate',
|
||||||
|
kwargs={'invoice_pk': invoice.pk}
|
||||||
|
))
|
10
cotisations/payment_methods/cheque/urls.py
Normal file
10
cotisations/payment_methods/cheque/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from django.conf.urls import url
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(
|
||||||
|
r'^validate/(?P<invoice_pk>[0-9]+)$',
|
||||||
|
views.cheque,
|
||||||
|
name='validate'
|
||||||
|
)
|
||||||
|
]
|
45
cotisations/payment_methods/cheque/views.py
Normal file
45
cotisations/payment_methods/cheque/views.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
"""Payment
|
||||||
|
|
||||||
|
Here are defined some views dedicated to cheque payement.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.shortcuts import redirect, render, get_object_or_404
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
from cotisations.models import Facture as Invoice
|
||||||
|
|
||||||
|
from .models import ChequePayment
|
||||||
|
from .forms import ChequeForm
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def cheque(request, invoice_pk):
|
||||||
|
invoice = get_object_or_404(Invoice, pk=invoice_pk)
|
||||||
|
payment_method = getattr(invoice.paiement, 'payment_method', None)
|
||||||
|
if invoice.valid or not isinstance(payment_method, ChequePayment):
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_("You cannot pay this invoice with a cheque.")
|
||||||
|
)
|
||||||
|
return redirect(reverse(
|
||||||
|
'users:profil',
|
||||||
|
kwargs={'userid': request.user.pk}
|
||||||
|
))
|
||||||
|
form = ChequeForm(request.POST or None)
|
||||||
|
if form.is_valid():
|
||||||
|
invoice.banque = form.cleaned_data['bank']
|
||||||
|
invoice.cheque = form.cleaned_data['number']
|
||||||
|
invoice.valid = True
|
||||||
|
invoice.save()
|
||||||
|
return redirect(reverse(
|
||||||
|
'users:profil',
|
||||||
|
kwargs={'userid': request.user.pk}
|
||||||
|
))
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
'cotisations/payment_form.html',
|
||||||
|
{'form': form}
|
||||||
|
)
|
6
cotisations/payment_methods/comnpay/__init__.py
Normal file
6
cotisations/payment_methods/comnpay/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
"""
|
||||||
|
This module contains a method to pay online using comnpay.
|
||||||
|
"""
|
||||||
|
from . import models, urls, views
|
||||||
|
NAME = "COMNPAY"
|
||||||
|
Payment = models.ComnpayPayment
|
94
cotisations/payment_methods/comnpay/aes_field.py
Normal file
94
cotisations/payment_methods/comnpay/aes_field.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# coding:utf-8
|
||||||
|
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
# quelques clics.
|
||||||
|
#
|
||||||
|
# Copyright © 2017 Gabriel Détraz
|
||||||
|
# Copyright © 2017 Goulven Kermarec
|
||||||
|
# Copyright © 2017 Augustin Lemesle
|
||||||
|
# Copyright © 2018 Maël Kervella
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
# App de gestion des machines pour re2o
|
||||||
|
# Gabriel Détraz, Augustin Lemesle
|
||||||
|
# Gplv2
|
||||||
|
"""preferences.aes_field
|
||||||
|
Module defining a AESEncryptedField object that can be used in forms
|
||||||
|
to handle the use of properly encrypting and decrypting AES keys
|
||||||
|
"""
|
||||||
|
|
||||||
|
import string
|
||||||
|
import binascii
|
||||||
|
from random import choice
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
EOD = '`%EofD%`' # This should be something that will not occur in strings
|
||||||
|
|
||||||
|
|
||||||
|
def genstring(length=16, chars=string.printable):
|
||||||
|
""" Generate a random string of length `length` and composed of
|
||||||
|
the characters in `chars` """
|
||||||
|
return ''.join([choice(chars) for i in range(length)])
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt(key, s):
|
||||||
|
""" AES Encrypt a secret `s` with the key `key` """
|
||||||
|
obj = AES.new(key)
|
||||||
|
datalength = len(s) + len(EOD)
|
||||||
|
if datalength < 16:
|
||||||
|
saltlength = 16 - datalength
|
||||||
|
else:
|
||||||
|
saltlength = 16 - datalength % 16
|
||||||
|
ss = ''.join([s, EOD, genstring(saltlength)])
|
||||||
|
return obj.encrypt(ss)
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(key, s):
|
||||||
|
""" AES Decrypt a secret `s` with the key `key` """
|
||||||
|
obj = AES.new(key)
|
||||||
|
ss = obj.decrypt(s)
|
||||||
|
return ss.split(bytes(EOD, 'utf-8'))[0]
|
||||||
|
|
||||||
|
|
||||||
|
class AESEncryptedField(models.CharField):
|
||||||
|
""" A Field that can be used in forms for adding the support
|
||||||
|
of AES ecnrypted fields """
|
||||||
|
def save_form_data(self, instance, data):
|
||||||
|
setattr(instance, self.name,
|
||||||
|
binascii.b2a_base64(encrypt(settings.AES_KEY, data)))
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
return decrypt(settings.AES_KEY,
|
||||||
|
binascii.a2b_base64(value)).decode('utf-8')
|
||||||
|
|
||||||
|
def from_db_value(self, value, *args, **kwargs):
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
return decrypt(settings.AES_KEY,
|
||||||
|
binascii.a2b_base64(value)).decode('utf-8')
|
||||||
|
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
return binascii.b2a_base64(encrypt(
|
||||||
|
settings.AES_KEY,
|
||||||
|
value
|
||||||
|
))
|
|
@ -10,7 +10,7 @@ import hashlib
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
|
||||||
class Payment():
|
class Transaction():
|
||||||
""" The class representing a transaction with all the functions
|
""" The class representing a transaction with all the functions
|
||||||
used during the negociation
|
used during the negociation
|
||||||
"""
|
"""
|
30
cotisations/payment_methods/comnpay/models.py
Normal file
30
cotisations/payment_methods/comnpay/models.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
from cotisations.models import Paiement as BasePayment
|
||||||
|
|
||||||
|
from .aes_field import AESEncryptedField
|
||||||
|
from .views import comnpay
|
||||||
|
|
||||||
|
|
||||||
|
class ComnpayPayment(models.Model):
|
||||||
|
"""
|
||||||
|
The model allowing you to pay with COMNPAY. It redefines post_payment
|
||||||
|
method. See `cotisations.models.Paiement for further details.
|
||||||
|
"""
|
||||||
|
payment = models.OneToOneField(BasePayment, related_name='payment_method')
|
||||||
|
|
||||||
|
payment_credential = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
default='',
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
payment_pass = AESEncryptedField(
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def end_payment(self, invoice, request):
|
||||||
|
content = comnpay(invoice, request)
|
||||||
|
return render(request, 'cotisations/payment.html', content)
|
20
cotisations/payment_methods/comnpay/urls.py
Normal file
20
cotisations/payment_methods/comnpay/urls.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from django.conf.urls import url
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(
|
||||||
|
r'^accept/(?P<factureid>[0-9]+)$',
|
||||||
|
views.accept_payment,
|
||||||
|
name='accept_payment'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^refuse/$',
|
||||||
|
views.refuse_payment,
|
||||||
|
name='refuse_payment'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^ipn/$',
|
||||||
|
views.ipn,
|
||||||
|
name='ipn'
|
||||||
|
),
|
||||||
|
]
|
|
@ -15,8 +15,8 @@ from django.utils.translation import ugettext as _
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
|
|
||||||
from preferences.models import AssoOption
|
from preferences.models import AssoOption
|
||||||
from .models import Facture
|
from cotisations.models import Facture
|
||||||
from .payment_utils.comnpay import Payment as ComnpayPayment
|
from .comnpay import Transaction
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
|
@ -73,7 +73,7 @@ def ipn(request):
|
||||||
Verify that we can firmly save the user's action and notify
|
Verify that we can firmly save the user's action and notify
|
||||||
Comnpay with 400 response if not or with a 200 response if yes
|
Comnpay with 400 response if not or with a 200 response if yes
|
||||||
"""
|
"""
|
||||||
p = ComnpayPayment()
|
p = Transaction()
|
||||||
order = ('idTpe', 'idTransaction', 'montant', 'result', 'sec', )
|
order = ('idTpe', 'idTransaction', 'montant', 'result', 'sec', )
|
||||||
try:
|
try:
|
||||||
data = OrderedDict([(f, request.POST[f]) for f in order])
|
data = OrderedDict([(f, request.POST[f]) for f in order])
|
||||||
|
@ -121,15 +121,15 @@ def comnpay(facture, request):
|
||||||
the preferences.
|
the preferences.
|
||||||
"""
|
"""
|
||||||
host = request.get_host()
|
host = request.get_host()
|
||||||
p = ComnpayPayment(
|
p = Transaction(
|
||||||
str(AssoOption.get_cached_value('payment_id')),
|
str(AssoOption.get_cached_value('payment_id')),
|
||||||
str(AssoOption.get_cached_value('payment_pass')),
|
str(AssoOption.get_cached_value('payment_pass')),
|
||||||
'https://' + host + reverse(
|
'https://' + host + reverse(
|
||||||
'cotisations:accept_payment',
|
'cotisations:comnpay_accept_payment',
|
||||||
kwargs={'factureid': facture.id}
|
kwargs={'factureid': facture.id}
|
||||||
),
|
),
|
||||||
'https://' + host + reverse('cotisations:refuse_payment'),
|
'https://' + host + reverse('cotisations:comnpay_refuse_payment'),
|
||||||
'https://' + host + reverse('cotisations:ipn'),
|
'https://' + host + reverse('cotisations:comnpay_ipn'),
|
||||||
"",
|
"",
|
||||||
"D"
|
"D"
|
||||||
)
|
)
|
||||||
|
@ -145,9 +145,3 @@ def comnpay(facture, request):
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
# The payment systems supported by re2o
|
|
||||||
PAYMENT_SYSTEM = {
|
|
||||||
'COMNPAY': comnpay,
|
|
||||||
'NONE': None
|
|
||||||
}
|
|
37
cotisations/templates/cotisations/payment_form.html
Normal file
37
cotisations/templates/cotisations/payment_form.html
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{% extends "cotisations/sidebar.html" %}
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2018 Hugo Levy-Falk
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load staticfiles%}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans form.title %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>{% trans form.title %}</h2>
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
{% bootstrap_button tr_confirm button_type='submit' icon='piggy-bank' %}
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -29,7 +29,7 @@ from django.conf.urls import url
|
||||||
|
|
||||||
import re2o
|
import re2o
|
||||||
from . import views
|
from . import views
|
||||||
from . import payment
|
from . import payment_methods
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(
|
url(
|
||||||
|
@ -143,20 +143,6 @@ urlpatterns = [
|
||||||
views.recharge,
|
views.recharge,
|
||||||
name='recharge'
|
name='recharge'
|
||||||
),
|
),
|
||||||
url(
|
|
||||||
r'^payment/accept/(?P<factureid>[0-9]+)$',
|
|
||||||
payment.accept_payment,
|
|
||||||
name='accept_payment'
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r'^payment/refuse/$',
|
|
||||||
payment.refuse_payment,
|
|
||||||
name='refuse_payment'
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r'^payment/ipn/$',
|
|
||||||
payment.ipn,
|
|
||||||
name='ipn'
|
|
||||||
),
|
|
||||||
url(r'^$', views.index, name='index'),
|
url(r'^$', views.index, name='index'),
|
||||||
]
|
] + payment_methods.urlpatterns
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ from .forms import (
|
||||||
CreditSoldeForm,
|
CreditSoldeForm,
|
||||||
RechargeForm
|
RechargeForm
|
||||||
)
|
)
|
||||||
from . import payment as online_payment
|
|
||||||
from .tex import render_invoice
|
from .tex import render_invoice
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,11 +158,6 @@ def new_facture(request, user, userid):
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': userid}
|
kwargs={'userid': userid}
|
||||||
))
|
))
|
||||||
is_online_payment = new_invoice_instance.paiement == (
|
|
||||||
Paiement.objects.get_or_create(
|
|
||||||
moyen='Rechargement en ligne')[0])
|
|
||||||
new_invoice_instance.valid = not is_online_payment
|
|
||||||
# Saving the invoice
|
|
||||||
new_invoice_instance.save()
|
new_invoice_instance.save()
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,34 +176,8 @@ def new_facture(request, user, userid):
|
||||||
)
|
)
|
||||||
new_purchase.save()
|
new_purchase.save()
|
||||||
|
|
||||||
if is_online_payment:
|
return new_invoice_instance.paiement.end_payment(new_invoice_instance, request)
|
||||||
content = online_payment.PAYMENT_SYSTEM[
|
|
||||||
AssoOption.get_cached_value('payment')
|
|
||||||
](new_invoice_instance, request)
|
|
||||||
return render(request, 'cotisations/payment.html', content)
|
|
||||||
|
|
||||||
# In case a cotisation was bought, inform the user, the
|
|
||||||
# cotisation time has been extended too
|
|
||||||
if any(art_item.cleaned_data['article'].type_cotisation
|
|
||||||
for art_item in articles if art_item.cleaned_data):
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
_("The cotisation of %(member_name)s has been \
|
|
||||||
extended to %(end_date)s.") % {
|
|
||||||
'member_name': user.pseudo,
|
|
||||||
'end_date': user.end_adhesion()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
# Else, only tell the invoice was created
|
|
||||||
else:
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
_("The invoice has been created.")
|
|
||||||
)
|
|
||||||
return redirect(reverse(
|
|
||||||
'users:profil',
|
|
||||||
kwargs={'userid': userid}
|
|
||||||
))
|
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
_("You need to choose at least one article.")
|
_("You need to choose at least one article.")
|
||||||
|
@ -894,9 +862,9 @@ def recharge(request):
|
||||||
number=1
|
number=1
|
||||||
)
|
)
|
||||||
purchase.save()
|
purchase.save()
|
||||||
content = online_payment.PAYMENT_SYSTEM[
|
# content = online_payment.PAYMENT_SYSTEM[
|
||||||
AssoOption.get_cached_value('payment')
|
# AssoOption.get_cached_value('payment')
|
||||||
](invoice, request)
|
# ](invoice, request)
|
||||||
return render(request, 'cotisations/payment.html', content)
|
return render(request, 'cotisations/payment.html', content)
|
||||||
return form({
|
return form({
|
||||||
'rechargeform': refill_form,
|
'rechargeform': refill_form,
|
||||||
|
|
|
@ -897,7 +897,7 @@ def profil(request, users, **_kwargs):
|
||||||
SortTable.USERS_INDEX_WHITE
|
SortTable.USERS_INDEX_WHITE
|
||||||
)
|
)
|
||||||
user_solde = OptionalUser.get_cached_value('user_solde')
|
user_solde = OptionalUser.get_cached_value('user_solde')
|
||||||
allow_online_payment = AssoOption.get_cached_value('payment') != 'NONE'
|
allow_online_payment = True# TODO : AssoOption.get_cached_value('payment') != 'NONE'
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
'users/profil.html',
|
'users/profil.html',
|
||||||
|
|
Loading…
Reference in a new issue