diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 9ba6c5096..3efc310f4 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -18,28 +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 + to_row, SaplFormHelper) from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao, - DocumentoAcessorio, TipoMateriaLegislativa) + DocumentoAcessorio, TipoMateriaLegislativa, MateriaEmTramitacao) from sapl.norma.models import (NormaJuridica, NormaEstatisticas) from sapl.protocoloadm.models import DocumentoAdministrativo from sapl.parlamentares.models import SessaoLegislativa, Partido, HistoricoPartido 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, - intervalos_tem_intersecao) + intervalos_tem_intersecao, + ImageThumbnailFileInput, models_with_gr_for_model, + qs_override_django_filter, RangeWidgetOverride, + RANGE_ANOS, YES_NO_CHOICES) from .models import AppConfig, CasaLegislativa from operator import xor @@ -1090,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) @@ -1106,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)]) diff --git a/sapl/base/views.py b/sapl/base/views.py index c953e3a23..9a620aeff 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -14,7 +14,7 @@ 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 @@ -34,20 +34,21 @@ 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) + DocumentoAcessorio, TipoDocumento, MateriaEmTramitacao, + Tramitacao) from sapl.norma.models import (NormaJuridica, TipoNormaJuridica, NormaEstatisticas) from sapl.parlamentares.models import (Parlamentar, Legislatura, Mandato, Filiacao, SessaoLegislativa, Bancada, AfastamentoParlamentar) from sapl.protocoloadm.models import (Protocolo, TipoDocumentoAdministrativo, StatusTramitacaoAdministrativo, DocumentoAdministrativo, Anexado) -from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, OrdemDia, +from sapl.sessao.models import (Bancada, PresencaOrdemDia, SessaoPlenaria, OrdemDia, SessaoPlenariaPresenca, TipoSessaoPlenaria) from sapl.utils import (parlamentares_ativos, gerar_hash_arquivo, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, mail_service_configured, @@ -59,7 +60,7 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioMateriasPorAutorFilterSet, - RelatorioMateriasTramitacaoilterSet, + RelatorioMateriasTramitacaoFilterSet, RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, UsuarioEditForm, RelatorioNormasMesFilterSet, @@ -747,61 +748,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') + context['qtdes'] = self.total_resultados_tipos + context['ano'] = (self.request.GET['materia__ano']) - li = [li1 for li1 in qs if li1.tramitacao_set.last() and li1.tramitacao_set.last().status.indicador != 'F'] - context['object_list'] = li - - 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 0cee4885f..ecc64c49c 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 %}