Correction sur la validation dans K-Psul

- Validation d'un OperationGroup par le form associé et sa méthode
  is_valid
- Validation d'une Operation par la méthode clean() du form associé
  selon le type d'opération effectuée
This commit is contained in:
Aurélien Delobelle 2016-08-07 17:02:01 +02:00
parent fdb105ab84
commit 5ff7ee51b3
3 changed files with 54 additions and 27 deletions

View file

@ -1,4 +1,5 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError
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 kfet.models import Account, Checkout, Article, OperationGroup, Operation from kfet.models import Account, Checkout, Article, OperationGroup, Operation
@ -114,12 +115,14 @@ class ArticleRestrictForm(ArticleForm):
# ----- # -----
class KPsulOperationGroupForm(forms.ModelForm): class KPsulOperationGroupForm(forms.ModelForm):
checkout = forms.ModelChoiceField(
queryset = Checkout.objects.filter(is_protected=False),
widget = forms.HiddenInput())
class Meta: class Meta:
model = OperationGroup model = OperationGroup
fields = ['on_acc', 'checkout'] fields = ['on_acc', 'checkout']
widgets = { widgets = {
'on_acc' : forms.HiddenInput(), 'on_acc' : forms.HiddenInput(),
'checkout': forms.HiddenInput(),
} }
class KPsulAccountForm(forms.ModelForm): class KPsulAccountForm(forms.ModelForm):
@ -140,8 +143,30 @@ class KPsulOperationForm(forms.ModelForm):
model = Operation model = Operation
fields = ['type', 'amount', 'is_checkout', 'article', 'article_nb'] fields = ['type', 'amount', 'is_checkout', 'article', 'article_nb']
def clean(self):
super(KPsulOperationForm, self).clean()
type_ope = self.cleaned_data.get('type')
amount = self.cleaned_data.get('amount')
article = self.cleaned_data.get('article')
article_nb = self.cleaned_data.get('article_nb')
if type_ope and type_ope == Operation.PURCHASE:
if not article or not article_nb:
raise ValidationError(
"Un achat nécessite un article et une quantité")
if article_nb < 1:
raise ValidationError("Impossible d'acheter moins de 1 article")
self.cleaned_data['amount'] = article.price * article_nb
self.cleaned_data['is_checkout'] = True
elif type_ope and type_ope in [Operation.DEPOSIT, Operation.WITHDRAW]:
if not amount or article or article_nb:
raise ValidationError("Bad request")
if type_ope == Operation.DEPOSIT and amount <= 0:
raise ValidationError("Charge non positive")
if type_ope == Operation.WITHDRAW and amount >= 0:
raise ValidationError("Retrait non négatif")
KPsulOperationFormSet = modelformset_factory( KPsulOperationFormSet = modelformset_factory(
Operation, Operation,
form = KPsulOperationForm, form = KPsulOperationForm,
extra = 0, extra = 0,
min_num = 1, validate_min = True) min_num = 1, validate_min = True)

View file

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied, ValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from gestioncof.models import CofProfile from gestioncof.models import CofProfile
from django.utils.six.moves import reduce from django.utils.six.moves import reduce
@ -186,9 +186,6 @@ class Checkout(models.Model):
class Meta: class Meta:
ordering = ['-valid_to'] ordering = ['-valid_to']
class IsProtected(Exception):
pass
def __str__(self): def __str__(self):
return self.name return self.name
@ -388,7 +385,9 @@ class Operation(models.Model):
type = models.CharField( type = models.CharField(
choices = TYPE_ORDER_CHOICES, choices = TYPE_ORDER_CHOICES,
max_length = choices_length(TYPE_ORDER_CHOICES)) max_length = choices_length(TYPE_ORDER_CHOICES))
amount = models.DecimalField(max_digits = 6, decimal_places = 2) amount = models.DecimalField(
max_digits = 6, decimal_places = 2,
blank = True, default = 0)
is_checkout = models.BooleanField(default = True) is_checkout = models.BooleanField(default = True)
# Optional # Optional
article = models.ForeignKey( article = models.ForeignKey(
@ -411,6 +410,10 @@ class Operation(models.Model):
max_digits = 6, decimal_places = 2, max_digits = 6, decimal_places = 2,
default = 0) default = 0)
def save(self, *args, **kwargs):
#self.full_clean()
return super(Operation, self).save(*args, **kwargs)
class GlobalPermissions(models.Model): class GlobalPermissions(models.Model):
class Meta: class Meta:
managed = False managed = False

View file

@ -1,5 +1,5 @@
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied, ValidationError
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
@ -385,32 +385,31 @@ def kpsul_checkout_data(request):
@permission_required('kfet.is_team') @permission_required('kfet.is_team')
def kpsul_perform_operations(request): def kpsul_perform_operations(request):
# Initializing # Initializing response data
data = defaultdict(list) data = defaultdict(list)
# Checking operationgroup data # Checking operationgroup
try: operationgroup_form = KPsulOperationGroupForm(request.POST)
account_pk = request.POST.get('on_acc', 0) if not operationgroup_form.is_valid():
account = Account.objects.get(pk=account_pk) data['errors'].append({'operation_group': list(operationgroup_form.errors)})
except (Account.DoesNotExist, ValueError):
data['errors'].append('Trigramme invalide') # Checking operation_formset
try: operation_formset = KPsulOperationFormSet(request.POST)
checkout_pk = request.POST.get('checkout', 0) if not operation_formset.is_valid():
checkout = Checkout.objects.get(pk=checkout_pk) data['errors'].append({'operations': list(operation_formset.errors) })
if checkout.is_protected:
raise Checkout.IsProtected # Returning bad request if errors
except (Checkout.DoesNotExist, ValueError, Checkout.IsProtected):
data['errors'].append('Caisse invalide')
if 'errors' in data: if 'errors' in data:
return JsonResponse(data, status=400) return JsonResponse(data, status=400)
operationgroup_form = KPsulOperationGroupForm(request.POST) # Pre-saving
operationgroup = operationgroup_form.save(commit = False) operationgroup = operationgroup_form.save(commit = False)
operation_formset = KPsulOperationFormSet(request.POST) operations = operation_formset.save(commit = False)
operations = operation_formset.save(commit = False)
for operation in operations: for operation in operations:
operationgroup.amount += operation.amount operationgroup.amount += operation.amount
operationgroup.save() operationgroup.save()
data['operationgroup'] = operationgroup.pk data['operationgroup'] = operationgroup.pk
for operation in operations: for operation in operations:
operation.group = operationgroup operation.group = operationgroup