Browse Source

Merge branch '3.1.x' into votacao_multipla

pull/2241/head
cristian-longhi 7 years ago
committed by GitHub
parent
commit
e11ee90e58
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Dockerfile
  2. 2
      docker-compose.yml
  3. 2
      requirements/dev-requirements.txt
  4. 23
      requirements/requirements.txt
  5. 97
      sapl/base/forms.py
  6. 8
      sapl/base/tests/teststub_urls.py
  7. 12
      sapl/base/urls.py
  8. 153
      sapl/base/views.py
  9. 11
      sapl/comissoes/forms.py
  10. 2
      sapl/comissoes/models.py
  11. 1
      sapl/comissoes/tests/test_comissoes.py
  12. 2
      sapl/compilacao/compilacao_data_tables.sql
  13. 35
      sapl/compilacao/migrations/0007_auto_20180911_1600.py
  14. 11
      sapl/crud/base.py
  15. 5
      sapl/materia/forms.py
  16. 21
      sapl/materia/migrations/0030_tramitacao_timestamp.py
  17. 3
      sapl/materia/models.py
  18. 23
      sapl/materia/views.py
  19. 8
      sapl/norma/forms.py
  20. 1
      sapl/norma/views.py
  21. 30
      sapl/protocoloadm/forms.py
  22. 20
      sapl/protocoloadm/migrations/0006_documentoadministrativo_restrito.py
  23. 5
      sapl/protocoloadm/models.py
  24. 6
      sapl/protocoloadm/tests/test_protocoloadm.py
  25. 22
      sapl/protocoloadm/views.py
  26. 6
      sapl/relatorios/templates/pdf_pauta_sessao_gerar.py
  27. 2
      sapl/relatorios/urls.py
  28. 29
      sapl/relatorios/views.py
  29. 29
      sapl/sessao/forms.py
  30. 37
      sapl/sessao/migrations/0023_auto_20180914_1315.py
  31. 8
      sapl/sessao/models.py
  32. 16
      sapl/sessao/serializers.py
  33. 4
      sapl/sessao/urls.py
  34. 145
      sapl/sessao/views.py
  35. 22
      sapl/settings.py
  36. 1
      sapl/templates/base/RelatorioAtas_filter.html
  37. 38
      sapl/templates/base/RelatorioAudiencia_filter.html
  38. 5
      sapl/templates/base/RelatorioDataFimPrazoTramitacao_filter.html
  39. 5
      sapl/templates/base/RelatorioHistoricoTramitacao_filter.html
  40. 37
      sapl/templates/base/RelatorioMateriasPorAnoAutorTipo_filter.html
  41. 5
      sapl/templates/base/RelatorioMateriasPorAutor_filter.html
  42. 6
      sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html
  43. 38
      sapl/templates/base/RelatorioReuniao_filter.html
  44. 10
      sapl/templates/base/relatorios_list.html
  45. 3
      sapl/templates/compilacao/text_edit_bloco.html
  46. 34
      sapl/templates/compilacao/text_list_blocoalteracao.html
  47. 10
      sapl/templates/materia/materialegislativa_detail.html
  48. 6
      sapl/templates/norma/normajuridica_filter.html
  49. 4
      sapl/templates/protocoloadm/documentoadministrativo_filter.html
  50. 12
      sapl/templates/sessao/blocos_ata/assinaturas.html
  51. 0
      sapl/templates/sessao/blocos_ata/conteudo_multimidia.html
  52. 9
      sapl/templates/sessao/blocos_ata/expedientes.html
  53. 8
      sapl/templates/sessao/blocos_ata/identificacao_basica.html
  54. 10
      sapl/templates/sessao/blocos_ata/lista_presenca.html
  55. 10
      sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html
  56. 25
      sapl/templates/sessao/blocos_ata/materias_expediente.html
  57. 23
      sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
  58. 10
      sapl/templates/sessao/blocos_ata/mesa_diretora.html
  59. 12
      sapl/templates/sessao/blocos_ata/oradores_expediente.html
  60. 9
      sapl/templates/sessao/blocos_ata/oradores_explicacoes.html
  61. 25
      sapl/templates/sessao/expedientemateria_form.html
  62. 2
      sapl/templates/sessao/layouts.yaml
  63. 2
      sapl/templates/sessao/pauta_sessao_detail.html
  64. 2
      sapl/templates/sessao/pauta_sessao_filter.html
  65. 23
      sapl/templates/sessao/resumo_ata.html
  66. 6
      sapl/templates/sessao/subnav.yaml
  67. 2
      sapl/test_urls.py
  68. 6
      sapl/urls.py
  69. 2
      setup.py

2
Dockerfile

@ -40,7 +40,7 @@ COPY config/env_dockerfile /var/interlegis/sapl/sapl/.env
# compilescss - Precompile all occurrences of your SASS/SCSS files for the whole project into css files # compilescss - Precompile all occurrences of your SASS/SCSS files for the whole project into css files
RUN python3 manage.py bower_install -- --allow-root --no-input && \ RUN python3 manage.py bower_install --allow-root && \
python3 manage.py compilescss python3 manage.py compilescss
RUN python3 manage.py collectstatic --noinput --clear RUN python3 manage.py collectstatic --noinput --clear

2
docker-compose.yml

@ -11,7 +11,7 @@ sapldb:
ports: ports:
- "5432:5432" - "5432:5432"
sapl: sapl:
image: interlegis/sapl:3.1.113 image: interlegis/sapl:3.1.119
restart: always restart: always
environment: environment:
ADMIN_PASSWORD: interlegis ADMIN_PASSWORD: interlegis

2
requirements/dev-requirements.txt

@ -2,7 +2,7 @@
autopep8==1.2.4 autopep8==1.2.4
beautifulsoup4==4.6.0 beautifulsoup4==4.6.0
django-debug-toolbar==1.5 django-debug-toolbar==1.8
ipdb==0.10.1 ipdb==0.10.1
pdbpp==0.9.2 pdbpp==0.9.2
pip-review==0.4 pip-review==0.4

23
requirements/requirements.txt

@ -1,24 +1,21 @@
dj-database-url==0.4.1 dj-database-url==0.4.1
django-haystack==2.6.0 django-haystack==2.6.0
django>=1.9,<1.10 django>=1.10,<1.11
# TODO O django-admin-bootstrapped 2.5.7 não inseriu a mudança que permite git+git://github.com/rubgombar1/django-admin-bootstrapped.git
# a compatibilidade com Django 1.9+. A linha abaixo será mudada quando uma
# nova versão do django-admin-bootstrapped for lançada
git+git://github.com/django-admin-bootstrapped/django-admin-bootstrapped.git
django-bootstrap3==7.0.1 django-bootstrap3==7.0.1
django-bower==5.1.0 django-bower==5.2.0
django-braces==1.9.0 django-braces==1.9.0
django-compressor==2.0 django-compressor==2.0
django-crispy-forms==1.6.0 django-crispy-forms==1.6.1
django-extensions==1.6.7 django-extensions==1.9.8
django-extra-views==0.8.0 django-extra-views==0.11.0
django-filter==0.15.3 django-filter==0.15.3
django-floppyforms==1.6.2 django-floppyforms==1.6.2
django-model-utils==2.5 django-model-utils==3.1.1
django-sass-processor==0.5.4 django-sass-processor==0.5.8
djangorestframework==3.4.0 djangorestframework==3.4.0
drfdocs==0.0.11 git+git://github.com/jasperlittle/django-rest-framework-docs
easy-thumbnails==2.3 easy-thumbnails==2.5
django-image-cropping==1.1.0 django-image-cropping==1.1.0
git+git://github.com/interlegis/trml2pdf.git git+git://github.com/interlegis/trml2pdf.git
libsass==0.11.1 libsass==0.11.1

97
sapl/base/forms.py

