import django_filters from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout, Submit from django import forms from django.core.exceptions import ValidationError from django.db.models import Max from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ from django.utils.text import capfirst from django_filters import FilterSet import crispy_layout_mixin import sapl from crispy_layout_mixin import form_actions from norma.models import LegislacaoCitada, TipoNormaJuridica from parlamentares.models import Parlamentar, Partido from sapl.settings import MAX_DOC_UPLOAD_SIZE from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, Numeracao, Origem, Proposicao, Relatoria, StatusTramitacao, TipoAutor, TipoMateriaLegislativa, Tramitacao, UnidadeTramitacao) def em_tramitacao(): return [('', 'Tanto Faz'), (True, 'Sim'), (False, 'Não')] def ordenacao(): return [('data, tipo, ano, numero', 'Data, Tipo, Ano, Numero'), ('tipo, ano, numero, data', 'Tipo, Ano, Numero, Data')] class ProposicaoForm(ModelForm): tipo_materia = forms.ModelChoiceField( label=_('Matéria Vinculada'), required=False, queryset=TipoMateriaLegislativa.objects.all(), empty_label='Selecione', ) numero_materia = forms.CharField( label='Número', required=False) ano_materia = forms.CharField( label='Ano', required=False) def clean_texto_original(self): texto_original = self.cleaned_data.get('texto_original', False) if texto_original: if texto_original.size > MAX_DOC_UPLOAD_SIZE: raise ValidationError("Arquivo muito grande. ( > 5mb )") return texto_original class Meta: model = Proposicao fields = ['tipo', 'data_envio', 'descricao', 'texto_original'] def __init__(self, excluir=False, *args, **kwargs): more = [] if excluir: more = [Submit('Excluir', 'Excluir')] row1 = crispy_layout_mixin.to_row( [('tipo', 8), ('data_envio', 4)]) row2 = crispy_layout_mixin.to_row( [('descricao', 12)]) row3 = crispy_layout_mixin.to_row( [('tipo_materia', 4), ('numero_materia', 4), ('ano_materia', 4)]) row4 = crispy_layout_mixin.to_row( [('texto_original', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Incluir Proposição'), row1, row2, row3, row4, form_actions(more=more)) ) super(ProposicaoForm, self).__init__( *args, **kwargs) class AcompanhamentoMateriaForm(ModelForm): class Meta: model = AcompanhamentoMateria fields = ['email'] def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row([('email', 10)]) row1.append( Column(form_actions(save_label='Cadastrar'), css_class='col-md-2') ) self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Acompanhamento de Matéria por e-mail'), row1 ) ) super(AcompanhamentoMateriaForm, self).__init__(*args, **kwargs) class DocumentoAcessorioForm(ModelForm): autor = forms.CharField(widget=forms.HiddenInput(), required=False) class Meta: model = DocumentoAcessorio fields = ['tipo', 'nome', 'data', 'autor', 'ementa'] widgets = { 'data': forms.DateInput(attrs={'class': 'dateinput'}) } def clean_autor(self): autor_field = self.cleaned_data['autor'] try: int(autor_field) except ValueError: return autor_field else: if autor_field: return str(Autor.objects.get(id=autor_field)) 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', 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)]) row3 = crispy_layout_mixin.to_row( [('ementa', 12)]) more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Incluir Documento Acessório'), row1, HTML(sapl.utils.autor_label), HTML(sapl.utils.autor_modal), row2, row3, form_actions(more=more) ) ) super(DocumentoAcessorioForm, self).__init__(*args, **kwargs) class RelatoriaForm(ModelForm): class Meta: model = Relatoria fields = ['data_designacao_relator', 'comissao', 'parlamentar', 'data_destituicao_relator', 'tipo_fim_relatoria' ] widgets = { 'data_designacao_relator': forms.DateInput(attrs={ 'class': 'dateinput'}), 'data_destituicao_relator': forms.DateInput(attrs={ 'class': 'dateinput'}), } class TramitacaoForm(ModelForm): urgente = forms.ChoiceField(required=False, label='Tramitando', choices=[(True, 'Sim'), (False, 'Não')], widget=forms.Select( attrs={'class': 'selector'})) class Meta: model = Tramitacao fields = ['data_tramitacao', 'unidade_tramitacao_local', 'status', 'turno', 'urgente', 'unidade_tramitacao_destino', 'data_encaminhamento', 'data_fim_prazo', 'texto'] def __init__(self, excluir=False, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('data_tramitacao', 6), ('unidade_tramitacao_local', 6)]) row2 = crispy_layout_mixin.to_row( [('status', 5), ('turno', 5), ('urgente', 2)]) row3 = crispy_layout_mixin.to_row( [('unidade_tramitacao_destino', 12)]) row4 = crispy_layout_mixin.to_row( [('data_encaminhamento', 6), ('data_fim_prazo', 6)]) row5 = crispy_layout_mixin.to_row( [('texto', 12)]) more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset(_('Incluir Tramitação'), row1, row2, row3, row4, row5, ), form_actions(more=more) ) super(TramitacaoForm, self).__init__( *args, **kwargs) class LegislacaoCitadaForm(ModelForm): tipo = forms.ModelChoiceField( label=_('Tipo Norma'), required=True, queryset=TipoNormaJuridica.objects.all(), empty_label='Selecione', ) numero = forms.CharField(label='Número', required=True) ano = forms.CharField(label='Ano', required=True) class Meta: model = LegislacaoCitada fields = ['tipo', 'numero', 'ano', 'disposicoes', 'parte', 'livro', 'titulo', 'capitulo', 'secao', 'subsecao', 'artigo', 'paragrafo', 'inciso', 'alinea', 'item'] def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('tipo', 4), ('numero', 4), ('ano', 4)]) row2 = crispy_layout_mixin.to_row( [('disposicoes', 3), ('parte', 3), ('livro', 3), ('titulo', 3)]) row3 = crispy_layout_mixin.to_row( [('capitulo', 3), ('secao', 3), ('subsecao', 3), ('artigo', 3)]) row4 = crispy_layout_mixin.to_row( [('paragrafo', 3), ('inciso', 3), ('alinea', 3), ('item', 3)]) self.helper = FormHelper() self.helper.form_class = 'form-horizontal' self.helper.layout = Layout( Fieldset( _('Incluir Legislação Citada'), row1, row2, row3, row4, form_actions() ) ) super(LegislacaoCitadaForm, self).__init__(*args, **kwargs) class NumeracaoForm(ModelForm): class Meta: model = Numeracao fields = ['tipo_materia', 'numero_materia', 'ano_materia', 'data_materia'] def __init__(self, excluir=False, *args, **kwargs): more = [] if excluir: more = [Submit('Excluir', 'Excluir')] row1 = crispy_layout_mixin.to_row( [('tipo_materia', 12)]) row2 = crispy_layout_mixin.to_row( [('numero_materia', 4), ('ano_materia', 4), ('data_materia', 4)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Incluir Numeração'), row1, row2, form_actions(more=more) ) ) super(NumeracaoForm, self).__init__(*args, **kwargs) class DespachoInicialForm(ModelForm): class Meta: model = DespachoInicial fields = ['comissao'] def __init__(self, excluir=False, *args, **kwargs): more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Adicionar Despacho Inicial'), 'comissao', form_actions(more=more) ) ) super(DespachoInicialForm, self).__init__(*args, **kwargs) class MateriaAnexadaForm(ModelForm): tipo = forms.ModelChoiceField( label='Tipo', required=True, queryset=TipoMateriaLegislativa.objects.all(), empty_label='Selecione', ) numero = forms.CharField(label='Número', required=True) ano = forms.CharField(label='Ano', required=True) class Meta: model = Anexada fields = ['tipo', 'numero', 'ano', 'data_anexacao', 'data_desanexacao'] widgets = { 'data_anexacao': forms.DateInput(attrs={'class': 'dateinput'}), 'data_desanexacao': forms.DateInput(attrs={'class': 'dateinput'}), } def __init__(self, excluir=False, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('tipo', 4), ('numero', 4), ('ano', 4)]) row2 = crispy_layout_mixin.to_row( [('data_anexacao', 6), ('data_desanexacao', 6)]) more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Anexar Matéria'), row1, row2, form_actions(more=more) ) ) super(MateriaAnexadaForm, self).__init__( *args, **kwargs) class FormularioSimplificadoForm(ModelForm): class Meta: model = MateriaLegislativa fields = ['tipo', 'numero', 'ano', 'data_apresentacao', 'numero_protocolo', 'regime_tramitacao', 'em_tramitacao', 'ementa', 'texto_original'] exclude = ['anexadas'] widgets = { 'data_apresentacao': forms.DateInput(attrs={'class': 'dateinput'}), } def clean_texto_original(self): texto_original = self.cleaned_data.get('texto_original', False) if texto_original: if texto_original.size > MAX_DOC_UPLOAD_SIZE: raise ValidationError("Arquivo muito grande. ( > 5mb )") return texto_original else: raise ValidationError("Não foi possível salvar o arquivo.") def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('tipo', 4), ('numero', 4), ('ano', 4)]) row2 = crispy_layout_mixin.to_row( [('data_apresentacao', 4), ('numero_protocolo', 4), ('regime_tramitacao', 4)]) row3 = crispy_layout_mixin.to_row( [('texto_original', 9), ('em_tramitacao', 3)]) row4 = crispy_layout_mixin.to_row( [('ementa', 12)]) self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Formulário Simplificado'), Fieldset( _('Identificação Básica'), row1, row2, row3, row4 ), form_actions() ) ) super(FormularioSimplificadoForm, self).__init__(*args, **kwargs) class FormularioCadastroForm(ModelForm): class Meta: model = MateriaLegislativa fields = ['tipo', 'numero', 'ano', 'data_apresentacao', 'numero_protocolo', 'tipo_apresentacao', 'texto_original', 'apelido', 'dias_prazo', 'polemica', 'objeto', 'regime_tramitacao', 'em_tramitacao', 'data_fim_prazo', 'data_publicacao', 'complementar', 'tipo_origem_externa', 'numero_origem_externa', 'ano_origem_externa', 'local_origem_externa', 'data_origem_externa', 'ementa', 'indexacao', 'observacao'] def __init__(self, *args, **kwargs): self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Formulário de Cadastro'), Fieldset( _('Identificação Básica'), 'tipo', 'numero', 'ano', 'data_apresentacao', 'numero_protocolo', 'tipo_apresentacao', 'texto_original' ), Fieldset( _('Outras Informações'), 'apelido', 'dias_prazo', 'polemica', 'objeto', 'regime_tramitacao', 'em_tramitacao', 'data_fim_prazo', 'data_publicacao', 'complementar' ), Fieldset( _('Origem Externa'), 'tipo_origem_externa', 'numero_origem_externa', 'ano_origem_externa', 'local_origem_externa', 'data_origem_externa' ), Fieldset( _('Dados Textuais'), 'ementa', 'indexacao', 'observacao' ), form_actions() ) ) super(FormularioCadastroForm, self).__init__(*args, **kwargs) class AutoriaForm(ModelForm): autor = forms.ModelChoiceField( label=_('Autor'), required=True, queryset=Autor.objects.all().order_by('tipo', 'nome'), ) primeiro_autor = forms.ChoiceField( label=_('Primeiro Autor'), required=True, choices=[(True, _('Sim')), (False, _('Não'))], ) class Meta: model = Autoria fields = ['autor', 'primeiro_autor', 'partido'] def __init__(self, excluir=False, *args, **kwargs): row1 = crispy_layout_mixin.to_row( [('autor', 4), ('primeiro_autor', 4), ('partido', 4)]) more = [] if excluir: more = [Submit('Excluir', 'Excluir')] self.helper = FormHelper() self.helper.layout = Layout( Fieldset( _('Adicionar Autoria'), row1, form_actions(more=more) ) ) super(AutoriaForm, self).__init__( *args, **kwargs) class RangeWidgetOverride(forms.MultiWidget): def __init__(self, attrs=None): widgets = (forms.DateInput( format='%d/%m/%Y', attrs={'class': 'dateinput'}), forms.DateInput( format='%d/%m/%Y', attrs={'class': 'dateinput'})) super(RangeWidgetOverride, self).__init__(widgets, attrs) def decompress(self, value): if value: return [value.start, value.stop] return [None, None] def format_output(self, rendered_widgets): return ''.join(rendered_widgets) class MateriaLegislativaPesquisaFields(FilterSet): numero = django_filters.CharFilter(required=False, label=u'Número da Matéria', help_text="") numero_protocolo = django_filters.CharFilter(required=False, label=u'Núm. Protocolo', help_text="") ano = django_filters.CharFilter(required=False, label=u'Ano da Matéria', help_text="") tipo = django_filters.ModelChoiceFilter( label=_('Tipo de Matéria'), required=False, queryset=TipoMateriaLegislativa.objects.all(), empty_label='Selecione', help_text="" ) data_apresentacao = django_filters.DateFromToRangeFilter( label=u'Data de Apresentação (Inicial - Final)', required=False, help_text="", widget=RangeWidgetOverride) data_publicacao = django_filters.DateFromToRangeFilter( label=u'Data da Publicação (Inicial - Final)', required=False, help_text="", widget=RangeWidgetOverride) autoria__autor = django_filters.CharFilter( widget=forms.HiddenInput(), required=False) autoria__autor__tipo = django_filters.ModelChoiceFilter( label=_('Tipo Autor'), required=False, queryset=TipoAutor.objects.all(), empty_label='Selecione', help_text="" ) autoria__partido = django_filters.ModelChoiceFilter( label=_('Partido (Autor)'), required=False, queryset=Partido.objects.all(), empty_label='Selecione', help_text="") relatoria__parlamentar_id = django_filters.ModelChoiceFilter( label='Relator', required=False, queryset=Parlamentar.objects.all().order_by('nome_parlamentar'), empty_label='Selecione', help_text="" ) local_origem_externa = django_filters.ModelChoiceFilter( label=_('Localização de Origem'), required=False, queryset=Origem.objects.all(), empty_label='Selecione', help_text="") tramitacao__unidade_tramitacao_destino = django_filters.ModelChoiceFilter( label=_('Localização Atual'), required=False, queryset=UnidadeTramitacao.objects.all(), empty_label='Selecione', help_text="" ) tramitacao__status = django_filters.ModelChoiceFilter( label='Situação', required=False, queryset=StatusTramitacao.objects.all(), empty_label='Selecione', help_text="" ) em_tramitacao = django_filters.ChoiceFilter(required=False, label='Tramitando', choices=em_tramitacao(), widget=forms.Select( attrs={'class': 'selector'}), help_text="") ementa = django_filters.CharFilter(required=False, label=u'Assunto', lookup_expr='icontains', help_text="") class Meta: models = MateriaLegislativa order_by = ( ('', 'Selecione'), ('dataC', 'Data, Tipo, Ano, Numero - Ordem Crescente'), ('dataD', 'Data, Tipo, Ano, Numero - Ordem Decrescente'), ('tipoC', 'Tipo, Ano, Numero, Data - Ordem Crescente'), ('tipoD', 'Tipo, Ano, Numero, Data - Ordem Decrescente') ) # def get_ordering_field(self, choices): # super( # MateriaLegislativaPesquisaFields, self).get_ordering_field(choices) # return forms.ChoiceField(label=_('Ordenação'), # required=False, # choices=choices) def get_order_by(self, order_value): if order_value == '': return [] elif order_value == 'dataC': return ['data_apresentacao', 'tipo__sigla', 'ano', 'numero'] elif order_value == 'dataD': return ['-data_apresentacao', '-tipo__sigla', '-ano', '-numero'] elif order_value == 'tipoC': return ['tipo__sigla', 'ano', 'numero', 'data_apresentacao'] else: return ['-tipo__sigla', '-ano', '-numero', '-data_apresentacao'] return super(MateriaLegislativaPesquisaFields, self).get_order_by(order_value) def __init__(self, *args, **kwargs): super(MateriaLegislativaPesquisaFields, self).__init__(*args, **kwargs) row1 = crispy_layout_mixin.to_row( [('tipo', 12)]) row2 = crispy_layout_mixin.to_row( [('numero', 4), ('ano', 4), ('numero_protocolo', 4)]) row3 = crispy_layout_mixin.to_row( [('data_apresentacao', 6)]) row4 = crispy_layout_mixin.to_row( [('data_publicacao', 6)]) row5 = crispy_layout_mixin.to_row( [('autoria__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)]) row6 = crispy_layout_mixin.to_row( [('autoria__autor__tipo', 6), ('autoria__partido', 6)]) row7 = crispy_layout_mixin.to_row( [('relatoria__parlamentar_id', 6), ('local_origem_externa', 6)]) row8 = crispy_layout_mixin.to_row( [('tramitacao__unidade_tramitacao_destino', 6), ('tramitacao__status', 6)]) row9 = crispy_layout_mixin.to_row( [('em_tramitacao', 6), ('o', 6)]) row10 = crispy_layout_mixin.to_row( [('ementa', 12)]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout( Fieldset(_('Pesquisa Básica'), row1, row2, row3, row4, HTML(sapl.utils.autor_label), HTML(sapl.utils.autor_modal), row5, row6, row7, row8, row9, row10, form_actions(save_label='Pesquisar')) ) def pega_ultima_tramitacao(): ultimas_tramitacoes = Tramitacao.objects.values( 'materia_id').annotate(data_encaminhamento=Max( 'data_encaminhamento'), id=Max('id')).values_list('id') lista = [item for sublist in ultimas_tramitacoes for item in sublist] return lista def filtra_tramitacao_status(status): lista = pega_ultima_tramitacao() ultimas_tramitacoes = Tramitacao.objects.filter( id__in=lista, status=status).distinct() lista = [ids.materia_id for ids in ultimas_tramitacoes] return lista def filtra_tramitacao_destino(destino): lista = pega_ultima_tramitacao() ultimas_tramitacoes = Tramitacao.objects.filter( id__in=lista, unidade_tramitacao_destino=destino).distinct() lista = [ids.materia_id for ids in ultimas_tramitacoes] return lista def filtra_tramitacao_destino_and_status(status, destino): lista = pega_ultima_tramitacao() ultimas_tramitacoes = Tramitacao.objects.filter( id__in=lista, status=status, unidade_tramitacao_destino=destino).distinct() lista = [ids.materia_id for ids in ultimas_tramitacoes] return lista