forked from DGNum/gestioCOF
Merge branch 'aureplop/kfet-tests_perform_operations' into 'master'
kfet.tests -- Add tests for perform_operations view + small things See merge request cof-geek/gestioCOF!313
This commit is contained in:
commit
39abfceb76
4 changed files with 1482 additions and 23 deletions
|
@ -1,25 +1,39 @@
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from djconfig import config
|
import djconfig
|
||||||
|
|
||||||
|
|
||||||
class KFetConfig(object):
|
class KFetConfig(object):
|
||||||
"""kfet app configuration.
|
"""kfet app configuration.
|
||||||
|
|
||||||
Enhance isolation with backend used to store config.
|
Enhance isolation with backend used to store config.
|
||||||
Usable after DjConfig middleware was called.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
prefix = 'kfet_'
|
prefix = 'kfet_'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Set this to False again to reload the config, e.g for testing
|
||||||
|
# purposes.
|
||||||
|
self._conf_init = False
|
||||||
|
|
||||||
|
def _check_init(self):
|
||||||
|
# For initialization purposes, we call 'reload_maybe' directly
|
||||||
|
# (normaly done once per request in middleware).
|
||||||
|
# Note it should be called only once across requests, if you use
|
||||||
|
# kfet_config instance below.
|
||||||
|
if not self._conf_init:
|
||||||
|
djconfig.reload_maybe()
|
||||||
|
self._conf_init = True
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
|
self._check_init()
|
||||||
if key == 'subvention_cof':
|
if key == 'subvention_cof':
|
||||||
# Allows accessing to the reduction as a subvention
|
# Allows accessing to the reduction as a subvention
|
||||||
# Other reason: backward compatibility
|
# Other reason: backward compatibility
|
||||||
reduction_mult = 1 - self.reduction_cof/100
|
reduction_mult = 1 - self.reduction_cof/100
|
||||||
return (1/reduction_mult - 1) * 100
|
return (1/reduction_mult - 1) * 100
|
||||||
return getattr(config, self._get_dj_key(key))
|
return getattr(djconfig.config, self._get_dj_key(key))
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""Get list of kfet app configuration.
|
"""Get list of kfet app configuration.
|
||||||
|
@ -30,7 +44,8 @@ class KFetConfig(object):
|
||||||
"""
|
"""
|
||||||
# prevent circular imports
|
# prevent circular imports
|
||||||
from kfet.forms import KFetConfigForm
|
from kfet.forms import KFetConfigForm
|
||||||
return [(field.label, getattr(config, name), )
|
self._check_init()
|
||||||
|
return [(field.label, getattr(djconfig.config, name), )
|
||||||
for name, field in KFetConfigForm.base_fields.items()]
|
for name, field in KFetConfigForm.base_fields.items()]
|
||||||
|
|
||||||
def _get_dj_key(self, key):
|
def _get_dj_key(self, key):
|
||||||
|
@ -47,6 +62,7 @@ class KFetConfig(object):
|
||||||
# prevent circular imports
|
# prevent circular imports
|
||||||
from kfet.forms import KFetConfigForm
|
from kfet.forms import KFetConfigForm
|
||||||
|
|
||||||
|
self._check_init()
|
||||||
# get old config
|
# get old config
|
||||||
new_cfg = KFetConfigForm().initial
|
new_cfg = KFetConfigForm().initial
|
||||||
# update to new config
|
# update to new config
|
||||||
|
|
|
@ -3,6 +3,7 @@ from decimal import Decimal
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.core import validators
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.forms import modelformset_factory
|
from django.forms import modelformset_factory
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -273,6 +274,10 @@ class ArticleRestrictForm(ArticleForm):
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
class KPsulOperationGroupForm(forms.ModelForm):
|
class KPsulOperationGroupForm(forms.ModelForm):
|
||||||
|
# FIXME(AD): Use timezone.now instead of timezone.now() to avoid using a
|
||||||
|
# fixed datetime (application boot here).
|
||||||
|
# One may even use: Checkout.objects.is_valid() if changing
|
||||||
|
# to now = timezone.now is ok in 'is_valid' definition.
|
||||||
checkout = forms.ModelChoiceField(
|
checkout = forms.ModelChoiceField(
|
||||||
queryset = Checkout.objects.filter(
|
queryset = Checkout.objects.filter(
|
||||||
is_protected=False, valid_from__lte=timezone.now(),
|
is_protected=False, valid_from__lte=timezone.now(),
|
||||||
|
@ -317,13 +322,18 @@ class KPsulOperationForm(forms.ModelForm):
|
||||||
queryset=Article.objects.select_related('category').all(),
|
queryset=Article.objects.select_related('category').all(),
|
||||||
required=False,
|
required=False,
|
||||||
widget = forms.HiddenInput())
|
widget = forms.HiddenInput())
|
||||||
|
article_nb = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
initial=None,
|
||||||
|
validators=[validators.MinValueValidator(1)],
|
||||||
|
widget=forms.HiddenInput(),
|
||||||
|
)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Operation
|
model = Operation
|
||||||
fields = ['type', 'amount', 'article', 'article_nb']
|
fields = ['type', 'amount', 'article', 'article_nb']
|
||||||
widgets = {
|
widgets = {
|
||||||
'type': forms.HiddenInput(),
|
'type': forms.HiddenInput(),
|
||||||
'amount': forms.HiddenInput(),
|
'amount': forms.HiddenInput(),
|
||||||
'article_nb': forms.HiddenInput(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
@ -332,22 +342,26 @@ class KPsulOperationForm(forms.ModelForm):
|
||||||
amount = self.cleaned_data.get('amount')
|
amount = self.cleaned_data.get('amount')
|
||||||
article = self.cleaned_data.get('article')
|
article = self.cleaned_data.get('article')
|
||||||
article_nb = self.cleaned_data.get('article_nb')
|
article_nb = self.cleaned_data.get('article_nb')
|
||||||
|
errors = []
|
||||||
if type_ope and type_ope == Operation.PURCHASE:
|
if type_ope and type_ope == Operation.PURCHASE:
|
||||||
if not article or not article_nb:
|
if not article or article_nb is None or article_nb < 1:
|
||||||
raise ValidationError(
|
errors.append(ValidationError(
|
||||||
"Un achat nécessite un article et une quantité")
|
"Un achat nécessite un article et une quantité"))
|
||||||
if article_nb < 1:
|
|
||||||
raise ValidationError("Impossible d'acheter moins de 1 article")
|
|
||||||
elif type_ope and type_ope in [Operation.DEPOSIT, Operation.WITHDRAW]:
|
elif type_ope and type_ope in [Operation.DEPOSIT, Operation.WITHDRAW]:
|
||||||
if not amount or article or article_nb:
|
if not amount or article or article_nb:
|
||||||
raise ValidationError("Bad request")
|
errors.append(ValidationError("Bad request"))
|
||||||
if type_ope == Operation.DEPOSIT and amount <= 0:
|
else:
|
||||||
raise ValidationError("Charge non positive")
|
if type_ope == Operation.DEPOSIT and amount <= 0:
|
||||||
if type_ope == Operation.WITHDRAW and amount >= 0:
|
errors.append(ValidationError("Charge non positive"))
|
||||||
raise ValidationError("Retrait non négatif")
|
elif type_ope == Operation.WITHDRAW and amount >= 0:
|
||||||
|
errors.append(ValidationError("Retrait non négatif"))
|
||||||
self.cleaned_data['article'] = None
|
self.cleaned_data['article'] = None
|
||||||
self.cleaned_data['article_nb'] = None
|
self.cleaned_data['article_nb'] = None
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
raise ValidationError(errors)
|
||||||
|
|
||||||
|
|
||||||
KPsulOperationFormSet = modelformset_factory(
|
KPsulOperationFormSet = modelformset_factory(
|
||||||
Operation,
|
Operation,
|
||||||
form = KPsulOperationForm,
|
form = KPsulOperationForm,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -178,7 +178,9 @@ class ViewTestCaseMixin(TestCaseMixin):
|
||||||
During setup, three users are created with their kfet account:
|
During setup, three users are created with their kfet account:
|
||||||
- 'user': a basic user without any permission, account trigramme: 000,
|
- 'user': a basic user without any permission, account trigramme: 000,
|
||||||
- 'team': a user with kfet.is_team permission, account trigramme: 100,
|
- 'team': a user with kfet.is_team permission, account trigramme: 100,
|
||||||
- 'root': a superuser, account trigramme: 200.
|
- 'root': a superuser, account trigramme: 200,
|
||||||
|
- 'liq': if class attribute 'with_liq' is 'True', account
|
||||||
|
trigramme: LIQ.
|
||||||
Their password is their username.
|
Their password is their username.
|
||||||
|
|
||||||
One can create additionnal users with 'get_users_extra' method, or prevent
|
One can create additionnal users with 'get_users_extra' method, or prevent
|
||||||
|
@ -221,6 +223,8 @@ class ViewTestCaseMixin(TestCaseMixin):
|
||||||
auth_user = None
|
auth_user = None
|
||||||
auth_forbidden = []
|
auth_forbidden = []
|
||||||
|
|
||||||
|
with_liq = False
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""
|
"""
|
||||||
Warning: Do not forget to call super().setUp() in subclasses.
|
Warning: Do not forget to call super().setUp() in subclasses.
|
||||||
|
@ -262,7 +266,7 @@ class ViewTestCaseMixin(TestCaseMixin):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Format desc: username, password, trigramme
|
# Format desc: username, password, trigramme
|
||||||
return {
|
users_base = {
|
||||||
# user, user, 000
|
# user, user, 000
|
||||||
'user': create_user(),
|
'user': create_user(),
|
||||||
# team, team, 100
|
# team, team, 100
|
||||||
|
@ -270,6 +274,9 @@ class ViewTestCaseMixin(TestCaseMixin):
|
||||||
# root, root, 200
|
# root, root, 200
|
||||||
'root': create_root(),
|
'root': create_root(),
|
||||||
}
|
}
|
||||||
|
if self.with_liq:
|
||||||
|
users_base['liq'] = create_user('liq', 'LIQ')
|
||||||
|
return users_base
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def users_base(self):
|
def users_base(self):
|
||||||
|
|
Loading…
Reference in a new issue