@ -18,6 +18,8 @@ from django.utils.translation import string_concat
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column,
to_row) to_row)
from sapl.audiencia.models import AudienciaPublica,TipoAudienciaPublica
from sapl.comissoes.models import Reuniao, Comissao
from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao) from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao)
from sapl.parlamentares.models import SessaoLegislativa from sapl.parlamentares.models import SessaoLegislativa
from sapl.sessao.models import SessaoPlenaria from sapl.sessao.models import SessaoPlenaria
@ -169,15 +171,15 @@ class SessaoLegislativaForm(ModelForm):
if not self.is_valid(): if not self.is_valid():
return cleaned_data return cleaned_data
flag_edit = True
data_inicio = cleaned_data['data_inicio'] data_inicio = cleaned_data['data_inicio']
data_fim = cleaned_data['data_fim'] data_fim = cleaned_data['data_fim']
legislatura = cleaned_data['legislatura'] legislatura = cleaned_data['legislatura']
numero = cleaned_data['numero'] numero = cleaned_data['numero']
data_inicio_leg = legislatura.data_inicio data_inicio_leg = legislatura.data_inicio
data_fim_leg = legislatura.data_fim data_fim_leg = legislatura.data_fim
pk = self.initial['id'] pk = self.initial['id'] if self.initial else None
# Queries para verificar se existem Sessões Legislativas no período selecionado no form
# Querys para verificar se existem Sessões Legislativas no período selecionado no form
# Caso onde a data_inicio e data_fim são iguais a de alguma sessão já criada # Caso onde a data_inicio e data_fim são iguais a de alguma sessão já criada
primeiro_caso = Q(data_inicio=data_inicio, data_fim=data_fim) primeiro_caso = Q(data_inicio=data_inicio, data_fim=data_fim)
# Caso onde a data_inicio está entre o início e o fim de uma Sessão já existente # Caso onde a data_inicio está entre o início e o fim de uma Sessão já existente
@ -192,22 +194,24 @@ class SessaoLegislativaForm(ModelForm):
'inserida, favor verificar as Sessões existentes antes de criar uma ' 'inserida, favor verificar as Sessões existentes antes de criar uma '
'nova Sessão Legislativa') 'nova Sessão Legislativa')
sessoes_legislativas = SessaoLegislativa.objects.filter(legislatura=legislatura).exclude(pk=pk) #sessoes_legislativas = SessaoLegislativa.objects.filter(legislatura=legislatura).exclude(pk=pk)
if sessoes_legislativas: # if sessoes_legislativas:
numeracoes = [n.numero for n in sessoes_legislativas] # numeracoes = [n.numero for n in sessoes_legislativas]
numeracoes = sorted(numeracoes) # numeracoes = sorted(numeracoes)
ult = max(numeracoes) # ult = max(numeracoes)
#
# else:
# ult = SessaoLegislativa.objects.latest('data_fim')
# flag_edit = ult.id != pk
# ult = ult.numero
else: ult = 0
ult = SessaoLegislativa.objects.latest('data_fim')
ult = ult.numero
if numero <= ult: if numero <= ult and flag_edit:
raise ValidationError('O número da Sessão Legislativa não pode ser menor ou igual ' raise ValidationError('O número da Sessão Legislativa não pode ser menor ou igual '
'que o de Sessões Legislativas passadas') 'que o de Sessões Legislativas passadas')
if data_inicio < data_inicio_leg or \ if data_inicio < data_inicio_leg or \
data_inicio > data_fim_leg: data_inicio > data_fim_leg:
raise ValidationError('A data de início da Sessão Legislativa deve estar compreendida ' raise ValidationError('A data de início da Sessão Legislativa deve estar compreendida '
@ -233,11 +237,10 @@ class SessaoLegislativaForm(ModelForm):
if data_inicio_intervalo < data_inicio or \ if data_inicio_intervalo < data_inicio or \
data_inicio_intervalo < data_inicio_leg or \ data_inicio_intervalo < data_inicio_leg or \
data_inicio_intervalo > data_fim or \ data_inicio_intervalo > data_fim or \
data_inicio_intervalo > data_inicio_leg: data_inicio_intervalo > data_fim_leg:
raise ValidationError('A data de início do intervalo deve estar compreendida entre ' raise ValidationError('A data de início do intervalo deve estar compreendida entre '
'as datas de início e fim tanto da Legislatura quanto da ' 'as datas de início e fim tanto da Legislatura quanto da '
'própria Sessão Legislativa') 'própria Sessão Legislativa')
if data_fim_intervalo: if data_fim_intervalo:
if data_fim_intervalo > data_fim or \ if data_fim_intervalo > data_fim or \
data_fim_intervalo > data_fim_leg or \ data_fim_intervalo > data_fim_leg or \
@ -729,6 +732,67 @@ class RelatorioDataFimPrazoTramitacaoFilterSet(django_filters.FilterSet):
) )
class RelatorioReuniaoFilterSet(django_filters.FilterSet):
@property
def qs(self):
parent = super(RelatorioReuniaoFilterSet, self).qs
return parent.distinct().order_by('-data', 'comissao')
class Meta:
model = Reuniao
fields = ['comissao', 'data',
'nome','tema']
def __init__(self, *args, **kwargs):
super(RelatorioReuniaoFilterSet, self).__init__(
*args, **kwargs)
row1 = to_row([('data', 12)])
row2 = to_row(
[('comissao', 4),
('nome', 4),
('tema', 4)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Reunião de Comissão'),
row1, row2,
form_actions(label='Pesquisar'))
)
class RelatorioAudienciaFilterSet(django_filters.FilterSet):
@property
def qs(self):
parent = super(RelatorioAudienciaFilterSet, self).qs
return parent.distinct().order_by('-data', 'tipo')
class Meta:
model = AudienciaPublica
fields = ['tipo', 'data',
'nome']
def __init__(self, *args, **kwargs):
super(RelatorioAudienciaFilterSet, self).__init__(
*args, **kwargs)
row1 = to_row([('data', 12)])
row2 = to_row(
[('tipo', 4),
('nome', 4)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Audiência Pública'),
row1, row2,
form_actions(label='Pesquisar'))
)
class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet): class RelatorioMateriasTramitacaoilterSet(django_filters.FilterSet):
ano = django_filters.ChoiceFilter(required=True, ano = django_filters.ChoiceFilter(required=True,
@ -814,7 +878,8 @@ class RelatorioMateriasPorAutorFilterSet(django_filters.FilterSet):
@property @property
def qs(self): def qs(self):
parent = super(RelatorioMateriasPorAutorFilterSet, self).qs parent = super(RelatorioMateriasPorAutorFilterSet, self).qs
return parent.distinct().filter(autoria__primeiro_autor=True).order_by('autoria__autor', '-autoria__primeiro_autor', 'tipo', '-ano', '-numero') return parent.distinct().filter(autoria__primeiro_autor=True)\
.order_by('autoria__autor', '-autoria__primeiro_autor', 'tipo', '-ano', '-numero')
class Meta: class Meta:
model = MateriaLegislativa model = MateriaLegislativa

8
sapl/base/tests/teststub_urls.py

@ -1,11 +1,9 @@
from django.conf.urls import patterns, url from django.conf.urls import url
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from sapl.urls import urlpatterns as original_patterns from sapl.urls import urlpatterns as original_patterns
ptrn = patterns('', ptrn = [url(r'^zzzz$',
url(r'^zzzz$',
TemplateView.as_view( TemplateView.as_view(
template_name='index.html'), name='zzzz')) template_name='index.html'), name='zzzz')]
urlpatterns = original_patterns + ptrn urlpatterns = original_patterns + ptrn

12
sapl/base/urls.py

@ -16,12 +16,14 @@ from .forms import LoginForm, NovaSenhaForm, RecuperarSenhaForm
from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
CreateUsuarioView, DeleteUsuarioView, EditUsuarioView, CreateUsuarioView, DeleteUsuarioView, EditUsuarioView,
HelpTopicView, ListarUsuarioView, LogotipoView, HelpTopicView, ListarUsuarioView, LogotipoView,
RelatorioAtasView, RelatorioDataFimPrazoTramitacaoView, RelatorioAtasView, RelatorioAudienciaView,
RelatorioDataFimPrazoTramitacaoView,
RelatorioHistoricoTramitacaoView, RelatorioHistoricoTramitacaoView,
RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAnoAutorTipoView,
RelatorioMateriasPorAutorView, RelatorioMateriasPorAutorView,
RelatorioMateriasTramitacaoView, RelatorioMateriasTramitacaoView,
RelatorioPresencaSessaoView, SaplSearchView) RelatorioPresencaSessaoView,
RelatorioReuniaoView, SaplSearchView)
app_name = AppConfig.name app_name = AppConfig.name
@ -104,6 +106,12 @@ urlpatterns = [
url(r'^sistema/relatorios/atas$', url(r'^sistema/relatorios/atas$',
RelatorioAtasView.as_view(), RelatorioAtasView.as_view(),
name='atas'), name='atas'),
url(r'^sistema/relatorios/reuniao$',
RelatorioReuniaoView.as_view(),
name='reuniao'),
url(r'^sistema/relatorios/audiencia$',
RelatorioAudienciaView.as_view(),
name='audiencia'),
url(r'^email/validate/(?P<uidb64>[0-9A-Za-z_\-]+)/' url(r'^email/validate/(?P<uidb64>[0-9A-Za-z_\-]+)/'
'(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})$', '(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})$',

153
sapl/base/views.py

@ -25,8 +25,10 @@ from sapl import settings
from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.crud.base import CrudAux, make_pagination from sapl.crud.base import CrudAux, make_pagination
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica
from sapl.comissoes.models import Reuniao, Comissao
from sapl.materia.models import (Autoria, MateriaLegislativa, from sapl.materia.models import (Autoria, MateriaLegislativa,
TipoMateriaLegislativa) TipoMateriaLegislativa, StatusTramitacao, UnidadeTramitacao)
from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca) SessaoPlenariaPresenca)
from sapl.utils import (parlamentares_ativos, sapl_logger, from sapl.utils import (parlamentares_ativos, sapl_logger,
@ -34,12 +36,14 @@ from sapl.utils import (parlamentares_ativos, sapl_logger,
from .forms import (AlterarSenhaForm, CasaLegislativaForm, from .forms import (AlterarSenhaForm, CasaLegislativaForm,
ConfiguracoesAppForm, RelatorioAtasFilterSet, ConfiguracoesAppForm, RelatorioAtasFilterSet,
RelatorioAudienciaFilterSet,
RelatorioDataFimPrazoTramitacaoFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet,
RelatorioHistoricoTramitacaoFilterSet, RelatorioHistoricoTramitacaoFilterSet,
RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet,
RelatorioMateriasPorAutorFilterSet, RelatorioMateriasPorAutorFilterSet,
RelatorioMateriasTramitacaoilterSet, RelatorioMateriasTramitacaoilterSet,
RelatorioPresencaSessaoFilterSet, UsuarioCreateForm, RelatorioPresencaSessaoFilterSet,
RelatorioReuniaoFilterSet, UsuarioCreateForm,
UsuarioEditForm) UsuarioEditForm)
from .models import AppConfig, CasaLegislativa from .models import AppConfig, CasaLegislativa
@ -262,6 +266,9 @@ class RelatorioAtasView(FilterView):
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
context['periodo'] = (
self.request.GET['data_inicio_0'] +
' - ' + self.request.GET['data_inicio_1'])
return context return context
@ -370,10 +377,29 @@ class RelatorioHistoricoTramitacaoView(FilterView):
context = super(RelatorioHistoricoTramitacaoView, context = super(RelatorioHistoricoTramitacaoView,
self).get_context_data(**kwargs) self).get_context_data(**kwargs)
context['title'] = _('Histórico de Tramitações') context['title'] = _('Histórico de Tramitações')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy() qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
context['data_tramitacao'] = (self.request.GET['tramitacao__data_tramitacao_0'] + ' - ' +
self.request.GET['tramitacao__data_tramitacao_1'])
if self.request.GET['tipo']:
tipo = self.request.GET['tipo']
context['tipo'] = (str(TipoMateriaLegislativa.objects.get(id=tipo)))
else:
context['tipo'] = ''
if self.request.GET['tramitacao__status']:
tramitacao_status = self.request.GET['tramitacao__status']
context['tramitacao__status'] = (str(StatusTramitacao.objects.get(id=tramitacao_status)))
else:
context['tramitacao__status'] = ''
if self.request.GET['tramitacao__unidade_tramitacao_local']:
context['tramitacao__unidade_tramitacao_local'] = \
(str(UnidadeTramitacao.objects.get(id=self.request.GET['tramitacao__unidade_tramitacao_local'])))
else:
context['tramitacao__unidade_tramitacao_destino'] = ''
return context return context
@ -387,14 +413,99 @@ class RelatorioDataFimPrazoTramitacaoView(FilterView):
context = super(RelatorioDataFimPrazoTramitacaoView, context = super(RelatorioDataFimPrazoTramitacaoView,
self).get_context_data(**kwargs) self).get_context_data(**kwargs)
context['title'] = _('Fim de Prazo de Tramitações') context['title'] = _('Fim de Prazo de Tramitações')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
context['data_tramitacao'] = (self.request.GET['tramitacao__data_fim_prazo_0'] + ' - ' +
self.request.GET['tramitacao__data_fim_prazo_1'])
if self.request.GET['tipo']:
tipo = self.request.GET['tipo']
context['tipo'] = (str(TipoMateriaLegislativa.objects.get(id=tipo)))
else:
context['tipo'] = ''
if self.request.GET['tramitacao__status']:
tramitacao_status = self.request.GET['tramitacao__status']
context['tramitacao__status'] = (str(StatusTramitacao.objects.get(id=tramitacao_status)))
else:
context['tramitacao__status'] = ''
if self.request.GET['tramitacao__unidade_tramitacao_local']:
context['tramitacao__unidade_tramitacao_local'] = \
(str(UnidadeTramitacao.objects.get(id=self.request.GET['tramitacao__unidade_tramitacao_local'])))
else:
context['tramitacao__unidade_tramitacao_destino'] = ''
return context
class RelatorioReuniaoView(FilterView):
model = Reuniao
filterset_class = RelatorioReuniaoFilterSet
template_name = 'base/RelatorioReuniao_filter.html'
def get_filterset_kwargs(self, filterset_class):
super(RelatorioReuniaoView,
self).get_filterset_kwargs(filterset_class)
kwargs = {'data': self.request.GET or None}
return kwargs
def get_context_data(self, **kwargs):
context = super(RelatorioReuniaoView,
self).get_context_data(**kwargs)
context['title'] = _('Reunião de Comissão')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
if self.request.GET['comissao']:
comissao = self.request.GET['comissao']
context['comissao'] = (str(Comissao.objects.get(id=comissao)))
else:
context['comissao'] = ''
return context
class RelatorioAudienciaView(FilterView):
model = AudienciaPublica
filterset_class = RelatorioAudienciaFilterSet
template_name = 'base/RelatorioAudiencia_filter.html'
def get_filterset_kwargs(self, filterset_class):
super(RelatorioAudienciaView,
self).get_filterset_kwargs(filterset_class)
kwargs = {'data': self.request.GET or None}
return kwargs
def get_context_data(self, **kwargs):
context = super(RelatorioAudienciaView,
self).get_context_data(**kwargs)
context['title'] = _('Audiência Pública')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy() qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
if self.request.GET['tipo']:
tipo = self.request.GET['tipo']
context['tipo'] = (str(TipoAudienciaPublica.objects.get(id=tipo)))
else:
context['tipo'] = ''
return context return context
class RelatorioMateriasTramitacaoView(FilterView): class RelatorioMateriasTramitacaoView(FilterView):
model = MateriaLegislativa model = MateriaLegislativa
filterset_class = RelatorioMateriasTramitacaoilterSet filterset_class = RelatorioMateriasTramitacaoilterSet
@ -405,6 +516,8 @@ class RelatorioMateriasTramitacaoView(FilterView):
self).get_context_data(**kwargs) self).get_context_data(**kwargs)
context['title'] = _('Matérias em Tramitação') context['title'] = _('Matérias em Tramitação')
if not self.filterset.form.is_valid():
return context
qr = self.request.GET.copy() qr = self.request.GET.copy()
qs = context['object_list'] qs = context['object_list']
@ -424,7 +537,22 @@ class RelatorioMateriasTramitacaoView(FilterView):
if qtde > 0: if qtde > 0:
qtdes[tipo] = qtde qtdes[tipo] = qtde
context['qtdes'] = qtdes context['qtdes'] = qtdes
context['ano'] = (self.request.GET['ano'])
if self.request.GET['tipo']:
tipo = self.request.GET['tipo']
context['tipo'] = (str(TipoMateriaLegislativa.objects.get(id=tipo)))
else:
context['tipo'] = ''
if self.request.GET['tramitacao__status']:
tramitacao_status = self.request.GET['tramitacao__status']
context['tramitacao__status'] = (str(StatusTramitacao.objects.get(id=tramitacao_status)))
else:
context['tramitacao__status'] = ''
if self.request.GET['tramitacao__unidade_tramitacao_destino']:
context['tramitacao__unidade_tramitacao_destino'] = (str(UnidadeTramitacao.objects.get(id=
self.request.GET['tramitacao__unidade_tramitacao_destino'])))
else:
context['tramitacao__unidade_tramitacao_destino'] = ''
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
@ -489,7 +617,8 @@ class RelatorioMateriasPorAnoAutorTipoView(FilterView):
self).get_context_data(**kwargs) self).get_context_data(**kwargs)
context['title'] = _('Matérias por Ano, Autor e Tipo') context['title'] = _('Matérias por Ano, Autor e Tipo')
if not self.filterset.form.is_valid():
return context
qtdes = {} qtdes = {}
for tipo in TipoMateriaLegislativa.objects.all(): for tipo in TipoMateriaLegislativa.objects.all():
qs = kwargs['object_list'] qs = kwargs['object_list']
@ -502,6 +631,7 @@ class RelatorioMateriasPorAnoAutorTipoView(FilterView):
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
context['ano'] = self.request.GET['ano']
if 'ano' in self.request.GET and self.request.GET['ano']: if 'ano' in self.request.GET and self.request.GET['ano']:
ano = int(self.request.GET['ano']) ano = int(self.request.GET['ano'])
@ -530,6 +660,8 @@ class RelatorioMateriasPorAutorView(FilterView):
self).get_context_data(**kwargs) self).get_context_data(**kwargs)
context['title'] = _('Matérias por Autor') context['title'] = _('Matérias por Autor')
if not self.filterset.form.is_valid():
return context
qtdes = {} qtdes = {}
for tipo in TipoMateriaLegislativa.objects.all(): for tipo in TipoMateriaLegislativa.objects.all():
@ -543,6 +675,19 @@ class RelatorioMateriasPorAutorView(FilterView):
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr) context['show_results'] = show_results_filter_set(qr)
if self.request.GET['tipo']:
tipo = int(self.request.GET['tipo'])
context['tipo'] = (str(TipoMateriaLegislativa.objects.get(id=tipo)))
else:
context['tipo'] = ''
if self.request.GET['autoria__autor']:
autor = int(self.request.GET['autoria__autor'])
context['autor'] = (str(Autor.objects.get(id=autor)))
else:
context['autor'] = ''
context['periodo'] = (
self.request.GET['data_apresentacao_0'] +
' - ' + self.request.GET['data_apresentacao_1'])
return context return context

