From ac91543b0fd0a32f3f30ec881e9052d1ce9cfa58 Mon Sep 17 00:00:00 2001 From: Leandro Roberto da Silva Date: Thu, 10 Jan 2019 20:45:58 -0200 Subject: [PATCH] Fix #2337 (#2448) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * impl data e hora manual no protocolo de matérias * impl data e hora manual no protocolo de documentos * ajustes de teste em protocoloadm --- sapl/protocoloadm/forms.py | 155 +++++++++++++----- .../migrations/0014_auto_20190110_1300.py | 35 ++++ ...15_protocolo_timestamp_data_hora_manual.py | 21 +++ .../migrations/0016_auto_20190110_1345.py | 21 +++ sapl/protocoloadm/models.py | 24 ++- sapl/protocoloadm/tests/test_protocoloadm.py | 23 ++- sapl/protocoloadm/views.py | 41 ++++- sapl/relatorios/views.py | 35 ++-- sapl/static/js/app.js | 1 + sapl/templates/protocoloadm/comprovante.html | 6 +- .../protocoloadm/protocolar_documento.html | 14 ++ .../protocoloadm/protocolar_materia.html | 62 ++++--- .../protocoloadm/protocolo_mostrar.html | 10 +- sapl/utils.py | 18 ++ 14 files changed, 369 insertions(+), 97 deletions(-) create mode 100644 sapl/protocoloadm/migrations/0014_auto_20190110_1300.py create mode 100644 sapl/protocoloadm/migrations/0015_protocolo_timestamp_data_hora_manual.py create mode 100644 sapl/protocoloadm/migrations/0016_auto_20190110_1345.py diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index d0c812958..8f476d443 100644 --- a/sapl/protocoloadm/forms.py +++ b/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: {} - {}
+ IP: {} - {}
+ + """.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(" "), - ), + css_id='protocolo_data_hora_manual', + css_class='hidden'), + row4, + row5, + HTML(" "), Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece ' 'a partir do número a ser informado)'), - row6, + row7, HTML(" "), 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: {} - {}
+ IP: {} - {}
+ + """.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(" "), - ), + css_id='protocolo_data_hora_manual', + css_class='hidden'), + row4, + row5, + HTML(" "), Fieldset(_('Número do Protocolo (Apenas se quiser que a numeração comece' ' a partir do número a ser informado)'), - row5, + row6, HTML(" "), 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, diff --git a/sapl/protocoloadm/migrations/0014_auto_20190110_1300.py b/sapl/protocoloadm/migrations/0014_auto_20190110_1300.py new file mode 100644 index 000000000..56cdf8d36 --- /dev/null +++ b/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'), + ), + ] diff --git a/sapl/protocoloadm/migrations/0015_protocolo_timestamp_data_hora_manual.py b/sapl/protocoloadm/migrations/0015_protocolo_timestamp_data_hora_manual.py new file mode 100644 index 000000000..85554edad --- /dev/null +++ b/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), + ), + ] diff --git a/sapl/protocoloadm/migrations/0016_auto_20190110_1345.py b/sapl/protocoloadm/migrations/0016_auto_20190110_1345.py new file mode 100644 index 000000000..71f2b7f7a --- /dev/null +++ b/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), + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 6d3d90671..e335a5db1 100644 --- a/sapl/protocoloadm/models.py +++ b/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() diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index 2a4c9f53c..c7e4bc341 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/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 diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 8dd7e9e47..f91ee5227 100755 --- a/sapl/protocoloadm/views.py +++ b/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') \ No newline at end of file + 'materia/impressos/ficha_adm_pdf.html') diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 0c5dfd377..f4bc8cda2 100755 --- a/sapl/relatorios/views.py +++ b/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, '', 6, 6, - 'expedientes', '') 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") + ' - Horário:' \ - + 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'] = 'Data: ' + tz_hora.strftime( "%d/%m/%Y") + ' - Horário: ' + 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 diff --git a/sapl/static/js/app.js b/sapl/static/js/app.js index 48777c0e3..d3616a8b5 100644 --- a/sapl/static/js/app.js +++ b/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"}); } diff --git a/sapl/templates/protocoloadm/comprovante.html b/sapl/templates/protocoloadm/comprovante.html index d285b4e4f..23d299ecf 100644 --- a/sapl/templates/protocoloadm/comprovante.html +++ b/sapl/templates/protocoloadm/comprovante.html @@ -65,7 +65,11 @@ Data / Horário - {{ protocolo.timestamp|date:"d/m/Y" }} - {{ protocolo.timestamp|date:"H:i:s" }} + {% if protocolo.timestamp %} + {{ protocolo.timestamp|date:"d/m/Y" }} - {{ protocolo.timestamp|date:"H:i:s" }} + {% else %} + {{ protocolo.data|date:"d/m/Y" }} - {{ protocolo.hora|date:"H:i:s" }} + {% endif %} {% if protocolo.tipo_processo == 1 %} diff --git a/sapl/templates/protocoloadm/protocolar_documento.html b/sapl/templates/protocoloadm/protocolar_documento.html index 5cb1fa789..49cf4933f 100644 --- a/sapl/templates/protocoloadm/protocolar_documento.html +++ b/sapl/templates/protocoloadm/protocolar_documento.html @@ -14,3 +14,17 @@ {% block detail_content %} {% crispy form %} {% endblock detail_content %} + +{% block extra_js %} + +{% endblock %} diff --git a/sapl/templates/protocoloadm/protocolar_materia.html b/sapl/templates/protocoloadm/protocolar_materia.html index db3785bd6..2dcb8b4f0 100644 --- a/sapl/templates/protocoloadm/protocolar_materia.html +++ b/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(); diff --git a/sapl/templates/protocoloadm/protocolo_mostrar.html b/sapl/templates/protocoloadm/protocolo_mostrar.html index 2cac987f3..d22464397 100644 --- a/sapl/templates/protocoloadm/protocolo_mostrar.html +++ b/sapl/templates/protocoloadm/protocolo_mostrar.html @@ -4,6 +4,14 @@ {% load crispy_forms_tags %} {% load static %} +{% block actions %} + + {{ block.super }} + +{% endblock %} + {% block detail_content %} Protocolo: {{ protocolo.numero|stringformat:'06d' }}/{{ protocolo.ano }} - Etiqueta Individual
@@ -12,7 +20,7 @@ {% if protocolo.timestamp %} Data Protocolo: {{ protocolo.timestamp|localtime|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ protocolo.timestamp|localtime|date:"G:i:s" }}
{% else %} - Data Protocolo: {{ protocolo.data|date:"d/m/Y"|default_if_none:"Não informado" }} - Horário: {{ protocolo.hora|date:"G:i:s" }}
+ Data Protocolo: {{ 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 %}
{% endif %} {% if protocolo.tipo_processo == 0 %} diff --git a/sapl/utils.py b/sapl/utils.py index 706d5cb65..eb26cadb1 100644 --- a/sapl/utils.py +++ b/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 '
%s
' % 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 = '
%s
%s
'\ + % tuple(rendered_widgets) + return '
%s
' % 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]