From a8b6c74a57bd92bddefcf08e3cac9157b993eae4 Mon Sep 17 00:00:00 2001 From: Edward <9326037+edwardoliveira@users.noreply.github.com> Date: Wed, 24 Feb 2021 22:00:03 -0300 Subject: [PATCH] Fixes OSTicket #247431 (#3354) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes OSTicket #247431 * Refatora lista_anexados * Ajusta signals * Adiciona timers * Fix #3353 * ajusta disposição dos signals * add import de tradução Co-authored-by: eribeiro Co-authored-by: Leandro Roberto --- sapl/base/apps.py | 3 + sapl/base/receivers.py | 93 +++++++++++++++---- sapl/base/signals.py | 48 ---------- sapl/materia/apps.py | 3 - sapl/materia/forms.py | 27 ++++-- sapl/materia/views.py | 98 +++++++------------- sapl/norma/signals.py | 0 sapl/protocoloadm/apps.py | 3 - sapl/protocoloadm/forms.py | 14 ++- sapl/protocoloadm/tests/test_protocoloadm.py | 2 +- sapl/protocoloadm/views.py | 38 +------- sapl/utils.py | 68 ++++++++------ 12 files changed, 184 insertions(+), 213 deletions(-) delete mode 100644 sapl/base/signals.py delete mode 100644 sapl/norma/signals.py diff --git a/sapl/base/apps.py b/sapl/base/apps.py index c3af888b7..403d74bd1 100644 --- a/sapl/base/apps.py +++ b/sapl/base/apps.py @@ -7,3 +7,6 @@ class AppConfig(django.apps.AppConfig): name = 'sapl.base' label = 'base' verbose_name = _('Dados Básicos') + + def ready(self): + from sapl.base import receivers diff --git a/sapl/base/receivers.py b/sapl/base/receivers.py index e812a3f5b..6a1e622be 100644 --- a/sapl/base/receivers.py +++ b/sapl/base/receivers.py @@ -2,36 +2,58 @@ import inspect import logging from django.conf import settings +from django.contrib.contenttypes.models import ContentType from django.core import serializers -from django.db.models.signals import post_delete, post_save +from django.db.models.signals import post_delete, post_save,\ + post_migrate +from django.db.utils import DEFAULT_DB_ALIAS from django.dispatch import receiver from django.utils import timezone +from django.utils.translation import ugettext_lazy as _ from sapl.base.email_utils import do_envia_email_tramitacao -from sapl.base.models import AuditLog -from sapl.base.signals import tramitacao_signal +from sapl.base.models import AuditLog, TipoAutor, Autor from sapl.materia.models import Tramitacao from sapl.protocoloadm.models import TramitacaoAdministrativo -from sapl.utils import get_base_url +from sapl.utils import get_base_url, models_with_gr_for_model -@receiver(tramitacao_signal) +@receiver(post_save, sender=Tramitacao) +@receiver(post_save, sender=TramitacaoAdministrativo) def handle_tramitacao_signal(sender, **kwargs): - tramitacao = kwargs.get("post") - request = kwargs.get("request") - if 'protocoloadm' in str(sender): - doc_mat = tramitacao.documento - tipo = "documento" - elif 'materia' in str(sender): + logger = logging.getLogger(__name__) + + tramitacao = kwargs.get('instance') + + if isinstance(tramitacao, Tramitacao): tipo = "materia" doc_mat = tramitacao.materia + else: + tipo = "documento" + doc_mat = tramitacao.documento - do_envia_email_tramitacao( - get_base_url(request), - tipo, - doc_mat, - tramitacao.status, - tramitacao.unidade_tramitacao_destino) + pilha_de_execucao = inspect.stack() + for i in pilha_de_execucao: + if i.function == 'migrate': + return + request = i.frame.f_locals.get('request', None) + if request: + break + + if not request: + logger.warning("Email não enviado, objeto request é None.") + return + try: + do_envia_email_tramitacao( + get_base_url(request), + tipo, + doc_mat, + tramitacao.status, + tramitacao.unidade_tramitacao_destino) + except Exception as e: + logger.error(f'user={request.user.username}. Tramitação criada, mas e-mail de acompanhamento ' + 'de matéria não enviado. Há problemas na configuração ' + 'do e-mail. ' + str(e)) @receiver(post_delete) @@ -116,3 +138,40 @@ def audit_log_post_delete(sender, **kwargs): def audit_log_post_save(sender, **kwargs): operation = 'C' if kwargs.get('created') else 'U' audit_log_function(sender, operation=operation, **kwargs) + + +def cria_models_tipo_autor(app_config=None, verbosity=2, interactive=True, + using=DEFAULT_DB_ALIAS, **kwargs): + + models = models_with_gr_for_model(Autor) + + print("\n\033[93m\033[1m{}\033[0m".format( + _('Atualizando registros TipoAutor do SAPL:'))) + for model in models: + content_type = ContentType.objects.get_for_model(model) + tipo_autor = TipoAutor.objects.filter( + content_type=content_type.id).exists() + + if tipo_autor: + msg1 = "Carga de {} não efetuada.".format( + TipoAutor._meta.verbose_name) + msg2 = " Já Existe um {} {} relacionado...".format( + TipoAutor._meta.verbose_name, + model._meta.verbose_name) + msg = " {}{}".format(msg1, msg2) + else: + novo_autor = TipoAutor() + novo_autor.content_type_id = content_type.id + novo_autor.descricao = model._meta.verbose_name + novo_autor.save() + msg1 = "Carga de {} efetuada.".format( + TipoAutor._meta.verbose_name) + msg2 = " {} {} criado...".format( + TipoAutor._meta.verbose_name, content_type.model) + msg = " {}{}".format(msg1, msg2) + print(msg) + # Disconecta função para evitar a chamada repetidas vezes. + post_migrate.disconnect(receiver=cria_models_tipo_autor) + + +post_migrate.connect(receiver=cria_models_tipo_autor) diff --git a/sapl/base/signals.py b/sapl/base/signals.py deleted file mode 100644 index b2cda2028..000000000 --- a/sapl/base/signals.py +++ /dev/null @@ -1,48 +0,0 @@ -from django.contrib.contenttypes.models import ContentType -from django.db.models.signals import post_migrate -from django.db.utils import DEFAULT_DB_ALIAS -import django.dispatch - -from django.utils.translation import ugettext_lazy as _ -from sapl.base.models import Autor, TipoAutor -from sapl.utils import models_with_gr_for_model - - -tramitacao_signal = django.dispatch.Signal(providing_args=['post', 'request']) - - -def cria_models_tipo_autor(app_config=None, verbosity=2, interactive=True, - using=DEFAULT_DB_ALIAS, **kwargs): - - models = models_with_gr_for_model(Autor) - - print("\n\033[93m\033[1m{}\033[0m".format( - _('Atualizando registros TipoAutor do SAPL:'))) - for model in models: - content_type = ContentType.objects.get_for_model(model) - tipo_autor = TipoAutor.objects.filter( - content_type=content_type.id).exists() - - if tipo_autor: - msg1 = "Carga de {} não efetuada.".format( - TipoAutor._meta.verbose_name) - msg2 = " Já Existe um {} {} relacionado...".format( - TipoAutor._meta.verbose_name, - model._meta.verbose_name) - msg = " {}{}".format(msg1, msg2) - else: - novo_autor = TipoAutor() - novo_autor.content_type_id = content_type.id - novo_autor.descricao = model._meta.verbose_name - novo_autor.save() - msg1 = "Carga de {} efetuada.".format( - TipoAutor._meta.verbose_name) - msg2 = " {} {} criado...".format( - TipoAutor._meta.verbose_name, content_type.model) - msg = " {}{}".format(msg1, msg2) - print(msg) - # Disconecta função para evitar a chamada repetidas vezes. - post_migrate.disconnect(receiver=cria_models_tipo_autor) - - -post_migrate.connect(receiver=cria_models_tipo_autor) diff --git a/sapl/materia/apps.py b/sapl/materia/apps.py index 2cc3559ae..3ac053d1b 100644 --- a/sapl/materia/apps.py +++ b/sapl/materia/apps.py @@ -6,6 +6,3 @@ class AppConfig(apps.AppConfig): name = 'sapl.materia' label = 'materia' verbose_name = _('Matéria') - - def ready(self): - from sapl.base import receivers diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 9a0d47bdc..f6d9ab2b8 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -35,7 +35,7 @@ from sapl.norma.models import (LegislacaoCitada, NormaJuridica, from sapl.parlamentares.models import Legislatura, Partido from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo) -from sapl.utils import (autor_label, autor_modal, +from sapl.utils import (autor_label, autor_modal, timing, ChoiceWithoutValidationField, choice_anos_com_materias, FileFieldCheckMixin, FilterOverridesMetaMixin, gerar_hash_arquivo, @@ -548,6 +548,7 @@ class TramitacaoForm(ModelForm): return cleaned_data + @timing @transaction.atomic def save(self, commit=True): tramitacao = super(TramitacaoForm, self).save(commit) @@ -559,16 +560,19 @@ class TramitacaoForm(ModelForm): 'tramitacao_materia') if tramitar_anexadas: lista_tramitacao = [] - anexadas_list = lista_anexados(materia) - for ma in anexadas_list: - if not ma.tramitacao_set.order_by('-data_tramitacao', '-id').all() \ - or ma.tramitacao_set.order_by('-data_tramitacao', '-id').first().unidade_tramitacao_destino \ + materias_anexadas = lista_anexados(materia) + for mat in materias_anexadas: + ultima_tramitacao = mat.tramitacao_set.\ + select_related('unidade_tramitacao_destino').\ + order_by('-data_tramitacao', '-id').first() + if not ultima_tramitacao or \ + ultima_tramitacao.unidade_tramitacao_destino \ == tramitacao.unidade_tramitacao_local: - ma.em_tramitacao = False if tramitacao.status.indicador == "F" else True - ma.save() + mat.em_tramitacao = False if \ + tramitacao.status.indicador == "F" else True lista_tramitacao.append(Tramitacao( status=tramitacao.status, - materia=ma, + materia=mat, data_tramitacao=tramitacao.data_tramitacao, unidade_tramitacao_local=tramitacao.unidade_tramitacao_local, data_encaminhamento=tramitacao.data_encaminhamento, @@ -581,8 +585,10 @@ class TramitacaoForm(ModelForm): ip=tramitacao.ip, ultima_edicao=tramitacao.ultima_edicao )) + ## TODO: BULK UPDATE não envia Signal para Tramitacao Tramitacao.objects.bulk_create(lista_tramitacao) - + # Atualiza status 'em_tramitacao' + MateriaLegislativa.objects.bulk_update(materias_anexadas, ['em_tramitacao']) return tramitacao @@ -679,6 +685,7 @@ class TramitacaoUpdateForm(TramitacaoForm): return cd + @timing @transaction.atomic def save(self, commit=True): ant_tram_principal = Tramitacao.objects.get(id=self.instance.id) @@ -711,6 +718,7 @@ class TramitacaoUpdateForm(TramitacaoForm): ma.em_tramitacao = False if nova_tram_principal.status.indicador == "F" else True ma.save() + ## TODO: refatorar? return nova_tram_principal @@ -1810,6 +1818,7 @@ class TramitacaoEmLoteForm(ModelForm): ip=tramitacao.ip, ultima_edicao=tramitacao.ultima_edicao )) + ## TODO: BULK UPDATE não envia Signal para Tramitacao Tramitacao.objects.bulk_create(lista_tramitacao) return tramitacao diff --git a/sapl/materia/views.py b/sapl/materia/views.py index ec263154b..48d44083e 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -37,7 +37,6 @@ import weasyprint import sapl from sapl.base.email_utils import do_envia_email_confirmacao from sapl.base.models import Autor, CasaLegislativa, AppConfig as BaseAppConfig -from sapl.base.signals import tramitacao_signal from sapl.comissoes.models import Comissao, Participacao, Composicao from sapl.compilacao.models import STATUS_TA_IMMUTABLE_RESTRICT, STATUS_TA_PRIVATE from sapl.compilacao.views import IntegracaoTaView @@ -1358,28 +1357,6 @@ class TramitacaoCrud(MasterDetailCrud): return context - def form_valid(self, form): - - self.object = form.save() - username = self.request.user.username - - try: - self.logger.debug("user=" + username + ". Tentando enviar Tramitacao (sender={}, post={}, request={})." - .format(Tramitacao, self.object, self.request)) - tramitacao_signal.send(sender=Tramitacao, - post=self.object, - request=self.request) - except Exception as e: - msg = _('Tramitação criada, mas e-mail de acompanhamento ' - 'de matéria não enviado. Há problemas na configuração ' - 'do e-mail.') - self.logger.warning('user=' + username + '. Tramitação criada, mas e-mail de acompanhamento ' - 'de matéria não enviado. Há problemas na configuração ' - 'do e-mail. ' + str(e)) - messages.add_message(self.request, messages.WARNING, msg) - return HttpResponseRedirect(self.get_success_url()) - return super().form_valid(form) - class UpdateView(MasterDetailCrud.UpdateView): form_class = TramitacaoUpdateForm logger = logging.getLogger(__name__) @@ -1397,27 +1374,6 @@ class TramitacaoCrud(MasterDetailCrud): return initial - def form_valid(self, form): - self.object = form.save() - user = self.request.user - - try: - self.logger.debug("user=" + user.username + ". Tentando enviar Tramitacao (sender={}, post={}, request={}" - .format(Tramitacao, self.object, self.request)) - tramitacao_signal.send(sender=Tramitacao, - post=self.object, - request=self.request) - except Exception: - msg = _('Tramitação atualizada, mas e-mail de acompanhamento ' - 'de matéria não enviado. Há problemas na configuração ' - 'do e-mail.') - self.logger.warning('user=' + user.username + '. Tramitação atualizada, mas e-mail de acompanhamento ' - 'de matéria não enviado. Há problemas na configuração ' - 'do e-mail.') - messages.add_message(self.request, messages.WARNING, msg) - return HttpResponseRedirect(self.get_success_url()) - return super().form_valid(form) - class ListView(MasterDetailCrud.ListView): def get_queryset(self): @@ -1432,7 +1388,7 @@ class TramitacaoCrud(MasterDetailCrud): logger = logging.getLogger(__name__) def delete(self, request, *args, **kwargs): - tramitacao = Tramitacao.objects.get(id=self.kwargs['pk']) + tramitacao = Tramitacao.objects.select_related('materia').get(id=self.kwargs['pk']) materia = tramitacao.materia url = reverse('sapl.materia:tramitacao_list', kwargs={'pk': materia.id}) @@ -1449,31 +1405,43 @@ class TramitacaoCrud(MasterDetailCrud): messages.add_message(request, messages.ERROR, msg) return HttpResponseRedirect(url) else: - tramitacoes_deletar = [tramitacao] - if materia.tramitacao_set.count() == 0: + + # recupera últimas duas tramitacoes + penultima_tramitacao = materia.tramitacao_set.order_by( + '-data_tramitacao', '-id').exclude( + id=ultima_tramitacao.id).first() + if not penultima_tramitacao or \ + penultima_tramitacao.status.indicador == "F": materia.em_tramitacao = False - materia.save() + else: + materia.em_tramitacao = True + materia.save() + + tramitacoes_deletar = [tramitacao.id] + tramitar_anexadas = sapl.base.models.AppConfig.attr( 'tramitacao_materia') if tramitar_anexadas: - mat_anexadas = lista_anexados(materia) - for ma in mat_anexadas: - tram_anexada = ma.tramitacao_set.order_by( + materias_anexadas = lista_anexados(materia) + for materia in materias_anexadas: + ultima_tramitacao = materia.tramitacao_set.order_by( '-data_tramitacao', '-id').first() - if compara_tramitacoes_mat(tram_anexada, tramitacao): - tramitacoes_deletar.append(tram_anexada) - if ma.tramitacao_set.count() == 0: - ma.em_tramitacao = False - ma.save() - Tramitacao.objects.filter( - id__in=[t.id for t in tramitacoes_deletar]).delete() - - # TODO: otimizar para passar a lista de matérias - # for tramitacao in tramitacoes_deletar: - # post_delete_signal.send(sender=None, - # instance=tramitacao, - # operation='C', - # request=self.request) + if compara_tramitacoes_mat(ultima_tramitacao, + tramitacao): + tramitacoes_deletar.append(ultima_tramitacao.id) + # recupera últimas duas tramitacoes + penultima_tramitacao = materia.tramitacao_set.order_by( + '-data_tramitacao', '-id').exclude( + id=ultima_tramitacao.id).first() + if not penultima_tramitacao or \ + penultima_tramitacao.status.indicador == "F": + materia.em_tramitacao = False + else: + materia.em_tramitacao = True + # Atualiza status 'em_tramitacao' + MateriaLegislativa.objects.\ + bulk_update(materias_anexadas, ['em_tramitacao']) + Tramitacao.objects.filter(id__in=tramitacoes_deletar).delete() return HttpResponseRedirect(url) diff --git a/sapl/norma/signals.py b/sapl/norma/signals.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/sapl/protocoloadm/apps.py b/sapl/protocoloadm/apps.py index 98e28ea36..8697e58d9 100644 --- a/sapl/protocoloadm/apps.py +++ b/sapl/protocoloadm/apps.py @@ -6,6 +6,3 @@ class AppConfig(apps.AppConfig): name = 'sapl.protocoloadm' label = 'protocoloadm' verbose_name = _('Protocolo Administrativo') - - def ready(self): - from sapl.base import receivers diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index b89fc7183..0441c454f 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -22,7 +22,7 @@ from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao) from sapl.utils import (AnoNumeroOrderingFilter, autor_label, autor_modal, choice_anos_com_documentoadministrativo, - choice_anos_com_materias, + choice_anos_com_materias, timing, choice_anos_com_protocolo, choice_force_optional, FileFieldCheckMixin, FilterOverridesMetaMixin, lista_anexados, RANGE_ANOS, @@ -755,6 +755,7 @@ class TramitacaoAdmForm(ModelForm): return self.cleaned_data + @timing @transaction.atomic def save(self, commit=True): tramitacao = super(TramitacaoAdmForm, self).save(commit) @@ -765,7 +766,7 @@ class TramitacaoAdmForm(ModelForm): tramitar_anexados = AppConfig.attr('tramitacao_documento') if tramitar_anexados: lista_tramitacao = [] - anexados_list = lista_anexados(documento, False) + anexados_list = lista_anexados(documento) for da in anexados_list: if not da.tramitacaoadministrativo_set.all() \ or da.tramitacaoadministrativo_set.last() \ @@ -786,6 +787,7 @@ class TramitacaoAdmForm(ModelForm): ip=tramitacao.ip, ultima_edicao=tramitacao.ultima_edicao )) + ## TODO: BULK UPDATE não envia Signal para Tramitacao TramitacaoAdministrativo.objects.bulk_create(lista_tramitacao) return tramitacao @@ -876,6 +878,7 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm): return cd + @timing @transaction.atomic def save(self, commit=True): ant_tram_principal = TramitacaoAdministrativo.objects.get( @@ -887,7 +890,7 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm): tramitar_anexados = AppConfig.attr('tramitacao_documento') if tramitar_anexados: - anexados_list = lista_anexados(documento, False) + anexados_list = lista_anexados(documento) for da in anexados_list: tram_anexada = da.tramitacaoadministrativo_set.last() if compara_tramitacoes_doc(ant_tram_principal, tram_anexada): @@ -906,6 +909,7 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm): da.tramitacao = False if nova_tram_principal.status.indicador == "F" else True da.save() + ## TODO: refatorar? return nova_tram_principal @@ -1624,6 +1628,7 @@ class TramitacaoEmLoteAdmForm(ModelForm): return cleaned_data + @timing @transaction.atomic def save(self, commit=True): cd = self.cleaned_data @@ -1655,7 +1660,7 @@ class TramitacaoEmLoteAdmForm(ModelForm): if tramitar_anexados: lista_tramitacao = [] - anexados = lista_anexados(doc, False) + anexados = lista_anexados(doc) for da in anexados: if not da.tramitacaoadministrativo_set.all() \ or da.tramitacaoadministrativo_set.last() \ @@ -1676,6 +1681,7 @@ class TramitacaoEmLoteAdmForm(ModelForm): ip=tramitacao.ip, ultima_edicao=tramitacao.ultima_edicao )) + ## TODO: BULK UPDATE não envia Signal para Tramitacao TramitacaoAdministrativo.objects.bulk_create(lista_tramitacao) return tramitacao diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index bfc5d769e..fe38765c3 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -507,7 +507,7 @@ def test_lista_documentos_anexados(): data_anexacao="2020-11-05" ) - lista = lista_anexados(documento_principal, False) + lista = lista_anexados(documento_principal) assert len(lista) == 2 assert lista[0] == documento_anexado diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index feda6b9b2..35cb9ba2b 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -29,7 +29,6 @@ from django_filters.views import FilterView import sapl from sapl.base.email_utils import do_envia_email_confirmacao from sapl.base.models import Autor, CasaLegislativa, AppConfig -from sapl.base.signals import tramitacao_signal from sapl.comissoes.models import Comissao from sapl.crud.base import (Crud, CrudAux, MasterDetailCrud, make_pagination, RP_LIST, RP_DETAIL) @@ -1281,24 +1280,6 @@ class TramitacaoAdmCrud(MasterDetailCrud): 'unidade_tramitacao_local'].widget.attrs['readonly'] = True return context - def form_valid(self, form): - self.object = form.save() - username = self.request.user.username - try: - tramitacao_signal.send(sender=TramitacaoAdministrativo, - post=self.object, - request=self.request) - except Exception as e: - self.logger.error('user=' + username + '. Tramitação criada, mas e-mail de acompanhamento de documento ' - 'não enviado. A não configuração do servidor de e-mail ' - 'impede o envio de aviso de tramitação. ' + str(e)) - msg = _('Tramitação criada, mas e-mail de acompanhamento ' - 'de documento não enviado. A não configuração do' - ' servidor de e-mail impede o envio de aviso de tramitação') - messages.add_message(self.request, messages.WARNING, msg) - return HttpResponseRedirect(self.get_success_url()) - return super().form_valid(form) - class UpdateView(MasterDetailCrud.UpdateView): form_class = TramitacaoAdmEditForm logger = logging.getLogger(__name__) @@ -1313,23 +1294,6 @@ class TramitacaoAdmCrud(MasterDetailCrud): return initial - def form_valid(self, form): - self.object = form.save() - username = self.request.user.username - try: - tramitacao_signal.send(sender=TramitacaoAdministrativo, - post=self.object, - request=self.request) - except Exception as e: - self.logger.error('user=' + username + '. Tramitação criada, mas e-mail de acompanhamento de documento ' - 'não enviado. A não configuração do servidor de e-mail ' - 'impede o envio de aviso de tramitação. ' + str(e)) - msg = _('Tramitação criada, mas e-mail de acompanhamento ' - 'de documento não enviado. A não configuração do' - ' servidor de e-mail impede o envio de aviso de tramitação') - messages.add_message(self.request, messages.WARNING, msg) - return HttpResponseRedirect(self.get_success_url()) - return super().form_valid(form) class ListView(DocumentoAdministrativoMixin, MasterDetailCrud.ListView): @@ -1381,7 +1345,7 @@ class TramitacaoAdmCrud(MasterDetailCrud): documento.save() tramitar_anexados = AppConfig.attr('tramitacao_documento') if tramitar_anexados: - docs_anexados = lista_anexados(documento, False) + docs_anexados = lista_anexados(documento) for da in docs_anexados: tram_anexada = da.tramitacaoadministrativo_set.last() if compara_tramitacoes_doc(tram_anexada, tramitacao): diff --git a/sapl/utils.py b/sapl/utils.py index 0104f3aed..7e57b027e 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -8,6 +8,7 @@ import platform import re import requests import tempfile +from time import time from unicodedata import normalize as unicodedata_normalize import unicodedata @@ -1017,35 +1018,50 @@ def google_recaptcha_configured(): return not AppConfig.attr('google_recaptcha_site_key') == '' -def lista_anexados(principal, isMateriaLegislativa=True): - anexados_total = [] - if isMateriaLegislativa: # MateriaLegislativa - from sapl.materia.models import Anexada - anexados_iterator = Anexada.objects.filter(materia_principal=principal) - else: # DocAdm - from sapl.protocoloadm.models import Anexado - anexados_iterator = Anexado.objects.filter( - documento_principal=principal) - - anexadas_temp = list(anexados_iterator) - - while anexadas_temp: - anx = anexadas_temp.pop() - if isMateriaLegislativa: - if anx.materia_anexada not in anexados_total: - anexados_total.append(anx.materia_anexada) - anexados_anexado = Anexada.objects.filter( - materia_principal=anx.materia_anexada) - anexadas_temp.extend(anexados_anexado) +def timing(f): + @wraps(f) + def wrap(*args, **kw): + logger = logging.getLogger(__name__) + ts = time() + result = f(*args, **kw) + te = time() + logger.info('funcao:%r args:[%r, %r] took: %2.4f sec' % \ + (f.__name__, args, kw, te-ts)) + return result + return wrap + +@timing +def lista_anexados(principal): + from sapl.materia.models import MateriaLegislativa + from sapl.materia.models import Anexada + from sapl.protocoloadm.models import Anexado + + if isinstance(principal, MateriaLegislativa): + anexados = {a.materia_anexada for a in Anexada.objects.select_related( + 'materia_anexada').filter(materia_principal=principal)} + else: + anexados = {a.documento_anexado for a in Anexado.objects.select_related( + 'documento_anexado').filter(documento_principal=principal)} + + anexados_total = set() + while anexados: + if isinstance(principal, MateriaLegislativa): + novos_anexados = {a.materia_anexada for a in + Anexada.objects.filter( + materia_principal__in=anexados) + if a.materia_anexada not in anexados_total} else: - if anx.documento_anexado not in anexados_total: - anexados_total.append(anx.documento_anexado) - anexados_anexado = Anexado.objects.filter( - documento_principal=anx.documento_anexado) - anexadas_temp.extend(anexados_anexado) + novos_anexados = {a.documento_anexado for a in + Anexado.objects.filter( + documento_principal__in=anexados) + if a.documento_anexado not in anexados_total} + anexados_total.update(anexados) + anexados = novos_anexados + if principal in anexados_total: anexados_total.remove(principal) - return anexados_total + + return list(anexados_total) def from_date_to_datetime_utc(data):