11
sapl/comissoes/forms.py

@ -64,9 +64,14 @@ class PeriodoForm(forms.ModelForm):
if data_fim and data_fim < data_inicio: if data_fim and data_fim < data_inicio:
raise ValidationError('A Data Final não pode ser menor que ' raise ValidationError('A Data Final não pode ser menor que '
'a Data Inicial') 'a Data Inicial')
legislatura = Legislatura.objects.filter(data_inicio__lte=data_inicio, # Evita NoneType exception se não preenchida a data_fim
data_fim__gte=data_fim) if not data_fim:
data_fim = data_inicio
legislatura = Legislatura.objects.filter(data_inicio__lte=data_inicio,
data_fim__gte=data_fim,
)
if not legislatura: if not legislatura:
raise ValidationError('O período informado ' raise ValidationError('O período informado '

2
sapl/comissoes/models.py

@ -111,6 +111,8 @@ class Periodo(models.Model): # PeriodoCompComissao
if self.data_inicio and self.data_fim: if self.data_inicio and self.data_fim:
return '%s - %s' % (self.data_inicio.strftime("%d/%m/%Y"), return '%s - %s' % (self.data_inicio.strftime("%d/%m/%Y"),
self.data_fim.strftime("%d/%m/%Y")) self.data_fim.strftime("%d/%m/%Y"))
elif self.data_inicio and not self.data_fim:
return '%s - ' % self.data_inicio.strftime("%d/%m/%Y")
else: else:
return '-' return '-'

1
sapl/comissoes/tests/test_comissoes.py

@ -74,6 +74,7 @@ def test_incluir_comissao_submit(admin_client):
'nome': 'Comissão Teste', 'nome': 'Comissão Teste',
'sigla': 'CT', 'sigla': 'CT',
'data_criacao': '2016-03-22', 'data_criacao': '2016-03-22',
'unidade_deliberativa': True,
'salvar': 'salvar'}, 'salvar': 'salvar'},
follow=True) follow=True)
assert response.status_code == 200 assert response.status_code == 200

2
sapl/compilacao/compilacao_data_tables.sql

@ -260,6 +260,8 @@ INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id,
INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id, filho_de_insercao_automatica, perfil_id, quantidade_permitida, permitir_variacao) VALUES (122, 119, false, 1, -1, false); INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id, filho_de_insercao_automatica, perfil_id, quantidade_permitida, permitir_variacao) VALUES (122, 119, false, 1, -1, false);
INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id, filho_de_insercao_automatica, perfil_id, quantidade_permitida, permitir_variacao) VALUES (122, 119, false, 2, -1, true); INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id, filho_de_insercao_automatica, perfil_id, quantidade_permitida, permitir_variacao) VALUES (122, 119, false, 2, -1, true);
INSERT INTO compilacao_tipodispositivorelationship (filho_permitido_id, pai_id, filho_de_insercao_automatica, perfil_id, quantidade_permitida, permitir_variacao) VALUES (3, 125, false, 3, -1, false);
INSERT INTO compilacao_tiponota (id, sigla, nome, modelo) VALUES (1, 'NE', 'Nota Explicativa', ''); INSERT INTO compilacao_tiponota (id, sigla, nome, modelo) VALUES (1, 'NE', 'Nota Explicativa', '');

35
sapl/compilacao/migrations/0007_auto_20180911_1600.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-21 13:54
from __future__ import unicode_literals
from django.db import migrations, models
def insert_relacionamento_entre_dispositivos(apps, schema_editor):
TipoDispositivoRelationship = apps.get_model(
'compilacao', 'TipoDispositivoRelationship')
try:
if TipoDispositivoRelationship.objects.exists():
rel = TipoDispositivoRelationship()
rel.filho_permitido_id = 3
rel.pai_id = 125
rel.filho_de_insercao_automatica = False
rel.perfil_id = 3
rel.quantidade_permitida = -1
rel.permitir_variacao = False
rel.save()
except:
pass
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0006_auto_20180321_1054'),
]
operations = [
migrations.RunPython(insert_relacionamento_entre_dispositivos),
]

11
sapl/crud/base.py

@ -17,8 +17,8 @@ from django.http.response import Http404
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.decorators import classonlymethod from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (CreateView, DeleteView, DetailView, ListView, from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
UpdateView) UpdateView)
from django.views.generic.base import ContextMixin from django.views.generic.base import ContextMixin
@ -30,6 +30,7 @@ from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL,
from sapl.settings import BASE_DIR from sapl.settings import BASE_DIR
from sapl.utils import normalize from sapl.utils import normalize
logger = logging.getLogger(BASE_DIR.name) logger = logging.getLogger(BASE_DIR.name)
ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \ ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \
@ -411,10 +412,13 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
m = self.model m = self.model
fn = fn.split('__') fn = fn.split('__')
for f in fn: for f in fn:
if not f:
continue
f = m._meta.get_field(f) f = m._meta.get_field(f)
if hasattr(f, 'related_model') and f.related_model: if hasattr(f, 'related_model') and f.related_model:
m = f.related_model m = f.related_model
s.append(force_text(f.verbose_name)) if f:
s.append(force_text(f.verbose_name))
s = ' / '.join(s) s = ' / '.join(s)
r.append(s) r.append(s)
return r return r
@ -440,6 +444,9 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
if isinstance(name, tuple): if isinstance(name, tuple):
s = '' s = ''
for j, n in enumerate(name): for j, n in enumerate(name):
if not n:
s += '<br>'
continue
m = obj m = obj
n = n.split('__') n = n.split('__')
for f in n[:-1]: for f in n[:-1]:

5
sapl/materia/forms.py

@ -676,7 +676,8 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet):
widget=forms.HiddenInput()) widget=forms.HiddenInput())
ementa = django_filters.CharFilter(lookup_expr='icontains') ementa = django_filters.CharFilter(lookup_expr='icontains')
indexacao = django_filters.CharFilter(lookup_expr='icontains') indexacao = django_filters.CharFilter(lookup_expr='icontains',
label=_('Indexação'))
em_tramitacao = django_filters.ChoiceFilter(required=False, em_tramitacao = django_filters.ChoiceFilter(required=False,
label='Em tramitação', label='Em tramitação',
@ -1160,7 +1161,7 @@ class TipoProposicaoSelect(Select):
str(data_has_perfil), str(data_has_perfil),
force_text(option_label)) force_text(option_label))
def render_options(self, choices, selected_choices): def render_options(self, selected_choices):
# Normalize to strings. # Normalize to strings.
selected_choices = set(force_text(v) for v in selected_choices) selected_choices = set(force_text(v) for v in selected_choices)
output = [] output = []

21
sapl/materia/migrations/0030_tramitacao_timestamp.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-09-18 12:13
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('materia', '0029_auto_20180901_1628'),
]
operations = [
migrations.AddField(
model_name='tramitacao',
name='timestamp',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

3
sapl/materia/models.py

@ -908,6 +908,9 @@ class Tramitacao(models.Model):
null=True, null=True,
verbose_name=_('Status')) verbose_name=_('Status'))
materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE) materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE)
# TODO: Remover os campos de data
# TODO: pois timestamp supre a necessidade
timestamp = models.DateTimeField(default=timezone.now)
data_tramitacao = models.DateField(verbose_name=_('Data Tramitação')) data_tramitacao = models.DateField(verbose_name=_('Data Tramitação'))
unidade_tramitacao_local = models.ForeignKey( unidade_tramitacao_local = models.ForeignKey(
UnidadeTramitacao, UnidadeTramitacao,

23
sapl/materia/views.py

@ -744,6 +744,10 @@ class ProposicaoCrud(Crud):
% (p.tipo, numero, p.ano))) % (p.tipo, numero, p.ano)))
except ValueError: except ValueError:
pass pass
except AttributeError:
pass
except TypeError:
pass
elif action == 'return': elif action == 'return':
if not p.data_envio: if not p.data_envio:
@ -1076,6 +1080,7 @@ class TramitacaoCrud(MasterDetailCrud):
ultima_tramitacao = Tramitacao.objects.filter( ultima_tramitacao = Tramitacao.objects.filter(
materia_id=self.kwargs['pk']).order_by( materia_id=self.kwargs['pk']).order_by(
'-data_tramitacao', '-data_tramitacao',
'-timestamp',
'-id').first() '-id').first()
if ultima_tramitacao: if ultima_tramitacao:
@ -1146,6 +1151,7 @@ class TramitacaoCrud(MasterDetailCrud):
qs = super(MasterDetailCrud.ListView, self).get_queryset() qs = super(MasterDetailCrud.ListView, self).get_queryset()
kwargs = {self.crud.parent_field: self.kwargs['pk']} kwargs = {self.crud.parent_field: self.kwargs['pk']}
return qs.filter(**kwargs).order_by('-data_tramitacao', return qs.filter(**kwargs).order_by('-data_tramitacao',
'-timestamp',
'-id') '-id')
class DeleteView(MasterDetailCrud.DeleteView): class DeleteView(MasterDetailCrud.DeleteView):
@ -1158,6 +1164,7 @@ class TramitacaoCrud(MasterDetailCrud):
ultima_tramitacao = materia.tramitacao_set.order_by( ultima_tramitacao = materia.tramitacao_set.order_by(
'-data_tramitacao', '-data_tramitacao',
'-timestamp',
'-id').first() '-id').first()
if tramitacao.pk != ultima_tramitacao.pk: if tramitacao.pk != ultima_tramitacao.pk:
@ -1843,7 +1850,7 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
# issue https://github.com/interlegis/sapl/issues/1123 # issue https://github.com/interlegis/sapl/issues/1123
# TODO: usar Form # TODO: usar Form
urgente = request.POST['urgente'] == 'True' urgente = request.POST['urgente'] == 'True'
flag_error = False
for materia_id in marcadas: for materia_id in marcadas:
t = Tramitacao( t = Tramitacao(
materia_id=materia_id, materia_id=materia_id,
@ -1861,9 +1868,17 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
texto=request.POST['texto'] texto=request.POST['texto']
) )
t.save() t.save()
tramitacao_signal.send(sender=Tramitacao, try:
post=t, tramitacao_signal.send(sender=Tramitacao,
request=self.request) post=t,
request=self.request)
except Exception:
flag_error = True
if flag_error:
msg = _('Tramitação criada, mas e-mail de acompanhamento '
'de matéria não enviado. Há problemas na configuração '
'do e-mail.')
messages.add_message(self.request, messages.ERROR, msg)
status = StatusTramitacao.objects.get(id=request.POST['status']) status = StatusTramitacao.objects.get(id=request.POST['status'])

8
sapl/norma/forms.py

@ -52,6 +52,9 @@ class NormaFilterSet(django_filters.FilterSet):
ementa = django_filters.CharFilter(lookup_expr='icontains') ementa = django_filters.CharFilter(lookup_expr='icontains')
indexacao = django_filters.CharFilter(lookup_expr='icontains',
label=_('Indexação'))
assuntos = django_filters.ModelChoiceFilter( assuntos = django_filters.ModelChoiceFilter(
queryset=AssuntoNorma.objects.all()) queryset=AssuntoNorma.objects.all())
@ -67,13 +70,14 @@ 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), ('o',6)]) row3 = to_row([('ementa', 6), ('assuntos', 6)])
row4 = to_row([('o',6), ('indexacao', 6)])
self.form.helper = FormHelper() self.form.helper = FormHelper()
self.form.helper.form_method = 'GET' self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout( self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Norma'), Fieldset(_('Pesquisa de Norma'),
row1, row2, row3, row1, row2, row3, row4,
form_actions(label='Pesquisar')) form_actions(label='Pesquisar'))
) )

1
sapl/norma/views.py

@ -236,6 +236,7 @@ class NormaCrud(Crud):
initial['tipo_materia'] = norma.materia.tipo initial['tipo_materia'] = norma.materia.tipo
initial['ano_materia'] = norma.materia.ano initial['ano_materia'] = norma.materia.ano
initial['numero_materia'] = norma.materia.numero initial['numero_materia'] = norma.materia.numero
initial['esfera_federacao'] = norma.esfera_federacao
return initial return initial

30
sapl/protocoloadm/forms.py

