Browse Source

Impl feature flag (#3357)

* add load para variável de ambiente

* altera url de primeira página se SAPL_AS_SAPN = True

* add context_processor para sapl as sapn

* ajuste de identação

* refatora base.html para sapl as sapn

* remove menus do sapl em sapn

* ajusta tabelas auxiliares

* refatora norma e compilação para sapl as sapn

* impl feature flag superficial

* ajusta menu Acessar em sapl as sapn

* add orgao como fk para normas

* add órgão no cadastro de normas

* ajuste de teste redirecionamento sapl index

* ajuste de teste de url
pull/3359/head
Leandro Roberto Silva 4 years ago
committed by GitHub
parent
commit
18c54c1401
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      sapl/base/forms.py
  2. 18
      sapl/base/migrations/0044_appconfig_sapl_as_sapn.py
  3. 18
      sapl/base/migrations/0045_auto_20210301_1537.py
  4. 5
      sapl/base/models.py
  5. 7
      sapl/base/templatetags/common_tags.py
  6. 32
      sapl/base/urls.py
  7. 9
      sapl/base/views.py
  8. 19
      sapl/compilacao/migrations/0018_auto_20210227_2152.py
  9. 3
      sapl/compilacao/models.py
  10. 13
      sapl/context_processors.py
  11. 26
      sapl/norma/forms.py
  12. 20
      sapl/norma/migrations/0038_normajuridica_orgao.py
  13. 8
      sapl/norma/models.py
  14. 4
      sapl/norma/urls.py
  15. 19
      sapl/norma/views.py
  16. 5
      sapl/redireciona_urls/tests.py
  17. 95
      sapl/redireciona_urls/views.py
  18. 1
      sapl/settings.py
  19. 43
      sapl/templates/base.html
  20. 3
      sapl/templates/base/layouts.yaml
  21. 4
      sapl/templates/compilacao/subnav.html
  22. 3
      sapl/templates/compilacao/text_list__embedded.html
  23. 74
      sapl/templates/menu_tabelas_auxiliares.yaml
  24. 4
      sapl/templates/navbar.yaml
  25. 4
      sapl/templates/norma/layouts.yaml
  26. 6
      sapl/templates/norma/normajuridica_detail.html
  27. 5
      sapl/templates/norma/normajuridica_form.html
  28. 3
      sapl/templates/search/search.html
  29. 14
      sapl/test_urls.py
  30. 14
      sapl/urls.py
  31. 7
      sapl/utils.py

3
sapl/base/forms.py

@ -1611,7 +1611,8 @@ class ConfiguracoesAppForm(ModelForm):
'tramitacao_materia', 'tramitacao_materia',
'tramitacao_documento', 'tramitacao_documento',
'google_recaptcha_site_key', 'google_recaptcha_site_key',
'google_recaptcha_secret_key'] 'google_recaptcha_secret_key',
'sapl_as_sapn']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ConfiguracoesAppForm, self).__init__(*args, **kwargs) super(ConfiguracoesAppForm, self).__init__(*args, **kwargs)

18
sapl/base/migrations/0044_appconfig_sapl_as_sapn.py

@ -0,0 +1,18 @@
# Generated by Django 2.2.13 on 2021-02-28 00:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0043_auto_20210203_1442'),
]
operations = [
migrations.AddField(
model_name='appconfig',
name='sapl_as_sapn',
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Utilizar SAPL com SAPN?'),
),
]

18
sapl/base/migrations/0045_auto_20210301_1537.py

@ -0,0 +1,18 @@
# Generated by Django 2.2.13 on 2021-03-01 18:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0044_appconfig_sapl_as_sapn'),
]
operations = [
migrations.AlterField(
model_name='appconfig',
name='sapl_as_sapn',
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Utilizar SAPL como SAPN?'),
),
]

5
sapl/base/models.py

@ -200,6 +200,11 @@ class AppConfig(models.Model):
verbose_name=_('Chave privada gerada pelo Google Recaptcha'), verbose_name=_('Chave privada gerada pelo Google Recaptcha'),
max_length=256, default='') max_length=256, default='')
sapl_as_sapn = models.BooleanField(
verbose_name=_(
'Utilizar SAPL como SAPN?'),
choices=YES_NO_CHOICES, default=False)
class Meta: class Meta:
verbose_name = _('Configurações da Aplicação') verbose_name = _('Configurações da Aplicação')
verbose_name_plural = _('Configurações da Aplicação') verbose_name_plural = _('Configurações da Aplicação')

7
sapl/base/templatetags/common_tags.py

@ -51,6 +51,13 @@ def model_verbose_name_plural(class_name):
model = get_class(class_name) model = get_class(class_name)
return model._meta.verbose_name_plural return model._meta.verbose_name_plural
@register.filter
def meta_model_value(instance, attr):
try:
return getattr(instance._meta, attr)
except:
return ''
@register.filter @register.filter
def split(value, arg): def split(value, arg):

32
sapl/base/urls.py

