From a5fac99d0cfb11b0d94a5c6a8c49d5b116d2cd40 Mon Sep 17 00:00:00 2001 From: Edward <9326037+edwardoliveira@users.noreply.github.com> Date: Sun, 23 Jul 2023 15:55:25 -0700 Subject: [PATCH] Move relatorios para app de relatorios (#3656) --- sapl/base/forms.py | 758 ------------- sapl/base/urls.py | 66 +- sapl/base/views.py | 1010 +---------------- sapl/relatorios/forms.py | 776 +++++++++++++ sapl/relatorios/urls.py | 58 +- sapl/relatorios/views.py | 985 +++++++++++++++- sapl/templates/navbar.yaml | 2 +- .../RelatorioAtas_filter.html | 2 +- .../RelatorioAudiencia_filter.html | 2 +- ...elatorioDataFimPrazoTramitacao_filter.html | 2 +- .../RelatorioDocumentosAcessorios_filter.html | 2 +- ...elatorioHistoricoTramitacaoAdm_filter.html | 2 +- .../RelatorioHistoricoTramitacao_filter.html | 2 +- .../RelatorioMateriasAnoAssunto.html | 0 ...latorioMateriasPorAnoAutorTipo_filter.html | 2 +- .../RelatorioMateriasPorAutor_filter.html | 2 +- ...RelatorioMateriasPorTramitacao_filter.html | 6 +- .../RelatorioNormaMes_filter.html | 2 +- .../RelatorioNormasPorAutor_filter.html | 2 +- .../RelatorioNormasVigencia_filter.html | 2 +- .../RelatorioPresencaSessao_filter.html | 2 +- .../RelatorioReuniao_filter.html | 2 +- .../{base => relatorios}/relatorios_list.html | 34 +- 23 files changed, 1863 insertions(+), 1858 deletions(-) create mode 100644 sapl/relatorios/forms.py rename sapl/templates/{base => relatorios}/RelatorioAtas_filter.html (89%) rename sapl/templates/{base => relatorios}/RelatorioAudiencia_filter.html (86%) rename sapl/templates/{base => relatorios}/RelatorioDataFimPrazoTramitacao_filter.html (94%) rename sapl/templates/{base => relatorios}/RelatorioDocumentosAcessorios_filter.html (92%) rename sapl/templates/{base => relatorios}/RelatorioHistoricoTramitacaoAdm_filter.html (93%) rename sapl/templates/{base => relatorios}/RelatorioHistoricoTramitacao_filter.html (93%) rename sapl/templates/{base => relatorios}/RelatorioMateriasAnoAssunto.html (100%) rename sapl/templates/{base => relatorios}/RelatorioMateriasPorAnoAutorTipo_filter.html (93%) rename sapl/templates/{base => relatorios}/RelatorioMateriasPorAutor_filter.html (94%) rename sapl/templates/{base => relatorios}/RelatorioMateriasPorTramitacao_filter.html (92%) rename sapl/templates/{base => relatorios}/RelatorioNormaMes_filter.html (94%) rename sapl/templates/{base => relatorios}/RelatorioNormasPorAutor_filter.html (95%) rename sapl/templates/{base => relatorios}/RelatorioNormasVigencia_filter.html (93%) rename sapl/templates/{base => relatorios}/RelatorioPresencaSessao_filter.html (96%) rename sapl/templates/{base => relatorios}/RelatorioReuniao_filter.html (87%) rename sapl/templates/{base => relatorios}/relatorios_list.html (52%) diff --git a/sapl/base/forms.py b/sapl/base/forms.py index a197fc8de..8c4b629ae 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -819,157 +819,6 @@ class OperadorAutorForm(ModelForm): self.fields['user'].widget = forms.RadioSelect() -class RelatorioDocumentosAcessoriosFilterSet(django_filters.FilterSet): - - @property - def qs(self): - parent = super(RelatorioDocumentosAcessoriosFilterSet, self).qs - return parent.distinct().order_by('-data') - - class Meta(FilterOverridesMetaMixin): - model = DocumentoAcessorio - fields = ['tipo', 'materia__tipo', 'data'] - - def __init__(self, *args, **kwargs): - super( - RelatorioDocumentosAcessoriosFilterSet, self - ).__init__(*args, **kwargs) - - self.filters['tipo'].label = 'Tipo de Documento' - self.filters['materia__tipo'].label = 'Tipo de Matéria do Documento' - self.filters['data'].label = 'Período (Data Inicial - Data Final)' - - self.form.fields['tipo'].required = True - - row0 = to_row([('tipo', 6), - ('materia__tipo', 6)]) - - row1 = to_row([('data', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisa'), - row0, row1, - buttons) - ) - - -class RelatorioAtasFilterSet(django_filters.FilterSet): - class Meta(FilterOverridesMetaMixin): - model = SessaoPlenaria - fields = ['data_inicio'] - - @property - def qs(self): - parent = super(RelatorioAtasFilterSet, self).qs - return parent.distinct().prefetch_related('tipo').exclude( - upload_ata='').order_by('-data_inicio', 'tipo', 'numero') - - def __init__(self, *args, **kwargs): - super(RelatorioAtasFilterSet, self).__init__( - *args, **kwargs) - - self.filters['data_inicio'].label = 'Período de Abertura (Inicial - Final)' - self.form.fields['data_inicio'].required = False - - row1 = to_row([('data_inicio', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Atas das Sessões Plenárias'), - row1, buttons, ) - ) - - -def ultimo_ano_com_norma(): - anos_normas = choice_anos_com_normas() - - if anos_normas: - return anos_normas[0] - return '' - - -class RelatorioNormasMesFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=True, - label='Ano da Norma', - choices=choice_anos_com_normas, - initial=ultimo_ano_com_norma) - - tipo = django_filters.ChoiceFilter(required=False, - label='Tipo Norma', - choices=choice_tipos_normas, - initial=0) - - class Meta: - model = NormaJuridica - fields = ['ano'] - - def __init__(self, *args, **kwargs): - super(RelatorioNormasMesFilterSet, self).__init__( - *args, **kwargs) - - self.filters['ano'].label = 'Ano' - self.form.fields['ano'].required = True - - row1 = to_row([('ano', 6), ('tipo', 6)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Normas por mês do ano.'), - row1, buttons, ) - ) - - @property - def qs(self): - parent = super(RelatorioNormasMesFilterSet, self).qs - return parent.distinct().order_by('data') - - class EstatisticasAcessoNormasForm(Form): ano = forms.ChoiceField(required=True, label='Ano de acesso', @@ -1033,502 +882,6 @@ class EstatisticasAcessoNormasForm(Form): return self.cleaned_data -class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=True, - label='Ano da Norma', - choices=choice_anos_com_normas, - initial=ultimo_ano_com_norma) - - tipo = django_filters.ChoiceFilter(required=False, - label='Tipo Norma', - choices=choice_tipos_normas, - initial=0) - - vigencia = forms.ChoiceField( - label=_('Vigência'), - choices=[(True, "Vigente"), (False, "Não vigente")], - widget=forms.RadioSelect(), - required=True, - initial=True) - - def __init__(self, *args, **kwargs): - super(RelatorioNormasVigenciaFilterSet, self).__init__( - *args, **kwargs) - - self.filters['ano'].label = 'Ano' - self.form.fields['ano'].required = True - self.form.fields['vigencia'] = self.vigencia - - row1 = to_row([('ano', 6), ('tipo', 6)]) - row2 = to_row([('vigencia', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Normas por vigência.'), - row1, row2, - buttons, ) - ) - - @property - def qs(self): - return qs_override_django_filter(self) - - -class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet): - class Meta(FilterOverridesMetaMixin): - model = SessaoPlenaria - fields = ['data_inicio', - 'sessao_legislativa', - 'tipo', - 'legislatura'] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.form.fields['exibir_ordem_dia'] = forms.BooleanField( - required=False, label='Exibir presença das Ordens do Dia') - self.form.initial['exibir_ordem_dia'] = True - - self.form.fields['exibir_somente_titular'] = forms.BooleanField( - required=False, label='Exibir somente parlamentares titulares') - self.form.initial['exibir_somente_titular'] = False - - self.form.fields['exibir_somente_ativo'] = forms.BooleanField( - required=False, label='Exibir somente parlamentares ativos') - self.form.initial['exibir_somente_ativo'] = False - - self.form.fields['legislatura'].required = True - - self.filters['data_inicio'].label = 'Período (Inicial - Final)' - - tipo_sessao_ordinaria = self.filters['tipo'].queryset.filter( - nome='Ordinária') - if tipo_sessao_ordinaria: - self.form.initial['tipo'] = tipo_sessao_ordinaria.first() - - row1 = to_row([('legislatura', 4), - ('sessao_legislativa', 4), - ('tipo', 4)]) - row2 = to_row([('exibir_ordem_dia', 12), - ('exibir_somente_titular', 12), - ('exibir_somente_ativo', 12)]) - row3 = to_row([('data_inicio', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Presença dos parlamentares nas sessões plenárias'), - row1, row2, row3, buttons, ) - ) - - @property - def qs(self): - return qs_override_django_filter(self) - - -class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): - autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) - - @property - def qs(self): - parent = super(RelatorioHistoricoTramitacaoFilterSet, self).qs - return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') - - class Meta(FilterOverridesMetaMixin): - model = MateriaLegislativa - fields = ['tipo', 'tramitacao__status', 'tramitacao__data_tramitacao', - 'tramitacao__unidade_tramitacao_local', 'tramitacao__unidade_tramitacao_destino'] - - def __init__(self, *args, **kwargs): - super(RelatorioHistoricoTramitacaoFilterSet, self).__init__( - *args, **kwargs) - - self.filters['tipo'].label = 'Tipo de Matéria' - self.filters['tramitacao__status'].label = _('Status') - self.filters['tramitacao__unidade_tramitacao_local'].label = _( - 'Unidade Local (Origem)') - self.filters['tramitacao__unidade_tramitacao_destino'].label = _( - 'Unidade Destino') - - row1 = to_row([('tramitacao__data_tramitacao', 12)]) - row2 = to_row([('tramitacao__unidade_tramitacao_local', 6), - ('tramitacao__unidade_tramitacao_destino', 6)]) - row3 = to_row( - [('tipo', 6), - ('tramitacao__status', 6)]) - - row4 = 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'), 2) - ]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisar'), - row1, row2, row3, row4, - HTML(autor_label), - HTML(autor_modal), - buttons, ) - ) - - -class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet): - materia__ano = django_filters.ChoiceFilter(required=False, - label='Ano da Matéria', - choices=choice_anos_com_materias) - - @property - def qs(self): - parent = super(RelatorioDataFimPrazoTramitacaoFilterSet, self).qs - return parent.distinct().prefetch_related('materia__tipo').order_by('tramitacao__data_fim_prazo', 'materia__tipo', 'materia__numero') - - class Meta(FilterOverridesMetaMixin): - model = MateriaEmTramitacao - fields = ['materia__tipo', - 'tramitacao__unidade_tramitacao_local', - 'tramitacao__unidade_tramitacao_destino', - 'tramitacao__status', - 'tramitacao__data_fim_prazo'] - - def __init__(self, *args, **kwargs): - super(RelatorioDataFimPrazoTramitacaoFilterSet, self).__init__( - *args, **kwargs) - - self.filters['materia__tipo'].label = 'Tipo de Matéria' - self.filters[ - 'tramitacao__unidade_tramitacao_local'].label = 'Unidade Local (Origem)' - self.filters['tramitacao__unidade_tramitacao_destino'].label = 'Unidade Destino' - self.filters['tramitacao__status'].label = 'Status de tramitação' - - row1 = to_row([('materia__ano', 12)]) - row2 = to_row([('tramitacao__data_fim_prazo', 12)]) - row3 = to_row([('tramitacao__unidade_tramitacao_local', 6), - ('tramitacao__unidade_tramitacao_destino', 6)]) - row4 = to_row( - [('materia__tipo', 6), - ('tramitacao__status', 6)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Tramitações'), - row1, row2, row3, row4, - buttons, ) - ) - - -class RelatorioReuniaoFilterSet(django_filters.FilterSet): - - @property - def qs(self): - parent = super(RelatorioReuniaoFilterSet, self).qs - return parent.distinct().order_by('-data', 'comissao') - - class Meta: - model = Reuniao - fields = ['comissao', 'data', - 'nome', 'tema'] - - def __init__(self, *args, **kwargs): - super(RelatorioReuniaoFilterSet, self).__init__( - *args, **kwargs) - - row1 = to_row([('data', 12)]) - row2 = to_row( - [('comissao', 4), - ('nome', 4), - ('tema', 4)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Reunião de Comissão'), - row1, row2, - buttons, ) - ) - - -class RelatorioAudienciaFilterSet(django_filters.FilterSet): - - @property - def qs(self): - parent = super(RelatorioAudienciaFilterSet, self).qs - return parent.distinct().order_by('-data', 'tipo') - - class Meta: - model = AudienciaPublica - fields = ['tipo', 'data', - 'nome'] - - def __init__(self, *args, **kwargs): - super(RelatorioAudienciaFilterSet, self).__init__( - *args, **kwargs) - - row1 = to_row([('data', 12)]) - row2 = to_row( - [('tipo', 4), - ('nome', 4)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Audiência Pública'), - row1, row2, - buttons, ) - ) - - -class RelatorioMateriasTramitacaoFilterSet(django_filters.FilterSet): - materia__ano = django_filters.ChoiceFilter(required=True, - label='Ano da Matéria', - choices=choice_anos_com_materias) - - tramitacao__unidade_tramitacao_destino = django_filters.ModelChoiceFilter( - queryset=UnidadeTramitacao.objects.all(), - label=_('Unidade Atual')) - - tramitacao__status = django_filters.ModelChoiceFilter( - queryset=StatusTramitacao.objects.all(), - label=_('Status Atual')) - - materia__autores = django_filters.ModelChoiceFilter( - label='Autor da Matéria', - queryset=Autor.objects.all()) - - @property - def qs(self): - parent = super(RelatorioMateriasTramitacaoFilterSet, self).qs - return parent.distinct().order_by( - '-materia__ano', 'materia__tipo', '-materia__numero' - ) - - class Meta: - model = MateriaEmTramitacao - fields = ['materia__ano', 'materia__tipo', - 'tramitacao__unidade_tramitacao_destino', - 'tramitacao__status', 'materia__autores'] - - def __init__(self, *args, **kwargs): - super(RelatorioMateriasTramitacaoFilterSet, self).__init__( - *args, **kwargs) - - self.filters['materia__tipo'].label = 'Tipo de Matéria' - - row1 = to_row([('materia__ano', 12)]) - row2 = to_row([('materia__tipo', 12)]) - row3 = to_row([('tramitacao__unidade_tramitacao_destino', 12)]) - row4 = to_row([('tramitacao__status', 12)]) - row5 = to_row([('materia__autores', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisa de Matéria em Tramitação'), - row1, row2, row3, row4, row5, - buttons, ) - ) - - -class RelatorioMateriasPorAnoAutorTipoFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=True, - label='Ano da Matéria', - choices=choice_anos_com_materias) - - class Meta: - model = MateriaLegislativa - fields = ['ano'] - - def __init__(self, *args, **kwargs): - super(RelatorioMateriasPorAnoAutorTipoFilterSet, self).__init__( - *args, **kwargs) - - row1 = to_row( - [('ano', 12)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisa de Matéria por Ano Autor Tipo'), - row1, - buttons, ) - ) - - -class RelatorioMateriasPorAutorFilterSet(django_filters.FilterSet): - autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) - - @property - def qs(self): - parent = super().qs - return parent.distinct().order_by('-ano', '-numero', 'tipo', 'autoria__autor', '-autoria__primeiro_autor') - - class Meta(FilterOverridesMetaMixin): - model = MateriaLegislativa - fields = ['tipo', 'data_apresentacao'] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.filters['tipo'].label = 'Tipo de Matéria' - - row1 = to_row( - [('tipo', 12)]) - row2 = to_row( - [('data_apresentacao', 12)]) - row3 = 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)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisa de Matéria por Autor'), - row1, row2, - HTML(autor_label), - HTML(autor_modal), - row3, - buttons, ) - ) - - class CasaLegislativaForm(FileFieldCheckMixin, ModelForm): class Meta: @@ -1866,117 +1219,6 @@ class PartidoForm(FileFieldCheckMixin, ModelForm): return cleaned_data -class RelatorioHistoricoTramitacaoAdmFilterSet(django_filters.FilterSet): - - @property - def qs(self): - parent = super(RelatorioHistoricoTramitacaoAdmFilterSet, self).qs - return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') - - class Meta(FilterOverridesMetaMixin): - model = DocumentoAdministrativo - fields = ['tipo', 'tramitacaoadministrativo__status', - 'tramitacaoadministrativo__data_tramitacao', - 'tramitacaoadministrativo__unidade_tramitacao_local', - 'tramitacaoadministrativo__unidade_tramitacao_destino'] - - def __init__(self, *args, **kwargs): - super(RelatorioHistoricoTramitacaoAdmFilterSet, self).__init__( - *args, **kwargs) - - self.filters['tipo'].label = 'Tipo de Documento' - self.filters['tramitacaoadministrativo__status'].label = _('Status') - self.filters['tramitacaoadministrativo__unidade_tramitacao_local'].label = _( - 'Unidade Local (Origem)') - self.filters['tramitacaoadministrativo__unidade_tramitacao_destino'].label = _( - 'Unidade Destino') - - row1 = to_row([('tramitacaoadministrativo__data_tramitacao', 12)]) - row2 = to_row([('tramitacaoadministrativo__unidade_tramitacao_local', 6), - ('tramitacaoadministrativo__unidade_tramitacao_destino', 6)]) - row3 = to_row( - [('tipo', 6), - ('tramitacaoadministrativo__status', 6)]) - - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_(''), - row1, row2, row3, - buttons, ) - ) - - -class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet): - autorianorma__autor = django_filters.CharFilter(widget=forms.HiddenInput()) - - @property - def qs(self): - parent = super().qs - return parent.distinct().filter(autorianorma__primeiro_autor=True) \ - .order_by('autorianorma__autor', '-autorianorma__primeiro_autor', 'tipo', '-ano', '-numero') - - class Meta(FilterOverridesMetaMixin): - model = NormaJuridica - fields = ['tipo', 'data'] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.filters['tipo'].label = 'Tipo de Norma' - - row1 = to_row( - [('tipo', 12)]) - row2 = to_row( - [('data', 12)]) - row3 = to_row( - [('autorianorma__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)]) - buttons = FormActions( - *[ - HTML(''' -
- - -
- ''') - ], - Submit('pesquisar', _('Pesquisar'), css_class='float-right', - onclick='return true;'), - css_class='form-group row justify-content-between', - ) - - self.form.helper = SaplFormHelper() - self.form.helper.form_method = 'GET' - self.form.helper.layout = Layout( - Fieldset(_('Pesquisar'), - row1, row2, - HTML(autor_label), - HTML(autor_modal), - row3, - form_actions(label='Pesquisar')) - ) - - class SaplSearchForm(ModelSearchForm): def search(self): diff --git a/sapl/base/urls.py b/sapl/base/urls.py index 7a527f102..6733a25ec 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -3,31 +3,22 @@ import os from django.conf.urls import include, url from django.contrib.auth import views from django.contrib.auth.decorators import permission_required - from django.views.generic.base import RedirectView, TemplateView from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView, - RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView, - IndexView, UserCrud) + RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, IndexView, UserCrud) from sapl.settings import MEDIA_URL, LOGOUT_REDIRECT_URL - from .apps import AppConfig -from .forms import LoginForm from .views import (LoginSapl, AlterarSenha, AppConfigCrud, CasaLegislativaCrud, - HelpTopicView, LogotipoView, RelatorioAtasView, PesquisarAuditLogView, - RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView, - RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView, - RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, RelatorioReuniaoView, SaplSearchView, - RelatorioNormasPublicadasMesView, RelatorioNormasVigenciaView, - EstatisticasAcessoNormas, RelatoriosListView, ListarInconsistenciasView, + HelpTopicView, LogotipoView, PesquisarAuditLogView, + SaplSearchView, + ListarInconsistenciasView, ListarProtocolosDuplicadosView, ListarProtocolosComMateriasView, ListarMatProtocoloInexistenteView, ListarParlamentaresDuplicadosView, ListarFiliacoesSemDataFiliacaoView, ListarMandatoSemDataInicioView, ListarParlMandatosIntersecaoView, ListarParlFiliacoesIntersecaoView, ListarAutoresDuplicadosView, ListarBancadaComissaoAutorExternoView, ListarLegislaturaInfindavelView, - ListarAnexadasCiclicasView, ListarAnexadosCiclicosView, pesquisa_textual, - RelatorioHistoricoTramitacaoAdmView, RelatorioDocumentosAcessoriosView, RelatorioNormasPorAutorView) - + ListarAnexadasCiclicasView, ListarAnexadosCiclicosView, pesquisa_textual) app_name = AppConfig.name @@ -68,53 +59,6 @@ urlpatterns = [ name="casa_legislativa"), url(r'^sistema/app-config/', include(AppConfigCrud.get_urls())), - # TODO mover estas telas para a app 'relatorios' - url(r'^sistema/relatorios/$', - RelatoriosListView.as_view(), name='relatorios_list'), - url(r'^sistema/relatorios/materia-por-autor$', - RelatorioMateriasPorAutorView.as_view(), name='materia_por_autor'), - url(r'^sistema/relatorios/relatorio-por-mes$', - RelatorioNormasPublicadasMesView.as_view(), name='normas_por_mes'), - url(r'^sistema/relatorios/relatorio-por-vigencia$', - RelatorioNormasVigenciaView.as_view(), name='normas_por_vigencia'), - url(r'^sistema/relatorios/estatisticas-acesso$', - EstatisticasAcessoNormas.as_view(), name='estatisticas_acesso'), - url(r'^sistema/relatorios/materia-por-ano-autor-tipo$', - RelatorioMateriasPorAnoAutorTipoView.as_view(), - name='materia_por_ano_autor_tipo'), - url(r'^sistema/relatorios/materia-por-tramitacao$', - RelatorioMateriasTramitacaoView.as_view(), - name='materia_por_tramitacao'), - url(r'^sistema/relatorios/materia-por-assunto$', - RelatorioMateriaAnoAssuntoView.as_view(), - name='materia_por_ano_assunto'), - url(r'^sistema/relatorios/historico-tramitacoes$', - RelatorioHistoricoTramitacaoView.as_view(), - name='historico_tramitacoes'), - url(r'^sistema/relatorios/data-fim-prazo-tramitacoes$', - RelatorioDataFimPrazoTramitacaoView.as_view(), - name='data_fim_prazo_tramitacoes'), - url(r'^sistema/relatorios/presenca$', - RelatorioPresencaSessaoView.as_view(), - name='presenca_sessao'), - url(r'^sistema/relatorios/atas$', - RelatorioAtasView.as_view(), - name='atas'), - url(r'^sistema/relatorios/reuniao$', - RelatorioReuniaoView.as_view(), - name='reuniao'), - url(r'^sistema/relatorios/audiencia$', - RelatorioAudienciaView.as_view(), - name='audiencia'), - url(r'^sistema/relatorios/historico-tramitacoesadm$', - RelatorioHistoricoTramitacaoAdmView.as_view(), - name='historico_tramitacoes_adm'), - url(r'^sistema/relatorios/documentos_acessorios$', - RelatorioDocumentosAcessoriosView.as_view(), - name='relatorio_documentos_acessorios'), - url(r'^sistema/relatorios/normas-por-autor$', - RelatorioNormasPorAutorView.as_view(), name='normas_por_autor'), - url(r'^email/validate/(?P[0-9A-Za-z_\-]+)/' '(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})$', ConfirmarEmailView.as_view(), name='confirmar_email'), diff --git a/sapl/base/views.py b/sapl/base/views.py index 88bc57943..197a813f8 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -1,10 +1,8 @@ -from collections import OrderedDict import collections -import datetime +import collections import itertools import logging import os -import re from django.apps.registry import apps from django.contrib import messages @@ -14,11 +12,9 @@ from django.contrib.auth.models import Group from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.views import (PasswordResetView, PasswordResetConfirmView, PasswordResetCompleteView, PasswordResetDoneView) -from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError +from django.core.exceptions import PermissionDenied, ValidationError from django.core.mail import send_mail -from django.db import connection -from django.db.models import Count, Q, Max, F -from django.forms.utils import ErrorList +from django.db.models import Count, Q, Max from django.http import Http404, HttpResponseRedirect, JsonResponse from django.shortcuts import redirect from django.template import TemplateDoesNotExist @@ -37,46 +33,27 @@ from haystack.views import SearchView from ratelimit.decorators import ratelimit from sapl import settings -from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica -from sapl.base.forms import (AutorForm, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm, +from sapl.base.forms import (AutorForm, TipoAutorForm, RecuperarSenhaForm, NovaSenhaForm, UserAdminForm, AuditLogFilterSet, - OperadorAutorForm, LoginForm, SaplSearchForm) -from sapl.base.models import AuditLog, Autor, TipoAutor, OperadorAutor -from sapl.comissoes.models import Comissao, Reuniao + LoginForm, SaplSearchForm) +from sapl.base.models import AuditLog, Autor, TipoAutor +from sapl.comissoes.models import Comissao from sapl.crud.base import CrudAux, make_pagination, Crud, \ - ListWithSearchForm, MasterDetailCrud -from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, MateriaEmTramitacao, MateriaLegislativa, - Proposicao, StatusTramitacao, TipoDocumento, TipoMateriaLegislativa, UnidadeTramitacao, - MateriaAssunto) -from sapl.norma.models import NormaJuridica, TipoNormaJuridica, \ - NormaEstatisticas, ViewNormasEstatisticas + ListWithSearchForm +from sapl.materia.models import (Anexada, MateriaLegislativa, + Proposicao) +from sapl.norma.models import NormaJuridica, ViewNormasEstatisticas from sapl.parlamentares.models import ( - Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa) -from sapl.protocoloadm.models import (Anexado, DocumentoAdministrativo, Protocolo, StatusTramitacaoAdministrativo, - TipoDocumentoAdministrativo) -from sapl.relatorios.views import (relatorio_materia_em_tramitacao, relatorio_materia_por_autor, - relatorio_materia_por_ano_autor, relatorio_presenca_sessao, - relatorio_historico_tramitacao, relatorio_fim_prazo_tramitacao, relatorio_atas, - relatorio_audiencia, relatorio_normas_mes, relatorio_normas_vigencia, - relatorio_historico_tramitacao_adm, relatorio_reuniao, - relatorio_estatisticas_acesso_normas, relatorio_normas_por_autor, - relatorio_documento_acessorio) + Filiacao, Legislatura, Mandato, Parlamentar) +from sapl.protocoloadm.models import (Anexado, Protocolo) +from sapl.relatorios.views import (relatorio_estatisticas_acesso_normas) from sapl.sessao.models import ( - Bancada, PresencaOrdemDia, SessaoPlenaria, SessaoPlenariaPresenca, TipoSessaoPlenaria) + Bancada, SessaoPlenaria) from sapl.settings import EMAIL_SEND_USER -from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, parlamentares_ativos, - SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo, - google_recaptcha_configured, sapl_as_sapn, - groups_remove_user, groups_add_user, get_client_ip) - -from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, - RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, - RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet, - RelatorioMateriasPorAutorFilterSet, RelatorioMateriasTramitacaoFilterSet, - RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, - RelatorioNormasMesFilterSet, RelatorioNormasVigenciaFilterSet, EstatisticasAcessoNormasForm, - RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioDocumentosAcessoriosFilterSet, - RelatorioNormasPorAutorFilterSet) +from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, + SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, google_recaptcha_configured, sapl_as_sapn, + get_client_ip) +from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, EstatisticasAcessoNormasForm) from .models import AppConfig, CasaLegislativa @@ -337,856 +314,6 @@ class AutorCrud(CrudAux): return qs.distinct('nome', 'id').order_by('nome', 'id') -class RelatoriosListView(TemplateView): - template_name = 'base/relatorios_list.html' - - def get_context_data(self, **kwargs): - context = super(TemplateView, self).get_context_data(**kwargs) - estatisticas_acesso_normas = AppConfig.objects.first().estatisticas_acesso_normas - context['estatisticas_acesso_normas'] = True if estatisticas_acesso_normas == 'S' else False - - return context - - -class RelatorioMixin: - def get(self, request, *args, **kwargs): - super(RelatorioMixin, self).get(request) - - is_relatorio = request.GET.get('relatorio') - context = self.get_context_data(filter=self.filterset) - - if is_relatorio: - return self.relatorio(request, context) - else: - return self.render_to_response(context) - - -class RelatorioDocumentosAcessoriosView(RelatorioMixin, FilterView): - model = DocumentoAcessorio - filterset_class = RelatorioDocumentosAcessoriosFilterSet - template_name = 'base/RelatorioDocumentosAcessorios_filter.html' - relatorio = relatorio_documento_acessorio - - def get_context_data(self, **kwargs): - context = super( - RelatorioDocumentosAcessoriosView, self - ).get_context_data(**kwargs) - - context['title'] = _('Documentos Acessórios das Matérias Legislativas') - - if not self.filterset.form.is_valid(): - return context - - query_dict = self.request.GET.copy() - context['show_results'] = show_results_filter_set(query_dict) - - context['tipo_documento'] = str( - TipoDocumento.objects.get(pk=self.request.GET['tipo']) - ) - - tipo_materia = self.request.GET['materia__tipo'] - if tipo_materia: - context['tipo_materia'] = str( - TipoMateriaLegislativa.objects.get(pk=tipo_materia) - ) - else: - context['tipo_materia'] = "Não selecionado" - - data_inicial = self.request.GET['data_0'] - data_final = self.request.GET['data_1'] - if not data_inicial: - data_inicial = "Data Inicial não definida" - if not data_final: - data_final = "Data Final não definida" - context['periodo'] = ( - data_inicial + ' - ' + data_final - ) - - return context - - -class RelatorioAtasView(RelatorioMixin, FilterView): - model = SessaoPlenaria - filterset_class = RelatorioAtasFilterSet - template_name = 'base/RelatorioAtas_filter.html' - relatorio = relatorio_atas - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['title'] = _('Atas das Sessões Plenárias') - - # Verifica se os campos foram preenchidos - if not self.filterset.form.is_valid(): - return context - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['periodo'] = ( - self.request.GET['data_inicio_0'] + - ' - ' + self.request.GET['data_inicio_1']) - - return context - - -class RelatorioPresencaSessaoView(RelatorioMixin, FilterView): - logger = logging.getLogger(__name__) - model = SessaoPlenaria - filterset_class = RelatorioPresencaSessaoFilterSet - template_name = 'base/RelatorioPresencaSessao_filter.html' - relatorio = relatorio_presenca_sessao - - def get_context_data(self, **kwargs): - - context = super().get_context_data(**kwargs) - context['title'] = _('Presença dos parlamentares nas sessões') - - # Verifica se os campos foram preenchidos - if not self.filterset.form.is_valid(): - return context - - cd = self.filterset.form.cleaned_data - if not cd['data_inicio'] and not cd['sessao_legislativa'] \ - and not cd['legislatura']: - msg = _( - "Formulário inválido! Preencha pelo menos algum dos campos Período, Legislatura ou Sessão Legislativa.") - messages.error(self.request, msg) - return context - - # Caso a data tenha sido preenchida, verifica se foi preenchida - # corretamente - if self.request.GET.get('data_inicio_0') and not self.request.GET.get('data_inicio_1'): - msg = _("Formulário inválido! Preencha a data do Período Final.") - messages.error(self.request, msg) - return context - - if not self.request.GET.get('data_inicio_0') and self.request.GET.get('data_inicio_1'): - msg = _("Formulário inválido! Preencha a data do Período Inicial.") - messages.error(self.request, msg) - return context - - param0 = {} - - legislatura_pk = self.request.GET.get('legislatura') - if legislatura_pk: - param0['sessao_plenaria__legislatura_id'] = legislatura_pk - legislatura = Legislatura.objects.get(id=legislatura_pk) - context['legislatura'] = legislatura - - sessao_legislativa_pk = self.request.GET.get('sessao_legislativa') - if sessao_legislativa_pk: - param0['sessao_plenaria__sessao_legislativa_id'] = sessao_legislativa_pk - sessao_legislativa = SessaoLegislativa.objects.get( - id=sessao_legislativa_pk) - context['sessao_legislativa'] = sessao_legislativa - - tipo_sessao_plenaria_pk = self.request.GET.get('tipo') - context['tipo'] = '' - if tipo_sessao_plenaria_pk: - param0['sessao_plenaria__tipo_id'] = tipo_sessao_plenaria_pk - context['tipo'] = TipoSessaoPlenaria.objects.get( - id=tipo_sessao_plenaria_pk) - - _range = [] - - if ('data_inicio_0' in self.request.GET) and self.request.GET['data_inicio_0'] and \ - ('data_inicio_1' in self.request.GET) and self.request.GET['data_inicio_1']: - where = context['object_list'].query.where - _range = where.children[0].rhs - - elif legislatura_pk and not sessao_legislativa_pk: - _range = [legislatura.data_inicio, legislatura.data_fim] - - elif sessao_legislativa_pk: - _range = [sessao_legislativa.data_inicio, - sessao_legislativa.data_fim] - - param0.update({'sessao_plenaria__data_inicio__range': _range}) - - # Parlamentares com Mandato no intervalo de tempo (Ativos) - parlamentares_qs = parlamentares_ativos( - _range[0], _range[1]).order_by('nome_parlamentar') - parlamentares_id = parlamentares_qs.values_list('id', flat=True) - - # Presenças de cada Parlamentar em Sessões - presenca_sessao = SessaoPlenariaPresenca.objects.filter( - **param0).values_list('parlamentar_id').annotate(sessao_count=Count('id')) - - # Presenças de cada Ordem do Dia - presenca_ordem = PresencaOrdemDia.objects.filter( - **param0).values_list('parlamentar_id').annotate(sessao_count=Count('id')) - - total_ordemdia = PresencaOrdemDia.objects.filter( - **param0).distinct('sessao_plenaria__id').order_by('sessao_plenaria__id').count() - - total_sessao = context['object_list'].count() - - username = self.request.user.username - - context['exibir_somente_titular'] = self.request.GET.get( - 'exibir_somente_titular') == 'on' - context['exibir_somente_ativo'] = self.request.GET.get( - 'exibir_somente_ativo') == 'on' - - # Completa o dicionario as informacoes parlamentar/sessao/ordem - parlamentares_presencas = [] - for p in parlamentares_qs: - parlamentar = {} - m = p.mandato_set.filter(Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__gte=_range[1]) | - Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__isnull=True) | - Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1]) | - # mandato suplente - Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1])) - - m = m.last() - - if not context['exibir_somente_titular'] and not context['exibir_somente_ativo']: - parlamentar = { - 'parlamentar': p, - 'titular': m.titular if m else False, - 'sessao_porc': 0, - 'ordemdia_porc': 0 - } - elif context['exibir_somente_titular'] and not context['exibir_somente_ativo']: - if m and m.titular: - parlamentar = { - 'parlamentar': p, - 'titular': m.titular if m else False, - 'sessao_porc': 0, - 'ordemdia_porc': 0 - } - else: - continue - elif not context['exibir_somente_titular'] and context['exibir_somente_ativo']: - if p.ativo: - parlamentar = { - 'parlamentar': p, - 'titular': m.titular if m else False, - 'sessao_porc': 0, - 'ordemdia_porc': 0 - } - else: - continue - elif context['exibir_somente_titular'] and context['exibir_somente_ativo']: - if m and m.titular and p.ativo: - parlamentar = { - 'parlamentar': p, - 'titular': m.titular if m else False, - 'sessao_porc': 0, - 'ordemdia_porc': 0 - } - else: - continue - else: - continue - - try: - self.logger.debug( - F'user={username}. Tentando obter presença do parlamentar (pk={p.id}).') - sessao_count = presenca_sessao.get(parlamentar_id=p.id)[1] - except ObjectDoesNotExist as e: - self.logger.error( - F'user={username}. Erro ao obter presença do parlamentar (pk={p.id}). Definido como 0. {str(e)}') - sessao_count = 0 - try: - # Presenças de cada Ordem do Dia - self.logger.info( - F'user={username}. Tentando obter PresencaOrdemDia para o parlamentar pk={p.id}.') - ordemdia_count = presenca_ordem.get(parlamentar_id=p.id)[1] - except ObjectDoesNotExist: - self.logger.error( - F'user={username}. Erro ao obter PresencaOrdemDia para o parlamentar pk={p.id}. Definido como 0.') - ordemdia_count = 0 - - parlamentar.update({ - 'sessao_count': sessao_count, - 'ordemdia_count': ordemdia_count - }) - - if total_sessao != 0: - parlamentar.update({'sessao_porc': round( - sessao_count * 100 / total_sessao, 2)}) - if total_ordemdia != 0: - parlamentar.update({'ordemdia_porc': round( - ordemdia_count * 100 / total_ordemdia, 2)}) - - parlamentares_presencas.append(parlamentar) - - context['date_range'] = _range - context['total_ordemdia'] = total_ordemdia - context['total_sessao'] = context['object_list'].count() - context['parlamentares'] = parlamentares_presencas - context['periodo'] = f"{self.request.GET['data_inicio_0']} - {self.request.GET['data_inicio_1']}" - context['sessao_legislativa'] = '' - context['legislatura'] = '' - context['exibir_ordem'] = self.request.GET.get( - 'exibir_ordem_dia') == 'on' - - if sessao_legislativa_pk: - context['sessao_legislativa'] = SessaoLegislativa.objects.get( - id=sessao_legislativa_pk) - if legislatura_pk: - context['legislatura'] = Legislatura.objects.get(id=legislatura_pk) - # ===================================================================== - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - - return context - - -class RelatorioHistoricoTramitacaoView(RelatorioMixin, FilterView): - model = MateriaLegislativa - filterset_class = RelatorioHistoricoTramitacaoFilterSet - template_name = 'base/RelatorioHistoricoTramitacao_filter.html' - relatorio = relatorio_historico_tramitacao - - def get_context_data(self, **kwargs): - context = super(RelatorioHistoricoTramitacaoView, - self).get_context_data(**kwargs) - context['title'] = _( - 'Histórico de Tramitações de Matérias Legislativas') - if not self.filterset.form.is_valid(): - return context - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['data_tramitacao'] = (self.request.GET['tramitacao__data_tramitacao_0'] + ' - ' + - self.request.GET['tramitacao__data_tramitacao_1']) - if self.request.GET['tipo']: - tipo = self.request.GET['tipo'] - context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=tipo))) - else: - context['tipo'] = '' - - if self.request.GET['tramitacao__status']: - tramitacao_status = self.request.GET['tramitacao__status'] - context['tramitacao__status'] = ( - str(StatusTramitacao.objects.get(id=tramitacao_status))) - else: - context['tramitacao__status'] = '' - - if self.request.GET['tramitacao__unidade_tramitacao_local']: - context['tramitacao__unidade_tramitacao_local'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_local']))) - else: - context['tramitacao__unidade_tramitacao_local'] = '' - - if self.request.GET['tramitacao__unidade_tramitacao_destino']: - context['tramitacao__unidade_tramitacao_destino'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_destino']))) - else: - context['tramitacao__unidade_tramitacao_destino'] = '' - - if self.request.GET['autoria__autor']: - context['autoria__autor'] = \ - (str(Autor.objects.get( - id=self.request.GET['autoria__autor']))) - else: - context['autoria__autor'] = '' - - return context - - -class RelatorioDataFimPrazoTramitacaoView(RelatorioMixin, FilterView): - model = MateriaEmTramitacao - filterset_class = RelatorioDataFimPrazoTramitacaoFilterSet - template_name = 'base/RelatorioDataFimPrazoTramitacao_filter.html' - relatorio = relatorio_fim_prazo_tramitacao - - def get_context_data(self, **kwargs): - context = super(RelatorioDataFimPrazoTramitacaoView, - self).get_context_data(**kwargs) - context['title'] = _( - 'Relatório de tramitações em intervalo de data de fim de prazo.') - if not self.filterset.form.is_valid(): - return context - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - - context['data_fim_prazo'] = (self.request.GET['tramitacao__data_fim_prazo_0'] + ' - ' + - self.request.GET['tramitacao__data_fim_prazo_1']) - - if self.request.GET['materia__ano']: - context['ano'] = self.request.GET['materia__ano'] - else: - context['ano'] = '' - - if self.request.GET['materia__tipo']: - tipo = self.request.GET['materia__tipo'] - context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=tipo))) - else: - context['tipo'] = '' - - if self.request.GET['tramitacao__status']: - tramitacao_status = self.request.GET['tramitacao__status'] - context['tramitacao__status'] = ( - str(StatusTramitacao.objects.get(id=tramitacao_status))) - else: - context['tramitacao__status'] = '' - - if self.request.GET['tramitacao__unidade_tramitacao_local']: - context['tramitacao__unidade_tramitacao_local'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_local']))) - else: - context['tramitacao__unidade_tramitacao_local'] = '' - - if self.request.GET['tramitacao__unidade_tramitacao_destino']: - context['tramitacao__unidade_tramitacao_destino'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_destino']))) - else: - context['tramitacao__unidade_tramitacao_destino'] = '' - - return context - - -class RelatorioReuniaoView(RelatorioMixin, FilterView): - model = Reuniao - filterset_class = RelatorioReuniaoFilterSet - template_name = 'base/RelatorioReuniao_filter.html' - relatorio = relatorio_reuniao - - def get_filterset_kwargs(self, filterset_class): - super(RelatorioReuniaoView, - self).get_filterset_kwargs(filterset_class) - - kwargs = {'data': self.request.GET or None} - return kwargs - - def get_context_data(self, **kwargs): - context = super(RelatorioReuniaoView, - self).get_context_data(**kwargs) - context['title'] = _('Reunião de Comissão') - if not self.filterset.form.is_valid(): - return context - qr = self.request.GET.copy() - - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - - if self.request.GET['comissao']: - comissao = self.request.GET['comissao'] - context['comissao'] = (str(Comissao.objects.get(id=comissao))) - else: - context['comissao'] = '' - - return context - - -class RelatorioAudienciaView(RelatorioMixin, FilterView): - model = AudienciaPublica - filterset_class = RelatorioAudienciaFilterSet - template_name = 'base/RelatorioAudiencia_filter.html' - relatorio = relatorio_audiencia - - def get_filterset_kwargs(self, filterset_class): - super(RelatorioAudienciaView, - self).get_filterset_kwargs(filterset_class) - - kwargs = {'data': self.request.GET or None} - return kwargs - - def get_context_data(self, **kwargs): - context = super(RelatorioAudienciaView, - self).get_context_data(**kwargs) - context['title'] = _('Audiência Pública') - if not self.filterset.form.is_valid(): - return context - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - - if self.request.GET['tipo']: - tipo = self.request.GET['tipo'] - context['tipo'] = (str(TipoAudienciaPublica.objects.get(id=tipo))) - else: - context['tipo'] = '' - - return context - - -class RelatorioMateriasTramitacaoView(RelatorioMixin, FilterView): - model = MateriaEmTramitacao - filterset_class = RelatorioMateriasTramitacaoFilterSet - template_name = 'base/RelatorioMateriasPorTramitacao_filter.html' - relatorio = relatorio_materia_em_tramitacao - - paginate_by = 100 - - total_resultados_tipos = {} - - def get_filterset_kwargs(self, filterset_class): - data = super().get_filterset_kwargs(filterset_class) - - if data['data']: - qs = data['queryset'] - - ano_materia = data['data']['materia__ano'] - tipo_materia = data['data']['materia__tipo'] - unidade_tramitacao_destino = data['data']['tramitacao__unidade_tramitacao_destino'] - status_tramitacao = data['data']['tramitacao__status'] - autor = data['data']['materia__autores'] - - kwargs = {} - if ano_materia: - kwargs['materia__ano'] = ano_materia - if tipo_materia: - kwargs['materia__tipo'] = tipo_materia - if unidade_tramitacao_destino: - kwargs['tramitacao__unidade_tramitacao_destino'] = unidade_tramitacao_destino - if status_tramitacao: - kwargs['tramitacao__status'] = status_tramitacao - if autor: - kwargs['materia__autores'] = autor - - qs = qs.filter(**kwargs) - data['queryset'] = qs - - self.total_resultados_tipos = num_materias_por_tipo( - qs, "materia__tipo") - - return data - - def get_queryset(self): - qs = super().get_queryset() - qs = qs.select_related('materia__tipo').filter( - materia__em_tramitacao=True - ).exclude( - tramitacao__status__indicador='F' - ).order_by('-materia__ano', '-materia__numero') - return qs - - def get_context_data(self, **kwargs): - context = super( - RelatorioMateriasTramitacaoView, self - ).get_context_data(**kwargs) - - context['title'] = _('Matérias em Tramitação') - - if not self.filterset.form.is_valid(): - return context - - qr = self.request.GET.copy() - - context['qtdes'] = self.total_resultados_tipos - context['ano'] = (self.request.GET['materia__ano']) - - if self.request.GET['materia__tipo']: - tipo = self.request.GET['materia__tipo'] - context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=tipo)) - ) - else: - context['tipo'] = '' - - if self.request.GET['tramitacao__status']: - tramitacao_status = self.request.GET['tramitacao__status'] - context['tramitacao__status'] = ( - str(StatusTramitacao.objects.get(id=tramitacao_status)) - ) - else: - context['tramitacao__status'] = '' - - if self.request.GET['tramitacao__unidade_tramitacao_destino']: - context['tramitacao__unidade_tramitacao_destino'] = ( - str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacao__unidade_tramitacao_destino'] - )) - ) - else: - context['tramitacao__unidade_tramitacao_destino'] = '' - - if self.request.GET['materia__autores']: - autor = self.request.GET['materia__autores'] - context['materia__autor'] = ( - str(Autor.objects.get(id=autor)) - ) - else: - context['materia__autor'] = '' - if 'page' in qr: - del qr['page'] - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - context['show_results'] = show_results_filter_set(qr) - - paginator = context['paginator'] - page_obj = context['page_obj'] - - context['page_range'] = make_pagination( - page_obj.number, paginator.num_pages - ) - context['NO_ENTRIES_MSG'] = 'Nenhum encontrado.' - - return context - - -class RelatorioMateriasPorAnoAutorTipoView(RelatorioMixin, FilterView): - model = MateriaLegislativa - filterset_class = RelatorioMateriasPorAnoAutorTipoFilterSet - template_name = 'base/RelatorioMateriasPorAnoAutorTipo_filter.html' - relatorio = relatorio_materia_por_ano_autor - - def get_materias_autor_ano(self, ano, primeiro_autor): - - autorias = Autoria.objects.filter(materia__ano=ano, primeiro_autor=primeiro_autor).values( - 'autor', - 'materia__tipo__sigla', - 'materia__tipo__descricao').annotate( - total=Count('materia__tipo')).order_by( - 'autor', - 'materia__tipo') - - autores_ids = set([i['autor'] for i in autorias]) - - autores = dict((a.id, a) for a in Autor.objects.filter( - id__in=autores_ids)) - - relatorio = [] - visitados = set() - curr = None - - for a in autorias: - # se mudou autor, salva atual, caso existente, e reinicia `curr` - if a['autor'] not in visitados: - if curr: - relatorio.append(curr) - - curr = {} - curr['autor'] = autores[a['autor']] - curr['materia'] = [] - curr['total'] = 0 - - visitados.add(a['autor']) - - # atualiza valores - curr['materia'].append((a['materia__tipo__descricao'], a['total'])) - curr['total'] += a['total'] - # adiciona o ultimo - relatorio.append(curr) - - return relatorio - - def get_filterset_kwargs(self, filterset_class): - super(RelatorioMateriasPorAnoAutorTipoView, - self).get_filterset_kwargs(filterset_class) - - kwargs = {'data': self.request.GET or None} - return kwargs - - def get_context_data(self, **kwargs): - context = super(RelatorioMateriasPorAnoAutorTipoView, - self).get_context_data(**kwargs) - - context['title'] = _('Matérias por Ano, Autor e Tipo') - if not self.filterset.form.is_valid(): - return context - qs = context['object_list'] - context['qtdes'] = num_materias_por_tipo(qs) - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['ano'] = self.request.GET['ano'] - - if 'ano' in self.request.GET and self.request.GET['ano']: - ano = int(self.request.GET['ano']) - context['relatorio'] = self.get_materias_autor_ano(ano, True) - context['corelatorio'] = self.get_materias_autor_ano(ano, False) - else: - context['relatorio'] = [] - - return context - - -class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): - model = MateriaLegislativa - filterset_class = RelatorioMateriasPorAutorFilterSet - template_name = 'base/RelatorioMateriasPorAutor_filter.html' - relatorio = relatorio_materia_por_autor - - def get_filterset_kwargs(self, filterset_class): - super().get_filterset_kwargs(filterset_class) - kwargs = {'data': self.request.GET or None} - return kwargs - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - context['title'] = _('Matérias por Autor') - if not self.filterset.form.is_valid(): - return context - - qs = context['object_list'] - context['materias_resultado'] = list(OrderedDict.fromkeys(qs)) - context['qtdes'] = num_materias_por_tipo(qs) - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - if self.request.GET['tipo']: - tipo = int(self.request.GET['tipo']) - context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=tipo))) - else: - context['tipo'] = '' - if self.request.GET['autoria__autor']: - autor = int(self.request.GET['autoria__autor']) - context['autor'] = (str(Autor.objects.get(id=autor))) - else: - context['autor'] = '' - context['periodo'] = ( - self.request.GET['data_apresentacao_0'] + - ' - ' + self.request.GET['data_apresentacao_1']) - - return context - - -class RelatorioMateriaAnoAssuntoView(ListView): - template_name = 'base/RelatorioMateriasAnoAssunto.html' - - def get_queryset(self): - return MateriaAssunto.objects.all().values( - 'assunto_id', - assunto_materia=F('assunto__assunto'), - ano=F('materia__ano')).annotate( - total=Count('assunto_id')).order_by('-materia__ano', 'assunto_id') - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['title'] = _('Matérias por Ano e Assunto') - - # In[10]: MateriaAssunto.objects.all().values( - # ...: 'materia__ano').annotate( - # ...: total = Count('materia__ano')).order_by('-materia__ano') - - mat = MateriaLegislativa.objects.filter( - materiaassunto__isnull=True).values( - 'ano').annotate( - total=Count('ano')).order_by('-ano') - - context.update({"materias_sem_assunto": mat}) - return context - - -class RelatorioNormasPublicadasMesView(RelatorioMixin, FilterView): - model = NormaJuridica - filterset_class = RelatorioNormasMesFilterSet - template_name = 'base/RelatorioNormaMes_filter.html' - relatorio = relatorio_normas_mes - - def get_context_data(self, **kwargs): - context = super(RelatorioNormasPublicadasMesView, - self).get_context_data(**kwargs) - context['title'] = _('Normas') - - # Verifica se os campos foram preenchidos - if not self.filterset.form.is_valid(): - return context - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['ano'] = self.request.GET['ano'] - - normas_mes = collections.OrderedDict() - meses = {1: 'Janeiro', 2: 'Fevereiro', 3: 'Março', 4: 'Abril', 5: 'Maio', 6: 'Junho', - 7: 'Julho', 8: 'Agosto', 9: 'Setembro', 10: 'Outubro', 11: 'Novembro', 12: 'Dezembro'} - for norma in context['object_list']: - if not meses[norma.data.month] in normas_mes: - normas_mes[meses[norma.data.month]] = [] - normas_mes[meses[norma.data.month]].append(norma) - - context['normas_mes'] = normas_mes - - quant_normas_mes = {} - for key in normas_mes.keys(): - quant_normas_mes[key] = len(normas_mes[key]) - - context['quant_normas_mes'] = quant_normas_mes - - return context - - -class RelatorioNormasVigenciaView(RelatorioMixin, FilterView): - model = NormaJuridica - filterset_class = RelatorioNormasVigenciaFilterSet - template_name = 'base/RelatorioNormasVigencia_filter.html' - relatorio = relatorio_normas_vigencia - - def get_filterset_kwargs(self, filterset_class): - super(RelatorioNormasVigenciaView, - self).get_filterset_kwargs(filterset_class) - - kwargs = {'data': self.request.GET or None} - qs = self.get_queryset().order_by('data').distinct() - if kwargs['data']: - ano = kwargs['data']['ano'] - vigencia = kwargs['data']['vigencia'] - if ano: - qs = qs.filter(ano=ano) - - if vigencia == 'True': - qs_dt_not_null = qs.filter(data_vigencia__isnull=True) - qs = (qs_dt_not_null | qs.filter( - data_vigencia__gte=datetime.datetime.now().date())).distinct() - else: - qs = qs.filter( - data_vigencia__lt=datetime.datetime.now().date()) - - kwargs.update({ - 'queryset': qs - }) - return kwargs - - def get_context_data(self, **kwargs): - context = super(RelatorioNormasVigenciaView, - self).get_context_data(**kwargs) - context['title'] = _('Normas por vigência') - - # Verifica se os campos foram preenchidos - if not self.filterset.form.is_valid(): - return context - - normas_totais = NormaJuridica.objects.filter( - ano=self.request.GET['ano']) - - context['quant_total'] = len(normas_totais) - if self.request.GET['vigencia'] == 'True': - context['vigencia'] = 'Vigente' - context['quant_vigente'] = len(context['object_list']) - context['quant_nao_vigente'] = context['quant_total'] - \ - context['quant_vigente'] - else: - context['vigencia'] = 'Não vigente' - context['quant_nao_vigente'] = len(context['object_list']) - context['quant_vigente'] = context['quant_total'] - \ - context['quant_nao_vigente'] - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['ano'] = self.request.GET['ano'] - - return context - - class EstatisticasAcessoNormas(TemplateView): template_name = 'base/EstatisticasAcessoNormas_filter.html' @@ -2421,102 +1548,3 @@ def pesquisa_textual(request): json_dict['resultados'].append(sec_dict) return JsonResponse(json_dict) - - -class RelatorioHistoricoTramitacaoAdmView(RelatorioMixin, FilterView): - model = DocumentoAdministrativo - filterset_class = RelatorioHistoricoTramitacaoAdmFilterSet - template_name = 'base/RelatorioHistoricoTramitacaoAdm_filter.html' - relatorio = relatorio_historico_tramitacao_adm - - def get_context_data(self, **kwargs): - context = super(RelatorioHistoricoTramitacaoAdmView, - self).get_context_data(**kwargs) - context['title'] = _( - 'Histórico de Tramitações de Documento Administrativo') - if not self.filterset.form.is_valid(): - return context - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - context['data_tramitacao'] = (self.request.GET['tramitacaoadministrativo__data_tramitacao_0'] + ' - ' + - self.request.GET['tramitacaoadministrativo__data_tramitacao_1']) - if self.request.GET['tipo']: - tipo = self.request.GET['tipo'] - context['tipo'] = ( - str(TipoDocumentoAdministrativo.objects.get(id=tipo))) - else: - context['tipo'] = '' - - if self.request.GET['tramitacaoadministrativo__status']: - tramitacao_status = self.request.GET['tramitacaoadministrativo__status'] - context['tramitacaoadministrativo__status'] = ( - str(StatusTramitacaoAdministrativo.objects.get(id=tramitacao_status))) - else: - context['tramitacaoadministrativo__status'] = '' - - if self.request.GET['tramitacaoadministrativo__unidade_tramitacao_local']: - context['tramitacaoadministrativo__unidade_tramitacao_local'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacaoadministrativo__unidade_tramitacao_local']))) - else: - context['tramitacaoadministrativo__unidade_tramitacao_local'] = '' - - if self.request.GET['tramitacaoadministrativo__unidade_tramitacao_destino']: - context['tramitacaoadministrativo__unidade_tramitacao_destino'] = \ - (str(UnidadeTramitacao.objects.get( - id=self.request.GET['tramitacaoadministrativo__unidade_tramitacao_destino']))) - else: - context['tramitacaoadministrativo__unidade_tramitacao_destino'] = '' - - return context - - -class RelatorioNormasPorAutorView(RelatorioMixin, FilterView): - model = NormaJuridica - filterset_class = RelatorioNormasPorAutorFilterSet - template_name = 'base/RelatorioNormasPorAutor_filter.html' - relatorio = relatorio_normas_por_autor - - def get_filterset_kwargs(self, filterset_class): - super().get_filterset_kwargs(filterset_class) - kwargs = {'data': self.request.GET or None} - return kwargs - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - context['title'] = _('Normas por Autor') - if not self.filterset.form.is_valid(): - return context - - qtdes = {} - for tipo in TipoNormaJuridica.objects.all(): - qs = context['object_list'] - qtde = len(qs.filter(tipo_id=tipo.id)) - if qtde > 0: - qtdes[tipo] = qtde - context['qtdes'] = qtdes - - qr = self.request.GET.copy() - context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' - - context['show_results'] = show_results_filter_set(qr) - if self.request.GET['tipo']: - tipo = int(self.request.GET['tipo']) - context['tipo'] = ( - str(TipoNormaJuridica.objects.get(id=tipo))) - else: - context['tipo'] = '' - - if self.request.GET['autorianorma__autor']: - autor = int(self.request.GET['autorianorma__autor']) - context['autor'] = (str(Autor.objects.get(id=autor))) - else: - context['autor'] = '' - context['periodo'] = ( - self.request.GET['data_0'] + - ' - ' + self.request.GET['data_1']) - - return context diff --git a/sapl/relatorios/forms.py b/sapl/relatorios/forms.py new file mode 100644 index 000000000..8ac7eca02 --- /dev/null +++ b/sapl/relatorios/forms.py @@ -0,0 +1,776 @@ +import django_filters +from crispy_forms.bootstrap import (FormActions) +from crispy_forms.layout import (HTML, Button, Fieldset, + Layout, Submit) +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from sapl.audiencia.models import AudienciaPublica +from sapl.base.models import Autor +from sapl.comissoes.models import Reuniao +from sapl.crispy_layout_mixin import SaplFormHelper, to_row, form_actions +from sapl.materia.models import DocumentoAcessorio, MateriaLegislativa, MateriaEmTramitacao, UnidadeTramitacao, \ + StatusTramitacao +from sapl.norma.models import NormaJuridica +from sapl.protocoloadm.models import DocumentoAdministrativo +from sapl.sessao.models import SessaoPlenaria +from sapl.utils import FilterOverridesMetaMixin, choice_anos_com_normas, qs_override_django_filter, \ + choice_anos_com_materias, choice_tipos_normas, autor_label, autor_modal + + +class RelatorioDocumentosAcessoriosFilterSet(django_filters.FilterSet): + + @property + def qs(self): + parent = super(RelatorioDocumentosAcessoriosFilterSet, self).qs + return parent.distinct().order_by('-data') + + class Meta(FilterOverridesMetaMixin): + model = DocumentoAcessorio + fields = ['tipo', 'materia__tipo', 'data'] + + def __init__(self, *args, **kwargs): + super( + RelatorioDocumentosAcessoriosFilterSet, self + ).__init__(*args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Documento' + self.filters['materia__tipo'].label = 'Tipo de Matéria do Documento' + self.filters['data'].label = 'Período (Data Inicial - Data Final)' + + self.form.fields['tipo'].required = True + + row0 = to_row([('tipo', 6), + ('materia__tipo', 6)]) + + row1 = to_row([('data', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisa'), + row0, row1, + buttons) + ) + + +class RelatorioAtasFilterSet(django_filters.FilterSet): + class Meta(FilterOverridesMetaMixin): + model = SessaoPlenaria + fields = ['data_inicio'] + + @property + def qs(self): + parent = super(RelatorioAtasFilterSet, self).qs + return parent.distinct().prefetch_related('tipo').exclude( + upload_ata='').order_by('-data_inicio', 'tipo', 'numero') + + def __init__(self, *args, **kwargs): + super(RelatorioAtasFilterSet, self).__init__( + *args, **kwargs) + + self.filters['data_inicio'].label = 'Período de Abertura (Inicial - Final)' + self.form.fields['data_inicio'].required = False + + row1 = to_row([('data_inicio', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Atas das Sessões Plenárias'), + row1, buttons, ) + ) + + +def ultimo_ano_com_norma(): + anos_normas = choice_anos_com_normas() + + if anos_normas: + return anos_normas[0] + return '' + + +class RelatorioNormasMesFilterSet(django_filters.FilterSet): + ano = django_filters.ChoiceFilter(required=True, + label='Ano da Norma', + choices=choice_anos_com_normas, + initial=ultimo_ano_com_norma) + + tipo = django_filters.ChoiceFilter(required=False, + label='Tipo Norma', + choices=choice_tipos_normas, + initial=0) + + class Meta: + model = NormaJuridica + fields = ['ano'] + + def __init__(self, *args, **kwargs): + super(RelatorioNormasMesFilterSet, self).__init__( + *args, **kwargs) + + self.filters['ano'].label = 'Ano' + self.form.fields['ano'].required = True + + row1 = to_row([('ano', 6), ('tipo', 6)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Normas por mês do ano.'), + row1, buttons, ) + ) + + @property + def qs(self): + parent = super(RelatorioNormasMesFilterSet, self).qs + return parent.distinct().order_by('data') + + +class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet): + class Meta(FilterOverridesMetaMixin): + model = SessaoPlenaria + fields = ['data_inicio', + 'sessao_legislativa', + 'tipo', + 'legislatura'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.form.fields['exibir_ordem_dia'] = forms.BooleanField( + required=False, label='Exibir presença das Ordens do Dia') + self.form.initial['exibir_ordem_dia'] = True + + self.form.fields['exibir_somente_titular'] = forms.BooleanField( + required=False, label='Exibir somente parlamentares titulares') + self.form.initial['exibir_somente_titular'] = False + + self.form.fields['exibir_somente_ativo'] = forms.BooleanField( + required=False, label='Exibir somente parlamentares ativos') + self.form.initial['exibir_somente_ativo'] = False + + self.form.fields['legislatura'].required = True + + self.filters['data_inicio'].label = 'Período (Inicial - Final)' + + tipo_sessao_ordinaria = self.filters['tipo'].queryset.filter( + nome='Ordinária') + if tipo_sessao_ordinaria: + self.form.initial['tipo'] = tipo_sessao_ordinaria.first() + + row1 = to_row([('legislatura', 4), + ('sessao_legislativa', 4), + ('tipo', 4)]) + row2 = to_row([('exibir_ordem_dia', 12), + ('exibir_somente_titular', 12), + ('exibir_somente_ativo', 12)]) + row3 = to_row([('data_inicio', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Presença dos parlamentares nas sessões plenárias'), + row1, row2, row3, buttons, ) + ) + + @property + def qs(self): + return qs_override_django_filter(self) + + +class RelatorioHistoricoTramitacaoFilterSet(django_filters.FilterSet): + autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) + + @property + def qs(self): + parent = super(RelatorioHistoricoTramitacaoFilterSet, self).qs + return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') + + class Meta(FilterOverridesMetaMixin): + model = MateriaLegislativa + fields = ['tipo', 'tramitacao__status', 'tramitacao__data_tramitacao', + 'tramitacao__unidade_tramitacao_local', 'tramitacao__unidade_tramitacao_destino'] + + def __init__(self, *args, **kwargs): + super(RelatorioHistoricoTramitacaoFilterSet, self).__init__( + *args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Matéria' + self.filters['tramitacao__status'].label = _('Status') + self.filters['tramitacao__unidade_tramitacao_local'].label = _( + 'Unidade Local (Origem)') + self.filters['tramitacao__unidade_tramitacao_destino'].label = _( + 'Unidade Destino') + + row1 = to_row([('tramitacao__data_tramitacao', 12)]) + row2 = to_row([('tramitacao__unidade_tramitacao_local', 6), + ('tramitacao__unidade_tramitacao_destino', 6)]) + row3 = to_row( + [('tipo', 6), + ('tramitacao__status', 6)]) + + row4 = 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'), 2) + ]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisar'), + row1, row2, row3, row4, + HTML(autor_label), + HTML(autor_modal), + buttons, ) + ) + + +class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet): + materia__ano = django_filters.ChoiceFilter(required=False, + label='Ano da Matéria', + choices=choice_anos_com_materias) + + @property + def qs(self): + parent = super(RelatorioDataFimPrazoTramitacaoFilterSet, self).qs + return parent.distinct().prefetch_related('materia__tipo').order_by('tramitacao__data_fim_prazo', 'materia__tipo', 'materia__numero') + + class Meta(FilterOverridesMetaMixin): + model = MateriaEmTramitacao + fields = ['materia__tipo', + 'tramitacao__unidade_tramitacao_local', + 'tramitacao__unidade_tramitacao_destino', + 'tramitacao__status', + 'tramitacao__data_fim_prazo'] + + def __init__(self, *args, **kwargs): + super(RelatorioDataFimPrazoTramitacaoFilterSet, self).__init__( + *args, **kwargs) + + self.filters['materia__tipo'].label = 'Tipo de Matéria' + self.filters[ + 'tramitacao__unidade_tramitacao_local'].label = 'Unidade Local (Origem)' + self.filters['tramitacao__unidade_tramitacao_destino'].label = 'Unidade Destino' + self.filters['tramitacao__status'].label = 'Status de tramitação' + + row1 = to_row([('materia__ano', 12)]) + row2 = to_row([('tramitacao__data_fim_prazo', 12)]) + row3 = to_row([('tramitacao__unidade_tramitacao_local', 6), + ('tramitacao__unidade_tramitacao_destino', 6)]) + row4 = to_row( + [('materia__tipo', 6), + ('tramitacao__status', 6)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Tramitações'), + row1, row2, row3, row4, + buttons, ) + ) + + +class RelatorioReuniaoFilterSet(django_filters.FilterSet): + + @property + def qs(self): + parent = super(RelatorioReuniaoFilterSet, self).qs + return parent.distinct().order_by('-data', 'comissao') + + class Meta: + model = Reuniao + fields = ['comissao', 'data', + 'nome', 'tema'] + + def __init__(self, *args, **kwargs): + super(RelatorioReuniaoFilterSet, self).__init__( + *args, **kwargs) + + row1 = to_row([('data', 12)]) + row2 = to_row( + [('comissao', 4), + ('nome', 4), + ('tema', 4)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Reunião de Comissão'), + row1, row2, + buttons, ) + ) + + +class RelatorioAudienciaFilterSet(django_filters.FilterSet): + + @property + def qs(self): + parent = super(RelatorioAudienciaFilterSet, self).qs + return parent.distinct().order_by('-data', 'tipo') + + class Meta: + model = AudienciaPublica + fields = ['tipo', 'data', + 'nome'] + + def __init__(self, *args, **kwargs): + super(RelatorioAudienciaFilterSet, self).__init__( + *args, **kwargs) + + row1 = to_row([('data', 12)]) + row2 = to_row( + [('tipo', 4), + ('nome', 4)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Audiência Pública'), + row1, row2, + buttons, ) + ) + + +class RelatorioMateriasTramitacaoFilterSet(django_filters.FilterSet): + materia__ano = django_filters.ChoiceFilter(required=True, + label='Ano da Matéria', + choices=choice_anos_com_materias) + + tramitacao__unidade_tramitacao_destino = django_filters.ModelChoiceFilter( + queryset=UnidadeTramitacao.objects.all(), + label=_('Unidade Atual')) + + tramitacao__status = django_filters.ModelChoiceFilter( + queryset=StatusTramitacao.objects.all(), + label=_('Status Atual')) + + materia__autores = django_filters.ModelChoiceFilter( + label='Autor da Matéria', + queryset=Autor.objects.all()) + + @property + def qs(self): + parent = super(RelatorioMateriasTramitacaoFilterSet, self).qs + return parent.distinct().order_by( + '-materia__ano', 'materia__tipo', '-materia__numero' + ) + + class Meta: + model = MateriaEmTramitacao + fields = ['materia__ano', 'materia__tipo', + 'tramitacao__unidade_tramitacao_destino', + 'tramitacao__status', 'materia__autores'] + + def __init__(self, *args, **kwargs): + super(RelatorioMateriasTramitacaoFilterSet, self).__init__( + *args, **kwargs) + + self.filters['materia__tipo'].label = 'Tipo de Matéria' + + row1 = to_row([('materia__ano', 12)]) + row2 = to_row([('materia__tipo', 12)]) + row3 = to_row([('tramitacao__unidade_tramitacao_destino', 12)]) + row4 = to_row([('tramitacao__status', 12)]) + row5 = to_row([('materia__autores', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisa de Matéria em Tramitação'), + row1, row2, row3, row4, row5, + buttons, ) + ) + + +class RelatorioMateriasPorAnoAutorTipoFilterSet(django_filters.FilterSet): + ano = django_filters.ChoiceFilter(required=True, + label='Ano da Matéria', + choices=choice_anos_com_materias) + + class Meta: + model = MateriaLegislativa + fields = ['ano'] + + def __init__(self, *args, **kwargs): + super(RelatorioMateriasPorAnoAutorTipoFilterSet, self).__init__( + *args, **kwargs) + + row1 = to_row( + [('ano', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisa de Matéria por Ano Autor Tipo'), + row1, + buttons, ) + ) + + +class RelatorioMateriasPorAutorFilterSet(django_filters.FilterSet): + autoria__autor = django_filters.CharFilter(widget=forms.HiddenInput()) + + @property + def qs(self): + parent = super().qs + return parent.distinct().order_by('-ano', '-numero', 'tipo', 'autoria__autor', '-autoria__primeiro_autor') + + class Meta(FilterOverridesMetaMixin): + model = MateriaLegislativa + fields = ['tipo', 'data_apresentacao'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Matéria' + + row1 = to_row( + [('tipo', 12)]) + row2 = to_row( + [('data_apresentacao', 12)]) + row3 = 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)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisa de Matéria por Autor'), + row1, row2, + HTML(autor_label), + HTML(autor_modal), + row3, + buttons, ) + ) + + +class RelatorioHistoricoTramitacaoAdmFilterSet(django_filters.FilterSet): + + @property + def qs(self): + parent = super(RelatorioHistoricoTramitacaoAdmFilterSet, self).qs + return parent.distinct().prefetch_related('tipo').order_by('-ano', 'tipo', 'numero') + + class Meta(FilterOverridesMetaMixin): + model = DocumentoAdministrativo + fields = ['tipo', 'tramitacaoadministrativo__status', + 'tramitacaoadministrativo__data_tramitacao', + 'tramitacaoadministrativo__unidade_tramitacao_local', + 'tramitacaoadministrativo__unidade_tramitacao_destino'] + + def __init__(self, *args, **kwargs): + super(RelatorioHistoricoTramitacaoAdmFilterSet, self).__init__( + *args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Documento' + self.filters['tramitacaoadministrativo__status'].label = _('Status') + self.filters['tramitacaoadministrativo__unidade_tramitacao_local'].label = _( + 'Unidade Local (Origem)') + self.filters['tramitacaoadministrativo__unidade_tramitacao_destino'].label = _( + 'Unidade Destino') + + row1 = to_row([('tramitacaoadministrativo__data_tramitacao', 12)]) + row2 = to_row([('tramitacaoadministrativo__unidade_tramitacao_local', 6), + ('tramitacaoadministrativo__unidade_tramitacao_destino', 6)]) + row3 = to_row( + [('tipo', 6), + ('tramitacaoadministrativo__status', 6)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_(''), + row1, row2, row3, + buttons, ) + ) + + +class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet): + autorianorma__autor = django_filters.CharFilter(widget=forms.HiddenInput()) + + @property + def qs(self): + parent = super().qs + return parent.distinct().filter(autorianorma__primeiro_autor=True) \ + .order_by('autorianorma__autor', '-autorianorma__primeiro_autor', 'tipo', '-ano', '-numero') + + class Meta(FilterOverridesMetaMixin): + model = NormaJuridica + fields = ['tipo', 'data'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.filters['tipo'].label = 'Tipo de Norma' + + row1 = to_row( + [('tipo', 12)]) + row2 = to_row( + [('data', 12)]) + row3 = to_row( + [('autorianorma__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)]) + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Pesquisar'), + row1, row2, + HTML(autor_label), + HTML(autor_modal), + row3, + form_actions(label='Pesquisar')) + ) + + +class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): + ano = django_filters.ChoiceFilter(required=True, + label='Ano da Norma', + choices=choice_anos_com_normas, + initial=ultimo_ano_com_norma) + + tipo = django_filters.ChoiceFilter(required=False, + label='Tipo Norma', + choices=choice_tipos_normas, + initial=0) + + vigencia = forms.ChoiceField( + label=_('Vigência'), + choices=[(True, "Vigente"), (False, "Não vigente")], + widget=forms.RadioSelect(), + required=True, + initial=True) + + def __init__(self, *args, **kwargs): + super(RelatorioNormasVigenciaFilterSet, self).__init__( + *args, **kwargs) + + self.filters['ano'].label = 'Ano' + self.form.fields['ano'].required = True + self.form.fields['vigencia'] = self.vigencia + + row1 = to_row([('ano', 6), ('tipo', 6)]) + row2 = to_row([('vigencia', 12)]) + + buttons = FormActions( + *[ + HTML(''' +
+ + +
+ ''') + ], + Submit('pesquisar', _('Pesquisar'), css_class='float-right', + onclick='return true;'), + css_class='form-group row justify-content-between', + ) + + self.form.helper = SaplFormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Normas por vigência.'), + row1, row2, + buttons, ) + ) + + @property + def qs(self): + return qs_override_django_filter(self) diff --git a/sapl/relatorios/urls.py b/sapl/relatorios/urls.py index 03db4c6e0..e16e44162 100644 --- a/sapl/relatorios/urls.py +++ b/sapl/relatorios/urls.py @@ -4,10 +4,15 @@ from .apps import AppConfig from .views import (relatorio_capa_processo, relatorio_documento_administrativo, relatorio_espelho, relatorio_etiqueta_protocolo, relatorio_materia, - relatorio_ordem_dia, relatorio_pauta_sessao, - relatorio_protocolo, relatorio_sessao_plenaria, + relatorio_ordem_dia, relatorio_protocolo, relatorio_sessao_plenaria, resumo_ata_pdf, relatorio_sessao_plenaria_pdf, etiqueta_materia_legislativa, - relatorio_materia_tramitacao) + relatorio_materia_tramitacao, RelatoriosListView, RelatorioMateriasPorAutorView, + RelatorioNormasPublicadasMesView, RelatorioNormasVigenciaView, RelatorioMateriasPorAnoAutorTipoView, + RelatorioMateriasTramitacaoView, RelatorioMateriaAnoAssuntoView, RelatorioHistoricoTramitacaoView, + RelatorioDataFimPrazoTramitacaoView, RelatorioPresencaSessaoView, RelatorioAtasView, + RelatorioReuniaoView, RelatorioAudienciaView, RelatorioHistoricoTramitacaoAdmView, + RelatorioDocumentosAcessoriosView, RelatorioNormasPorAutorView) +from ..base.views import EstatisticasAcessoNormas app_name = AppConfig.name @@ -45,4 +50,51 @@ urlpatterns = [ url(r'^relatorios/(?P\d+)/materia-tramitacao$', relatorio_materia_tramitacao, name='relatorio_materia_tramitacao'), + + # TODO mover estas telas para a app 'relatorios' + url(r'^sistema/relatorios/$', + RelatoriosListView.as_view(), name='relatorios_list'), + url(r'^sistema/relatorios/materia-por-autor$', + RelatorioMateriasPorAutorView.as_view(), name='materia_por_autor'), + url(r'^sistema/relatorios/relatorio-por-mes$', + RelatorioNormasPublicadasMesView.as_view(), name='normas_por_mes'), + url(r'^sistema/relatorios/relatorio-por-vigencia$', + RelatorioNormasVigenciaView.as_view(), name='normas_por_vigencia'), + url(r'^sistema/relatorios/estatisticas-acesso$', + EstatisticasAcessoNormas.as_view(), name='estatisticas_acesso'), + url(r'^sistema/relatorios/materia-por-ano-autor-tipo$', + RelatorioMateriasPorAnoAutorTipoView.as_view(), + name='materia_por_ano_autor_tipo'), + url(r'^sistema/relatorios/materia-por-tramitacao$', + RelatorioMateriasTramitacaoView.as_view(), + name='materia_por_tramitacao'), + url(r'^sistema/relatorios/materia-por-assunto$', + RelatorioMateriaAnoAssuntoView.as_view(), + name='materia_por_ano_assunto'), + url(r'^sistema/relatorios/historico-tramitacoes$', + RelatorioHistoricoTramitacaoView.as_view(), + name='historico_tramitacoes'), + url(r'^sistema/relatorios/data-fim-prazo-tramitacoes$', + RelatorioDataFimPrazoTramitacaoView.as_view(), + name='data_fim_prazo_tramitacoes'), + url(r'^sistema/relatorios/presenca$', + RelatorioPresencaSessaoView.as_view(), + name='presenca_sessao'), + url(r'^sistema/relatorios/atas$', + RelatorioAtasView.as_view(), + name='atas'), + url(r'^sistema/relatorios/reuniao$', + RelatorioReuniaoView.as_view(), + name='reuniao'), + url(r'^sistema/relatorios/audiencia$', + RelatorioAudienciaView.as_view(), + name='audiencia'), + url(r'^sistema/relatorios/historico-tramitacoesadm$', + RelatorioHistoricoTramitacaoAdmView.as_view(), + name='historico_tramitacoes_adm'), + url(r'^sistema/relatorios/documentos_acessorios$', + RelatorioDocumentosAcessoriosView.as_view(), + name='relatorio_documentos_acessorios'), + url(r'^sistema/relatorios/normas-por-autor$', + RelatorioNormasPorAutorView.as_view(), name='normas_por_autor'), ] diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 5a2ce0e3d..436bc40b1 100755 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -1,32 +1,44 @@ -from datetime import datetime as dt +import collections import html import logging import re -import tempfile +from datetime import datetime as dt, datetime +import unidecode from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Count, Q, F from django.http import Http404, HttpResponse from django.template.loader import render_to_string from django.utils import timezone -from django.utils.html import strip_tags from django.utils.translation import ugettext_lazy as _ -import unidecode +from django.views.generic import TemplateView, ListView +from django_filters.views import FilterView from weasyprint import HTML, CSS -from sapl.base.models import Autor, CasaLegislativa, AppConfig as SaplAppConfig -from sapl.comissoes.models import Comissao +from sapl.audiencia.models import TipoAudienciaPublica, AudienciaPublica +from sapl.base.models import Autor, CasaLegislativa, AppConfig as SaplAppConfig, AppConfig +from sapl.comissoes.models import Comissao, Reuniao from sapl.materia.models import (Autoria, MateriaLegislativa, Numeracao, - Tramitacao, UnidadeTramitacao, ConfigEtiquetaMateriaLegislativa) -from sapl.parlamentares.models import CargoMesa, Filiacao, Parlamentar + Tramitacao, UnidadeTramitacao, ConfigEtiquetaMateriaLegislativa, MateriaAssunto, + TipoMateriaLegislativa, MateriaEmTramitacao, DocumentoAcessorio, TipoDocumento, + StatusTramitacao) +from sapl.norma.models import TipoNormaJuridica, NormaJuridica +from sapl.parlamentares.models import Filiacao, Parlamentar, SessaoLegislativa, Legislatura from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo, - TramitacaoAdministrativo) + TramitacaoAdministrativo, StatusTramitacaoAdministrativo, + TipoDocumentoAdministrativo) +from sapl.relatorios.forms import RelatorioNormasPorAutorFilterSet, RelatorioHistoricoTramitacaoAdmFilterSet, \ + RelatorioNormasVigenciaFilterSet, RelatorioNormasMesFilterSet, RelatorioMateriasPorAutorFilterSet, \ + RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioMateriasTramitacaoFilterSet, RelatorioAudienciaFilterSet, \ + RelatorioReuniaoFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, RelatorioHistoricoTramitacaoFilterSet, \ + RelatorioPresencaSessaoFilterSet, RelatorioAtasFilterSet, RelatorioDocumentosAcessoriosFilterSet from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, IntegranteMesa, JustificativaAusencia, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, SessaoPlenariaPresenca, OcorrenciaSessao, RegistroVotacao, VotoParlamentar, OradorOrdemDia, - ConsideracoesFinais, TipoExpediente, ResumoOrdenacao) + ConsideracoesFinais, ResumoOrdenacao, TipoSessaoPlenaria) from sapl.sessao.views import (get_identificacao_basica, get_mesa_diretora, get_presenca_sessao, get_expedientes, get_materias_expediente, get_oradores_expediente, @@ -37,13 +49,14 @@ from sapl.sessao.views import (get_identificacao_basica, get_mesa_diretora, get_correspondencias) from sapl.settings import MEDIA_URL from sapl.settings import STATIC_ROOT -from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data, create_barcode - +from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data, create_barcode, show_results_filter_set, \ + num_materias_por_tipo, parlamentares_ativos from .templates import (pdf_capa_processo_gerar, pdf_documento_administrativo_gerar, pdf_espelho_gerar, pdf_etiqueta_protocolo_gerar, pdf_materia_gerar, pdf_ordem_dia_gerar, pdf_pauta_sessao_gerar, pdf_protocolo_gerar, pdf_sessao_plenaria_gerar) +from sapl.crud.base import make_pagination def get_kwargs_params(request, fields): @@ -1733,3 +1746,951 @@ def relatorio_materia_tramitacao(request, pk): response.write(pdf_file) return response + + +class RelatoriosListView(TemplateView): + template_name = 'relatorios/relatorios_list.html' + + def get_context_data(self, **kwargs): + context = super(TemplateView, self).get_context_data(**kwargs) + estatisticas_acesso_normas = AppConfig.objects.first().estatisticas_acesso_normas + context['estatisticas_acesso_normas'] = True if estatisticas_acesso_normas == 'S' else False + + return context + + +class RelatorioMixin: + def get(self, request, *args, **kwargs): + super(RelatorioMixin, self).get(request) + + is_relatorio = request.GET.get('relatorio') + context = self.get_context_data(filter=self.filterset) + + if is_relatorio: + return self.relatorio(request, context) + else: + return self.render_to_response(context) + + +class RelatorioDocumentosAcessoriosView(RelatorioMixin, FilterView): + model = DocumentoAcessorio + filterset_class = RelatorioDocumentosAcessoriosFilterSet + template_name = 'relatorios/RelatorioDocumentosAcessorios_filter.html' + relatorio = relatorio_documento_acessorio + + def get_context_data(self, **kwargs): + context = super( + RelatorioDocumentosAcessoriosView, self + ).get_context_data(**kwargs) + + context['title'] = _('Documentos Acessórios das Matérias Legislativas') + + if not self.filterset.form.is_valid(): + return context + + query_dict = self.request.GET.copy() + context['show_results'] = show_results_filter_set(query_dict) + + context['tipo_documento'] = str( + TipoDocumento.objects.get(pk=self.request.GET['tipo']) + ) + + tipo_materia = self.request.GET['materia__tipo'] + if tipo_materia: + context['tipo_materia'] = str( + TipoMateriaLegislativa.objects.get(pk=tipo_materia) + ) + else: + context['tipo_materia'] = "Não selecionado" + + data_inicial = self.request.GET['data_0'] + data_final = self.request.GET['data_1'] + if not data_inicial: + data_inicial = "Data Inicial não definida" + if not data_final: + data_final = "Data Final não definida" + context['periodo'] = ( + data_inicial + ' - ' + data_final + ) + + return context + + +class RelatorioAtasView(RelatorioMixin, FilterView): + model = SessaoPlenaria + filterset_class = RelatorioAtasFilterSet + template_name = 'relatorios/RelatorioAtas_filter.html' + relatorio = relatorio_atas + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = _('Atas das Sessões Plenárias') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['periodo'] = ( + self.request.GET['data_inicio_0'] + + ' - ' + self.request.GET['data_inicio_1']) + + return context + + +class RelatorioPresencaSessaoView(RelatorioMixin, FilterView): + logger = logging.getLogger(__name__) + model = SessaoPlenaria + filterset_class = RelatorioPresencaSessaoFilterSet + template_name = 'relatorios/RelatorioPresencaSessao_filter.html' + relatorio = relatorio_presenca_sessao + + def get_context_data(self, **kwargs): + + context = super().get_context_data(**kwargs) + context['title'] = _('Presença dos parlamentares nas sessões') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + cd = self.filterset.form.cleaned_data + if not cd['data_inicio'] and not cd['sessao_legislativa'] \ + and not cd['legislatura']: + msg = _( + "Formulário inválido! Preencha pelo menos algum dos campos Período, Legislatura ou Sessão Legislativa.") + messages.error(self.request, msg) + return context + + # Caso a data tenha sido preenchida, verifica se foi preenchida + # corretamente + if self.request.GET.get('data_inicio_0') and not self.request.GET.get('data_inicio_1'): + msg = _("Formulário inválido! Preencha a data do Período Final.") + messages.error(self.request, msg) + return context + + if not self.request.GET.get('data_inicio_0') and self.request.GET.get('data_inicio_1'): + msg = _("Formulário inválido! Preencha a data do Período Inicial.") + messages.error(self.request, msg) + return context + + param0 = {} + + legislatura_pk = self.request.GET.get('legislatura') + if legislatura_pk: + param0['sessao_plenaria__legislatura_id'] = legislatura_pk + legislatura = Legislatura.objects.get(id=legislatura_pk) + context['legislatura'] = legislatura + + sessao_legislativa_pk = self.request.GET.get('sessao_legislativa') + if sessao_legislativa_pk: + param0['sessao_plenaria__sessao_legislativa_id'] = sessao_legislativa_pk + sessao_legislativa = SessaoLegislativa.objects.get( + id=sessao_legislativa_pk) + context['sessao_legislativa'] = sessao_legislativa + + tipo_sessao_plenaria_pk = self.request.GET.get('tipo') + context['tipo'] = '' + if tipo_sessao_plenaria_pk: + param0['sessao_plenaria__tipo_id'] = tipo_sessao_plenaria_pk + context['tipo'] = TipoSessaoPlenaria.objects.get( + id=tipo_sessao_plenaria_pk) + + _range = [] + + if ('data_inicio_0' in self.request.GET) and self.request.GET['data_inicio_0'] and \ + ('data_inicio_1' in self.request.GET) and self.request.GET['data_inicio_1']: + where = context['object_list'].query.where + _range = where.children[0].rhs + + elif legislatura_pk and not sessao_legislativa_pk: + _range = [legislatura.data_inicio, legislatura.data_fim] + + elif sessao_legislativa_pk: + _range = [sessao_legislativa.data_inicio, + sessao_legislativa.data_fim] + + param0.update({'sessao_plenaria__data_inicio__range': _range}) + + # Parlamentares com Mandato no intervalo de tempo (Ativos) + parlamentares_qs = parlamentares_ativos( + _range[0], _range[1]).order_by('nome_parlamentar') + parlamentares_id = parlamentares_qs.values_list('id', flat=True) + + # Presenças de cada Parlamentar em Sessões + presenca_sessao = SessaoPlenariaPresenca.objects.filter( + **param0).values_list('parlamentar_id').annotate(sessao_count=Count('id')) + + # Presenças de cada Ordem do Dia + presenca_ordem = PresencaOrdemDia.objects.filter( + **param0).values_list('parlamentar_id').annotate(sessao_count=Count('id')) + + total_ordemdia = PresencaOrdemDia.objects.filter( + **param0).distinct('sessao_plenaria__id').order_by('sessao_plenaria__id').count() + + total_sessao = context['object_list'].count() + + username = self.request.user.username + + context['exibir_somente_titular'] = self.request.GET.get( + 'exibir_somente_titular') == 'on' + context['exibir_somente_ativo'] = self.request.GET.get( + 'exibir_somente_ativo') == 'on' + + # Completa o dicionario as informacoes parlamentar/sessao/ordem + parlamentares_presencas = [] + for p in parlamentares_qs: + parlamentar = {} + m = p.mandato_set.filter(Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__gte=_range[1]) | + Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__isnull=True) | + Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1]) | + # mandato suplente + Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1])) + + m = m.last() + + if not context['exibir_somente_titular'] and not context['exibir_somente_ativo']: + parlamentar = { + 'parlamentar': p, + 'titular': m.titular if m else False, + 'sessao_porc': 0, + 'ordemdia_porc': 0 + } + elif context['exibir_somente_titular'] and not context['exibir_somente_ativo']: + if m and m.titular: + parlamentar = { + 'parlamentar': p, + 'titular': m.titular if m else False, + 'sessao_porc': 0, + 'ordemdia_porc': 0 + } + else: + continue + elif not context['exibir_somente_titular'] and context['exibir_somente_ativo']: + if p.ativo: + parlamentar = { + 'parlamentar': p, + 'titular': m.titular if m else False, + 'sessao_porc': 0, + 'ordemdia_porc': 0 + } + else: + continue + elif context['exibir_somente_titular'] and context['exibir_somente_ativo']: + if m and m.titular and p.ativo: + parlamentar = { + 'parlamentar': p, + 'titular': m.titular if m else False, + 'sessao_porc': 0, + 'ordemdia_porc': 0 + } + else: + continue + else: + continue + + try: + self.logger.debug( + F'user={username}. Tentando obter presença do parlamentar (pk={p.id}).') + sessao_count = presenca_sessao.get(parlamentar_id=p.id)[1] + except ObjectDoesNotExist as e: + self.logger.error( + F'user={username}. Erro ao obter presença do parlamentar (pk={p.id}). Definido como 0. {str(e)}') + sessao_count = 0 + try: + # Presenças de cada Ordem do Dia + self.logger.info( + F'user={username}. Tentando obter PresencaOrdemDia para o parlamentar pk={p.id}.') + ordemdia_count = presenca_ordem.get(parlamentar_id=p.id)[1] + except ObjectDoesNotExist: + self.logger.error( + F'user={username}. Erro ao obter PresencaOrdemDia para o parlamentar pk={p.id}. Definido como 0.') + ordemdia_count = 0 + + parlamentar.update({ + 'sessao_count': sessao_count, + 'ordemdia_count': ordemdia_count + }) + + if total_sessao != 0: + parlamentar.update({'sessao_porc': round( + sessao_count * 100 / total_sessao, 2)}) + if total_ordemdia != 0: + parlamentar.update({'ordemdia_porc': round( + ordemdia_count * 100 / total_ordemdia, 2)}) + + parlamentares_presencas.append(parlamentar) + + context['date_range'] = _range + context['total_ordemdia'] = total_ordemdia + context['total_sessao'] = context['object_list'].count() + context['parlamentares'] = parlamentares_presencas + context['periodo'] = f"{self.request.GET['data_inicio_0']} - {self.request.GET['data_inicio_1']}" + context['sessao_legislativa'] = '' + context['legislatura'] = '' + context['exibir_ordem'] = self.request.GET.get( + 'exibir_ordem_dia') == 'on' + + if sessao_legislativa_pk: + context['sessao_legislativa'] = SessaoLegislativa.objects.get( + id=sessao_legislativa_pk) + if legislatura_pk: + context['legislatura'] = Legislatura.objects.get(id=legislatura_pk) + # ===================================================================== + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + + return context + + +class RelatorioHistoricoTramitacaoView(RelatorioMixin, FilterView): + model = MateriaLegislativa + filterset_class = RelatorioHistoricoTramitacaoFilterSet + template_name = 'relatorios/RelatorioHistoricoTramitacao_filter.html' + relatorio = relatorio_historico_tramitacao + + def get_context_data(self, **kwargs): + context = super(RelatorioHistoricoTramitacaoView, + self).get_context_data(**kwargs) + context['title'] = _( + 'Histórico de Tramitações de Matérias Legislativas') + if not self.filterset.form.is_valid(): + return context + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['data_tramitacao'] = (self.request.GET['tramitacao__data_tramitacao_0'] + ' - ' + + self.request.GET['tramitacao__data_tramitacao_1']) + if self.request.GET['tipo']: + tipo = self.request.GET['tipo'] + context['tipo'] = ( + str(TipoMateriaLegislativa.objects.get(id=tipo))) + else: + context['tipo'] = '' + + if self.request.GET['tramitacao__status']: + tramitacao_status = self.request.GET['tramitacao__status'] + context['tramitacao__status'] = ( + str(StatusTramitacao.objects.get(id=tramitacao_status))) + else: + context['tramitacao__status'] = '' + + if self.request.GET['tramitacao__unidade_tramitacao_local']: + context['tramitacao__unidade_tramitacao_local'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_local']))) + else: + context['tramitacao__unidade_tramitacao_local'] = '' + + if self.request.GET['tramitacao__unidade_tramitacao_destino']: + context['tramitacao__unidade_tramitacao_destino'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_destino']))) + else: + context['tramitacao__unidade_tramitacao_destino'] = '' + + if self.request.GET['autoria__autor']: + context['autoria__autor'] = \ + (str(Autor.objects.get( + id=self.request.GET['autoria__autor']))) + else: + context['autoria__autor'] = '' + + return context + + +class RelatorioDataFimPrazoTramitacaoView(RelatorioMixin, FilterView): + model = MateriaEmTramitacao + filterset_class = RelatorioDataFimPrazoTramitacaoFilterSet + template_name = 'relatorios/RelatorioDataFimPrazoTramitacao_filter.html' + relatorio = relatorio_fim_prazo_tramitacao + + def get_context_data(self, **kwargs): + context = super(RelatorioDataFimPrazoTramitacaoView, + self).get_context_data(**kwargs) + context['title'] = _( + 'Relatório de tramitações em intervalo de data de fim de prazo.') + if not self.filterset.form.is_valid(): + return context + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + + context['data_fim_prazo'] = (self.request.GET['tramitacao__data_fim_prazo_0'] + ' - ' + + self.request.GET['tramitacao__data_fim_prazo_1']) + + if self.request.GET['materia__ano']: + context['ano'] = self.request.GET['materia__ano'] + else: + context['ano'] = '' + + if self.request.GET['materia__tipo']: + tipo = self.request.GET['materia__tipo'] + context['tipo'] = ( + str(TipoMateriaLegislativa.objects.get(id=tipo))) + else: + context['tipo'] = '' + + if self.request.GET['tramitacao__status']: + tramitacao_status = self.request.GET['tramitacao__status'] + context['tramitacao__status'] = ( + str(StatusTramitacao.objects.get(id=tramitacao_status))) + else: + context['tramitacao__status'] = '' + + if self.request.GET['tramitacao__unidade_tramitacao_local']: + context['tramitacao__unidade_tramitacao_local'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_local']))) + else: + context['tramitacao__unidade_tramitacao_local'] = '' + + if self.request.GET['tramitacao__unidade_tramitacao_destino']: + context['tramitacao__unidade_tramitacao_destino'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_destino']))) + else: + context['tramitacao__unidade_tramitacao_destino'] = '' + + return context + + +class RelatorioReuniaoView(RelatorioMixin, FilterView): + model = Reuniao + filterset_class = RelatorioReuniaoFilterSet + template_name = 'relatorios/RelatorioReuniao_filter.html' + relatorio = relatorio_reuniao + + def get_filterset_kwargs(self, filterset_class): + super(RelatorioReuniaoView, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + return kwargs + + def get_context_data(self, **kwargs): + context = super(RelatorioReuniaoView, + self).get_context_data(**kwargs) + context['title'] = _('Reunião de Comissão') + if not self.filterset.form.is_valid(): + return context + qr = self.request.GET.copy() + + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + + if self.request.GET['comissao']: + comissao = self.request.GET['comissao'] + context['comissao'] = (str(Comissao.objects.get(id=comissao))) + else: + context['comissao'] = '' + + return context + + +class RelatorioAudienciaView(RelatorioMixin, FilterView): + model = AudienciaPublica + filterset_class = RelatorioAudienciaFilterSet + template_name = 'relatorios/RelatorioAudiencia_filter.html' + relatorio = relatorio_audiencia + + def get_filterset_kwargs(self, filterset_class): + super(RelatorioAudienciaView, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + return kwargs + + def get_context_data(self, **kwargs): + context = super(RelatorioAudienciaView, + self).get_context_data(**kwargs) + context['title'] = _('Audiência Pública') + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + + if self.request.GET['tipo']: + tipo = self.request.GET['tipo'] + context['tipo'] = (str(TipoAudienciaPublica.objects.get(id=tipo))) + else: + context['tipo'] = '' + + return context + + +class RelatorioMateriasTramitacaoView(RelatorioMixin, FilterView): + model = MateriaEmTramitacao + filterset_class = RelatorioMateriasTramitacaoFilterSet + template_name = 'relatorios/RelatorioMateriasPorTramitacao_filter.html' + relatorio = relatorio_materia_em_tramitacao + + paginate_by = 100 + + total_resultados_tipos = {} + + def get_filterset_kwargs(self, filterset_class): + data = super().get_filterset_kwargs(filterset_class) + + if data['data']: + qs = data['queryset'] + + ano_materia = data['data']['materia__ano'] + tipo_materia = data['data']['materia__tipo'] + unidade_tramitacao_destino = data['data']['tramitacao__unidade_tramitacao_destino'] + status_tramitacao = data['data']['tramitacao__status'] + autor = data['data']['materia__autores'] + + kwargs = {} + if ano_materia: + kwargs['materia__ano'] = ano_materia + if tipo_materia: + kwargs['materia__tipo'] = tipo_materia + if unidade_tramitacao_destino: + kwargs['tramitacao__unidade_tramitacao_destino'] = unidade_tramitacao_destino + if status_tramitacao: + kwargs['tramitacao__status'] = status_tramitacao + if autor: + kwargs['materia__autores'] = autor + + qs = qs.filter(**kwargs) + data['queryset'] = qs + + self.total_resultados_tipos = num_materias_por_tipo( + qs, "materia__tipo") + + return data + + def get_queryset(self): + qs = super().get_queryset() + qs = qs.select_related('materia__tipo').filter( + materia__em_tramitacao=True + ).exclude( + tramitacao__status__indicador='F' + ).order_by('-materia__ano', '-materia__numero') + return qs + + def get_context_data(self, **kwargs): + context = super( + RelatorioMateriasTramitacaoView, self + ).get_context_data(**kwargs) + + context['title'] = _('Matérias em Tramitação') + + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + + context['qtdes'] = self.total_resultados_tipos + context['ano'] = (self.request.GET['materia__ano']) + + if self.request.GET['materia__tipo']: + tipo = self.request.GET['materia__tipo'] + context['tipo'] = ( + str(TipoMateriaLegislativa.objects.get(id=tipo)) + ) + else: + context['tipo'] = '' + + if self.request.GET['tramitacao__status']: + tramitacao_status = self.request.GET['tramitacao__status'] + context['tramitacao__status'] = ( + str(StatusTramitacao.objects.get(id=tramitacao_status)) + ) + else: + context['tramitacao__status'] = '' + + if self.request.GET['tramitacao__unidade_tramitacao_destino']: + context['tramitacao__unidade_tramitacao_destino'] = ( + str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_destino'] + )) + ) + else: + context['tramitacao__unidade_tramitacao_destino'] = '' + + if self.request.GET['materia__autores']: + autor = self.request.GET['materia__autores'] + context['materia__autor'] = ( + str(Autor.objects.get(id=autor)) + ) + else: + context['materia__autor'] = '' + if 'page' in qr: + del qr['page'] + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + context['show_results'] = show_results_filter_set(qr) + + paginator = context['paginator'] + page_obj = context['page_obj'] + + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages + ) + context['NO_ENTRIES_MSG'] = 'Nenhum encontrado.' + + return context + + +class RelatorioMateriasPorAnoAutorTipoView(RelatorioMixin, FilterView): + model = MateriaLegislativa + filterset_class = RelatorioMateriasPorAnoAutorTipoFilterSet + template_name = 'relatorios/RelatorioMateriasPorAnoAutorTipo_filter.html' + relatorio = relatorio_materia_por_ano_autor + + def get_materias_autor_ano(self, ano, primeiro_autor): + + autorias = Autoria.objects.filter(materia__ano=ano, primeiro_autor=primeiro_autor).values( + 'autor', + 'materia__tipo__sigla', + 'materia__tipo__descricao').annotate( + total=Count('materia__tipo')).order_by( + 'autor', + 'materia__tipo') + + autores_ids = set([i['autor'] for i in autorias]) + + autores = dict((a.id, a) for a in Autor.objects.filter( + id__in=autores_ids)) + + relatorio = [] + visitados = set() + curr = None + + for a in autorias: + # se mudou autor, salva atual, caso existente, e reinicia `curr` + if a['autor'] not in visitados: + if curr: + relatorio.append(curr) + + curr = {} + curr['autor'] = autores[a['autor']] + curr['materia'] = [] + curr['total'] = 0 + + visitados.add(a['autor']) + + # atualiza valores + curr['materia'].append((a['materia__tipo__descricao'], a['total'])) + curr['total'] += a['total'] + # adiciona o ultimo + relatorio.append(curr) + + return relatorio + + def get_filterset_kwargs(self, filterset_class): + super(RelatorioMateriasPorAnoAutorTipoView, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + return kwargs + + def get_context_data(self, **kwargs): + context = super(RelatorioMateriasPorAnoAutorTipoView, + self).get_context_data(**kwargs) + + context['title'] = _('Matérias por Ano, Autor e Tipo') + if not self.filterset.form.is_valid(): + return context + qs = context['object_list'] + context['qtdes'] = num_materias_por_tipo(qs) + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + if 'ano' in self.request.GET and self.request.GET['ano']: + ano = int(self.request.GET['ano']) + context['relatorio'] = self.get_materias_autor_ano(ano, True) + context['corelatorio'] = self.get_materias_autor_ano(ano, False) + else: + context['relatorio'] = [] + + return context + + +class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): + model = MateriaLegislativa + filterset_class = RelatorioMateriasPorAutorFilterSet + template_name = 'relatorios/RelatorioMateriasPorAutor_filter.html' + relatorio = relatorio_materia_por_autor + + def get_filterset_kwargs(self, filterset_class): + super().get_filterset_kwargs(filterset_class) + kwargs = {'data': self.request.GET or None} + return kwargs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['title'] = _('Matérias por Autor') + if not self.filterset.form.is_valid(): + return context + + qs = context['object_list'] + context['materias_resultado'] = list(collections.OrderedDict.fromkeys(qs)) + context['qtdes'] = num_materias_por_tipo(qs) + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + if self.request.GET['tipo']: + tipo = int(self.request.GET['tipo']) + context['tipo'] = ( + str(TipoMateriaLegislativa.objects.get(id=tipo))) + else: + context['tipo'] = '' + if self.request.GET['autoria__autor']: + autor = int(self.request.GET['autoria__autor']) + context['autor'] = (str(Autor.objects.get(id=autor))) + else: + context['autor'] = '' + context['periodo'] = ( + self.request.GET['data_apresentacao_0'] + + ' - ' + self.request.GET['data_apresentacao_1']) + + return context + + +class RelatorioMateriaAnoAssuntoView(ListView): + template_name = 'relatorios/RelatorioMateriasAnoAssunto.html' + + def get_queryset(self): + return MateriaAssunto.objects.all().values( + 'assunto_id', + assunto_materia=F('assunto__assunto'), + ano=F('materia__ano')).annotate( + total=Count('assunto_id')).order_by('-materia__ano', 'assunto_id') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = _('Matérias por Ano e Assunto') + + # In[10]: MateriaAssunto.objects.all().values( + # ...: 'materia__ano').annotate( + # ...: total = Count('materia__ano')).order_by('-materia__ano') + + mat = MateriaLegislativa.objects.filter( + materiaassunto__isnull=True).values( + 'ano').annotate( + total=Count('ano')).order_by('-ano') + + context.update({"materias_sem_assunto": mat}) + return context + + +class RelatorioNormasPublicadasMesView(RelatorioMixin, FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasMesFilterSet + template_name = 'relatorios/RelatorioNormaMes_filter.html' + relatorio = relatorio_normas_mes + + def get_context_data(self, **kwargs): + context = super(RelatorioNormasPublicadasMesView, + self).get_context_data(**kwargs) + context['title'] = _('Normas') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + normas_mes = collections.OrderedDict() + meses = {1: 'Janeiro', 2: 'Fevereiro', 3: 'Março', 4: 'Abril', 5: 'Maio', 6: 'Junho', + 7: 'Julho', 8: 'Agosto', 9: 'Setembro', 10: 'Outubro', 11: 'Novembro', 12: 'Dezembro'} + for norma in context['object_list']: + if not meses[norma.data.month] in normas_mes: + normas_mes[meses[norma.data.month]] = [] + normas_mes[meses[norma.data.month]].append(norma) + + context['normas_mes'] = normas_mes + + quant_normas_mes = {} + for key in normas_mes.keys(): + quant_normas_mes[key] = len(normas_mes[key]) + + context['quant_normas_mes'] = quant_normas_mes + + return context + + +class RelatorioNormasVigenciaView(RelatorioMixin, FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasVigenciaFilterSet + template_name = 'relatorios/RelatorioNormasVigencia_filter.html' + relatorio = relatorio_normas_vigencia + + def get_filterset_kwargs(self, filterset_class): + super(RelatorioNormasVigenciaView, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + qs = self.get_queryset().order_by('data').distinct() + if kwargs['data']: + ano = kwargs['data']['ano'] + vigencia = kwargs['data']['vigencia'] + if ano: + qs = qs.filter(ano=ano) + + if vigencia == 'True': + qs_dt_not_null = qs.filter(data_vigencia__isnull=True) + qs = (qs_dt_not_null | qs.filter( + data_vigencia__gte=datetime.now().date())).distinct() + else: + qs = qs.filter( + data_vigencia__lt=datetime.now().date()) + + kwargs.update({ + 'queryset': qs + }) + return kwargs + + def get_context_data(self, **kwargs): + context = super(RelatorioNormasVigenciaView, + self).get_context_data(**kwargs) + context['title'] = _('Normas por vigência') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + normas_totais = NormaJuridica.objects.filter( + ano=self.request.GET['ano']) + + context['quant_total'] = len(normas_totais) + if self.request.GET['vigencia'] == 'True': + context['vigencia'] = 'Vigente' + context['quant_vigente'] = len(context['object_list']) + context['quant_nao_vigente'] = context['quant_total'] - \ + context['quant_vigente'] + else: + context['vigencia'] = 'Não vigente' + context['quant_nao_vigente'] = len(context['object_list']) + context['quant_vigente'] = context['quant_total'] - \ + context['quant_nao_vigente'] + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + return context + +class RelatorioHistoricoTramitacaoAdmView(RelatorioMixin, FilterView): + model = DocumentoAdministrativo + filterset_class = RelatorioHistoricoTramitacaoAdmFilterSet + template_name = 'relatorios/RelatorioHistoricoTramitacaoAdm_filter.html' + relatorio = relatorio_historico_tramitacao_adm + + def get_context_data(self, **kwargs): + context = super(RelatorioHistoricoTramitacaoAdmView, + self).get_context_data(**kwargs) + context['title'] = _( + 'Histórico de Tramitações de Documento Administrativo') + if not self.filterset.form.is_valid(): + return context + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['data_tramitacao'] = (self.request.GET['tramitacaoadministrativo__data_tramitacao_0'] + ' - ' + + self.request.GET['tramitacaoadministrativo__data_tramitacao_1']) + if self.request.GET['tipo']: + tipo = self.request.GET['tipo'] + context['tipo'] = ( + str(TipoDocumentoAdministrativo.objects.get(id=tipo))) + else: + context['tipo'] = '' + + if self.request.GET['tramitacaoadministrativo__status']: + tramitacao_status = self.request.GET['tramitacaoadministrativo__status'] + context['tramitacaoadministrativo__status'] = ( + str(StatusTramitacaoAdministrativo.objects.get(id=tramitacao_status))) + else: + context['tramitacaoadministrativo__status'] = '' + + if self.request.GET['tramitacaoadministrativo__unidade_tramitacao_local']: + context['tramitacaoadministrativo__unidade_tramitacao_local'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacaoadministrativo__unidade_tramitacao_local']))) + else: + context['tramitacaoadministrativo__unidade_tramitacao_local'] = '' + + if self.request.GET['tramitacaoadministrativo__unidade_tramitacao_destino']: + context['tramitacaoadministrativo__unidade_tramitacao_destino'] = \ + (str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacaoadministrativo__unidade_tramitacao_destino']))) + else: + context['tramitacaoadministrativo__unidade_tramitacao_destino'] = '' + + return context + + +class RelatorioNormasPorAutorView(RelatorioMixin, FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasPorAutorFilterSet + template_name = 'relatorios/RelatorioNormasPorAutor_filter.html' + relatorio = relatorio_normas_por_autor + + def get_filterset_kwargs(self, filterset_class): + super().get_filterset_kwargs(filterset_class) + kwargs = {'data': self.request.GET or None} + return kwargs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['title'] = _('Normas por Autor') + if not self.filterset.form.is_valid(): + return context + + qtdes = {} + for tipo in TipoNormaJuridica.objects.all(): + qs = context['object_list'] + qtde = len(qs.filter(tipo_id=tipo.id)) + if qtde > 0: + qtdes[tipo] = qtde + context['qtdes'] = qtdes + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + if self.request.GET['tipo']: + tipo = int(self.request.GET['tipo']) + context['tipo'] = ( + str(TipoNormaJuridica.objects.get(id=tipo))) + else: + context['tipo'] = '' + + if self.request.GET['autorianorma__autor']: + autor = int(self.request.GET['autorianorma__autor']) + context['autor'] = (str(Autor.objects.get(id=autor))) + else: + context['autor'] = '' + context['periodo'] = ( + self.request.GET['data_0'] + + ' - ' + self.request.GET['data_1']) + + return context diff --git a/sapl/templates/navbar.yaml b/sapl/templates/navbar.yaml index bca7a7007..e4dc39c10 100644 --- a/sapl/templates/navbar.yaml +++ b/sapl/templates/navbar.yaml @@ -57,7 +57,7 @@ url: sapl.materia:proposicao_list check_permission: materia.add_proposicao - title: {% trans 'Relatórios' %} - url: sapl.base:relatorios_list + url: sapl.relatorios:relatorios_list - title: {% trans 'Sessões Plenárias' %} url: sapl.sessao:pesquisar_sessao - title: {% trans 'Tramitação em Lote' %} diff --git a/sapl/templates/base/RelatorioAtas_filter.html b/sapl/templates/relatorios/RelatorioAtas_filter.html similarity index 89% rename from sapl/templates/base/RelatorioAtas_filter.html rename to sapl/templates/relatorios/RelatorioAtas_filter.html index 4c55c69d5..fa91bb73d 100644 --- a/sapl/templates/base/RelatorioAtas_filter.html +++ b/sapl/templates/relatorios/RelatorioAtas_filter.html @@ -10,7 +10,7 @@ {% if filter_url %}


PERÍODO: {{ periodo }}


diff --git a/sapl/templates/base/RelatorioAudiencia_filter.html b/sapl/templates/relatorios/RelatorioAudiencia_filter.html similarity index 86% rename from sapl/templates/base/RelatorioAudiencia_filter.html rename to sapl/templates/relatorios/RelatorioAudiencia_filter.html index d41bd04d1..14867cb89 100644 --- a/sapl/templates/base/RelatorioAudiencia_filter.html +++ b/sapl/templates/relatorios/RelatorioAudiencia_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



{% if object_list|length > 0 %} diff --git a/sapl/templates/base/RelatorioDataFimPrazoTramitacao_filter.html b/sapl/templates/relatorios/RelatorioDataFimPrazoTramitacao_filter.html similarity index 94% rename from sapl/templates/base/RelatorioDataFimPrazoTramitacao_filter.html rename to sapl/templates/relatorios/RelatorioDataFimPrazoTramitacao_filter.html index 14944cca8..953169f7c 100644 --- a/sapl/templates/base/RelatorioDataFimPrazoTramitacao_filter.html +++ b/sapl/templates/relatorios/RelatorioDataFimPrazoTramitacao_filter.html @@ -8,7 +8,7 @@ {% crispy filter.form %} {% else %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioDocumentosAcessorios_filter.html b/sapl/templates/relatorios/RelatorioDocumentosAcessorios_filter.html similarity index 92% rename from sapl/templates/base/RelatorioDocumentosAcessorios_filter.html rename to sapl/templates/relatorios/RelatorioDocumentosAcessorios_filter.html index 0649a0624..92488fa8c 100644 --- a/sapl/templates/base/RelatorioDocumentosAcessorios_filter.html +++ b/sapl/templates/relatorios/RelatorioDocumentosAcessorios_filter.html @@ -7,7 +7,7 @@ {% crispy filter.form %} {% else %}



PARÂMETROS DE PESQUISA
diff --git a/sapl/templates/base/RelatorioHistoricoTramitacaoAdm_filter.html b/sapl/templates/relatorios/RelatorioHistoricoTramitacaoAdm_filter.html similarity index 93% rename from sapl/templates/base/RelatorioHistoricoTramitacaoAdm_filter.html rename to sapl/templates/relatorios/RelatorioHistoricoTramitacaoAdm_filter.html index ba0488aac..6a92f9128 100644 --- a/sapl/templates/base/RelatorioHistoricoTramitacaoAdm_filter.html +++ b/sapl/templates/relatorios/RelatorioHistoricoTramitacaoAdm_filter.html @@ -8,7 +8,7 @@ {% crispy filter.form %} {% else %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html b/sapl/templates/relatorios/RelatorioHistoricoTramitacao_filter.html similarity index 93% rename from sapl/templates/base/RelatorioHistoricoTramitacao_filter.html rename to sapl/templates/relatorios/RelatorioHistoricoTramitacao_filter.html index eacfcc709..16fd7c003 100644 --- a/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html +++ b/sapl/templates/relatorios/RelatorioHistoricoTramitacao_filter.html @@ -8,7 +8,7 @@ {% crispy filter.form %} {% else %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioMateriasAnoAssunto.html b/sapl/templates/relatorios/RelatorioMateriasAnoAssunto.html similarity index 100% rename from sapl/templates/base/RelatorioMateriasAnoAssunto.html rename to sapl/templates/relatorios/RelatorioMateriasAnoAssunto.html diff --git a/sapl/templates/base/RelatorioMateriasPorAnoAutorTipo_filter.html b/sapl/templates/relatorios/RelatorioMateriasPorAnoAutorTipo_filter.html similarity index 93% rename from sapl/templates/base/RelatorioMateriasPorAnoAutorTipo_filter.html rename to sapl/templates/relatorios/RelatorioMateriasPorAnoAutorTipo_filter.html index 561fd671c..895bfc7ba 100644 --- a/sapl/templates/base/RelatorioMateriasPorAnoAutorTipo_filter.html +++ b/sapl/templates/relatorios/RelatorioMateriasPorAnoAutorTipo_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioMateriasPorAutor_filter.html b/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html similarity index 94% rename from sapl/templates/base/RelatorioMateriasPorAutor_filter.html rename to sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html index 2690b5d4e..5acb303c1 100644 --- a/sapl/templates/base/RelatorioMateriasPorAutor_filter.html +++ b/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html b/sapl/templates/relatorios/RelatorioMateriasPorTramitacao_filter.html similarity index 92% rename from sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html rename to sapl/templates/relatorios/RelatorioMateriasPorTramitacao_filter.html index 869c08c1d..c0ef7e9b7 100644 --- a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html +++ b/sapl/templates/relatorios/RelatorioMateriasPorTramitacao_filter.html @@ -9,7 +9,7 @@ {% if filter_url %}



PARÂMETROS DE PESQUISA:
@@ -72,6 +72,8 @@ {% endfor %} {% endif %} - {% include 'paginacao.html' %} + {% if page.object_list %} + {% include "paginacao.html" %} + {% endif %}
{% endblock base_content %} diff --git a/sapl/templates/base/RelatorioNormaMes_filter.html b/sapl/templates/relatorios/RelatorioNormaMes_filter.html similarity index 94% rename from sapl/templates/base/RelatorioNormaMes_filter.html rename to sapl/templates/relatorios/RelatorioNormaMes_filter.html index 3a9276657..717f6bb5a 100644 --- a/sapl/templates/base/RelatorioNormaMes_filter.html +++ b/sapl/templates/relatorios/RelatorioNormaMes_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioNormasPorAutor_filter.html b/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html similarity index 95% rename from sapl/templates/base/RelatorioNormasPorAutor_filter.html rename to sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html index aaf5247a9..c3f045301 100644 --- a/sapl/templates/base/RelatorioNormasPorAutor_filter.html +++ b/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioNormasVigencia_filter.html b/sapl/templates/relatorios/RelatorioNormasVigencia_filter.html similarity index 93% rename from sapl/templates/base/RelatorioNormasVigencia_filter.html rename to sapl/templates/relatorios/RelatorioNormasVigencia_filter.html index 3b2a3206f..b53fe6e67 100644 --- a/sapl/templates/base/RelatorioNormasVigencia_filter.html +++ b/sapl/templates/relatorios/RelatorioNormasVigencia_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



PARÂMETROS DE PESQUISA:
diff --git a/sapl/templates/base/RelatorioPresencaSessao_filter.html b/sapl/templates/relatorios/RelatorioPresencaSessao_filter.html similarity index 96% rename from sapl/templates/base/RelatorioPresencaSessao_filter.html rename to sapl/templates/relatorios/RelatorioPresencaSessao_filter.html index 9688ab33f..3d4b2e785 100644 --- a/sapl/templates/base/RelatorioPresencaSessao_filter.html +++ b/sapl/templates/relatorios/RelatorioPresencaSessao_filter.html @@ -16,7 +16,7 @@



PERÍODO: {{periodo}}
diff --git a/sapl/templates/base/RelatorioReuniao_filter.html b/sapl/templates/relatorios/RelatorioReuniao_filter.html similarity index 87% rename from sapl/templates/base/RelatorioReuniao_filter.html rename to sapl/templates/relatorios/RelatorioReuniao_filter.html index 8bd1e7f35..8e50742a9 100644 --- a/sapl/templates/base/RelatorioReuniao_filter.html +++ b/sapl/templates/relatorios/RelatorioReuniao_filter.html @@ -9,7 +9,7 @@ {% if show_results %}



{% if object_list|length > 0 %} diff --git a/sapl/templates/base/relatorios_list.html b/sapl/templates/relatorios/relatorios_list.html similarity index 52% rename from sapl/templates/base/relatorios_list.html rename to sapl/templates/relatorios/relatorios_list.html index 8fe5535fe..5f77a5e6a 100644 --- a/sapl/templates/base/relatorios_list.html +++ b/sapl/templates/relatorios/relatorios_list.html @@ -13,69 +13,69 @@ - Matérias em tramitação + Matérias em tramitação Matérias Legislativas por Ano, Tipo, Local atual e Status da Tramitação informados. - Matérias por Autor + Matérias por Autor Listagem e totalização de matérias por autor, com filtros para tipo e período. - Matérias por Ano, Autor e Tipo + Matérias por Ano, Autor e Tipo Totalização anual de matérias agrupadas por autor e tipo. - Matérias por Ano, Assunto + Matérias por Ano, Assunto Totalização de matérias agrupadas por ano e assunto. - Presença nas sessões + Presença nas sessões Presença dos parlamentares nas sessões plenárias. - Atas + Atas Atas de Sessão Plenária. - Histórico de tramitações de Matérias + Histórico de tramitações de Matérias Histórico de tramitações por período e local informados. - Matérias por prazos de Tramitação + Matérias por prazos de Tramitação Relatório de tramitações em intervalo de data de fim de prazo. - Reunião de Comissão + Reunião de Comissão Reunião de Comissão por data. - Audiência Pública + Audiência Pública Audiência Pública com o tipo. - Normas por mês + Normas por mês Normas publicadas por mês. - Normas por vigência + Normas por vigência Normas vigentes ou não vigentes. - Histórico de tramitações de Documentos - Histórico de tramitações de Documentos por período e local informados. + Histórico de tramitações de documentos + Histórico de tramitações de documentos por período e local informados. {% if estatisticas_acesso_normas %} - Estatísticas de acesso de Normas + Estatísticas de acesso de Normas Normas por acesso. {% endif %} - Documentos Acessórios de Matérias Legislativas + Documentos Acessórios de Matérias Legislativas Documentos Acessórios por tipo, período e tipo da Matéria Legislativa associada. - Normas Por Autor + Normas Por Autor Listagem e totalização de normas por autor, com filtros para tipo e período.