diff --git a/sapl/base/forms.py b/sapl/base/forms.py index e3ec2b6a9..d111e7f4c 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -18,27 +18,25 @@ from django.utils.translation import string_concat from django.utils.translation import ugettext_lazy as _ import django_filters -from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica -from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica +from sapl.audiencia.models import AudienciaPublica from sapl.base.models import Autor, TipoAutor -from sapl.comissoes.models import Reuniao, Comissao -from sapl.comissoes.models import Reuniao, Comissao -from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, - to_row) -from sapl.crispy_layout_mixin import SaplFormHelper -from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao, - DocumentoAcessorio, TipoMateriaLegislativa) -from sapl.norma.models import (NormaJuridica, NormaEstatisticas) -from sapl.parlamentares.models import SessaoLegislativa, Partido +from sapl.comissoes.models import Reuniao +from sapl.crispy_layout_mixin import (form_actions, to_column, to_row, + SaplFormHelper, SaplFormLayout) +from sapl.materia.models import (DocumentoAcessorio, MateriaEmTramitacao, + MateriaLegislativa, UnidadeTramitacao, + StatusTramitacao) +from sapl.norma.models import NormaJuridica +from sapl.parlamentares.models import Partido, SessaoLegislativa from sapl.protocoloadm.models import DocumentoAdministrativo from sapl.sessao.models import SessaoPlenaria from sapl.settings import MAX_IMAGE_UPLOAD_SIZE -from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, - ChoiceWithoutValidationField, ImageThumbnailFileInput, - RangeWidgetOverride, autor_label, autor_modal, - models_with_gr_for_model, qs_override_django_filter, +from sapl.utils import (autor_label, autor_modal, ChoiceWithoutValidationField, choice_anos_com_normas, choice_anos_com_materias, - FilterOverridesMetaMixin, FileFieldCheckMixin) + FilterOverridesMetaMixin, FileFieldCheckMixin, + ImageThumbnailFileInput, models_with_gr_for_model, + qs_override_django_filter, RangeWidgetOverride, + RANGE_ANOS, YES_NO_CHOICES) from .models import AppConfig, CasaLegislativa @@ -1089,9 +1087,9 @@ class RelatorioAudienciaFilterSet(django_filters.FilterSet): ) -class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): +class RelatorioMateriasTramitacaoFilterSet(django_filters.FilterSet): - ano = django_filters.ChoiceFilter(required=True, + materia__ano = django_filters.ChoiceFilter(required=True, label='Ano da Matéria', choices=choice_anos_com_materias) @@ -1105,22 +1103,25 @@ class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): @property def qs(self): - parent = super(RelatorioMateriasTramitacaoilterSet, self).qs - return parent.distinct().order_by('-ano', 'tipo', '-numero') + parent = super(RelatorioMateriasTramitacaoFilterSet, self).qs + return parent.distinct().order_by( + '-materia__ano', 'materia__tipo', '-materia__numero' + ) class Meta: - model = MateriaLegislativa - fields = ['ano', 'tipo', 'tramitacao__unidade_tramitacao_destino', + model = MateriaEmTramitacao + fields = ['materia__ano', 'materia__tipo', + 'tramitacao__unidade_tramitacao_destino', 'tramitacao__status'] def __init__(self, *args, **kwargs): - super(RelatorioMateriasTramitacaoilterSet, self).__init__( + super(RelatorioMateriasTramitacaoFilterSet, self).__init__( *args, **kwargs) - self.filters['tipo'].label = 'Tipo de Matéria' + self.filters['materia__tipo'].label = 'Tipo de Matéria' - row1 = to_row([('ano', 12)]) - row2 = to_row([('tipo', 12)]) + 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)]) @@ -1576,4 +1577,4 @@ class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet): HTML(autor_modal), row3, form_actions(label='Pesquisar')) - ) \ No newline at end of file + ) diff --git a/sapl/base/views.py b/sapl/base/views.py index da9698702..c54dc34cd 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -13,7 +13,8 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, Validat from django.core.mail import send_mail from django.core.urlresolvers import reverse, reverse_lazy from django.db import connection -from django.db.models import Count, Q, ProtectedError +from django.db.models import Count, Q, ProtectedError, Max +from django.shortcuts import render from django.http import Http404, HttpResponseRedirect, JsonResponse from django.template import TemplateDoesNotExist from django.template.loader import get_template @@ -31,23 +32,26 @@ from haystack.query import SearchQuerySet from sapl import settings from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica -from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm from sapl.base.models import Autor, TipoAutor -from sapl.comissoes.models import Reuniao, Comissao +from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm +from sapl.comissoes.models import Comissao, Reuniao from sapl.crud.base import CrudAux, make_pagination -from sapl.materia.models import (Autoria, MateriaLegislativa, Proposicao, Anexada, - TipoMateriaLegislativa, StatusTramitacao, UnidadeTramitacao, - DocumentoAcessorio, TipoDocumento) -from sapl.norma.models import (NormaJuridica, TipoNormaJuridica, NormaEstatisticas) -from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato, Filiacao, SessaoLegislativa -from sapl.protocoloadm.models import (Protocolo, TipoDocumentoAdministrativo, - StatusTramitacaoAdministrativo, - DocumentoAdministrativo, Anexado) -from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, - SessaoPlenariaPresenca, Bancada, TipoSessaoPlenaria) -from sapl.utils import (parlamentares_ativos, gerar_hash_arquivo, SEPARADOR_HASH_PROPOSICAO, - show_results_filter_set, mail_service_configured, - intervalos_tem_intersecao, remover_acentos) +from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, + MateriaEmTramitacao, MateriaLegislativa, Proposicao, + StatusTramitacao, TipoDocumento, + TipoMateriaLegislativa, UnidadeTramitacao, Tramitacao) +from sapl.norma.models import NormaJuridica, TipoNormaJuridica +from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato, Parlamentar, + SessaoLegislativa) +from sapl.protocoloadm.models import (Anexado, DocumentoAdministrativo, Protocolo, + StatusTramitacaoAdministrativo, + TipoDocumentoAdministrativo) +from sapl.sessao.models import (Bancada, PresencaOrdemDia, SessaoPlenaria, + SessaoPlenariaPresenca, TipoSessaoPlenaria) +from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, + mail_service_configured, parlamentares_ativos, + SEPARADOR_HASH_PROPOSICAO, show_results_filter_set) + from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, RelatorioAudienciaFilterSet, @@ -55,7 +59,7 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioMateriasPorAutorFilterSet, - RelatorioMateriasTramitacaoilterSet, + RelatorioMateriasTramitacaoFilterSet, RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, UsuarioEditForm, RelatorioNormasMesFilterSet, @@ -67,19 +71,6 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, from .models import AppConfig, CasaLegislativa -def filtra_url_materias_em_tramitacao(qr, qs, campo_url, local_ou_status): - id_materias = [] - filtro_url = qr[campo_url] - if local_ou_status == 'local': - id_materias = [item.id for item in qs if item.tramitacao_set.order_by( - '-id').first().unidade_tramitacao_destino_id == int(filtro_url)] - elif local_ou_status == 'status': - id_materias = [item.id for item in qs if item.tramitacao_set.order_by( - '-id').first().status_id == int(filtro_url)] - - return qs.filter(em_tramitacao=True, id__in=id_materias) - - def get_casalegislativa(): return CasaLegislativa.objects.first() @@ -703,61 +694,108 @@ class RelatorioAudienciaView(FilterView): class RelatorioMateriasTramitacaoView(FilterView): - model = MateriaLegislativa - filterset_class = RelatorioMateriasTramitacaoilterSet + model = MateriaEmTramitacao + filterset_class = RelatorioMateriasTramitacaoFilterSet template_name = 'base/RelatorioMateriasPorTramitacao_filter.html' + 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'] + + 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 + qs = qs.filter(**kwargs) + + data['queryset'] = qs + + qtdes = { tipo:0 for tipo in TipoMateriaLegislativa.objects.all() } + for i in qs: + qtdes[i.materia.tipo] += 1 + + # remove as entradas de valor igual a zero + qtdes = {k:v for k,v in qtdes.items() if v > 0} + self.total_resultados_tipos = qtdes + + 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 = 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() - qs = context['object_list'] - qs = qs.filter(em_tramitacao=True) - - if qr.get('tramitacao__unidade_tramitacao_destino'): - qs = filtra_url_materias_em_tramitacao( - qr, qs, 'tramitacao__unidade_tramitacao_destino', 'local') - if qr.get('tramitacao__status'): - qs = filtra_url_materias_em_tramitacao( - qr, qs, 'tramitacao__status', 'status') - li = [li1 for li1 in qs if li1.tramitacao_set.last() and li1.tramitacao_set.last().status.indicador != 'F'] - context['object_list'] = li + context['qtdes'] = self.total_resultados_tipos + context['ano'] = (self.request.GET['materia__ano']) - qtdes = {} - for tipo in TipoMateriaLegislativa.objects.all(): - li = context['object_list'] - qtde = sum(1 for i in li if i.tipo_id==tipo.id) - if qtde > 0: - qtdes[tipo] = qtde - context['qtdes'] = qtdes - context['ano'] = (self.request.GET['ano']) - if self.request.GET['tipo']: - tipo = self.request.GET['tipo'] + if self.request.GET['materia__tipo']: + tipo = self.request.GET['materia__tipo'] context['tipo'] = ( - str(TipoMateriaLegislativa.objects.get(id=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))) + 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']))) + context['tramitacao__unidade_tramitacao_destino'] = ( + str(UnidadeTramitacao.objects.get( + id=self.request.GET['tramitacao__unidade_tramitacao_destino'] + )) + ) else: context['tramitacao__unidade_tramitacao_destino'] = '' + 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 diff --git a/sapl/materia/migrations/0056_popula_materiaemtramitacao.py b/sapl/materia/migrations/0056_popula_materiaemtramitacao.py new file mode 100644 index 000000000..dfa4c0175 --- /dev/null +++ b/sapl/materia/migrations/0056_popula_materiaemtramitacao.py @@ -0,0 +1,23 @@ +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0055_auto_20190816_0943'), + ] + + operations = [ + migrations.RunSQL(""" + create or replace view materia_materiaemtramitacao as + select m.id as id, + m.id as materia_id, + t.id as tramitacao_id + from materia_materialegislativa m + inner join materia_tramitacao t on (m.id = t.materia_id) + where t.id = (select max(id) from materia_tramitacao where materia_id = m.id) + order by m.id DESC + """), + ] \ No newline at end of file diff --git a/sapl/materia/migrations/0057_materiaemtramitacao.py b/sapl/materia/migrations/0057_materiaemtramitacao.py new file mode 100644 index 000000000..95953f50b --- /dev/null +++ b/sapl/materia/migrations/0057_materiaemtramitacao.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-08-27 20:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0056_popula_materiaemtramitacao'), + ] + + operations = [ + migrations.CreateModel( + name='MateriaEmTramitacao', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'db_table': 'materia_materiaemtramitacao', + 'managed': False, + }, + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index b641377de..77203e0e4 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1084,3 +1084,15 @@ class Tramitacao(models.Model): 'materia': self.materia, 'status': self.status, 'data': self.data_tramitacao.strftime("%d/%m/%Y")} + + +class MateriaEmTramitacao(models.Model): + materia = models.ForeignKey(MateriaLegislativa, on_delete=models.DO_NOTHING) + tramitacao = models.ForeignKey(Tramitacao, on_delete=models.DO_NOTHING) + + class Meta: + managed = False + db_table = "materia_materiaemtramitacao" + + def __str__(self): + return '{}/{}'.format(self.materia, self.tramitacao) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 4f1b4b515..aa187477d 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -127,6 +127,7 @@ rules_group_materia = { ['can_access_impressos'], __perms_publicas__), (materia.Numeracao, __base__, __perms_publicas__), (materia.Tramitacao, __base__, __perms_publicas__), + (materia.MateriaEmTramitacao, __base__, __perms_publicas__), (norma.LegislacaoCitada, __base__, __perms_publicas__), (norma.AutoriaNorma, __base__, __perms_publicas__), (compilacao.Dispositivo, __base__ + [ diff --git a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html b/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html index 02cad5e43..738e615b8 100644 --- a/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html +++ b/sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html @@ -44,17 +44,20 @@
- {% for materia in object_list %} + {% for materia_em_tramitacao in object_list %}