Browse Source

Fix #2337 (#2448)

* impl data e hora manual no protocolo de matérias

* impl data e hora manual no protocolo de documentos

* ajustes de teste em protocoloadm
pull/2457/head
Leandro Roberto da Silva 6 years ago
committed by GitHub
parent
commit
ac91543b0f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 155
      sapl/protocoloadm/forms.py
  2. 35
      sapl/protocoloadm/migrations/0014_auto_20190110_1300.py
  3. 21
      sapl/protocoloadm/migrations/0015_protocolo_timestamp_data_hora_manual.py
  4. 21
      sapl/protocoloadm/migrations/0016_auto_20190110_1345.py
  5. 24
      sapl/protocoloadm/models.py
  6. 23
      sapl/protocoloadm/tests/test_protocoloadm.py
  7. 41
      sapl/protocoloadm/views.py
  8. 35
      sapl/relatorios/views.py
  9. 1
      sapl/static/js/app.js
  10. 6
      sapl/templates/protocoloadm/comprovante.html
  11. 14
      sapl/templates/protocoloadm/protocolar_documento.html
  12. 62
      sapl/templates/protocoloadm/protocolar_materia.html
  13. 10
      sapl/templates/protocoloadm/protocolo_mostrar.html
  14. 18
      sapl/utils.py

155
sapl/protocoloadm/forms.py

