Browse Source

#2764 - Cria tramitação em Lote para Documento Administrativo (#2773)

* Fix #2764 - Tramitacao em lote para Doc Adm

* Adiciona validação do formulario

* Tramitacao em Lote

* Corrige permissões

* Adiciona testes para Tramtacao em lote Adm
pull/2811/head
Cesar Augusto de Carvalho 6 years ago
committed by Cesar Carvalho
parent
commit
f06f8add9f
  1. 7
      sapl/materia/views.py
  2. 249
      sapl/protocoloadm/forms.py
  3. 341
      sapl/protocoloadm/tests/test_protocoloadm.py
  4. 10
      sapl/protocoloadm/urls.py
  5. 151
      sapl/protocoloadm/views.py
  6. 9
      sapl/templates/navbar.yaml
  7. 5
      sapl/templates/protocoloadm/em_lote/subnav_em_lote.yaml
  8. 46
      sapl/templates/protocoloadm/em_lote/tramitacaoadm.html

7
sapl/materia/views.py

@ -1317,12 +1317,19 @@ class TramitacaoCrud(MasterDetailCrud):
return HttpResponseRedirect(url)
else:
tramitacoes_deletar = [tramitacao.id]
if materia.tramitacao_set.count() == 0:
materia.em_tramitacao = False
materia.save()
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)
if ma.tramitacao_set.count() == 0:
ma.em_tramitacao = False
ma.save()
Tramitacao.objects.filter(id__in=tramitacoes_deletar).delete()
return HttpResponseRedirect(url)
class DetailView(MasterDetailCrud.DetailView):

249
sapl/protocoloadm/forms.py

