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. 137
      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. 39
      sapl/protocoloadm/views.py
  8. 27
      sapl/relatorios/views.py
  9. 1
      sapl/static/js/app.js
  10. 4
      sapl/templates/protocoloadm/comprovante.html
  11. 14
      sapl/templates/protocoloadm/protocolar_documento.html
  12. 8
      sapl/templates/protocoloadm/protocolar_materia.html
  13. 10
      sapl/templates/protocoloadm/protocolo_mostrar.html
  14. 18
      sapl/utils.py

137
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,
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,7 +454,8 @@ class ProtocoloMateriaForm(ModelForm):
ano_materia = forms.CharField(
label=_('Ano matéria'), required=False)
vincular_materia = forms.ChoiceField(label=_('Vincular a matéria existente?'),
vincular_materia = forms.ChoiceField(
label=_('Vincular a matéria existente?'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
@ -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,
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,14 +926,14 @@ 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,
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):
@ -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

39
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':

27
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:
@ -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,7 +829,6 @@ 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,
@ -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)

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"});
}

4
sapl/templates/protocoloadm/comprovante.html

@ -65,7 +65,11 @@
</tr>
<tr>
<th>Data / Horário</th>
{% 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 %}

8
sapl/templates/protocoloadm/protocolar_materia.html

@ -26,6 +26,14 @@
}
$(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')
function busca_ementa() {
var vincular_materia = $("#id_vincular_materia_1").prop("checked");
var ano_materia = $("#id_ano_materia").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