@ -1,9 +1,9 @@
import logging
from crispy_forms.bootstrap import InlineRadios
from crispy_forms.bootstrap import InlineRadios, Alert
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout
from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout, Div
from django import forms
from django.core.exceptions import (MultipleObjectsReturned,
ObjectDoesNotExist, ValidationError)
@ -18,11 +18,12 @@ from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row
from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa,
UnidadeTramitacao)
from sapl.protocoloadm.models import Protocolo
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter,
RangeWidgetOverride, autor_label, autor_modal,
choice_anos_com_protocolo, choice_force_optional,
choice_anos_com_documentoadministrativo,
FilterOverridesMetaMixin)
FilterOverridesMetaMixin, choice_anos_com_materias)
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo,
@ -344,6 +345,12 @@ class ProtocoloDocumentForm(ModelForm):
numero = forms.IntegerField(
required=False, label=_('Número de Protocolo (opcional)'))
data_hora_manual = forms.ChoiceField(
label=_('Informar data e hora manualmente?'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
class Meta:
model = Protocolo
fields = ['tipo_protocolo',
@ -352,7 +359,9 @@ class ProtocoloDocumentForm(ModelForm):
'assunto',
'interessado',
'observacao',
'numero'
'numero',
'data',
'hora',
]
def __init__(self, *args, **kwargs):
@ -360,30 +369,56 @@ class ProtocoloDocumentForm(ModelForm):
row1 = to_row(
[(InlineRadios('tipo_protocolo'), 12)])
row2 = to_row(
[('tipo_documento', 6),
('numero_paginas', 6)])
row3 = to_row(
[('assunto', 12)])
[('tipo_documento', 5),
('numero_paginas', 2),
(Div(), 1),
(InlineRadios('data_hora_manual'), 4),
])
row3 = to_row([
(Div(), 2),
(Alert(
"""
Usuário: <strong>{}</strong> - {}<br>
IP: <strong>{}</strong> - {}<br>
""".format(
kwargs['initial']['user_data_hora_manual'],
Protocolo._meta.get_field(
'user_data_hora_manual').help_text,
kwargs['initial']['ip_data_hora_manual'],
Protocolo._meta.get_field(
'ip_data_hora_manual').help_text,
),
dismiss=False,
css_class='alert-info'), 6),
('data', 2),
('hora', 2),
])
row4 = to_row(
[('interessado', 12)])
[('assunto', 12)])
row5 = to_row(
[('observacao', 12)])
[('interessado', 12)])
row6 = to_row(
[('observacao', 12)])
row7 = to_row(
[('numero', 12)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Identificação de Documento'),
row1,
row2,
row2),
Fieldset(_('Protocolo com data e hora informados manualmente'),
row3,
row4,
row5,
HTML("&nbsp;"),
),
css_id='protocolo_data_hora_manual',
css_class='hidden'),
row4,
row5,
HTML("&nbsp;"),
Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece '
'a partir do número a ser informado)'),
row6,
row7,
HTML("&nbsp;"),
form_actions(label=_('Protocolar Documento'))
)
@ -419,10 +454,11 @@ class ProtocoloMateriaForm(ModelForm):
ano_materia = forms.CharField(
label=_('Ano matéria'), required=False)
vincular_materia = forms.ChoiceField(label=_('Vincular a matéria existente?'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
vincular_materia = forms.ChoiceField(
label=_('Vincular a matéria existente?'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
numero_paginas = forms.CharField(label=_('Núm. Páginas'), required=True)
@ -435,6 +471,12 @@ class ProtocoloMateriaForm(ModelForm):
numero = forms.IntegerField(
required=False, label=_('Número de Protocolo (opcional)'))
data_hora_manual = forms.ChoiceField(
label=_('Informar data e hora manualmente?'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
class Meta:
model = Protocolo
fields = ['tipo_materia',
@ -446,7 +488,9 @@ class ProtocoloMateriaForm(ModelForm):
'numero_materia',
'ano_materia',
'vincular_materia',
'numero'
'numero',
'data',
'hora',
]
def clean_autor(self):
@ -506,28 +550,55 @@ class ProtocoloMateriaForm(ModelForm):
('tipo_autor', 3),
('autor', 3)])
row2 = to_row(
[(InlineRadios('vincular_materia'), 4),
('numero_materia', 4),
('ano_materia', 4), ])
row3 = to_row(
[('assunto_ementa', 12)])
[(InlineRadios('vincular_materia'), 3),
('numero_materia', 2),
('ano_materia', 2),
(Div(), 1),
(InlineRadios('data_hora_manual'), 4),
])
row3 = to_row([
(Div(), 2),
(Alert(
"""
Usuário: <strong>{}</strong> - {}<br>
IP: <strong>{}</strong> - {}<br>
""".format(
kwargs['initial']['user_data_hora_manual'],
Protocolo._meta.get_field(
'user_data_hora_manual').help_text,
kwargs['initial']['ip_data_hora_manual'],
Protocolo._meta.get_field(
'ip_data_hora_manual').help_text,
),
dismiss=False,
css_class='alert-info'), 6),
('data', 2),
('hora', 2),
])
row4 = to_row(
[('observacao', 12)])
[('assunto_ementa', 12)])
row5 = to_row(
[('observacao', 12)])
row6 = to_row(
[('numero', 12)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Identificação da Matéria'),
row1,
row2,
row2),
Fieldset(_('Protocolo com data e hora informados manualmente'),
row3,
row4,
HTML("&nbsp;"),
),
css_id='protocolo_data_hora_manual',
css_class='hidden'),
row4,
row5,
HTML("&nbsp;"),
Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece'
' a partir do número a ser informado)'),
row5,
row6,
HTML("&nbsp;"),
form_actions(label=_('Protocolar Matéria')))
)
@ -855,15 +926,15 @@ class DesvincularDocumentoForm(ModelForm):
logger = logging.getLogger(__name__)
numero = forms.CharField(required=True,
label=DocumentoAdministrativo._meta.
get_field('numero').verbose_name
)
ano = forms.ChoiceField(required=True,
label=DocumentoAdministrativo._meta.
get_field('ano').verbose_name,
choices=RANGE_ANOS,
widget=forms.Select(attrs={'class': 'selector'}))
numero = forms.CharField(
required=True,
label=DocumentoAdministrativo._meta.get_field('numero').verbose_name)
ano = forms.ChoiceField(
required=True,
label=DocumentoAdministrativo._meta.get_field('ano').verbose_name,
choices=choice_anos_com_documentoadministrativo,
widget=forms.Select(attrs={'class': 'selector'}))
def clean(self):
super(DesvincularDocumentoForm, self).clean()
@ -929,7 +1000,7 @@ class DesvincularMateriaForm(forms.Form):
label=_('Número da Matéria'))
ano = forms.ChoiceField(required=True,
label=_('Ano da Matéria'),
choices=RANGE_ANOS,
choices=choice_anos_com_materias,
widget=forms.Select(attrs={'class': 'selector'}))
tipo = forms.ModelChoiceField(label=_('Tipo de Matéria'),
required=True,

35
sapl/protocoloadm/migrations/0014_auto_20190110_1300.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2019-01-10 15:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0013_auto_20190106_1336'),
]
operations = [
migrations.AddField(
model_name='protocolo',
name='ip_data_hora_manual',
field=models.CharField(blank=True, help_text='Endereço IP da estação de trabalho do usuário que está realizando Protocolo e informando data e hora manualmente.', max_length=15, verbose_name='IP'),
),
migrations.AddField(
model_name='protocolo',
name='user_data_hora_manual',
field=models.CharField(blank=True, help_text='Usuário que está realizando Protocolo e informando data e hora manualmente.', max_length=20, verbose_name='IP'),
),
migrations.AlterField(
model_name='protocolo',
name='data',
field=models.DateField(blank=True, help_text='Informado manualmente', null=True, verbose_name='Data do Protocolo'),
),
migrations.AlterField(
model_name='protocolo',
name='hora',
field=models.TimeField(blank=True, help_text='Informado manualmente', null=True, verbose_name='Hora do Protocolo'),
),
]