@ -304,15 +304,15 @@ class ProtocoloDocumentForm(ModelForm):
numero_paginas = forms.CharField(label=_('Núm. Páginas'), required=True) numero_paginas = forms.CharField(label=_('Núm. Páginas'), required=True)
assunto = forms.CharField( assunto = forms.CharField(
widget=forms.Textarea, label='Assunto', required=True) widget=forms.Textarea, label=_('Assunto'), required=True)
interessado = forms.CharField(required=True, interessado = forms.CharField(required=True,
label='Interessado') label=_('Interessado'))
observacao = forms.CharField(required=False, observacao = forms.CharField(required=False,
widget=forms.Textarea, label='Observação') widget=forms.Textarea, label=_('Observação'))
numero = forms.IntegerField(required=False, label='Número de Protocolo (opcional)') numero = forms.IntegerField(required=False, label=_('Número de Protocolo (opcional)'))
class Meta: class Meta:
model = Protocolo model = Protocolo
@ -394,12 +394,12 @@ class ProtocoloMateriaForm(ModelForm):
numero_paginas = forms.CharField(label=_('Núm. Páginas'), required=True) numero_paginas = forms.CharField(label=_('Núm. Páginas'), required=True)
observacao = forms.CharField(required=False, observacao = forms.CharField(required=False,
widget=forms.Textarea, label='Observação') widget=forms.Textarea, label=_('Observação'))
assunto_ementa = forms.CharField(required=True, assunto_ementa = forms.CharField(required=True,
widget=forms.Textarea, label='Ementa') widget=forms.Textarea, label=_('Ementa'))
numero = forms.IntegerField(required=False, label='Número de Protocolo (opcional)') numero = forms.IntegerField(required=False, label=_('Número de Protocolo (opcional)'))
class Meta: class Meta:
model = Protocolo model = Protocolo
@ -636,6 +636,11 @@ class DocumentoAdministrativoForm(ModelForm):
label=Protocolo._meta. label=Protocolo._meta.
get_field('numero').verbose_name) get_field('numero').verbose_name)
restrito = forms.ChoiceField(label=_('Acesso Restrito'),
widget=forms.RadioSelect(),
choices=YES_NO_CHOICES,
initial=False)
class Meta: class Meta:
model = DocumentoAdministrativo model = DocumentoAdministrativo
fields = ['tipo', fields = ['tipo',
@ -653,6 +658,7 @@ class DocumentoAdministrativoForm(ModelForm):
'observacao', 'observacao',
'texto_integral', 'texto_integral',
'protocolo', 'protocolo',
'restrito'
] ]
widgets = {'protocolo': forms.HiddenInput()} widgets = {'protocolo': forms.HiddenInput()}
@ -682,7 +688,7 @@ class DocumentoAdministrativoForm(ModelForm):
tipo=tipo_documento, tipo=tipo_documento,
ano=ano_protocolo).exists() ano=ano_protocolo).exists()
if doc_exists: if doc_exists:
raise ValidationError('Documento já existente') raise ValidationError(_('Documento já existente'))
# campos opcionais, mas que se informados devem ser válidos # campos opcionais, mas que se informados devem ser válidos
if numero_protocolo and ano_protocolo: if numero_protocolo and ano_protocolo:
@ -740,7 +746,7 @@ class DocumentoAdministrativoForm(ModelForm):
[('assunto', 12)]) [('assunto', 12)])
row4 = to_row( row4 = to_row(
[('interessado', 9), ('tramitacao', 3)]) [('interessado', 8), ('tramitacao', 2), (InlineRadios('restrito'), 2)])
row5 = to_row( row5 = to_row(
[('texto_integral', 12)]) [('texto_integral', 12)])
@ -878,7 +884,7 @@ class DesvincularMateriaForm(forms.Form):
def pega_ultima_tramitacao_adm(): def pega_ultima_tramitacao_adm():
return TramitacaoAdministrativo.objects.values( return TramitacaoAdministrativo.objects.values(
'materia_id').annotate(data_encaminhamento=Max( 'documento_id').annotate(data_encaminhamento=Max(
'data_encaminhamento'), 'data_encaminhamento'),
id=Max('id')).values_list('id', flat=True) id=Max('id')).values_list('id', flat=True)
@ -895,7 +901,7 @@ def filtra_tramitacao_adm_destino(destino):
return TramitacaoAdministrativo.objects.filter( return TramitacaoAdministrativo.objects.filter(
id__in=lista, id__in=lista,
unidade_tramitacao_destino=destino).distinct().values_list( unidade_tramitacao_destino=destino).distinct().values_list(
'materia_id', flat=True) 'documento_id', flat=True)
def filtra_tramitacao_adm_destino_and_status(status, destino): def filtra_tramitacao_adm_destino_and_status(status, destino):
@ -904,4 +910,4 @@ def filtra_tramitacao_adm_destino_and_status(status, destino):
id__in=lista, id__in=lista,
status=status, status=status,
unidade_tramitacao_destino=destino).distinct().values_list( unidade_tramitacao_destino=destino).distinct().values_list(
'materia_id', flat=True) 'documento_id', flat=True)

20
sapl/protocoloadm/migrations/0006_documentoadministrativo_restrito.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-09-10 12:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0005_auto_20180824_1241'),
]
operations = [
migrations.AddField(
model_name='documentoadministrativo',
name='restrito',
field=models.BooleanField(default=False, verbose_name='Acesso Restrito'),
),
]

5
sapl/protocoloadm/models.py

@ -93,7 +93,7 @@ class Protocolo(models.Model):
user_anulacao = models.CharField(max_length=20, blank=True) user_anulacao = models.CharField(max_length=20, blank=True)
ip_anulacao = models.CharField(max_length=15, blank=True) ip_anulacao = models.CharField(max_length=15, blank=True)
justificativa_anulacao = models.CharField( justificativa_anulacao = models.CharField(
max_length=60, blank=True, verbose_name='Motivo') max_length=60, blank=True, verbose_name=_('Motivo'))
timestamp_anulacao = models.DateTimeField(blank=True, null=True) timestamp_anulacao = models.DateTimeField(blank=True, null=True)
class Meta: class Meta:
@ -148,6 +148,9 @@ class DocumentoAdministrativo(models.Model):
null=True, null=True,
upload_to=texto_upload_path, upload_to=texto_upload_path,
verbose_name=_('Texto Integral')) verbose_name=_('Texto Integral'))
restrito = models.BooleanField(default=False,
verbose_name=_('Acesso Restrito'),
blank=True)
class Meta: class Meta:
verbose_name = _('Documento Administrativo') verbose_name = _('Documento Administrativo')

6
sapl/protocoloadm/tests/test_protocoloadm.py

@ -359,8 +359,9 @@ def test_documento_administrativo_invalido():
assert errors['assunto'] == [_('Este campo é obrigatório.')] assert errors['assunto'] == [_('Este campo é obrigatório.')]
assert errors['numero'] == [_('Este campo é obrigatório.')] assert errors['numero'] == [_('Este campo é obrigatório.')]
assert errors['data'] == [_('Este campo é obrigatório.')] assert errors['data'] == [_('Este campo é obrigatório.')]
assert errors['restrito'] == [_('Este campo é obrigatório.')]
assert len(errors) == 5 assert len(errors) == 6
@pytest.mark.django_db(transaction=False) @pytest.mark.django_db(transaction=False)
@ -374,7 +375,8 @@ def test_documento_administrativo_protocolo_inexistente():
'numero': '1', 'numero': '1',
'data': '2017-10-10', 'data': '2017-10-10',
'numero_protocolo': '11', 'numero_protocolo': '11',
'ano_protocolo': '2017' 'ano_protocolo': '2017',
'restrito': False
}) })
assert not form.is_valid() assert not form.is_valid()

22
sapl/protocoloadm/views.py

