Browse Source

Fix #2987 - Número Inicial de Protocolo (#3019)

* Retirar campo de numeração manual - Protocolo Doc

* Retirar campo de numeração manual - Protocolo Mat

* Fix #2987

* Update sapl/protocoloadm/views.py

Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com>

* Adiciona correções

* Fix migrations

* Atualiza cód. commit 658f261

Co-authored-by: Edward <9326037+edwardoliveira@users.noreply.github.com>
pull/3165/head
João Rodrigues 4 years ago
committed by GitHub
parent
commit
0cf7cf7254
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      sapl/base/forms.py
  2. 20
      sapl/base/migrations/0040_appconfig_inicio_numeracao_protocolo.py
  3. 5
      sapl/base/models.py
  4. 59
      sapl/base/views.py
  5. 26
      sapl/protocoloadm/forms.py
  6. 4
      sapl/protocoloadm/tests/test_protocoloadm.py
  7. 131
      sapl/protocoloadm/views.py
  8. 2
      sapl/templates/base/layouts.yaml

1
sapl/base/forms.py

@ -1553,6 +1553,7 @@ class ConfiguracoesAppForm(ModelForm):
model = AppConfig model = AppConfig
fields = ['documentos_administrativos', fields = ['documentos_administrativos',
'sequencia_numeracao_protocolo', 'sequencia_numeracao_protocolo',
'inicio_numeracao_protocolo',
'sequencia_numeracao_proposicao', 'sequencia_numeracao_proposicao',
'esfera_federacao', 'esfera_federacao',
# 'painel_aberto', # TODO: a ser implementado na versão 3.2 # 'painel_aberto', # TODO: a ser implementado na versão 3.2

20
sapl/base/migrations/0040_appconfig_inicio_numeracao_protocolo.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-05-26 17:58
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0039_auto_20191202_1114'),
]
operations = [
migrations.AddField(
model_name='appconfig',
name='inicio_numeracao_protocolo',
field=models.PositiveIntegerField(default=1, verbose_name='Início da numeração de protocolo'),
),
]

5
sapl/base/models.py

@ -108,6 +108,11 @@ class AppConfig(models.Model):
verbose_name=_('Sequência de numeração de protocolos'), verbose_name=_('Sequência de numeração de protocolos'),
choices=SEQUENCIA_NUMERACAO_PROTOCOLO, default='A') choices=SEQUENCIA_NUMERACAO_PROTOCOLO, default='A')
inicio_numeracao_protocolo = models.PositiveIntegerField(
verbose_name=_('Início da numeração de protocolo'),
default=1
)
esfera_federacao = models.CharField( esfera_federacao = models.CharField(
max_length=1, max_length=1,
blank=True, blank=True,

59
sapl/base/views.py

@ -56,9 +56,9 @@ from sapl.protocoloadm.models import (Anexado, DocumentoAdministrativo, Protocol
TipoDocumentoAdministrativo) TipoDocumentoAdministrativo)
from sapl.sessao.models import (Bancada, PresencaOrdemDia, SessaoPlenaria, from sapl.sessao.models import (Bancada, PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoSessaoPlenaria) SessaoPlenariaPresenca, TipoSessaoPlenaria)
from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, from sapl.utils import (from_date_to_datetime_utc, gerar_hash_arquivo, intervalos_tem_intersecao,
mail_service_configured, parlamentares_ativos, mail_service_configured, parlamentares_ativos, SEPARADOR_HASH_PROPOSICAO,
SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo) show_results_filter_set, num_materias_por_tipo)
from .forms import (AlterarSenhaForm, CasaLegislativaForm, from .forms import (AlterarSenhaForm, CasaLegislativaForm,
ConfiguracoesAppForm, RelatorioAtasFilterSet, ConfiguracoesAppForm, RelatorioAtasFilterSet,
@ -2103,6 +2103,59 @@ class AppConfigCrud(CrudAux):
kwargs={'pk': app_config.pk})) kwargs={'pk': app_config.pk}))
class UpdateView(CrudAux.UpdateView):
form_class = ConfiguracoesAppForm
def form_valid(self, form):
numeracao = AppConfig.objects.last().sequencia_numeracao_protocolo
numeracao_antiga = AppConfig.objects.last().inicio_numeracao_protocolo
self.object = form.save()
numeracao_nova = self.object.inicio_numeracao_protocolo
if numeracao_nova != numeracao_antiga:
if numeracao == 'A':
numero_max = Protocolo.objects.filter(
ano=timezone.now().year
).aggregate(Max('numero'))['numero__max']
elif numeracao == 'L':
legislatura = Legislatura.objects.filter(
data_inicio__year__lte=timezone.now().year,
data_fim__year__gte=timezone.now().year
).first()
data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim
data_inicio_utc = from_date_to_datetime_utc(data_inicio)
data_fim_utc = from_date_to_datetime_utc(data_fim)
numero_max = Protocolo.objects.filter(
Q(data__isnull=False, data__gte=data_inicio, data__lte=data_fim) |
Q(
timestamp__isnull=False, timestamp__gte=data_inicio_utc,
timestamp__lte=data_fim_utc
) | Q(
timestamp_data_hora_manual__isnull=False,
timestamp_data_hora_manual__gte=data_inicio_utc,
timestamp_data_hora_manual__lte=data_fim_utc,
)
).aggregate(Max('numero'))['numero__max']
elif numeracao == 'U':
numero_max = Protocolo.objects.all().aggregate(
Max('numero')
)['numero__max']
ultimo_numero_cadastrado = int(numero_max) if numero_max else 0
if numeracao_nova <= ultimo_numero_cadastrado and numeracao != 'U':
msg = "O novo início da numeração de protocolo entrará em vigor na " \
"próxima sequência, pois já existe protocolo cadastrado com " \
"número superior ou igual ao número inicial definido."
messages.warning(self.request, msg)
return super().form_valid(form)
class ListView(CrudAux.ListView): class ListView(CrudAux.ListView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):

