Browse Source

Fix #2763 - Edita e remove tramitacões anexadas se possível (#2765)

* Fix #2763

* Adiciona testes de tramitação
pull/2811/head
Cesar Augusto de Carvalho 6 years ago
committed by João
parent
commit
c2c7013494
  1. 58
      sapl/materia/forms.py
  2. 185
      sapl/materia/tests/test_materia.py
  3. 24
      sapl/materia/views.py
  4. 53
      sapl/protocoloadm/forms.py
  5. 252
      sapl/protocoloadm/tests/test_protocoloadm.py
  6. 24
      sapl/protocoloadm/views.py
  7. 28
      sapl/utils.py

58
sapl/materia/forms.py

@ -38,14 +38,15 @@ from sapl.materia.models import (AssuntoMateria, Autoria, MateriaAssunto,
from sapl.norma.models import (LegislacaoCitada, NormaJuridica, from sapl.norma.models import (LegislacaoCitada, NormaJuridica,
TipoNormaJuridica) TipoNormaJuridica)
from sapl.parlamentares.models import Legislatura, Partido, Parlamentar from sapl.parlamentares.models import Legislatura, Partido, Parlamentar
from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo, Anexado
from sapl.settings import MAX_DOC_UPLOAD_SIZE from sapl.settings import MAX_DOC_UPLOAD_SIZE
from sapl.utils import (YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO, from sapl.utils import (YES_NO_CHOICES, SEPARADOR_HASH_PROPOSICAO,
ChoiceWithoutValidationField, ChoiceWithoutValidationField,
MateriaPesquisaOrderingFilter, RangeWidgetOverride, MateriaPesquisaOrderingFilter, RangeWidgetOverride,
autor_label, autor_modal, gerar_hash_arquivo, autor_label, autor_modal, gerar_hash_arquivo,
models_with_gr_for_model, qs_override_django_filter, models_with_gr_for_model, qs_override_django_filter,
choice_anos_com_materias, FilterOverridesMetaMixin, FileFieldCheckMixin) choice_anos_com_materias, FilterOverridesMetaMixin, FileFieldCheckMixin,
lista_anexados)
from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial,
DocumentoAcessorio, Numeracao, Proposicao, Relatoria, DocumentoAcessorio, Numeracao, Proposicao, Relatoria,
@ -555,8 +556,10 @@ class TramitacaoForm(ModelForm):
materia = tramitacao.materia materia = tramitacao.materia
materia.em_tramitacao = False if tramitacao.status.indicador == "F" else True materia.em_tramitacao = False if tramitacao.status.indicador == "F" else True
materia.save() materia.save()
lista_tramitacao = [] lista_tramitacao = []
for ma in materia.anexadas.all(): lista_anexadas = lista_anexados(materia)
for ma in lista_anexadas:
if not ma.tramitacao_set.all() \ if not ma.tramitacao_set.all() \
or ma.tramitacao_set.last().unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local: or ma.tramitacao_set.last().unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local:
ma.em_tramitacao = False if tramitacao.status.indicador == "F" else True ma.em_tramitacao = False if tramitacao.status.indicador == "F" else True
@ -580,19 +583,16 @@ class TramitacaoForm(ModelForm):
return tramitacao return tramitacao
def lista_anexadas(materia_principal): # Compara se os campos de duas tramitações são iguais,
materias_anexadas = [] # exceto os campos id, documento_id e timestamp
anexadas_principal = Anexada.objects.filter(materia_principal=materia_principal) def compara_tramitacoes_mat(tramitacao1, tramitacao2):
while anexadas_principal: if not tramitacao1 or not tramitacao2:
anexadas = [] return False
for anexada in anexadas_principal:
materias_anexadas.append(anexada.materia_anexada)
anexadas_anexada = Anexada.objects.filter(materia_principal=anexada.materia_anexada)
anexadas.extend(anexadas_anexada)
anexadas_principal = anexadas
return materias_anexadas
lst_items = ['id', 'materia_id', 'timestamp']
values = [(k,v) for k,v in tramitacao1.__dict__.items() if ((k not in lst_items) and (k[0] != '_'))]
other_values = [(k,v) for k,v in tramitacao2.__dict__.items() if (k not in lst_items and k[0] != '_')]
return values == other_values
class TramitacaoUpdateForm(TramitacaoForm): class TramitacaoUpdateForm(TramitacaoForm):
unidade_tramitacao_local = forms.ModelChoiceField( unidade_tramitacao_local = forms.ModelChoiceField(
@ -670,6 +670,34 @@ class TramitacaoUpdateForm(TramitacaoForm):
return cd return cd
@transaction.atomic
def save(self, commit=True):
ant_tram_principal = Tramitacao.objects.get(id=self.instance.id)
nova_tram_principal = super(TramitacaoUpdateForm, self).save(commit)
materia = nova_tram_principal.materia
materia.em_tramitacao = False if nova_tram_principal.status.indicador == "F" else True
materia.save()
lista_anexadas = lista_anexados(materia)
for ma in lista_anexadas:
tram_anexada = ma.tramitacao_set.last()
if compara_tramitacoes_mat(ant_tram_principal, tram_anexada):
tram_anexada.status = nova_tram_principal.status
tram_anexada.data_tramitacao = nova_tram_principal.data_tramitacao
tram_anexada.unidade_tramitacao_local = nova_tram_principal.unidade_tramitacao_local
tram_anexada.data_encaminhamento = nova_tram_principal.data_encaminhamento
tram_anexada.unidade_tramitacao_destino = nova_tram_principal.unidade_tramitacao_destino
tram_anexada.urgente = nova_tram_principal.urgente
tram_anexada.turno = nova_tram_principal.turno
tram_anexada.texto = nova_tram_principal.texto
tram_anexada.data_fim_prazo = nova_tram_principal.data_fim_prazo
tram_anexada.user = nova_tram_principal.user
tram_anexada.ip = nova_tram_principal.ip
tram_anexada.save()
ma.em_tramitacao = False if nova_tram_principal.status.indicador == "F" else True
ma.save()
return nova_tram_principal
class LegislacaoCitadaForm(ModelForm): class LegislacaoCitadaForm(ModelForm):

185
sapl/materia/tests/test_materia.py

@ -1,3 +1,4 @@
from datetime import date
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
@ -14,15 +15,16 @@ from sapl.materia.models import (Anexada, Autoria, DespachoInicial,
StatusTramitacao, TipoDocumento, StatusTramitacao, TipoDocumento,
TipoMateriaLegislativa, TipoProposicao, TipoMateriaLegislativa, TipoProposicao,
Tramitacao, UnidadeTramitacao) Tramitacao, UnidadeTramitacao)
from sapl.materia.forms import lista_anexadas from sapl.materia.forms import (TramitacaoForm, compara_tramitacoes_mat,
TramitacaoUpdateForm)
from sapl.norma.models import (LegislacaoCitada, NormaJuridica, from sapl.norma.models import (LegislacaoCitada, NormaJuridica,
TipoNormaJuridica) TipoNormaJuridica)
from sapl.parlamentares.models import Legislatura from sapl.parlamentares.models import Legislatura
from sapl.utils import models_with_gr_for_model from sapl.utils import models_with_gr_for_model, lista_anexados
@pytest.mark.django_db(transaction=False) @pytest.mark.django_db(transaction=False)
def test_lista_anexadas(): def test_lista_materias_anexadas():
tipo_materia = mommy.make( tipo_materia = mommy.make(
TipoMateriaLegislativa, TipoMateriaLegislativa,
descricao="Tipo_Teste" descricao="Tipo_Teste"
@ -69,7 +71,7 @@ def test_lista_anexadas():
data_anexacao="2020-11-05" data_anexacao="2020-11-05"
) )
lista = lista_anexadas(materia_principal) lista = lista_anexados(materia_principal)
assert len(lista) == 2 assert len(lista) == 2
assert lista[0] == materia_anexada assert lista[0] == materia_anexada
@ -637,3 +639,178 @@ def test_numeracao_materia_legislativa_por_ano(admin_client):
response_content = eval(response.content.decode('ascii')) response_content = eval(response.content.decode('ascii'))
esperado_outro_ano = eval('{"ano": "2010", "numero": 1}') esperado_outro_ano = eval('{"ano": "2010", "numero": 1}')
assert response_content['numero'] == esperado_outro_ano['numero'] assert response_content['numero'] == esperado_outro_ano['numero']
@pytest.mark.django_db(transaction=False)
def test_tramitacoes_materias_anexadas(admin_client):
tipo_materia = mommy.make(
TipoMateriaLegislativa,
descricao="Tipo_Teste"
)
materia_principal = mommy.make(
MateriaLegislativa,
ano=2018,
data_apresentacao="2018-01-04",
tipo=tipo_materia
)
materia_anexada = mommy.make(
MateriaLegislativa,
ano=2019,
data_apresentacao="2019-05-04",
tipo=tipo_materia
)
materia_anexada_anexada = mommy.make(
MateriaLegislativa,
ano=2020,
data_apresentacao="2020-01-05",
tipo=tipo_materia
)
mommy.make(
Anexada,
materia_principal=materia_principal,
materia_anexada=materia_anexada,
data_anexacao="2019-05-11"
)
mommy.make(
Anexada,
materia_principal=materia_anexada,
materia_anexada=materia_anexada_anexada,
data_anexacao="2020-11-05"
)
unidade_tramitacao_local_1 = make_unidade_tramitacao(descricao="Teste 1")
unidade_tramitacao_destino_1 = make_unidade_tramitacao(descricao="Teste 2")
unidade_tramitacao_destino_2 = make_unidade_tramitacao(descricao="Teste 3")
status = mommy.make(
StatusTramitacao,
indicador='R')
# Teste criação de Tramitacao
form = TramitacaoForm(data={})
form.data = {'data_tramitacao':date(2019, 5, 6),
'unidade_tramitacao_local':unidade_tramitacao_local_1.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_1.pk,
'status':status.pk,
'urgente': False,
'texto': "Texto de teste"}
form.instance.materia_id=materia_principal.pk
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = materia_anexada.tramitacao_set.last()
tramitacao_anexada_anexada = materia_anexada_anexada.tramitacao_set.last()
# Verifica se foram criadas as tramitações para as matérias anexadas e anexadas às anexadas
assert materia_principal.tramitacao_set.last() == tramitacao_principal
assert tramitacao_principal.materia.em_tramitacao == (tramitacao_principal.status.indicador != "F")
assert compara_tramitacoes_mat(tramitacao_principal, tramitacao_anexada)
assert MateriaLegislativa.objects.get(id=materia_anexada.pk).em_tramitacao \
== (tramitacao_anexada.status.indicador != "F")
assert compara_tramitacoes_mat(tramitacao_anexada_anexada, tramitacao_principal)
assert MateriaLegislativa.objects.get(id=materia_anexada_anexada.pk).em_tramitacao \
== (tramitacao_anexada_anexada.status.indicador != "F")
# Teste Edição de Tramitacao
form = TramitacaoUpdateForm(data={})
# Alterando unidade_tramitacao_destino
form.data = {'data_tramitacao':tramitacao_principal.data_tramitacao,
'unidade_tramitacao_local':tramitacao_principal.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_2.pk,
'status':tramitacao_principal.status.pk,
'urgente': tramitacao_principal.urgente,
'texto': tramitacao_principal.texto}
form.instance = tramitacao_principal
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = materia_anexada.tramitacao_set.last()
tramitacao_anexada_anexada = materia_anexada_anexada.tramitacao_set.last()
assert tramitacao_principal.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
# Teste Remoção de Tramitacao
url = reverse('sapl.materia:tramitacao_delete',
kwargs={'pk': tramitacao_principal.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert Tramitacao.objects.filter(id=tramitacao_principal.pk).count() == 0
assert Tramitacao.objects.filter(id=tramitacao_anexada.pk).count() == 0
assert Tramitacao.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 0
# Testes para quando as tramitações das anexadas divergem
form = TramitacaoForm(data={})
form.data = {'data_tramitacao':date(2019, 5, 6),
'unidade_tramitacao_local':unidade_tramitacao_local_1.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_1.pk,
'status':status.pk,
'urgente': False,
'texto': "Texto de teste"}
form.instance.materia_id=materia_principal.pk
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = materia_anexada.tramitacao_set.last()
tramitacao_anexada_anexada = materia_anexada_anexada.tramitacao_set.last()
form = TramitacaoUpdateForm(data={})
# Alterando unidade_tramitacao_destino
form.data = {'data_tramitacao':tramitacao_anexada.data_tramitacao,
'unidade_tramitacao_local':tramitacao_anexada.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_2.pk,
'status':tramitacao_anexada.status.pk,
'urgente': tramitacao_anexada.urgente,
'texto': tramitacao_anexada.texto}
form.instance = tramitacao_anexada
assert form.is_valid()
tramitacao_anexada = form.save()
tramitacao_anexada_anexada = materia_anexada_anexada.tramitacao_set.last()
assert tramitacao_principal.unidade_tramitacao_destino == unidade_tramitacao_destino_1
assert tramitacao_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
# Editando a tramitação principal, as tramitações anexadas não devem ser editadas
form = TramitacaoUpdateForm(data={})
# Alterando o texto
form.data = {'data_tramitacao':tramitacao_principal.data_tramitacao,
'unidade_tramitacao_local':tramitacao_principal.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':tramitacao_principal.unidade_tramitacao_destino.pk,
'status':tramitacao_principal.status.pk,
'urgente': tramitacao_principal.urgente,
'texto': "Testando a alteração"}
form.instance = tramitacao_principal
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = materia_anexada.tramitacao_set.last()
tramitacao_anexada_anexada = materia_anexada_anexada.tramitacao_set.last()
assert tramitacao_principal.texto == "Testando a alteração"
assert not tramitacao_anexada.texto == "Testando a alteração"
assert not tramitacao_anexada_anexada.texto == "Testando a alteração"
# Removendo a tramitação pricipal, as tramitações anexadas não devem ser removidas, pois divergiram
url = reverse('sapl.materia:tramitacao_delete',
kwargs={'pk': tramitacao_principal.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert Tramitacao.objects.filter(id=tramitacao_principal.pk).count() == 0
assert Tramitacao.objects.filter(id=tramitacao_anexada.pk).count() == 1
assert Tramitacao.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 1
# Removendo a tramitação anexada, a tramitação anexada à anexada deve ser removida
url = reverse('sapl.materia:tramitacao_delete',
kwargs={'pk': tramitacao_anexada.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert Tramitacao.objects.filter(id=tramitacao_anexada.pk).count() == 0
assert Tramitacao.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 0

24
sapl/materia/views.py

@ -47,8 +47,7 @@ from sapl.materia.forms import (AnexadaForm, AutoriaForm,
ConfirmarProposicaoForm, ConfirmarProposicaoForm,
DevolverProposicaoForm, LegislacaoCitadaForm, DevolverProposicaoForm, LegislacaoCitadaForm,
OrgaoForm, ProposicaoForm, TipoProposicaoForm, OrgaoForm, ProposicaoForm, TipoProposicaoForm,
TramitacaoForm, TramitacaoUpdateForm, MateriaPesquisaSimplesForm, TramitacaoForm, TramitacaoUpdateForm, MateriaPesquisaSimplesForm)
lista_anexadas)
from sapl.norma.models import LegislacaoCitada from sapl.norma.models import LegislacaoCitada
from sapl.parlamentares.models import Legislatura from sapl.parlamentares.models import Legislatura
from sapl.protocoloadm.models import Protocolo from sapl.protocoloadm.models import Protocolo
@ -56,7 +55,7 @@ from sapl.settings import MEDIA_ROOT
from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, SEPARADOR_HASH_PROPOSICAO, from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, SEPARADOR_HASH_PROPOSICAO,
gerar_hash_arquivo, get_base_url, get_client_ip, gerar_hash_arquivo, get_base_url, get_client_ip,
get_mime_type_from_file_extension, montar_row_autor, get_mime_type_from_file_extension, montar_row_autor,
show_results_filter_set, mail_service_configured) show_results_filter_set, mail_service_configured, lista_anexados)
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
AnexadaEmLoteFilterSet, AnexadaEmLoteFilterSet,
@ -70,7 +69,7 @@ from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
filtra_tramitacao_destino, filtra_tramitacao_destino,
filtra_tramitacao_destino_and_status, filtra_tramitacao_destino_and_status,
filtra_tramitacao_status, filtra_tramitacao_status,
ExcluirTramitacaoEmLote) ExcluirTramitacaoEmLote, compara_tramitacoes_mat)
from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria, from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria,
DespachoInicial, DocumentoAcessorio, MateriaAssunto, DespachoInicial, DocumentoAcessorio, MateriaAssunto,
MateriaLegislativa, Numeracao, Orgao, Origem, Proposicao, MateriaLegislativa, Numeracao, Orgao, Origem, Proposicao,
@ -1299,18 +1298,17 @@ class TramitacaoCrud(MasterDetailCrud):
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
tramitacao = Tramitacao.objects.get(id=self.kwargs['pk']) tramitacao = Tramitacao.objects.get(id=self.kwargs['pk'])
materia = MateriaLegislativa.objects.get(id=tramitacao.materia.id) materia = tramitacao.materia
url = reverse('sapl.materia:tramitacao_list', url = reverse('sapl.materia:tramitacao_list',
kwargs={'pk': tramitacao.materia.id}) kwargs={'pk': materia.id})
ultima_tramitacao = materia.tramitacao_set.order_by( ultima_tramitacao = materia.tramitacao_set.order_by(
'-data_tramitacao', '-data_tramitacao',
'-timestamp', '-timestamp',
'-id').first() '-id').first()
username = request.user.username
if tramitacao.pk != ultima_tramitacao.pk: if tramitacao.pk != ultima_tramitacao.pk:
username = request.user.username
self.logger.error("user=" + username + ". Não é possível deletar a tramitação de pk={}. " self.logger.error("user=" + username + ". Não é possível deletar a tramitação de pk={}. "
"Somente a última tramitação (pk={}) pode ser deletada!." "Somente a última tramitação (pk={}) pode ser deletada!."
.format(tramitacao.pk, ultima_tramitacao.pk)) .format(tramitacao.pk, ultima_tramitacao.pk))
@ -1318,7 +1316,13 @@ class TramitacaoCrud(MasterDetailCrud):
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
tramitacao.delete() tramitacoes_deletar = [tramitacao.id]
mat_anexadas = lista_anexados(materia)
for ma in mat_anexadas:
tram_anexada = ma.tramitacao_set.last()
if compara_tramitacoes_mat(tram_anexada, tramitacao):
tramitacoes_deletar.append(tram_anexada.id)
Tramitacao.objects.filter(id__in=tramitacoes_deletar).delete()
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
class DetailView(MasterDetailCrud.DetailView): class DetailView(MasterDetailCrud.DetailView):
@ -1606,7 +1610,7 @@ class MateriaLegislativaCrud(Crud):
if Anexada.objects.filter(materia_principal=self.kwargs['pk']).exists(): if Anexada.objects.filter(materia_principal=self.kwargs['pk']).exists():
materia = MateriaLegislativa.objects.get(pk=self.kwargs['pk']) materia = MateriaLegislativa.objects.get(pk=self.kwargs['pk'])
anexadas = lista_anexadas(materia) anexadas = lista_anexados(materia)
for anexada in anexadas: for anexada in anexadas:
anexada.em_tramitacao = True if form.instance.em_tramitacao else False anexada.em_tramitacao = True if form.instance.em_tramitacao else False

53
sapl/protocoloadm/forms.py

@ -24,7 +24,7 @@ from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter,
choice_anos_com_protocolo, choice_force_optional, choice_anos_com_protocolo, choice_force_optional,
choice_anos_com_documentoadministrativo, choice_anos_com_documentoadministrativo,
FilterOverridesMetaMixin, choice_anos_com_materias, FilterOverridesMetaMixin, choice_anos_com_materias,
FileFieldCheckMixin) FileFieldCheckMixin, lista_anexados)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, DocumentoAdministrativo,
@ -749,11 +749,17 @@ class TramitacaoAdmForm(ModelForm):
def save(self, commit=True): def save(self, commit=True):
tramitacao = super(TramitacaoAdmForm, self).save(commit) tramitacao = super(TramitacaoAdmForm, self).save(commit)
documento = tramitacao.documento documento = tramitacao.documento
documento.tramitacao = False if tramitacao.status.indicador == "F" else True
documento.save()
lista_tramitacao = [] lista_tramitacao = []
for da in documento.anexados.all(): list_anexados = lista_anexados(documento, False)
for da in list_anexados:
if not da.tramitacaoadministrativo_set.all() \ if not da.tramitacaoadministrativo_set.all() \
or da.tramitacaoadministrativo_set.last() \ or da.tramitacaoadministrativo_set.last() \
.unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local: .unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local:
da.tramitacao = False if tramitacao.status.indicador == "F" else True
da.save()
lista_tramitacao.append(TramitacaoAdministrativo( lista_tramitacao.append(TramitacaoAdministrativo(
status=tramitacao.status, status=tramitacao.status,
documento=da, documento=da,
@ -772,6 +778,19 @@ class TramitacaoAdmForm(ModelForm):
return tramitacao return tramitacao
# Compara se os campos de duas tramitações são iguais,
# exceto os campos id, documento_id e timestamp
def compara_tramitacoes_doc(tramitacao1, tramitacao2):
if not tramitacao1 or not tramitacao2:
return False
lst_items = ['id', 'documento_id', 'timestamp']
values = [(k,v) for k,v in tramitacao1.__dict__.items() if ((k not in lst_items) and (k[0] != '_'))]
other_values = [(k,v) for k,v in tramitacao2.__dict__.items() if (k not in lst_items and k[0] != '_')]
return values == other_values
class TramitacaoAdmEditForm(TramitacaoAdmForm): class TramitacaoAdmEditForm(TramitacaoAdmForm):
unidade_tramitacao_local = forms.ModelChoiceField( unidade_tramitacao_local = forms.ModelChoiceField(
@ -839,6 +858,36 @@ class TramitacaoAdmEditForm(TramitacaoAdmForm):
return cd return cd
@transaction.atomic
def save(self, commit=True):
# tram_principal = super(TramitacaoAdmEditForm, self).save(commit)
ant_tram_principal = TramitacaoAdministrativo.objects.get(id=self.instance.id)
nova_tram_principal = super(TramitacaoAdmEditForm, self).save(commit)
documento = nova_tram_principal.documento
documento.tramitacao = False if nova_tram_principal.status.indicador == "F" else True
documento.save()
list_anexados = lista_anexados(documento, False)
for da in list_anexados:
tram_anexada = da.tramitacaoadministrativo_set.last()
if compara_tramitacoes_doc(ant_tram_principal, tram_anexada):
tram_anexada.status = nova_tram_principal.status
tram_anexada.data_tramitacao = nova_tram_principal.data_tramitacao
tram_anexada.unidade_tramitacao_local = nova_tram_principal.unidade_tramitacao_local
tram_anexada.data_encaminhamento = nova_tram_principal.data_encaminhamento
tram_anexada.unidade_tramitacao_destino = nova_tram_principal.unidade_tramitacao_destino
tram_anexada.urgente = nova_tram_principal.urgente
tram_anexada.texto = nova_tram_principal.texto
tram_anexada.data_fim_prazo = nova_tram_principal.data_fim_prazo
tram_anexada.user = nova_tram_principal.user
tram_anexada.ip = nova_tram_principal.ip
tram_anexada.save()
da.tramitacao = False if nova_tram_principal.status.indicador == "F" else True
da.save()
return nova_tram_principal
class AnexadoForm(ModelForm): class AnexadoForm(ModelForm):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

252
sapl/protocoloadm/tests/test_protocoloadm.py

@ -8,16 +8,20 @@ from model_mommy import mommy
import pytest import pytest
from sapl.base.models import AppConfig from sapl.base.models import AppConfig
from sapl.comissoes.models import Comissao, TipoComissao
from sapl.materia.models import UnidadeTramitacao from sapl.materia.models import UnidadeTramitacao
from sapl.protocoloadm.forms import (AnularProtocoloAdmForm, from sapl.protocoloadm.forms import (AnularProtocoloAdmForm,
DocumentoAdministrativoForm, DocumentoAdministrativoForm,
MateriaLegislativa, ProtocoloDocumentForm, MateriaLegislativa, ProtocoloDocumentForm,
ProtocoloMateriaForm) ProtocoloMateriaForm, TramitacaoAdmForm,
TramitacaoAdmEditForm,
compara_tramitacoes_doc)
from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo, from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo,
StatusTramitacaoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TipoDocumentoAdministrativo,
TipoMateriaLegislativa, TipoMateriaLegislativa, Anexado,
TramitacaoAdministrativo) TramitacaoAdministrativo)
from sapl.utils import lista_anexados
@pytest.mark.django_db(transaction=False) @pytest.mark.django_db(transaction=False)
@ -455,3 +459,247 @@ def test_protocolo_materia_invalido():
assert errors['vincular_materia'] == [_('Este campo é obrigatório.')] assert errors['vincular_materia'] == [_('Este campo é obrigatório.')]
assert len(errors) == 7 assert len(errors) == 7
@pytest.mark.django_db(transaction=False)
def test_lista_documentos_anexados():
tipo_documento = mommy.make(
TipoDocumentoAdministrativo,
descricao="Tipo_Teste"
)
documento_principal = mommy.make(
DocumentoAdministrativo,
numero=20,
ano=2018,
data="2018-01-04",
tipo=tipo_documento
)
documento_anexado = mommy.make(
DocumentoAdministrativo,
numero=21,
ano=2019,
data="2019-05-04",
tipo=tipo_documento
)
documento_anexado_anexado = mommy.make(
DocumentoAdministrativo,
numero=22,
ano=2020,
data="2020-01-05",
tipo=tipo_documento
)
mommy.make(
Anexado,
documento_principal=documento_principal,
documento_anexado=documento_anexado,
data_anexacao="2019-05-11"
)
mommy.make(
Anexado,
documento_principal=documento_anexado,
documento_anexado=documento_anexado_anexado,
data_anexacao="2020-11-05"
)
lista = lista_anexados(documento_principal, False)
assert len(lista) == 2
assert lista[0] == documento_anexado
assert lista[1] == documento_anexado_anexado
@pytest.mark.django_db(transaction=False)
def make_unidade_tramitacao(descricao):
# Cria uma comissão para ser a unidade de tramitação
tipo_comissao = mommy.make(TipoComissao)
comissao = mommy.make(Comissao,
tipo=tipo_comissao,
nome=descricao,
sigla='T',
data_criacao='2016-03-21')
# Testa a comissão
assert comissao.tipo == tipo_comissao
assert comissao.nome == descricao
# Cria a unidade
unidade = mommy.make(UnidadeTramitacao, comissao=comissao)
assert unidade.comissao == comissao
return unidade
@pytest.mark.django_db(transaction=False)
def test_tramitacoes_documentos_anexados(admin_client):
tipo_documento = mommy.make(
TipoDocumentoAdministrativo,
descricao="Tipo_Teste"
)
documento_principal = mommy.make(
DocumentoAdministrativo,
numero=20,
ano=2018,
data="2018-01-04",
tipo=tipo_documento
)
documento_anexado = mommy.make(
DocumentoAdministrativo,
numero=21,
ano=2019,
data="2019-05-04",
tipo=tipo_documento
)
documento_anexado_anexado = mommy.make(
DocumentoAdministrativo,
numero=22,
ano=2020,
data="2020-01-05",
tipo=tipo_documento
)
mommy.make(
Anexado,
documento_principal=documento_principal,
documento_anexado=documento_anexado,
data_anexacao="2019-05-11"
)
mommy.make(
Anexado,
documento_principal=documento_anexado,
documento_anexado=documento_anexado_anexado,
data_anexacao="2020-11-05"
)
unidade_tramitacao_local_1 = make_unidade_tramitacao(descricao="Teste 1")
unidade_tramitacao_destino_1 = make_unidade_tramitacao(descricao="Teste 2")
unidade_tramitacao_destino_2 = make_unidade_tramitacao(descricao="Teste 3")
status = mommy.make(
StatusTramitacaoAdministrativo,
indicador='R')
# Teste criação de Tramitacao
form = TramitacaoAdmForm(data={})
form.data = {'data_tramitacao':date(2019, 5, 6),
'unidade_tramitacao_local':unidade_tramitacao_local_1.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_1.pk,
'status':status.pk,
'urgente': False,
'texto': "Texto de teste"}
form.instance.documento_id=documento_principal.pk
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = documento_anexado.tramitacaoadministrativo_set.last()
tramitacao_anexada_anexada = documento_anexado_anexado.tramitacaoadministrativo_set.last()
# Verifica se foram criadas as tramitações para os documentos anexados e anexados aos anexados
assert documento_principal.tramitacaoadministrativo_set.last() == tramitacao_principal
assert tramitacao_principal.documento.tramitacao == (tramitacao_principal.status.indicador != "F")
assert compara_tramitacoes_doc(tramitacao_principal, tramitacao_anexada)
assert DocumentoAdministrativo.objects.get(id=documento_anexado.pk).tramitacao \
== (tramitacao_anexada.status.indicador != "F")
assert compara_tramitacoes_doc(tramitacao_anexada_anexada, tramitacao_principal)
assert DocumentoAdministrativo.objects.get(id=documento_anexado_anexado.pk).tramitacao \
== (tramitacao_anexada_anexada.status.indicador != "F")
# Teste Edição de Tramitacao
form = TramitacaoAdmEditForm(data={})
# Alterando unidade_tramitacao_destino
form.data = {'data_tramitacao':tramitacao_principal.data_tramitacao,
'unidade_tramitacao_local':tramitacao_principal.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_2.pk,
'status':tramitacao_principal.status.pk,
'urgente': tramitacao_principal.urgente,
'texto': tramitacao_principal.texto}
form.instance = tramitacao_principal
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = documento_anexado.tramitacaoadministrativo_set.last()
tramitacao_anexada_anexada = documento_anexado_anexado.tramitacaoadministrativo_set.last()
assert tramitacao_principal.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
# Teste Remoção de Tramitacao
url = reverse('sapl.protocoloadm:tramitacaoadministrativo_delete',
kwargs={'pk': tramitacao_principal.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_principal.pk).count() == 0
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada.pk).count() == 0
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 0
# Testes para quando as tramitações das anexadas divergem
form = TramitacaoAdmForm(data={})
form.data = {'data_tramitacao':date(2019, 5, 6),
'unidade_tramitacao_local':unidade_tramitacao_local_1.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_1.pk,
'status':status.pk,
'urgente': False,
'texto': "Texto de teste"}
form.instance.documento_id=documento_principal.pk
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = documento_anexado.tramitacaoadministrativo_set.last()
tramitacao_anexada_anexada = documento_anexado_anexado.tramitacaoadministrativo_set.last()
form = TramitacaoAdmEditForm(data={})
# Alterando unidade_tramitacao_destino
form.data = {'data_tramitacao':tramitacao_anexada.data_tramitacao,
'unidade_tramitacao_local':tramitacao_anexada.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':unidade_tramitacao_destino_2.pk,
'status':tramitacao_anexada.status.pk,
'urgente': tramitacao_anexada.urgente,
'texto': tramitacao_anexada.texto}
form.instance = tramitacao_anexada
assert form.is_valid()
tramitacao_anexada = form.save()
tramitacao_anexada_anexada = documento_anexado_anexado.tramitacaoadministrativo_set.last()
assert tramitacao_principal.unidade_tramitacao_destino == unidade_tramitacao_destino_1
assert tramitacao_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
assert tramitacao_anexada_anexada.unidade_tramitacao_destino == unidade_tramitacao_destino_2
# Editando a tramitação principal, as tramitações anexadas não devem ser editadas
form = TramitacaoAdmEditForm(data={})
# Alterando o texto
form.data = {'data_tramitacao':tramitacao_principal.data_tramitacao,
'unidade_tramitacao_local':tramitacao_principal.unidade_tramitacao_local.pk,
'unidade_tramitacao_destino':tramitacao_principal.unidade_tramitacao_destino.pk,
'status':tramitacao_principal.status.pk,
'urgente': tramitacao_principal.urgente,
'texto': "Testando a alteração"}
form.instance = tramitacao_principal
assert form.is_valid()
tramitacao_principal = form.save()
tramitacao_anexada = documento_anexado.tramitacaoadministrativo_set.last()
tramitacao_anexada_anexada = documento_anexado_anexado.tramitacaoadministrativo_set.last()
assert tramitacao_principal.texto == "Testando a alteração"
assert not tramitacao_anexada.texto == "Testando a alteração"
assert not tramitacao_anexada_anexada.texto == "Testando a alteração"
# Removendo a tramitação pricipal, as tramitações anexadas não devem ser removidas, pois divergiram
url = reverse('sapl.protocoloadm:tramitacaoadministrativo_delete',
kwargs={'pk': tramitacao_principal.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_principal.pk).count() == 0
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada.pk).count() == 1
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 1
# Removendo a tramitação anexada, a tramitação anexada à anexada deve ser removida
url = reverse('sapl.protocoloadm:tramitacaoadministrativo_delete',
kwargs={'pk': tramitacao_anexada.pk})
response = admin_client.post(url, {'confirmar':'confirmar'} ,follow=True)
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada.pk).count() == 0
assert TramitacaoAdministrativo.objects.filter(id=tramitacao_anexada_anexada.pk).count() == 0

24
sapl/protocoloadm/views.py

@ -34,7 +34,7 @@ from sapl.materia.views import gerar_pdf_impressos
from sapl.parlamentares.models import Legislatura, Parlamentar from sapl.parlamentares.models import Legislatura, Parlamentar
from sapl.protocoloadm.models import Protocolo from sapl.protocoloadm.models import Protocolo
from sapl.utils import (create_barcode, get_base_url, get_client_ip, from sapl.utils import (create_barcode, get_base_url, get_client_ip,
get_mime_type_from_file_extension, get_mime_type_from_file_extension, lista_anexados,
show_results_filter_set, mail_service_configured) show_results_filter_set, mail_service_configured)
from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm, from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm,
@ -46,7 +46,8 @@ from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm,
DesvincularDocumentoForm, DesvincularMateriaForm, DesvincularDocumentoForm, DesvincularMateriaForm,
filtra_tramitacao_adm_destino_and_status, filtra_tramitacao_adm_destino_and_status,
filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status, filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status,
AnexadoForm, AnexadoEmLoteFilterSet) AnexadoForm, AnexadoEmLoteFilterSet,
compara_tramitacoes_doc)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, StatusTramitacaoAdministrativo, DocumentoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo, Anexado) TipoDocumentoAdministrativo, TramitacaoAdministrativo, Anexado)
@ -1225,14 +1226,15 @@ class TramitacaoAdmCrud(MasterDetailCrud):
class DeleteView(MasterDetailCrud.DeleteView): class DeleteView(MasterDetailCrud.DeleteView):
logger = logging.getLogger(__name__)
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
tramitacao = TramitacaoAdministrativo.objects.get( tramitacao = TramitacaoAdministrativo.objects.get(
id=self.kwargs['pk']) id=self.kwargs['pk'])
documento = DocumentoAdministrativo.objects.get( documento = tramitacao.documento
id=tramitacao.documento.id)
url = reverse( url = reverse(
'sapl.protocoloadm:tramitacaoadministrativo_list', 'sapl.protocoloadm:tramitacaoadministrativo_list',
kwargs={'pk': tramitacao.documento.id}) kwargs={'pk': documento.id})
ultima_tramitacao = \ ultima_tramitacao = \
documento.tramitacaoadministrativo_set.order_by( documento.tramitacaoadministrativo_set.order_by(
@ -1240,11 +1242,21 @@ class TramitacaoAdmCrud(MasterDetailCrud):
'-id').first() '-id').first()
if tramitacao.pk != ultima_tramitacao.pk: if tramitacao.pk != ultima_tramitacao.pk:
username = request.user.username
self.logger.error("user=" + username + ". Não é possível deletar a tramitação de pk={}. "
"Somente a última tramitação (pk={}) pode ser deletada!."
.format(tramitacao.pk, ultima_tramitacao.pk))
msg = _('Somente a última tramitação pode ser deletada!') msg = _('Somente a última tramitação pode ser deletada!')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
tramitacao.delete() tramitacoes_deletar = [tramitacao.id]
docs_anexados = lista_anexados(documento, False)
for da in docs_anexados:
tram_anexada = da.tramitacaoadministrativo_set.last()
if compara_tramitacoes_doc(tram_anexada, tramitacao):
tramitacoes_deletar.append(tram_anexada.id)
TramitacaoAdministrativo.objects.filter(id__in=tramitacoes_deletar).delete()
return HttpResponseRedirect(url) return HttpResponseRedirect(url)