@ -142,6 +142,13 @@ class DocumentoAdministrativoCrud(Crud):
class DetailView(DocumentoAdministrativoMixin, Crud.DetailView): class DetailView(DocumentoAdministrativoMixin, Crud.DetailView):
def get(self, *args, **kwargs):
pk = self.kwargs['pk']
documento = DocumentoAdministrativo.objects.get(id=pk)
if documento.restrito and self.request.user.is_anonymous():
return redirect('/')
return super(Crud.DetailView, self).get(args, kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
self.layout_display[0]['rows'][-1][0]['text'] = ( self.layout_display[0]['rows'][-1][0]['text'] = (
@ -561,18 +568,19 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin,
kwargs = {'data': self.request.GET or None} kwargs = {'data': self.request.GET or None}
status_tramitacao = self.request.GET.get('tramitacao__status') status_tramitacao = self.request.GET.get(
'tramitacaoadministrativo__status')
unidade_destino = self.request.GET.get( unidade_destino = self.request.GET.get(
'tramitacao__unidade_tramitacao_destino') 'tramitacaoadministrativo__unidade_tramitacao_destino')
qs = self.get_queryset() qs = self.get_queryset()
qs = qs.prefetch_related("documentoacessorioadministrativo_set", qs = qs.prefetch_related("documentoacessorioadministrativo_set",
"tramitacaoadministrativo_set", "tramitacaoadministrativo_set",
"tipo", "tipo",
"tramitacaoadministrativo_set__status", "tramitacaoadministrativo_set__status",
"tramitacaoadministrativo_set__unidade_tramitacao_local", "tramitacaoadministrativo_set__unidade_tramitacao_local",
"tramitacaoadministrativo_set__unidade_tramitacao_destino") "tramitacaoadministrativo_set__unidade_tramitacao_destino")
if status_tramitacao and unidade_destino: if status_tramitacao and unidade_destino:
lista = filtra_tramitacao_adm_destino_and_status(status_tramitacao, lista = filtra_tramitacao_adm_destino_and_status(status_tramitacao,

6
sapl/relatorios/templates/pdf_pauta_sessao_gerar.py

@ -145,10 +145,10 @@ def votacao(lst_votacao):
tmp += '<blockTable style="repeater" repeatRows="1">\n' tmp += '<blockTable style="repeater" repeatRows="1">\n'
tmp += '<tr><td >Matéria</td><td >Ementa</td><td>Situação</td></tr>\n' tmp += '<tr><td >Matéria</td><td >Ementa</td><td>Situação</td></tr>\n'
for votacao in lst_votacao: for votacao in lst_votacao:
tmp += '<tr><td><para style="P3"><b>' + str(votacao['num_ordem']) + '</b> - ' + votacao['id_materia'] + '</para>\n' + '<para style="P3"><b>Processo: </b>' + votacao[ tmp += '<tr><td><para style="P3"><b>' + str(votacao['num_ordem']) + '</b> - ' + str(votacao['id_materia']) + '</para>\n' + '<para style="P3"><b>Processo: </b>' + str(votacao[
'des_numeracao'] + '</para>\n' + '<para style="P3"><b>Turno: </b>' + votacao['des_turno'] + '</para>\n' + '<para style="P3"><b>Autor: </b>' + votacao['nom_autor'] + '</para></td>\n' 'des_numeracao']) + '</para>\n' + '<para style="P3"><b>Turno: </b>' + str(votacao['des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + str(votacao['nom_autor']) + '</para></td>\n'
tmp += '<td><para style="P4">' + \ tmp += '<td><para style="P4">' + \
votacao['txt_ementa'] + '</para></td>\n' str(votacao['txt_ementa']) + '</para></td>\n'
tmp += '<td><para style="P3">' + \ tmp += '<td><para style="P3">' + \
str(votacao['des_situacao']) + '</para></td></tr>\n' str(votacao['des_situacao']) + '</para></td></tr>\n'

2
sapl/relatorios/urls.py

@ -26,6 +26,6 @@ urlpatterns = [
relatorio_protocolo, name='relatorio_protocolo'), relatorio_protocolo, name='relatorio_protocolo'),
url(r'^relatorios/(?P<nro>\d+)/(?P<ano>\d+)/etiqueta-protocolo$', url(r'^relatorios/(?P<nro>\d+)/(?P<ano>\d+)/etiqueta-protocolo$',
relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'), relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'),
url(r'^relatorios/pauta-sessao$', url(r'^relatorios/pauta-sessao/(?P<pk>\d+)/$',
relatorio_pauta_sessao, name='relatorio_pauta_sessao'), relatorio_pauta_sessao, name='relatorio_pauta_sessao'),
] ]

29
sapl/relatorios/views.py

@ -751,6 +751,9 @@ def get_turno(dic, materia, sessao_data_inicio):
'materia__tipo').order_by( 'materia__tipo').order_by(
'-data_tramitacao' '-data_tramitacao'
).first() ).first()
if tramitacao is None:
tramitacao = materia.tramitacao_set.last()
if tramitacao is not None: if tramitacao is not None:
for t in Tramitacao.TURNO_CHOICES: for t in Tramitacao.TURNO_CHOICES:
if t[0] == tramitacao.turno: if t[0] == tramitacao.turno:
@ -986,7 +989,7 @@ def get_etiqueta_protocolos(prots):
return protocolos return protocolos
def relatorio_pauta_sessao(request): def relatorio_pauta_sessao(request, pk):
''' '''
pdf__pauta_sessao_gerar.py pdf__pauta_sessao_gerar.py
''' '''
@ -1002,7 +1005,7 @@ def relatorio_pauta_sessao(request):
rodape = get_rodape(casa) rodape = get_rodape(casa)
imagem = get_imagem(casa) imagem = get_imagem(casa)
sessao = SessaoPlenaria.objects.first() sessao = SessaoPlenaria.objects.get(id=pk)
lst_expediente_materia, lst_votacao, inf_basicas_dic = get_pauta_sessao( lst_expediente_materia, lst_votacao, inf_basicas_dic = get_pauta_sessao(
sessao, casa) sessao, casa)
@ -1087,9 +1090,10 @@ def get_pauta_sessao(sessao, casa):
lst_votacao = [] lst_votacao = []
for votacao in OrdemDia.objects.filter( for votacao in OrdemDia.objects.filter(
data_ordem=sessao.data_inicio, sessao_plenaria=sessao): sessao_plenaria=sessao):
materia = MateriaLegislativa.objects.filter( materia = MateriaLegislativa.objects.filter(
id=votacao.materia.id).first() id=votacao.materia.id).first()
dic_votacao = {} dic_votacao = {}
dic_votacao["num_ordem"] = votacao.numero_ordem dic_votacao["num_ordem"] = votacao.numero_ordem
dic_votacao["id_materia"] = str( dic_votacao["id_materia"] = str(
@ -1098,11 +1102,17 @@ def get_pauta_sessao(sessao, casa):
dic_votacao["ordem_observacao"] = votacao.observacao dic_votacao["ordem_observacao"] = votacao.observacao
dic_votacao["des_numeracao"] = ' ' dic_votacao["des_numeracao"] = ' '
# numeracao = Numeracao.objects.filter(materia=materia)
# if numeracao is not None: numeracao = Numeracao.objects.filter(
# numeracao = numeracao.first() materia=votacao.materia).first()
# dic_votacao["des_numeracao"] = str( if numeracao is not None:
# numeracao.numero_materia) + '/' + str(numeracao.ano_materia) numeracao = numeracao.first()
dic_votacao["des_numeracao"] = str(
numeracao.numero_materia) + '/' + str(numeracao.ano_materia)
turno, tramitacao = get_turno(dic_votacao, materia, sessao.data_inicio)
dic_votacao["des_turno"] = turno
dic_votacao["des_situacao"] = tramitacao
dic_votacao["nom_autor"] = ' ' dic_votacao["nom_autor"] = ' '
autoria = Autoria.objects.filter( autoria = Autoria.objects.filter(
@ -1126,9 +1136,6 @@ def get_pauta_sessao(sessao, casa):
elif autoria is None: elif autoria is None:
dic_votacao["nom_autor"] = 'Desconhecido' dic_votacao["nom_autor"] = 'Desconhecido'
turno, tramitacao = get_turno(dic_expediente_materia, materia, sessao.data_inicio)
dic_votacao["des_turno"] = turno
dic_votacao["des_situacao"] = tramitacao
lst_votacao.append(dic_votacao) lst_votacao.append(dic_votacao)
return (lst_expediente_materia, return (lst_expediente_materia,

29
sapl/sessao/forms.py

@ -1,6 +1,5 @@
from datetime import datetime from datetime import datetime
import django_filters
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Fieldset, Layout from crispy_forms.layout import HTML, Button, Fieldset, Layout
from django import forms from django import forms
@ -9,6 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import transaction from django.db import transaction
from django.forms import ModelForm from django.forms import ModelForm
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, to_row from sapl.crispy_layout_mixin import form_actions, to_row
@ -98,14 +98,12 @@ class SessaoPlenariaForm(ModelForm):
else: # create else: # create
raise error raise error
# Condições da verificação # Condições da verificação
abertura_entre_leg = leg.data_inicio <= abertura <= leg.data_fim abertura_entre_leg = leg.data_inicio <= abertura <= leg.data_fim
abertura_entre_sl = sl.data_inicio <= abertura <= sl.data_fim abertura_entre_sl = sl.data_inicio <= abertura <= sl.data_fim
if encerramento is not None: if encerramento is not None:
encerramento_entre_leg = leg.data_inicio < encerramento < leg.data_fim encerramento_entre_leg = leg.data_inicio <= encerramento <= leg.data_fim
encerramento_entre_sl = sl.data_inicio < encerramento < sl.data_fim encerramento_entre_sl = sl.data_inicio <= encerramento <= sl.data_fim
# Verificação das datas de abertura e encerramento da Sessão # Verificação das datas de abertura e encerramento da Sessão
# Verificações com a data de encerramento preenchidas # Verificações com a data de encerramento preenchidas
if encerramento is not None: if encerramento is not None:
@ -113,7 +111,8 @@ class SessaoPlenariaForm(ModelForm):
if encerramento < abertura: if encerramento < abertura:
raise ValidationError("A data de encerramento não pode ser " raise ValidationError("A data de encerramento não pode ser "
"anterior a data de abertura.") "anterior a data de abertura.")
# Verifica se a data de abertura está entre a data de início e fim da legislatura # Verifica se a data de abertura está entre a data de início e fim
# da legislatura
if abertura_entre_leg and encerramento_entre_leg: if abertura_entre_leg and encerramento_entre_leg:
if abertura_entre_sl and encerramento_entre_sl: if abertura_entre_sl and encerramento_entre_sl:
pass pass
@ -165,7 +164,6 @@ class SessaoPlenariaForm(ModelForm):
"datas de início e fim tanto Legislatura " "datas de início e fim tanto Legislatura "
"quanto da Sessão Legislativa.") "quanto da Sessão Legislativa.")
# Verificações com a data de encerramento vazia # Verificações com a data de encerramento vazia
else: else:
if abertura_entre_leg: if abertura_entre_leg:
@ -424,7 +422,7 @@ class VotacaoForm(forms.Form):
class VotacaoNominalForm(forms.Form): class VotacaoNominalForm(forms.Form):
resultado_votacao = forms.ModelChoiceField(label='Resultado da Votação', resultado_votacao = forms.ModelChoiceField(label='Resultado da Votação',
required=True, required=False,
queryset=TipoResultadoVotacao.objects.all()) queryset=TipoResultadoVotacao.objects.all())
@ -455,7 +453,6 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
# pré-popula o campo do formulário com o ano corrente # pré-popula o campo do formulário com o ano corrente
self.form.fields['data_inicio__year'].initial = timezone.now().year self.form.fields['data_inicio__year'].initial = timezone.now().year
row1 = to_row( row1 = to_row(
[('data_inicio__year', 3), [('data_inicio__year', 3),
('data_inicio__month', 3), ('data_inicio__month', 3),
@ -570,13 +567,14 @@ class OradorExpedienteForm(ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(OradorExpedienteForm, self).__init__(*args, **kwargs) super(OradorExpedienteForm, self).__init__(*args, **kwargs)
legislatura_vigente = SessaoPlenaria.objects.get(pk=kwargs['initial']['id_sessao']).legislatura legislatura_vigente = SessaoPlenaria.objects.get(
pk=kwargs['initial']['id_sessao']).legislatura
if legislatura_vigente: if legislatura_vigente:
self.fields['parlamentar'].queryset = \ self.fields['parlamentar'].queryset = \
Parlamentar.objects.filter(ativo=True, Parlamentar.objects.filter(ativo=True,
mandato__legislatura=legislatura_vigente mandato__legislatura=legislatura_vigente
).order_by('nome_parlamentar') ).order_by('nome_parlamentar')
def clean(self): def clean(self):
super(OradorExpedienteForm, self).clean() super(OradorExpedienteForm, self).clean()
@ -586,11 +584,11 @@ class OradorExpedienteForm(ModelForm):
return self.cleaned_data return self.cleaned_data
sessao_id = self.initial['id_sessao'] sessao_id = self.initial['id_sessao']
numero = self.initial.get('numero') # Retorna None se inexistente numero = self.initial.get('numero') # Retorna None se inexistente
ordem = OradorExpediente.objects.filter( ordem = OradorExpediente.objects.filter(
sessao_plenaria_id=sessao_id, sessao_plenaria_id=sessao_id,
numero_ordem=cleaned_data['numero_ordem'] numero_ordem=cleaned_data['numero_ordem']
).exists() ).exists()
if ordem and (cleaned_data['numero_ordem'] != numero): if ordem and (cleaned_data['numero_ordem'] != numero):
raise ValidationError(_( raise ValidationError(_(
@ -598,7 +596,6 @@ class OradorExpedienteForm(ModelForm):
return self.cleaned_data return self.cleaned_data
class Meta: class Meta:
model = OradorExpediente model = OradorExpediente
exclude = ['sessao_plenaria'] exclude = ['sessao_plenaria']

37
sapl/sessao/migrations/0023_auto_20180914_1315.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-09-14 16:15
from __future__ import unicode_literals
from django.db import migrations, models
def limpa_observacao_igual_ementa(apps, schema_editor):
ExpedienteMateria = apps.get_model('sessao', 'ExpedienteMateria')
OrdemDia = apps.get_model('sessao', 'OrdemDia')
q = models.Q(observacao__iexact=models.F('materia__ementa'))
ExpedienteMateria.objects.filter(q).update(observacao='')
OrdemDia.objects.filter(q).update(observacao='')
class Migration(migrations.Migration):
dependencies = [
('sessao', '0022_auto_20180618_1625'),
]
operations = [
migrations.AlterField(
model_name='expedientemateria',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.AlterField(
model_name='ordemdia',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.RunPython(limpa_observacao_igual_ementa),
]

8
sapl/sessao/models.py

@ -1,10 +1,10 @@
from operator import xor from operator import xor
import reversion
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from model_utils import Choices from model_utils import Choices
import reversion
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.materia.models import MateriaLegislativa from sapl.materia.models import MateriaLegislativa
@ -237,7 +237,7 @@ class AbstractOrdemDia(models.Model):
verbose_name=_('Matéria')) verbose_name=_('Matéria'))
data_ordem = models.DateField(verbose_name=_('Data da Sessão')) data_ordem = models.DateField(verbose_name=_('Data da Sessão'))
observacao = models.TextField( observacao = models.TextField(
blank=True, verbose_name=_('Ementa')) blank=True, verbose_name=_('Observação'))
numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem')) numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem'))
resultado = models.TextField(blank=True, verbose_name=_('Resultado')) resultado = models.TextField(blank=True, verbose_name=_('Resultado'))
tipo_votacao = models.PositiveIntegerField( tipo_votacao = models.PositiveIntegerField(
@ -254,6 +254,10 @@ class AbstractOrdemDia(models.Model):
class Meta: class Meta:
abstract = True abstract = True
@property
def ementa(self):
return self.materia.ementa
def __str__(self): def __str__(self):
return 'Ordem do Dia/Expediente: %s - %s em %s' % ( return 'Ordem do Dia/Expediente: %s - %s em %s' % (
self.numero_ordem, self.materia, self.sessao_plenaria) self.numero_ordem, self.materia, self.sessao_plenaria)

16
sapl/sessao/serializers.py

@ -1,19 +1,3 @@
from rest_framework import serializers from rest_framework import serializers
from .models import SessaoPlenaria from .models import SessaoPlenaria
class SessaoPlenariaSerializer(serializers.Serializer):
class Meta:
model = SessaoPlenaria
fields = ('tipo',
'sessao_legislativa',
'legislatura',
'data_inicio',
'hora_inicio',
'hora_fim',
'url_video',
'iniciada',
'finalizada'
)

4
sapl/sessao/urls.py

@ -10,7 +10,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
PesquisarPautaSessaoView, PesquisarPautaSessaoView,
PesquisarSessaoPlenariaView, PesquisarSessaoPlenariaView,
PresencaOrdemDiaView, PresencaView, PresencaOrdemDiaView, PresencaView,
ResumoOrdenacaoView, ResumoView, SessaoCrud, ResumoOrdenacaoView, ResumoView, ResumoAtaView, SessaoCrud,
TipoExpedienteCrud, TipoResultadoVotacaoCrud, TipoExpedienteCrud, TipoResultadoVotacaoCrud,
TipoSessaoCrud, VotacaoEditView, TipoSessaoCrud, VotacaoEditView,
VotacaoExpedienteEditView, VotacaoExpedienteEditView,
@ -117,6 +117,8 @@ urlpatterns = [
name='presencaordemdia'), name='presencaordemdia'),
url(r'^sessao/(?P<pk>\d+)/resumo$', url(r'^sessao/(?P<pk>\d+)/resumo$',
ResumoView.as_view(), name='resumo'), ResumoView.as_view(), name='resumo'),
url(r'^sessao/(?P<pk>\d+)/resumo_ata$',
ResumoAtaView.as_view(), name='resumo_ata'),
url(r'^sessao/pesquisar-sessao$', url(r'^sessao/pesquisar-sessao$',
PesquisarSessaoPlenariaView.as_view(), name='pesquisar_sessao'), PesquisarSessaoPlenariaView.as_view(), name='pesquisar_sessao'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votnom/(?P<oid>\d+)/(?P<mid>\d+)$', url(r'^sessao/(?P<pk>\d+)/matordemdia/votnom/(?P<oid>\d+)/(?P<mid>\d+)$',

145
sapl/sessao/views.py

@ -1,5 +1,5 @@
from re import sub
from operator import itemgetter from operator import itemgetter
from re import sub
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
@ -327,9 +327,9 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'mid': obj.materia_id}) 'mid': obj.materia_id})
resultado = ('<a href="%s">%s<br/>%s</a>' % resultado = ('<a href="%s">%s<br/>%s</a>' %
(url, (url,
resultado_descricao, resultado_descricao,
resultado_observacao)) resultado_observacao))
else: else:
if obj.tipo_votacao == 2: if obj.tipo_votacao == 2:
@ -340,7 +340,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id, 'pk': obj.sessao_plenaria_id,
'oid': obj.pk, 'oid': obj.pk,
'mid': obj.materia_id}) + \ 'mid': obj.materia_id}) + \
'?&materia=expediente' '?&materia=expediente'
else: else:
url = reverse( url = reverse(
'sapl.sessao:votacao_nominal_transparencia', 'sapl.sessao:votacao_nominal_transparencia',
@ -348,12 +348,12 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id, 'pk': obj.sessao_plenaria_id,
'oid': obj.pk, 'oid': obj.pk,
'mid': obj.materia_id}) + \ 'mid': obj.materia_id}) + \
'?&materia=ordem' '?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' % resultado = ('<a href="%s">%s<br/>%s</a>' %
(url, (url,
resultado_descricao, resultado_descricao,
resultado_observacao)) resultado_observacao))
elif obj.tipo_votacao == 1: elif obj.tipo_votacao == 1:
if is_expediente: if is_expediente:
@ -363,7 +363,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id, 'pk': obj.sessao_plenaria_id,
'oid': obj.pk, 'oid': obj.pk,
'mid': obj.materia_id}) + \ 'mid': obj.materia_id}) + \
'?&materia=expediente' '?&materia=expediente'
else: else:
url = reverse( url = reverse(
'sapl.sessao:votacao_simbolica_transparencia', 'sapl.sessao:votacao_simbolica_transparencia',
@ -371,7 +371,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id, 'pk': obj.sessao_plenaria_id,
'oid': obj.pk, 'oid': obj.pk,
'mid': obj.materia_id}) + \ 'mid': obj.materia_id}) + \
'?&materia=ordem' '?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' % resultado = ('<a href="%s">%s<br/>%s</a>' %
(url, (url,
@ -379,8 +379,8 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
resultado_observacao)) resultado_observacao))
else: else:
resultado = ('%s<br/>%s' % resultado = ('%s<br/>%s' %
(resultado_descricao, (resultado_descricao,
resultado_observacao)) resultado_observacao))
context['rows'][i][3] = (resultado, None) context['rows'][i][3] = (resultado, None)
return context return context
@ -391,7 +391,8 @@ def get_presencas_generic(model, sessao, legislatura):
presentes = [p.parlamentar for p in presencas] presentes = [p.parlamentar for p in presencas]
presentes = sorted(presentes, key=lambda x: remover_acentos(x.nome_parlamentar)) presentes = sorted(
presentes, key=lambda x: remover_acentos(x.nome_parlamentar))
mandato = Mandato.objects.filter( mandato = Mandato.objects.filter(
legislatura=legislatura).order_by('parlamentar__nome_parlamentar') legislatura=legislatura).order_by('parlamentar__nome_parlamentar')
@ -415,7 +416,8 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
public = [RP_LIST, RP_DETAIL] public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia', 'materia__ementa', list_field_names = ['numero_ordem', 'materia',
('materia__ementa', '', 'observacao'),
'resultado'] 'resultado']
class CreateView(MasterDetailCrud.CreateView): class CreateView(MasterDetailCrud.CreateView):
@ -446,17 +448,18 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return initial return initial
class DetailView(MasterDetailCrud.DetailView): class DetailView(MasterDetailCrud.DetailView):
layout_key = 'OrdemDiaDetail' layout_key = 'OrdemDiaDetail'
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
paginate_by = None paginate_by = None
ordering = ['numero_ordem', 'materia', 'resultado'] ordering = ['numero_ordem', 'materia', 'resultado']
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
has_permition = self.request.user.has_module_perms(AppConfig.label) has_permition = self.request.user.has_module_perms(AppConfig.label)
return customize_link_materia(context, self.kwargs['pk'], has_permition, False) return customize_link_materia(context, self.kwargs['pk'], has_permition, False)
def recuperar_materia(request): def recuperar_materia(request):
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia']) tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia'])
numero = request.GET['numero_materia'] numero = request.GET['numero_materia']
@ -470,7 +473,7 @@ def recuperar_materia(request):
'id': materia.id, 'id': materia.id,
'indexacao': materia.indexacao}) 'indexacao': materia.indexacao})
except ObjectDoesNotExist: except ObjectDoesNotExist:
response = JsonResponse({'ementa': '', 'id': 0, 'indexacao':''}) response = JsonResponse({'ementa': '', 'id': 0, 'indexacao': ''})
return response return response
@ -483,7 +486,8 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia', list_field_names = ['numero_ordem', 'materia',
'materia__ementa', 'resultado'] ('materia__ementa', '', 'observacao'),
'resultado']
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
paginate_by = None paginate_by = None
@ -551,7 +555,6 @@ class OradorExpedienteCrud(OradorCrud):
return reverse('sapl.sessao:oradorexpediente_list', return reverse('sapl.sessao:oradorexpediente_list',
kwargs={'pk': self.kwargs['pk']}) kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView): class UpdateView(MasterDetailCrud.UpdateView):
form_class = OradorExpedienteForm form_class = OradorExpedienteForm
@ -676,10 +679,10 @@ class SessaoCrud(Crud):
return { return {
'legislatura': legislatura, 'legislatura': legislatura,
'sessao_legislativa': legislatura.sessaolegislativa_set.filter( 'sessao_legislativa': legislatura.sessaolegislativa_set.filter(
legislatura_id=legislatura.id, legislatura_id=legislatura.id,
data_inicio__year=timezone.now().year data_inicio__year=timezone.now().year
).first() ).first()
} }
else: else:
msg = _('Cadastre alguma legislatura antes de adicionar ' + msg = _('Cadastre alguma legislatura antes de adicionar ' +
'uma sessão plenária!') 'uma sessão plenária!')
@ -785,7 +788,8 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
cronometro_discurso = AppsAppConfig.attr('cronometro_discurso') cronometro_discurso = AppsAppConfig.attr('cronometro_discurso')
cronometro_aparte = AppsAppConfig.attr('cronometro_aparte') cronometro_aparte = AppsAppConfig.attr('cronometro_aparte')
cronometro_ordem = AppsAppConfig.attr('cronometro_ordem') cronometro_ordem = AppsAppConfig.attr('cronometro_ordem')
cronometro_consideracoes = AppsAppConfig.attr('cronometro_consideracoes') cronometro_consideracoes = AppsAppConfig.attr(
'cronometro_consideracoes')
if (not cronometro_discurso or not cronometro_aparte if (not cronometro_discurso or not cronometro_aparte
or not cronometro_ordem or not cronometro_consideracoes): or not cronometro_ordem or not cronometro_consideracoes):
@ -1006,15 +1010,18 @@ class MesaView(FormMixin, DetailView):
cargos_vagos = list(set(cargos) - set(cargos_ocupados)) cargos_vagos = list(set(cargos) - set(cargos_ocupados))
# FIX-ME: tem formas melhores de fazer isso, poupando linhas. # FIX-ME: tem formas melhores de fazer isso, poupando linhas.
parlamentares = Legislatura.objects.get(id=sessao.legislatura_id).mandato_set.all() parlamentares = Legislatura.objects.get(
id=sessao.legislatura_id).mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in mesa] parlamentares_ocupados = [m.parlamentar for m in mesa]
parlamentares_vagos = list( parlamentares_vagos = list(
set( set(
[p.parlamentar for p in parlamentares]) - set( [p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados)) parlamentares_ocupados))
org_parlamentares_vagos = parlamentares_vagos org_parlamentares_vagos = parlamentares_vagos
org_parlamentares_vagos.sort(key=lambda x: remover_acentos(x.nome_parlamentar)) org_parlamentares_vagos.sort(
org_parlamentares_vagos = [p for p in org_parlamentares_vagos if p.ativo] key=lambda x: remover_acentos(x.nome_parlamentar))
org_parlamentares_vagos = [
p for p in org_parlamentares_vagos if p.ativo]
# Se todos os cargos estiverem ocupados, a listagem de parlamentares # Se todos os cargos estiverem ocupados, a listagem de parlamentares
# deve ser renderizada vazia # deve ser renderizada vazia
if not cargos_vagos: if not cargos_vagos:
@ -1166,15 +1173,15 @@ class ResumoOrdenacaoView(PermissionRequiredMixin, FormView):
ordenacao = ResumoOrdenacao.objects.first() ordenacao = ResumoOrdenacao.objects.first()
if ordenacao: if ordenacao:
initial.update({'primeiro': ordenacao.primeiro, initial.update({'primeiro': ordenacao.primeiro,
'segundo': ordenacao.segundo, 'segundo': ordenacao.segundo,
'terceiro': ordenacao.terceiro, 'terceiro': ordenacao.terceiro,
'quarto': ordenacao.quarto, 'quarto': ordenacao.quarto,
'quinto': ordenacao.quinto, 'quinto': ordenacao.quinto,
'sexto': ordenacao.sexto, 'sexto': ordenacao.sexto,
'setimo': ordenacao.setimo, 'setimo': ordenacao.setimo,
'oitavo': ordenacao.oitavo, 'oitavo': ordenacao.oitavo,
'nono': ordenacao.nono, 'nono': ordenacao.nono,
'decimo': ordenacao.decimo}) 'decimo': ordenacao.decimo})
return initial return initial
def form_valid(self, form): def form_valid(self, form):
@ -1279,7 +1286,6 @@ class ResumoView(DetailView):
ex = {'tipo': tipo, 'conteudo': conteudo} ex = {'tipo': tipo, 'conteudo': conteudo}
expedientes.append(ex) expedientes.append(ex)
context.update({'expedientes': expedientes}) context.update({'expedientes': expedientes})
# ===================================================================== # =====================================================================
# Matérias Expediente # Matérias Expediente
materias = ExpedienteMateria.objects.filter( materias = ExpedienteMateria.objects.filter(
@ -1335,7 +1341,7 @@ class ResumoView(DetailView):
ora = {'numero_ordem': numero_ordem, ora = {'numero_ordem': numero_ordem,
'url_discurso': url_discurso, 'url_discurso': url_discurso,
'parlamentar': parlamentar, 'parlamentar': parlamentar,
'observacao' : observacao 'observacao': observacao
} }
oradores.append(ora) oradores.append(ora)
@ -1455,7 +1461,8 @@ class ResumoView(DetailView):
'decimo_ordenacao': dict_ord_template['oradores_expli']}) 'decimo_ordenacao': dict_ord_template['oradores_expli']})
return self.render_to_response(context) return self.render_to_response(context)
class ResumoAtaView(ResumoView):
template_name = 'sessao/resumo_ata.html'
class ExpedienteView(FormMixin, DetailView): class ExpedienteView(FormMixin, DetailView):
template_name = 'sessao/expediente.html' template_name = 'sessao/expediente.html'
@ -1485,8 +1492,8 @@ class ExpedienteView(FormMixin, DetailView):
for tipo, conteudo in zip(list_tipo, list_conteudo): for tipo, conteudo in zip(list_tipo, list_conteudo):
ExpedienteSessao.objects.filter( ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id, sessao_plenaria_id=self.object.id,
tipo_id=tipo).delete() tipo_id=tipo).delete()
expediente = ExpedienteSessao() expediente = ExpedienteSessao()
expediente.sessao_plenaria_id = self.object.id expediente.sessao_plenaria_id = self.object.id
@ -1832,13 +1839,11 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
elif self.expediente: elif self.expediente:
expediente_id = kwargs['oid'] expediente_id = kwargs['oid']
try: try:
materia_votacao = ExpedienteMateria.objects.get(id=expediente_id) materia_votacao = ExpedienteMateria.objects.get(
id=expediente_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404() raise Http404()
if 'cancelar-votacao' in request.POST:
fechar_votacao_materia(materia_votacao)
return self.form_valid(form)
if form.is_valid(): if form.is_valid():
votos_sim = 0 votos_sim = 0
@ -1846,6 +1851,21 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
abstencoes = 0 abstencoes = 0
nao_votou = 0 nao_votou = 0
if 'cancelar-votacao' in request.POST:
fechar_votacao_materia(materia_votacao)
if self.ordem:
return HttpResponseRedirect(reverse(
'sapl.sessao:ordemdia_list', kwargs={'pk': kwargs['pk']}))
else:
return HttpResponseRedirect(reverse(
'sapl.sessao:expedientemateria_list',
kwargs={'pk': kwargs['pk']}))
else:
if form.cleaned_data['resultado_votacao'] == None:
form.add_error(None, 'Não é possível finalizar a votação sem '
'nenhum resultado da votação')
return self.form_invalid(form)
for votos in request.POST.getlist('voto_parlamentar'): for votos in request.POST.getlist('voto_parlamentar'):
v = votos.split(':') v = votos.split(':')
voto = v[0] voto = v[0]
@ -1930,7 +1950,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
return self.form_invalid(form) return self.form_invalid(form)
def form_invalid(self, form): def form_invalid(self, form):
errors_tuple = [(form[e].label, form.errors[e]) for e in form.errors if e in form.fields] errors_tuple = [(form[e].label, form.errors[e])
for e in form.errors if e in form.fields]
error_message = '''<ul>''' error_message = '''<ul>'''
for e in errors_tuple: for e in errors_tuple:
error_message += '''<li><b>%s</b>: %s</li>''' % (e[0], e[1][0]) error_message += '''<li><b>%s</b>: %s</li>''' % (e[0], e[1][0])
@ -2007,8 +2028,10 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
elif self.expediente: elif self.expediente:
expediente_id = kwargs['oid'] expediente_id = kwargs['oid']
expediente = ExpedienteMateria.objects.filter(id=expediente_id).last() expediente = ExpedienteMateria.objects.filter(
votacao = RegistroVotacao.objects.filter(expediente_id=expediente_id).last() id=expediente_id).last()
votacao = RegistroVotacao.objects.filter(
expediente_id=expediente_id).last()
if not expediente or not votacao: if not expediente or not votacao:
raise Http404() raise Http404()
@ -2127,9 +2150,11 @@ class VotacaoNominalTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None) materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem': if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last() votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente': elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last() votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else: else:
raise Http404() raise Http404()
@ -2210,18 +2235,20 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None) materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem': if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last() votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente': elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last() votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else: else:
raise Http404() raise Http404()
context['votacao'] = votacao context['votacao'] = votacao
registro_votacao = {'numero_votos_sim': votacao.numero_votos_sim, registro_votacao = {'numero_votos_sim': votacao.numero_votos_sim,
'numero_votos_nao': votacao.numero_votos_nao, 'numero_votos_nao': votacao.numero_votos_nao,
'numero_abstencoes': votacao.numero_abstencoes} 'numero_abstencoes': votacao.numero_abstencoes}
context.update({'registro_votacao':registro_votacao}) context.update({'registro_votacao': registro_votacao})
votacao_existente = {'observacao': sub( votacao_existente = {'observacao': sub(
'&nbsp;', ' ', strip_tags(votacao.observacao)), '&nbsp;', ' ', strip_tags(votacao.observacao)),
@ -2237,6 +2264,7 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
for tipo in TipoResultadoVotacao.objects.all(): for tipo in TipoResultadoVotacao.objects.all():
yield tipo yield tipo
class VotacaoExpedienteView(SessaoPermissionMixin): class VotacaoExpedienteView(SessaoPermissionMixin):
""" """
@ -2420,7 +2448,8 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin):
expediente_id = kwargs['oid'] expediente_id = kwargs['oid']
if int(request.POST['anular_votacao']) == 1: if int(request.POST['anular_votacao']) == 1:
RegistroVotacao.objects.filter(expediente_id=expediente_id).delete() RegistroVotacao.objects.filter(
expediente_id=expediente_id).delete()
expediente = ExpedienteMateria.objects.get( expediente = ExpedienteMateria.objects.get(
sessao_plenaria_id=self.object.id, sessao_plenaria_id=self.object.id,
@ -2459,10 +2488,10 @@ class PautaSessaoView(TemplateView):
sessao = SessaoPlenaria.objects.order_by("-data_inicio").first() sessao = SessaoPlenaria.objects.order_by("-data_inicio").first()
if not sessao: if not sessao:
return self.render_to_response({}) return self.render_to_response({})
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao.pk})) reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao.pk}))
class PautaSessaoDetailView(DetailView): class PautaSessaoDetailView(DetailView):