@ -11,7 +11,8 @@ from django.views.generic.base import RedirectView, TemplateView
from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView, from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView,
PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView, PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView,
RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView) RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView,
IndexView)
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL, LOGOUT_REDIRECT_URL from sapl.settings import EMAIL_SEND_USER, MEDIA_URL, LOGOUT_REDIRECT_URL
from .apps import AppConfig from .apps import AppConfig
@ -35,10 +36,14 @@ app_name = AppConfig.name
admin_user = [ admin_user = [
url(r'^sistema/usuario/$', PesquisarUsuarioView.as_view(), name='usuario'), url(r'^sistema/usuario/$', PesquisarUsuarioView.as_view(), name='usuario'),
url(r'^sistema/usuario/create$', CreateUsuarioView.as_view(), name='user_create'), url(r'^sistema/usuario/create$',
url(r'^sistema/usuario/(?P<pk>\d+)$', DetailUsuarioView.as_view(), name='user_detail'), CreateUsuarioView.as_view(), name='user_create'),
url(r'^sistema/usuario/(?P<pk>\d+)/edit$', EditUsuarioView.as_view(), name='user_edit'), url(r'^sistema/usuario/(?P<pk>\d+)$',
url(r'^sistema/usuario/(?P<pk>\d+)/delete$', DeleteUsuarioView.as_view(), name='user_delete') DetailUsuarioView.as_view(), name='user_detail'),
url(r'^sistema/usuario/(?P<pk>\d+)/edit$',
EditUsuarioView.as_view(), name='user_edit'),
url(r'^sistema/usuario/(?P<pk>\d+)/delete$',
DeleteUsuarioView.as_view(), name='user_delete')
] ]
alterar_senha = [ alterar_senha = [
@ -49,17 +54,23 @@ alterar_senha = [
] ]
recuperar_senha = [ recuperar_senha = [
url(r'^recuperar-senha/email/$', RecuperarSenhaEmailView.as_view(), name='recuperar_senha_email'), url(r'^recuperar-senha/email/$', RecuperarSenhaEmailView.as_view(),
url(r'^recuperar-senha/finalizado/$', RecuperarSenhaFinalizadoView.as_view(), name='recuperar_senha_finalizado'), name='recuperar_senha_email'),
url(r'^recuperar-senha/finalizado/$',
RecuperarSenhaFinalizadoView.as_view(), name='recuperar_senha_finalizado'),
url(r'^recuperar-senha/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', RecuperarSenhaConfirmaView.as_view(), url(r'^recuperar-senha/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', RecuperarSenhaConfirmaView.as_view(),
name='recuperar_senha_confirma'), name='recuperar_senha_confirma'),
url(r'^recuperar-senha/completo/$', RecuperarSenhaCompletoView.as_view(), name='recuperar_senha_completo'), url(r'^recuperar-senha/completo/$',
RecuperarSenhaCompletoView.as_view(), name='recuperar_senha_completo'),
] ]
urlpatterns = [ urlpatterns = [
url(r'^$', IndexView.as_view(template_name='index.html'), name='sapl_index'),
url(r'^sistema/autor/tipo/', include(TipoAutorCrud.get_urls())), url(r'^sistema/autor/tipo/', include(TipoAutorCrud.get_urls())),
url(r'^sistema/autor/', include(AutorCrud.get_urls())), url(r'^sistema/autor/', include(AutorCrud.get_urls())),
url(r'^sistema/autor/pesquisar-autor/', PesquisarAutorView.as_view(), name='pesquisar_autor'), url(r'^sistema/autor/pesquisar-autor/',
PesquisarAutorView.as_view(), name='pesquisar_autor'),
url(r'^sistema/ajuda/(?P<topic>\w+)$', url(r'^sistema/ajuda/(?P<topic>\w+)$',
HelpTopicView.as_view(), name='help_topic'), HelpTopicView.as_view(), name='help_topic'),
@ -176,7 +187,8 @@ urlpatterns = [
url(r'^login/$', views.LoginView.as_view(template_name='base/login.html', authentication_form=LoginForm), url(r'^login/$', views.LoginView.as_view(template_name='base/login.html', authentication_form=LoginForm),
name='login'), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), {'next_page': LOGOUT_REDIRECT_URL}, name='logout'), url(r'^logout/$', views.LogoutView.as_view(),
{'next_page': LOGOUT_REDIRECT_URL}, name='logout'),
url(r'^sistema/search/', SaplSearchView(), name='haystack_search'), url(r'^sistema/search/', SaplSearchView(), name='haystack_search'),

9
sapl/base/views.py

@ -60,7 +60,7 @@ from sapl.sessao.models import (
from sapl.settings import EMAIL_SEND_USER from sapl.settings import EMAIL_SEND_USER
from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, parlamentares_ativos, from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, parlamentares_ativos,
SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo,
google_recaptcha_configured) google_recaptcha_configured, sapl_as_sapn)
from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet,
RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet,
@ -77,6 +77,13 @@ def get_casalegislativa():
return CasaLegislativa.objects.first() return CasaLegislativa.objects.first()
class IndexView(TemplateView):
def get(self, request, *args, **kwargs):
if sapl_as_sapn():
return redirect('/norma/pesquisar')
return TemplateView.get(self, request, *args, **kwargs)
class ConfirmarEmailView(TemplateView): class ConfirmarEmailView(TemplateView):
template_name = "email/confirma.html" template_name = "email/confirma.html"

19
sapl/compilacao/migrations/0018_auto_20210227_2152.py

@ -0,0 +1,19 @@
# Generated by Django 2.2.13 on 2021-02-28 00:52
from django.db import migrations
import image_cropping.fields
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0017_auto_20210225_1127'),
]
operations = [
migrations.AlterField(
model_name='dispositivo',
name='imagem_cropping',
field=image_cropping.fields.ImageRatioField('imagem', '100x100', adapt_rotation=False, allow_fullsize=False, free_crop=True, help_text='O recorte de imagem é possível após a atualização.', hide_image_field=False, size_warning=True, verbose_name='Recorte de Imagem'),
),
]

3
sapl/compilacao/models.py

@ -1192,8 +1192,7 @@ class Dispositivo(BaseModel, TimestampedMixin):
imagem = ImageCropField( imagem = ImageCropField(
verbose_name=_('Imagem'), verbose_name=_('Imagem'),
upload_to=imagem_upload_path, upload_to=imagem_upload_path, null=True, blank=True)
validators=[restringe_tipos_de_arquivo_img], null=True, blank=True)
imagem_cropping = ImageRatioField( imagem_cropping = ImageRatioField(
'imagem', '100x100', verbose_name=_('Recorte de Imagem'), 'imagem', '100x100', verbose_name=_('Recorte de Imagem'),

13
sapl/context_processors.py

@ -1,8 +1,10 @@
import logging import logging
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils,\
sapl_as_sapn as sapl_as_sapn_utils
from sapl.utils import mail_service_configured as mail_service_configured_utils from sapl.utils import mail_service_configured as mail_service_configured_utils
@ -32,3 +34,12 @@ def google_recaptcha_configured(request):
logger.warning(_('Google Recaptcha não configurado.')) logger.warning(_('Google Recaptcha não configurado.'))
return {'google_recaptcha_configured': False} return {'google_recaptcha_configured': False}
return {'google_recaptcha_configured': True} return {'google_recaptcha_configured': True}
def sapl_as_sapn(request):
return {
'sapl_as_sapn': sapl_as_sapn_utils(),
'nome_sistema': _('Sistema de Apoio ao Processo Legislativo')
if not sapl_as_sapn_utils()
else _('Sistema de Apoio a Publicação de Normas')
}

26
sapl/norma/forms.py

@ -1,8 +1,6 @@
import django_filters
import logging import logging
from crispy_forms.layout import Fieldset, Layout from crispy_forms.layout import Fieldset, Layout
from django import forms from django import forms
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import models from django.db import models
@ -10,6 +8,7 @@ from django.db.models import Q
from django.forms import ModelChoiceField, ModelForm, widgets from django.forms import ModelChoiceField, ModelForm, widgets
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import django_filters
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import form_actions, SaplFormHelper, to_row from sapl.crispy_layout_mixin import form_actions, SaplFormHelper, to_row
@ -85,7 +84,7 @@ class NormaFilterSet(django_filters.FilterSet):
class Meta(FilterOverridesMetaMixin): class Meta(FilterOverridesMetaMixin):
model = NormaJuridica model = NormaJuridica
fields = ['tipo', 'numero', 'ano', 'data', 'data_vigencia', fields = ['orgao', 'tipo', 'numero', 'ano', 'data', 'data_vigencia',
'data_publicacao', 'ementa', 'assuntos'] 'data_publicacao', 'ementa', 'assuntos']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -94,7 +93,7 @@ class NormaFilterSet(django_filters.FilterSet):
row1 = to_row([('tipo', 4), ('numero', 4), ('ano', 4)]) row1 = to_row([('tipo', 4), ('numero', 4), ('ano', 4)])
row2 = to_row([('data', 6), ('data_publicacao', 6)]) row2 = to_row([('data', 6), ('data_publicacao', 6)])
row3 = to_row([('ementa', 6), ('assuntos', 6)]) row3 = to_row([('ementa', 6), ('assuntos', 6)])
row4 = to_row([('data_vigencia', 12)]) row4 = to_row([('data_vigencia', 6), ('orgao', 6), ])
row5 = to_row([('o', 6), ('indexacao', 6)]) row5 = to_row([('o', 6), ('indexacao', 6)])
self.form.helper = SaplFormHelper() self.form.helper = SaplFormHelper()
@ -143,6 +142,7 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm):
fields = ['tipo', fields = ['tipo',
'numero', 'numero',
'ano', 'ano',
'orgao',
'data', 'data',
'esfera_federacao', 'esfera_federacao',
'complemento', 'complemento',
@ -184,14 +184,18 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm):
'Número de norma não pode conter somente letras') 'Número de norma não pode conter somente letras')
if self.instance.numero != cleaned_data['numero']: if self.instance.numero != cleaned_data['numero']:
norma = NormaJuridica.objects.filter(ano=cleaned_data['ano'], params = {
numero=cleaned_data['numero'], 'ano': cleaned_data['ano'],
tipo=cleaned_data['tipo']).exists() 'numero': cleaned_data['numero'],
'tipo': cleaned_data['tipo'],
}
params['orgao'] = cleaned_data['orgao']
norma = NormaJuridica.objects.filter(**params).exists()
if norma: if norma:
self.logger.warning("Já existe uma norma de mesmo Tipo ({}), Ano ({}) " self.logger.warning("Já existe uma norma de mesmo Tipo ({}), Ano ({}) "
"e Número ({}) no sistema." "e Número ({}) no sistema."
.format(cleaned_data['tipo'], cleaned_data['ano'], cleaned_data['numero'])) .format(cleaned_data['tipo'], cleaned_data['ano'], cleaned_data['numero']))
raise ValidationError("Já existe uma norma de mesmo Tipo, Ano " raise ValidationError("Já existe uma norma de mesmo Tipo, Ano, Órgão "
"e Número no sistema") "e Número no sistema")
if (cleaned_data['tipo_materia'] and if (cleaned_data['tipo_materia'] and
cleaned_data['numero_materia'] and cleaned_data['numero_materia'] and
@ -454,7 +458,9 @@ class NormaPesquisaSimplesForm(forms.Form):
raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e ' raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e '
'Data Final devem ser preenchidos obrigatoriamente')) 'Data Final devem ser preenchidos obrigatoriamente'))
elif data_inicial > data_final: elif data_inicial > data_final:
self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial)) self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(
raise ValidationError(_('A Data Final não pode ser menor que a Data Inicial')) data_final, data_inicial))
raise ValidationError(
_('A Data Final não pode ser menor que a Data Inicial'))
return cleaned_data return cleaned_data

