From 5ff7ee51b37e0cceec0b3c6e71cb61d841af0714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sun, 7 Aug 2016 17:02:01 +0200 Subject: [PATCH] Correction sur la validation dans K-Psul MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- kfet/forms.py | 31 ++++++++++++++++++++++++++++--- kfet/models.py | 13 ++++++++----- kfet/views.py | 37 ++++++++++++++++++------------------- 3 files changed, 54 insertions(+), 27 deletions(-) diff --git a/kfet/forms.py b/kfet/forms.py index 021b8411..4ba5f7c1 100644 --- a/kfet/forms.py +++ b/kfet/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.core.exceptions import ValidationError from django.contrib.auth.models import User from django.forms import modelformset_factory from kfet.models import Account, Checkout, Article, OperationGroup, Operation @@ -114,12 +115,14 @@ class ArticleRestrictForm(ArticleForm): # ----- class KPsulOperationGroupForm(forms.ModelForm): + checkout = forms.ModelChoiceField( + queryset = Checkout.objects.filter(is_protected=False), + widget = forms.HiddenInput()) class Meta: model = OperationGroup fields = ['on_acc', 'checkout'] widgets = { 'on_acc' : forms.HiddenInput(), - 'checkout': forms.HiddenInput(), } class KPsulAccountForm(forms.ModelForm): @@ -140,8 +143,30 @@ class KPsulOperationForm(forms.ModelForm): model = Operation 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( Operation, - form = KPsulOperationForm, - extra = 0, + form = KPsulOperationForm, + extra = 0, min_num = 1, validate_min = True) diff --git a/kfet/models.py b/kfet/models.py index ff69d0fa..d74eeb7b 100644 --- a/kfet/models.py +++ b/kfet/models.py @@ -1,6 +1,6 @@ from django.db import models 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 gestioncof.models import CofProfile from django.utils.six.moves import reduce @@ -186,9 +186,6 @@ class Checkout(models.Model): class Meta: ordering = ['-valid_to'] - class IsProtected(Exception): - pass - def __str__(self): return self.name @@ -388,7 +385,9 @@ class Operation(models.Model): type = models.CharField( choices = 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) # Optional article = models.ForeignKey( @@ -411,6 +410,10 @@ class Operation(models.Model): max_digits = 6, decimal_places = 2, default = 0) + def save(self, *args, **kwargs): + #self.full_clean() + return super(Operation, self).save(*args, **kwargs) + class GlobalPermissions(models.Model): class Meta: managed = False diff --git a/kfet/views.py b/kfet/views.py index 529e6053..b3eee1f2 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1,5 +1,5 @@ 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.edit import CreateView, UpdateView, DeleteView from django.core.urlresolvers import reverse_lazy @@ -385,32 +385,31 @@ def kpsul_checkout_data(request): @permission_required('kfet.is_team') def kpsul_perform_operations(request): - # Initializing + # Initializing response data data = defaultdict(list) - # Checking operationgroup data - try: - account_pk = request.POST.get('on_acc', 0) - account = Account.objects.get(pk=account_pk) - except (Account.DoesNotExist, ValueError): - data['errors'].append('Trigramme invalide') - try: - checkout_pk = request.POST.get('checkout', 0) - checkout = Checkout.objects.get(pk=checkout_pk) - if checkout.is_protected: - raise Checkout.IsProtected - except (Checkout.DoesNotExist, ValueError, Checkout.IsProtected): - data['errors'].append('Caisse invalide') + # Checking operationgroup + operationgroup_form = KPsulOperationGroupForm(request.POST) + if not operationgroup_form.is_valid(): + data['errors'].append({'operation_group': list(operationgroup_form.errors)}) + + # Checking operation_formset + operation_formset = KPsulOperationFormSet(request.POST) + if not operation_formset.is_valid(): + data['errors'].append({'operations': list(operation_formset.errors) }) + + # Returning bad request if errors if 'errors' in data: return JsonResponse(data, status=400) - operationgroup_form = KPsulOperationGroupForm(request.POST) - operationgroup = operationgroup_form.save(commit = False) - operation_formset = KPsulOperationFormSet(request.POST) - operations = operation_formset.save(commit = False) + # Pre-saving + operationgroup = operationgroup_form.save(commit = False) + operations = operation_formset.save(commit = False) + for operation in operations: operationgroup.amount += operation.amount operationgroup.save() + data['operationgroup'] = operationgroup.pk for operation in operations: operation.group = operationgroup