22
sapl/settings.py

@ -116,11 +116,7 @@ HAYSTACK_CONNECTIONS = {
}, },
} }
MIDDLEWARE = [
if DEBUG:
INSTALLED_APPS += ('debug_toolbar', 'rest_framework_docs',)
MIDDLEWARE_CLASSES = (
'reversion.middleware.RevisionMiddleware', 'reversion.middleware.RevisionMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
@ -131,8 +127,13 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
# 'speedinfo.middleware.ProfilerMiddleware', # Bug na versão 1.9 'speedinfo.middleware.ProfilerMiddleware',
) ]
if DEBUG:
INSTALLED_APPS += ('debug_toolbar', 'rest_framework_docs',)
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]
INTERNAL_IPS = ('127.0.0.1')
CACHES = { CACHES = {
'default': { 'default': {
@ -221,7 +222,7 @@ EMAIL_SEND_USER = config('EMAIL_SEND_USER', cast=str, default='')
DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', cast=str, default='') DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', cast=str, default='')
SERVER_EMAIL = config('SERVER_EMAIL', cast=str, default='') SERVER_EMAIL = config('SERVER_EMAIL', cast=str, default='')
MAX_DOC_UPLOAD_SIZE = 50 * 1024 * 1024 # 50MB MAX_DOC_UPLOAD_SIZE = 60 * 1024 * 1024 # 60MB
MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB
# Internationalization # Internationalization
@ -231,7 +232,10 @@ LANGUAGES = (
('pt-br', 'Português'), ('pt-br', 'Português'),
) )
TIME_ZONE = config('TZ', cast=str, default='America/Sao_Paulo') TIME_ZONE = config('TZ', default='America/Sao_Paulo')
if not TIME_ZONE:
raise ValueError('TIMEZONE env variable undefined in .env settings file! Leaving...')
USE_I18N = True USE_I18N = True
USE_L10N = True USE_L10N = True
USE_TZ = True USE_TZ = True

1
sapl/templates/base/RelatorioAtas_filter.html

@ -12,6 +12,7 @@
<a href="{% url 'sapl.base:atas' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:atas' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /> <br /><br /><br />
<b>PERÍODO: {{ periodo }}<br /></b><br /><br/>
{% if object_list|length > 0 %} {% if object_list|length > 0 %}
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">
<thead> <thead>

38
sapl/templates/base/RelatorioAudiencia_filter.html

@ -0,0 +1,38 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block base_content %}
{% if not show_results %}
{% crispy filter.form %}
{% endif %}
{% if show_results %}
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.base:audiencia' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div>
<br /><br /><br /><br />
{% if object_list|length > 0 %}
<table class="table table-bordered table-hover">
<thead class="thead-default" >
<tr class="active">
<th>Tipo de Audiência</th>
<th>Nome</th>
</tr>
</thead>
<tbody>
{% for audiencia in object_list %}
<tr>
<td><a href="{% url 'sapl.audiencia:audienciapublica_detail' audiencia.id %}">
{{audiencia.tipo}}
</a></td>
<td>{{audiencia.nome}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="5"><p align="center">Nenhuma Audiência Pública foi encontrada!</p></font>
{% endif %}
{% endif %}
{% endblock base_content %}

5
sapl/templates/base/RelatorioDataFimPrazoTramitacao_filter.html

@ -12,6 +12,11 @@
<a href="{% url 'sapl.base:data_fim_prazo_tramitacoes' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:data_fim_prazo_tramitacoes' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /><br /> <br /><br /><br /><br />
<b>PARÂMETROS DE PESQUISA:<br /></b>
&emsp;Período: {{ data_tramitacao }} <br />
&emsp;Tipo de matéria: {{ tipo }}<br />
&emsp;Status atual: {{ tramitacao__status }}<br />
&emsp;Local atual: {{ tramitacao__unidade_tramitacao_local }}<br /><br /><br />
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead class="thead-default" > <thead class="thead-default" >
<tr class="active"> <tr class="active">

5
sapl/templates/base/RelatorioHistoricoTramitacao_filter.html

@ -12,6 +12,11 @@
<a href="{% url 'sapl.base:historico_tramitacoes' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:historico_tramitacoes' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /><br /> <br /><br /><br /><br />
<b>PARÂMETROS DE PESQUISA:<br /></b>
&emsp;Período: {{ data_tramitacao }} <br />
&emsp;Tipo de matéria: {{ tipo }}<br />
&emsp;Status atual: {{ tramitacao__status }}<br />
&emsp;Local atual: {{ tramitacao__unidade_tramitacao_local }}<br /><br /><br />
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead class="thead-default" > <thead class="thead-default" >
<tr class="active"> <tr class="active">

37
sapl/templates/base/RelatorioMateriasPorAnoAutorTipo_filter.html

@ -12,6 +12,25 @@
<a href="{% url 'sapl.base:materia_por_ano_autor_tipo' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:materia_por_ano_autor_tipo' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /><br /> <br /><br /><br /><br />
<b>PARÂMETROS DE PESQUISA:<br /></b>
&emsp;Ano: {{ano}}<br /><br /><br/>
<table class="table table-bordered table-hover">
<thead class="thead-default" >
<tr class="active"><th colspan="2" class="text-center">QUADRO GERAL</th></tr>
<tr class="active">
<th>Tipo Matéria</th>
<th>Quantidade</th>
</tr>
</thead>
<tbody>
{% for key, value in qtdes.items %}
<tr>
<td>{{key.sigla}} - {{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1>Autorias</h1> <h1>Autorias</h1>
<br/><br/> <br/><br/>
{% for r in relatorio %} {% for r in relatorio %}
@ -59,24 +78,6 @@
<br/> <br/>
<br/> <br/>
{% endfor %} {% endfor %}
<br/><br/>
<table class="table table-bordered table-hover">
<thead class="thead-default" >
<tr class="active"><th colspan="2" class="text-center">QUADRO GERAL</th></tr>
<tr class="active">
<th>Tipo Matéria</th>
<th>Quantidade</th>
</tr>
</thead>
<tbody>
{% for key, value in qtdes.items %}
<tr>
<td>{{key.sigla}} - {{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %} {% endif %}
{% endblock base_content %} {% endblock base_content %}

5
sapl/templates/base/RelatorioMateriasPorAutor_filter.html

@ -12,7 +12,10 @@
<a href="{% url 'sapl.base:materia_por_autor' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:materia_por_autor' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /><br /> <br /><br /><br /><br />
<b>PARÂMETROS DE PESQUISA:<br /></b>
&emsp;Autor: {{ autor }}<br />
&emsp;Tipo de matéria: {{ tipo }}<br />
&emsp;Data de apresentação: {{periodo}}<br /><br /><br/>
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead class="thead-default" > <thead class="thead-default" >
<tr class="active"><th colspan="3" class="text-center">QUADRO GERAL</th></tr> <tr class="active"><th colspan="3" class="text-center">QUADRO GERAL</th></tr>

6
sapl/templates/base/RelatorioMateriasPorTramitacao_filter.html

@ -12,7 +12,11 @@
<a href="{% url 'sapl.base:materia_por_tramitacao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> <a href="{% url 'sapl.base:materia_por_tramitacao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div> </div>
<br /><br /><br /><br /> <br /><br /><br /><br />
<b>PARÂMETROS DE PESQUISA:<br /></b>
&emsp;Ano: {{ ano }} <br />
&emsp;Tipo de matéria: {{ tipo }}<br />
&emsp;Status atual: {{ tramitacao__status }}<br />
&emsp;Local atual: {{ tramitacao__unidade_tramitacao_destino }}<br /><br /><br />
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead class="thead-default" > <thead class="thead-default" >
<tr class="active"><th colspan="2" class="text-center">QUADRO GERAL</th></tr> <tr class="active"><th colspan="2" class="text-center">QUADRO GERAL</th></tr>

38
sapl/templates/base/RelatorioReuniao_filter.html

@ -0,0 +1,38 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block base_content %}
{% if not show_results %}
{% crispy filter.form %}
{% endif %}
{% if show_results %}
<div class="actions btn-group pull-right" role="group">
<a href="{% url 'sapl.base:reuniao' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a>
</div>
<br /><br /><br /><br />
{% if object_list|length > 0 %}
<table class="table table-bordered table-hover">
<thead class="thead-default" >
<tr class="active">
<th>Comissao</th>
<th>Nome</th>
</tr>
</thead>
<tbody>
{% for reuniao in object_list %}
<tr>
<td><a href="{% url 'sapl.comissoes:reuniao_detail' reuniao.pk %}">
{{reuniao.comissao}}
</a></td>
<td>{{reuniao.nome}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="5"><p align="center">Nenhum reunião foi encontrada!</p></font>
{% endif %}
{% endif %}
{% endblock base_content %}

10
sapl/templates/base/relatorios_list.html

@ -40,7 +40,15 @@
<td><a href="{% url 'sapl.base:data_fim_prazo_tramitacoes' %}">Tramitações por fim de prazo</a></td> <td><a href="{% url 'sapl.base:data_fim_prazo_tramitacoes' %}">Tramitações por fim de prazo</a></td>
<td> Tramitações com fim de prazo no intervalo informado. </td> <td> Tramitações com fim de prazo no intervalo informado. </td>
</tr> </tr>
<tr>
<td><a href="{% url 'sapl.base:reuniao' %}">Reunião de Comissão</a></td>
<td> Reunião de Comissão por data. </td>
</tr>
<tr>
<td><a href="{% url 'sapl.base:audiencia' %}">Audiência Pública</a></td>
<td> Audiência Pública com o tipo. </td>
</tr>
</tbody> </tbody>
</table> </table>
</fieldset </fieldset>
{% endblock base_content %} {% endblock base_content %}

3
sapl/templates/compilacao/text_edit_bloco.html

@ -36,9 +36,6 @@
{{ node.td.rotulo_sufixo_html|safe }} {{ node.td.rotulo_sufixo_html|safe }}
{% endif %} {% endif %}
{{ node.td.texto_prefixo_html|safe }} {{ node.td.texto_prefixo_html|safe }}
{% if node.da and node in node.da.alts and not node.dpt.visibilidade %}<small>({% trans 'Dispositivo visível apenas no Texto Articulado Original'%})</small>{% endif %} {% if node.da and node in node.da.alts and not node.dpt.visibilidade %}<small>({% trans 'Dispositivo visível apenas no Texto Articulado Original'%})</small>{% endif %}

34
sapl/templates/compilacao/text_list_blocoalteracao.html

@ -5,15 +5,31 @@
{% if ch.visibilidade %} {% if ch.visibilidade %}
<div class="dpt" id="d{{ch.id}}" nivel="{{ch.nivel}}"> <div class="dpt" id="d{{ch.id}}" nivel="{{ch.nivel}}">
<div class="{{ ch.tipo_dispositivo.class_css }}" id="id{{ch.id}}" nivel="{{ch.nivel}}"> <div class="{{ ch.tipo_dispositivo.class_css }}" id="id{{ch.id}}" nivel="{{ch.nivel}}">
{% if ch.auto_inserido %} {% if ch.auto_inserido %}
{{ ch.dispositivo_pai.tipo_dispositivo.rotulo_prefixo_html|safe }} {{ ch.dispositivo_pai.tipo_dispositivo.rotulo_prefixo_html|safe }}
<a name="{{ch.dispositivo_pai.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.dispositivo_pai.ta.pk %}#{{ch.dispositivo_pai.pk}}">{{ ch.dispositivo_pai.rotulo }}</a> {% if ch.dispositivo_pai.rotulo %}
{{ ch.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }} <a name="{{ch.dispositivo_pai.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.dispositivo_pai.ta.pk %}#{{ch.dispositivo_pai.pk}}">{{ ch.dispositivo_pai.rotulo }}</a>
{% endif %} {{ ch.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }} {% else %}
<a name="{{ch.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.ta.pk %}#{{ch.pk}}">{{ ch.rotulo }}</a> <a name="{{ch.dispositivo_pai.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.dispositivo_pai.ta.pk %}#{{ch.dispositivo_pai.pk}}">
{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ ch.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }} </a>
{% endif %}
{% endif %}
{{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }}
{% if ch.rotulo %}
<a name="{{ch.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.ta.pk %}#{{ch.pk}}">{{ ch.rotulo }}</a>
{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }}
{% elif not ch.rotulo and not ch.auto_inserido %}
<a name="{{ch.pk}}" href="{% url 'sapl.compilacao:ta_text' ch.ta.pk %}#{{ch.pk}}">
{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }}
</a>
{% else %}
{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }}
{% endif %}
</div> </div>
</div> </div>
{%endif%} {%endif%}

10
sapl/templates/materia/materialegislativa_detail.html

@ -8,3 +8,13 @@
</div> </div>
{% endif %} {% endif %}
{% endblock sub_actions %} {% endblock sub_actions %}
{% block detail_content %}
{{ block.super }}
{% if object.normajuridica_set.last %}
<p class="control-label">&emsp; Norma Jurídica Relacionada</p>
<div class="actions btn-group btn-group-sm" role="group">
&emsp;&emsp;<a href="{% url 'sapl.norma:normajuridica_detail' object.normajuridica_set.last.id %}">
{{ object.normajuridica_set.last }}</a>
</div>
{% endif %}
{% endblock detail_content %}

6
sapl/templates/norma/normajuridica_filter.html

@ -51,7 +51,11 @@
{% for n in page_obj %} {% for n in page_obj %}
<tr> <tr>
<td><a href="{% url 'sapl.norma:normajuridica_detail' n.id %}">{{n.tipo}}</a></td> <td><a href="{% url 'sapl.norma:normajuridica_detail' n.id %}">{{n.tipo}}</a></td>
<td>{{n.numero}}</td> {% if n.texto_integral %}
<td><a href="{{n.texto_integral.url}}">{{n.numero}}</a></td>
{% else %}
<td>{{n.numero}}</td>
{% endif %}
<td>{{n.ano}}</td> <td>{{n.ano}}</td>
<td>{{n.data}}</td> <td>{{n.data}}</td>
<td>{{n.ementa|safe}}</td> <td>{{n.ementa|safe}}</td>

4
sapl/templates/protocoloadm/documentoadministrativo_filter.html

@ -34,10 +34,11 @@
{% endif %} {% endif %}
{% for d in page_obj %} {% for d in page_obj %}
{% if request.user.is_anonymous and not d.restrito or not request.user.is_anonymous%}
<tr> <tr>
<td> <td>
<strong><a href="{% url 'sapl.protocoloadm:documentoadministrativo_detail' d.id %}">{{d.tipo.sigla}} {{d.numero}}/{{d.ano}} - {{d.tipo}}</strong></a></br> <strong><a href="{% url 'sapl.protocoloadm:documentoadministrativo_detail' d.id %}">{{d.tipo.sigla}} {{d.numero}}/{{d.ano}} - {{d.tipo}}</strong></a></br>
<strong>Interessado:</strong>&nbsp;{{ d.interessado|default_if_none:"Não informado"}} <strong>Interessado:</strong>&nbsp;{{ d.interessado|default_if_none:"Não informado"}}
</br> </br>
<strong>Assunto:</strong>&nbsp;{{ d.assunto|safe }} <strong>Assunto:</strong>&nbsp;{{ d.assunto|safe }}
</br> </br>
@ -65,6 +66,7 @@
</td> </td>
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
{% else %} {% else %}
<tr><td><h3>Nenhum documento encontrado com essas especificações</h3></tr> <tr><td><h3>Nenhum documento encontrado com essas especificações</h3></tr>

12
sapl/templates/sessao/blocos_ata/assinaturas.html

@ -0,0 +1,12 @@
{% load common_tags %}
</p>
</p>
<legend>Assinatura Parlamentares Presentes</legend>
<div class="row">
{% for p in presenca_ordem %}
<div class="col-md-12">{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }}</p>
</div>
{% endfor %}
</div>
</fieldset>

0
sapl/templates/sessao/blocos_ata/conteudo_multimidia.html

9
sapl/templates/sessao/blocos_ata/expedientes.html

@ -0,0 +1,9 @@
<fieldset>
<p align="justify">
<strong>Expedientes: </strong>
{% for e in expedientes %}
<b>{{e.tipo}}</b>:
{{e.conteudo|striptags|safe}}
{% endfor %}
</p>
</fieldset>

8
sapl/templates/sessao/blocos_ata/identificacao_basica.html

@ -0,0 +1,8 @@
<fieldset>
<p align="justify">
<strong>Identificação Básica: </strong>
{% for b in basica %}
{{b}} ;
{% endfor %}
</p>
</fieldset>

10
sapl/templates/sessao/blocos_ata/lista_presenca.html

@ -0,0 +1,10 @@
{% load common_tags %}
<fieldset>
<p align="justify">
<strong>Lista de Presença na Sessão: </strong>
{% for p in presenca_sessao %}
{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ;
{% endfor %}
</p>
</fieldset>

10
sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html

@ -0,0 +1,10 @@
{% load common_tags %}
<fieldset>
<p align="justify">
<strong>Lista de Presença na Ordem do Dia: </strong>
{% for p in presenca_ordem %}
{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ;
{% endfor %}
</p>
</fieldset>

25
sapl/templates/sessao/blocos_ata/materias_expediente.html

@ -0,0 +1,25 @@
<fieldset>
<p align="justify">
<strong>Matérias do Expediente: </strong>
{% for m in materia_expediente %}
<b>{{m.numero}} - {{m.titulo}}</b>
{% if m.turno %}
Turno: {{m.turno}}
{% endif %}
Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
{% if m.numero_protocolo %}
Número de Protocolo: {{ m.numero_protocolo }}
{% endif %}
{% if m.numero_processo %}
Processo: {{ m.numero_processo }}
{% endif %}
{{m.ementa|safe}}
{{m.resultado}} {{m.resultado_observacao}}</td>
{% endfor %}
</p>
</fieldset>

23
sapl/templates/sessao/blocos_ata/materias_ordem_dia.html

@ -0,0 +1,23 @@
<fieldset>
<p align="justify">
<strong>Matérias da Ordem do Dia: </strong>
{% for m in materias_ordem %}
<b>{{m.numero}} - {{m.titulo}} </b>
{% if m.turno %}
Turno:{{m.turno}}
{% endif %}
Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
{% if m.numero_protocolo %}
Número de Protocolo: {{ m.numero_protocolo }}
{% endif %}
{% if m.numero_processo %}
Processo: {{ m.numero_processo }}
{% endif %}
{{m.ementa|safe}}
{{m.resultado}} {{m.resultado_observacao}}
{% endfor %}
</p>
</fieldset>

10
sapl/templates/sessao/blocos_ata/mesa_diretora.html

@ -0,0 +1,10 @@
<fieldset>
<p align="justify">
<strong>Mesa Diretora: </strong>
{% for m in mesa %}
{{m.cargo}}:
{{m.parlamentar.nome_parlamentar}} / {{ m.parlamentar.filiacao_atual }} ;
{% endfor %}
</p>
</fieldset>

12
sapl/templates/sessao/blocos_ata/oradores_expediente.html

@ -0,0 +1,12 @@
<fieldset>
<p align="justify">
<strong>Oradores do Expediente: </strong>
{% for o in oradores %}
<div><b>{{o.numero_ordem}}</b> - {{o.parlamentar}}</div>
<div>{{o.url_discurso}}</div>
<div>{{o.observacao}}</div>
</br>
{% endfor %}
</p>
</div>
</fieldset>

9
sapl/templates/sessao/blocos_ata/oradores_explicacoes.html

@ -0,0 +1,9 @@
<fieldset>
<p align="justify">
<strong>Oradores das Explicações Pessoais: </strong>
{% for o in oradores_explicacoes %}
<b>{{o.numero_ordem}}</b> - {{o.parlamentar.nome_parlamentar}} / {{ o.parlamentar.filiacao_atual }} ;
{{o.url_discurso}}
{% endfor %}
</p>
</fieldset>

25
sapl/templates/sessao/expedientemateria_form.html

@ -6,7 +6,7 @@
{% block extra_js %} {% block extra_js %}
<script language="Javascript"> <script language="Javascript">
document.getElementById("id_observacao").readOnly = true; //document.getElementById("id_observacao").readOnly = true;
function recuperar_materia() { function recuperar_materia() {
var tipo_materia = $("#id_tipo_materia").val() var tipo_materia = $("#id_tipo_materia").val()
@ -14,18 +14,29 @@
var ano_materia = $("#id_ano_materia").val() var ano_materia = $("#id_ano_materia").val()
if (tipo_materia && numero_materia && ano_materia) { if (tipo_materia && numero_materia && ano_materia) {
$.get("/sessao/recuperar-materia",{tipo_materia: tipo_materia, $.get("/sessao/recuperar-materia", {
numero_materia: numero_materia, tipo_materia: tipo_materia,
ano_materia: ano_materia}, numero_materia: numero_materia,
function(data, status) { ano_materia: ano_materia
$("#id_observacao").val(data.ementa); },
}); function(data, status) {
if ($(".ementa-materia").length === 0) {
$("#div_id_tipo_materia").closest('.row-fluid').after(
$('<div class="row-fluid"/>').append(
$('<div class="col-xs-12"/>').append(
$('<div class="alert alert-info ementa-materia"/>').html(data.ementa))))
}
else {
$('.ementa-materia').html(data.ementa)
}
});
} }
} }
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"] var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]
for (i = 0; i < fields.length; i++) { for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_materia); $(fields[i]).change(recuperar_materia);
} }
recuperar_materia()
</script> </script>
{% endblock %} {% endblock %}

2
sapl/templates/sessao/layouts.yaml

@ -56,12 +56,14 @@ OrdemDia:
ExpedienteMateriaDetail: ExpedienteMateriaDetail:
{% trans 'Matérias do Expediente' %}: {% trans 'Matérias do Expediente' %}:
- materia - materia
- ementa
- tipo_votacao - tipo_votacao
- observacao - observacao
OrdemDiaDetail: OrdemDiaDetail:
{% trans 'Matérias da Ordem do Dia' %}: {% trans 'Matérias da Ordem do Dia' %}:
- materia - materia
- ementa
- tipo_votacao - tipo_votacao
- observacao - observacao

2
sapl/templates/sessao/pauta_sessao_detail.html

@ -3,7 +3,7 @@
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block base_content %} {% block base_content %}
<div align=right><a href="{% url 'sapl.relatorios:relatorio_sessao_plenaria' object.id %}"> Impressão PDF</a></li></div> <div align=right><a href="{% url 'sapl.relatorios:relatorio_pauta_sessao' object.pk %}"> Impressão PDF</a></li></div>
<fieldset> <fieldset>
<legend>Identificação Básica</legend> <legend>Identificação Básica</legend>
<table class="table"> <table class="table">