26
sapl/protocoloadm/forms.py

@ -343,7 +343,7 @@ class AnularProtocoloAdmForm(ModelForm):
*args, **kwargs) *args, **kwargs)
class ProtocoloDocumentForm(ModelForm): class ProtocoloDocumentoForm(ModelForm):
tipo_protocolo = forms.ChoiceField(required=True, tipo_protocolo = forms.ChoiceField(required=True,
label=_('Tipo de Protocolo'), label=_('Tipo de Protocolo'),
@ -367,9 +367,6 @@ class ProtocoloDocumentForm(ModelForm):
observacao = forms.CharField(required=False, observacao = forms.CharField(required=False,
widget=forms.Textarea, label=_('Observação')) widget=forms.Textarea, label=_('Observação'))
numero = forms.IntegerField(
required=False, label=_('Número de Protocolo (opcional)'))
data_hora_manual = forms.ChoiceField( data_hora_manual = forms.ChoiceField(
label=_('Informar data e hora manualmente?'), label=_('Informar data e hora manualmente?'),
widget=forms.RadioSelect(), widget=forms.RadioSelect(),
@ -384,7 +381,6 @@ class ProtocoloDocumentForm(ModelForm):
'assunto', 'assunto',
'interessado', 'interessado',
'observacao', 'observacao',
'numero',
'data', 'data',
'hora', 'hora',
] ]
@ -426,8 +422,6 @@ class ProtocoloDocumentForm(ModelForm):
[('interessado', 12)]) [('interessado', 12)])
row6 = to_row( row6 = to_row(
[('observacao', 12)]) [('observacao', 12)])
row7 = to_row(
[('numero', 12)])
fieldset = Fieldset(_('Protocolo com data e hora informados manualmente'), fieldset = Fieldset(_('Protocolo com data e hora informados manualmente'),
row3, row3,
@ -447,14 +441,11 @@ class ProtocoloDocumentForm(ModelForm):
row4, row4,
row5, row5,
HTML("&nbsp;"), HTML("&nbsp;"),
Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece ' Fieldset(HTML("&nbsp;"),
'a partir do número a ser informado)'),
row7,
HTML("&nbsp;"),
form_actions(label=_('Protocolar Documento')) form_actions(label=_('Protocolar Documento'))
) )
) )
super(ProtocoloDocumentForm, self).__init__( super(ProtocoloDocumentoForm, self).__init__(
*args, **kwargs) *args, **kwargs)
if not config.protocolo_manual: if not config.protocolo_manual:
@ -503,9 +494,6 @@ class ProtocoloMateriaForm(ModelForm):
assunto_ementa = forms.CharField(required=True, assunto_ementa = forms.CharField(required=True,
widget=forms.Textarea, label=_('Ementa')) widget=forms.Textarea, label=_('Ementa'))
numero = forms.IntegerField(
required=False, label=_('Número de Protocolo (opcional)'))
data_hora_manual = forms.ChoiceField( data_hora_manual = forms.ChoiceField(
label=_('Informar data e hora manualmente?'), label=_('Informar data e hora manualmente?'),
widget=forms.RadioSelect(), widget=forms.RadioSelect(),
@ -523,7 +511,6 @@ class ProtocoloMateriaForm(ModelForm):
'numero_materia', 'numero_materia',
'ano_materia', 'ano_materia',
'vincular_materia', 'vincular_materia',
'numero',
'data', 'data',
'hora', 'hora',
] ]
@ -616,8 +603,6 @@ class ProtocoloMateriaForm(ModelForm):
[('assunto_ementa', 12)]) [('assunto_ementa', 12)])
row5 = to_row( row5 = to_row(
[('observacao', 12)]) [('observacao', 12)])
row6 = to_row(
[('numero', 12)])
fieldset = Fieldset(_('Protocolo com data e hora informados manualmente'), fieldset = Fieldset(_('Protocolo com data e hora informados manualmente'),
row3, row3,
@ -637,10 +622,7 @@ class ProtocoloMateriaForm(ModelForm):
row4, row4,
row5, row5,
HTML("&nbsp;"), HTML("&nbsp;"),
Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece' Fieldset(HTML("&nbsp;"),
' a partir do número a ser informado)'),
row6,
HTML("&nbsp;"),
form_actions(label=_('Protocolar Matéria'))) form_actions(label=_('Protocolar Matéria')))
) )

