Browse Source

Fixes OSTicket #247431 (#3354)

* 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 <edwardr@senado.leg.br>
Co-authored-by: Leandro Roberto <leandroroberto.br@gmail.com>
pull/3358/head
Edward 4 years ago
committed by GitHub
parent
commit
a8b6c74a57
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      sapl/base/apps.py
  2. 81
      sapl/base/receivers.py
  3. 48
      sapl/base/signals.py
  4. 3
      sapl/materia/apps.py
  5. 27
      sapl/materia/forms.py
  6. 96
      sapl/materia/views.py
  7. 0
      sapl/norma/signals.py
  8. 3
      sapl/protocoloadm/apps.py
  9. 14
      sapl/protocoloadm/forms.py
  10. 2
      sapl/protocoloadm/tests/test_protocoloadm.py
  11. 38
      sapl/protocoloadm/views.py
  12. 64
      sapl/utils.py

3
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

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

48
sapl/base/signals.py

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

3
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

27
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

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

0
sapl/norma/signals.py

3
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

14
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

2
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

38
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):

64
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
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
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)
if isinstance(principal, MateriaLegislativa):
anexados = {a.materia_anexada for a in Anexada.objects.select_related(
'materia_anexada').filter(materia_principal=principal)}
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)
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:
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):

Loading…
Cancel
Save