21
sapl/protocoloadm/migrations/0015_protocolo_timestamp_data_hora_manual.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2019-01-10 15:43
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0014_auto_20190110_1300'),
]
operations = [
migrations.AddField(
model_name='protocolo',
name='timestamp_data_hora_manual',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

21
sapl/protocoloadm/migrations/0016_auto_20190110_1345.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2019-01-10 15:45
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0015_protocolo_timestamp_data_hora_manual'),
]
operations = [
migrations.AlterField(
model_name='protocolo',
name='timestamp',
field=models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True),
),
]

24
sapl/protocoloadm/models.py

@ -57,13 +57,29 @@ class Protocolo(models.Model):
choices=RANGE_ANOS,
verbose_name=_('Ano do Protocolo'))
# FIXME: https://github.com/interlegis/sapl/issues/2337
data = models.DateField(null=True, blank=True)
hora = models.TimeField(null=True, blank=True)
data = models.DateField(null=True, blank=True,
verbose_name=_('Data do Protocolo'),
help_text=_('Informado manualmente'))
hora = models.TimeField(null=True, blank=True,
verbose_name=_('Hora do Protocolo'),
help_text=_('Informado manualmente'))
timestamp_data_hora_manual = models.DateTimeField(default=timezone.now)
user_data_hora_manual = models.CharField(
max_length=20, blank=True,
verbose_name=_('IP'),
help_text=_('Usuário que está realizando Protocolo e informando '
'data e hora manualmente.'))
ip_data_hora_manual = models.CharField(
max_length=15, blank=True,
verbose_name=_('IP'),
help_text=_('Endereço IP da estação de trabalho '
'do usuário que está realizando Protocolo e informando '
'data e hora manualmente.'))
# Não foi utilizado auto_now_add=True em timestamp porque
# ele usa datetime.now que não é timezone aware.
timestamp = models.DateTimeField(default=timezone.now)
timestamp = models.DateTimeField(
default=timezone.now, null=True, blank=True)
tipo_protocolo = models.PositiveIntegerField(
blank=True, null=True, verbose_name=_('Tipo de Protocolo'))
tipo_processo = models.PositiveIntegerField()

23
sapl/protocoloadm/tests/test_protocoloadm.py