4
sapl/protocoloadm/tests/test_protocoloadm.py

@ -13,7 +13,7 @@ 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, ProtocoloDocumentoForm,
ProtocoloMateriaForm, TramitacaoAdmForm, ProtocoloMateriaForm, TramitacaoAdmForm,
TramitacaoAdmEditForm, TramitacaoAdmEditForm,
compara_tramitacoes_doc, compara_tramitacoes_doc,
@ -415,7 +415,7 @@ def test_protocolo_documento_form_invalido():
config = baker.make(AppConfig) config = baker.make(AppConfig)
form = ProtocoloDocumentForm( form = ProtocoloDocumentoForm(
data={}, data={},
initial={ initial={
'user_data_hora_manual': '', 'user_data_hora_manual': '',

131
sapl/protocoloadm/views.py

@ -44,23 +44,19 @@ from sapl.utils import (create_barcode, get_base_url, get_client_ip,
from django.shortcuts import render from django.shortcuts import render
from .forms import (AcompanhamentoDocumentoForm, AnularProtocoloAdmForm, from .forms import (AcompanhamentoDocumentoForm, AnexadoEmLoteFilterSet, AnexadoForm,
DocumentoAcessorioAdministrativoForm, AnularProtocoloAdmForm, compara_tramitacoes_doc,
DocumentoAdministrativoFilterSet,
DocumentoAdministrativoForm, FichaPesquisaAdmForm, FichaSelecionaAdmForm, ProtocoloDocumentForm,
ProtocoloFilterSet, ProtocoloMateriaForm,
TramitacaoAdmEditForm, TramitacaoAdmForm,
DesvincularDocumentoForm, DesvincularMateriaForm, DesvincularDocumentoForm, DesvincularMateriaForm,
filtra_tramitacao_adm_destino_and_status, DocumentoAcessorioAdministrativoForm, DocumentoAdministrativoFilterSet,
filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status, DocumentoAdministrativoForm, FichaPesquisaAdmForm, FichaSelecionaAdmForm,
AnexadoForm, AnexadoEmLoteFilterSet, filtra_tramitacao_adm_destino, filtra_tramitacao_adm_destino_and_status,
PrimeiraTramitacaoEmLoteAdmFilterSet, filtra_tramitacao_adm_status, PrimeiraTramitacaoEmLoteAdmFilterSet,
TramitacaoEmLoteAdmForm, ProtocoloDocumentoForm, ProtocoloFilterSet, ProtocoloMateriaForm,
TramitacaoEmLoteAdmFilterSet, TramitacaoAdmEditForm, TramitacaoAdmForm, TramitacaoEmLoteAdmForm,
compara_tramitacoes_doc) TramitacaoEmLoteAdmFilterSet)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, from .models import (Anexado, AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, StatusTramitacaoAdministrativo, DocumentoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo, Anexado) TipoDocumentoAdministrativo, TramitacaoAdministrativo)
TipoDocumentoAdministrativoCrud = CrudAux.build( TipoDocumentoAdministrativoCrud = CrudAux.build(
@ -582,7 +578,7 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
template_name = "protocoloadm/protocolar_documento.html" template_name = "protocoloadm/protocolar_documento.html"
form_class = ProtocoloDocumentForm form_class = ProtocoloDocumentoForm
form_valid_message = _('Protocolo cadastrado com sucesso!') form_valid_message = _('Protocolo cadastrado com sucesso!')
permission_required = ('protocoloadm.add_protocolo', ) permission_required = ('protocoloadm.add_protocolo', )
@ -617,12 +613,14 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
if numeracao == 'A': if numeracao == 'A':
numero = Protocolo.objects.filter( numero_max = Protocolo.objects.filter(ano=timezone.now().year).aggregate(
ano=timezone.now().year).aggregate(Max('numero')) Max('numero')
)['numero__max']
elif numeracao == 'L': elif numeracao == 'L':
legislatura = Legislatura.objects.filter( legislatura = Legislatura.objects.filter(
data_inicio__year__lte=timezone.now().year, data_inicio__year__lte=timezone.now().year,
data_fim__year__gte=timezone.now().year).first() data_fim__year__gte=timezone.now().year
).first()
data_inicio = legislatura.data_inicio data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim data_fim = legislatura.data_fim
@ -630,32 +628,28 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
data_inicio_utc = from_date_to_datetime_utc(data_inicio) data_inicio_utc = from_date_to_datetime_utc(data_inicio)
data_fim_utc = from_date_to_datetime_utc(data_fim) data_fim_utc = from_date_to_datetime_utc(data_fim)
numero = Protocolo.objects.filter( numero_max = Protocolo.objects.filter(
Q(data__isnull=False, Q(data__isnull=False, data__gte=data_inicio, data__lte=data_fim) | Q(
data__gte=data_inicio, timestamp__isnull=False, timestamp__gte=data_inicio_utc,
data__lte=data_fim) | timestamp__lte=data_fim_utc
Q(timestamp__isnull=False, ) | Q(
timestamp__gte=data_inicio_utc, timestamp_data_hora_manual__isnull=False,
timestamp__lte=data_fim_utc) | timestamp_data_hora_manual__gte=data_inicio_utc,
Q(timestamp_data_hora_manual__isnull=False, timestamp_data_hora_manual__lte=data_fim_utc,
timestamp_data_hora_manual__gte=data_inicio_utc, )
timestamp_data_hora_manual__lte=data_fim_utc,)).\ ).aggregate(Max('numero'))['numero__max']
aggregate(Max('numero'))
elif numeracao == 'U': elif numeracao == 'U':
numero = Protocolo.objects.all().aggregate(Max('numero')) numero_max = Protocolo.objects.all().aggregate(Max('numero'))['numero__max']
protocolo.tipo_processo = '0' # TODO validar o significado protocolo.tipo_processo = '0' # TODO validar o significado
protocolo.anulado = False protocolo.anulado = False
if not protocolo.numero:
protocolo.numero = ( inicio_numeracao = AppConfig.objects.first().inicio_numeracao_protocolo
numero['numero__max'] + 1) if numero['numero__max'] else 1 numero = int(numero_max) if numero_max else 0
elif protocolo.numero < (numero['numero__max'] + 1) if numero['numero__max'] else 0: protocolo.numero = (
msg = _('Número de protocolo deve ser maior que {}'.format( (numero + 1 ) if numero and numero >= inicio_numeracao else inicio_numeracao
numero['numero__max'])) )
self.logger.error(
"user=" + username + ". Número de protocolo deve ser maior que {}.".format(numero['numero__max']))
messages.add_message(self.request, messages.ERROR, msg)
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year protocolo.ano = timezone.now().year
protocolo.assunto_ementa = self.request.POST['assunto'] protocolo.assunto_ementa = self.request.POST['assunto']
@ -829,47 +823,40 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
if numeracao == 'A': if numeracao == 'A':
numero = Protocolo.objects.filter( numero_max = Protocolo.objects.filter(ano=timezone.now().year).aggregate(
ano=timezone.now().year).aggregate(Max('numero')) Max('numero')
)['numero__max']
elif numeracao == 'L': elif numeracao == 'L':
legislatura = Legislatura.objects.filter( legislatura = Legislatura.objects.filter(
data_inicio__year__lte=timezone.now().year, data_inicio__year__lte=timezone.now().year,
data_fim__year__gte=timezone.now().year).first() data_fim__year__gte=timezone.now().year
).first()
data_inicio = legislatura.data_inicio data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim data_fim = legislatura.data_fim
data_inicio_utc = from_date_to_datetime_utc(data_inicio) data_inicio_utc = from_date_to_datetime_utc(data_inicio)
data_fim_utc = from_date_to_datetime_utc(data_fim) data_fim_utc = from_date_to_datetime_utc(data_fim)
numero = Protocolo.objects.filter( numero_max = Protocolo.objects.filter(
Q(data__isnull=False, Q(data__isnull=False, data__gte=data_inicio, data__lte=data_fim) | Q(
data__gte=data_inicio, timestamp__isnull=False, timestamp__gte=data_inicio_utc,
data__lte=data_fim) | timestamp__lte=data_fim_utc
Q(timestamp__isnull=False, ) | Q(
timestamp__gte=data_inicio_utc, timestamp_data_hora_manual__isnull=False,
timestamp__lte=data_fim_utc) | timestamp_data_hora_manual__gte=data_inicio_utc,
Q(timestamp_data_hora_manual__isnull=False, timestamp_data_hora_manual__lte=data_fim_utc,
timestamp_data_hora_manual__gte=data_inicio_utc, )
timestamp_data_hora_manual__lte=data_fim_utc,)).\ ).aggregate(Max('numero'))['numero__max']
aggregate(Max('numero'))
elif numeracao == 'U': elif numeracao == 'U':
numero = Protocolo.objects.all().aggregate(Max('numero')) numero_max = Protocolo.objects.all().aggregate(Max('numero'))['numero__max']
if numeracao is None: inicio_numeracao = AppConfig.objects.first().inicio_numeracao_protocolo
numero['numero__max'] = 0 numero = int(numero_max) if numero_max else 0
protocolo.numero = (
if not protocolo.numero: (numero + 1 ) if numero and numero >= inicio_numeracao else inicio_numeracao
protocolo.numero = ( )
numero['numero__max'] + 1) if numero['numero__max'] else 1
if numero['numero__max']:
if protocolo.numero < (numero['numero__max'] + 1):
self.logger.error("user=" + username + ". Número de protocolo ({}) é menor que {}"
.format(protocolo.numero, numero['numero__max']))
msg = _('Número de protocolo deve ser maior que {}'.format(
numero['numero__max']))
messages.add_message(self.request, messages.ERROR, msg)
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year protocolo.ano = timezone.now().year
protocolo.tipo_protocolo = 0 protocolo.tipo_protocolo = 0

2
sapl/templates/base/layouts.yaml

@ -18,7 +18,7 @@ AppConfig:
- esfera_federacao - esfera_federacao
{% trans 'Proposições e Protocolo' %}: {% trans 'Proposições e Protocolo' %}:
- sequencia_numeracao_proposicao sequencia_numeracao_protocolo - sequencia_numeracao_proposicao sequencia_numeracao_protocolo inicio_numeracao_protocolo
- protocolo_manual receber_recibo_proposicao - protocolo_manual receber_recibo_proposicao
- proposicao_incorporacao_obrigatoria escolher_numero_materia_proposicao - proposicao_incorporacao_obrigatoria escolher_numero_materia_proposicao

Loading…
Cancel
Save