28
sapl/utils.py

@ -5,7 +5,7 @@ import os
import re import re
from unicodedata import normalize as unicodedata_normalize from unicodedata import normalize as unicodedata_normalize
import unicodedata import unicodedata
import logging
from crispy_forms.layout import HTML, Button from crispy_forms.layout import HTML, Button
from django import forms from django import forms
from django.apps import apps from django.apps import apps
@ -940,15 +940,41 @@ def remover_acentos(string):
def mail_service_configured(request=None): def mail_service_configured(request=None):
logger = logging.getLogger(__name__)
if settings.EMAIL_RUNNING is None: if settings.EMAIL_RUNNING is None:
result = True result = True
try: try:
connection = get_connection() connection = get_connection()
connection.open() connection.open()
except Exception as e: except Exception as e:
logger.error(str(e))
result = False result = False
finally: finally:
connection.close() connection.close()
settings.EMAIL_RUNNING = result settings.EMAIL_RUNNING = result
return settings.EMAIL_RUNNING return settings.EMAIL_RUNNING
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)
while anexados_iterator:
anexados_tmp = []
for anx in anexados_iterator:
if isMateriaLegislativa:
anexados_total.append(anx.materia_anexada)
anexados_anexado = Anexada.objects.filter(materia_principal=anx.materia_anexada)
else:
anexados_total.append(anx.documento_anexado)
anexados_anexado = Anexado.objects.filter(documento_principal=anx.documento_anexado)
anexados_tmp.extend(anexados_anexado)
anexados_iterator = anexados_tmp
return anexados_total

Loading…
Cancel
Save