@ -1,4 +1,4 @@
from datetime import date, timedelta
from datetime import date, timedelta, datetime
from django.core.urlresolvers import reverse
from django.utils import timezone
@ -392,29 +392,42 @@ def test_documento_administrativo_protocolo_inexistente():
def test_protocolo_documento_form_invalido():
form = ProtocoloDocumentForm(data={})
form = ProtocoloDocumentForm(
data={},
initial={
'user_data_hora_manual': '',
'ip_data_hora_manual': '',
'data': timezone.localdate(timezone.now()),
'hora': timezone.localtime(timezone.now())})
assert not form.is_valid()
errors = form.errors
assert errors['data_hora_manual'] == [_('Este campo é obrigatório.')]
assert errors['tipo_protocolo'] == [_('Este campo é obrigatório.')]
assert errors['interessado'] == [_('Este campo é obrigatório.')]
assert errors['tipo_documento'] == [_('Este campo é obrigatório.')]
assert errors['numero_paginas'] == [_('Este campo é obrigatório.')]
assert errors['assunto'] == [_('Este campo é obrigatório.')]
assert len(errors) == 5
assert len(errors) == 6
def test_protocolo_materia_invalido():
form = ProtocoloMateriaForm(data={})
form = ProtocoloMateriaForm(data={},
initial={
'user_data_hora_manual': '',
'ip_data_hora_manual': '',
'data': timezone.localdate(timezone.now()),
'hora': timezone.localtime(timezone.now())})
assert not form.is_valid()
errors = form.errors
assert errors['data_hora_manual'] == [_('Este campo é obrigatório.')]
assert errors['assunto_ementa'] == [_('Este campo é obrigatório.')]
assert errors['tipo_autor'] == [_('Este campo é obrigatório.')]
assert errors['tipo_materia'] == [_('Este campo é obrigatório.')]
@ -422,4 +435,4 @@ def test_protocolo_materia_invalido():
assert errors['autor'] == [_('Este campo é obrigatório.')]
assert errors['vincular_materia'] == [_('Este campo é obrigatório.')]
assert len(errors) == 6
assert len(errors) == 7

41
sapl/protocoloadm/views.py

@ -492,6 +492,15 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
return reverse('sapl.protocoloadm:protocolo_mostrar',
kwargs={'pk': self.object.id})
def get_initial(self):
initial = super().get_initial()
initial['user_data_hora_manual'] = self.request.user.username
initial['ip_data_hora_manual'] = get_client_ip(self.request)
initial['data'] = timezone.localdate(timezone.now())
initial['hora'] = timezone.localtime(timezone.now())
return initial
def form_valid(self, form):
protocolo = form.save(commit=False)
username = self.request.user.username
@ -538,6 +547,17 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year
protocolo.assunto_ementa = self.request.POST['assunto']
if form.cleaned_data['data_hora_manual'] == 'True':
protocolo.timestamp = None
protocolo.user_data_hora_manual = username
protocolo.ip_data_hora_manual = get_client_ip(self.request)
else:
protocolo.data = None
protocolo.hora = None
protocolo.user_data_hora_manual = ''
protocolo.ip_data_hora_manual = ''
protocolo.save()
self.object = protocolo
return redirect(self.get_success_url())
@ -659,6 +679,15 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
return reverse('sapl.protocoloadm:materia_continuar', kwargs={
'pk': protocolo.pk})
def get_initial(self):
initial = super().get_initial()
initial['user_data_hora_manual'] = self.request.user.username
initial['ip_data_hora_manual'] = get_client_ip(self.request)
initial['data'] = timezone.localdate(timezone.now())
initial['hora'] = timezone.localtime(timezone.now())
return initial
def form_valid(self, form):
protocolo = form.save(commit=False)
username = self.request.user.username
@ -719,6 +748,16 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
protocolo.observacao = self.request.POST['observacao']
protocolo.assunto_ementa = self.request.POST['assunto_ementa']
if form.cleaned_data['data_hora_manual'] == 'True':
protocolo.timestamp = None
protocolo.user_data_hora_manual = username
protocolo.ip_data_hora_manual = get_client_ip(self.request)
else:
protocolo.data = None
protocolo.hora = None
protocolo.user_data_hora_manual = ''
protocolo.ip_data_hora_manual = ''
protocolo.save()
data = form.cleaned_data
if data['vincular_materia'] == 'True':
@ -1168,4 +1207,4 @@ class FichaSelecionaAdmView(PermissionRequiredMixin, FormView):
context['documento'] = documento
return gerar_pdf_impressos(self.request, context,
'materia/impressos/ficha_adm_pdf.html')
'materia/impressos/ficha_adm_pdf.html')

35
sapl/relatorios/views.py

