mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-26 06:32:26 +00:00
Translation: Marking of strings in cotisations app
This commit is contained in:
parent
99928c885b
commit
a7d47b972d
5 changed files with 481 additions and 190 deletions
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
Here are defined some functions to check acl on the application.
|
Here are defined some functions to check acl on the application.
|
||||||
"""
|
"""
|
||||||
|
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.
|
||||||
|
@ -37,4 +38,4 @@ 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 "Vous ne pouvez pas voir cette application."
|
return can, None if can else _("You don't have the rights to see this application.")
|
||||||
|
|
|
@ -40,6 +40,8 @@ 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 .models import Article, Paiement, Facture, Banque
|
from .models import Article, Paiement, Facture, Banque
|
||||||
from preferences.models import OptionalUser
|
from preferences.models import OptionalUser
|
||||||
from users.models import User
|
from users.models import User
|
||||||
|
@ -50,15 +52,18 @@ from re2o.mixins import FormRevMixin
|
||||||
class NewFactureForm(FormRevMixin, ModelForm):
|
class NewFactureForm(FormRevMixin, ModelForm):
|
||||||
"""Creation d'une facture, moyen de paiement, banque et numero
|
"""Creation d'une facture, moyen de paiement, banque et numero
|
||||||
de cheque"""
|
de cheque"""
|
||||||
|
# TODO : translate doc string in English
|
||||||
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(NewFactureForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(NewFactureForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
# TODO : remove the use of cheque and banque and paiement
|
||||||
|
# for something more generic or at least in English
|
||||||
self.fields['cheque'].required = False
|
self.fields['cheque'].required = False
|
||||||
self.fields['banque'].required = False
|
self.fields['banque'].required = False
|
||||||
self.fields['cheque'].label = 'Numero de chèque'
|
self.fields['cheque'].label = _("Cheque number")
|
||||||
self.fields['banque'].empty_label = "Non renseigné"
|
self.fields['banque'].empty_label = _("Not specified")
|
||||||
self.fields['paiement'].empty_label = "Séléctionner\
|
self.fields['paiement'].empty_label = \
|
||||||
un moyen de paiement"
|
_("Select a payment method")
|
||||||
paiement_list = Paiement.objects.filter(type_paiement=1)
|
paiement_list = Paiement.objects.filter(type_paiement=1)
|
||||||
if paiement_list:
|
if paiement_list:
|
||||||
self.fields['paiement'].widget\
|
self.fields['paiement'].widget\
|
||||||
|
@ -70,41 +75,47 @@ class NewFactureForm(FormRevMixin, ModelForm):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(NewFactureForm, self).clean()
|
cleaned_data = super(NewFactureForm, self).clean()
|
||||||
paiement = cleaned_data.get("paiement")
|
paiement = cleaned_data.get('paiement')
|
||||||
cheque = cleaned_data.get("cheque")
|
cheque = cleaned_data.get('cheque')
|
||||||
banque = cleaned_data.get("banque")
|
banque = cleaned_data.get('banque')
|
||||||
if not paiement:
|
if not paiement:
|
||||||
raise forms.ValidationError("Le moyen de paiement est obligatoire")
|
raise forms.ValidationError(
|
||||||
elif paiement.type_paiement == "check" and not (cheque and banque):
|
_("A payment method must be specified")
|
||||||
raise forms.ValidationError("Le numéro de chèque et\
|
)
|
||||||
la banque sont obligatoires.")
|
elif paiement.type_paiement == 'check' and not (cheque and banque):
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_("A cheque number and a bank must be specified")
|
||||||
|
)
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class CreditSoldeForm(NewFactureForm):
|
class CreditSoldeForm(NewFactureForm):
|
||||||
"""Permet de faire des opérations sur le solde si il est activé"""
|
"""Permet de faire des opérations sur le solde si il est activé"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
class Meta(NewFactureForm.Meta):
|
class Meta(NewFactureForm.Meta):
|
||||||
model = Facture
|
model = Facture
|
||||||
fields = ['paiement', 'banque', 'cheque']
|
fields = ['paiement', 'banque', 'cheque']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(CreditSoldeForm, self).__init__(*args, **kwargs)
|
super(CreditSoldeForm, self).__init__(*args, **kwargs)
|
||||||
|
# TODO : change solde to balance
|
||||||
self.fields['paiement'].queryset = Paiement.objects.exclude(
|
self.fields['paiement'].queryset = Paiement.objects.exclude(
|
||||||
moyen='solde'
|
moyen='solde'
|
||||||
).exclude(moyen="Solde")
|
).exclude(moyen='Solde')
|
||||||
|
|
||||||
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):
|
||||||
"""Selection d'un article lors de la creation d'une facture"""
|
"""Selection d'un article lors de la creation d'une facture"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
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="Article",
|
label=_("Article"),
|
||||||
required=True
|
required=True
|
||||||
)
|
)
|
||||||
quantity = forms.IntegerField(
|
quantity = forms.IntegerField(
|
||||||
label="Quantité",
|
label=_("Quantity"),
|
||||||
validators=[MinValueValidator(1)],
|
validators=[MinValueValidator(1)],
|
||||||
required=True
|
required=True
|
||||||
)
|
)
|
||||||
|
@ -112,54 +123,63 @@ class SelectUserArticleForm(FormRevMixin, Form):
|
||||||
|
|
||||||
class SelectClubArticleForm(Form):
|
class SelectClubArticleForm(Form):
|
||||||
"""Selection d'un article lors de la creation d'une facture"""
|
"""Selection d'un article lors de la creation d'une facture"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
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="Article",
|
label=_("Article"),
|
||||||
required=True
|
required=True
|
||||||
)
|
)
|
||||||
quantity = forms.IntegerField(
|
quantity = forms.IntegerField(
|
||||||
label="Quantité",
|
label=_("Quantity"),
|
||||||
validators=[MinValueValidator(1)],
|
validators=[MinValueValidator(1)],
|
||||||
required=True
|
required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO : change Facture to Invoice
|
||||||
class NewFactureFormPdf(Form):
|
class NewFactureFormPdf(Form):
|
||||||
"""Creation d'un pdf facture par le trésorier"""
|
"""Creation d'un pdf facture par le trésorier"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
article = forms.ModelMultipleChoiceField(
|
article = forms.ModelMultipleChoiceField(
|
||||||
queryset=Article.objects.all(),
|
queryset=Article.objects.all(),
|
||||||
label="Article"
|
label=_("Article")
|
||||||
)
|
)
|
||||||
number = forms.IntegerField(
|
number = forms.IntegerField(
|
||||||
label="Quantité",
|
label=_("Quantity"),
|
||||||
validators=[MinValueValidator(1)]
|
validators=[MinValueValidator(1)]
|
||||||
)
|
)
|
||||||
paid = forms.BooleanField(label="Payé", required=False)
|
paid = forms.BooleanField(label=_("Paid"), required=False)
|
||||||
dest = forms.CharField(required=True, max_length=255, label="Destinataire")
|
# TODO : change dest field to recipient
|
||||||
chambre = forms.CharField(required=False, max_length=10, label="Adresse")
|
dest = forms.CharField(required=True, max_length=255, label=_("Recipient"))
|
||||||
|
# TODO : change chambre field to address
|
||||||
|
chambre = forms.CharField(required=False, max_length=10, label=_("Address"))
|
||||||
|
# TODO : change fid field to invoice_id
|
||||||
fid = forms.CharField(
|
fid = forms.CharField(
|
||||||
required=True,
|
required=True,
|
||||||
max_length=10,
|
max_length=10,
|
||||||
label="Numéro de la facture"
|
label=_("Invoice number")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO : change Facture to Invoice
|
||||||
class EditFactureForm(FieldPermissionFormMixin, NewFactureForm):
|
class EditFactureForm(FieldPermissionFormMixin, NewFactureForm):
|
||||||
"""Edition d'une facture : moyen de paiement, banque, user parent"""
|
"""Edition d'une facture : moyen de paiement, banque, user parent"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
class Meta(NewFactureForm.Meta):
|
class Meta(NewFactureForm.Meta):
|
||||||
|
# TODO : change Facture to Invoice
|
||||||
model = Facture
|
model = Facture
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
# TODO : change Facture to Invoice
|
||||||
super(EditFactureForm, self).__init__(*args, **kwargs)
|
super(EditFactureForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['user'].label = 'Adherent'
|
self.fields['user'].label = _("Member")
|
||||||
self.fields['user'].empty_label = "Séléctionner\
|
self.fields['user'].empty_label = \
|
||||||
l'adhérent propriétaire"
|
_("Select the proprietary member")
|
||||||
self.fields['valid'].label = 'Validité de la facture'
|
self.fields['valid'].label = _("Validated invoice")
|
||||||
|
|
||||||
|
|
||||||
class ArticleForm(FormRevMixin, ModelForm):
|
class ArticleForm(FormRevMixin, ModelForm):
|
||||||
"""Creation d'un article. Champs : nom, cotisation, durée"""
|
"""Creation d'un article. Champs : nom, cotisation, durée"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Article
|
model = Article
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -167,15 +187,16 @@ class ArticleForm(FormRevMixin, ModelForm):
|
||||||
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(ArticleForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(ArticleForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['name'].label = "Désignation de l'article"
|
self.fields['name'].label = _("Article name")
|
||||||
|
|
||||||
|
|
||||||
class DelArticleForm(FormRevMixin, Form):
|
class DelArticleForm(FormRevMixin, Form):
|
||||||
"""Suppression d'un ou plusieurs articles en vente. Choix
|
"""Suppression d'un ou plusieurs articles en vente. Choix
|
||||||
parmis les modèles"""
|
parmis les modèles"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
articles = forms.ModelMultipleChoiceField(
|
articles = forms.ModelMultipleChoiceField(
|
||||||
queryset=Article.objects.none(),
|
queryset=Article.objects.none(),
|
||||||
label="Articles actuels",
|
label=_("Existing articles"),
|
||||||
widget=forms.CheckboxSelectMultiple
|
widget=forms.CheckboxSelectMultiple
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -188,26 +209,36 @@ class DelArticleForm(FormRevMixin, Form):
|
||||||
self.fields['articles'].queryset = Article.objects.all()
|
self.fields['articles'].queryset = Article.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change Paiement to Payment
|
||||||
class PaiementForm(FormRevMixin, ModelForm):
|
class PaiementForm(FormRevMixin, ModelForm):
|
||||||
"""Creation d'un moyen de paiement, champ text moyen et type
|
"""Creation d'un moyen de paiement, champ text moyen et type
|
||||||
permettant d'indiquer si il s'agit d'un chèque ou non pour le form"""
|
permettant d'indiquer si il s'agit d'un chèque ou non pour le form"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Paiement
|
model = Paiement
|
||||||
|
# TODO : change moyen to method and type_paiement to payment_type
|
||||||
fields = ['moyen', 'type_paiement']
|
fields = ['moyen', 'type_paiement']
|
||||||
|
|
||||||
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 = 'Moyen de paiement à ajouter'
|
self.fields['moyen'].label = _("Payment method name")
|
||||||
self.fields['type_paiement'].label = 'Type de paiement à ajouter'
|
self.fields['type_paiement'].label = _("Payment type")
|
||||||
|
self.fields['type_paiement'].help_text = \
|
||||||
|
_("The payement type is use 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
|
||||||
class DelPaiementForm(FormRevMixin, Form):
|
class DelPaiementForm(FormRevMixin, Form):
|
||||||
"""Suppression d'un ou plusieurs moyens de paiements, selection
|
"""Suppression d'un ou plusieurs moyens de paiements, selection
|
||||||
parmis les models"""
|
parmis les models"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change paiement to payment
|
||||||
paiements = forms.ModelMultipleChoiceField(
|
paiements = forms.ModelMultipleChoiceField(
|
||||||
queryset=Paiement.objects.none(),
|
queryset=Paiement.objects.none(),
|
||||||
label="Moyens de paiement actuels",
|
label=_("Existing payment method"),
|
||||||
widget=forms.CheckboxSelectMultiple
|
widget=forms.CheckboxSelectMultiple
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -220,23 +251,29 @@ class DelPaiementForm(FormRevMixin, Form):
|
||||||
self.fields['paiements'].queryset = Paiement.objects.all()
|
self.fields['paiements'].queryset = Paiement.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change banque to bank
|
||||||
class BanqueForm(FormRevMixin, ModelForm):
|
class BanqueForm(FormRevMixin, ModelForm):
|
||||||
"""Creation d'une banque, field name"""
|
"""Creation d'une banque, field name"""
|
||||||
|
# TODO : translate docstring to Englishh
|
||||||
class Meta:
|
class Meta:
|
||||||
|
# TODO : change banque to bank
|
||||||
model = Banque
|
model = Banque
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
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(BanqueForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(BanqueForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['name'].label = 'Banque à ajouter'
|
self.fields['name'].label = _("Bank name")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change banque to bank
|
||||||
class DelBanqueForm(FormRevMixin, Form):
|
class DelBanqueForm(FormRevMixin, Form):
|
||||||
"""Selection d'une ou plusieurs banques, pour suppression"""
|
"""Selection d'une ou plusieurs banques, pour suppression"""
|
||||||
|
# TODO : translate docstrign to English
|
||||||
|
# TODO : change banque to bank
|
||||||
banques = forms.ModelMultipleChoiceField(
|
banques = forms.ModelMultipleChoiceField(
|
||||||
queryset=Banque.objects.none(),
|
queryset=Banque.objects.none(),
|
||||||
label="Banques actuelles",
|
label=_("Existing banks"),
|
||||||
widget=forms.CheckboxSelectMultiple
|
widget=forms.CheckboxSelectMultiple
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -249,43 +286,56 @@ class DelBanqueForm(FormRevMixin, Form):
|
||||||
self.fields['banques'].queryset = Banque.objects.all()
|
self.fields['banques'].queryset = Banque.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to Invoice
|
||||||
class NewFactureSoldeForm(NewFactureForm):
|
class NewFactureSoldeForm(NewFactureForm):
|
||||||
"""Creation d'une facture, moyen de paiement, banque et numero
|
"""Creation d'une facture, moyen de paiement, banque et numero
|
||||||
de cheque"""
|
de cheque"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
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__)
|
||||||
self.fields['cheque'].required = False
|
self.fields['cheque'].required = False
|
||||||
self.fields['banque'].required = False
|
self.fields['banque'].required = False
|
||||||
self.fields['cheque'].label = 'Numero de chèque'
|
self.fields['cheque'].label = _('Cheque number')
|
||||||
self.fields['banque'].empty_label = "Non renseigné"
|
self.fields['banque'].empty_label = _("Not specified")
|
||||||
self.fields['paiement'].empty_label = "Séléctionner\
|
self.fields['paiement'].empty_label = \
|
||||||
une bite de paiement"
|
_("Select a payment method")
|
||||||
|
# TODO : change paiement to payment
|
||||||
paiement_list = Paiement.objects.filter(type_paiement=1)
|
paiement_list = Paiement.objects.filter(type_paiement=1)
|
||||||
if paiement_list:
|
if paiement_list:
|
||||||
self.fields['paiement'].widget\
|
self.fields['paiement'].widget\
|
||||||
.attrs['data-cheque'] = paiement_list.first().id
|
.attrs['data-cheque'] = paiement_list.first().id
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
# TODO : change facture to invoice
|
||||||
model = Facture
|
model = Facture
|
||||||
|
# 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
|
||||||
paiement = cleaned_data.get("paiement")
|
paiement = cleaned_data.get("paiement")
|
||||||
cheque = cleaned_data.get("cheque")
|
cheque = cleaned_data.get("cheque")
|
||||||
|
# TODO : change banque to bank
|
||||||
banque = cleaned_data.get("banque")
|
banque = cleaned_data.get("banque")
|
||||||
|
# TODO : change paiement to payment
|
||||||
if not paiement:
|
if not paiement:
|
||||||
raise forms.ValidationError("Le moyen de paiement est obligatoire")
|
raise forms.ValidationError(
|
||||||
|
_("A payment method must be specified.")
|
||||||
|
)
|
||||||
|
# TODO : change paiement and banque to payment and bank
|
||||||
elif paiement.type_paiement == "check" and not (cheque and banque):
|
elif paiement.type_paiement == "check" and not (cheque and banque):
|
||||||
raise forms.ValidationError("Le numéro de chèque et\
|
raise forms.ValidationError(
|
||||||
la banque sont obligatoires.")
|
_("A cheque number and a bank must be specified.")
|
||||||
|
)
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : Better name and docstring
|
||||||
class RechargeForm(FormRevMixin, Form):
|
class RechargeForm(FormRevMixin, Form):
|
||||||
value = forms.FloatField(
|
value = forms.FloatField(
|
||||||
label='Valeur',
|
label=_("Amount"),
|
||||||
min_value=0.01,
|
min_value=0.01,
|
||||||
validators = []
|
validators = []
|
||||||
)
|
)
|
||||||
|
@ -297,7 +347,21 @@ class RechargeForm(FormRevMixin, Form):
|
||||||
def clean_value(self):
|
def clean_value(self):
|
||||||
value = self.cleaned_data['value']
|
value = self.cleaned_data['value']
|
||||||
if value < OptionalUser.get_cached_value('min_online_payment'):
|
if value < OptionalUser.get_cached_value('min_online_payment'):
|
||||||
raise forms.ValidationError("Montant inférieur au montant minimal de paiement en ligne (%s) €" % OptionalUser.get_cached_value('min_online_payment'))
|
raise forms.ValidationError(
|
||||||
|
_("Requested amount is too small. Minimum amount possible : \
|
||||||
|
%(min_online_amount)s €") % {
|
||||||
|
min_online_amount: OptionalUser.get_cached_value(
|
||||||
|
'min_online_payment'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
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("Le solde ne peux excéder %s " % OptionalUser.get_cached_value('max_solde'))
|
raise forms.ValidationError(
|
||||||
|
_("Requested amount is too high. Your balance can't exceed \
|
||||||
|
%(max_online_balance)s €") % {
|
||||||
|
max_online_balance: OptionalUser.get_cached_value(
|
||||||
|
'max_solde'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -42,6 +42,7 @@ Post_save et Post_delete : sychronisation des services et régénération
|
||||||
des services d'accès réseau (ex dhcp) lors de la vente d'une cotisation
|
des services d'accès réseau (ex dhcp) lors de la vente d'une cotisation
|
||||||
par exemple
|
par exemple
|
||||||
"""
|
"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
@ -55,55 +56,86 @@ from django.core.validators import MinValueValidator
|
||||||
from django.db.models import Max
|
from django.db.models import Max
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from machines.models import regen
|
from machines.models import regen
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from re2o.field_permissions import FieldPermissionModelMixin
|
from re2o.field_permissions import FieldPermissionModelMixin
|
||||||
from re2o.mixins import AclMixin, RevMixin
|
from re2o.mixins import AclMixin, RevMixin
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
""" Définition du modèle des factures. Une facture regroupe une ou
|
""" Définition du modèle des factures. Une facture regroupe une ou
|
||||||
plusieurs ventes, rattachée à un user, et reliée à un moyen de paiement
|
plusieurs ventes, rattachée à un user, et reliée à un moyen de paiement
|
||||||
et si il y a lieu un numero pour les chèques. Possède les valeurs
|
et si il y a lieu un numero pour les chèques. Possède les valeurs
|
||||||
valides et controle (trésorerie)"""
|
valides et controle (trésorerie)"""
|
||||||
PRETTY_NAME = "Factures émises"
|
# TODO : translate docstrign to English
|
||||||
|
|
||||||
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
||||||
|
# TODO : change paiement to payment
|
||||||
paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT)
|
paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT)
|
||||||
|
# TODO : change banque to bank
|
||||||
banque = models.ForeignKey(
|
banque = models.ForeignKey(
|
||||||
'Banque',
|
'Banque',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True)
|
null=True
|
||||||
cheque = models.CharField(max_length=255, blank=True)
|
)
|
||||||
date = models.DateTimeField(auto_now_add=True)
|
# TODO : maybe change to cheque nummber because not evident
|
||||||
valid = models.BooleanField(default=True)
|
cheque = models.CharField(
|
||||||
control = models.BooleanField(default=False)
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Cheque number")
|
||||||
|
)
|
||||||
|
date = models.DateTimeField(
|
||||||
|
auto_now_add=True,
|
||||||
|
verbose_name=_("Date")
|
||||||
|
)
|
||||||
|
# TODO : change name to validity for clarity
|
||||||
|
valid = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("Validated")
|
||||||
|
)
|
||||||
|
# TODO : changed name to controlled for clarity
|
||||||
|
control = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
verbose_name=_("Controlled")
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
permissions = (
|
permissions = (
|
||||||
("change_facture_control", "Peut changer l'etat de controle"),
|
# TODO : change facture to invoice
|
||||||
("change_facture_pdf", "Peut éditer une facture pdf"),
|
('change_facture_control', _("Can change the controlled state")),
|
||||||
("view_facture", "Peut voir un objet facture"),
|
# TODO : seems more likely to be call create_facture_pdf or create_invoice_pdf
|
||||||
("change_all_facture", "Superdroit, peut modifier toutes les factures"),
|
('change_facture_pdf', _("Can create a custom PDF invoice")),
|
||||||
|
('view_facture', _("Can see an invoice's details")),
|
||||||
|
('change_all_facture', _("Can edit all the previous invoices")),
|
||||||
)
|
)
|
||||||
|
verbose_name = _("Invoice")
|
||||||
|
verbose_name_plural = _("Invoices")
|
||||||
|
|
||||||
def linked_objects(self):
|
def linked_objects(self):
|
||||||
"""Return linked objects : machine and domain.
|
"""Return linked objects : machine and domain.
|
||||||
Usefull in history display"""
|
Usefull in history display"""
|
||||||
return self.vente_set.all()
|
return self.vente_set.all()
|
||||||
|
|
||||||
|
# TODO : change prix to price
|
||||||
def prix(self):
|
def prix(self):
|
||||||
"""Renvoie le prix brut sans les quantités. Méthode
|
"""Renvoie le prix brut sans les quantités. Méthode
|
||||||
dépréciée"""
|
dépréciée"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change prix to price
|
||||||
prix = Vente.objects.filter(
|
prix = Vente.objects.filter(
|
||||||
facture=self
|
facture=self
|
||||||
).aggregate(models.Sum('prix'))['prix__sum']
|
).aggregate(models.Sum('prix'))['prix__sum']
|
||||||
return prix
|
return prix
|
||||||
|
|
||||||
|
# TODO : change prix to price
|
||||||
def prix_total(self):
|
def prix_total(self):
|
||||||
"""Prix total : somme des produits prix_unitaire et quantité des
|
"""Prix total : somme des produits prix_unitaire et quantité des
|
||||||
ventes de l'objet"""
|
ventes de l'objet"""
|
||||||
|
# TODO : translate docstrign to English
|
||||||
|
# TODO : change Vente to somethingelse
|
||||||
return Vente.objects.filter(
|
return Vente.objects.filter(
|
||||||
facture=self
|
facture=self
|
||||||
).aggregate(
|
).aggregate(
|
||||||
|
@ -115,6 +147,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
"""String, somme des name des ventes de self"""
|
"""String, somme des name des ventes de self"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
name = ' - '.join(Vente.objects.filter(
|
name = ' - '.join(Vente.objects.filter(
|
||||||
facture=self
|
facture=self
|
||||||
).values_list('name', flat=True))
|
).values_list('name', flat=True))
|
||||||
|
@ -122,44 +155,41 @@ 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, u"Vous n'avez pas le droit d'éditer les factures"
|
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 not self.user.can_edit(user_request, *args, **kwargs)[0]:
|
||||||
return False, u"Vous ne pouvez pas éditer les factures de cet user protégé"
|
return False, _("You don't have the right to edit this user's invoices.")
|
||||||
elif not user_request.has_perm('cotisations.change_all_facture') and\
|
elif not user_request.has_perm('cotisations.change_all_facture') and\
|
||||||
(self.control or not self.valid):
|
(self.control or not self.valid):
|
||||||
return False, u"Vous n'avez pas le droit d'éditer une facture\
|
return False, _("You don't have the right to edit an invoice already controlled or invalidated.")
|
||||||
controlée ou invalidée par un trésorier"
|
|
||||||
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_facture'):
|
if not user_request.has_perm('cotisations.delete_facture'):
|
||||||
return False, u"Vous n'avez pas le droit de supprimer une facture"
|
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, u"Vous ne pouvez pas éditer les factures de cet user protégé"
|
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, u"Vous ne pouvez pas supprimer une facture\
|
return False, _("You don't have the right to delete an invoice already controlled or invalidated.")
|
||||||
contrôlée ou invalidée par un trésorier"
|
|
||||||
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, u"Vous ne pouvez pas afficher l'historique d'une\
|
return False, _("You don't have the right to see someone else's invoices history.")
|
||||||
facture d'un autre user que vous sans droit cableur"
|
|
||||||
elif not self.valid:
|
elif not self.valid:
|
||||||
return False, u"La facture est invalidée et ne peut être affichée"
|
return False, _("The invoice has been invalidated.")
|
||||||
else:
|
else:
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
@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'), "Vous ne pouvez pas éditer le controle sans droit trésorier"
|
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'), "Vous ne pouvez pas éditer une facture sans droit trésorier"
|
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)
|
||||||
|
@ -174,6 +204,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
@receiver(post_save, sender=Facture)
|
@receiver(post_save, sender=Facture)
|
||||||
def facture_post_save(sender, **kwargs):
|
def facture_post_save(sender, **kwargs):
|
||||||
"""Post save d'une facture, synchronise l'user ldap"""
|
"""Post save d'une facture, synchronise l'user ldap"""
|
||||||
|
# TODO : translate docstrign into English
|
||||||
facture = kwargs['instance']
|
facture = kwargs['instance']
|
||||||
user = facture.user
|
user = facture.user
|
||||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||||
|
@ -182,51 +213,82 @@ def facture_post_save(sender, **kwargs):
|
||||||
@receiver(post_delete, sender=Facture)
|
@receiver(post_delete, sender=Facture)
|
||||||
def facture_post_delete(sender, **kwargs):
|
def facture_post_delete(sender, **kwargs):
|
||||||
"""Après la suppression d'une facture, on synchronise l'user ldap"""
|
"""Après la suppression d'une facture, on synchronise l'user ldap"""
|
||||||
|
# TODO : translate docstring into English
|
||||||
user = kwargs['instance'].user
|
user = kwargs['instance'].user
|
||||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change Vente to Purchase
|
||||||
class Vente(RevMixin, AclMixin, models.Model):
|
class Vente(RevMixin, AclMixin, models.Model):
|
||||||
"""Objet vente, contient une quantité, une facture parente, un nom,
|
"""Objet vente, contient une quantité, une facture parente, un nom,
|
||||||
un prix. Peut-être relié à un objet cotisation, via le boolean
|
un prix. Peut-être relié à un objet cotisation, via le boolean
|
||||||
iscotisation"""
|
iscotisation"""
|
||||||
PRETTY_NAME = "Ventes effectuées"
|
# TODO : translate docstring into English
|
||||||
|
|
||||||
|
# TODO : change this to English
|
||||||
COTISATION_TYPE = (
|
COTISATION_TYPE = (
|
||||||
('Connexion', 'Connexion'),
|
('Connexion', _("Connexion")),
|
||||||
('Adhesion', 'Adhesion'),
|
('Adhesion', _("Membership")),
|
||||||
('All', 'All'),
|
('All', _("Both of them")),
|
||||||
)
|
)
|
||||||
|
|
||||||
facture = models.ForeignKey('Facture', on_delete=models.CASCADE)
|
# TODO : change facture to invoice
|
||||||
number = models.IntegerField(validators=[MinValueValidator(1)])
|
facture = models.ForeignKey(
|
||||||
name = models.CharField(max_length=255)
|
'Facture',
|
||||||
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_("Invoice")
|
||||||
|
)
|
||||||
|
# TODO : change number to amount for clarity
|
||||||
|
number = models.IntegerField(
|
||||||
|
validators=[MinValueValidator(1)],
|
||||||
|
verbose_name=_("Amount")
|
||||||
|
)
|
||||||
|
# TODO : change this field for a ForeinKey to Article
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("Article")
|
||||||
|
)
|
||||||
|
# TODO : change prix to price
|
||||||
|
# TODO : this field is not needed if you use Article ForeignKey
|
||||||
|
prix = models.DecimalField(
|
||||||
|
max_digits=5,
|
||||||
|
decimal_places=2,
|
||||||
|
verbose_name=_("Price"))
|
||||||
|
# TODO : this field is not needed if you use Article ForeignKey
|
||||||
duration = models.PositiveIntegerField(
|
duration = models.PositiveIntegerField(
|
||||||
help_text="Durée exprimée en mois entiers",
|
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True)
|
null=True,
|
||||||
|
verbose_name=_("Duration (in whole month)")
|
||||||
|
)
|
||||||
|
# TODO : this field is not needed if you use Article ForeignKey
|
||||||
type_cotisation = models.CharField(
|
type_cotisation = models.CharField(
|
||||||
choices=COTISATION_TYPE,
|
choices=COTISATION_TYPE,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
max_length=255
|
max_length=255,
|
||||||
|
verbose_name=_("Type of cotisation")
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_vente", "Peut voir un objet vente"),
|
('view_vente', _("Can see a purchase's details")),
|
||||||
("change_all_vente", "Superdroit, peut modifier toutes les ventes"),
|
('change_all_vente', _("Can edit all the previous purchases")),
|
||||||
)
|
)
|
||||||
|
verbose_name = _("Purchase")
|
||||||
|
verbose_name_plural = _("Purchases")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change prix_total to total_price
|
||||||
def prix_total(self):
|
def prix_total(self):
|
||||||
"""Renvoie le prix_total de self (nombre*prix)"""
|
"""Renvoie le prix_total de self (nombre*prix)"""
|
||||||
|
# TODO : translate docstring to english
|
||||||
return self.prix*self.number
|
return self.prix*self.number
|
||||||
|
|
||||||
def update_cotisation(self):
|
def update_cotisation(self):
|
||||||
"""Mets à jour l'objet related cotisation de la vente, si
|
"""Mets à jour l'objet related cotisation de la vente, si
|
||||||
il existe : update la date de fin à partir de la durée de
|
il existe : update la date de fin à partir de la durée de
|
||||||
la vente"""
|
la vente"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
if hasattr(self, 'cotisation'):
|
if hasattr(self, 'cotisation'):
|
||||||
cotisation = self.cotisation
|
cotisation = self.cotisation
|
||||||
cotisation.date_end = cotisation.date_start + relativedelta(
|
cotisation.date_end = cotisation.date_start + relativedelta(
|
||||||
|
@ -237,6 +299,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
"""Update et crée l'objet cotisation associé à une facture, prend
|
"""Update et crée l'objet cotisation associé à une facture, prend
|
||||||
en argument l'user, la facture pour la quantitéi, et l'article pour
|
en argument l'user, la facture pour la quantitéi, et l'article pour
|
||||||
la durée"""
|
la durée"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
if not hasattr(self, 'cotisation') and self.type_cotisation:
|
if not hasattr(self, 'cotisation') and self.type_cotisation:
|
||||||
cotisation = Cotisation(vente=self)
|
cotisation = Cotisation(vente=self)
|
||||||
cotisation.type_cotisation = self.type_cotisation
|
cotisation.type_cotisation = self.type_cotisation
|
||||||
|
@ -264,41 +327,40 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
return
|
return
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
# TODO : ecrire une docstring
|
||||||
# On verifie que si iscotisation, duration est présent
|
# On verifie que si iscotisation, duration est présent
|
||||||
if self.type_cotisation and not self.duration:
|
if self.type_cotisation and not self.duration:
|
||||||
raise ValidationError("Cotisation et durée doivent être présents\
|
raise ValidationError(
|
||||||
ensembles")
|
_("A cotisation should always have a duration.")
|
||||||
|
)
|
||||||
self.update_cotisation()
|
self.update_cotisation()
|
||||||
super(Vente, self).save(*args, **kwargs)
|
super(Vente, self).save(*args, **kwargs)
|
||||||
|
|
||||||
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, u"Vous n'avez pas le droit d'éditer les ventes"
|
return False, _("You don't have the rights 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 not self.facture.user.can_edit(user_request, *args, **kwargs)[0]:
|
||||||
return False, u"Vous ne pouvez pas éditer les factures de cet user protégé"
|
return False, _("You don't have the right to edit this user's purchases.")
|
||||||
elif not user_request.has_perm('cotisations.change_all_vente') and\
|
elif not user_request.has_perm('cotisations.change_all_vente') and\
|
||||||
(self.facture.control or not self.facture.valid):
|
(self.facture.control or not self.facture.valid):
|
||||||
return False, u"Vous n'avez pas le droit d'éditer une vente\
|
return False, _("You don't have the right to edit a purchase already controlled or invalidated.")
|
||||||
controlée ou invalidée par un trésorier"
|
|
||||||
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_vente'):
|
if not user_request.has_perm('cotisations.delete_vente'):
|
||||||
return False, u"Vous n'avez pas le droit de supprimer une vente"
|
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, u"Vous ne pouvez pas éditer les factures de cet user protégé"
|
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, u"Vous ne pouvez pas supprimer une vente\
|
return False, _("You don't have the right to delete a purchase already controlled or invalidated.")
|
||||||
contrôlée ou invalidée par un trésorier"
|
|
||||||
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, u"Vous ne pouvez pas afficher l'historique d'une\
|
return False, _("You don't have the right to see someone else's purchase history.")
|
||||||
facture d'un autre user que vous sans droit cableur"
|
|
||||||
else:
|
else:
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
@ -306,10 +368,13 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
return str(self.name) + ' ' + str(self.facture)
|
return str(self.name) + ' ' + str(self.facture)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change vente to purchase
|
||||||
@receiver(post_save, sender=Vente)
|
@receiver(post_save, sender=Vente)
|
||||||
def vente_post_save(sender, **kwargs):
|
def vente_post_save(sender, **kwargs):
|
||||||
"""Post save d'une vente, déclencge la création de l'objet cotisation
|
"""Post save d'une vente, déclencge la création de l'objet cotisation
|
||||||
si il y a lieu(si iscotisation) """
|
si il y a lieu(si iscotisation) """
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change vente to purchase
|
||||||
vente = kwargs['instance']
|
vente = kwargs['instance']
|
||||||
if hasattr(vente, 'cotisation'):
|
if hasattr(vente, 'cotisation'):
|
||||||
vente.cotisation.vente = vente
|
vente.cotisation.vente = vente
|
||||||
|
@ -321,10 +386,13 @@ def vente_post_save(sender, **kwargs):
|
||||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change vente to purchase
|
||||||
@receiver(post_delete, sender=Vente)
|
@receiver(post_delete, sender=Vente)
|
||||||
def vente_post_delete(sender, **kwargs):
|
def vente_post_delete(sender, **kwargs):
|
||||||
"""Après suppression d'une vente, on synchronise l'user ldap (ex
|
"""Après suppression d'une vente, on synchronise l'user ldap (ex
|
||||||
suppression d'une cotisation"""
|
suppression d'une cotisation"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change vente to purchase
|
||||||
vente = kwargs['instance']
|
vente = kwargs['instance']
|
||||||
if vente.type_cotisation:
|
if vente.type_cotisation:
|
||||||
user = vente.facture.user
|
user = vente.facture.user
|
||||||
|
@ -334,53 +402,69 @@ def vente_post_delete(sender, **kwargs):
|
||||||
class Article(RevMixin, AclMixin, models.Model):
|
class Article(RevMixin, AclMixin, models.Model):
|
||||||
"""Liste des articles en vente : prix, nom, et attribut iscotisation
|
"""Liste des articles en vente : prix, nom, et attribut iscotisation
|
||||||
et duree si c'est une cotisation"""
|
et duree si c'est une cotisation"""
|
||||||
PRETTY_NAME = "Articles en vente"
|
# TODO : translate docstring to English
|
||||||
|
|
||||||
|
# TODO : Either use TYPE or TYPES in both choices but not both
|
||||||
USER_TYPES = (
|
USER_TYPES = (
|
||||||
('Adherent', 'Adherent'),
|
('Adherent', _("Member")),
|
||||||
('Club', 'Club'),
|
('Club', _("Club")),
|
||||||
('All', 'All'),
|
('All', _("Both of them")),
|
||||||
)
|
)
|
||||||
|
|
||||||
COTISATION_TYPE = (
|
COTISATION_TYPE = (
|
||||||
('Connexion', 'Connexion'),
|
('Connexion', _("Connexion")),
|
||||||
('Adhesion', 'Adhesion'),
|
('Adhesion', _("Membership")),
|
||||||
('All', 'All'),
|
('All', _("Both of them")),
|
||||||
)
|
)
|
||||||
|
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(
|
||||||
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
max_length=255,
|
||||||
|
verbose_name=_("Designation")
|
||||||
|
)
|
||||||
|
# TODO : change prix to price
|
||||||
|
prix = models.DecimalField(
|
||||||
|
max_digits=5,
|
||||||
|
decimal_places=2,
|
||||||
|
verbose_name=_("Unitary price")
|
||||||
|
)
|
||||||
duration = models.PositiveIntegerField(
|
duration = models.PositiveIntegerField(
|
||||||
help_text="Durée exprimée en mois entiers",
|
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
validators=[MinValueValidator(0)])
|
validators=[MinValueValidator(0)],
|
||||||
|
verbose_name=_("Duration (in whole month)")
|
||||||
|
)
|
||||||
type_user = models.CharField(
|
type_user = models.CharField(
|
||||||
choices=USER_TYPES,
|
choices=USER_TYPES,
|
||||||
default='All',
|
default='All',
|
||||||
max_length=255
|
max_length=255,
|
||||||
|
verbose_name=_("Type of users concerned")
|
||||||
)
|
)
|
||||||
type_cotisation = models.CharField(
|
type_cotisation = models.CharField(
|
||||||
choices=COTISATION_TYPE,
|
choices=COTISATION_TYPE,
|
||||||
default=None,
|
default=None,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
max_length=255
|
max_length=255,
|
||||||
|
verbose_name=_("Type of cotisation")
|
||||||
)
|
)
|
||||||
|
|
||||||
unique_together = ('name', 'type_user')
|
unique_together = ('name', 'type_user')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_article", "Peut voir un objet article"),
|
('view_article', _("Can see an article's details")),
|
||||||
)
|
)
|
||||||
|
verbose_name = "Article"
|
||||||
|
verbose_name_plural = "Articles"
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.name.lower() == "solde":
|
if self.name.lower() == 'solde':
|
||||||
raise ValidationError("Solde est un nom d'article invalide")
|
raise ValidationError(
|
||||||
|
_("Solde is a reserved article name")
|
||||||
|
)
|
||||||
if self.type_cotisation and not self.duration:
|
if self.type_cotisation and not self.duration:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
"La durée est obligatoire si il s'agit d'une cotisation"
|
_("Duration must be specified for a cotisation")
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -389,34 +473,51 @@ class Article(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
class Banque(RevMixin, AclMixin, models.Model):
|
class Banque(RevMixin, AclMixin, models.Model):
|
||||||
"""Liste des banques"""
|
"""Liste des banques"""
|
||||||
PRETTY_NAME = "Banques enregistrées"
|
# TODO : translate docstring to English
|
||||||
|
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("Name")
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_banque", "Peut voir un objet banque"),
|
('view_banque', _("Can see a bank's details")),
|
||||||
)
|
)
|
||||||
|
verbose_name=_("Bank")
|
||||||
|
verbose_name_plural=_("Banks")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change Paiement to Payment
|
||||||
class Paiement(RevMixin, AclMixin, models.Model):
|
class Paiement(RevMixin, AclMixin, models.Model):
|
||||||
"""Moyens de paiement"""
|
"""Moyens de paiement"""
|
||||||
PRETTY_NAME = "Moyens de paiement"
|
# TODO : translate docstring to English
|
||||||
|
|
||||||
PAYMENT_TYPES = (
|
PAYMENT_TYPES = (
|
||||||
(0, 'Autre'),
|
(0, _("Standard")),
|
||||||
(1, 'Chèque'),
|
(1, _("Cheque")),
|
||||||
)
|
)
|
||||||
|
|
||||||
moyen = models.CharField(max_length=255)
|
# TODO : change moyen to method
|
||||||
type_paiement = models.IntegerField(choices=PAYMENT_TYPES, default=0)
|
moyen = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("Method")
|
||||||
|
)
|
||||||
|
type_paiement = models.IntegerField(
|
||||||
|
choices=PAYMENT_TYPES,
|
||||||
|
default=0,
|
||||||
|
verbose_name=_("Payment type")
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_paiement", "Peut voir un objet paiement"),
|
('view_paiement', _("Can see a payement's details")),
|
||||||
)
|
)
|
||||||
|
verbose_name = _("Payment method")
|
||||||
|
verbose_name_plural = _("Payment methods")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.moyen
|
return self.moyen
|
||||||
|
@ -426,61 +527,71 @@ class Paiement(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""Un seul type de paiement peut-etre cheque..."""
|
"""Un seul type de paiement peut-etre cheque..."""
|
||||||
|
# TODO : translate docstring to English
|
||||||
if Paiement.objects.filter(type_paiement=1).count() > 1:
|
if Paiement.objects.filter(type_paiement=1).count() > 1:
|
||||||
raise ValidationError("On ne peut avoir plusieurs mode de paiement\
|
raise ValidationError(
|
||||||
chèque")
|
_("You cannot have multiple payment method of type cheque")
|
||||||
|
)
|
||||||
super(Paiement, self).save(*args, **kwargs)
|
super(Paiement, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Cotisation(RevMixin, AclMixin, models.Model):
|
class Cotisation(RevMixin, AclMixin, models.Model):
|
||||||
"""Objet cotisation, debut et fin, relié en onetoone à une vente"""
|
"""Objet cotisation, debut et fin, relié en onetoone à une vente"""
|
||||||
PRETTY_NAME = "Cotisations"
|
# TODO : translate docstring to English
|
||||||
|
|
||||||
COTISATION_TYPE = (
|
COTISATION_TYPE = (
|
||||||
('Connexion', 'Connexion'),
|
('Connexion', _("Connexion")),
|
||||||
('Adhesion', 'Adhesion'),
|
('Adhesion', _("Adhesion")),
|
||||||
('All', 'All'),
|
('All', _("Both of them")),
|
||||||
)
|
)
|
||||||
|
|
||||||
vente = models.OneToOneField('Vente', on_delete=models.CASCADE, null=True)
|
# TODO : change vente to purchase
|
||||||
|
vente = models.OneToOneField(
|
||||||
|
'Vente',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
null=True,
|
||||||
|
verbose_name=_("Purchase")
|
||||||
|
)
|
||||||
type_cotisation = models.CharField(
|
type_cotisation = models.CharField(
|
||||||
choices=COTISATION_TYPE,
|
choices=COTISATION_TYPE,
|
||||||
max_length=255,
|
max_length=255,
|
||||||
default='All',
|
default='All',
|
||||||
|
verbose_name=_("Type of cotisation")
|
||||||
|
)
|
||||||
|
date_start = models.DateTimeField(
|
||||||
|
verbose_name=_("Starting date")
|
||||||
|
)
|
||||||
|
date_end = models.DateTimeField(
|
||||||
|
verbose_name=_("Ending date")
|
||||||
)
|
)
|
||||||
date_start = models.DateTimeField()
|
|
||||||
date_end = models.DateTimeField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_cotisation", "Peut voir un objet cotisation"),
|
('view_cotisation', _("Can see a cotisation's details")),
|
||||||
("change_all_cotisation", "Superdroit, peut modifier toutes les cotisations"),
|
('change_all_cotisation', _("Can edit the previous cotisations")),
|
||||||
)
|
)
|
||||||
|
|
||||||
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, u"Vous n'avez pas le droit d'éditer les cotisations"
|
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') and\
|
||||||
(self.vente.facture.control or not self.vente.facture.valid):
|
(self.vente.facture.control or not self.vente.facture.valid):
|
||||||
return False, u"Vous n'avez pas le droit d'éditer une cotisation\
|
return False, _("You don't have the right to edit a cotisation already controlled or invalidated.")
|
||||||
controlée ou invalidée par un trésorier"
|
|
||||||
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, u"Vous n'avez pas le droit de supprimer une cotisations"
|
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, u"Vous ne pouvez pas supprimer une cotisations\
|
return False, _("You don't have the right to delete a cotisation already controlled or invalidated.")
|
||||||
contrôlée ou invalidée par un trésorier"
|
|
||||||
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, u"Vous ne pouvez pas afficher l'historique d'une\
|
return False, _("You don't have the right to display someone else's cotisation history.")
|
||||||
cotisation d'un autre user que vous sans droit cableur"
|
|
||||||
else:
|
else:
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
@ -491,15 +602,18 @@ class Cotisation(RevMixin, AclMixin, models.Model):
|
||||||
@receiver(post_save, sender=Cotisation)
|
@receiver(post_save, sender=Cotisation)
|
||||||
def cotisation_post_save(sender, **kwargs):
|
def cotisation_post_save(sender, **kwargs):
|
||||||
"""Après modification d'une cotisation, regeneration des services"""
|
"""Après modification d'une cotisation, regeneration des services"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
regen('dns')
|
regen('dns')
|
||||||
regen('dhcp')
|
regen('dhcp')
|
||||||
regen('mac_ip_list')
|
regen('mac_ip_list')
|
||||||
regen('mailing')
|
regen('mailing')
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : should be name cotisation_post_delete
|
||||||
@receiver(post_delete, sender=Cotisation)
|
@receiver(post_delete, sender=Cotisation)
|
||||||
def vente_post_delete(sender, **kwargs):
|
def vente_post_delete(sender, **kwargs):
|
||||||
"""Après suppression d'une vente, régénération des services"""
|
"""Après suppression d'une vente, régénération des services"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
cotisation = kwargs['instance']
|
cotisation = kwargs['instance']
|
||||||
regen('mac_ip_list')
|
regen('mac_ip_list')
|
||||||
regen('mailing')
|
regen('mailing')
|
||||||
|
|
|
@ -8,6 +8,7 @@ from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.utils.datastructures import MultiValueDictKeyError
|
from django.utils.datastructures import MultiValueDictKeyError
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -22,7 +23,9 @@ def accept_payment(request, factureid):
|
||||||
facture = get_object_or_404(Facture, id=factureid)
|
facture = get_object_or_404(Facture, id=factureid)
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
"Le paiement de {} € a été accepté.".format(facture.prix())
|
_("The payment of %(amount)s € has been accepted.") % {
|
||||||
|
amount: facture.prix()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return redirect(reverse('users:profil', kwargs={'userid':request.user.id}))
|
return redirect(reverse('users:profil', kwargs={'userid':request.user.id}))
|
||||||
|
|
||||||
|
@ -32,7 +35,7 @@ def accept_payment(request, factureid):
|
||||||
def refuse_payment(request):
|
def refuse_payment(request):
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"Le paiement a été refusé."
|
_("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}))
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ def ipn(request):
|
||||||
idTransaction = request.POST['idTransaction']
|
idTransaction = request.POST['idTransaction']
|
||||||
|
|
||||||
# On vérifie que le paiement nous est destiné
|
# On vérifie que le paiement nous est destiné
|
||||||
|
# TODO : translate comment to English
|
||||||
if not idTpe == AssoOption.get_cached_value('payment_id'):
|
if not idTpe == AssoOption.get_cached_value('payment_id'):
|
||||||
return HttpResponseBadRequest("HTTP/1.1 400 Bad Request")
|
return HttpResponseBadRequest("HTTP/1.1 400 Bad Request")
|
||||||
|
|
||||||
|
@ -63,6 +67,7 @@ def ipn(request):
|
||||||
|
|
||||||
facture = get_object_or_404(Facture, id=factureid)
|
facture = get_object_or_404(Facture, id=factureid)
|
||||||
|
|
||||||
|
# TODO : translate comments to English
|
||||||
# On vérifie que le paiement est valide
|
# On vérifie que le paiement est valide
|
||||||
if not result:
|
if not result:
|
||||||
# Le paiement a échoué : on effectue les actions nécessaires (On indique qu'elle a échoué)
|
# Le paiement a échoué : on effectue les actions nécessaires (On indique qu'elle a échoué)
|
||||||
|
|
|
@ -36,6 +36,7 @@ from django.db import transaction
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.forms import modelformset_factory, formset_factory
|
from django.forms import modelformset_factory, formset_factory
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.decorators.debug import sensitive_variables
|
from django.views.decorators.debug import sensitive_variables
|
||||||
# Import des models, forms et fonctions re2o
|
# Import des models, forms et fonctions re2o
|
||||||
|
@ -88,12 +89,16 @@ def new_facture(request, user, userid):
|
||||||
enfin sauve la facture parente.
|
enfin sauve la facture parente.
|
||||||
TODO : simplifier cette fonction, déplacer l'intelligence coté models
|
TODO : simplifier cette fonction, déplacer l'intelligence coté models
|
||||||
Facture et Vente."""
|
Facture et Vente."""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change facture to invoice
|
||||||
facture = Facture(user=user)
|
facture = Facture(user=user)
|
||||||
|
# TODO : change comment to English
|
||||||
# Le template a besoin de connaitre les articles pour le js
|
# Le template a besoin de connaitre les articles pour le js
|
||||||
article_list = Article.objects.filter(
|
article_list = Article.objects.filter(
|
||||||
Q(type_user='All') | Q(type_user=request.user.class_name)
|
Q(type_user='All') | Q(type_user=request.user.class_name)
|
||||||
)
|
)
|
||||||
# On envoie la form fature et un formset d'articles
|
# On envoie la form fature et un formset d'articles
|
||||||
|
# TODO : change facture to invoice
|
||||||
facture_form = NewFactureForm(request.POST or None, instance=facture)
|
facture_form = NewFactureForm(request.POST or None, instance=facture)
|
||||||
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)
|
||||||
|
@ -104,22 +109,27 @@ def new_facture(request, user, userid):
|
||||||
articles = article_formset
|
articles = article_formset
|
||||||
# Si au moins un article est rempli
|
# Si au moins un article est rempli
|
||||||
if any(art.cleaned_data for art in articles):
|
if any(art.cleaned_data for art in articles):
|
||||||
|
# TODO : change solde to balance
|
||||||
user_solde = OptionalUser.get_cached_value('user_solde')
|
user_solde = OptionalUser.get_cached_value('user_solde')
|
||||||
solde_negatif = OptionalUser.get_cached_value('solde_negatif')
|
solde_negatif = OptionalUser.get_cached_value('solde_negatif')
|
||||||
# Si on paye par solde, que l'option est activée,
|
# Si on paye par solde, que l'option est activée,
|
||||||
# on vérifie que le négatif n'est pas atteint
|
# on vérifie que le négatif n'est pas atteint
|
||||||
if user_solde:
|
if user_solde:
|
||||||
|
# TODO : change Paiement to Payment
|
||||||
if new_facture_instance.paiement == Paiement.objects.get_or_create(
|
if new_facture_instance.paiement == Paiement.objects.get_or_create(
|
||||||
moyen='solde'
|
moyen='solde'
|
||||||
)[0]:
|
)[0]:
|
||||||
prix_total = 0
|
prix_total = 0
|
||||||
for art_item in articles:
|
for art_item in articles:
|
||||||
if art_item.cleaned_data:
|
if art_item.cleaned_data:
|
||||||
|
# change prix to price
|
||||||
prix_total += art_item.cleaned_data['article']\
|
prix_total += art_item.cleaned_data['article']\
|
||||||
.prix*art_item.cleaned_data['quantity']
|
.prix*art_item.cleaned_data['quantity']
|
||||||
if float(user.solde) - float(prix_total) < solde_negatif:
|
if float(user.solde) - float(prix_total) < solde_negatif:
|
||||||
messages.error(request, "Le solde est insuffisant pour\
|
messages.error(
|
||||||
effectuer l'opération")
|
request,
|
||||||
|
_("Your balance is too low for this operation.")
|
||||||
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': userid}
|
kwargs={'userid': userid}
|
||||||
|
@ -142,34 +152,43 @@ def new_facture(request, user, userid):
|
||||||
for art_item in articles if art_item.cleaned_data):
|
for art_item in articles if art_item.cleaned_data):
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
"La cotisation a été prolongée\
|
_("The cotisation of %(member_name)s has been \
|
||||||
pour l'adhérent %s jusqu'au %s" % (
|
extended to %(end_date)s.") % {
|
||||||
user.pseudo, user.end_adhesion()
|
member_name: user.pseudo,
|
||||||
)
|
end_date: user.end_adhesion()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.success(request, "La facture a été crée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been created.")
|
||||||
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': userid}
|
kwargs={'userid': userid}
|
||||||
))
|
))
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
u"Il faut au moins un article valide pour créer une facture"
|
_("You need to choose at least one article.")
|
||||||
)
|
)
|
||||||
return form({
|
return form(
|
||||||
|
{
|
||||||
'factureform': facture_form,
|
'factureform': facture_form,
|
||||||
'venteform': article_formset,
|
'venteform': article_formset,
|
||||||
'articlelist': article_list
|
'articlelist': article_list
|
||||||
}, 'cotisations/new_facture.html', request)
|
},
|
||||||
|
'cotisations/new_facture.html', request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_change(Facture, 'pdf')
|
@can_change(Facture, 'pdf')
|
||||||
def new_facture_pdf(request):
|
def new_facture_pdf(request):
|
||||||
"""Permet de générer un pdf d'une facture. Réservée
|
"""Permet de générer un pdf d'une facture. Réservée
|
||||||
au trésorier, permet d'emettre des factures sans objet
|
au trésorier, permet d'emettre des factures sans objet
|
||||||
Vente ou Facture correspondant en bdd"""
|
Vente ou Facture correspondant en bdd"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
facture_form = NewFactureFormPdf(request.POST or None)
|
facture_form = NewFactureFormPdf(request.POST or None)
|
||||||
if facture_form.is_valid():
|
if facture_form.is_valid():
|
||||||
tbl = []
|
tbl = []
|
||||||
|
@ -204,6 +223,7 @@ def new_facture_pdf(request):
|
||||||
}, 'cotisations/facture.html', request)
|
}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_view(Facture)
|
@can_view(Facture)
|
||||||
def facture_pdf(request, facture, factureid):
|
def facture_pdf(request, facture, factureid):
|
||||||
|
@ -211,7 +231,8 @@ def facture_pdf(request, facture, factureid):
|
||||||
et génére une facture avec le total, le moyen de paiement, l'adresse
|
et génére une facture avec le total, le moyen de paiement, l'adresse
|
||||||
de l'adhérent, etc. Réservée à self pour un user sans droits,
|
de l'adhérent, etc. Réservée à self pour un user sans droits,
|
||||||
les droits cableurs permettent d'afficher toute facture"""
|
les droits cableurs permettent d'afficher toute facture"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change vente to purchase
|
||||||
ventes_objects = Vente.objects.all().filter(facture=facture)
|
ventes_objects = Vente.objects.all().filter(facture=facture)
|
||||||
ventes = []
|
ventes = []
|
||||||
for vente in ventes_objects:
|
for vente in ventes_objects:
|
||||||
|
@ -233,12 +254,14 @@ def facture_pdf(request, facture, factureid):
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_edit(Facture)
|
@can_edit(Facture)
|
||||||
def edit_facture(request, facture, factureid):
|
def edit_facture(request, facture, factureid):
|
||||||
"""Permet l'édition d'une facture. On peut y éditer les ventes
|
"""Permet l'édition d'une facture. On peut y éditer les ventes
|
||||||
déjà effectuer, ou rendre une facture invalide (non payées, chèque
|
déjà effectuer, ou rendre une facture invalide (non payées, chèque
|
||||||
en bois etc). Mets à jour les durée de cotisation attenantes"""
|
en bois etc). Mets à jour les durée de cotisation attenantes"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
facture_form = EditFactureForm(request.POST or None, instance=facture, user=request.user)
|
facture_form = EditFactureForm(request.POST or None, instance=facture, user=request.user)
|
||||||
ventes_objects = Vente.objects.filter(facture=facture)
|
ventes_objects = Vente.objects.filter(facture=facture)
|
||||||
vente_form_set = modelformset_factory(
|
vente_form_set = modelformset_factory(
|
||||||
|
@ -252,7 +275,10 @@ def edit_facture(request, facture, factureid):
|
||||||
if facture_form.changed_data:
|
if facture_form.changed_data:
|
||||||
facture_form.save()
|
facture_form.save()
|
||||||
vente_form.save()
|
vente_form.save()
|
||||||
messages.success(request, "La facture a bien été modifiée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been successfully edited.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index'))
|
return redirect(reverse('cotisations:index'))
|
||||||
return form({
|
return form({
|
||||||
'factureform': facture_form,
|
'factureform': facture_form,
|
||||||
|
@ -260,14 +286,18 @@ def edit_facture(request, facture, factureid):
|
||||||
}, 'cotisations/edit_facture.html', request)
|
}, 'cotisations/edit_facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_delete(Facture)
|
@can_delete(Facture)
|
||||||
def del_facture(request, facture, factureid):
|
def del_facture(request, facture, factureid):
|
||||||
"""Suppression d'une facture. Supprime en cascade les ventes
|
"""Suppression d'une facture. Supprime en cascade les ventes
|
||||||
et cotisations filles"""
|
et cotisations filles"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
facture.delete()
|
messages.success(
|
||||||
messages.success(request, "La facture a été détruite")
|
request,
|
||||||
|
_("The invoice has been successfully deleted")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index'))
|
return redirect(reverse('cotisations:index'))
|
||||||
return form({
|
return form({
|
||||||
'objet': facture,
|
'objet': facture,
|
||||||
|
@ -275,11 +305,14 @@ def del_facture(request, facture, factureid):
|
||||||
}, 'cotisations/delete.html', request)
|
}, 'cotisations/delete.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change solde to balance
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(Facture)
|
@can_create(Facture)
|
||||||
@can_edit(User)
|
@can_edit(User)
|
||||||
def credit_solde(request, user, userid):
|
def credit_solde(request, user, userid):
|
||||||
""" Credit ou débit de solde """
|
""" Credit ou débit de solde """
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change facture to invoice
|
||||||
facture = CreditSoldeForm(request.POST or None)
|
facture = CreditSoldeForm(request.POST or None)
|
||||||
if facture.is_valid():
|
if facture.is_valid():
|
||||||
facture_instance = facture.save(commit=False)
|
facture_instance = facture.save(commit=False)
|
||||||
|
@ -292,7 +325,10 @@ def credit_solde(request, user, userid):
|
||||||
number=1
|
number=1
|
||||||
)
|
)
|
||||||
new_vente.save()
|
new_vente.save()
|
||||||
messages.success(request, "Solde modifié")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("Banlance successfully updated.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index'))
|
return redirect(reverse('cotisations:index'))
|
||||||
return form({'factureform': facture, 'action_name' : 'Créditer'}, 'cotisations/facture.html', request)
|
return form({'factureform': facture, 'action_name' : 'Créditer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
@ -307,10 +343,14 @@ def add_article(request):
|
||||||
aux articles en vente. La désignation, le prix... sont
|
aux articles en vente. La désignation, le prix... sont
|
||||||
copiés à la création de la facture. Un changement de prix n'a
|
copiés à la création de la facture. Un changement de prix n'a
|
||||||
PAS de conséquence sur les ventes déjà faites"""
|
PAS de conséquence sur les ventes déjà faites"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
article = ArticleForm(request.POST or None)
|
article = ArticleForm(request.POST or None)
|
||||||
if article.is_valid():
|
if article.is_valid():
|
||||||
article.save()
|
article.save()
|
||||||
messages.success(request, "L'article a été ajouté")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The article has been successfully created.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-article'))
|
return redirect(reverse('cotisations:index-article'))
|
||||||
return form({'factureform': article, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
return form({'factureform': article, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
@ -320,11 +360,15 @@ def add_article(request):
|
||||||
def edit_article(request, article_instance, articleid):
|
def edit_article(request, article_instance, articleid):
|
||||||
"""Edition d'un article (designation, prix, etc)
|
"""Edition d'un article (designation, prix, etc)
|
||||||
Réservé au trésorier"""
|
Réservé au trésorier"""
|
||||||
|
# TODO : translate dosctring to English
|
||||||
article = ArticleForm(request.POST or None, instance=article_instance)
|
article = ArticleForm(request.POST or None, instance=article_instance)
|
||||||
if article.is_valid():
|
if article.is_valid():
|
||||||
if article.changed_data:
|
if article.changed_data:
|
||||||
article.save()
|
article.save()
|
||||||
messages.success(request, "Type d'article modifié")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The article has been successfully edited.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-article'))
|
return redirect(reverse('cotisations:index-article'))
|
||||||
return form({'factureform': article, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
return form({'factureform': article, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
@ -333,45 +377,62 @@ def edit_article(request, article_instance, articleid):
|
||||||
@can_delete_set(Article)
|
@can_delete_set(Article)
|
||||||
def del_article(request, instances):
|
def del_article(request, instances):
|
||||||
"""Suppression d'un article en vente"""
|
"""Suppression d'un article en vente"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
article = DelArticleForm(request.POST or None, instances=instances)
|
article = DelArticleForm(request.POST or None, instances=instances)
|
||||||
if article.is_valid():
|
if article.is_valid():
|
||||||
article_del = article.cleaned_data['articles']
|
article_del = article.cleaned_data['articles']
|
||||||
article_del.delete()
|
article_del.delete()
|
||||||
messages.success(request, "Le/les articles ont été supprimé")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The article(s) have been successfully deleted.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-article'))
|
return redirect(reverse('cotisations:index-article'))
|
||||||
return form({'factureform': article, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
return form({'factureform': article, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change paiement to payment
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(Paiement)
|
@can_create(Paiement)
|
||||||
def add_paiement(request):
|
def add_paiement(request):
|
||||||
"""Ajoute un moyen de paiement. Relié aux factures
|
"""Ajoute un moyen de paiement. Relié aux factures
|
||||||
via foreign key"""
|
via foreign key"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
|
# TODO : change paiement to Payment
|
||||||
paiement = PaiementForm(request.POST or None)
|
paiement = PaiementForm(request.POST or None)
|
||||||
if paiement.is_valid():
|
if paiement.is_valid():
|
||||||
paiement.save()
|
paiement.save()
|
||||||
messages.success(request, "Le moyen de paiement a été ajouté")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The payment method has been successfully created.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-paiement'))
|
return redirect(reverse('cotisations:index-paiement'))
|
||||||
return form({'factureform': paiement, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
return form({'factureform': paiement, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : chnage paiement to Payment
|
||||||
@login_required
|
@login_required
|
||||||
@can_edit(Paiement)
|
@can_edit(Paiement)
|
||||||
def edit_paiement(request, paiement_instance, paiementid):
|
def edit_paiement(request, paiement_instance, paiementid):
|
||||||
"""Edition d'un moyen de paiement"""
|
"""Edition d'un moyen de paiement"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
paiement = PaiementForm(request.POST or None, instance=paiement_instance)
|
paiement = PaiementForm(request.POST or None, instance=paiement_instance)
|
||||||
if paiement.is_valid():
|
if paiement.is_valid():
|
||||||
if paiement.changed_data:
|
if paiement.changed_data:
|
||||||
paiement.save()
|
paiement.save()
|
||||||
messages.success(request, "Type de paiement modifié")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The payement method has been successfully edited.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-paiement'))
|
return redirect(reverse('cotisations:index-paiement'))
|
||||||
return form({'factureform': paiement, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
return form({'factureform': paiement, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change paiement to payment
|
||||||
@login_required
|
@login_required
|
||||||
@can_delete_set(Paiement)
|
@can_delete_set(Paiement)
|
||||||
def del_paiement(request, instances):
|
def del_paiement(request, instances):
|
||||||
"""Suppression d'un moyen de paiement"""
|
"""Suppression d'un moyen de paiement"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
paiement = DelPaiementForm(request.POST or None, instances=instances)
|
paiement = DelPaiementForm(request.POST or None, instances=instances)
|
||||||
if paiement.is_valid():
|
if paiement.is_valid():
|
||||||
paiement_dels = paiement.cleaned_data['paiements']
|
paiement_dels = paiement.cleaned_data['paiements']
|
||||||
|
@ -380,67 +441,97 @@ def del_paiement(request, instances):
|
||||||
paiement_del.delete()
|
paiement_del.delete()
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
"Le moyen de paiement a été supprimé"
|
_("The payment method %(method_name)s has been \
|
||||||
|
successfully deleted") % {
|
||||||
|
method_name: paiement_del
|
||||||
|
}
|
||||||
)
|
)
|
||||||
except ProtectedError:
|
except ProtectedError:
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"Le moyen de paiement %s est affecté à au moins une\
|
_("The payment method %(method_name) can't be deleted \
|
||||||
facture, vous ne pouvez pas le supprimer" % paiement_del
|
because there are invoices using it.") % {
|
||||||
|
method_name: paiement_del
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return redirect(reverse('cotisations:index-paiement'))
|
return redirect(reverse('cotisations:index-paiement'))
|
||||||
return form({'factureform': paiement, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
return form({'factureform': paiement, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change banque to bank
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(Banque)
|
@can_create(Banque)
|
||||||
def add_banque(request):
|
def add_banque(request):
|
||||||
"""Ajoute une banque à la liste des banques"""
|
"""Ajoute une banque à la liste des banques"""
|
||||||
|
# TODO : tranlate docstring to English
|
||||||
banque = BanqueForm(request.POST or None)
|
banque = BanqueForm(request.POST or None)
|
||||||
if banque.is_valid():
|
if banque.is_valid():
|
||||||
banque.save()
|
banque.save()
|
||||||
messages.success(request, "La banque a été ajoutée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The bank has been successfully created.")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-banque'))
|
return redirect(reverse('cotisations:index-banque'))
|
||||||
return form({'factureform': banque, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
return form({'factureform': banque, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change banque to bank
|
||||||
@login_required
|
@login_required
|
||||||
@can_edit(Banque)
|
@can_edit(Banque)
|
||||||
def edit_banque(request, banque_instance, banqueid):
|
def edit_banque(request, banque_instance, banqueid):
|
||||||
"""Edite le nom d'une banque"""
|
"""Edite le nom d'une banque"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
banque = BanqueForm(request.POST or None, instance=banque_instance)
|
banque = BanqueForm(request.POST or None, instance=banque_instance)
|
||||||
if banque.is_valid():
|
if banque.is_valid():
|
||||||
if banque.changed_data:
|
if banque.changed_data:
|
||||||
banque.save()
|
banque.save()
|
||||||
messages.success(request, "Banque modifiée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The bank has been successfully edited")
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-banque'))
|
return redirect(reverse('cotisations:index-banque'))
|
||||||
return form({'factureform': banque, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
return form({'factureform': banque, 'action_name' : 'Editer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : chnage banque to bank
|
||||||
@login_required
|
@login_required
|
||||||
@can_delete_set(Banque)
|
@can_delete_set(Banque)
|
||||||
def del_banque(request, instances):
|
def del_banque(request, instances):
|
||||||
"""Supprime une banque"""
|
"""Supprime une banque"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
banque = DelBanqueForm(request.POST or None, instances=instances)
|
banque = DelBanqueForm(request.POST or None, instances=instances)
|
||||||
if banque.is_valid():
|
if banque.is_valid():
|
||||||
banque_dels = banque.cleaned_data['banques']
|
banque_dels = banque.cleaned_data['banques']
|
||||||
for banque_del in banque_dels:
|
for banque_del in banque_dels:
|
||||||
try:
|
try:
|
||||||
banque_del.delete()
|
banque_del.delete()
|
||||||
messages.success(request, "La banque a été supprimée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The bank %(bank_name)s has been successfully \
|
||||||
|
deleted.") % {
|
||||||
|
bank_name: banque_del
|
||||||
|
}
|
||||||
|
)
|
||||||
except ProtectedError:
|
except ProtectedError:
|
||||||
messages.error(request, "La banque %s est affectée à au moins\
|
messages.error(
|
||||||
une facture, vous ne pouvez pas la supprimer" % banque_del)
|
request,
|
||||||
|
_("The bank %(bank_name)s can't be deleted \
|
||||||
|
because there are invoices using it.") % {
|
||||||
|
bank_name: banque_del
|
||||||
|
}
|
||||||
|
)
|
||||||
return redirect(reverse('cotisations:index-banque'))
|
return redirect(reverse('cotisations:index-banque'))
|
||||||
return form({'factureform': banque, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
return form({'factureform': banque, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(Facture)
|
@can_view_all(Facture)
|
||||||
@can_change(Facture, 'control')
|
@can_change(Facture, 'control')
|
||||||
def control(request):
|
def control(request):
|
||||||
"""Pour le trésorier, vue pour controler en masse les
|
"""Pour le trésorier, vue pour controler en masse les
|
||||||
factures.Case à cocher, pratique"""
|
factures.Case à cocher, pratique"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
||||||
facture_list = Facture.objects.select_related('user').select_related('paiement')
|
facture_list = Facture.objects.select_related('user').select_related('paiement')
|
||||||
facture_list = SortTable.sort(
|
facture_list = SortTable.sort(
|
||||||
|
@ -470,26 +561,31 @@ def control(request):
|
||||||
@can_view_all(Article)
|
@can_view_all(Article)
|
||||||
def index_article(request):
|
def index_article(request):
|
||||||
"""Affiche l'ensemble des articles en vente"""
|
"""Affiche l'ensemble des articles en vente"""
|
||||||
|
# TODO : translate docstrign to English
|
||||||
article_list = Article.objects.order_by('name')
|
article_list = Article.objects.order_by('name')
|
||||||
return render(request, 'cotisations/index_article.html', {
|
return render(request, 'cotisations/index_article.html', {
|
||||||
'article_list': article_list
|
'article_list': article_list
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change paiement to payment
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(Paiement)
|
@can_view_all(Paiement)
|
||||||
def index_paiement(request):
|
def index_paiement(request):
|
||||||
"""Affiche l'ensemble des moyens de paiement en vente"""
|
"""Affiche l'ensemble des moyens de paiement en vente"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
paiement_list = Paiement.objects.order_by('moyen')
|
paiement_list = Paiement.objects.order_by('moyen')
|
||||||
return render(request, 'cotisations/index_paiement.html', {
|
return render(request, 'cotisations/index_paiement.html', {
|
||||||
'paiement_list': paiement_list
|
'paiement_list': paiement_list
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change banque to bank
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(Banque)
|
@can_view_all(Banque)
|
||||||
def index_banque(request):
|
def index_banque(request):
|
||||||
"""Affiche l'ensemble des banques"""
|
"""Affiche l'ensemble des banques"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
banque_list = Banque.objects.order_by('name')
|
banque_list = Banque.objects.order_by('name')
|
||||||
return render(request, 'cotisations/index_banque.html', {
|
return render(request, 'cotisations/index_banque.html', {
|
||||||
'banque_list': banque_list
|
'banque_list': banque_list
|
||||||
|
@ -500,6 +596,7 @@ def index_banque(request):
|
||||||
@can_view_all(Facture)
|
@can_view_all(Facture)
|
||||||
def index(request):
|
def index(request):
|
||||||
"""Affiche l'ensemble des factures, pour les cableurs et +"""
|
"""Affiche l'ensemble des factures, pour les cableurs et +"""
|
||||||
|
# TODO : translate docstring to English
|
||||||
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
||||||
facture_list = Facture.objects.select_related('user')\
|
facture_list = Facture.objects.select_related('user')\
|
||||||
.select_related('paiement').prefetch_related('vente_set')
|
.select_related('paiement').prefetch_related('vente_set')
|
||||||
|
@ -515,6 +612,7 @@ def index(request):
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
def new_facture_solde(request, userid):
|
def new_facture_solde(request, userid):
|
||||||
"""Creation d'une facture pour un user. Renvoie la liste des articles
|
"""Creation d'une facture pour un user. Renvoie la liste des articles
|
||||||
|
@ -524,10 +622,12 @@ def new_facture_solde(request, userid):
|
||||||
enfin sauve la facture parente.
|
enfin sauve la facture parente.
|
||||||
TODO : simplifier cette fonction, déplacer l'intelligence coté models
|
TODO : simplifier cette fonction, déplacer l'intelligence coté models
|
||||||
Facture et Vente."""
|
Facture et Vente."""
|
||||||
|
# TODO : translate docstring to English
|
||||||
user = request.user
|
user = request.user
|
||||||
facture = Facture(user=user)
|
facture = Facture(user=user)
|
||||||
paiement, _created = Paiement.objects.get_or_create(moyen='Solde')
|
paiement, _created = Paiement.objects.get_or_create(moyen='Solde')
|
||||||
facture.paiement = paiement
|
facture.paiement = paiement
|
||||||
|
# TODO : translate comments to English
|
||||||
# Le template a besoin de connaitre les articles pour le js
|
# Le template a besoin de connaitre les articles pour le js
|
||||||
article_list = Article.objects.filter(
|
article_list = Article.objects.filter(
|
||||||
Q(type_user='All') | Q(type_user=request.user.class_name)
|
Q(type_user='All') | Q(type_user=request.user.class_name)
|
||||||
|
@ -551,8 +651,10 @@ def new_facture_solde(request, userid):
|
||||||
prix_total += art_item.cleaned_data['article']\
|
prix_total += art_item.cleaned_data['article']\
|
||||||
.prix*art_item.cleaned_data['quantity']
|
.prix*art_item.cleaned_data['quantity']
|
||||||
if float(user.solde) - float(prix_total) < solde_negatif:
|
if float(user.solde) - float(prix_total) < solde_negatif:
|
||||||
messages.error(request, "Le solde est insuffisant pour\
|
messages.error(
|
||||||
effectuer l'opération")
|
request,
|
||||||
|
_("The balance is too low for this operation.")
|
||||||
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': userid}
|
kwargs={'userid': userid}
|
||||||
|
@ -575,20 +677,24 @@ def new_facture_solde(request, userid):
|
||||||
for art_item in articles if art_item.cleaned_data):
|
for art_item in articles if art_item.cleaned_data):
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
"La cotisation a été prolongée\
|
_("The balance of %(member_name)s has been successfully \
|
||||||
pour l'adhérent %s jusqu'au %s" % (
|
extended to %(end_date)s") % {
|
||||||
user.pseudo, user.end_adhesion()
|
member_name: user.pseudo,
|
||||||
)
|
end_date: user.end_adhesion()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.success(request, "La facture a été crée")
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been successuflly created.")
|
||||||
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
kwargs={'userid': userid}
|
kwargs={'userid': userid}
|
||||||
))
|
))
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
u"Il faut au moins un article valide pour créer une facture"
|
_("You need to choose at least one article.")
|
||||||
)
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
|
@ -601,12 +707,13 @@ def new_facture_solde(request, userid):
|
||||||
}, 'cotisations/new_facture_solde.html', request)
|
}, 'cotisations/new_facture_solde.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change recharge to reload
|
||||||
@login_required
|
@login_required
|
||||||
def recharge(request):
|
def recharge(request):
|
||||||
if AssoOption.get_cached_value('payment') == 'NONE':
|
if AssoOption.get_cached_value('payment') == 'NONE':
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"Le paiement en ligne est désactivé."
|
_("Online payment is disabled.")
|
||||||
)
|
)
|
||||||
return redirect(reverse(
|
return redirect(reverse(
|
||||||
'users:profil',
|
'users:profil',
|
||||||
|
|
Loading…
Reference in a new issue