20
sapl/norma/migrations/0038_normajuridica_orgao.py

@ -0,0 +1,20 @@
# Generated by Django 2.2.13 on 2021-03-01 18:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('materia', '0077_auto_20210209_1047'),
('norma', '0037_auto_20210107_1408'),
]
operations = [
migrations.AddField(
model_name='normajuridica',
name='orgao',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.Orgao', verbose_name='Órgão'),
),
]

8
sapl/norma/models.py

@ -8,7 +8,7 @@ import reversion
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.compilacao.models import TextoArticulado from sapl.compilacao.models import TextoArticulado
from sapl.materia.models import MateriaLegislativa from sapl.materia.models import MateriaLegislativa, Orgao
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES,
restringe_tipos_de_arquivo_txt, restringe_tipos_de_arquivo_txt,
texto_upload_path, texto_upload_path,
@ -151,6 +151,9 @@ class NormaJuridica(models.Model):
materia = models.ForeignKey( materia = models.ForeignKey(
MateriaLegislativa, blank=True, null=True, MateriaLegislativa, blank=True, null=True,
on_delete=models.PROTECT, verbose_name=_('Matéria')) on_delete=models.PROTECT, verbose_name=_('Matéria'))
orgao = models.ForeignKey(
Orgao, blank=True, null=True,
on_delete=models.PROTECT, verbose_name=_('Órgão'))
numero = models.CharField( numero = models.CharField(
max_length=8, max_length=8,
verbose_name=_('Número')) verbose_name=_('Número'))
@ -247,8 +250,9 @@ class NormaJuridica(models.Model):
if numero_norma.isnumeric(): if numero_norma.isnumeric():
numero_norma = '{0:,}'.format(int(self.numero)).replace(',', '.') numero_norma = '{0:,}'.format(int(self.numero)).replace(',', '.')
return _('%(tipo)s%(numero)s, de %(data)s') % { return _('%(tipo)s%(orgao_sigla)s%(numero)s, de %(data)s') % {
'tipo': self.tipo, 'tipo': self.tipo,
'orgao_sigla': f'-{self.orgao.sigla}' if self.orgao else '',
'numero': numero_norma, 'numero': numero_norma,
'data': defaultfilters.date(self.data, "d \d\e F \d\e Y").lower()} 'data': defaultfilters.date(self.data, "d \d\e F \d\e Y").lower()}

4
sapl/norma/urls.py

@ -1,3 +1,4 @@
from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from sapl.norma.views import (AnexoNormaJuridicaCrud, AssuntoNormaCrud, from sapl.norma.views import (AnexoNormaJuridicaCrud, AssuntoNormaCrud,
@ -7,8 +8,10 @@ from sapl.norma.views import (AnexoNormaJuridicaCrud, AssuntoNormaCrud,
recuperar_numero_norma, AutoriaNormaCrud, recuperar_numero_norma, AutoriaNormaCrud,
PesquisarAssuntoNormaView) PesquisarAssuntoNormaView)
from .apps import AppConfig from .apps import AppConfig
app_name = AppConfig.name app_name = AppConfig.name
@ -37,5 +40,4 @@ urlpatterns = [
url(r'^norma/recuperar-norma$', recuperar_norma, name="recuperar_norma"), url(r'^norma/recuperar-norma$', recuperar_norma, name="recuperar_norma"),
url(r'^norma/recuperar-numero-norma$', recuperar_numero_norma, url(r'^norma/recuperar-numero-norma$', recuperar_numero_norma,
name="recuperar_numero_norma"), name="recuperar_numero_norma"),
] ]

19
sapl/norma/views.py

