mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-27 07:02:26 +00:00
Utilisation de django field permission sur le controle facture
This commit is contained in:
parent
da382fbeb6
commit
784ef5d598
4 changed files with 107 additions and 23 deletions
|
@ -43,6 +43,8 @@ from django.forms import ModelForm, Form
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from .models import Article, Paiement, Facture, Banque
|
from .models import Article, Paiement, Facture, Banque
|
||||||
|
|
||||||
|
from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
|
|
||||||
|
|
||||||
class NewFactureForm(ModelForm):
|
class NewFactureForm(ModelForm):
|
||||||
"""Creation d'une facture, moyen de paiement, banque et numero
|
"""Creation d'une facture, moyen de paiement, banque et numero
|
||||||
|
@ -141,27 +143,18 @@ class NewFactureFormPdf(Form):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EditFactureForm(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"""
|
||||||
class Meta(NewFactureForm.Meta):
|
class Meta(NewFactureForm.Meta):
|
||||||
fields = ['paiement', 'banque', 'cheque', 'user']
|
model = Facture
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(EditFactureForm, self).__init__(*args, **kwargs)
|
super(EditFactureForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['user'].label = 'Adherent'
|
self.fields['user'].label = 'Adherent'
|
||||||
self.fields['user'].empty_label = "Séléctionner\
|
self.fields['user'].empty_label = "Séléctionner\
|
||||||
l'adhérent propriétaire"
|
l'adhérent propriétaire"
|
||||||
|
|
||||||
|
|
||||||
class TrezEditFactureForm(EditFactureForm):
|
|
||||||
"""Vue pour édition controle trésorier"""
|
|
||||||
class Meta(EditFactureForm.Meta):
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(TrezEditFactureForm, self).__init__(*args, **kwargs)
|
|
||||||
self.fields['valid'].label = 'Validité de la facture'
|
self.fields['valid'].label = 'Validité de la facture'
|
||||||
self.fields['control'].label = 'Contrôle de la facture'
|
|
||||||
|
|
||||||
|
|
||||||
class ArticleForm(ModelForm):
|
class ArticleForm(ModelForm):
|
||||||
|
|
|
@ -56,8 +56,10 @@ 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 re2o.field_permissions import FieldPermissionModelMixin
|
||||||
|
|
||||||
class Facture(models.Model):
|
|
||||||
|
class Facture(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
|
||||||
|
@ -76,6 +78,9 @@ class Facture(models.Model):
|
||||||
valid = models.BooleanField(default=True)
|
valid = models.BooleanField(default=True)
|
||||||
control = models.BooleanField(default=False)
|
control = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = False
|
||||||
|
|
||||||
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"""
|
||||||
|
@ -144,12 +149,16 @@ class Facture(models.Model):
|
||||||
else:
|
else:
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
def can_change_control(user_request, *args, **kwargs):
|
def can_change_control(user, *args, **kwargs):
|
||||||
return user_request.has_perms(('tresorier',)), "Vous ne pouvez pas éditer le controle sans droit trésorier"
|
return user.has_perms(('tresorier',)), "Vous ne pouvez pas éditer le controle sans droit trésorier"
|
||||||
|
|
||||||
def can_change_pdf(user_request, *args, **kwargs):
|
def can_change_pdf(user_request, *args, **kwargs):
|
||||||
return user_request.has_perms(('tresorier',)), "Vous ne pouvez pas éditer une facture sans droit trésorier"
|
return user_request.has_perms(('tresorier',)), "Vous ne pouvez pas éditer une facture sans droit trésorier"
|
||||||
|
|
||||||
|
field_permissions = {
|
||||||
|
'control': can_change_control,
|
||||||
|
}
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.user) + ' ' + str(self.date)
|
return str(self.user) + ' ' + str(self.date)
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ from preferences.models import OptionalUser, AssoOption, GeneralOption
|
||||||
from .models import Facture, Article, Vente, Paiement, Banque
|
from .models import Facture, Article, Vente, Paiement, Banque
|
||||||
from .forms import (
|
from .forms import (
|
||||||
NewFactureForm,
|
NewFactureForm,
|
||||||
TrezEditFactureForm,
|
|
||||||
EditFactureForm,
|
EditFactureForm,
|
||||||
ArticleForm,
|
ArticleForm,
|
||||||
DelArticleForm,
|
DelArticleForm,
|
||||||
|
@ -73,6 +72,7 @@ from .forms import (
|
||||||
from .tex import render_invoice
|
from .tex import render_invoice
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(Facture)
|
@can_create(Facture)
|
||||||
@can_edit(User)
|
@can_edit(User)
|
||||||
|
@ -243,13 +243,7 @@ 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"""
|
||||||
if request.user.has_perms(['tresorier']):
|
facture_form = EditFactureForm(request.POST or None, instance=facture, user=request.user)
|
||||||
facture_form = TrezEditFactureForm(
|
|
||||||
request.POST or None,
|
|
||||||
instance=facture
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
facture_form = EditFactureForm(request.POST or None, instance=facture)
|
|
||||||
ventes_objects = Vente.objects.filter(facture=facture)
|
ventes_objects = Vente.objects.filter(facture=facture)
|
||||||
vente_form_set = modelformset_factory(
|
vente_form_set = modelformset_factory(
|
||||||
Vente,
|
Vente,
|
||||||
|
|
88
re2o/field_permissions.py
Normal file
88
re2o/field_permissions.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
from django.db import models
|
||||||
|
from django import forms
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
|
class FieldPermissionModelMixin:
|
||||||
|
field_permissions = {} # {'field_name': callable}
|
||||||
|
FIELD_PERM_CODENAME = 'can_change_{model}_{name}'
|
||||||
|
FIELD_PERMISSION_GETTER = 'can_change_{name}'
|
||||||
|
FIELD_PERMISSION_MISSING_DEFAULT = True
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
def has_perm(self, user, perm):
|
||||||
|
return user.has_perm(perm) # Never give 'obj' argument here
|
||||||
|
|
||||||
|
def has_field_perm(self, user, field):
|
||||||
|
if field in self.field_permissions:
|
||||||
|
checks = self.field_permissions[field]
|
||||||
|
if not isinstance(checks, (list, tuple)):
|
||||||
|
checks = [checks]
|
||||||
|
for i, perm in enumerate(checks):
|
||||||
|
if callable(perm):
|
||||||
|
checks[i] = partial(perm, field=field)
|
||||||
|
|
||||||
|
else:
|
||||||
|
checks = []
|
||||||
|
|
||||||
|
# Consult the optional field-specific hook.
|
||||||
|
getter_name = self.FIELD_PERMISSION_GETTER.format(name=field)
|
||||||
|
if hasattr(self, getter_name):
|
||||||
|
checks.append(getattr(self, getter_name))
|
||||||
|
|
||||||
|
# Try to find a static permission for the field
|
||||||
|
else:
|
||||||
|
perm_label = self.FIELD_PERM_CODENAME.format(**{
|
||||||
|
'model': self._meta.model_name,
|
||||||
|
'name': field,
|
||||||
|
})
|
||||||
|
if perm_label in dict(self._meta.permissions):
|
||||||
|
checks.append(perm_label)
|
||||||
|
|
||||||
|
# No requirements means no restrictions.
|
||||||
|
if not len(checks):
|
||||||
|
return self.FIELD_PERMISSION_MISSING_DEFAULT
|
||||||
|
|
||||||
|
# Try to find a user setting that qualifies them for permission.
|
||||||
|
for perm in checks:
|
||||||
|
if callable(perm):
|
||||||
|
result, plop = perm(user=user)
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
result = user.has_perm(perm) # Don't supply 'obj', or else infinite recursion.
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If no requirement can be met, then permission is denied.
|
||||||
|
return False
|
||||||
|
|
||||||
|
class FieldPermissionModel(FieldPermissionModelMixin, models.Model):
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class FieldPermissionFormMixin:
|
||||||
|
"""
|
||||||
|
ModelForm logic for removing fields when a user is found not to have change permissions.
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
user = kwargs.pop('user')
|
||||||
|
|
||||||
|
super(FieldPermissionFormMixin, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
model = self.Meta.model
|
||||||
|
model_field_names = [f.name for f in model._meta.get_fields()] # this might be too broad
|
||||||
|
for name in model_field_names:
|
||||||
|
if name in self.fields and not self.instance.has_field_perm(user, field=name):
|
||||||
|
self.remove_unauthorized_field(name)
|
||||||
|
|
||||||
|
def remove_unauthorized_field(self, name):
|
||||||
|
del self.fields[name]
|
||||||
|
|
||||||
|
|
||||||
|
class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm):
|
||||||
|
pass
|
||||||
|
|
Loading…
Reference in a new issue