class AssociadoForm(forms.ModelForm): layout = material.Layout( material.Fieldset("Informações Pessoais", material.Row('nome', 'sobrenome'), material.Row('email', 'telefone'), ), material.Fieldset("Informações de Curso", material.Row('matricula', 'ano_matricula', 'previsao_conclusao') ), ) telefone = forms.CharField(widget=forms.TextInput(attrs={'class': 'mascara-telefone'}), required=False) class Meta: model = models.Associado fields = ( "nome", "sobrenome", "matricula", "email", "ano_matricula", "previsao_conclusao", "telefone", "password", )
class VendaForm(forms.ModelForm): associado = forms.ModelChoiceField(queryset=Associado.objects.all( ).order_by('nome', 'sobrenome', 'matricula')) finalizada = forms.BooleanField(help_text="Venda foi concluída?", required=False) desconto = forms.CharField( widget=forms.TextInput(attrs={'class': 'mascara-dinheiro'}), required=False) layout = material.Layout( material.Row('associado'), material.Row('data', 'desconto', 'finalizada'), ) def __init__(self, *args, **kwargs): super(VendaForm, self).__init__(*args, **kwargs) if self.instance and self.instance.pk: desconto = '{:,.2f}'.format(float(self.instance.desconto)) desconto = desconto.replace(',', 'v') desconto = desconto.replace('.', ',') desconto = f"R$ {desconto}" self.fields['desconto'].widget.attrs['value'] = desconto if self.instance.finalizada: self.fields['associado'].widget.attrs['disabled'] = True self.fields['data'].widget.attrs['disabled'] = True self.fields['finalizada'].widget.attrs['disabled'] = True self.fields['desconto'].widget.attrs['disabled'] = True if self.instance.entradas.count() > 0: self.fields['desconto'].widget.attrs['disabled'] = True def clean_desconto(self): """Tira formatação de moeda""" if self.instance and self.instance.pk: if self.instance.entradas.count() > 0: return self.instance.desconto desconto = self.cleaned_data.get("desconto") if not desconto: return 0 desconto = desconto.replace('R$', '') desconto = desconto.replace('.', '') desconto = desconto.replace(',', '.') desconto = float(desconto) return desconto class Meta: model = Venda fields = ('associado', 'data', 'finalizada', 'desconto')
class PersonForm(forms.ModelForm): birth_date = DateField(label='Date de naissance', ) layout = material.Layout( material.Fieldset( 'Identité de la personne transportée', material.Row( 'first_name', 'last_name', ), 'birth_date', ), material.Fieldset('Identité de l\'assuré', material.Row( 'nir', 'email', )), ) def clean_birth_date(self): data = self.cleaned_data['birth_date'] if data and (now().date() - data).days < 0: raise forms.ValidationError( 'Doit être antèrieure à la date du jour') return data def get_or_create(self): # Return existing person untouched if possible # Case of twins : we added a unicity check # with the person's first name person = Person.objects.filter( birth_date=self.cleaned_data['birth_date'], nir=self.cleaned_data['nir'], first_name=self.cleaned_data['first_name']).first() if person: return person # Otherwise create a new Person return super().save() class Meta: model = Person fields = [ 'nir', 'email', 'first_name', 'last_name', 'birth_date', ]
class MRSRequestCreateForm(MRSRequestForm): layouts = dict(above=material.Layout( material.Fieldset( 'Votre caisse d\'assurance maladie', 'caisse', ), ), top=material.Layout( material.Fieldset( 'Votre prescription médicale', 'pmt', ), ), bottom=material.Layout( material.Row('distance', ), 'expense', 'bills', )) def clean(self): cleaned_data = super().clean() expense = cleaned_data.get('expense') bills = cleaned_data.get('bills') if expense and not bills: self.add_error( 'bills', 'Merci de soumettre vos justificatifs de transport') return cleaned_data class Meta: model = MRSRequest fields = [ 'caisse', 'distance', 'expense', ]
class TransportForm(forms.ModelForm): date_depart = DateField(label='Date de l\'aller') date_return = DateField(label='Date de retour') layout = material.Layout(material.Row( 'date_depart', 'date_return', ), ) class Meta: model = Transport fields = [ 'date_depart', 'date_return', ] def clean(self): cleaned_data = super().clean() date_depart = cleaned_data.get('date_depart') date_return = cleaned_data.get('date_return') if date_depart and date_return and date_depart > date_return: self.add_error( 'date_return', 'La date de retour doit être égale ou postérieure à la' ' date aller', ) return cleaned_data
class VendaProdutoForm(forms.ModelForm): produto = forms.ModelChoiceField(queryset=Produto.objects.filter( arquivado=False)) quantidade = forms.IntegerField( min_value=1, widget=forms.TextInput(attrs={'class': 'quantidade-produto'}), initial=1, help_text= "Estoque será decrementado após a geração das entradas financeiras.") adicionar = forms.CharField( required=False, label='', widget=forms.TextInput(attrs={'class': 'somar-produto'})) remover = forms.CharField( required=False, label='', widget=forms.TextInput(attrs={'class': 'diminuir-produto'})) layout = material.Layout( material.Row( material.Span5('produto'), material.Field('remover'), material.Span3('quantidade'), material.Field('adicionar'), material.Span2('DELETE'), )) def __init__(self, *args, **kwargs): instance = kwargs.get('instance', None) if not instance: self.layout = material.Layout( material.Row( material.Span6('produto'), material.Field('remover'), material.Span4('quantidade'), material.Field('adicionar'), )) super(VendaProdutoForm, self).__init__(*args, **kwargs) def clean_quantidade(self): quantidade = self.cleaned_data.get('quantidade') produto = self.cleaned_data.get('produto') if not produto.servico: if produto.estoque.quantidade - quantidade < 0: raise forms.ValidationError( f'Produto sem estoque para esta venda! Estoque atual {produto.estoque.quantidade}' ) return quantidade class Meta: model = VendaProduto fields = ( 'produto', 'quantidade', )
class EgressoForm(forms.ModelForm): layout = material.Layout( material.Fieldset( "Informações Pessoais", material.Row('nome', 'sobrenome'), material.Row('email', 'telefone'), ), material.Fieldset( "Informações de Curso", material.Row('matricula', 'ano_matricula', 'previsao_conclusao')), material.Fieldset("Informações de Acesso", material.Row('password', 'password_confirm')), ) password = forms.CharField(label='Senha', widget=forms.PasswordInput()) password_confirm = forms.CharField(label='Confirmar Senha', widget=forms.PasswordInput()) telefone = forms.CharField( widget=forms.TextInput(attrs={'class': 'mascara-telefone'}), required=False) def clean(self): cleaned_data = super(EgressoForm, self).clean() password = cleaned_data.get("password") password_confirm = cleaned_data.get("password_confirm") if password != password_confirm: raise forms.ValidationError( "password and password_confirm does not match") class Meta: model = models.Egresso fields = ( "nome", "sobrenome", "matricula", "email", "ano_matricula", "previsao_conclusao", "telefone", "password", )
class ProdutoForm(forms.ModelForm): preco = forms.CharField( widget=forms.TextInput(attrs={'class': 'mascara-dinheiro'}), label="Preço do Produto") servico = forms.BooleanField( label="Serviço", help_text="Este produto é uma prestação de serviço?", required=False) layout = material.Layout( material.Fieldset('Informações do Produto', material.Row('nome', 'preco', 'servico'), material.Row('foto')), ) def __init__(self, *args, **kwargs): instance = kwargs.get('instance') if instance: preco = str(instance.preco) preco = '{:,.2f}'.format(float(instance.preco)) preco = preco.replace(',', 'v') preco = preco.replace('.', ',') preco = f"R$ {preco}" if 'initial' in kwargs: kwargs['initial']['preco'] = preco super(ProdutoForm, self).__init__(*args, **kwargs) def clean_preco(self): """Tira formatação de moeda""" data = self.cleaned_data.get("preco") data = data.replace('R$', '') data = data.replace('.', '') data = data.replace(',', '.') data = float(data) return data class Meta: model = Produto fields = ('nome', 'preco', 'servico', 'foto')
class SaidaFinanceiraForm(forms.ModelForm): descricao = forms.CharField(max_length=100, label="Descrição") carteira = forms.ModelChoiceField(queryset=Carteira.objects.all()) valor = forms.CharField(widget=forms.TextInput( attrs={'class': 'mascara-dinheiro'})) efetivado = forms.BooleanField( label="Efetivada", help_text="Movimentação Financeira já foi efetivada?", required=False) layout = material.Layout(material.Row('descricao', 'valor'), material.Row('data', 'efetivado'), material.Row('carteira')) def __init__(self, *args, **kwargs): instance = kwargs.get('instance') if instance: valor = '{:,.2f}'.format(float(instance.valor)) valor = valor.replace(',', 'v') valor = valor.replace('.', ',') valor = f"R$ {valor}" if 'initial' in kwargs: kwargs['initial']['valor'] = valor super(SaidaFinanceiraForm, self).__init__(*args, **kwargs) def clean_valor(self): """Tira formatação de moeda""" data = self.cleaned_data.get("valor") data = data.replace('R$', '') data = data.replace('.', '') data = data.replace(',', '.') data = float(data) return data class Meta: model = SaidaFinanceira fields = ('descricao', 'valor', 'carteira', 'data', 'efetivado')
def __init__(self, *args, **kwargs): instance = kwargs.get('instance', None) if not instance: self.layout = material.Layout( material.Row( material.Span6('produto'), material.Field('remover'), material.Span4('quantidade'), material.Field('adicionar'), )) super(VendaProdutoForm, self).__init__(*args, **kwargs)
class ContactForm(forms.Form): nom = forms.CharField() email = forms.EmailField() message = forms.CharField(widget=forms.Textarea) layout = material.Layout( material.Fieldset( 'N\'hésitez pas à nous contacter !', material.Row( 'nom', 'email', ), 'message', ))
class EstoqueForm(forms.ModelForm): quantidade = forms.IntegerField(help_text="Quantidade em estoque") quantidade_minima = forms.IntegerField( label="Quantidade Mínima", help_text="Quantidade mínima em estoque para realização de encomenda", ) quantidade_encomenda = forms.IntegerField( label="Quantidade para Encomenda", help_text="Quantidade mínima de interessados para encomenda") layout = material.Layout( material.Fieldset( 'Informações de Estoque', material.Row('quantidade', 'quantidade_minima', 'quantidade_encomenda')), ) class Meta: model = Estoque fields = ('quantidade', 'quantidade_minima', 'quantidade_encomenda')
class TransportIterativeForm(TransportForm): iterative_show = forms.BooleanField( label='Avez-vous des transports itératifs à déclarer ?', widget=forms.CheckboxInput, required=False, ) iterative_number = forms.IntegerField( label='Combien de trajets itératifs souhaitez-vous déclarer ?', initial=1, required=False, ) layout = material.Layout( material.Fieldset( 'Informations sur le transport', material.Row( 'date_depart', 'date_return', ), 'iterative_show', 'iterative_number', ), )
class StatListView(crudlfap.ListView): material_icon = 'show_chart' title_menu = 'suivi des indicateurs' title_link = 'Suivi des indicateurs' date_args = [ 'date__gte', 'date__lte', ] filter_fields = [ 'caisse', ] filterset_form_layout = material.Row('caisse', *date_args) filterset_extra_class_attributes = dict( date__gte=django_filters.DateFilter(field_name='date', lookup_expr='gte', input_formats=['%d/%m/%Y'], label='Date minimale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, )), date__lte=django_filters.DateFilter( field_name='date', lookup_expr='lte', input_formats=['%d/%m/%Y'], label='Date maximale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, ), ), ) def get_filterset(self): filterset = super().get_filterset() or self.filterset form = filterset.form if 'caisse' in form.fields and self.request.user.profile != 'admin': form.fields['caisse'].queryset = self.request.user.caisses.all() return filterset body_class = 'full-width' @classmethod def reverse(cls, *args, **kwargs): params = {str(k): str(v) for k, v in cls.date_default_filters.items()} if cls.request.user.profile != 'admin': params['caisse'] = cls.request.user.caisses.first().pk return ''.join([ str(super().reverse(*args, **kwargs)), '?', # pure abuse of Factory below urllib.parse.urlencode(params) ]) def get_date_default_filters(self): today = datetime.date.today() return dict( date__gte=datetime.date( day=1, month=today.month, year=today.year, ).strftime('%d/%m/%Y'), date__lte=(datetime.date( day=1, month=today.month + 1 if today.month < 12 else 1, year=today.year if today.month < 12 else today.year + 1, ) - datetime.timedelta(days=1)).strftime('%d/%m/%Y'), ) def get_validation_average_delay(self): return self.object_list.aggregate( result=models.Avg('validation_average_delay'))['result'] def get_mrsrequest_count(self, arg): return self.object_list.aggregate( result=models.Sum('mrsrequest_count_' + arg))['result'] def get_mrsrequests_by_shifted_insured_count(self): return self.mrsrequests.filter(insured__shifted=True).count() def get_insured_shifts(self): return self.object_list.aggregate( result=models.Sum('insured_shifts'))['result'] def get_insured_count_replied(self): mrsrequests = self.mrsrequests.status_filter( 'validated', 'rejected', **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }) return Person.objects.filter( mrsrequest__in=mrsrequests).distinct().count() def get_insured_count(self): mrsrequests = self.mrsrequests.created( **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }, caisse=self.filterset.form.cleaned_data.get('caisse')) return Person.objects.filter( mrsrequest__in=mrsrequests).distinct().count() def get_shifted_insured_count(self): caisse_set = self.filterset.form.cleaned_data.get('caisse') if caisse_set: mrsrequests = self.mrsrequests.filter(caisse=caisse_set) else: mrsrequests = self.mrsrequests return Person.objects.filter( shifted=True, mrsrequest__in=mrsrequests).distinct().count() def get_mrsrequests_processed(self): mrsrequests = self.mrsrequests.created( **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }, caisse=self.filterset.form.cleaned_data.get('caisse')).filter( status__in=( MRSRequest.STATUS_VALIDATED, MRSRequest.STATUS_REJECTED, ), ) return mrsrequests.distinct().count() def get_average_payment_delay(self): mrsrequests = self.mrsrequests.created( **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }, caisse=self.filterset.form.cleaned_data.get('caisse')) return '{:0.2f}'.format( mrsrequests.aggregate(result=models.Avg('delay'))['result'] or 0).replace('.', ',') def get_savings(self): mrsrequests = self.mrsrequests.created( **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }, caisse=self.filterset.form.cleaned_data.get('caisse')) return mrsrequests.aggregate(result=models.Sum('saving'))['result'] def get_primo_users(self): mrsrequests = self.mrsrequests.created( **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }, caisse=self.filterset.form.cleaned_data.get('caisse')) return Person.objects.annotate( requestscount=Count('mrsrequest')).filter( requestscount=1, mrsrequest__in=mrsrequests).distinct().count() def get_mrsrequests(self): # the default controller's list view will return objects user can see controller = crudlfap.site['mrsrequest.MRSRequest'] self.mrsrequests = controller['list']( request=self.request).get_objects() for i in ('caisse'): if self.filterset.form.cleaned_data.get(i, None): self.mrsrequests = self.mrsrequests.filter( **{i: self.filterset_form_cleaned_data[i]}) return self.mrsrequests def get_object_list(self): qs = super().get_object_list() self.object_list = self.filter_caisse(qs) return self.object_list def filter_caisse(self, qs): if not self.request.GET.get('caisse'): qs = qs.filter(caisse=None) return qs
class PersonForm(forms.ModelForm): nir = forms.CharField( label='Numéro de sécurité sociale', max_length=13, min_length=13, ) birth_date = DateField( label='Date de naissance', ) layout = material.Layout( material.Fieldset( 'Identité de la personne transportée', material.Row( 'first_name', 'last_name', ), 'birth_date', ), material.Fieldset( 'Identité de l\'assuré', material.Row( 'nir', 'email', ) ), ) layout = material.Layout( material.Fieldset( 'Identité de la personne transportée', material.Row( 'first_name', 'last_name', ), 'birth_date', ), material.Fieldset( 'Identité de l\'assuré', material.Row( 'nir', 'email', ) ), ) def clean_nir(self): nir = self.cleaned_data['nir'] try: int(nir) except ValueError: raise forms.ValidationError( 'Doit être composé de 13 chiffres' ) return nir def clean_birth_date(self): data = self.cleaned_data['birth_date'] if data and (now().date() - data).days < 0: raise forms.ValidationError( 'Doit être antèrieure à la date du jour') return data def get_or_create(self): # Return existing person untouched if possible person = Person.objects.filter( birth_date=self.cleaned_data['birth_date'], nir=self.cleaned_data['nir'], ).first() if person: return person # Otherwise create a new Person return super().save() class Meta: model = Person fields = [ 'nir', 'email', 'first_name', 'last_name', 'birth_date', ]
class PersonForm(forms.ModelForm): birth_date = DateFieldNativeWithoutDatepicker(label='Date de naissance', ) nir = CharFieldNative( label='Numéro de Sécurité sociale', help_text='<b>Si le patient transporté est mineur, indiquer ' 'le numéro de Sécurité sociale de son parent</b>', max_length=13, ) first_name = CharFieldNative( label='Prénom', max_length=70, ) last_name = CharFieldNative( label='Nom de famille', max_length=70, ) email = CharFieldNative( label='Adresse email', max_length=254, ) layout = material.Layout( material.Fieldset( '', material.Row( 'first_name', 'last_name', ), 'nir', 'birth_date', material.Row('email', ), )) def clean_birth_date(self): data = self.cleaned_data['birth_date'] if data and (now().date() - data).days < 0: raise forms.ValidationError( 'Doit être antèrieure à la date du jour') return data def clean_first_name(self): return name_clean(self.cleaned_data['first_name']) def clean_last_name(self): return name_clean(self.cleaned_data['last_name']) def get_or_create(self): # Return existing person untouched if possible # Case of twins : we added a unicity check # with the person's first name person = Person.objects.filter( birth_date=self.cleaned_data['birth_date'], nir=self.cleaned_data['nir'], first_name__iexact=self.cleaned_data['first_name']).first() if person: save = False # Ensure legacy data containing invalid last name are fixed try: person.full_clean() except ValidationError as e: if 'last_name' in e.error_dict: person.last_name = self.cleaned_data['last_name'] save = True if ('email' in self.cleaned_data and person.email != self.cleaned_data['email']): save = True person.email = self.cleaned_data['email'] if save: person.save() return person # Otherwise create a new Person return super().save() class Meta: model = Person fields = [ 'nir', 'email', 'first_name', 'last_name', 'birth_date', ]
class StatListView(crudlfap.ListView): material_icon = 'insert_chart' title_menu = 'quotidiennes' title_link = 'Graphique de statistiques quotidiennes' keys = [ 'date', 'mrsrequest_count_new', 'mrsrequest_count_inprogress', 'mrsrequest_count_validated', 'mrsrequest_count_rejected', 'mrsrequest_count_conflicted', 'mrsrequest_count_conflicting', 'mrsrequest_count_resolved', 'insured_shifts', ] date_args = [ 'date__gte', 'date__lte', ] filter_fields = [ 'caisse', 'institution', ] filterset_form_layout = material.Row('caisse', 'institution', *date_args) filterset_extra_class_attributes = dict( date__gte=django_filters.DateFilter(field_name='date', lookup_expr='gte', input_formats=['%d/%m/%Y'], label='Date minimale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, )), date__lte=django_filters.DateFilter( field_name='date', lookup_expr='lte', input_formats=['%d/%m/%Y'], label='Date maximale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, ), ), ) def get_filterset(self): filterset = super().get_filterset() or self.filterset form = filterset.form if 'caisse' in form.fields and self.request.user.profile != 'admin': form.fields['caisse'].queryset = self.request.user.caisses.all() return filterset body_class = 'full-width' @classmethod def reverse(cls, *args, **kwargs): params = {str(k): str(v) for k, v in cls.date_default_filters.items()} if cls.request.user.profile != 'admin': params['caisse'] = cls.request.user.caisses.first().pk return ''.join([ str(super().reverse(*args, **kwargs)), '?', # pure abuse of Factory below urllib.parse.urlencode(params) ]) def get_date_default_filters(self): today = datetime.date.today() return dict( date__gte=datetime.date( day=1, month=today.month, year=today.year, ).strftime('%d/%m/%Y'), date__lte=(datetime.date( day=1, month=today.month + 1 if today.month < 12 else 1, year=today.year if today.month < 12 else today.year + 1, ) - datetime.timedelta(days=1)).strftime('%d/%m/%Y'), ) def get_validation_average_delay(self): return self.object_list.aggregate( result=models.Avg('validation_average_delay'))['result'] def get_mrsrequest_count(self, arg): return self.object_list.aggregate( result=models.Sum('mrsrequest_count_' + arg))['result'] def get_mrsrequests_by_shifted_insured_count(self): return self.mrsrequests.filter(insured__shifted=True).count() def get_savings(self): return self.object_list.aggregate( result=models.Sum('savings'))['result'] def get_insured_shifts(self): return self.object_list.aggregate( result=models.Sum('insured_shifts'))['result'] def get_insured_count_replied(self): mrsrequests = self.mrsrequests.status_filter( 'validated', 'rejected', **{ k: v for k, v in self.filterset.form.cleaned_data.items() if k.startswith('date_') }) return Person.objects.filter( mrsrequest__in=mrsrequests).distinct().count() def get_mrsrequests(self): # the default controller's list view will return objects user can see controller = crudlfap.site['mrsrequest.MRSRequest'] self.mrsrequests = controller['list']( request=self.request).get_objects() for i in ('caisse', 'institution'): if self.filterset.form.cleaned_data.get(i, None): self.mrsrequests = self.mrsrequests.filter( **{i: self.filterset_form_cleaned_data[i]}) return self.mrsrequests def get_object_list(self): qs = super().get_object_list() self.object_list = self.filter_caisse_institution(qs) return self.object_list def filter_caisse_institution(self, qs): if not self.request.GET.get('caisse'): qs = qs.filter(caisse=None) if not self.request.GET.get('institution'): qs = qs.filter(institution=None) return qs def get_chart_json(self): columns = [[ 'x' if k == 'date' else self.model._meta.get_field(k).verbose_name ] for k in self.keys] rows = self.object_list.values_list(*self.keys) for row in rows: for i, value in enumerate(row): if isinstance(value, datetime.date): columns[i].append(value.strftime('%Y-%m-%d')) else: columns[i].append(value) return json.dumps( dict(bindto='#chart', data=dict( x='x', columns=columns, ), axis=dict( x=dict(type='timeseries', tick=dict(format='%d/%m/%Y', )), y=dict( min=0, padding=dict(bottom=0), ), ), point=dict(show=len(rows) < 32, )))
class VendaEntradaForm(forms.ModelForm): carteira = forms.ModelChoiceField(queryset=Carteira.objects.all()) valor = forms.CharField(widget=forms.TextInput( attrs={'class': 'mascara-dinheiro'})) efetivado = forms.BooleanField(label="Efetivada", help_text="Dinheiro já recebido?", required=False) data = forms.DateField(initial=timezone.now()) layout = material.Layout( material.Row( material.Span3('data'), material.Span3('valor'), material.Span3('carteira'), material.Span3('efetivado'), )) def __init__(self, *args, **kwargs): super(VendaEntradaForm, self).__init__(*args, **kwargs) if self.instance and self.instance.pk: valor = '{:,.2f}'.format(float(self.instance.entrada.valor)) valor = valor.replace(',', 'v') valor = valor.replace('.', ',') valor = f"R$ {valor}" self.fields['carteira'].initial = self.instance.entrada.carteira self.fields['valor'].initial = valor self.fields['efetivado'].initial = self.instance.entrada.efetivado self.fields['data'].initial = self.instance.entrada.data if self.instance.entrada.efetivado: self.fields['carteira'].widget.attrs['disabled'] = True self.fields['carteira'].required = False self.fields['valor'].widget.attrs['disabled'] = True self.fields['valor'].required = False self.fields['efetivado'].widget.attrs['disabled'] = True self.fields['efetivado'].required = False self.fields['data'].widget.attrs['disabled'] = True self.fields['data'].required = False def clean_data(self): """Tira formatação de moeda""" if self.instance and self.instance.pk: if self.instance.entrada.efetivado: return self.instance.entrada.data return self.cleaned_data.get('data') def clean_carteira(self): """Tira formatação de moeda""" if self.instance and self.instance.pk: if self.instance.entrada.efetivado: return self.instance.entrada.carteira return self.cleaned_data.get('carteira') def clean_efetivado(self): """Tira formatação de moeda""" if self.instance and self.instance.pk: if self.instance.entrada.efetivado: return self.instance.entrada.efetivado return self.cleaned_data.get('efetivado') def clean_valor(self): """Tira formatação de moeda""" if self.instance and self.instance.pk: if self.instance.entrada.efetivado: return self.instance.entrada.valor valor = self.cleaned_data.get("valor") valor = valor.replace('R$', '') valor = valor.replace('.', '') valor = valor.replace(',', '.') valor = float(valor) return valor class Meta: model = VendaEntrada fields = ()
class MRSRequestLogEntryListView(crudlfap.ListView): material_icon = 'insert_chart' filter_fields = ['mrsrequest__caisse', 'user'] date_args = ['date__gte', 'date__lte'] filterset_form_layout = material.Row('mrsrequest__caisse', 'user', 'date__gte', 'date__lte') filterset_extra_class_attributes = dict( date__gte=django_filters.DateFilter(field_name='date', lookup_expr='gte', input_formats=['%d/%m/%Y'], label='Date minimale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, )), date__lte=django_filters.DateFilter( field_name='date', lookup_expr='lte', input_formats=['%d/%m/%Y'], label='Date maximale', widget=forms.TextInput(attrs={ 'class': 'crudlfap-datepicker', 'data-clearable': 'true', 'data-format': 'dd/mm/yyyy', }, ), ), ) body_class = 'full-width' def has_perm(self): return self.request.user.is_superuser def get_chart_json(self): from mrsemail.models import EmailTemplate templates = list(EmailTemplate.objects.all()) columns = [['x']] + [[str(t)] for t in templates] dates = dict() for obj in self.object_list.exclude(emailtemplate=None): if obj.date not in dates: dates[obj.date] = [0] * len(templates) dates[obj.date][templates.index(obj.emailtemplate)] += 1 for date, row in dates.items(): columns[0].append(date.strftime('%Y-%m-%d')) for i, et in enumerate(templates): columns[i + 1].append(row[i]) return json.dumps( dict(bindto='#chart', data=dict( x='x', columns=columns, ), axis=dict( x=dict(type='timeseries', tick=dict(format='%d/%m/%Y', )), y=dict( min=0, padding=dict(bottom=0), ), ), point=dict(show=len(dates.keys()) < 32, )))
class ContactForm(forms.Form): motif = forms.ChoiceField( label='Motif', choices=MOTIF_CHOICES, ) caisse = forms.ModelChoiceField( queryset=Caisse.objects.filter(active=True), label='Votre caisse de rattachement', ) nom = forms.CharField( # noqa max_length=70, validators=name_validators, ) email = forms.EmailField() mrsrequest_display_id = forms.CharField( label='Numéro de demande (optionnel)', required=False, max_length=12, validators=[ validators.RegexValidator( regex=r'^\d{12}$', message=_('MRSREQUEST_UNEXPECTED_DISPLAY_ID'), ) ]) message = forms.CharField(widget=forms.Textarea, max_length=3000) captcha = CaptchaField(required=True) layout = material.Layout( material.Fieldset( ' ', material.Row( 'motif', 'caisse', ), 'mrsrequest_display_id', material.Row( 'nom', 'email', ), 'message', 'captcha', )) def clean_nom(self): return name_clean(self.cleaned_data['nom']) def clean_message(self): message = self.cleaned_data['message'] if re.findall('https?://', message): raise forms.ValidationError( 'Votre message ne doit pas contenir de lien.') if '<' in message: raise forms.ValidationError( 'Votre message ne doit pas contenir de chevrons.') return message def get_email_kwargs(self): data = self.cleaned_data email = getattr(data['caisse'], 'liquidation_email', None) if email: to = [email] else: to = [settings.TEAM_EMAIL] if data['motif'].startswith('request'): subject = 'RÉCLAMATION MRS' else: subject = 'Nouveau message envoyé depuis le site mrs.beta.gouv.fr' body = template.loader.get_template( 'contact/contact_mail_body.txt').render( dict( data=data, motif=dict(self.fields['motif'].choices)[data['motif']], )).strip() return dict( subject=subject, body=body, to=to, reply_to=[data['email']], ) def save(self): instance = Contact( subject=self.cleaned_data['motif'], name=self.cleaned_data['nom'], email=self.cleaned_data['email'], message=self.cleaned_data['message'], ) mid = self.cleaned_data['mrsrequest_display_id'] if mid: mrs = MRSRequest.objects.filter(display_id=mid).first() if mrs: instance.mrsrequest = mrs caisse = self.cleaned_data['caisse'] if caisse != 'other': instance.caisse = self.cleaned_data['caisse'] instance.save() return instance
class TransportForm(forms.Form): date_depart = DateFieldNative(label='Date de l\'aller', required=True, validators=[ transport_date_min_validator, transport_date_max_validator ]) date_return = DateFieldNative(label='Date de retour', required=False, validators=[ transport_date_min_validator, transport_date_max_validator ]) layout = material.Layout(material.Row( 'date_depart', 'date_return', )) def __init__(self, *args, **kwargs): self.confirms = dict() super().__init__(*args, **kwargs) def clean(self): cleaned_data = super().clean() date_depart = cleaned_data.get('date_depart') date_return = cleaned_data.get('date_return') if date_depart and date_return and date_depart > date_return: self.add_error( 'date_return', 'La date de retour doit être égale ou postérieure à la' ' date aller', ) return cleaned_data def add_confirm(self, field, kind, other): self.confirms.setdefault(field, dict()) self.confirms[field].setdefault(kind, list()) self.confirms[field][kind].append(other) def set_confirms(self, formset, transports): """Provision self.confirms""" self.set_confirms_formset(formset) self.set_confirms_queryset(transports) def set_confirms_queryset(self, transports): date_depart = self.cleaned_data.get('date_depart') for transport in transports: if date_depart != transport.date_depart: continue if transport.mrsrequest.status_in('new', 'inprogress'): self.add_confirm('date_depart', 'inprogress', transport) if transport.mrsrequest.status_in('validated'): self.add_confirm('date_depart', 'validated', transport) def set_confirms_formset(self, formset): for my_name in ('depart', 'return'): my_name = f'date_{my_name}' my_value = self.cleaned_data.get(my_name) for form_number, form in enumerate(formset.forms): if form is self: break for other_name in ('depart', 'return'): other_name = f'date_{other_name}' other_value = form.cleaned_data[other_name] if my_value == other_value: self.add_confirm(my_name, 'duplicate', (form_number, other_name)) def add_confirms(self): for field, confirms in self.confirms.items(): for confirm, confirm_data in confirms.items(): self.add_error( field, getattr(self, f'get_{confirm}_message')(confirm_data)) def get_duplicate_message(self, forms_fields): names = dict(date_depart='aller', date_return='retour') labels = [ f'{names[field_name]} n° {form_number + 1}' for form_number, field_name in forms_fields ] msg = ['Date de trajet déjà présente dans'] if len(labels) == 1: msg.append(f'le trajet {labels[0]}') else: msg += [ 'les trajets', ', '.join(labels[:-1]), 'et', labels[-1], ] return ' '.join(msg) + '.' def get_verbose_transports(self, singular, plural, transports): mrsrequests = set([transport.mrsrequest for transport in transports]) msg = [plural if len(mrsrequests) > 1 else singular] labels = [ ' '.join([ 'du', mrsrequest.creation_date_normalized, 'n°', str(mrsrequest.display_id), ]) for mrsrequest in mrsrequests ] if len(labels) == 1: msg += ['demande', labels[0]] else: msg += [ 'demandes', ', '.join(labels[:-1]), 'et', labels[-1], ] return ' '.join(msg) def get_inprogress_message(self, transports): return ' '.join([ 'Votre demande de prise en charge pour ce trajet', 'est en cours de traitement dans', self.get_verbose_transports('la', 'les', transports) ]) + '.' def get_validated_message(self, transports): return ' '.join([ 'Ce trajet vous a été réglé lors', self.get_verbose_transports('de la', 'des', transports), ]) + '.'
class MRSRequestCreateForm(forms.ModelForm): # do not trust this field, it's used for javascript and checked # by the view for permission against the request session, but is # NOT to be trusted as input: don't use data['mrsrequest_uuid'] nor # cleaned_data['mrsrequest_uuid'], you've been warned. mrsrequest_uuid = forms.CharField(widget=forms.HiddenInput, required=False) pmt = MRSAttachmentField( PMT, 'mrsrequest:pmt_upload', 'mrsrequest:pmt_download', 20, label='Prescription Médicale de Transport obligatoire', help_text=PMT_HELP, required=False, ) pmt_pel = forms.ChoiceField( choices=( ('pmt', 'PMT (Prescription Papier)'), ('pel', 'PMET (Prescription Électronique)'), ), initial='pmt', label='Avez-vous une ...', widget=forms.RadioSelect, ) pel = forms.CharField( label='Numéro de Prescription Électronique', help_text=PEL_HELP, required=False, ) billvps = MRSAttachmentField( BillVP, 'mrsrequest:billvp_upload', 'mrsrequest:bill_download', 20, label='Justificatifs', required=False, help_text=('Joindre vos justificatifs de péage' ' <span data-parking-enable>' ' / stationnement' ' </span>')) billatps = MRSAttachmentField( BillATP, 'mrsrequest:billatp_upload', 'mrsrequest:bill_download', 20, label='Justificatifs', required=False, help_text=('Joindre vos justificatifs de transport en commun')) caisse = ActiveCaisseChoiceField( label='Votre caisse de rattachement', help_text='Votre caisse n\'apparaît pas dans la liste ? Elle n\'a pas ' 'encore rejoint le dispositif MRS. Cliquez sur "Autre" pour ' 'la sélectionner et recevoir un e-mail dès que celle-ci ' 'sera disponible !') region = ActiveRegionChoiceField(label='Votre région', ) expenseatp = AllowedCommaDecimalField( decimal_places=2, max_digits=6, validators=[validators.MinValueValidator(Decimal('0.00'))], label='Frais de transports', help_text=('Somme totale des frais de transport en commun (en € TTC)'), required=False, widget=forms.TextInput, ) expensevp_toll = AllowedCommaDecimalField( decimal_places=2, max_digits=6, validators=[validators.MinValueValidator(Decimal('0.00'))], label='Frais de péage', help_text=('Somme totale des frais de péage (en € TTC)'), required=False, widget=forms.TextInput, ) expensevp_parking = AllowedCommaDecimalField( decimal_places=2, max_digits=6, validators=[validators.MinValueValidator(Decimal('0.00'))], label='Frais de stationnement', help_text=('Somme totale des frais de stationnement (en € TTC)'), required=False, widget=forms.TextInput, ) layouts = dict( start=material.Layout(material.Fieldset( 'Votre région', 'region', ), ), above=material.Layout( material.Fieldset( 'Votre caisse d\'assurance maladie', 'caisse', ), ), top=material.Layout( material.Fieldset( 'Votre prescription médicale', 'pmt_pel', ), material.Row('pmt', ), material.Row('pel', ), ), modevp=material.Layout('modevp', ), vp_form=material.Layout( material.Row('distancevp', ), material.Row( 'expensevp_toll', 'expensevp_parking', ), 'billvps', ), modeatp=material.Layout('modeatp', ), atp_form=material.Layout( 'expenseatp', 'billatps', ), ) class Meta: model = MRSRequest fields = [ 'caisse', 'expenseatp', 'expensevp_parking', 'expensevp_toll', 'distancevp', 'modevp', 'modeatp', 'pel', ] widgets = dict( distancevp=forms.TextInput, expensevp_toll=forms.TextInput, expensevp_parking=forms.TextInput, ) def __init__(self, *args, **kwargs): kwargs.setdefault('initial', {}) initial = kwargs['initial'] kwargs['initial'].setdefault('expensevp_parking', 0) kwargs['initial'].setdefault('expensevp_toll', 0) if 'mrsrequest_uuid' in kwargs: mrsrequest_uuid = kwargs.pop('mrsrequest_uuid') instance = kwargs.get('instance') if not instance: kwargs['instance'] = MRSRequest() kwargs['instance'].id = mrsrequest_uuid elif 'instance' in kwargs: mrsrequest_uuid = str(kwargs['instance'].id) else: raise Exception('No instance, no uuid, secure it yourself') initial['mrsrequest_uuid'] = mrsrequest_uuid data, files, args, kwargs = self.args_extract(args, kwargs) if data: data, files = self.data_attachments(data, files, mrsrequest_uuid) kwargs['data'] = data kwargs['files'] = files super().__init__(*args, **kwargs) def cleaned_pmt_pel(self, cleaned_data): pmt_pel = cleaned_data.get('pmt_pel', 'pmt') if pmt_pel == 'pmt': cleaned_data.pop('pel', None) if not cleaned_data.get('pmt'): self.add_error('pmt', 'Merci de sélectionner votre PMT') elif pmt_pel == 'pel': if not cleaned_data.get('pel'): self.add_error('pel', 'Merci de saisir votre numéro de PMET') def cleaned_vp_atp(self, cleaned_data): vp = cleaned_data.get('modevp') atp = cleaned_data.get('modeatp') if not vp and not atp: self.add_error( 'modeatp', 'Merci de choisir véhicule personnel et / ou transports en' ' commun', ) self.add_error( 'modevp', 'Merci de choisir véhicule personnel et / ou transports en' ' commun', ) if vp: distancevp = cleaned_data.get('distancevp') if not distancevp: self.add_error( 'distancevp', 'Merci de saisir la distance du trajet', ) expensevp_toll = cleaned_data.get('expensevp_toll') expensevp_parking = cleaned_data.get('expensevp_parking') billvps = cleaned_data.get('billvps') if (expensevp_toll or expensevp_parking) and not billvps: self.add_error( 'billvps', 'Merci de soumettre vos justificatifs de transport') if atp: billatps = cleaned_data.get('billatps') if not billatps: self.add_error( 'billatps', 'Merci de fournir les justificatifs de transport', ) expenseatp = cleaned_data.get('expenseatp') if not expenseatp: self.add_error( 'expenseatp', 'Merci de saisir le total du coût de transports en commun', ) def clean(self): cleaned_data = super().clean() self.cleaned_pmt_pel(cleaned_data) self.cleaned_vp_atp(cleaned_data) return cleaned_data def data_attachments(self, data, files, mrsrequest_uuid): data['pmt'] = PMT.objects.recorded_uploads(mrsrequest_uuid) data['billvps'] = BillVP.objects.recorded_uploads(mrsrequest_uuid) data['billatps'] = BillATP.objects.recorded_uploads(mrsrequest_uuid) if files: files.update(data) else: files = data return data, files def args_extract(self, args, kwargs): """Extract data and files args, return mutable objects.""" # make popable (can't pop tuple of args) args = list(args) def getarg(name, num): if args and len(args) > num: return args.pop(num) elif kwargs.get('files'): return kwargs.pop('files') return None # First to not affect data = args.pop(0) files = getarg('files', 1) data = getarg('data', 0) # make mutable if something if files: files = MultiValueDict(files) if data: data = MultiValueDict(data) return data, files, args, kwargs def save(self, commit=True): if self.cleaned_data.get('parking_expensevp', None): self.instance.expensevp += self.cleaned_data.get( 'parking_expensevp') obj = super().save(commit=commit) def save_attachments(form, obj): if form.cleaned_data.get('pmt_pel') == 'pmt': obj.save_pmt() else: obj.delete_pmt() obj.save_bills() save_m2m = getattr(self, 'save_m2m', None) if save_m2m: def _save_m2m(): save_attachments(self, obj) save_m2m() self.save_m2m = _save_m2m else: save_attachments(self, obj) return obj
class GrupoForm(forms.ModelForm): layout = material.Layout( material.Row('name'), material.Fieldset('Permissões de Gestão', material.Row( material.Fieldset("Diretório Acadêmico", material.Column('change_diretorioacademico', 'view_diretorioacademico') ), material.Fieldset("Atas de Reunião", material.Column('add_reuniao', 'change_reuniao', 'delete_reuniao', 'view_reuniao') ), material.Fieldset("Áreas", material.Column('add_area', 'change_area', 'delete_area', 'view_area') ), ), material.Row( material.Fieldset("Alunos", material.Column('add_aluno', 'change_aluno', 'delete_aluno', 'view_aluno') ), material.Fieldset("Egressos", material.Column('add_egresso', 'change_egresso', 'delete_egresso', 'view_egresso') ), material.Fieldset("Diretores", material.Column('add_diretor', 'change_diretor', 'delete_diretor', 'view_diretor') ), material.Fieldset("Grupos", material.Column('add_group', 'change_group', 'delete_group', 'view_group') ), ), ), material.Fieldset('Permissões de Finanças', material.Row( material.Fieldset("Carteiras Financeiras", material.Column('add_carteira', 'change_carteira', 'delete_carteira', 'view_carteira') ), material.Fieldset("Entradas Financeiras", material.Column('add_entradafinanceira', 'change_entradafinanceira', 'delete_entradafinanceira', 'view_entradafinanceira') ), material.Fieldset("Saídas Financeiras", material.Column('add_saidafinanceira', 'change_saidafinanceira', 'delete_saidafinanceira', 'view_saidafinanceira') ), material.Fieldset("Transferências Financeiras", material.Column('add_transferenciafinanceira', 'change_transferenciafinanceira', 'delete_transferenciafinanceira', 'view_transferenciafinanceira') ), ), material.Row( material.Fieldset("Produtos", material.Column('add_produto', 'change_produto', 'delete_produto', 'view_produto') ), material.Fieldset("Recibos de Pagamento", material.Column('add_recibopagamento', 'change_recibopagamento', 'delete_recibopagamento', 'view_recibopagamento') ), material.Fieldset("Vendas", material.Column('add_venda', 'change_venda', 'delete_venda', 'view_venda') ), ), ), material.Fieldset('Permissões de Eventos', material.Row( material.Fieldset("Eventos", material.Column('add_evento', 'change_evento', 'delete_evento', 'view_evento') ), material.Fieldset("Atrações de Eventos", material.Column('add_atracaoevento', 'change_atracaoevento', 'delete_atracaoevento', 'view_atracaoevento') ), material.Fieldset("Inscrições de Eventos", material.Column('add_inscricaoevento', 'change_inscricaoevento', 'delete_inscricaoevento', 'view_inscricaoevento') ), material.Fieldset("Inscrições em Atrações de Eventos", material.Column('add_inscricaoatracao', 'change_inscricaoatracao', 'delete_inscricaoatracao', 'view_inscricaoatracao') ), ), ), ) __content_type_black_list = [ 'logentry', 'permission', 'content_type', 'session', 'cargo', ] __permission_black_list = [ 'add_diretorioacademico', 'delete_diretorioacademico', ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) permissions_add = Permission.objects.exclude(content_type__model__in=self.__content_type_black_list).exclude( codename__in=self.__permission_black_list).filter(codename__startswith='add_') permissions_change = Permission.objects.exclude(content_type__model__in=self.__content_type_black_list).exclude( codename__in=self.__permission_black_list).filter(codename__startswith='change_') permissions_delete = Permission.objects.exclude(content_type__model__in=self.__content_type_black_list).exclude( codename__in=self.__permission_black_list).filter(codename__startswith='delete_') permissions_view = Permission.objects.exclude(content_type__model__in=self.__content_type_black_list).exclude( codename__in=self.__permission_black_list).filter(codename__startswith='view_') for permission in permissions_add: self.fields[permission.codename] = forms.BooleanField(required=False, initial=False, label='Adicionar') for permission in permissions_change: self.fields[permission.codename] = forms.BooleanField(required=False, initial=False, label='Alterar') for permission in permissions_delete: self.fields[permission.codename] = forms.BooleanField(required=False, initial=False, label='Remover') for permission in permissions_view: self.fields[permission.codename] = forms.BooleanField(required=False, initial=False, label='Visualizar') if self.instance.id: group_permissions = self.instance.permissions.all() for permission in group_permissions: self.fields[permission.codename].initial = True def clean(self): data = {} data['name'] = self.cleaned_data.pop('name') data['permissions'] = [] for permissao in self.cleaned_data: if self.cleaned_data[permissao]: data['permissions'].append(Permission.objects.get(codename=permissao)) self.cleaned_data = data def save(self): group = super().save() group.permissions.clear() for permissao in self.cleaned_data['permissions']: group.permissions.add(permissao) return group class Meta: model = Group fields = ("name",)