@ -7,6 +7,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q from django.db.models import Q
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse
from django.http.response import HttpResponseRedirect from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect
from django.template import RequestContext, loader from django.template import RequestContext, loader
from django.urls import reverse from django.urls import reverse
from django.urls.base import reverse_lazy from django.urls.base import reverse_lazy
@ -25,7 +26,9 @@ from sapl.base.models import AppConfig
from sapl.compilacao.views import IntegracaoTaView from sapl.compilacao.views import IntegracaoTaView
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud, make_pagination) MasterDetailCrud, make_pagination)
from sapl.utils import show_results_filter_set, get_client_ip from sapl.materia.models import Orgao
from sapl.utils import show_results_filter_set, get_client_ip,\
sapl_as_sapn
from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm,
NormaPesquisaSimplesForm, NormaRelacionadaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm,
@ -35,8 +38,6 @@ from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelac
# LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '')
TipoNormaCrud = CrudAux.build( TipoNormaCrud = CrudAux.build(
TipoNormaJuridica, 'tipo_norma_juridica', TipoNormaJuridica, 'tipo_norma_juridica',
list_field_names=['sigla', 'descricao', 'equivalente_lexml']) list_field_names=['sigla', 'descricao', 'equivalente_lexml'])
@ -273,6 +274,11 @@ class NormaCrud(Crud):
norma_id=kwargs['pk'], norma_id=kwargs['pk'],
ano=timezone.now().year, ano=timezone.now().year,
horario_acesso=timezone.now()) horario_acesso=timezone.now())
if not 'display' in request.GET and not request.user.has_perm('norma.change_normajuridica') and \
self.get_object().texto_articulado.exists():
return redirect(reverse('sapl.norma:norma_ta',
kwargs={'pk': self.kwargs['pk']}))
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
class DeleteView(Crud.DeleteView): class DeleteView(Crud.DeleteView):
@ -450,9 +456,14 @@ def recuperar_norma(request):
def recuperar_numero_norma(request): def recuperar_numero_norma(request):
tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo']) tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo'])
ano = request.GET.get('ano', '') ano = request.GET.get('ano', '')
orgao = request.GET.get('orgao', '')
param = {'tipo': tipo, param = {'tipo': tipo,
'ano': ano if ano else timezone.now().year 'ano': ano if ano else timezone.now().year,
} }
if orgao:
param['orgao'] = Orgao.objects.get(pk=orgao)
norma = NormaJuridica.objects.filter(**param).order_by( norma = NormaJuridica.objects.filter(**param).order_by(
'tipo', 'ano', 'numero').values_list('numero', flat=True) 'tipo', 'ano', 'numero').values_list('numero', flat=True)
if norma: if norma:

5
sapl/redireciona_urls/tests.py

@ -1,5 +1,6 @@
from django.urls import reverse
from django.test import TestCase from django.test import TestCase
from django.urls import reverse
MovedPermanentlyHTTPStatusCode = 301 MovedPermanentlyHTTPStatusCode = 301
EMPTY_STRING = '' EMPTY_STRING = ''
@ -11,7 +12,7 @@ class RedirecionaURLsTests(TestCase):
response = self.client.get(reverse( response = self.client.get(reverse(
'sapl.redireciona_urls:redireciona_sapl_index') 'sapl.redireciona_urls:redireciona_sapl_index')
) )
url_e = reverse('sapl_index') url_e = reverse('sapl.base:sapl_index')
self.assertEqual(response.status_code, MovedPermanentlyHTTPStatusCode) self.assertEqual(response.status_code, MovedPermanentlyHTTPStatusCode)
self.assertEqual(response.url, url_e) self.assertEqual(response.url, url_e)

95
sapl/redireciona_urls/views.py