@ -1,7 +1,7 @@
from datetime import datetime as dt
import html
import re
import logging
from datetime import datetime as dt
import re
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404, HttpResponse
@ -581,7 +581,6 @@ def get_sessao_plenaria(sessao, casa):
if dic_expedientes:
lst_expedientes.append(dic_expedientes)
# Lista das matérias do Expediente, incluindo o resultado das votacoes
lst_expediente_materia = []
for expediente_materia in ExpedienteMateria.objects.filter(
@ -612,7 +611,8 @@ def get_sessao_plenaria(sessao, casa):
dic_expediente_materia["nom_autor"] = ''
autoria = materia.autoria_set.all()
dic_expediente_materia['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
dic_expediente_materia['num_autores'] = 'Autores' if len(
autoria) > 1 else 'Autor'
if autoria:
for a in autoria:
if a.autor.nome:
@ -687,7 +687,7 @@ def get_sessao_plenaria(sessao, casa):
numeracao = materia.numeracao_set.first()
if numeracao:
dic_votacao["des_numeracao"] = (
str(numeracao.numero_materia) +
'/' +
@ -762,7 +762,6 @@ def get_sessao_plenaria(sessao, casa):
lst_ocorrencias.append(o)
return (inf_basicas_dic,
lst_mesa,
lst_presenca_sessao,
@ -810,10 +809,12 @@ def relatorio_sessao_plenaria(request, pk):
imagem = get_imagem(casa)
try:
logger.debug("user=" + username + ". Tentando obter SessaoPlenaria com id={}.".format(pk))
logger.debug("user=" + username +
". Tentando obter SessaoPlenaria com id={}.".format(pk))
sessao = SessaoPlenaria.objects.get(id=pk)
except ObjectDoesNotExist as e:
logger.error("user=" + username + ". Essa SessaoPlenaria não existe (pk={}). ".format(pk) + str(e))
logger.error("user=" + username +
". Essa SessaoPlenaria não existe (pk={}). ".format(pk) + str(e))
raise Http404('Essa página não existe')
(inf_basicas_dic,
@ -828,11 +829,10 @@ def relatorio_sessao_plenaria(request, pk):
lst_oradores,
lst_ocorrencias) = get_sessao_plenaria(sessao, casa)
for idx in range(len(lst_expedientes)):
txt_expedientes = lst_expedientes[idx]['txt_expediente']
txt_expedientes = TrocaTag(txt_expedientes, '<table', 'table>', 6, 6,
'expedientes', '</para><blockTable style = "', 'blockTable><para>')
'expedientes', '</para><blockTable style = "', 'blockTable><para>')
lst_expedientes[idx]['txt_expediente'] = txt_expedientes
pdf = pdf_sessao_plenaria_gerar.principal(
@ -868,7 +868,7 @@ def get_protocolos(prots):
ts.strftime("%H:%m")
else:
dic['data'] = protocolo.data.strftime("%d/%m/%Y") + ' - <b>Horário:</b>' \
+ protocolo.hora.strftime("%H:%m")
+ protocolo.hora.strftime("%H:%m")
dic['txt_assunto'] = protocolo.assunto_ementa
@ -979,8 +979,8 @@ def get_etiqueta_protocolos(prots):
dic['titulo'] = str(p.numero) + '/' + str(p.ano)
tz_hora = timezone.localtime(p.timestamp)
if p.timestamp:
tz_hora = timezone.localtime(p.timestamp)
dic['data'] = '<b>Data: </b>' + tz_hora.strftime(
"%d/%m/%Y") + ' - <b>Horário: </b>' + tz_hora.strftime("%H:%M")
else:
@ -1072,7 +1072,8 @@ def get_pauta_sessao(sessao, casa):
id=expediente_materia.materia.id).first()
dic_expediente_materia = {}
dic_expediente_materia["tipo_materia"] = materia.tipo.sigla + ' - ' + materia.tipo.descricao
dic_expediente_materia["tipo_materia"] = materia.tipo.sigla + \
' - ' + materia.tipo.descricao
dic_expediente_materia["num_ordem"] = str(
expediente_materia.numero_ordem)
dic_expediente_materia["id_materia"] = str(
@ -1090,7 +1091,8 @@ def get_pauta_sessao(sessao, casa):
dic_expediente_materia["nom_autor"] = ''
autoria = materia.autoria_set.all()
dic_expediente_materia['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
dic_expediente_materia['num_autores'] = 'Autores' if len(
autoria) > 1 else 'Autor'
if autoria:
for a in autoria:
if a.autor.nome:
@ -1112,7 +1114,8 @@ def get_pauta_sessao(sessao, casa):
materia = MateriaLegislativa.objects.filter(
id=votacao.materia.id).first()
dic_votacao = {}
dic_votacao["tipo_materia"] = materia.tipo.sigla + ' - ' + materia.tipo.descricao
dic_votacao["tipo_materia"] = materia.tipo.sigla + \
' - ' + materia.tipo.descricao
dic_votacao["num_ordem"] = votacao.numero_ordem
dic_votacao["id_materia"] = str(
materia.numero) + "/" + str(materia.ano)
@ -1124,7 +1127,7 @@ def get_pauta_sessao(sessao, casa):
numeracao = Numeracao.objects.filter(materia=votacao.materia).first()
if numeracao:
dic_votacao["des_numeracao"] = str(
numeracao.numero_materia) + '/' + str(numeracao.ano_materia)
numeracao.numero_materia) + '/' + str(numeracao.ano_materia)
turno, tramitacao = get_turno(materia)
dic_votacao["des_turno"] = turno

1
sapl/static/js/app.js

@ -47,6 +47,7 @@ function refreshMask() {
$('.dateinput').mask('00/00/0000', {placeholder:"__/__/____"});
$('.hora').mask("00:00", {placeholder:"hh:mm"});
$('.hora_hms').mask("00:00:00", {placeholder:"hh:mm:ss"});
$('.timeinput').mask("00:00:00", {placeholder:"hh:mm:ss"});
$('.cronometro').mask("00:00:00", {placeholder:"hh:mm:ss"});
}

6
sapl/templates/protocoloadm/comprovante.html

@ -65,7 +65,11 @@
</tr>
<tr>
<th>Data / Horário</th>
<td>{{ protocolo.timestamp|date:"d/m/Y" }} - {{ protocolo.timestamp|date:"H:i:s" }}</td>
{% if protocolo.timestamp %}
<td>{{ protocolo.timestamp|date:"d/m/Y" }} - {{ protocolo.timestamp|date:"H:i:s" }}</td>
{% else %}
<td>{{ protocolo.data|date:"d/m/Y" }} - {{ protocolo.hora|date:"H:i:s" }}</td>
{% endif %}
</tr>
{% if protocolo.tipo_processo == 1 %}
<tr>

14
sapl/templates/protocoloadm/protocolar_documento.html

@ -14,3 +14,17 @@
{% block detail_content %}
{% crispy form %}
{% endblock detail_content %}
{% block extra_js %}
<script language="Javascript">
$(document).ready(function() {
$("input[name=data_hora_manual]").change(function(event) {
if (this.value === 'True' && this.checked)
$("#protocolo_data_hora_manual").removeClass('hidden');
else if (this.value === 'False' && this.checked)
$("#protocolo_data_hora_manual").addClass('hidden');
});
$("input[name=data_hora_manual]").trigger('change')
});
</script>
{% endblock %}

62
sapl/templates/protocoloadm/protocolar_materia.html

@ -26,35 +26,43 @@
}
$(document).ready(function() {
function busca_ementa() {
var vincular_materia = $("#id_vincular_materia_1").prop("checked");
var ano_materia = $("#id_ano_materia").val();
var numero_materia = $("#id_numero_materia").val();
var tipo_materia = $("#id_tipo_materia").val();
var json_data = {
ano : ano_materia,
numero : numero_materia,
tipo : tipo_materia
}
if (vincular_materia === true && ano_materia !== undefined &&
numero_materia !== undefined && numero_materia !== "") {
$.getJSON("/protocoloadm/recuperar-materia", json_data, function(data){
if (data) {
if (data['error'] === undefined){
$('#id_assunto_ementa').val(data['ementa']);
if (data['autor'] !== undefined) {
$('#id_autor').val(data['autor']);
$('#id_tipo_autor').val(data['tipo_autor']);
$("input[name=data_hora_manual]").change(function(event) {
if (this.value === 'True' && this.checked)
$("#protocolo_data_hora_manual").removeClass('hidden');
else if (this.value === 'False' && this.checked)
$("#protocolo_data_hora_manual").addClass('hidden');
});
$("input[name=data_hora_manual]").trigger('change')
function busca_ementa() {
var vincular_materia = $("#id_vincular_materia_1").prop("checked");
var ano_materia = $("#id_ano_materia").val();
var numero_materia = $("#id_numero_materia").val();
var tipo_materia = $("#id_tipo_materia").val();
var json_data = {
ano : ano_materia,
numero : numero_materia,
tipo : tipo_materia
}
if (vincular_materia === true && ano_materia !== undefined &&
numero_materia !== undefined && numero_materia !== "") {
$.getJSON("/protocoloadm/recuperar-materia", json_data, function(data){
if (data) {
if (data['error'] === undefined){
$('#id_assunto_ementa').val(data['ementa']);
if (data['autor'] !== undefined) {
$('#id_autor').val(data['autor']);
$('#id_tipo_autor').val(data['tipo_autor']);
}
}
}
})
}
}
}
}
})
}
};
$("#id_ano_materia").blur(busca_ementa);
$("#id_numero_materia").blur(busca_ementa);
$("#id_tipo_materia").change(busca_ementa);
$("#id_ano_materia").blur(busca_ementa);
$("#id_numero_materia").blur(busca_ementa);
$("#id_tipo_materia").change(busca_ementa);
$("#id_tipo_autor").change(function() {
var tipo_selecionado = $("#id_tipo_autor").val();

10
sapl/templates/protocoloadm/protocolo_mostrar.html

@ -4,6 +4,14 @@
{% load crispy_forms_tags %}
{% load static %}
{% block actions %}
{{ block.super }}
<div class="actions btn-group pull-right grid-gutter-width-right " role="group">
<a href="{% url 'sapl.protocoloadm:protocolo' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div>
{% endblock %}
{% block detail_content %}
<strong>Protocolo: </strong>{{ protocolo.numero|stringformat:'06d' }}/{{ protocolo.ano }} -
<a href="{% url 'sapl.relatorios:relatorio_etiqueta_protocolo' protocolo.numero protocolo.ano %}"><img src="{% static 'img/etiqueta.png' %}" alt="Etiqueta Individual"></a></br>
@ -12,7 +20,7 @@
{% if protocolo.timestamp %}
<strong>Data Protocolo:</strong> {{ protocolo.timestamp|localtime|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ protocolo.timestamp|localtime|date:"G:i:s" }}</br>
{% else %}
<strong>Data Protocolo:</strong> {{ protocolo.data|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ protocolo.hora|date:"G:i:s" }}</br>
<strong>Data Protocolo:</strong> {{ protocolo.data|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ protocolo.hora|date:"G:i:s" }} - {% if not protocolo.timestamp %} Informado Manualmente por: {{protocolo.user_data_hora_manual}}{% endif %}</br>
{% endif %}
{% if protocolo.tipo_processo == 0 %}

18
sapl/utils.py

@ -18,6 +18,7 @@ from django.core.exceptions import ValidationError
from django.core.mail import get_connection
from django.db import models
from django.db.models import Q
from django.forms.widgets import SplitDateTimeWidget
from django.utils import six, timezone
from django.utils.translation import ugettext_lazy as _
import django_filters
@ -234,6 +235,23 @@ class RangeWidgetOverride(forms.MultiWidget):
return '<div class="row">%s</div>' % html
class CustomSplitDateTimeWidget(SplitDateTimeWidget):
def render(self, name, value, attrs=None, renderer=None):
rendered_widgets = []
for i, x in enumerate(self.widgets):
x.attrs['class'] += ' form-control'
rendered_widgets.append(
x.render(
'%s_%d' % (name, i), self.decompress(
value)[i] if value else ''
)
)
html = '<div class="col-6">%s</div><div class="col-6">%s</div>'\
% tuple(rendered_widgets)
return '<div class="row">%s</div>' % html
def register_all_models_in_admin(module_name, exclude_list=[]):
appname = module_name.split('.')
appname = appname[1] if appname[0] == 'sapl' else appname[0]

Loading…
Cancel
Save