8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-22 03:13:12 +00:00

Pep8 compliance on cotisations

This commit is contained in:
Maël Kervella 2018-04-13 18:58:29 +00:00
parent e56c80b747
commit b25137acf4
8 changed files with 224 additions and 121 deletions

View file

@ -27,6 +27,7 @@ Here are defined some functions to check acl on the application.
""" """
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
def can_view(user): def can_view(user):
"""Check if an user can view the application. """Check if an user can view the application.
@ -38,4 +39,7 @@ def can_view(user):
viewing is granted and msg is a message (can be None). viewing is granted and msg is a message (can be None).
""" """
can = user.has_module_perms('cotisations') can = user.has_module_perms('cotisations')
return can, None if can else _("You don't have the rights to see this application.") if can:
return can, None
else:
return can, _("You don't have the rights to see this application.")

View file

@ -20,7 +20,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """
Forms for the 'cotisation' app of re2o. It highly depends on Forms for the 'cotisation' app of re2o. It highly depends on
:cotisations:models and is mainly used by :cotisations:views. :cotisations:models and is mainly used by :cotisations:views.
The following forms are mainly used to create, edit or delete The following forms are mainly used to create, edit or delete
@ -38,7 +38,7 @@ from __future__ import unicode_literals
from django import forms from django import forms
from django.db.models import Q from django.db.models import Q
from django.forms import ModelForm, Form from django.forms import ModelForm, Form
from django.core.validators import MinValueValidator,MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
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
@ -47,7 +47,8 @@ from preferences.models import OptionalUser
from users.models import User from users.models import User
from re2o.field_permissions import FieldPermissionFormMixin from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin from re2o.mixins import FormRevMixin
class NewFactureForm(FormRevMixin, ModelForm): class NewFactureForm(FormRevMixin, ModelForm):
""" """
@ -109,12 +110,16 @@ class CreditSoldeForm(NewFactureForm):
montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True) montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True)
class SelectUserArticleForm(FormRevMixin, Form): class SelectUserArticleForm(
FormRevMixin, Form):
""" """
Form used to select an article during the creation of an invoice for a member. Form used to select an article during the creation of an invoice for a
member.
""" """
article = forms.ModelChoiceField( article = forms.ModelChoiceField(
queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Adherent')), queryset=Article.objects.filter(
Q(type_user='All') | Q(type_user='Adherent')
),
label=_l("Article"), label=_l("Article"),
required=True required=True
) )
@ -127,10 +132,13 @@ class SelectUserArticleForm(FormRevMixin, Form):
class SelectClubArticleForm(Form): class SelectClubArticleForm(Form):
""" """
Form used to select an article during the creation of an invoice for a club. Form used to select an article during the creation of an invoice for a
club.
""" """
article = forms.ModelChoiceField( article = forms.ModelChoiceField(
queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Club')), queryset=Article.objects.filter(
Q(type_user='All') | Q(type_user='Club')
),
label=_l("Article"), label=_l("Article"),
required=True required=True
) )
@ -140,6 +148,7 @@ class SelectClubArticleForm(Form):
required=True required=True
) )
# TODO : change Facture to Invoice # TODO : change Facture to Invoice
class NewFactureFormPdf(Form): class NewFactureFormPdf(Form):
""" """
@ -147,9 +156,18 @@ class NewFactureFormPdf(Form):
""" """
paid = forms.BooleanField(label=_l("Paid"), required=False) paid = forms.BooleanField(label=_l("Paid"), required=False)
# TODO : change dest field to recipient # TODO : change dest field to recipient
dest = forms.CharField(required=True, max_length=255, label=_l("Recipient")) dest = forms.CharField(
required=True,
max_length=255,
label=_l("Recipient")
)
# TODO : change chambre field to address # TODO : change chambre field to address
chambre = forms.CharField(required=False, max_length=10, label=_l("Address")) chambre = forms.CharField(
required=False,
max_length=10,
label=_l("Address")
)
# TODO : change Facture to Invoice # TODO : change Facture to Invoice
class EditFactureForm(FieldPermissionFormMixin, NewFactureForm): class EditFactureForm(FieldPermissionFormMixin, NewFactureForm):
@ -313,7 +331,6 @@ class NewFactureSoldeForm(NewFactureForm):
# TODO : change paiement to payment and baque to bank # TODO : change paiement to payment and baque to bank
fields = ['paiement', 'banque'] fields = ['paiement', 'banque']
def clean(self): def clean(self):
cleaned_data = super(NewFactureSoldeForm, self).clean() cleaned_data = super(NewFactureSoldeForm, self).clean()
# TODO : change paiement to payment # TODO : change paiement to payment
@ -342,7 +359,7 @@ class RechargeForm(FormRevMixin, Form):
value = forms.FloatField( value = forms.FloatField(
label=_l("Amount"), label=_l("Amount"),
min_value=0.01, min_value=0.01,
validators = [] validators=[]
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -360,7 +377,8 @@ class RechargeForm(FormRevMixin, Form):
) )
} }
) )
if value + self.user.solde > OptionalUser.get_cached_value('max_solde'): if value + self.user.solde > \
OptionalUser.get_cached_value('max_solde'):
raise forms.ValidationError( raise forms.ValidationError(
_("Requested amount is too high. Your balance can't exceed \ _("Requested amount is too high. Your balance can't exceed \
%(max_online_balance)s .") % { %(max_online_balance)s .") % {

View file

@ -54,7 +54,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
""" """
The model for an invoice. It reprensents the fact that a user paid for The model for an invoice. It reprensents the fact that a user paid for
something (it can be multiple article paid at once). something (it can be multiple article paid at once).
An invoice is linked to : An invoice is linked to :
* one or more purchases (one for each article sold that time) * one or more purchases (one for each article sold that time)
* a user (the one who bought those articles) * a user (the one who bought those articles)
@ -105,11 +105,16 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
abstract = False abstract = False
permissions = ( permissions = (
# TODO : change facture to invoice # TODO : change facture to invoice
('change_facture_control', _l("Can change the \"controlled\" state")), ('change_facture_control',
# TODO : seems more likely to be call create_facture_pdf or create_invoice_pdf _l("Can change the \"controlled\" state")),
('change_facture_pdf', _l("Can create a custom PDF invoice")), # TODO : seems more likely to be call create_facture_pdf
('view_facture', _l("Can see an invoice's details")), # or create_invoice_pdf
('change_all_facture', _l("Can edit all the previous invoices")), ('change_facture_pdf',
_l("Can create a custom PDF invoice")),
('view_facture',
_l("Can see an invoice's details")),
('change_all_facture',
_l("Can edit all the previous invoices")),
) )
verbose_name = _l("Invoice") verbose_name = _l("Invoice")
verbose_name_plural = _l("Invoices") verbose_name_plural = _l("Invoices")
@ -159,11 +164,14 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
def can_edit(self, user_request, *args, **kwargs): def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_facture'): if not user_request.has_perm('cotisations.change_facture'):
return False, _("You don't have the right to edit an invoice.") return False, _("You don't have the right to edit an invoice.")
elif not user_request.has_perm('cotisations.change_all_facture') and not self.user.can_edit(user_request, *args, **kwargs)[0]: elif not user_request.has_perm('cotisations.change_all_facture') and \
return False, _("You don't have the right to edit this user's invoices.") not self.user.can_edit(user_request, *args, **kwargs)[0]:
elif not user_request.has_perm('cotisations.change_all_facture') and\ return False, _("You don't have the right to edit this user's "
(self.control or not self.valid): "invoices.")
return False, _("You don't have the right to edit an invoice already controlled or invalidated.") elif not user_request.has_perm('cotisations.change_all_facture') and \
(self.control or not self.valid):
return False, _("You don't have the right to edit an invoice "
"already controlled or invalidated.")
else: else:
return True, None return True, None
@ -171,16 +179,19 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
if not user_request.has_perm('cotisations.delete_facture'): if not user_request.has_perm('cotisations.delete_facture'):
return False, _("You don't have the right to delete an invoice.") return False, _("You don't have the right to delete an invoice.")
if not self.user.can_edit(user_request, *args, **kwargs)[0]: if not self.user.can_edit(user_request, *args, **kwargs)[0]:
return False, _("You don't have the right to delete this user's invoices.") return False, _("You don't have the right to delete this user's "
"invoices.")
if self.control or not self.valid: if self.control or not self.valid:
return False, _("You don't have the right to delete an invoice already controlled or invalidated.") return False, _("You don't have the right to delete an invoice "
"already controlled or invalidated.")
else: else:
return True, None return True, None
def can_view(self, user_request, *args, **kwargs): def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_facture') and\ if not user_request.has_perm('cotisations.view_facture') and \
self.user != user_request: self.user != user_request:
return False, _("You don't have the right to see someone else's invoices history.") return False, _("You don't have the right to see someone else's "
"invoices history.")
elif not self.valid: elif not self.valid:
return False, _("The invoice has been invalidated.") return False, _("The invoice has been invalidated.")
else: else:
@ -188,16 +199,22 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
@staticmethod @staticmethod
def can_change_control(user_request, *args, **kwargs): def can_change_control(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_facture_control'), _("You don't have the right to edit the \"controlled\" state.") return (
user_request.has_perm('cotisations.change_facture_control'),
_("You don't have the right to edit the \"controlled\" state.")
)
@staticmethod @staticmethod
def can_change_pdf(user_request, *args, **kwargs): def can_change_pdf(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_facture_pdf'), _("You don't have the right to edit an invoice.") return (
user_request.has_perm('cotisations.change_facture_pdf'),
_("You don't have the right to edit an invoice.")
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Facture, self).__init__(*args, **kwargs) super(Facture, self).__init__(*args, **kwargs)
self.field_permissions = { self.field_permissions = {
'control' : self.can_change_control, 'control': self.can_change_control,
} }
def __str__(self): def __str__(self):
@ -228,7 +245,7 @@ class Vente(RevMixin, AclMixin, models.Model):
""" """
The model defining a purchase. It consist of one type of article being The model defining a purchase. It consist of one type of article being
sold. In particular there may be multiple purchases in a single invoice. sold. In particular there may be multiple purchases in a single invoice.
It's reprensentated by: It's reprensentated by:
* an amount (the number of items sold) * an amount (the number of items sold)
* an invoice (whose the purchase is part of) * an invoice (whose the purchase is part of)
@ -289,7 +306,6 @@ class Vente(RevMixin, AclMixin, models.Model):
verbose_name = _l("Purchase") verbose_name = _l("Purchase")
verbose_name_plural = _l("Purchases") verbose_name_plural = _l("Purchases")
# TODO : change prix_total to total_price # TODO : change prix_total to total_price
def prix_total(self): def prix_total(self):
""" """
@ -323,11 +339,13 @@ class Vente(RevMixin, AclMixin, models.Model):
facture__in=Facture.objects.filter( facture__in=Facture.objects.filter(
user=self.facture.user user=self.facture.user
).exclude(valid=False)) ).exclude(valid=False))
).filter(Q(type_cotisation='All') | Q(type_cotisation=self.type_cotisation) ).filter(
Q(type_cotisation='All') |
Q(type_cotisation=self.type_cotisation)
).filter( ).filter(
date_start__lt=date_start date_start__lt=date_start
).aggregate(Max('date_end'))['date_end__max'] ).aggregate(Max('date_end'))['date_end__max']
elif self.type_cotisation=="Adhesion": elif self.type_cotisation == "Adhesion":
end_cotisation = self.facture.user.end_adhesion() end_cotisation = self.facture.user.end_adhesion()
else: else:
end_cotisation = self.facture.user.end_connexion() end_cotisation = self.facture.user.end_connexion()
@ -357,11 +375,15 @@ class Vente(RevMixin, AclMixin, models.Model):
def can_edit(self, user_request, *args, **kwargs): def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_vente'): if not user_request.has_perm('cotisations.change_vente'):
return False, _("You don't have the right to edit the purchases.") return False, _("You don't have the right to edit the purchases.")
elif not user_request.has_perm('cotisations.change_all_facture') and not self.facture.user.can_edit(user_request, *args, **kwargs)[0]: elif not user_request.has_perm('cotisations.change_all_facture') and \
return False, _("You don't have the right to edit this user's purchases.") not self.facture.user.can_edit(
elif not user_request.has_perm('cotisations.change_all_vente') and\ user_request, *args, **kwargs)[0]:
(self.facture.control or not self.facture.valid): return False, _("You don't have the right to edit this user's "
return False, _("You don't have the right to edit a purchase already controlled or invalidated.") "purchases.")
elif not user_request.has_perm('cotisations.change_all_vente') and \
(self.facture.control or not self.facture.valid):
return False, _("You don't have the right to edit a purchase "
"already controlled or invalidated.")
else: else:
return True, None return True, None
@ -369,16 +391,19 @@ class Vente(RevMixin, AclMixin, models.Model):
if not user_request.has_perm('cotisations.delete_vente'): if not user_request.has_perm('cotisations.delete_vente'):
return False, _("You don't have the right to delete a purchase.") return False, _("You don't have the right to delete a purchase.")
if not self.facture.user.can_edit(user_request, *args, **kwargs)[0]: if not self.facture.user.can_edit(user_request, *args, **kwargs)[0]:
return False, _("You don't have the right to delete this user's purchases.") return False, _("You don't have the right to delete this user's "
"purchases.")
if self.facture.control or not self.facture.valid: if self.facture.control or not self.facture.valid:
return False, _("You don't have the right to delete a purchase already controlled or invalidated.") return False, _("You don't have the right to delete a purchase "
"already controlled or invalidated.")
else: else:
return True, None return True, None
def can_view(self, user_request, *args, **kwargs): def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_vente') and\ if not user_request.has_perm('cotisations.view_vente') and \
self.facture.user != user_request: self.facture.user != user_request:
return False, _("You don't have the right to see someone else's purchase history.") return False, _("You don't have the right to see someone "
"else's purchase history.")
else: else:
return True, None return True, None
@ -418,12 +443,14 @@ def vente_post_delete(sender, **kwargs):
class Article(RevMixin, AclMixin, models.Model): class Article(RevMixin, AclMixin, models.Model):
""" """
The definition of an article model. It represents an type of object that can be sold to the user. The definition of an article model. It represents a type of object
that can be sold to the user.
It's represented by: It's represented by:
* a name * a name
* a price * a price
* a cotisation type (indicating if this article reprensents a cotisation or not) * a cotisation type (indicating if this article reprensents a
cotisation or not)
* a duration (if it is a cotisation) * a duration (if it is a cotisation)
* a type of user (indicating what kind of user can buy this article) * a type of user (indicating what kind of user can buy this article)
""" """
@ -513,8 +540,8 @@ class Banque(RevMixin, AclMixin, models.Model):
permissions = ( permissions = (
('view_banque', _l("Can see a bank's details")), ('view_banque', _l("Can see a bank's details")),
) )
verbose_name=_l("Bank") verbose_name = _l("Bank")
verbose_name_plural=_l("Banks") verbose_name_plural = _l("Banks")
def __str__(self): def __str__(self):
return self.name return self.name
@ -530,7 +557,7 @@ class Paiement(RevMixin, AclMixin, models.Model):
* a type (used for the type 'cheque' which implies the use of a bank * a type (used for the type 'cheque' which implies the use of a bank
and an account number in related models) and an account number in related models)
""" """
PAYMENT_TYPES = ( PAYMENT_TYPES = (
(0, _l("Standard")), (0, _l("Standard")),
(1, _l("Cheque")), (1, _l("Cheque")),
@ -622,24 +649,29 @@ class Cotisation(RevMixin, AclMixin, models.Model):
def can_edit(self, user_request, *args, **kwargs): def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_cotisation'): if not user_request.has_perm('cotisations.change_cotisation'):
return False, _("You don't have the right to edit a cotisation.") return False, _("You don't have the right to edit a cotisation.")
elif not user_request.has_perm('cotisations.change_all_cotisation') and\ elif not user_request.has_perm('cotisations.change_all_cotisation') \
(self.vente.facture.control or not self.vente.facture.valid): and (self.vente.facture.control or
return False, _("You don't have the right to edit a cotisation already controlled or invalidated.") not self.vente.facture.valid):
return False, _("You don't have the right to edit a cotisation "
"already controlled or invalidated.")
else: else:
return True, None return True, None
def can_delete(self, user_request, *args, **kwargs): def can_delete(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.delete_cotisation'): if not user_request.has_perm('cotisations.delete_cotisation'):
return False, _("You don't have the right to delete a cotisation.") return False, _("You don't have the right to delete a "
"cotisation.")
if self.vente.facture.control or not self.vente.facture.valid: if self.vente.facture.control or not self.vente.facture.valid:
return False, _("You don't have the right to delete a cotisation already controlled or invalidated.") return False, _("You don't have the right to delete a cotisation "
"already controlled or invalidated.")
else: else:
return True, None return True, None
def can_view(self, user_request, *args, **kwargs): def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_cotisation') and\ if not user_request.has_perm('cotisations.view_cotisation') and\
self.vente.facture.user != user_request: self.vente.facture.user != user_request:
return False, _("You don't have the right to see someone else's cotisation history.") return False, _("You don't have the right to see someone else's "
"cotisation history.")
else: else:
return True, None return True, None

View file

@ -17,6 +17,7 @@ from preferences.models import AssoOption
from .models import Facture from .models import Facture
from .payment_utils.comnpay import Payment as ComnpayPayment from .payment_utils.comnpay import Payment as ComnpayPayment
@csrf_exempt @csrf_exempt
@login_required @login_required
def accept_payment(request, factureid): def accept_payment(request, factureid):
@ -30,7 +31,10 @@ def accept_payment(request, factureid):
'amount': facture.prix() 'amount': facture.prix()
} }
) )
return redirect(reverse('users:profil', kwargs={'userid':request.user.id})) return redirect(reverse(
'users:profil',
kwargs={'userid': request.user.id}
))
@csrf_exempt @csrf_exempt
@ -43,7 +47,11 @@ def refuse_payment(request):
request, request,
_("The payment has been refused.") _("The payment has been refused.")
) )
return redirect(reverse('users:profil', kwargs={'userid':request.user.id})) return redirect(reverse(
'users:profil',
kwargs={'userid': request.user.id}
))
@csrf_exempt @csrf_exempt
def ipn(request): def ipn(request):
@ -105,7 +113,7 @@ def comnpay(facture, request):
str(AssoOption.get_cached_value('payment_pass')), str(AssoOption.get_cached_value('payment_pass')),
'https://' + host + reverse( 'https://' + host + reverse(
'cotisations:accept_payment', 'cotisations:accept_payment',
kwargs={'factureid':facture.id} kwargs={'factureid': facture.id}
), ),
'https://' + host + reverse('cotisations:refuse_payment'), 'https://' + host + reverse('cotisations:refuse_payment'),
'https://' + host + reverse('cotisations:ipn'), 'https://' + host + reverse('cotisations:ipn'),
@ -113,20 +121,20 @@ def comnpay(facture, request):
"D" "D"
) )
r = { r = {
'action' : 'https://secure.homologation.comnpay.com', 'action': 'https://secure.homologation.comnpay.com',
'method' : 'POST', 'method': 'POST',
'content' : p.buildSecretHTML( 'content': p.buildSecretHTML(
"Rechargement du solde", "Rechargement du solde",
facture.prix(), facture.prix(),
idTransaction=str(facture.id) idTransaction=str(facture.id)
), ),
'amount' : facture.prix, 'amount': facture.prix,
} }
return r return r
# The payment systems supported by re2o # The payment systems supported by re2o
PAYMENT_SYSTEM = { PAYMENT_SYSTEM = {
'COMNPAY' : comnpay, 'COMNPAY': comnpay,
'NONE' : None 'NONE': None
} }

View file

@ -5,6 +5,7 @@ import hashlib
from collections import OrderedDict from collections import OrderedDict
from itertools import chain from itertools import chain
class Payment(): class Payment():
vad_number = "" vad_number = ""
@ -15,7 +16,8 @@ class Payment():
source = "" source = ""
typeTr = "D" typeTr = "D"
def __init__(self, vad_number = "", secret_key = "", urlRetourOK = "", urlRetourNOK = "", urlIPN = "", source="", typeTr="D"): def __init__(self, vad_number="", secret_key="", urlRetourOK="",
urlRetourNOK="", urlIPN="", source="", typeTr="D"):
self.vad_number = vad_number self.vad_number = vad_number
self.secret_key = secret_key self.secret_key = secret_key
self.urlRetourOK = urlRetourOK self.urlRetourOK = urlRetourOK
@ -24,36 +26,45 @@ class Payment():
self.source = source self.source = source
self.typeTr = typeTr self.typeTr = typeTr
def buildSecretHTML(self, produit="Produit", montant="0.00", idTransaction=""): def buildSecretHTML(self, produit="Produit", montant="0.00",
idTransaction=""):
if idTransaction == "": if idTransaction == "":
self.idTransaction = str(time.time())+self.vad_number+str(randrange(999)) self.idTransaction = str(time.time())
self.idTransaction += self.vad_number
self.idTransaction += str(randrange(999))
else: else:
self.idTransaction = idTransaction self.idTransaction = idTransaction
array_tpe = OrderedDict( array_tpe = OrderedDict(
montant= str(montant), montant=str(montant),
idTPE= self.vad_number, idTPE=self.vad_number,
idTransaction= self.idTransaction, idTransaction=self.idTransaction,
devise= "EUR", devise="EUR",
lang= 'fr', lang='fr',
nom_produit= produit, nom_produit=produit,
source= self.source, source=self.source,
urlRetourOK= self.urlRetourOK, urlRetourOK=self.urlRetourOK,
urlRetourNOK= self.urlRetourNOK, urlRetourNOK=self.urlRetourNOK,
typeTr= str(self.typeTr) typeTr=str(self.typeTr)
) )
if self.urlIPN!="": if self.urlIPN != "":
array_tpe['urlIPN'] = self.urlIPN array_tpe['urlIPN'] = self.urlIPN
array_tpe['key'] = self.secret_key; array_tpe['key'] = self.secret_key
strWithKey = base64.b64encode(bytes('|'.join(array_tpe.values()), 'utf-8')) strWithKey = base64.b64encode(bytes(
'|'.join(array_tpe.values()),
'utf-8'
))
del array_tpe["key"] del array_tpe["key"]
array_tpe['sec'] = hashlib.sha512(strWithKey).hexdigest() array_tpe['sec'] = hashlib.sha512(strWithKey).hexdigest()
ret = "" ret = ""
for key in array_tpe: for key in array_tpe:
ret += '<input type="hidden" name="'+key+'" value="'+array_tpe[key]+'"/>' ret += '<input type="hidden" name="{k}" value="{v}"/>'.format(
'k'=key,
'v'=array_type[key]
)
return ret return ret
@ -61,8 +72,10 @@ class Payment():
if "sec" in values: if "sec" in values:
sec = values['sec'] sec = values['sec']
del values["sec"] del values["sec"]
strWithKey = hashlib.sha512(base64.b64encode(bytes('|'.join(values.values()) +"|"+secret_key, 'utf-8'))).hexdigest() strWithKey = hashlib.sha512(base64.b64encode(bytes(
'|'.join(values.values()) + "|" + secret_key,
'utf-8'
))).hexdigest()
return strWithKey.upper() == sec.upper() return strWithKey.upper() == sec.upper()
else: else:
return False return False

View file

@ -46,7 +46,7 @@ def render_invoice(request, ctx={}):
date, the user, the articles, the prices, ... date, the user, the articles, the prices, ...
""" """
filename = '_'.join([ filename = '_'.join([
'invoice', 'invoice',
slugify(ctx['asso_name']), slugify(ctx['asso_name']),
slugify(ctx['recipient_name']), slugify(ctx['recipient_name']),
str(ctx['DATE'].year), str(ctx['DATE'].year),
@ -54,9 +54,12 @@ def render_invoice(request, ctx={}):
str(ctx['DATE'].day), str(ctx['DATE'].day),
]) ])
r = render_tex(request, 'cotisations/factures.tex', ctx) r = render_tex(request, 'cotisations/factures.tex', ctx)
r['Content-Disposition'] = ''.join(['attachment; filename="',filename,'.pdf"']) r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format(
name=filename
)
return r return r
def render_tex(request, template, ctx={}): def render_tex(request, template, ctx={}):
""" """
Creates a PDF from a LaTex templates using pdflatex. Creates a PDF from a LaTex templates using pdflatex.
@ -66,13 +69,13 @@ def render_tex(request, template, ctx={}):
context = Context(ctx) context = Context(ctx)
template = get_template(template) template = get_template(template)
rendered_tpl = template.render(context).encode('utf-8') rendered_tpl = template.render(context).encode('utf-8')
with tempfile.TemporaryDirectory() as tempdir: with tempfile.TemporaryDirectory() as tempdir:
for i in range(2): for i in range(2):
process = Popen( process = Popen(
['pdflatex', '-output-directory', tempdir], ['pdflatex', '-output-directory', tempdir],
stdin = PIPE, stdin=PIPE,
stdout = PIPE, stdout=PIPE,
) )
process.communicate(rendered_tpl) process.communicate(rendered_tpl)
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f: with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f:

View file

@ -101,12 +101,11 @@ urlpatterns = [
views.index_paiement, views.index_paiement,
name='index-paiement' name='index-paiement'
), ),
url( url(r'history/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$',
r'history/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$',
re2o.views.history, re2o.views.history,
name='history', name='history',
kwargs={'application':'cotisations'}, kwargs={'application': 'cotisations'},
), ),
url(r'^control/$', url(r'^control/$',
views.control, views.control,
name='control' name='control'
@ -122,14 +121,14 @@ urlpatterns = [
url(r'^payment/accept/(?P<factureid>[0-9]+)$', url(r'^payment/accept/(?P<factureid>[0-9]+)$',
payment.accept_payment, payment.accept_payment,
name='accept_payment' name='accept_payment'
), ),
url(r'^payment/refuse/$', url(r'^payment/refuse/$',
payment.refuse_payment, payment.refuse_payment,
name='refuse_payment' name='refuse_payment'
), ),
url(r'^payment/ipn/$', url(r'^payment/ipn/$',
payment.ipn, payment.ipn,
name='ipn' name='ipn'
), ),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
] ]

View file

@ -77,7 +77,6 @@ from . import payment as online_payment
from .tex import render_invoice from .tex import render_invoice
@login_required @login_required
@can_create(Facture) @can_create(Facture)
@can_edit(User) @can_edit(User)
@ -102,9 +101,13 @@ def new_facture(request, user, userid):
# Building the invocie form and the article formset # Building the invocie form and the article formset
invoice_form = NewFactureForm(request.POST or None, instance=invoice) invoice_form = NewFactureForm(request.POST or None, instance=invoice)
if request.user.is_class_club: if request.user.is_class_club:
article_formset = formset_factory(SelectClubArticleForm)(request.POST or None) article_formset = formset_factory(SelectClubArticleForm)(
request.POST or None
)
else: else:
article_formset = formset_factory(SelectUserArticleForm)(request.POST or None) article_formset = formset_factory(SelectUserArticleForm)(
request.POST or None
)
if invoice_form.is_valid() and article_formset.is_valid(): if invoice_form.is_valid() and article_formset.is_valid():
new_invoice_instance = invoice_form.save(commit=False) new_invoice_instance = invoice_form.save(commit=False)
@ -118,15 +121,18 @@ def new_facture(request, user, userid):
# the authorized minimum (negative_balance) # the authorized minimum (negative_balance)
if user_balance: if user_balance:
# TODO : change Paiement to Payment # TODO : change Paiement to Payment
if new_invoice_instance.paiement == Paiement.objects.get_or_create( if new_invoice_instance.paiement == (
moyen='solde' Paiement.objects.get_or_create(moyen='solde')[0]
)[0]: ):
total_price = 0 total_price = 0
for art_item in articles: for art_item in articles:
if art_item.cleaned_data: if art_item.cleaned_data:
total_price += art_item.cleaned_data['article']\ total_price += (
.prix*art_item.cleaned_data['quantity'] art_item.cleaned_data['article'].prix *
if float(user.solde) - float(total_price) < negative_balance: art_item.cleaned_data['quantity']
)
if (float(user.solde) - float(total_price)
< negative_balance):
messages.error( messages.error(
request, request,
_("Your balance is too low for this operation.") _("Your balance is too low for this operation.")
@ -194,7 +200,7 @@ def new_facture(request, user, userid):
@can_change(Facture, 'pdf') @can_change(Facture, 'pdf')
def new_facture_pdf(request): def new_facture_pdf(request):
""" """
View used to generate a custom PDF invoice. It's mainly used to View used to generate a custom PDF invoice. It's mainly used to
get invoices that are not taken into account, for the administrative get invoices that are not taken into account, for the administrative
point of view. point of view.
""" """
@ -205,9 +211,13 @@ def new_facture_pdf(request):
# Building the invocie form and the article formset # Building the invocie form and the article formset
invoice_form = NewFactureFormPdf(request.POST or None) invoice_form = NewFactureFormPdf(request.POST or None)
if request.user.is_class_club: if request.user.is_class_club:
articles_formset = formset_factory(SelectClubArticleForm)(request.POST or None) articles_formset = formset_factory(SelectClubArticleForm)(
request.POST or None
)
else: else:
articles_formset = formset_factory(SelectUserArticleForm)(request.POST or None) articles_formset = formset_factory(SelectUserArticleForm)(
request.POST or None
)
if invoice_form.is_valid() and articles_formset.is_valid(): if invoice_form.is_valid() and articles_formset.is_valid():
# Get the article list and build an list out of it # Get the article list and build an list out of it
# contiaining (article_name, article_price, quantity, total_price) # contiaining (article_name, article_price, quantity, total_price)
@ -303,7 +313,11 @@ def edit_facture(request, facture, factureid):
can be set as desired. This is also the view used to invalidate can be set as desired. This is also the view used to invalidate
an invoice. an invoice.
""" """
invoice_form = EditFactureForm(request.POST or None, instance=facture, user=request.user) invoice_form = EditFactureForm(
request.POST or None,
instance=facture,
user=request.user
)
purchases_objects = Vente.objects.filter(facture=facture) purchases_objects = Vente.objects.filter(facture=facture)
purchase_form_set = modelformset_factory( purchase_form_set = modelformset_factory(
Vente, Vente,
@ -311,7 +325,10 @@ def edit_facture(request, facture, factureid):
extra=0, extra=0,
max_num=len(purchases_objects) max_num=len(purchases_objects)
) )
purchase_form = purchase_form_set(request.POST or None, queryset=purchases_objects) purchase_form = purchase_form_set(
request.POST or None,
queryset=purchases_objects
)
if invoice_form.is_valid() and purchase_form.is_valid(): if invoice_form.is_valid() and purchase_form.is_valid():
if invoice_form.changed_data: if invoice_form.changed_data:
invoice_form.save() invoice_form.save()
@ -385,7 +402,7 @@ def credit_solde(request, user, userid):
def add_article(request): def add_article(request):
""" """
View used to add an article. View used to add an article.
.. note:: If a purchase has already been sold, the price are calculated .. note:: If a purchase has already been sold, the price are calculated
once and for all. That means even if the price of an article is edited once and for all. That means even if the price of an article is edited
later, it won't change the invoice. That is really important to keep later, it won't change the invoice. That is really important to keep
@ -613,7 +630,8 @@ def control(request):
View used to control the invoices all at once. View used to control the invoices all at once.
""" """
pagination_number = GeneralOption.get_cached_value('pagination_number') pagination_number = GeneralOption.get_cached_value('pagination_number')
invoice_list = Facture.objects.select_related('user').select_related('paiement') invoice_list = (Facture.objects.select_related('user').
select_related('paiement'))
invoice_list = SortTable.sort( invoice_list = SortTable.sort(
invoice_list, invoice_list,
request.GET.get('col'), request.GET.get('col'),
@ -725,9 +743,13 @@ def new_facture_solde(request, userid):
Q(type_user='All') | Q(type_user=request.user.class_name) Q(type_user='All') | Q(type_user=request.user.class_name)
) )
if request.user.is_class_club: if request.user.is_class_club:
article_formset = formset_factory(SelectClubArticleForm)(request.POST or None) article_formset = formset_factory(SelectClubArticleForm)(
request.POST or None
)
else: else:
article_formset = formset_factory(SelectUserArticleForm)(request.POST or None) article_formset = formset_factory(SelectUserArticleForm)(
request.POST or None
)
if article_formset.is_valid(): if article_formset.is_valid():
articles = article_formset articles = article_formset
@ -826,7 +848,9 @@ def recharge(request):
refill_form = RechargeForm(request.POST or None, user=request.user) refill_form = RechargeForm(request.POST or None, user=request.user)
if refill_form.is_valid(): if refill_form.is_valid():
invoice = Facture(user=request.user) invoice = Facture(user=request.user)
payment, _created = Paiement.objects.get_or_create(moyen='Rechargement en ligne') payment, _created = Paiement.objects.get_or_create(
moyen='Rechargement en ligne'
)
invoice.paiement = payment invoice.paiement = payment
invoice.valid = False invoice.valid = False
invoice.save() invoice.save()
@ -837,7 +861,9 @@ def recharge(request):
number=1 number=1
) )
purchase.save() purchase.save()
content = online_payment.PAYMENT_SYSTEM[AssoOption.get_cached_value('payment')](invoice, request) content = online_payment.PAYMENT_SYSTEM[
AssoOption.get_cached_value('payment')
](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