2
sapl/templates/sessao/pauta_sessao_filter.html

@ -24,7 +24,7 @@
{% for s in page_obj %} {% for s in page_obj %}
<tr> <tr>
<td><a href="{% url 'sapl.sessao:pauta_sessao_detail' s.id %}"><strong>{{s}}</strong></br></a></td><td> <td><a href="{% url 'sapl.sessao:pauta_sessao_detail' s.id %}"><strong>{{s}}</strong></br></a></td><td>
<a href="{% url 'sapl.relatorios:relatorio_sessao_plenaria' s.id %}"><img height="30" width="30" src="{% static 'img/pdflogo.png' %}"></a> <a href="{% url 'sapl.relatorios:relatorio_pauta_sessao' s.pk %}"><img height="30" width="30" src="{% static 'img/pdflogo.png' %}"></a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

23
sapl/templates/sessao/resumo_ata.html

@ -0,0 +1,23 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block title %}
<h1 class="page-header">
Extrato Eletrônico da {{sessaoplenaria}}
</h1>
{% endblock %}
{% block detail_content %}
{% include 'sessao/blocos_ata/'|add:primeiro_ordenacao %}
{% include 'sessao/blocos_ata/'|add:segundo_ordenacao %}
{% include 'sessao/blocos_ata/'|add:terceiro_ordenacao %}
{% include 'sessao/blocos_ata/'|add:quarto_ordenacao %}
{% include 'sessao/blocos_ata/'|add:quinto_ordenacao %}
{% include 'sessao/blocos_ata/'|add:sexto_ordenacao %}
{% include 'sessao/blocos_ata/'|add:setimo_ordenacao %}
{% include 'sessao/blocos_ata/'|add:oitavo_ordenacao %}
{% include 'sessao/blocos_ata/'|add:nono_ordenacao %}
{% include 'sessao/blocos_ata/'|add:decimo_ordenacao %}
{% include 'sessao/blocos_ata/assinaturas.html' %}
{% endblock detail_content %}

