diff --git a/Dockerfile b/Dockerfile index 9f89509d7..8fd83756b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,8 @@ ENV BUILD_PACKAGES postgresql-dev graphviz-dev graphviz build-base git pkgconfig python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev nodejs py3-lxml \ py3-magic postgresql-client poppler-utils antiword vim +RUN apk update && apk upgrade + RUN apk --update add fontconfig ttf-dejavu && fc-cache -fv RUN apk add --no-cache python3 nginx tzdata && \ diff --git a/create_admin.py b/create_admin.py index f03bbd7c8..e67c8afd4 100755 --- a/create_admin.py +++ b/create_admin.py @@ -7,24 +7,43 @@ import django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sapl.settings") +def get_enviroment_admin_password(username): + password = os.environ.get('ADMIN_PASSWORD') + if not password: + print( + "[SUPERUSER] Environment variable $ADMIN_PASSWORD" + " for user %s was not set. Leaving..." % username) + sys.exit('MISSING_ADMIN_PASSWORD') + + +def create_user_interlegis(): + from django.contrib.auth.models import User + + password = get_enviroment_admin_password('interlegis') + print("[SUPERUSER INTERLEGIS] Creating interlegis superuser...") + user, created = User.objects.get_or_create(username='interlegis') + if not created: + print("[SUPERUSER INTERLEGIS] User interlegis already exists." + " Updating password.") + user.is_superuser = True + user.is_staff = True + user.set_password(password) + user.save() + print("[SUPERUSER INTERLEGIS] Done.") + + def create_superuser(): from django.contrib.auth.models import User username = "admin" - password = os.environ[ - 'ADMIN_PASSWORD'] if 'ADMIN_PASSWORD' in os.environ else None - email = os.environ['ADMIN_EMAIL'] if 'ADMIN_EMAIL' in os.environ else '' + email = os.environ.get('ADMIN_EMAIL', '') if User.objects.filter(username=username).exists(): print("[SUPERUSER] User %s already exists." " Exiting without change." % username) sys.exit('ADMIN_USER_EXISTS') else: - if not password: - print( - "[SUPERUSER] Environment variable $ADMIN_PASSWORD" - " for user %s was not set. Leaving..." % username) - sys.exit('MISSING_ADMIN_PASSWORD') + password = get_enviroment_admin_password(username) print("[SUPERUSER] Creating superuser...") @@ -39,4 +58,5 @@ def create_superuser(): if __name__ == '__main__': django.setup() + create_user_interlegis() # must come before create_superuser create_superuser() diff --git a/docker-compose.yml b/docker-compose.yml index df1b25454..0f7694ede 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.107 + image: interlegis/sapl:3.1.110 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/sapl/audiencia/views.py b/sapl/audiencia/views.py index bdfc6993c..c999cf4ff 100644 --- a/sapl/audiencia/views.py +++ b/sapl/audiencia/views.py @@ -34,9 +34,10 @@ class AudienciaCrud(Crud): def get_initial(self): initial = super(UpdateView, self).get_initial() - initial['tipo_materia'] = self.object.materia.tipo.id - initial['numero_materia'] = self.object.materia.numero - initial['ano_materia'] = self.object.materia.ano + if self.object.materia: + initial['tipo_materia'] = self.object.materia.tipo.id + initial['numero_materia'] = self.object.materia.numero + initial['ano_materia'] = self.object.materia.ano return initial class DeleteView(Crud.DeleteView): diff --git a/sapl/base/migrations/0020_auto_20180821_1421.py b/sapl/base/migrations/0020_auto_20180821_1421.py new file mode 100644 index 000000000..90e77181d --- /dev/null +++ b/sapl/base/migrations/0020_auto_20180821_1421.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-08-21 17:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0019_auto_20180815_1025'), + ] + + operations = [ + migrations.AlterField( + model_name='appconfig', + name='documentos_administrativos', + field=models.CharField(choices=[('O', 'Ostensiva'), ('R', 'Restritiva')], default='O', max_length=1, verbose_name='Visibilidade dos Documentos Administrativos'), + ), + ] diff --git a/sapl/base/models.py b/sapl/base/models.py index df8ae7c3f..6e3d2ee67 100644 --- a/sapl/base/models.py +++ b/sapl/base/models.py @@ -9,8 +9,8 @@ from django.utils.translation import ugettext_lazy as _ from sapl.utils import (LISTA_DE_UFS, YES_NO_CHOICES, get_settings_auth_user_model, models_with_gr_for_model) -TIPO_DOCUMENTO_ADMINISTRATIVO = (('O', _('Ostensivo')), - ('R', _('Restritivo'))) +TIPO_DOCUMENTO_ADMINISTRATIVO = (('O', _('Ostensiva')), + ('R', _('Restritiva'))) SEQUENCIA_NUMERACAO = (('A', _('Sequencial por ano')), ('L', _('Sequencial por legislatura')), @@ -70,7 +70,7 @@ class AppConfig(models.Model): documentos_administrativos = models.CharField( max_length=1, - verbose_name=_('Ostensivo/Restritivo'), + verbose_name=_('Visibilidade dos Documentos Administrativos'), choices=TIPO_DOCUMENTO_ADMINISTRATIVO, default='O') sequencia_numeracao = models.CharField( diff --git a/sapl/comissoes/forms.py b/sapl/comissoes/forms.py index fc81b3510..0353e7734 100644 --- a/sapl/comissoes/forms.py +++ b/sapl/comissoes/forms.py @@ -45,6 +45,7 @@ class ComposicaoForm(forms.ModelForm): return cleaned_data + class PeriodoForm(forms.ModelForm): class Meta: @@ -63,9 +64,20 @@ class PeriodoForm(forms.ModelForm): if data_fim and data_fim < data_inicio: raise ValidationError('A Data Final não pode ser menor que ' 'a Data Inicial') + + legislatura = Legislatura.objects.filter(data_inicio__lte=data_inicio, + data_fim__gte=data_fim) + + if not legislatura: + raise ValidationError('O período informado ' + 'deve estar contido em uma única ' + 'legislatura existente') + + return cleaned_data + class ParticipacaoCreateForm(forms.ModelForm): parent_pk = forms.CharField(required=False) # widget=forms.HiddenInput()) @@ -245,11 +257,36 @@ class ComissaoForm(forms.ModelForm): if len(self.cleaned_data['nome']) > 100: msg = _('Nome da Comissão deve ter no máximo 50 caracteres.') raise ValidationError(msg) - if self.cleaned_data['data_extincao']: - if (self.cleaned_data['data_extincao'] < - self.cleaned_data['data_criacao']): + if (self.cleaned_data['data_extincao'] and + self.cleaned_data['data_extincao'] < + self.cleaned_data['data_criacao']): msg = _('Data de extinção não pode ser menor que a de criação') raise ValidationError(msg) + if (self.cleaned_data['data_final_prevista_temp'] and + self.cleaned_data['data_final_prevista_temp'] < + self.cleaned_data['data_criacao']): + msg = _('Data Prevista para Término não pode ser menor que a de criação') + raise ValidationError(msg) + if (self.cleaned_data['data_prorrogada_temp'] and + self.cleaned_data['data_prorrogada_temp'] < + self.cleaned_data['data_criacao']): + msg = _('Data Novo Prazo não pode ser menor que a de criação') + raise ValidationError(msg) + if (self.cleaned_data['data_instalacao_temp'] and + self.cleaned_data['data_instalacao_temp'] < + self.cleaned_data['data_criacao']): + msg = _('Data de Instalação não pode ser menor que a de criação') + raise ValidationError(msg) + if (self.cleaned_data['data_final_prevista_temp'] and self.cleaned_data['data_instalacao_temp'] and + self.cleaned_data['data_final_prevista_temp'] < + self.cleaned_data['data_instalacao_temp']): + msg = _('Data Prevista para Término não pode ser menor que a de Instalação') + raise ValidationError(msg) + if (self.cleaned_data['data_prorrogada_temp'] and self.cleaned_data['data_instalacao_temp'] and + self.cleaned_data['data_prorrogada_temp'] < + self.cleaned_data['data_instalacao_temp']): + msg = _('Data Novo Prazo não pode ser menor que a de Instalação') + raise ValidationError(msg) return self.cleaned_data @transaction.atomic diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index 28b963038..ff6cbdab1 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -237,7 +237,10 @@ class TextoArticulado(TimestampedMixin): def __str__(self): if self.content_object: - return str(self.content_object) + assert hasattr(self.content_object, 'epigrafe'), _( + 'Modelos integrados aos Textos Articulados devem possuir a ' + 'property "epigrafe"') + return str(self.content_object.epigrafe) else: return _('%(tipo)s nº %(numero)s de %(data)s') % { 'tipo': self.tipo_ta, diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index dac910cc2..a9ebf3fa4 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -137,6 +137,7 @@ class IntegracaoTaView(TemplateView): 'observacao': 'observacao', 'numero': 'numero', 'ano': 'ano', + 'tipo': 'tipo', } Caso o model de integração não possua um dos campos, @@ -562,7 +563,7 @@ class TaDetailView(CompMixin, DetailView): 'Metadados para o Texto Articulado de %s\n' '%s') % ( self.get_object().content_object._meta.verbose_name_plural, - self.get_object().content_object) + self.get_object().content_object.epigrafe) else: return self.get_object() diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 88db58f8b..ff9b12d56 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -123,13 +123,14 @@ class MateriaSimplificadaForm(ModelForm): model = MateriaLegislativa fields = ['tipo', 'numero', 'ano', 'data_apresentacao', 'numero_protocolo', 'regime_tramitacao', - 'em_tramitacao', 'ementa', 'texto_original'] + 'em_tramitacao', 'ementa', 'tipo_apresentacao', + 'texto_original'] def __init__(self, *args, **kwargs): row1 = to_row([('tipo', 6), ('numero', 3), ('ano', 3)]) row2 = to_row([('data_apresentacao', 6), ('numero_protocolo', 6)]) - row3 = to_row([('regime_tramitacao', 6), ('em_tramitacao', 6)]) + row3 = to_row([('regime_tramitacao', 6), ('em_tramitacao', 3), ('tipo_apresentacao', 3)]) row4 = to_row([('ementa', 12)]) row5 = to_row([('texto_original', 12)]) diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 606fabbd7..82aea25dd 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1,14 +1,15 @@ -import reversion from django.contrib.auth.models import Group from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.db.models.functions import Concat +from django.template import defaultfilters from django.utils import formats, timezone from django.utils.translation import ugettext_lazy as _ from model_utils import Choices +import reversion from sapl.base.models import SEQUENCIA_NUMERACAO, Autor from sapl.comissoes.models import Comissao @@ -19,6 +20,7 @@ from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, SaplGenericForeignKey, SaplGenericRelation, restringe_tipos_de_arquivo_txt, texto_upload_path) + EM_TRAMITACAO = [(1, 'Sim'), (0, 'Não')] @@ -242,6 +244,16 @@ class MateriaLegislativa(models.Model): return _('%(tipo)s nº %(numero)s de %(ano)s') % { 'tipo': self.tipo, 'numero': self.numero, 'ano': self.ano} + @property + def epigrafe(self): + return _('%(tipo)s nº %(numero)s de %(data)s') % { + 'tipo': self.tipo, + 'numero': self.numero, + 'data': defaultfilters.date( + self.data_apresentacao, + "d \d\e F \d\e Y" + )} + def data_entrada_protocolo(self): ''' hack: recuperar a data de entrada do protocolo sem gerar @@ -425,7 +437,8 @@ class DocumentoAcessorio(models.Model): verbose_name=_('Tipo')) nome = models.CharField(max_length=50, verbose_name=_('Nome')) - data = models.DateField(blank=True, null=True, default=None, verbose_name=_('Data')) + data = models.DateField(blank=True, null=True, + default=None, verbose_name=_('Data')) autor = models.CharField( max_length=50, blank=True, verbose_name=_('Autor')) ementa = models.TextField(blank=True, verbose_name=_('Ementa')) @@ -756,6 +769,16 @@ class Proposicao(models.Model): self.id, descricao) + @property + def epigrafe(self): + return _('%(tipo)s nº %(numero)s de %(data)s') % { + 'tipo': self.tipo, + 'numero': self.numero, + 'data': defaultfilters.date( + self.data_envio if self.data_envio else timezone.now(), + "d \d\e F \d\e Y" + )} + def delete(self, using=None, keep_parents=False): if self.texto_original: self.texto_original.delete() diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py index f2c89c908..cfbfff591 100644 --- a/sapl/materia/urls.py +++ b/sapl/materia/urls.py @@ -24,7 +24,7 @@ from sapl.materia.views import (AcompanhamentoConfirmarView, TipoProposicaoCrud, TramitacaoCrud, TramitacaoEmLoteView, UnidadeTramitacaoCrud, proposicao_texto, recuperar_materia, - ExcluirTramitacaoEmLoteView) + ExcluirTramitacaoEmLoteView, RetornarProposicao) from sapl.norma.views import NormaPesquisaSimplesView from .apps import AppConfig @@ -120,6 +120,8 @@ urlpatterns_proposicao = [ url(r'^proposicao/texto/(?P\d+)$', proposicao_texto, name='proposicao_texto'), + url(r'^proposicao/(?P\d+)/retornar', RetornarProposicao.as_view(), + name='retornar-proposicao'), ] urlpatterns_sistema = [ diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 5f1b81ccf..da147dfaf 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -2,7 +2,6 @@ from datetime import datetime from random import choice from string import ascii_letters, digits -import weasyprint from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML from django.contrib import messages @@ -17,10 +16,11 @@ from django.shortcuts import get_object_or_404, redirect from django.template import RequestContext, loader from django.utils import formats, timezone from django.utils.translation import ugettext_lazy as _ -from django.views.generic import FormView, ListView, TemplateView, CreateView, UpdateView +from django.views.generic import ListView, TemplateView, CreateView, UpdateView from django.views.generic.base import RedirectView from django.views.generic.edit import FormView from django_filters.views import FilterView +import weasyprint import sapl from sapl.base.models import Autor, CasaLegislativa @@ -67,6 +67,7 @@ from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria, TipoProposicao, Tramitacao, UnidadeTramitacao) from .signals import tramitacao_signal + AssuntoMateriaCrud = CrudAux.build(AssuntoMateria, 'assunto_materia') OrigemCrud = CrudAux.build(Origem, '') @@ -96,9 +97,10 @@ def proposicao_texto(request, pk): if proposicao.texto_original: if (not proposicao.data_recebimento and proposicao.autor.user_id != request.user.id): - messages.error(request, _('Você não tem permissão para acessar o texto original.')) + messages.error(request, _( + 'Você não tem permissão para acessar o texto original.')) return redirect(reverse('sapl.materia:proposicao_detail', - kwargs={'pk':pk})) + kwargs={'pk': pk})) arquivo = proposicao.texto_original @@ -221,6 +223,7 @@ class MateriaTaView(IntegracaoTaView): 'observacao': None, 'numero': 'numero', 'ano': 'ano', + 'tipo': 'tipo', } map_funcs = { 'publicacao_func': False, @@ -251,6 +254,7 @@ class ProposicaoTaView(IntegracaoTaView): 'observacao': None, 'numero': 'numero_proposicao', 'ano': 'ano', + 'tipo': 'tipo', } map_funcs = { 'publicacao_func': False @@ -509,6 +513,31 @@ class ReceberProposicao(PermissionRequiredForAppCrudMixin, FormView): return context +class RetornarProposicao(UpdateView): + app_label = sapl.protocoloadm.apps.AppConfig.label + template_name = "materia/proposicao_confirm_return.html" + model = Proposicao + fields = ['data_envio', 'descricao' ] + permission_required = ('materia.detail_proposicao_enviada', ) + + def dispatch(self, request, *args, **kwargs): + + try: + p = Proposicao.objects.get(id=kwargs['pk']) + except: + raise Http404() + + if p.autor.user != request.user: + messages.error( + request, + 'Usuário sem acesso a esta opção.' % + request.user) + return redirect('/') + + return super(RetornarProposicao, self).dispatch( + request, *args, **kwargs) + + class ConfirmarProposicao(PermissionRequiredForAppCrudMixin, UpdateView): app_label = sapl.protocoloadm.apps.AppConfig.label template_name = "materia/confirmar_proposicao.html" @@ -994,7 +1023,8 @@ class RelatoriaCrud(MasterDetailCrud): except ObjectDoesNotExist: pass else: - composicao = comissao.composicao_set.last() + composicao = comissao.composicao_set.order_by( + '-periodo__data_inicio').first() participacao = Participacao.objects.filter( composicao=composicao) @@ -1034,7 +1064,7 @@ class TramitacaoCrud(MasterDetailCrud): if local: initial['unidade_tramitacao_local' - ] = local.unidade_tramitacao_destino.pk + ] = local.unidade_tramitacao_destino.pk else: initial['unidade_tramitacao_local'] = '' initial['data_tramitacao'] = timezone.now().date() @@ -2035,10 +2065,13 @@ class ExcluirTramitacaoEmLoteView(PermissionRequiredMixin, FormView): def form_valid(self, form): - tramitacao_set = Tramitacao.objects.filter(data_tramitacao=form.cleaned_data['data_tramitacao'], - unidade_tramitacao_local=form.cleaned_data['unidade_tramitacao_local'], - unidade_tramitacao_destino=form.cleaned_data['unidade_tramitacao_destino'], - status=form.cleaned_data['status']) + tramitacao_set = Tramitacao.objects.filter( + data_tramitacao=form.cleaned_data['data_tramitacao'], + unidade_tramitacao_local=form.cleaned_data[ + 'unidade_tramitacao_local'], + unidade_tramitacao_destino=form.cleaned_data[ + 'unidade_tramitacao_destino'], + status=form.cleaned_data['status']) for tramitacao in tramitacao_set: materia = tramitacao.materia if tramitacao == materia.tramitacao_set.last(): diff --git a/sapl/norma/models.py b/sapl/norma/models.py index ff7b44dca..c011b174e 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -1,9 +1,9 @@ -import reversion from django.contrib.contenttypes.fields import GenericRelation from django.db import models from django.template import defaultfilters from django.utils.translation import ugettext_lazy as _ from model_utils import Choices +import reversion from sapl.compilacao.models import TextoArticulado from sapl.materia.models import MateriaLegislativa @@ -146,12 +146,18 @@ class NormaJuridica(models.Model): norma=self.id) return anexos - def __str__(self): return _('nº %(numero)s de %(data)s') % { 'numero': self.numero, 'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")} + @property + def epigrafe(self): + return _('%(tipo)s nº %(numero)s de %(data)s') % { + 'tipo': self.tipo, + 'numero': self.numero, + 'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")} + def delete(self, using=None, keep_parents=False): if self.texto_integral: self.texto_integral.delete() diff --git a/sapl/norma/views.py b/sapl/norma/views.py index 87b842802..80c30a63d 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -1,6 +1,6 @@ import re -import weasyprint + from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse @@ -12,6 +12,7 @@ from django.views.generic import TemplateView, UpdateView from django.views.generic.base import RedirectView from django.views.generic.edit import FormView from django_filters.views import FilterView +import weasyprint from sapl.base.models import AppConfig from sapl.compilacao.views import IntegracaoTaView @@ -24,6 +25,7 @@ from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, TipoNormaJuridica, TipoVinculoNormaJuridica) + # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') AssuntoNormaCrud = CrudAux.build(AssuntoNorma, 'assunto_norma_juridica', list_field_names=['assunto', 'descricao']) @@ -72,7 +74,10 @@ class NormaPesquisaView(FilterView): def get_queryset(self): qs = super().get_queryset() - qs = qs.extra({'norma_i': "CAST(regexp_replace(numero,'[^0-9]','', 'g') AS INTEGER)", 'norma_letra': "regexp_replace(numero,'[^a-zA-Z]','', 'g')"}).order_by('-data', '-norma_i', '-norma_letra') + qs = qs.extra({ + 'nm_i': "CAST(regexp_replace(numero,'[^0-9]','', 'g') AS INTEGER)", + 'norma_letra': "regexp_replace(numero,'[^a-zA-Z]','', 'g')" + }).order_by('-data', '-nm_i', '-norma_letra') return qs @@ -98,6 +103,7 @@ class NormaPesquisaView(FilterView): return context + class AnexoNormaJuridicaCrud(MasterDetailCrud): model = AnexoNormaJuridica parent_field = 'norma' @@ -105,7 +111,7 @@ class AnexoNormaJuridicaCrud(MasterDetailCrud): public = [RP_LIST, RP_DETAIL] class BaseMixin(MasterDetailCrud.BaseMixin): - list_field_names = ['id','anexo_arquivo'] + list_field_names = ['id', 'anexo_arquivo'] class CreateView(MasterDetailCrud.CreateView): form_class = AnexoNormaJuridicaForm @@ -141,6 +147,7 @@ class NormaTaView(IntegracaoTaView): 'observacao': 'observacao', 'numero': 'numero', 'ano': 'ano', + 'tipo': 'tipo', } map_funcs = { @@ -238,7 +245,7 @@ def recuperar_numero_norma(request): param = {'tipo': tipo} param['ano'] = ano if ano else timezone.now().year norma = NormaJuridica.objects.filter(**param).order_by( - 'tipo', 'ano', 'numero').values_list('numero', 'ano').last() + 'tipo', 'ano', 'numero').values_list('numero', 'ano').last() if norma: response = JsonResponse({'numero': int(re.sub("[^0-9].*", '', norma[0])) + 1, 'ano': norma[1]}) diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index cf7616d7a..33ceade8c 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -55,6 +55,8 @@ class Protocolo(models.Model): null=False, choices=RANGE_ANOS, verbose_name=_('Ano do Protocolo')) + # TODO: Remover esses dois campos após migração, + # TODO: pois timestamp supre a necessidade data = models.DateField() hora = models.TimeField() # TODO transformar campo timestamp em auto_now_add diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index 223c38014..8ed9216f2 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -12,6 +12,7 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView, ProtocoloMostrarView, ProtocoloPesquisaView, StatusTramitacaoAdministrativoCrud, + recuperar_materia_protocolo, TipoDocumentoAdministrativoCrud, TramitacaoAdmCrud, atualizar_numero_documento, @@ -77,6 +78,8 @@ urlpatterns_protocolo = [ url(r'^protocoloadm/atualizar_numero_documento$', atualizar_numero_documento, name='atualizar_numero_documento'), + url(r'^protocoloadm/recuperar-materia', + recuperar_materia_protocolo, name='recuperar_materia_protocolo'), ] diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 67d43fe51..4e4063ba6 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -1,6 +1,7 @@ from braces.views import FormValidMessageMixin from django.contrib import messages +from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist @@ -45,6 +46,24 @@ TipoDocumentoAdministrativoCrud = CrudAux.build( # FIXME precisa de uma chave diferente para o layout # ProtocoloMateriaCrud = Crud.build(Protocolo, '') +@permission_required('protocoloadm.add_protocolo') +def recuperar_materia_protocolo(request): + tipo = request.GET.get('tipo') + ano = request.GET.get('ano') + numero = request.GET.get('numero') + try: + materia = MateriaLegislativa.objects.get( + tipo=tipo, ano=ano,numero=numero) + autoria = materia.autoria_set.first() + content = {'ementa': materia.ementa.strip(), + 'ano':materia.ano, 'numero':materia.numero} + if autoria: + content.update({'autor': autoria.autor.pk, + 'tipo_autor':autoria.autor.tipo.pk}) + response = JsonResponse(content) + except Exception as e: + response = JsonResponse({'error':e}) + return response def doc_texto_integral(request, pk): can_see = True @@ -782,4 +801,4 @@ class DesvincularMateriaView(PermissionRequiredMixin, FormView): tipo=form.cleaned_data['tipo']) materia.numero_protocolo = None materia.save() - return redirect(self.get_success_url()) \ No newline at end of file + return redirect(self.get_success_url()) diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 28d6010e4..57752753e 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -826,9 +826,10 @@ def get_protocolos(prots): dic['titulo'] = str(protocolo.numero) + '/' + str(protocolo.ano) - dic['data'] = protocolo.data.strftime( - "%d/%m/%Y") + ' - Horário:' + protocolo.hora.strftime( - "%H:%m") + ts = timezone.localtime(protocolo.timestamp) + + dic['data'] = ts.strftime("%d/%m/%Y") + ' - Horário:' + \ + ts.strftime("%H:%m") dic['txt_assunto'] = protocolo.assunto_ementa @@ -941,7 +942,7 @@ def get_etiqueta_protocolos(prots): tz_hora = timezone.localtime(p.timestamp) - dic['data'] = 'Data: ' + p.data.strftime( + dic['data'] = 'Data: ' + tz_hora.strftime( "%d/%m/%Y") + ' - Horário: ' + tz_hora.strftime("%H:%M") dic['txt_assunto'] = p.assunto_ementa dic['txt_interessado'] = p.interessado diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index c9e1e0e00..5a2b0785a 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -460,9 +460,10 @@ def recuperar_materia(request): ano=ano, numero=numero) response = JsonResponse({'ementa': materia.ementa, - 'id': materia.id}) + 'id': materia.id, + 'indexacao': materia.indexacao}) except ObjectDoesNotExist: - response = JsonResponse({'ementa': '', 'id': 0}) + response = JsonResponse({'ementa': '', 'id': 0, 'indexacao':''}) return response diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 6a578d102..046aa58e4 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -558,6 +558,19 @@ p { } } +.btn-cancel-iframe { + position: relative; + text-align: right; + opacity: 0.5; + &:hover { + opacity: 1; + } + a { + padding: 10px; + display: inline-block; + } +} + @media (max-width: 1199px) { .masthead { diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 3e1dc3a39..61db86669 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -29,6 +29,7 @@
+ {% if not request|has_iframe %} {% block navigation %}