@ -76,13 +76,14 @@ class RedirecionaSAPLIndex(RedirectView):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_redirect_url(self): def get_redirect_url(self):
url_pattern = 'sapl_index' url_pattern = 'sapl.base:sapl_index'
username = self.request.user.username username = self.request.user.username
try: try:
self.logger.info("user=" + username + ". Tentando obter url.") self.logger.info("user=" + username + ". Tentando obter url.")
url = reverse(url_pattern) url = reverse(url_pattern)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(url_pattern) raise UnknownUrlNameError(url_pattern)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -105,17 +106,20 @@ class RedirecionaParlamentar(RedirectView):
if pk_parlamentar: if pk_parlamentar:
try: try:
kwargs = {'pk': pk_parlamentar} kwargs = {'pk': pk_parlamentar}
self.logger.debug("user=" + username + ". Tentando obter url correspondente.") self.logger.debug("user=" + username +
". Tentando obter url correspondente.")
url = reverse(parlamentar_detail, kwargs=kwargs) url = reverse(parlamentar_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(parlamentar_detail, kwargs=kwargs) raise UnknownUrlNameError(parlamentar_detail, kwargs=kwargs)
else: else:
try: try:
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(parlamentar_list) url = reverse(parlamentar_list)
except NoReverseMatch: except NoReverseMatch:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(parlamentar_list) raise UnknownUrlNameError(parlamentar_list)
numero_legislatura = self.request.GET.get( numero_legislatura = self.request.GET.get(
@ -143,17 +147,20 @@ class RedirecionaComissao(RedirectView):
kwargs = {'pk': pk_comissao} kwargs = {'pk': pk_comissao}
try: try:
self.logger.debug("user=" + username + ". Tentando obter url correspondente.") self.logger.debug("user=" + username +
". Tentando obter url correspondente.")
url = reverse(comissao_detail, kwargs=kwargs) url = reverse(comissao_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(comissao_detail) raise UnknownUrlNameError(comissao_detail)
else: else:
try: try:
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(comissao_list) url = reverse(comissao_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(comissao_list) raise UnknownUrlNameError(comissao_list)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -176,17 +183,20 @@ class RedirecionaComposicaoComissao(RedirectView):
kwargs = {'pk': pk_comissao} kwargs = {'pk': pk_comissao}
try: try:
self.logger.debug("user=" + username + ". Tentando obter url correspondente.") self.logger.debug("user=" + username +
". Tentando obter url correspondente.")
url = reverse(comissao_detail, kwargs=kwargs) url = reverse(comissao_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(comissao_detail) raise UnknownUrlNameError(comissao_detail)
else: else:
try: try:
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(comissao_list) url = reverse(comissao_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(comissao_list) raise UnknownUrlNameError(comissao_list)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -208,17 +218,20 @@ class RedirecionaPautaSessao(RedirectView):
if pk_sessao_plenaria: if pk_sessao_plenaria:
kwargs = {'pk': pk_sessao_plenaria} kwargs = {'pk': pk_sessao_plenaria}
try: try:
self.logger.debug("user=" + username + ". Tentando obter url correspondente.") self.logger.debug("user=" + username +
". Tentando obter url correspondente.")
url = reverse(pauta_sessao_detail, kwargs=kwargs) url = reverse(pauta_sessao_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(pauta_sessao_detail) raise UnknownUrlNameError(pauta_sessao_detail)
else: else:
try: try:
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(pauta_sessao_list) url = reverse(pauta_sessao_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(pauta_sessao_list) raise UnknownUrlNameError(pauta_sessao_list)
data_sessao_plenaria = self.request.GET.get( data_sessao_plenaria = self.request.GET.get(
@ -255,10 +268,12 @@ class RedirecionaSessaoPlenaria(RedirectView):
if pk_sessao_plenaria: if pk_sessao_plenaria:
kwargs = {'pk': pk_sessao_plenaria} kwargs = {'pk': pk_sessao_plenaria}
try: try:
self.logger.debug("user=" + username + ". Tentando obter url correspondente.") self.logger.debug("user=" + username +
". Tentando obter url correspondente.")
url = reverse(sessao_plenaria_detail, kwargs=kwargs) url = reverse(sessao_plenaria_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(sessao_plenaria_detail) raise UnknownUrlNameError(sessao_plenaria_detail)
else: else:
@ -266,7 +281,8 @@ class RedirecionaSessaoPlenaria(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(sessao_plenaria_list) url = reverse(sessao_plenaria_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(sessao_plenaria_list) raise UnknownUrlNameError(sessao_plenaria_list)
year = self.request.GET.get( year = self.request.GET.get(
@ -309,7 +325,8 @@ class RedirecionaRelatoriosList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(relatorios_list) url = reverse(relatorios_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(relatorios_list) raise UnknownUrlNameError(relatorios_list)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -328,7 +345,8 @@ class RedirecionaRelatoriosMateriasEmTramitacaoList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(relatorio_materia_por_tramitacao) url = reverse(relatorio_materia_por_tramitacao)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(relatorio_materia_por_tramitacao) raise UnknownUrlNameError(relatorio_materia_por_tramitacao)
year = self.request.GET.get( year = self.request.GET.get(
@ -396,7 +414,8 @@ class RedirecionaMateriaLegislativaList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(materialegislativa_list) url = reverse(materialegislativa_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(materialegislativa_list) raise UnknownUrlNameError(materialegislativa_list)
tipo_materia = self.request.GET.get( tipo_materia = self.request.GET.get(
@ -475,7 +494,8 @@ class RedirecionaMesaDiretoraView(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(parlamentar_mesa_diretora) url = reverse(parlamentar_mesa_diretora)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(parlamentar_mesa_diretora) raise UnknownUrlNameError(parlamentar_mesa_diretora)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -509,12 +529,14 @@ class RedirecionaNormasJuridicasTextoIntegral(RedirectView):
url = EMPTY_STRING url = EMPTY_STRING
username = self.request.user.username username = self.request.user.username
try: try:
self.logger.debug("user=" + username + ". Tentando obter NormaJuridica com pk={}.".format(kwargs['norma_id'])) self.logger.debug(
"user=" + username + ". Tentando obter NormaJuridica com pk={}.".format(kwargs['norma_id']))
norma = NormaJuridica.objects.get(pk=kwargs['norma_id']) norma = NormaJuridica.objects.get(pk=kwargs['norma_id'])
if norma: if norma:
url = norma.texto_integral.url url = norma.texto_integral.url
except Exception as e: except Exception as e:
self.logger.error("user=" + username + ". Erro ao obter NormaJuridica com pk={}. ".format(kwargs['norma_id']) + str(e)) self.logger.error(
"user=" + username + ". Erro ao obter NormaJuridica com pk={}. ".format(kwargs['norma_id']) + str(e))
raise e raise e
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -535,7 +557,8 @@ class RedirecionaNormasJuridicasList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(norma_juridica_pesquisa) url = reverse(norma_juridica_pesquisa)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(norma_juridica_pesquisa) raise UnknownUrlNameError(norma_juridica_pesquisa)
tipo_norma = self.request.GET.get( tipo_norma = self.request.GET.get(
@ -598,7 +621,8 @@ class RedirecionaHistoricoTramitacoesList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(historico_tramitacoes) url = reverse(historico_tramitacoes)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(historico_tramitacoes) raise UnknownUrlNameError(historico_tramitacoes)
inicio_intervalo_data_tramitacao = self.request.GET.get( inicio_intervalo_data_tramitacao = self.request.GET.get(
@ -660,7 +684,8 @@ class RedirecionaAtasList(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(pesquisar_atas) url = reverse(pesquisar_atas)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(pesquisar_atas) raise UnknownUrlNameError(pesquisar_atas)
inicio_intervalo_data_ata = self.request.GET.get( inicio_intervalo_data_ata = self.request.GET.get(
@ -699,7 +724,8 @@ class RedirecionaPresencaParlamentares(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(presenca_sessao) url = reverse(presenca_sessao)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(presenca_sessao) raise UnknownUrlNameError(presenca_sessao)
inicio_intervalo_data_presenca_parlamentar = self.request.GET.get( inicio_intervalo_data_presenca_parlamentar = self.request.GET.get(
@ -736,7 +762,8 @@ class RedirecionaMateriasPorAutor(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(relatorio_materia_por_autor) url = reverse(relatorio_materia_por_autor)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(relatorio_materia_por_autor) raise UnknownUrlNameError(relatorio_materia_por_autor)
url = has_iframe(url, self.request) url = has_iframe(url, self.request)
@ -758,7 +785,8 @@ class RedirecionaMateriasPorAnoAutorTipo(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(relatorio_materia_por_ano_autor_tipo) url = reverse(relatorio_materia_por_ano_autor_tipo)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(relatorio_materia_por_ano_autor_tipo) raise UnknownUrlNameError(relatorio_materia_por_ano_autor_tipo)
if ano: if ano:
@ -785,10 +813,12 @@ class RedirecionaReuniao(RedirectView):
if pk_reuniao: if pk_reuniao:
kwargs = {'pk': pk_reuniao} kwargs = {'pk': pk_reuniao}
try: try:
self.logger.debug("user=" + username + ". Tentando obter url correspondente (pk={}).".format(kwargs['pk'])) self.logger.debug(
"user=" + username + ". Tentando obter url correspondente (pk={}).".format(kwargs['pk']))
url = reverse(reuniao_detail, kwargs=kwargs) url = reverse(reuniao_detail, kwargs=kwargs)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(reuniao_detail) raise UnknownUrlNameError(reuniao_detail)
else: else:
@ -796,7 +826,8 @@ class RedirecionaReuniao(RedirectView):
self.logger.debug("user=" + username + ". Tentando obter url.") self.logger.debug("user=" + username + ". Tentando obter url.")
url = reverse(reuniao_list) url = reverse(reuniao_list)
except NoReverseMatch as e: except NoReverseMatch as e:
self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) self.logger.error("user=" + username +
". Erro ao obter url. " + str(e))
raise UnknownUrlNameError(reuniao_list) raise UnknownUrlNameError(reuniao_list)
year = self.request.GET.get( year = self.request.GET.get(

1
sapl/settings.py

@ -196,6 +196,7 @@ TEMPLATES = [
'sapl.context_processors.parliament_info', 'sapl.context_processors.parliament_info',
'sapl.context_processors.mail_service_configured', 'sapl.context_processors.mail_service_configured',
'sapl.context_processors.google_recaptcha_configured', 'sapl.context_processors.google_recaptcha_configured',
'sapl.context_processors.sapl_as_sapn',
], ],
'debug': DEBUG 'debug': DEBUG

43
sapl/templates/base.html

@ -34,6 +34,7 @@
<body> <body>
<div class="page fadein"> <div class="page fadein">
{% if not sapl_as_sapn or user.is_authenticated%}
{% if not request|has_iframe %} {% if not request|has_iframe %}
{% block navigation %} {% block navigation %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
@ -42,6 +43,7 @@
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
{% block sections_navbar %} {% navbar 'navbar.yaml' %} {% endblock sections_navbar %} {% block sections_navbar %} {% navbar 'navbar.yaml' %} {% endblock sections_navbar %}
<ul class="nav navbar-nav justify-content-end" id="autenticacao"> <ul class="nav navbar-nav justify-content-end" id="autenticacao">
@ -64,7 +66,7 @@
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="dropdown-item"><a>{{user.username}}</a></li> <li class="dropdown-item"><a>{{user.username}}</a></li>
{% if 'parlamentares.can_vote' in request.user.get_all_permissions %} {% if not sapl_as_sapn and 'parlamentares.can_vote' in request.user.get_all_permissions %}
<li class="dropdown-item"><a href="" onclick="window.open('{% url 'sapl.painel:voto_individual' %}','Voto Individual','width=1000, height=800, scrollbars=yes')";> <li class="dropdown-item"><a href="" onclick="window.open('{% url 'sapl.painel:voto_individual' %}','Voto Individual','width=1000, height=800, scrollbars=yes')";>
Votar Matéria Votar Matéria
</a></li> </a></li>
@ -80,7 +82,29 @@
</div> </div>
</nav> </nav>
{% endblock navigation %} {% endblock navigation %}
{% else %}
<div class="btn-cancel-iframe">
<a href="?iframe=0" target="_blank"><i class="fa fa-2x fa-arrows-alt"></i></a>
</div>
<header class="masthead">
<div class="container">
<div class="hidden-print">
{% subnav %}
</div>
</div>
</header>
{% endif %}
{% else %}
<div class="container">
<div class="row justify-content-end px-3">
{% if sapl_as_sapn and not user.is_authenticated%}
<small><a href="{% url 'sapl.base:login' %}">Acessar</a></small>
{% endif %}
</div>
</div>
{% endif %}
{% if not request|has_iframe %}
{# Header #} {# Header #}
{% block main_header %} {% block main_header %}
<header class="masthead"> <header class="masthead">
@ -90,7 +114,7 @@
<img src="{% if logotipo %}{{ MEDIA_URL }}{{ logotipo }}{% else %}{% webpack_static 'img/logo.png' %}{% endif %}" <img src="{% if logotipo %}{{ MEDIA_URL }}{{ logotipo }}{% else %}{% webpack_static 'img/logo.png' %}{% endif %}"
alt="Logo" class="img-responsive" > alt="Logo" class="img-responsive" >
<span class="vcenter">{% if nome %}{{ nome }}{% else %}{% trans 'Câmara/Assembléia não configurada'%}{% endif %} <span class="vcenter">{% if nome %}{{ nome }}{% else %}{% trans 'Câmara/Assembléia não configurada'%}{% endif %}
<br/><small>{% trans 'Sistema de Apoio ao Processo Legislativo' %}</small> <br/><small>{{nome_sistema}}</small>
</span> </span>
</a> </a>
</div> </div>
@ -100,17 +124,6 @@
</div> </div>
</header> </header>
{% endblock main_header %} {% endblock main_header %}
{% else %}
<div class="btn-cancel-iframe">
<a href="?iframe=0" target="_blank"><i class="fa fa-2x fa-arrows-alt"></i></a>
</div>
<header class="masthead">
<div class="container">
<div class="hidden-print">
{% subnav %}
</div>
</div>
</header>
{% endif %} {% endif %}
{# Main content #} {# Main content #}
@ -205,6 +218,7 @@
<br> <br>
<a href="{{endereco_web}}" class="url">{% trans 'Site' %}</a> | <a href="{{endereco_web}}" class="url">{% trans 'Site' %}</a> |
<a href="mailto:{{email}}" class="email">{% trans 'Fale Conosco' %}</a> <a href="mailto:{{email}}" class="email">{% trans 'Fale Conosco' %}</a>
</small> </small>
</address> </address>
{% else %} {% else %}
@ -214,6 +228,9 @@
<a href="{% url 'sapl.base:casalegislativa_list' %}">Favor configurar clicando aqui</a> <a href="{% url 'sapl.base:casalegislativa_list' %}">Favor configurar clicando aqui</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>

3
sapl/templates/base/layouts.yaml

@ -13,8 +13,7 @@ CasaLegislativa:
AppConfig: AppConfig:
{% trans 'Configurações Gerais' %}: {% trans 'Configurações Gerais' %}:
- esfera_federacao - esfera_federacao documentos_administrativos sapl_as_sapn
- documentos_administrativos
#{% trans 'Módulo Parlamentares' %}: #{% trans 'Módulo Parlamentares' %}:

4
sapl/templates/compilacao/subnav.html

@ -4,7 +4,9 @@
<ul class="nav nav-tabs justify-content-end"> <ul class="nav nav-tabs justify-content-end">
{%if object %} {%if object %}
<li class="nav-item"> <li class="nav-item">
{% if request.GET.back_type == 'history' and object.content_object %} {% if object.content_object|meta_model_value:'model_name' == 'normajuridica' %}
<a class="nav-link" href="{% url object|urldetail_content_type:object.content_object object.content_object.pk %}?display" title="{% trans 'Dados Complementares '%}">{% trans 'Dados Complementares '%}</a>
{% elif request.GET.back_type == 'history' and object.content_object %}
<a class="nav-link" href="javascript:window.history.back()" title="{% trans 'Voltar para '%}{{object}}">{% trans 'Voltar para '%}{{object}}</a> <a class="nav-link" href="javascript:window.history.back()" title="{% trans 'Voltar para '%}{{object}}">{% trans 'Voltar para '%}{{object}}</a>
{% elif object.content_object%} {% elif object.content_object%}
<a class="nav-link" href="{% url object|urldetail_content_type:object.content_object object.content_object.pk %}" title="{% trans 'Voltar para '%}{{object}}">{% trans 'Voltar para '%}{{object}}</a> <a class="nav-link" href="{% url object|urldetail_content_type:object.content_object object.content_object.pk %}" title="{% trans 'Voltar para '%}{{object}}">{% trans 'Voltar para '%}{{object}}</a>

3
sapl/templates/compilacao/text_list__embedded.html

@ -6,6 +6,9 @@
{% if object_list %} {% if object_list %}
{% if 'print' not in request.GET %} {% if 'print' not in request.GET %}
<div class="actions btn-group" role="group"> <div class="actions btn-group" role="group">
{% if sapl_as_sapn %}
<a href="{% url 'sapl.norma:norma_pesquisa' %}" class="btn btn-outline-primary" >{% trans 'Fazer nova pesquisa' %}</a>
{% endif %}
<a href="{% if 'compilacao' not in request.resolver_match.namespace %}{% url 'sapl.compilacao:ta_text' object_list.0.ta_id %}{% else %}{{request.path}}{% endif %}?print" class="btn btn-outline-primary" id="btn_impressao">{% trans 'Preparar para impressão' %}</a> <a href="{% if 'compilacao' not in request.resolver_match.namespace %}{% url 'sapl.compilacao:ta_text' object_list.0.ta_id %}{% else %}{{request.path}}{% endif %}?print" class="btn btn-outline-primary" id="btn_impressao">{% trans 'Preparar para impressão' %}</a>
</div> </div>
{% endif %} {% endif %}

74
sapl/templates/menu_tabelas_auxiliares.yaml

@ -17,6 +17,7 @@
- title: {% trans 'Tipo de Autor' %} - title: {% trans 'Tipo de Autor' %}
url: sapl.base:tipoautor_list url: sapl.base:tipoautor_list
css_class: btn btn-link css_class: btn btn-link
{% if not sapl_as_sapn%}
- title: {% trans 'Módulo Parlamentares' %} - title: {% trans 'Módulo Parlamentares' %}
css_class: head_title css_class: head_title
children: children:
@ -137,6 +138,40 @@
- title: {% trans 'Configuração Etiqueta Materia Legislativa' %} - title: {% trans 'Configuração Etiqueta Materia Legislativa' %}
url: sapl.materia:configEtiquetaMateriaLegislativaCrud url: sapl.materia:configEtiquetaMateriaLegislativaCrud
css_class: btn btn-link css_class: btn btn-link
- title: {% trans 'Módulo Sessão Plenária' %}
css_class: head_title
children:
- title: {% trans 'Tipo de Sessão Plenária' %}
url: sapl.sessao:tiposessaoplenaria_list
css_class: btn btn-link
- title: {% trans 'Tipo de Resultado da Votação' %}
url: sapl.sessao:tiporesultadovotacao_list
css_class: btn btn-link
- title: {% trans 'Tipo de Expediente' %}
url: sapl.sessao:tipoexpediente_list
css_class: btn btn-link
- title: {% trans 'Tipo de Retirada de Pauta' %}
url: sapl.sessao:tiporetiradapauta_list
css_class: btn btn-link
- title: {% trans 'Ordenação do Resumo' %}
url: sapl.sessao:resumo_ordenacao
css_class: btn btn-link
- title: {% trans 'Tipo de Justificativa' %}
url: sapl.sessao:tipojustificativa_list
css_class: btn btn-link
- title: {% trans 'Módulo Administrativo' %}
css_class: head_title
children:
- title: {% trans 'Tipo de Documento' %}
url: sapl.protocoloadm:tipodocumentoadministrativo_list
css_class: btn btn-link
- title: {% trans 'Status de Tramitação' %}
url: sapl.protocoloadm:statustramitacaoadministrativo_list
css_class: btn btn-link
- title: {% trans 'Apagar Protocolos' %}
url: sapl.protocoloadm:apaga_protocolos_view
css_class: btn btn-link
{% endif %}
- title: {% trans 'Módulo Normas Jurídicas' %} - title: {% trans 'Módulo Normas Jurídicas' %}
css_class: head_title css_class: head_title
children: children:
@ -152,6 +187,12 @@
- title: {% trans 'Adicionar Assunto de Norma Jurídica' %} - title: {% trans 'Adicionar Assunto de Norma Jurídica' %}
url: sapl.norma:assuntonorma_create url: sapl.norma:assuntonorma_create
css_class: btn btn-link css_class: btn btn-link
{% if sapl_as_sapn %}
- title: {% trans 'Órgão' %}
url: sapl.materia:orgao_list
css_class: btn btn-link
{% endif %}
- title: {% trans 'Módulo Textos Articulados' %} - title: {% trans 'Módulo Textos Articulados' %}
css_class: head_title css_class: head_title
children: children:
@ -170,27 +211,6 @@
- title: {% trans 'Tipos de Vides' %} - title: {% trans 'Tipos de Vides' %}
url: sapl.compilacao:tipovide_list url: sapl.compilacao:tipovide_list
css_class: btn btn-link css_class: btn btn-link
- title: {% trans 'Módulo Sessão Plenária' %}
css_class: head_title
children:
- title: {% trans 'Tipo de Sessão Plenária' %}
url: sapl.sessao:tiposessaoplenaria_list
css_class: btn btn-link
- title: {% trans 'Tipo de Resultado da Votação' %}
url: sapl.sessao:tiporesultadovotacao_list
css_class: btn btn-link
- title: {% trans 'Tipo de Expediente' %}
url: sapl.sessao:tipoexpediente_list
css_class: btn btn-link
- title: {% trans 'Tipo de Retirada de Pauta' %}
url: sapl.sessao:tiporetiradapauta_list
css_class: btn btn-link
- title: {% trans 'Ordenação do Resumo' %}
url: sapl.sessao:resumo_ordenacao
css_class: btn btn-link
- title: {% trans 'Tipo de Justificativa' %}
url: sapl.sessao:tipojustificativa_list
css_class: btn btn-link
- title: {% trans 'Módulo LexML' %} - title: {% trans 'Módulo LexML' %}
css_class: head_title css_class: head_title
children: children:
@ -200,15 +220,3 @@
- title: {% trans 'Publicador' %} - title: {% trans 'Publicador' %}
url: sapl.lexml:lexmlpublicador_list url: sapl.lexml:lexmlpublicador_list
css_class: btn btn-link css_class: btn btn-link
- title: {% trans 'Módulo Administrativo' %}
css_class: head_title
children:
- title: {% trans 'Tipo de Documento' %}
url: sapl.protocoloadm:tipodocumentoadministrativo_list
css_class: btn btn-link
- title: {% trans 'Status de Tramitação' %}
url: sapl.protocoloadm:statustramitacaoadministrativo_list
css_class: btn btn-link
- title: {% trans 'Apagar Protocolos' %}
url: sapl.protocoloadm:apaga_protocolos_view
css_class: btn btn-link

4
sapl/templates/navbar.yaml

@ -2,7 +2,7 @@
- title: {% trans 'Início' %} - title: {% trans 'Início' %}
url: '/' url: '/'
{% if not sapl_as_sapn %}
- title: {% trans 'Institucional' %} - title: {% trans 'Institucional' %}
children: children:
- title: {% trans 'Mesa Diretora' %} - title: {% trans 'Mesa Diretora' %}
@ -66,7 +66,7 @@
- title: {% trans 'Excluir Tramitação em Lote' %} - title: {% trans 'Excluir Tramitação em Lote' %}
url: sapl.materia:excluir_tramitacao_em_lote url: sapl.materia:excluir_tramitacao_em_lote
check_permission: materia.list_tramitacao {% comment %} FIXME transformar para checagens de menu_[funcionalidade]{% endcomment%} check_permission: materia.list_tramitacao {% comment %} FIXME transformar para checagens de menu_[funcionalidade]{% endcomment%}
{% endif %}
- title: {% trans 'Normas Jurídicas' %} - title: {% trans 'Normas Jurídicas' %}
children: children:
- title: {% trans 'Pesquisar Normas Jurídicas' %} - title: {% trans 'Pesquisar Normas Jurídicas' %}

4
sapl/templates/norma/layouts.yaml

@ -14,7 +14,7 @@ TipoNormaJuridica:
NormaJuridica: NormaJuridica:
{% trans 'Identificação Básica' %}: {% trans 'Identificação Básica' %}:
- tipo numero ano - orgao tipo:5 numero:2 ano:2
- data esfera_federacao complemento - data esfera_federacao complemento
- materia - materia
- data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao - data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao
@ -32,7 +32,7 @@ AnexoNormaJuridica:
NormaJuridicaCreate: NormaJuridicaCreate:
{% trans 'Identificação Básica' %}: {% trans 'Identificação Básica' %}:
- tipo ano numero - orgao tipo:5 numero:2 ano:2
- data esfera_federacao complemento - data esfera_federacao complemento
- tipo_materia numero_materia ano_materia - tipo_materia numero_materia ano_materia
- data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao - data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao

6
sapl/templates/norma/normajuridica_detail.html

@ -132,7 +132,7 @@
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %} {% if not sapl_as_sapn and object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %}
<hr /> <hr />
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
@ -146,13 +146,13 @@
{% block webpack_loader_js %} {% block webpack_loader_js %}
{{ block.super }} {{ block.super }}
{% if object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %} {% if not sapl_as_sapn and object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %}
{% render_bundle 'compilacao' 'js' %} {% render_bundle 'compilacao' 'js' %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
{% if object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %} {% if not sapl_as_sapn and object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %}
<script language="Javascript"> <script language="Javascript">
window.onload = function () { window.onload = function () {
$.get("{% url 'sapl.compilacao:ta_text' object.texto_articulado.first.id %}?embedded", $.get("{% url 'sapl.compilacao:ta_text' object.texto_articulado.first.id %}?embedded",

5
sapl/templates/norma/normajuridica_form.html

@ -37,16 +37,17 @@
function recuperar_norma() { function recuperar_norma() {
var tipo = $("#id_tipo").val(); var tipo = $("#id_tipo").val();
var ano = $("#id_ano").val(); var ano = $("#id_ano").val();
var orgao = $("#id_orgao").val();
if (tipo) { if (tipo) {
$.get("/norma/recuperar-numero-norma", { tipo: tipo, ano: ano }, $.get("/norma/recuperar-numero-norma", { tipo: tipo, ano: ano , orgao: orgao },
(data, status) => { (data, status) => {
$("#id_numero").val(data.numero); $("#id_numero").val(data.numero);
$("#id_ano").val(data.ano); $("#id_ano").val(data.ano);
}); });
} }
} }
var fields = ["#id_tipo", "#id_ano"]; var fields = ["#id_tipo", "#id_ano", "#id_orgao"];
for (i = 0; i < fields.length; i++) { for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_norma); $(fields[i]).change(recuperar_norma);
} }

3
sapl/templates/search/search.html

@ -12,6 +12,8 @@
</div> </div>
</div> </div>
{% if not sapl_as_sapn %}
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<h3> Em quais tipos de documento deseja pesquisar?</h3> <h3> Em quais tipos de documento deseja pesquisar?</h3>
@ -25,6 +27,7 @@
{{ form.models }} {{ form.models }}
</div> </div>
</div> </div>
{% endif %}
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">

14
sapl/test_urls.py

@ -1,4 +1,3 @@
import pytest
from django.apps import apps from django.apps import apps
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.management import _get_all_permissions from django.contrib.auth.management import _get_all_permissions
@ -6,6 +5,7 @@ from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import transaction from django.db import transaction
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import pytest
from sapl.crud.base import PermissionRequiredForAppCrudMixin from sapl.crud.base import PermissionRequiredForAppCrudMixin
from sapl.rules.apps import AppConfig, update_groups from sapl.rules.apps import AppConfig, update_groups
@ -13,6 +13,7 @@ from scripts.lista_urls import lista_urls
from .settings import SAPL_APPS from .settings import SAPL_APPS
pytestmark = pytest.mark.django_db pytestmark = pytest.mark.django_db
sapl_appconfs = [apps.get_app_config(n[5:]) for n in SAPL_APPS] sapl_appconfs = [apps.get_app_config(n[5:]) for n in SAPL_APPS]
@ -159,7 +160,9 @@ apps_url_patterns_prefixs_and_users = {
'/recuperar-senha', '/recuperar-senha',
'/sapl', '/sapl',
'/XSLT', '/XSLT',
]}, ],
'exact': ['/']
},
'comissoes': { 'comissoes': {
'users': {'operador_geral': ['/sistema', '/comissao'], 'users': {'operador_geral': ['/sistema', '/comissao'],
'operador_comissoes': ['/comissao']}, 'operador_comissoes': ['/comissao']},
@ -276,12 +279,19 @@ def test_urlpatterns(url_item, admin_client):
if app_name in apps_url_patterns_prefixs_and_users: if app_name in apps_url_patterns_prefixs_and_users:
prefixs = apps_url_patterns_prefixs_and_users[app_name]['prefixs'] prefixs = apps_url_patterns_prefixs_and_users[app_name]['prefixs']
exacts = apps_url_patterns_prefixs_and_users[app_name].get(
'exact', [])
isvalid = False isvalid = False
for prefix in prefixs: for prefix in prefixs:
if url.startswith(prefix): if url.startswith(prefix):
isvalid = True isvalid = True
break break
if not isvalid:
for exact in exacts:
if url == exact:
isvalid = True
break
assert isvalid, """ assert isvalid, """
O prefixo da url (%s) não está no padrão de sua app (%s). O prefixo da url (%s) não está no padrão de sua app (%s).

14
sapl/urls.py

@ -36,9 +36,9 @@ import sapl.redireciona_urls.urls
import sapl.relatorios.urls import sapl.relatorios.urls
import sapl.sessao.urls import sapl.sessao.urls
urlpatterns = [ urlpatterns = []
url(r'^$', TemplateView.as_view(template_name='index.html'),
name='sapl_index'), urlpatterns += [
url(r'^message$', TemplateView.as_view(template_name='base.html')), url(r'^message$', TemplateView.as_view(template_name='base.html')),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
@ -54,17 +54,21 @@ urlpatterns = [
url(r'', include(sapl.relatorios.urls)), url(r'', include(sapl.relatorios.urls)),
url(r'', include(sapl.audiencia.urls)), url(r'', include(sapl.audiencia.urls)),
# name='sapl_index'),
# must come at the end # must come at the end
# so that base /sistema/ url doesn't capture its children # so that base /sistema/ url doesn't capture its children
url(r'', include(sapl.base.urls)), url(r'', include(sapl.base.urls)),
url(r'', include(sapl.api.urls)), url(r'', include(sapl.api.urls)),
url(r'^favicon\.ico$', RedirectView.as_view(url='/static/sapl/img/favicon.ico', permanent=True)), url(r'^favicon\.ico$', RedirectView.as_view(
url='/static/sapl/img/favicon.ico', permanent=True)),
url(r'', include(sapl.redireciona_urls.urls)), url(r'', include(sapl.redireciona_urls.urls)),
path("robots.txt", TemplateView.as_view(template_name="robots.txt", content_type="text/plain")), path("robots.txt", TemplateView.as_view(
template_name="robots.txt", content_type="text/plain")),
] ]

7
sapl/utils.py

@ -6,6 +6,7 @@ from operator import itemgetter
import os import os
import platform import platform
import re import re
import sys
import tempfile import tempfile
from time import time from time import time
from unicodedata import normalize as unicodedata_normalize from unicodedata import normalize as unicodedata_normalize
@ -27,6 +28,7 @@ from django.db import models
from django.db.models import Q from django.db.models import Q
from django.forms import BaseForm from django.forms import BaseForm
from django.forms.widgets import SplitDateTimeWidget from django.forms.widgets import SplitDateTimeWidget
from django.urls.base import clear_url_caches
from django.utils import six, timezone from django.utils import six, timezone
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -1019,6 +1021,11 @@ def google_recaptcha_configured():
return not AppConfig.attr('google_recaptcha_site_key') == '' return not AppConfig.attr('google_recaptcha_site_key') == ''
def sapl_as_sapn():
from sapl.base.models import AppConfig
return AppConfig.attr('sapl_as_sapn')
def timing(f): def timing(f):
@wraps(f) @wraps(f)
def wrap(*args, **kw): def wrap(*args, **kw):

Loading…
Cancel
Save