diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 2604abb43..5a9f9cf2c 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -34,7 +34,7 @@ celery-haystack==0.10 redis>=2.10.5,<2.11 django-celery-results==1.0.4 Whoosh==2.7.4 - +more-itertools==8.2.0 pysolr==3.6.0 diff --git a/sapl/base/views.py b/sapl/base/views.py index ba94e5d87..a8c7b95ba 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -58,9 +58,10 @@ from sapl.protocoloadm.models import (Protocolo, TipoDocumentoAdministrativo, DocumentoAdministrativo, Anexado) from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, OrdemDia, SessaoPlenariaPresenca, 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.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, + mail_service_configured, parlamentares_ativos, + SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo) + from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, RelatorioAudienciaFilterSet, @@ -822,13 +823,7 @@ class RelatorioMateriasTramitacaoView(RelatorioMixin, FilterView): 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 + self.total_resultados_tipos = num_materias_por_tipo(qs, "materia__tipo") return data @@ -955,13 +950,8 @@ class RelatorioMateriasPorAnoAutorTipoView(RelatorioMixin, FilterView): context['title'] = _('Matérias por Ano, Autor e Tipo') if not self.filterset.form.is_valid(): return context - qtdes = {} - for tipo in TipoMateriaLegislativa.objects.all(): - qs = context['object_list'] - qtde = len(qs.filter(tipo_id=tipo.id)) - if qtde > 0: - qtdes[tipo] = qtde - context['qtdes'] = qtdes + 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 '' @@ -997,13 +987,8 @@ class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): if not self.filterset.form.is_valid(): return context - qtdes = {} - for tipo in TipoMateriaLegislativa.objects.all(): - qs = context['object_list'] - qtde = len(qs.filter(tipo_id=tipo.id)) - if qtde > 0: - qtdes[tipo] = qtde - context['qtdes'] = qtdes + 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 '' @@ -1021,8 +1006,8 @@ class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): else: context['autor'] = '' context['periodo'] = ( - self.request.GET['data_apresentacao_0'] + - ' - ' + self.request.GET['data_apresentacao_1']) + self.request.GET['data_apresentacao_0'] + + ' - ' + self.request.GET['data_apresentacao_1']) return context diff --git a/sapl/utils.py b/sapl/utils.py index 39a52a7ed..7e773bf57 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,3 +1,5 @@ +from itertools import groupby + import django_filters import hashlib import logging @@ -6,7 +8,7 @@ import os import re import unicodedata -from crispy_forms.layout import Button, HTML +from crispy_forms.layout import Button, HTML from easy_thumbnails import source_generators from floppyforms import ClearableFileInput from functools import wraps @@ -44,6 +46,32 @@ from sapl.settings import MAX_DOC_UPLOAD_SIZE SEPARADOR_HASH_PROPOSICAO = 'K' +def num_materias_por_tipo(qs, attr_tipo='tipo'): + """ + :argument um QuerySet em MateriaLegislativa + :return um dict com o mapeamento {tipo: }, + se não existir o matéria para o tipo informado então não + haverá entrada no dicionário. + """ + qtdes = {} + + if attr_tipo == 'tipo': + def sort_function(m): return m.tipo + else: + def sort_function(m): return m.materia.tipo + + # select_related eh importante por questoes de desempenho, pois caso + # contrario ele realizara uma consulta ao banco para cada iteracao, + # na key do groupby (uma alternativa é só usar tipo_id, na chave). + qs2 = qs.select_related(attr_tipo).order_by(attr_tipo+'_id') + + for key, values in groupby(qs2, key=sort_function): + # poderia usar qtdes[key] = len(list(values)) aqui, mas + # desse modo economiza memória RAM + qtdes[key] = sum(1 for x in values) + return qtdes + + def validar_arquivo(arquivo, nome_campo): if len(arquivo.name) > 200: raise ValidationError(