@ -1407,3 +1407,252 @@ class FichaSelecionaAdmForm(forms.Form):
form_actions(label='Gerar Impresso')
)
)
class PrimeiraTramitacaoEmLoteAdmFilterSet(django_filters.FilterSet):
class Meta(FilterOverridesMetaMixin):
model = DocumentoAdministrativo
fields = ['tipo', 'data']
def __init__(self, *args, **kwargs):
super(PrimeiraTramitacaoEmLoteAdmFilterSet, self).__init__(
*args, **kwargs)
self.filters['tipo'].label = 'Tipo de Documento'
self.filters['data'].label = 'Data (Inicial - Final)'
self.form.fields['tipo'].required = True
self.form.fields['data'].required = False
row1 = to_row([('tipo', 12)])
row2 = to_row([('data', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Primeira Tramitação'),
row1, row2, form_actions(label='Pesquisar')))
class TramitacaoEmLoteAdmForm(ModelForm):
logger = logging.getLogger(__name__)
class Meta:
model = TramitacaoAdministrativo
fields = ['data_tramitacao',
'unidade_tramitacao_local',
'status',
'urgente',
'unidade_tramitacao_destino',
'data_encaminhamento',
'data_fim_prazo',
'texto',
'user',
'ip']
widgets = {'user': forms.HiddenInput(),
'ip': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super(TramitacaoEmLoteAdmForm, self).__init__(*args, **kwargs)
self.fields['data_tramitacao'].initial = timezone.now().date()
ust = UnidadeTramitacao.objects.select_related().all()
unidade_tramitacao_destino = [('', '---------')] + [(ut.pk, ut)
for ut in ust if ut.comissao and ut.comissao.ativa]
unidade_tramitacao_destino.extend(
[(ut.pk, ut) for ut in ust if ut.orgao])
unidade_tramitacao_destino.extend(
[(ut.pk, ut) for ut in ust if ut.parlamentar])
self.fields['unidade_tramitacao_destino'].choices = unidade_tramitacao_destino
self.fields['urgente'].label = "Urgente? *"
row1 = to_row([
('data_tramitacao', 4),
('data_encaminhamento', 4),
('data_fim_prazo', 4)
])
row2 = to_row([
('unidade_tramitacao_local', 6),
('unidade_tramitacao_destino', 6),
])
row3 = to_row([
('status', 6),
('urgente', 6)
])
row4 = to_row([
('texto', 12)
])
documentos_checkbox_HTML = '''
<br\><br\><br\>
<fieldset>
<legend style="font-size: 24px;">Selecione os documentos para tramitação:</legend>
<table class="table table-striped table-hover">
<div class="controls">
<div class="checkbox">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(this)" /> Marcar/Desmarcar Todos
</label>
</div>
</div>
<thead>
<tr><th>Documento</th></tr>
</thead>
<tbody>
{% for documento in object_list %}
<tr>
<td>
<input type="checkbox" name="documentos" value="{{documento.id}}" {% if check %} checked {% endif %}/>
<a href="{% url 'sapl.protocoloadm:documentoadministrativo_detail' documento.id %}">
{{documento.tipo.sigla}} {{documento.tipo.descricao}} {{documento.numero}}/{{documento.ano}}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
'''
self.helper = SaplFormHelper()
self.helper.layout = Layout(
Fieldset(
'Detalhes da tramitação:',
row1, row2, row3, row4,
HTML(documentos_checkbox_HTML),
form_actions(label='Salvar')
)
)
def clean(self):
cleaned_data = super(TramitacaoEmLoteAdmForm, self).clean()
if not self.is_valid():
return self.cleaned_data
if 'data_encaminhamento' in cleaned_data:
data_enc_form = cleaned_data['data_encaminhamento']
if 'data_fim_prazo' in cleaned_data:
data_prazo_form = cleaned_data['data_fim_prazo']
if 'data_tramitacao' in cleaned_data:
data_tram_form = cleaned_data['data_tramitacao']
if not self.instance.data_tramitacao:
if cleaned_data['data_tramitacao'] > timezone.now().date():
self.logger.error('A data de tramitação ({}) deve ser '
'menor ou igual a data de hoje ({})!'
.format(cleaned_data['data_tramitacao'], timezone.now().date()))
msg = _(
'A data de tramitação deve ser ' +
'menor ou igual a data de hoje!')
raise ValidationError(msg)
if data_enc_form:
if data_enc_form < data_tram_form:
self.logger.error('A data de encaminhamento ({}) deve ser '
'maior que a data de tramitação ({})!'
.format(data_enc_form, data_tram_form))
msg = _('A data de encaminhamento deve ser ' +
'maior que a data de tramitação!')
raise ValidationError(msg)
if data_prazo_form:
if data_prazo_form < data_tram_form:
self.logger.error('A data fim de prazo ({}) deve ser '
'maior que a data de tramitação ({})!'
.format(data_prazo_form, data_tram_form))
msg = _('A data fim de prazo deve ser ' +
'maior que a data de tramitação!')
raise ValidationError(msg)
if cleaned_data['unidade_tramitacao_local'] == cleaned_data['unidade_tramitacao_destino']:
msg = _('Unidade tramitação local deve ser diferente da unidade tramitação destino.')
self.logger.error('Unidade tramitação local ({}) deve ser diferente da unidade tramitação destino'
.format(cleaned_data['unidade_tramitacao_local']))
raise ValidationError(msg)
return cleaned_data
@transaction.atomic
def save(self, commit=True):
cd = self.cleaned_data
documentos = self.initial['documentos']
user = self.initial['user'] if 'user' in self.initial else None
ip = self.initial['ip'] if 'ip' in self.initial else ''
for doc_id in documentos:
doc = DocumentoAdministrativo.objects.get(id=doc_id)
tramitacao = TramitacaoAdministrativo.objects.create(
status=cd['status'],
documento=doc,
data_tramitacao=cd['data_tramitacao'],
unidade_tramitacao_local=cd['unidade_tramitacao_local'],
unidade_tramitacao_destino=cd['unidade_tramitacao_destino'],
data_encaminhamento=cd['data_encaminhamento'],
urgente=cd['urgente'],
texto=cd['texto'],
data_fim_prazo=cd['data_fim_prazo'],
user=user,
ip=ip
)
doc.tramitacao = False if tramitacao.status.indicador == "F" else True
doc.save()
lista_tramitacao = []
anexados = lista_anexados(doc, False)
for da in anexados:
if not da.tramitacaoadministrativo_set.all() \
or da.tramitacaoadministrativo_set.last() \
.unidade_tramitacao_destino == tramitacao.unidade_tramitacao_local:
da.tramitacao = False if tramitacao.status.indicador == "F" else True
da.save()
lista_tramitacao.append(TramitacaoAdministrativo(
status=tramitacao.status,
documento=da,
data_tramitacao=tramitacao.data_tramitacao,
unidade_tramitacao_local=tramitacao.unidade_tramitacao_local,
data_encaminhamento=tramitacao.data_encaminhamento,
unidade_tramitacao_destino=tramitacao.unidade_tramitacao_destino,
urgente=tramitacao.urgente,
texto=tramitacao.texto,
data_fim_prazo=tramitacao.data_fim_prazo,
user=tramitacao.user,
ip=tramitacao.ip
))
TramitacaoAdministrativo.objects.bulk_create(lista_tramitacao)
return tramitacao
class TramitacaoEmLoteAdmFilterSet(django_filters.FilterSet):
class Meta(FilterOverridesMetaMixin):
model = DocumentoAdministrativo
fields = ['tipo', 'data', 'tramitacaoadministrativo__status',
'tramitacaoadministrativo__unidade_tramitacao_destino']
def __init__(self, *args, **kwargs):
super(TramitacaoEmLoteAdmFilterSet, self).__init__(
*args, **kwargs)
self.filters['tipo'].label = _('Tipo de Documento')
self.filters['data'].label = _('Data (Inicial - Final)')
self.filters['tramitacaoadministrativo__unidade_tramitacao_destino'
].label = _('Unidade Destino (Último Destino)')
self.filters['tramitacaoadministrativo__status'].label = _('Status')
self.form.fields['tipo'].required = True
self.form.fields['data'].required = False
self.form.fields['tramitacaoadministrativo__status'].required = True
self.form.fields[
'tramitacaoadministrativo__unidade_tramitacao_destino'].required = True
row1 = to_row([
('tipo', 4),
('tramitacaoadministrativo__unidade_tramitacao_destino', 4),
('tramitacaoadministrativo__status', 4)])
row2 = to_row([('data', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Tramitação em Lote'),
row1, row2, form_actions(label=_('Pesquisar'))))

341
sapl/protocoloadm/tests/test_protocoloadm.py

@ -1,10 +1,11 @@
from datetime import date, timedelta, datetime
from datetime import date, timedelta
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from model_mommy import mommy
from urllib.parse import urlencode
import pytest
from sapl.base.models import AppConfig
@ -15,7 +16,8 @@ from sapl.protocoloadm.forms import (AnularProtocoloAdmForm,
MateriaLegislativa, ProtocoloDocumentForm,
ProtocoloMateriaForm, TramitacaoAdmForm,
TramitacaoAdmEditForm,
compara_tramitacoes_doc)
compara_tramitacoes_doc,
TramitacaoEmLoteAdmForm)
from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo,
StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo,
@ -703,3 +705,338 @@ def test_tramitacoes_documentos_anexados(admin_client):
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
@pytest.mark.django_db(transaction=False)
def test_tramitacao_lote_documentos_form(admin_client):
tipo_documento = mommy.make(
TipoDocumentoAdministrativo,
descricao="Tipo_Teste"
)
documento = mommy.make(
DocumentoAdministrativo,
numero=20,
ano=2018,
data="2019-05-16",
tipo=tipo_documento
)
unidade_tramitacao_local_1 = make_unidade_tramitacao(descricao="Teste 1")
unidade_tramitacao_destino_1 = make_unidade_tramitacao(descricao="Teste 2")
status = mommy.make(
StatusTramitacaoAdministrativo,
indicador='R')
# Form sem campos obrigatórios
documentos = []
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
errors = form.errors
assert errors['data_tramitacao'] == ['Este campo é obrigatório.']
assert errors['unidade_tramitacao_local'] == ['Este campo é obrigatório.']
assert errors['status'] == ['Este campo é obrigatório.']
assert errors['unidade_tramitacao_destino'] == ['Este campo é obrigatório.']
assert errors['texto'] == ['Este campo é obrigatório.']
assert not form.is_valid()
# Tramitar apenas um documento sem anexados
documentos = [documento.id]
now = timezone.now().date()
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
form.data = {'data_tramitacao': now + timedelta(days=5),
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa'}
assert form.errors['__all__'] == \
["A data de tramitação deve ser menor ou igual a data de hoje!"]
assert not form.is_valid()
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
form.data = {'data_tramitacao': '2019-05-14',
'data_encaminhamento' : '2019-05-09',
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa'}
assert form.errors['__all__'] == \
["A data de encaminhamento deve ser maior que a data de tramitação!"]
assert not form.is_valid()
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
form.data = {'data_tramitacao': '2019-05-14',
'data_encaminhamento' : '2019-05-15',
'data_fim_prazo': '2019-05-09',
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa'}
assert form.errors['__all__'] == \
["A data fim de prazo deve ser maior que a data de tramitação!"]
assert not form.is_valid()
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
form.data = {'data_tramitacao': '2019-05-14',
'data_encaminhamento' : '2019-05-15',
'data_fim_prazo': '2019-05-18',
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_local_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa'}
assert form.errors['__all__'] == \
["Unidade tramitação local deve ser diferente da unidade tramitação destino."]
assert not form.is_valid()
form = TramitacaoEmLoteAdmForm(initial={'documentos': documentos}, data={})
form.data = {'data_tramitacao': '2019-05-14',
'data_encaminhamento' : '2019-05-15',
'data_fim_prazo': '2019-05-18',
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa'}
assert form.is_valid()
@pytest.mark.django_db(transaction=False)
def test_tramitacao_lote_documentos_views(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
)
documento_sem_anexados = mommy.make(
DocumentoAdministrativo,
numero=23,
ano=2020,
data="2021-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")
unidade_tramitacao_destino_3 = make_unidade_tramitacao(descricao="Teste 4")
status = mommy.make(
StatusTramitacaoAdministrativo,
indicador='R')
url = reverse('sapl.protocoloadm:primeira_tramitacao_em_lote_docadm')
url = url + '?' + urlencode({'tipo':tipo_documento.id, 'data_0':'', 'data_1':''})
response = admin_client.post(url, {'salvar':'salvar'}, follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert len(msgs) == 1
assert msgs[0] == 'Escolha algum Documento para ser tramitado.'
documentos = [documento_sem_anexados.id, documento_anexado_anexado.id]
response = admin_client.post(url, {'documentos': documentos,'salvar':'salvar'}, follow=True)
msgs = [m.message for m in response.context['messages']]
assert 'Data Tramitação: Este campo é obrigatório.' in msgs
assert 'Unidade Local: Este campo é obrigatório.' in msgs
assert 'Status: Este campo é obrigatório.' in msgs
assert 'Unidade Destino: Este campo é obrigatório.' in msgs
assert 'Texto da Ação: Este campo é obrigatório.' in msgs
# Primeira tramitação em lote
response = admin_client.post(url,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
assert TramitacaoAdministrativo.objects.all().count() == 2
assert documento_sem_anexados.tramitacaoadministrativo_set.all().count() == 1
assert documento_anexado_anexado.tramitacaoadministrativo_set.all().count() == 1
# Segunda tramitação em lote
url_lote = reverse('sapl.protocoloadm:tramitacao_em_lote_docadm')
url_lote = url_lote + '?' + urlencode(
{'tipo':tipo_documento.id,
'tramitacaoadministrativo__unidade_tramitacao_destino':unidade_tramitacao_destino_1.id,
'tramitacaoadministrativo__status': status.id,
'data_0':'',
'data_1':''})
response = admin_client.post(url_lote, {'salvar':'salvar'}, follow=True)
assert response.status_code == 200
assert response.context_data['object_list'].count() == 2
msgs = [m.message for m in response.context['messages']]
assert len(msgs) == 1
assert msgs[0] == 'Escolha algum Documento para ser tramitado.'
response = admin_client.post(url_lote, {'documentos':documentos, 'salvar':'salvar'}, follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert 'Data Tramitação: Este campo é obrigatório.' in msgs
assert 'Unidade Local: Este campo é obrigatório.' in msgs
assert 'Status: Este campo é obrigatório.' in msgs
assert 'Unidade Destino: Este campo é obrigatório.' in msgs
assert 'Texto da Ação: Este campo é obrigatório.' in msgs
response = admin_client.post(url_lote,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_destino_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert 'Unidade tramitação local deve ser diferente da unidade tramitação destino.' in msgs
response = admin_client.post(url_lote,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_destino_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_2.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert 'Tramitação completa.' in msgs
assert TramitacaoAdministrativo.objects.all().count() == 4
assert documento_sem_anexados.tramitacaoadministrativo_set.all().count() == 2
assert documento_anexado_anexado.tramitacaoadministrativo_set.all().count() == 2
# Tramitar documentos com anexados
# O documento anexado ao anexado não deve tramitar junto porque já está com tramitação diferente
documentos = [documento_principal.id]
response = admin_client.post(url,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_local_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_1.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
assert TramitacaoAdministrativo.objects.all().count() == 6
assert documento_principal.tramitacaoadministrativo_set.all().count() == 1
assert documento_anexado.tramitacaoadministrativo_set.all().count() == 1
# Segunda tramitação com documentos anexados
response = admin_client.post(url_lote,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_destino_1.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_2.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert 'Tramitação completa.' in msgs
assert TramitacaoAdministrativo.objects.all().count() == 8
assert documento_principal.tramitacaoadministrativo_set.all().count() == 2
assert documento_anexado.tramitacaoadministrativo_set.all().count() == 2
# Terceira tramitação em lote
# Agora, o documento anexado ao anexado deve tramitar junto com o documento principal,
# pois suas tramitações convergiram
response = admin_client.post(url_lote,
{'documentos': documentos,
'data_tramitacao': date(2019, 5, 15),
'unidade_tramitacao_local': unidade_tramitacao_destino_2.id,
'unidade_tramitacao_destino': unidade_tramitacao_destino_3.id,
'status': status.id,
'urgente': False,
'texto': 'aaaa',
'salvar':'salvar'},
follow=True)
assert response.status_code == 200
msgs = [m.message for m in response.context['messages']]
assert 'Tramitação completa.' in msgs
assert TramitacaoAdministrativo.objects.all().count() == 11
assert documento_principal.tramitacaoadministrativo_set.all().count() == 3
assert documento_anexado.tramitacaoadministrativo_set.all().count() == 3
assert documento_anexado_anexado.tramitacaoadministrativo_set.all().count() == 3

10
sapl/protocoloadm/urls.py

@ -22,7 +22,9 @@ from sapl.protocoloadm.views import (AcompanhamentoDocumentoView,
doc_texto_integral,
DesvincularDocumentoView,
DesvincularMateriaView,
AnexadoCrud, DocumentoAnexadoEmLoteView)
AnexadoCrud, DocumentoAnexadoEmLoteView,
PrimeiraTramitacaoEmLoteAdmView,
TramitacaoEmLoteAdmView)
from .apps import AppConfig
@ -98,6 +100,12 @@ urlpatterns_protocolo = [
url(r'^protocoloadm/recuperar-materia',
recuperar_materia_protocolo, name='recuperar_materia_protocolo'),
url(r'^protocoloadm/primeira-tramitacao-em-lote',
PrimeiraTramitacaoEmLoteAdmView.as_view(),
name='primeira_tramitacao_em_lote_docadm'),
url(r'^protocoloadm/tramitacao-em-lote', TramitacaoEmLoteAdmView.as_view(),
name='tramitacao_em_lote_docadm'),
]

151
sapl/protocoloadm/views.py

@ -29,7 +29,7 @@ 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)
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa, UnidadeTramitacao
from sapl.materia.views import gerar_pdf_impressos
from sapl.parlamentares.models import Legislatura, Parlamentar
from sapl.protocoloadm.models import Protocolo
@ -47,6 +47,9 @@ from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm,
filtra_tramitacao_adm_destino_and_status,
filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status,
AnexadoForm, AnexadoEmLoteFilterSet,
PrimeiraTramitacaoEmLoteAdmFilterSet,
TramitacaoEmLoteAdmForm,
TramitacaoEmLoteAdmFilterSet,
compara_tramitacoes_doc)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, StatusTramitacaoAdministrativo,
@ -1251,12 +1254,19 @@ class TramitacaoAdmCrud(MasterDetailCrud):
return HttpResponseRedirect(url)
else:
tramitacoes_deletar = [tramitacao.id]
if documento.tramitacaoadministrativo_set.count() == 0:
documento.tramitacao = False
documento.save()
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)
if da.tramitacaoadministrativo_set.count() == 0:
da.tramitacao = False
da.save()
TramitacaoAdministrativo.objects.filter(id__in=tramitacoes_deletar).delete()
return HttpResponseRedirect(url)
@ -1437,3 +1447,142 @@ class FichaSelecionaAdmView(PermissionRequiredMixin, FormView):
return gerar_pdf_impressos(self.request, context,
'materia/impressos/ficha_adm_pdf.html')
class PrimeiraTramitacaoEmLoteAdmView(PermissionRequiredMixin, FilterView):
filterset_class = PrimeiraTramitacaoEmLoteAdmFilterSet
template_name = 'protocoloadm/em_lote/tramitacaoadm.html'
permission_required = ('materia.add_tramitacao', )
primeira_tramitacao = True
logger = logging.getLogger(__name__)
def get_context_data(self, **kwargs):
context = super(PrimeiraTramitacaoEmLoteAdmView,
self).get_context_data(**kwargs)
context['subnav_template_name'] = 'protocoloadm/em_lote/subnav_em_lote.yaml'
context['primeira_tramitacao'] = self.primeira_tramitacao
# Verifica se os campos foram preenchidos
if not self.filterset.form.is_valid():
return context
context['object_list'] = context['object_list'].order_by(
'ano', 'numero')
qr = self.request.GET.copy()
form = TramitacaoEmLoteAdmForm()
context['form'] = form
if self.primeira_tramitacao:
context['title'] = _('Primeira Tramitação em Lote')
# Pega somente documentos que não possuem tramitação
context['object_list'] = [obj for obj in context['object_list']
if obj.tramitacaoadministrativo_set.all().count() == 0]
else:
context['title'] = _('Tramitação em Lote')
context['form'].fields['unidade_tramitacao_local'].initial = UnidadeTramitacao.objects.get(
id=qr['tramitacaoadministrativo__unidade_tramitacao_destino'])
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
return context
def post(self, request, *args, **kwargs):
user = request.user
ip = get_client_ip(request)
documentos_ids = request.POST.getlist('documentos')
if not documentos_ids:
msg = _("Escolha algum Documento para ser tramitado.")
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
form = TramitacaoEmLoteAdmForm(request.POST, initial=
{'documentos': documentos_ids,
'user': user, 'ip':ip})
if form.is_valid():
# cd = form.clean()
form.save()
msg = _('Tramitação completa.')
self.logger.info('user=' + user.username + '. Tramitação completa.')
messages.add_message(request, messages.SUCCESS, msg)
return self.get_success_url()
return self.form_invalid(form)
def get_success_url(self):
return HttpResponseRedirect(reverse('sapl.protocoloadm:primeira_tramitacao_em_lote_docadm'))
def form_invalid(self, form, *args, **kwargs):
for key, erros in form.errors.items():
if not key=='__all__':
[messages.add_message(self.request, messages.ERROR, form.fields[key].label + ": " + e) for e in erros]
else:
[messages.add_message(self.request, messages.ERROR, e) for e in erros]
return self.get(self.request, kwargs, {'form':form})
class TramitacaoEmLoteAdmView(PrimeiraTramitacaoEmLoteAdmView):
filterset_class = TramitacaoEmLoteAdmFilterSet
primeira_tramitacao = False
def get_context_data(self, **kwargs):
context = super(TramitacaoEmLoteAdmView,
self).get_context_data(**kwargs)
qr = self.request.GET.copy()
context['primeira_tramitacao'] = False
if ('tramitacao__status' in qr and
'tramitacao__unidade_tramitacao_destino' in qr and
qr['tramitacao__status'] and
qr['tramitacao__unidade_tramitacao_destino']):
lista = self.filtra_tramitacao_destino_and_status(
qr['tramitacao__status'],
qr['tramitacao__unidade_tramitacao_destino'])
context['object_list'] = context['object_list'].filter(
id__in=lista).distinct()
return context
def pega_ultima_tramitacao(self):
return TramitacaoAdministrativo.objects.values(
'documento_id').annotate(data_encaminhamento=Max(
'data_encaminhamento'),
id=Max('id')).values_list('id', flat=True)
def filtra_tramitacao_status(self, status):
lista = self.pega_ultima_tramitacao()
return TramitacaoAdministrativo.objects.filter(
id__in=lista,
status=status).distinct().values_list('documento_id', flat=True)
def filtra_tramitacao_destino(self, destino):
lista = self.pega_ultima_tramitacao()
return TramitacaoAdministrativo.objects.filter(
id__in=lista,
unidade_tramitacao_destino=destino).distinct().values_list(
'documento_id', flat=True)
def filtra_tramitacao_destino_and_status(self, status, destino):
lista = self.pega_ultima_tramitacao()
return TramitacaoAdministrativo.objects.filter(
id__in=lista,
status=status,
unidade_tramitacao_destino=destino).distinct().values_list(
'documento_id', flat=True)

9
sapl/templates/navbar.yaml

@ -29,8 +29,13 @@
url: sapl.materia:receber-proposicao
- title: {% trans 'Documentos Administrativos' %}
{% if 'documentos_administrativos'|get_config_attr == 'R' %}check_permission: protocoloadm.list_documentoadministrativo{%endif%}
url: sapl.protocoloadm:pesq_doc_adm
{% if 'documentos_administrativos'|get_config_attr == 'R' %}check_permission: protocoloadm.list_documentoadministrativo {% endif %}
children:
- title: {% trans 'Pesquisar Documentos Administrativos' %}
url: sapl.protocoloadm:pesq_doc_adm
- title: {% trans 'Tramitação em Lote' %}
url: sapl.protocoloadm:primeira_tramitacao_em_lote_docadm
check_permission: sapl.documento:add_tramitacao
- title: {% trans 'Atividade Legislativa' %}
children:

5
sapl/templates/protocoloadm/em_lote/subnav_em_lote.yaml

@ -0,0 +1,5 @@
{% load i18n common_tags %}
- title: {% trans 'Primeira Tramitação' %}
url: primeira_tramitacao_em_lote_docadm
- title: {% trans 'Tramitação em Lote' %}
url: tramitacao_em_lote_docadm

46
sapl/templates/protocoloadm/em_lote/tramitacaoadm.html

@ -0,0 +1,46 @@
{% extends "crud/detail.html" %}
{% load i18n crispy_forms_tags %}
{% block detail_content %}
{% if not show_results %}
{% crispy filter.form %}
{% else %}
{% if object_list|length > 0 %}
{% if object_list|length == 1 %}
<h3 style="text-align: right;">{% trans 'Pesquisa concluída com sucesso! Foi encontrado 1 documento.'%}</h3>
{% else %}
<h3 style="text-align: right;">Foram encontrados {{object_list|length}} documentos.</h3>
{% endif %}
{% crispy form %}
{% else %}
<tr><td><h3 style="text-align: right;">Nenhum documento encontrado.</h3></td></tr>
{% endif %}
{% endif%}
{% endblock detail_content %}
{% block extra_js %}
<script language="JavaScript">
function checkAll(elem) {
let checkboxes = document.getElementsByName('documentos');
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].type == 'checkbox')
checkboxes[i].checked = elem.checked;
}
}
$(document).ready(function(){
var primeira_tramitacao = {{primeira_tramitacao|yesno:"true,false"}}
if (primeira_tramitacao == false){
$('#id_unidade_tramitacao_local').prop('disabled', true);
}
// Reabilita o campo, no momento do Submit, para que seu dado seja enviado
$('input[type=submit]').click(function() {
$('#id_unidade_tramitacao_local').attr('disabled', false);
$('#id_unidade_tramitacao_local').parents('form').submit();
});
});
</script>
{% endblock %}
Loading…
Cancel
Save