6
sapl/templates/sessao/subnav.yaml

@ -33,4 +33,8 @@
check_permission: painel.list_painel check_permission: painel.list_painel
- title: {% trans 'Resumo' %} - title: {% trans 'Resumo' %}
url: resumo children:
- title: {% trans 'Resumo' %}
url: resumo
- title: {% trans 'Extrato' %}
url: resumo_ata

2
sapl/test_urls.py

@ -56,7 +56,7 @@ def create_perms_post_migrate(sapl_app_config):
ctype = ContentType.objects.get_for_model(klass) ctype = ContentType.objects.get_for_model(klass)
ctypes.add(ctype) ctypes.add(ctype)
for perm in _get_all_permissions(klass._meta, ctype): for perm in _get_all_permissions(klass._meta):
searched_perms.append((ctype, perm)) searched_perms.append((ctype, perm))
all_perms = set(Permission.objects.filter( all_perms = set(Permission.objects.filter(

6
sapl/urls.py

@ -70,6 +70,12 @@ urlpatterns = [
# http://stackoverflow.com/questions/35510373/ # http://stackoverflow.com/questions/35510373/
if settings.DEBUG: if settings.DEBUG:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
urlpatterns += static(settings.STATIC_URL, urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT) document_root=settings.STATIC_ROOT)

2
setup.py

@ -49,7 +49,7 @@ install_requires = [
] ]
setup( setup(
name='interlegis-sapl', name='interlegis-sapl',
version='3.1.113', version='3.1.119',
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',

Loading…
Cancel
Save