# -*- coding: utf-8 -*- from __future__ import (absolute_import, division, print_function, unicode_literals) from builtins import * from decimal import Decimal from django import forms from django.core.exceptions import ValidationError from django.core.validators import MinLengthValidator from django.contrib.auth.models import User, Group, Permission from django.contrib.contenttypes.models import ContentType from django.forms import modelformset_factory, inlineformset_factory from django.forms.models import BaseInlineFormSet from django.utils import timezone from kfet.models import (Account, Checkout, Article, OperationGroup, Operation, CheckoutStatement, ArticleCategory, Settings, AccountNegative, Transfer, TransferGroup, Supplier, Inventory, InventoryArticle) from gestion.models import Profile # ----- # Widgets # ----- class DateTimeWidget(forms.DateTimeInput): def __init__(self, attrs = None): super(DateTimeWidget, self).__init__(attrs) self.attrs['format'] = '%Y-%m-%d %H:%M' class Media: css = { 'all': ('kfet/css/bootstrap-datetimepicker.min.css',) } js = ( 'kfet/js/moment.js', 'kfet/js/moment-fr.js', 'kfet/js/bootstrap-datetimepicker.min.js', ) # ----- # Account forms # ----- class AccountForm(forms.ModelForm): # Surcharge pour passer data à Account.save() def save(self, data = {}, *args, **kwargs): obj = super(AccountForm, self).save(commit = False, *args, **kwargs) obj.save(data = data) return obj class Meta: model = Account fields = ['trigramme', 'promo', 'nickname', 'is_frozen'] widgets = { 'trigramme': forms.TextInput(attrs={'autocomplete': 'off'}), } class AccountBalanceForm(forms.ModelForm): class Meta: model = Account fields = ['balance'] class AccountTriForm(AccountForm): def clean_trigramme(self): trigramme = self.cleaned_data['trigramme'] return trigramme.upper() class Meta(AccountForm.Meta): fields = ['trigramme'] class AccountNoTriForm(AccountForm): class Meta(AccountForm.Meta): exclude = ['trigramme'] class AccountRestrictForm(AccountForm): class Meta(AccountForm.Meta): fields = ['is_frozen'] class AccountPwdForm(forms.Form): pwd1 = forms.CharField( widget=forms.PasswordInput) pwd2 = forms.CharField( widget=forms.PasswordInput) def clean(self): pwd1 = self.cleaned_data.get('pwd1', '') pwd2 = self.cleaned_data.get('pwd2', '') if len(pwd1) < 8: raise ValidationError("Mot de passe trop court") if pwd1 != pwd2: raise ValidationError("Les mots de passes sont différents") super(AccountPwdForm, self).clean() class ProfileForm(forms.ModelForm): # def clean_is_cof(self): # instance = getattr(self, 'instance', None) # if instance and instance.pk: # return instance.is_cof # else: # return False class Meta: model = Profile # XXX. I am removing is_cof from here. fields = ['login_clipper', 'departement'] class ProfileRestrictForm(ProfileForm): class Meta(ProfileForm.Meta): fields = ['departement'] class UserForm(forms.ModelForm): def __init__(self, *args, **kwargs): from_clipper = kwargs.pop('from_clipper', False) new_user = kwargs.get('instance') is None and not from_clipper super(UserForm, self).__init__(*args, **kwargs) if new_user: self.fields['username'].validators = [MinLengthValidator(9)] class Meta: model = User fields = ['username', 'first_name', 'last_name', 'email'] help_texts = { 'username': '' } class UserRestrictForm(UserForm): class Meta(UserForm.Meta): fields = ['first_name', 'last_name'] class UserRestrictTeamForm(UserForm): class Meta(UserForm.Meta): fields = ['first_name', 'last_name', 'email'] class UserGroupForm(forms.ModelForm): groups = forms.ModelMultipleChoiceField( Group.objects.filter(name__icontains='K-Fêt')) class Meta: model = User fields = ['groups'] class GroupForm(forms.ModelForm): permissions = forms.ModelMultipleChoiceField( queryset= Permission.objects.filter(content_type__in= ContentType.objects.filter(app_label='kfet'))) def clean_name(self): name = self.cleaned_data['name'] return 'K-Fêt %s' % name class Meta: model = Group fields = ['name', 'permissions'] class AccountNegativeForm(forms.ModelForm): class Meta: model = AccountNegative fields = ['authz_overdraft_amount', 'authz_overdraft_until', 'balance_offset', 'comment'] widgets = { 'authz_overdraft_until': DateTimeWidget(), } # ----- # Checkout forms # ----- class CheckoutForm(forms.ModelForm): class Meta: model = Checkout fields = ['name', 'valid_from', 'valid_to', 'balance', 'is_protected'] widgets = { 'valid_from': DateTimeWidget(), 'valid_to' : DateTimeWidget(), } class CheckoutRestrictForm(CheckoutForm): class Meta(CheckoutForm.Meta): fields = ['name', 'valid_from', 'valid_to'] class CheckoutStatementCreateForm(forms.ModelForm): balance_001 = forms.IntegerField(min_value=0, initial=0, required=False) balance_002 = forms.IntegerField(min_value=0, initial=0, required=False) balance_005 = forms.IntegerField(min_value=0, initial=0, required=False) balance_01 = forms.IntegerField(min_value=0, initial=0, required=False) balance_02 = forms.IntegerField(min_value=0, initial=0, required=False) balance_05 = forms.IntegerField(min_value=0, initial=0, required=False) balance_1 = forms.IntegerField(min_value=0, initial=0, required=False) balance_2 = forms.IntegerField(min_value=0, initial=0, required=False) balance_5 = forms.IntegerField(min_value=0, initial=0, required=False) balance_10 = forms.IntegerField(min_value=0, initial=0, required=False) balance_20 = forms.IntegerField(min_value=0, initial=0, required=False) balance_50 = forms.IntegerField(min_value=0, initial=0, required=False) balance_100 = forms.IntegerField(min_value=0, initial=0, required=False) balance_200 = forms.IntegerField(min_value=0, initial=0, required=False) balance_500 = forms.IntegerField(min_value=0, initial=0, required=False) class Meta: model = CheckoutStatement exclude = ['by', 'at', 'checkout', 'amount_error', 'amount_taken', 'balance_old', 'balance_new'] def clean(self): not_count = self.cleaned_data['not_count'] if not not_count and ( self.cleaned_data['balance_001'] is None or self.cleaned_data['balance_002'] is None or self.cleaned_data['balance_005'] is None or self.cleaned_data['balance_01'] is None or self.cleaned_data['balance_02'] is None or self.cleaned_data['balance_05'] is None or self.cleaned_data['balance_1'] is None or self.cleaned_data['balance_2'] is None or self.cleaned_data['balance_5'] is None or self.cleaned_data['balance_10'] is None or self.cleaned_data['balance_20'] is None or self.cleaned_data['balance_50'] is None or self.cleaned_data['balance_100'] is None or self.cleaned_data['balance_200'] is None or self.cleaned_data['balance_500'] is None): raise ValidationError("Y'a un problème. Si tu comptes la caisse, mets au moins des 0 stp (et t'as pas idée de comment c'est long de vérifier que t'as mis des valeurs de partout...)") super(CheckoutStatementCreateForm, self).clean() class CheckoutStatementUpdateForm(forms.ModelForm): class Meta: model = CheckoutStatement exclude = ['by', 'at', 'checkout', 'amount_error', 'amount_taken'] # ----- # Article forms # ----- class ArticleForm(forms.ModelForm): category_new = forms.CharField( max_length=45, required = False) category = forms.ModelChoiceField( queryset = ArticleCategory.objects.all(), required = False) suppliers = forms.ModelMultipleChoiceField( queryset = Supplier.objects.all(), required = False) supplier_new = forms.CharField( max_length = 45, required = False) def __init__(self, *args, **kwargs): super(ArticleForm, self).__init__(*args, **kwargs) if self.instance.pk: self.initial['suppliers'] = self.instance.suppliers.values_list('pk', flat=True) def clean(self): category = self.cleaned_data.get('category') category_new = self.cleaned_data.get('category_new') if not category and not category_new: raise ValidationError('Sélectionnez une catégorie ou créez en une') elif not category: category, _ = ArticleCategory.objects.get_or_create(name=category_new) self.cleaned_data['category'] = category super(ArticleForm, self).clean() class Meta: model = Article fields = ['name', 'is_sold', 'price', 'stock', 'category', 'box_type', 'box_capacity'] class ArticleRestrictForm(ArticleForm): class Meta(ArticleForm.Meta): fields = ['name', 'is_sold', 'price', 'category', 'box_type', 'box_capacity'] # ----- # K-Psul forms # ----- class KPsulOperationGroupForm(forms.ModelForm): checkout = forms.ModelChoiceField( queryset = Checkout.objects.filter( is_protected=False, valid_from__lte=timezone.now(), valid_to__gte=timezone.now()), widget = forms.HiddenInput()) on_acc = forms.ModelChoiceField( queryset = Account.objects.exclude(trigramme='GNR'), widget = forms.HiddenInput()) class Meta: model = OperationGroup fields = ['on_acc', 'checkout', 'comment'] class KPsulAccountForm(forms.ModelForm): class Meta: model = Account fields = ['trigramme'] widgets = { 'trigramme': forms.TextInput( attrs={ 'autocomplete': 'off', 'spellcheck': 'false', }), } class KPsulCheckoutForm(forms.Form): checkout = forms.ModelChoiceField( queryset=Checkout.objects.filter( is_protected=False, valid_from__lte=timezone.now(), valid_to__gte=timezone.now()), widget=forms.Select(attrs={'id':'id_checkout_select'})) class KPsulOperationForm(forms.ModelForm): article = forms.ModelChoiceField( queryset=Article.objects.select_related('category').all(), required=False, widget = forms.HiddenInput()) class Meta: model = Operation fields = ['type', 'amount', 'is_checkout', 'article', 'article_nb'] widgets = { 'type': forms.HiddenInput(), 'amount': forms.HiddenInput(), 'is_checkout': forms.HiddenInput(), 'article_nb': forms.HiddenInput(), } 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['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") self.cleaned_data['article'] = None self.cleaned_data['article_nb'] = None KPsulOperationFormSet = modelformset_factory( Operation, form = KPsulOperationForm, can_delete = True, extra = 0, min_num = 1, validate_min = True) class AddcostForm(forms.Form): trigramme = forms.CharField(required = False) amount = forms.DecimalField( required = False, max_digits=6,decimal_places=2,min_value=Decimal(0)) def clean(self): trigramme = self.cleaned_data.get('trigramme') if trigramme: try: Account.objects.get(trigramme=trigramme) except Account.DoesNotExist: raise ValidationError('Compte invalide') else: self.cleaned_data['amount'] = 0 super(AddcostForm, self).clean() # ----- # Settings forms # ----- class SettingsForm(forms.ModelForm): class Meta: model = Settings fields = ['value_decimal', 'value_account', 'value_duration'] def clean(self): name = self.instance.name value_decimal = self.cleaned_data.get('value_decimal') value_account = self.cleaned_data.get('value_account') value_duration = self.cleaned_data.get('value_duration') type_decimal = ['SUBVENTION_COF', 'ADDCOST_AMOUNT', 'OVERDRAFT_AMOUNT'] type_account = ['ADDCOST_FOR'] type_duration = ['OVERDRAFT_DURATION', 'CANCEL_DURATION'] self.cleaned_data['name'] = name if name in type_decimal: if not value_decimal: raise ValidationError('Renseignez une valeur décimale') self.cleaned_data['value_account'] = None self.cleaned_data['value_duration'] = None elif name in type_account: self.cleaned_data['value_decimal'] = None self.cleaned_data['value_duration'] = None elif name in type_duration: if not value_duration: raise ValidationError('Renseignez une durée') self.cleaned_data['value_decimal'] = None self.cleaned_data['value_account'] = None super(SettingsForm, self).clean() class FilterHistoryForm(forms.Form): checkouts = forms.ModelMultipleChoiceField(queryset = Checkout.objects.all()) accounts = forms.ModelMultipleChoiceField(queryset = Account.objects.all()) # ----- # Transfer forms # ----- class TransferGroupForm(forms.ModelForm): class Meta: model = TransferGroup fields = ['comment'] class TransferForm(forms.ModelForm): from_acc = forms.ModelChoiceField( queryset = Account.objects.exclude(trigramme__in=['LIQ', '#13', 'GNR']), widget = forms.HiddenInput() ) to_acc = forms.ModelChoiceField( queryset = Account.objects.exclude(trigramme__in=['LIQ', '#13', 'GNR']), widget = forms.HiddenInput() ) def clean_amount(self): amount = self.cleaned_data['amount'] if amount <= 0: raise forms.ValidationError("Montant invalide") return amount class Meta: model = Transfer fields = ['from_acc', 'to_acc', 'amount'] TransferFormSet = modelformset_factory( Transfer, form = TransferForm, min_num = 1, validate_min = True, extra = 9, ) # ----- # Inventory forms # ----- class InventoryArticleForm(forms.Form): article = forms.ModelChoiceField( queryset = Article.objects.all(), widget = forms.HiddenInput(), ) stock_new = forms.IntegerField(required = False) def __init__(self, *args, **kwargs): super(InventoryArticleForm, self).__init__(*args, **kwargs) if 'initial' in kwargs: self.name = kwargs['initial']['name'] self.stock_old = kwargs['initial']['stock_old'] self.category = kwargs['initial']['category'] self.category_name = kwargs['initial']['category__name'] # ----- # Order forms # ----- class OrderArticleForm(forms.Form): article = forms.ModelChoiceField( queryset = Article.objects.all(), widget = forms.HiddenInput(), ) quantity_ordered = forms.IntegerField(required = False) def __init__(self, *args, **kwargs): super(OrderArticleForm, self).__init__(*args, **kwargs) if 'initial' in kwargs: self.name = kwargs['initial']['name'] self.stock = kwargs['initial']['stock'] self.category = kwargs['initial']['category'] self.category_name = kwargs['initial']['category__name'] self.box_capacity = kwargs['initial']['box_capacity'] self.v_s1 = kwargs['initial']['v_s1'] self.v_s2 = kwargs['initial']['v_s2'] self.v_s3 = kwargs['initial']['v_s3'] self.v_s4 = kwargs['initial']['v_s4'] self.v_s5 = kwargs['initial']['v_s5'] self.v_moy = kwargs['initial']['v_moy'] self.v_et = kwargs['initial']['v_et'] self.v_prev = kwargs['initial']['v_prev'] self.c_rec = kwargs['initial']['c_rec'] class OrderArticleToInventoryForm(forms.Form): article = forms.ModelChoiceField( queryset = Article.objects.all(), widget = forms.HiddenInput(), ) price_HT = forms.DecimalField( max_digits = 7, decimal_places = 4, required = False) TVA = forms.DecimalField( max_digits = 7, decimal_places = 2, required = False) rights = forms.DecimalField( max_digits = 7, decimal_places = 4, required = False) quantity_received = forms.IntegerField() def __init__(self, *args, **kwargs): super(OrderArticleToInventoryForm, self).__init__(*args, **kwargs) if 'initial' in kwargs: self.name = kwargs['initial']['name'] self.category = kwargs['initial']['category'] self.category_name = kwargs['initial']['category__name'] self.quantity_ordered = kwargs['initial']['quantity_ordered']