import django_filters from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout, Submit from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models from django.db.models import Max from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ import crispy_layout_mixin import sapl from crispy_layout_mixin import form_actions from materia.forms import RangeWidgetOverride from materia.models import Autor from sapl.utils import RANGE_ANOS from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido'), ('', 'Ambos')] NATUREZA_PROCESSO = [('', 'Ambos'), ('0', 'Administrativo'), ('1', 'Legislativo')] ANO_CHOICES = [('', '---------')] + RANGE_ANOS EM_TRAMITACAO = [('', 'Tanto Faz'), (0, 'Sim'), (1, 'Não')] class ProtocoloFilterSet(django_filters.FilterSet): filter_overrides = {models.DateField: { 'filter_class': django_filters.DateFromToRangeFilter, 'extra': lambda f: { 'label': 'Data (%s)' % (_('Inicial - Final')), 'widget': RangeWidgetOverride} }} ano = django_filters.ChoiceFilter(required=False, label=u'Ano da Matéria', choices=ANO_CHOICES) assunto_ementa = django_filters.CharFilter(lookup_expr='icontains') interessado = django_filters.CharFilter(lookup_expr='icontains') autor = django_filters.CharFilter(widget=forms.HiddenInput()) tipo_protocolo = django_filters.ChoiceFilter(required=False, label='Tipo de Protocolo', choices=TIPOS_PROTOCOLO, widget=forms.Select( attrs={'class': 'selector'})) tipo_processo = django_filters.ChoiceFilter(required=False, label='Natureza do Processo', choices=NATUREZA_PROCESSO, widget=forms.Select( attrs={'class': 'selector'})) class Meta: model = Protocolo fields = ['numero', 'tipo_documento', 'data', 'tipo_materia', ] order_by = ( ('', 'Selecione'), ('CRE', 'Ordem Crescente'), ('DEC', 'Ordem Decrescente'), ) order_by_mapping = { '': [], 'CRE': ['ano', 'numero'], 'DEC': ['-ano', '-numero'], } def get_order_by(self, order_value): if order_value in self.order_by_mapping: return self.order_by_mapping[order_value] else: return super(ProtocoloFilterSet, self).get_order_by(order_value) def __init__(self, *args, **kwargs): super(ProtocoloFilterSet, self).__init__(*args, **kwargs) self.filters['autor'].label = 'Tipo de Matéria' self.filters['assunto_ementa'].label = 'Assunto' row1 = crispy_layout_mixin.to_row( [('numero', 4), ('ano', 4), ('data', 4)]) row2 = crispy_layout_mixin.to_row( [('tipo_documento', 4), ('tipo_protocolo', 4), ('tipo_materia', 4)]) row3 = crispy_layout_mixin.to_row( [('interessado', 6), ('assunto_ementa', 6)]) row4 = crispy_layout_mixin.to_row( [('autor', 0), (Button('pesquisar', 'Pesquisar Autor', css_class='btn btn-primary btn-sm'), 2), (Button('limpar', 'Limpar Autor', css_class='btn btn-primary btn-sm'), 10)]) row5 = crispy_layout_mixin.to_row( [('tipo_processo', 12)]) row6 = crispy_layout_mixin.to_row( [('o', 12)]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( Fieldset(_('Pesquisar Protocolo'), row1, row2, row3, HTML(sapl.utils.autor_label), HTML(sapl.utils.autor_modal), row4, row5, row6, form_actions(save_label='Pesquisar')) ) class DocumentoAdministrativoFilterSet(django_filters.FilterSet): filter_overrides = {models.DateField: { 'filter_class': django_filters.DateFromToRangeFilter, 'extra': lambda f: { 'label': 'Data (%s)' % (_('Inicial - Final')), 'widget': RangeWidgetOverride} }} ano = django_filters.ChoiceFilter(required=False, label=u'Ano', choices=ANO_CHOICES) tramitacao = django_filters.ChoiceFilter(required=False, label=u'Em Tramitação?', choices=EM_TRAMITACAO) assunto = django_filters.CharFilter(lookup_expr='icontains') interessado = django_filters.CharFilter(lookup_expr='icontains') class Meta: model = DocumentoAdministrativo fields = ['tipo', 'numero', 'numero_protocolo', 'data', 'tramitacaoadministrativo__unidade_tramitacao_destino', 'tramitacaoadministrativo__status'] order_by = ( ('', 'Selecione'), ('CRE', 'Ordem Crescente'), ('DEC', 'Ordem Decrescente'), ) order_by_mapping = { '': [], 'CRE': ['ano', 'numero'], 'DEC': ['-ano', '-numero'], } def get_order_by(self, order_value): if order_value in self.order_by_mapping: return self.order_by_mapping[order_value] else: return super(DocumentoAdministrativoFilterSet, self).get_order_by(order_value) def __init__(self, *args, **kwargs): super(DocumentoAdministrativoFilterSet, self).__init__(*args, **kwargs) local_atual = 'tramitacaoadministrativo__unidade_tramitacao_destino' self.filters['tipo'].label = 'Tipo de Documento' self.filters['tramitacaoadministrativo__status'].label = 'Situação' self.filters[local_atual].label = 'Localização Atual' row1 = crispy_layout_mixin.to_row( [('tipo', 6), ('numero', 6)]) row2 = crispy_layout_mixin.to_row( [('ano', 4), ('numero_protocolo', 4), ('data', 4)]) row3 = crispy_layout_mixin.to_row( [('interessado', 4), ('assunto', 4), ('tramitacao', 4)]) row4 = crispy_layout_mixin.to_row( [('tramitacaoadministrativo__unidade_tramitacao_destino', 6), ('tramitacaoadministrativo__status', 6)]) row5 = crispy_layout_mixin.to_row( [('o', 12)]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( Fieldset(_('Pesquisar Documento'), row1, row2, row3, row4, row5, form_actions(save_label='Pesquisar')) ) class AnularProcoloAdmForm(ModelForm): numero = forms.CharField(required=True, label=Protocolo._meta. get_field('numero').verbose_name ) ano = forms.ChoiceField(required=True, label=Protocolo._meta. get_field('ano').verbose_name, choices=RANGE_ANOS, widget=forms.Select(attrs={'class': 'selector'})) justificativa_anulacao = forms.CharField( required=True, label=Protocolo._meta.get_field('justificativa_anulacao').verbose_name, widget=forms.Textarea) def clean(self): cleaned_data = super(AnularProcoloAdmForm, self).clean() numero = cleaned_data.get("numero") ano = cleaned_data.get("ano") # se não inserido numero ou ano não prosseguir # (e ele vai falhar pq numero e ano são obrigatórios) if not numero or not ano: return try: protocolo = Protocolo.objects.get(numero=numero, ano=ano) if protocolo.anulado: raise forms.ValidationError( _("Protocolo %s/%s já encontra-se anulado") % (numero, ano)) except ObjectDoesNotExist: raise forms.ValidationError( _("Protocolo %s/%s não existe" % (numero, ano))) class Meta: model = Protocolo fields = ['numero', 'ano', 'justificativa_anulacao', 'anulado', 'user_anulacao', 'ip_anulacao', ] widgets = {'anulado': forms.HiddenInput(), 'user_anulacao': forms.HiddenInput(), 'ip_anulacao': forms.HiddenInput(), } def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('numero', 6), ('ano', 6)]) row2 = crispy_layout_mixin.to_row( [('justificativa_anulacao', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Identificação do Protocolo'), row1, row2, HTML(" "), form_actions(save_label='Anular') ) ) super(AnularProcoloAdmForm, self).__init__( *args, **kwargs) class ProtocoloDocumentForm(ModelForm): NUMERACAO_CHOICES = [('1', _('Sequencial por Ano')), ('2', _('Sequencial Único'))] numeracao = forms.ChoiceField(required=True, choices=NUMERACAO_CHOICES, label='') tipo_protocolo = forms.ChoiceField(required=True, label=_('Tipo de Protocolo'), choices=TIPOS_PROTOCOLO,) tipo_documento = forms.ModelChoiceField( label=_('Tipo de Documento'), required=False, queryset=TipoDocumentoAdministrativo.objects.all(), empty_label='Selecione', ) num_paginas = forms.CharField(label=_('Núm. Páginas'), required=True) assunto = forms.CharField( widget=forms.Textarea, label='Assunto', required=True) interessado = forms.CharField(required=True, label='Interessado') observacao = forms.CharField(required=True, widget=forms.Textarea, label='Observação') class Meta: model = Protocolo fields = ['numeracao', 'tipo_protocolo', 'tipo_documento', 'num_paginas', 'assunto', 'interessado', 'observacao', ] def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [(InlineRadios('numeracao'), 12)]) row2 = crispy_layout_mixin.to_row( [(InlineRadios('tipo_protocolo'), 12)]) row3 = crispy_layout_mixin.to_row( [('tipo_documento', 6), ('num_paginas', 6)]) row4 = crispy_layout_mixin.to_row( [('assunto', 12)]) row5 = crispy_layout_mixin.to_row( [('interessado', 12)]) row6 = crispy_layout_mixin.to_row( [('observacao', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Protocolo - Opção de Numeração'), row1), Fieldset(_('Identificação de Documento'), row2, row3, row4, row5, row6, HTML(" "), form_actions(save_label=_('Protocolar Documento')) ) ) super(ProtocoloDocumentForm, self).__init__( *args, **kwargs) class ProtocoloMateriaForm(ModelForm): NUMERACAO_CHOICES = [('1', 'Sequencial por Ano'), ('2', 'Sequencial Único')] numeracao = forms.ChoiceField(required=True, choices=NUMERACAO_CHOICES, label='') tipo_protocolo = forms.ChoiceField(required=True, label='Tipo de Protocolo', choices=TIPOS_PROTOCOLO,) autor = forms.IntegerField(widget=forms.HiddenInput(), required=False) def clean_autor(self): autor_field = self.cleaned_data['autor'] try: autor = Autor.objects.get(id=autor_field) except ObjectDoesNotExist: autor_field = None else: autor_field = autor return autor_field class Meta: model = Protocolo fields = ['numeracao', 'tipo_protocolo', 'tipo_materia', 'numero_paginas', 'autor', 'observacao'] def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [(InlineRadios('numeracao'), 12)]) row2 = crispy_layout_mixin.to_row( [('tipo_materia', 4), (InlineRadios('tipo_protocolo'), 4), ('numero_paginas', 4)]) row3 = crispy_layout_mixin.to_row( [('autor', 0), (Button('pesquisar', 'Pesquisar Autor', css_class='btn btn-primary btn-sm'), 2), (Button('limpar', 'limpar Autor', css_class='btn btn-primary btn-sm'), 10)]) row4 = crispy_layout_mixin.to_row( [('observacao', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Protocolo - Opção de Numeração'), row1), Fieldset(_('Identificação da Matéria'), row2, HTML(sapl.utils.autor_label), HTML(sapl.utils.autor_modal), row3, row4, form_actions(save_label='Protocolar Matéria') ) ) super(ProtocoloMateriaForm, self).__init__( *args, **kwargs) class ProposicaoSimpleForm(forms.Form): tipo = forms.CharField(label='Tipo', widget=forms.TextInput( attrs={'readonly': 'readonly'})) materia = forms.CharField(label='Matéria', widget=forms.TextInput( attrs={'readonly': 'readonly'})) data_envio = forms.DateField(label=_('Data Envio'), widget=forms.DateInput( format='%d/%m/%Y', attrs={'readonly': 'readonly'})) data_recebimento = forms.DateField(label=_('Data Recebimento'), widget=forms.DateInput( format='%d/%m/%Y', attrs={'readonly': 'readonly'})) descricao = forms.CharField(label='Descrição', widget=forms.TextInput( attrs={'readonly': 'readonly'})) numero_proposicao = forms.CharField(label='Número', widget=forms.TextInput( attrs={'readonly': 'readonly'})) # ano = forms.CharField(label='Ano', # widget = forms.TextInput( # attrs={'readonly':'readonly'})) class DocumentoAcessorioAdministrativoForm(ModelForm): class Meta: model = DocumentoAcessorioAdministrativo fields = ['tipo', 'nome', 'data', 'autor', 'arquivo', 'assunto'] widgets = { 'data': forms.DateInput(format='%d/%m/%Y') } def __init__(self, excluir=False, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('tipo', 4), ('nome', 4), ('data', 4)]) row2 = crispy_layout_mixin.to_row( [('autor', 12)]) row3 = crispy_layout_mixin.to_row( [('arquivo', 12)]) row4 = crispy_layout_mixin.to_row( [('assunto', 12)]) more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Incluir Documento Acessório'), row1, row2, row3, row4, form_actions(more=more) ) ) super(DocumentoAcessorioAdministrativoForm, self).__init__( *args, **kwargs) class TramitacaoAdmForm(ModelForm): class Meta: model = TramitacaoAdministrativo fields = ['data_tramitacao', 'unidade_tramitacao_local', 'status', 'unidade_tramitacao_destino', 'data_encaminhamento', 'data_fim_prazo', 'texto', ] widgets = { 'data_tramitacao': forms.DateInput(format='%d/%m/%Y'), 'data_encaminhamento': forms.DateInput(format='%d/%m/%Y'), 'data_fim_prazo': forms.DateInput(format='%d/%m/%Y'), } def clean(self): if self.errors: return self.errors if (not self.cleaned_data['data_tramitacao'] or not self.cleaned_data['status'] or not self.cleaned_data['unidade_tramitacao_local']): msg = _('Você deixou campos obrigatórios em branco!') raise ValidationError(msg) ultima_data_tram = TramitacaoAdministrativo.objects.filter( documento_id=5).aggregate(Max('data_tramitacao')) data = ultima_data_tram.get('data_encaminhamento__max') ultima_tramitacao = TramitacaoAdministrativo.objects.filter( documento_id=5, data_encaminhamento=data).order_by( 'data_encaminhamento').first() if ultima_tramitacao: destino = ultima_tramitacao.unidade_tramitacao_destino if (destino != self.cleaned_data['unidade_tramitacao_local']): msg = _('A origem da nova tramitação deve ser igual ao ' 'destino da última adicionada!') raise ValidationError(msg) return self.cleaned_data class DocumentoAdministrativoForm(ModelForm): class Meta: model = DocumentoAdministrativo fields = ['tipo', 'numero', 'ano', 'data', 'numero_protocolo', 'assunto', 'interessado', 'tramitacao', 'dias_prazo', 'data_fim_prazo', 'observacao', 'texto_integral', ] def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('tipo', 4), ('numero', 4), ('ano', 4)]) row2 = crispy_layout_mixin.to_row( [('data', 6), ('numero_protocolo', 6)]) row3 = crispy_layout_mixin.to_row( [('assunto', 12)]) row4 = crispy_layout_mixin.to_row( [('interessado', 9), ('tramitacao', 3)]) row5 = crispy_layout_mixin.to_row( [('texto_integral', 12)]) row6 = crispy_layout_mixin.to_row( [('dias_prazo', 6), ('data_fim_prazo', 6)]) row7 = crispy_layout_mixin.to_row( [('observacao', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Identificação Básica'), row1, row2, row3, row4, row5), Fieldset(_('Outras Informações'), row6, row7), form_actions(more=[Submit('Excluir', 'Excluir')]), ) super(DocumentoAdministrativoForm, self).__init__( *args, **kwargs)