Browse Source

Fix Ticket #923744 - Tempo de resposta do relatório de matérias em tramitação (#2955)

* Otimiza relatório de matérias em tramitação

* Refatoração

* HOT-FIX: corrige erro apontado pelo travis

* Adicionar nova model

* Adicionar on_delete nos campos da model

* Acelera pesquisa do relatório

* Refatoração
pull/2965/head
João Rodrigues 5 years ago
committed by Edward
parent
commit
55c070b577
  1. 55
      sapl/base/forms.py
  2. 158
      sapl/base/views.py
  3. 23
      sapl/materia/migrations/0056_popula_materiaemtramitacao.py
  4. 25
      sapl/materia/migrations/0057_materiaemtramitacao.py
  5. 12
      sapl/materia/models.py
  6. 1
      sapl/rules/map_rules.py
  7. 17
      sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html

55
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'))
)
)

158
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

23
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
"""),
]

25
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,
},
),
]

12
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)

1
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__ + [

17
sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html

@ -44,17 +44,20 @@
</tr>
</thead>
<tbody>
{% for materia in object_list %}
{% for materia_em_tramitacao in object_list %}
<tr>
<td><a href="{% url 'sapl.materia:materialegislativa_detail' materia.pk %}">
{{materia.tipo.descricao}} {{materia.numero}}/{{materia.ano}}
</a></td>
<td>{{materia.tramitacao_set.last.unidade_tramitacao_destino}}</td>
<td>{{materia.tramitacao_set.last.status}}</td>
<td>
<a href="{% url 'sapl.materia:materialegislativa_detail' materia_em_tramitacao.materia.pk %}">
{{ materia_em_tramitacao.materia.tipo.descricao }} {{ materia_em_tramitacao.materia.numero }}/{{ materia_em_tramitacao.materia.ano }}
</a>
</td>
<td>{{ materia_em_tramitacao.materia.tramitacao_set.last.unidade_tramitacao_destino }}</td>
<td>{{ materia_em_tramitacao.materia.tramitacao_set.last.status }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% include 'paginacao.html' %}
<br/>
{% endblock base_content %}

Loading…
Cancel
Save