From 11c8d9283aa3e5e8414e2a4f5ddc256b491b7c60 Mon Sep 17 00:00:00 2001
From: Leandro Roberto Silva
Date: Tue, 26 Mar 2019 16:34:40 -0300
Subject: [PATCH 01/18] =?UTF-8?q?Cria=20Rodap=C3=A9=20Global=20por=20tipos?=
=?UTF-8?q?=20de=20textos=20articulados=20(#2659)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* add field rodape_global
* add o field rodape_global ao formulário de edição e a renderização do texto
---
sapl/compilacao/forms.py | 24 +++++++++++++++----
.../0011_tipotextoarticulado_rodape_global.py | 20 ++++++++++++++++
sapl/compilacao/models.py | 7 ++++++
sapl/templates/compilacao/layouts.yaml | 1 +
sapl/templates/compilacao/text_list.html | 3 +++
5 files changed, 51 insertions(+), 4 deletions(-)
create mode 100644 sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py
diff --git a/sapl/compilacao/forms.py b/sapl/compilacao/forms.py
index 71d6ad7e5..222a86aed 100644
--- a/sapl/compilacao/forms.py
+++ b/sapl/compilacao/forms.py
@@ -3,7 +3,6 @@ from datetime import timedelta
from crispy_forms.bootstrap import (Alert, FieldWithButtons, FormActions,
InlineCheckboxes, InlineRadios,
StrictButton)
-from sapl.crispy_layout_mixin import SaplFormHelper
from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset,
Layout, Row, Submit)
from django import forms
@@ -23,10 +22,12 @@ from sapl.compilacao.models import (NOTAS_PUBLICIDADE_CHOICES,
TipoTextoArticulado, TipoVide,
VeiculoPublicacao, Vide)
from sapl.compilacao.utils import DISPOSITIVO_SELECT_RELATED
+from sapl.crispy_layout_mixin import SaplFormHelper
from sapl.crispy_layout_mixin import SaplFormLayout, to_column, to_row,\
form_actions
from sapl.utils import YES_NO_CHOICES
+
error_messages = {
'required': _('Este campo é obrigatório'),
'invalid': _('URL inválida.')
@@ -59,6 +60,13 @@ class TipoTaForm(ModelForm):
widget=forms.RadioSelect(),
required=True)
+ rodape_global = forms.CharField(
+ label=TipoTextoArticulado._meta.get_field(
+ 'rodape_global').verbose_name,
+ widget=forms.Textarea(attrs={'id': 'texto-rico'}),
+ required=False
+ )
+
class Meta:
model = TipoTextoArticulado
fields = ['sigla',
@@ -66,10 +74,12 @@ class TipoTaForm(ModelForm):
'content_type',
'participacao_social',
'publicacao_func',
- 'perfis'
+ 'perfis',
+ 'rodape_global'
]
- widgets = {'perfis': widgets.CheckboxSelectMultiple()}
+ widgets = {'perfis': widgets.CheckboxSelectMultiple(),
+ 'rodape_global': forms.Textarea}
def __init__(self, *args, **kwargs):
@@ -84,12 +94,18 @@ class TipoTaForm(ModelForm):
('perfis', 12),
])
+ row3 = to_row([
+ ('rodape_global', 12),
+ ])
+
self.helper = SaplFormHelper()
self.helper.layout = SaplFormLayout(
Fieldset(_('Identificação Básica'),
row1, css_class="col-md-12"),
Fieldset(_('Funcionalidades'),
- row2, css_class="col-md-12"))
+ row2, css_class="col-md-12"),
+ Fieldset(_('Nota de Rodapé Global'),
+ row3, css_class="col-md-12"))
super(TipoTaForm, self).__init__(*args, **kwargs)
diff --git a/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py b/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py
new file mode 100644
index 000000000..f3b0e323b
--- /dev/null
+++ b/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-03-26 18:59
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('compilacao', '0010_auto_20181004_1939'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='tipotextoarticulado',
+ name='rodape_global',
+ field=models.TextField(default='', help_text='A cada Tipo de Texto Articulado pode ser adicionado uma nota global de rodapé!', verbose_name='Rodapé Global'),
+ ),
+ ]
diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py
index f36e406f9..f64285aee 100644
--- a/sapl/compilacao/models.py
+++ b/sapl/compilacao/models.py
@@ -149,6 +149,13 @@ class TipoTextoArticulado(models.Model):
em edição.
"""))
+ rodape_global = models.TextField(
+ verbose_name=_('Rodapé Global'),
+ help_text=_('A cada Tipo de Texto Articulado pode ser adicionado '
+ 'uma nota global de rodapé!'),
+ default=''
+ )
+
class Meta:
verbose_name = _('Tipo de Texto Articulado')
verbose_name_plural = _('Tipos de Texto Articulados')
diff --git a/sapl/templates/compilacao/layouts.yaml b/sapl/templates/compilacao/layouts.yaml
index 20446ba19..a92c8627b 100644
--- a/sapl/templates/compilacao/layouts.yaml
+++ b/sapl/templates/compilacao/layouts.yaml
@@ -45,3 +45,4 @@ TipoTextoArticulado:
{% trans 'Funcionalidaes' %}:
- participacao_social publicacao_func
- perfis
+ - rodape_global
diff --git a/sapl/templates/compilacao/text_list.html b/sapl/templates/compilacao/text_list.html
index 3e9468e24..4efd992a9 100644
--- a/sapl/templates/compilacao/text_list.html
+++ b/sapl/templates/compilacao/text_list.html
@@ -18,4 +18,7 @@
{% endblock %}
{% include 'compilacao/text_list__embedded.html'%}
+ {{object.tipo_ta.rodape_global|dont_break_out}}
+
+
{% endblock base_content %}
From c618d6781e19f1bc698fefc1463afb989e66e808 Mon Sep 17 00:00:00 2001
From: Edward
Date: Wed, 27 Mar 2019 13:48:07 -0300
Subject: [PATCH 02/18] Fixes #2657 (#2661)
---
sapl/sessao/views.py | 74 ++++++++-----------
.../sessao/blocos_ata/materias_ordem_dia.html | 4 +-
2 files changed, 34 insertions(+), 44 deletions(-)
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 4a080d155..236c9320d 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -1033,9 +1033,6 @@ class ListMateriaOrdemDiaView(FormMixin, DetailView):
return self.get(self, request, args, kwargs)
-def ordenar_integrantes_por_cargo(integrantes):
- return sorted(integrantes, key=lambda k: k['cargo'].id)
-
class MesaView(FormMixin, DetailView):
template_name = 'sessao/mesa.html'
@@ -1338,24 +1335,17 @@ def get_conteudo_multimidia(sessao_plenaria):
def get_mesa_diretora(sessao_plenaria):
- mesa = IntegranteMesa.objects.filter(sessao_plenaria=sessao_plenaria)
- integrantes = []
- for m in mesa:
- parlamentar = Parlamentar.objects.get(
- id=m.parlamentar_id)
- cargo = CargoMesa.objects.get(
- id=m.cargo_id)
- integrante = {'parlamentar': parlamentar, 'cargo': cargo}
- integrantes.append(integrante)
- return ({'mesa': ordenar_integrantes_por_cargo(integrantes)})
+ mesa = IntegranteMesa.objects.filter(sessao_plenaria=sessao_plenaria).order_by('cargo_id')
+ integrantes = [{'parlamentar': m.parlamentar,
+ 'cargo': m.cargo} for m in mesa]
+ return {'mesa': integrantes}
def get_presenca_sessao(sessao_plenaria):
- presencas = SessaoPlenariaPresenca.objects.filter(
- sessao_plenaria_id=sessao_plenaria.id
- ).order_by('parlamentar__nome_parlamentar')
- parlamentares_sessao = [p.parlamentar for p in presencas]
+ parlamentares_sessao = [p.parlamentar for p in SessaoPlenariaPresenca.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
ausentes_sessao = JustificativaAusencia.objects.filter(
sessao_plenaria_id=sessao_plenaria.id
@@ -1440,48 +1430,45 @@ def get_oradores_expediente(sessao_plenaria):
'observacao': observacao
}
oradores.append(ora)
- context = {'oradores': oradores}
- return context
+ return {'oradores': oradores}
def get_presenca_ordem_do_dia(sessao_plenaria):
- mesa_aux = get_mesa_diretora(sessao_plenaria)
- presencas = PresencaOrdemDia.objects.filter(
- sessao_plenaria_id=sessao_plenaria.id
- ).order_by('parlamentar__nome_parlamentar')
+ parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
- parlamentares_mesa_dia = [m for m in mesa_aux['mesa']]
+ return {'presenca_ordem': parlamentares_ordem}
- presidente_dia = ''
- for m in mesa_aux['mesa']:
- if m['cargo'].descricao == 'Presidente':
- presidente_dia = [m['parlamentar']]
- break
- parlamentares_ordem = [p.parlamentar for p in presencas]
+def get_assinaturas(sessao_plenaria):
+ mesa_dia = get_mesa_diretora(sessao_plenaria)['mesa']
- cont = 0
- for index, parlamentar in enumerate(parlamentares_ordem):
- try:
- if parlamentar == parlamentares_mesa_dia[cont]["parlamentar"]:
- del(parlamentares_ordem[index])
- cont += 1
- except IndexError:
- pass
+ presidente_dia = next(iter(
+ [m['parlamentar'] for m in mesa_dia if m['cargo'].descricao == 'Presidente']),
+ '')
+
+ parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
+
+ parlamentares_mesa = [m['parlamentar'] for m in mesa_dia]
+
+ # filtra parlamentares retirando os que sao da mesa
+ parlamentares_ordem = [p for p in parlamentares_ordem if p not in parlamentares_mesa]
context = {}
- context.update({'presenca_ordem': parlamentares_ordem})
config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata
if config_assinatura_ata == 'T' and parlamentares_ordem:
context.update(
{'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'})
- context.update({'assinatura_mesa': parlamentares_mesa_dia,
+ context.update({'assinatura_mesa': mesa_dia,
'assinatura_presentes': parlamentares_ordem})
- elif config_assinatura_ata == 'M' and parlamentares_mesa_dia:
+ elif config_assinatura_ata == 'M' and mesa_dia:
context.update(
{'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'})
- context.update({'assinatura_presentes': parlamentares_mesa_dia})
+ context.update({'assinatura_presentes': mesa_dia})
elif config_assinatura_ata == 'P' and presidente_dia:
context.update(
{'texto_assinatura': 'Assinatura do Presidente da Sessão'})
@@ -1649,6 +1636,9 @@ class ResumoView(DetailView):
# Presença Ordem do Dia
context.update(get_presenca_ordem_do_dia(self.object))
# =====================================================================
+ # Assinaturas
+ context.update(get_assinaturas(self.object))
+ # =====================================================================
# Matérias Ordem do Dia
# Votos de Votação Nominal de Matérias Ordem do Dia
materias_ordem_dia_votacao_nominal = OrdemDia.objects.filter(
diff --git a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
index 40c4e718a..ae1d494e2 100644
--- a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
+++ b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
@@ -4,9 +4,9 @@
{% for m in materias_ordem %}
- Materia do Expediente: {{m.numero}} - {{m.titulo}}
+ {{m.numero}} - {{m.titulo}}
Descrição: {{m.ementa|safe}}
- Autor: {{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
+ Autor {{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
{% if m.numero_protocolo %}
Número de Protocolo: {{ m.numero_protocolo }}
{% endif %}
From 973ff973250b53aa748340e288012fbc66ccf925 Mon Sep 17 00:00:00 2001
From: Edward Ribeiro
Date: Wed, 27 Mar 2019 15:48:18 -0300
Subject: [PATCH 03/18] Fixes #2663
---
sapl/sessao/views.py | 3 ++-
sapl/templates/relatorios/header_ata.html | 2 +-
sapl/templates/relatorios/relatorio_ata.html | 3 ++-
.../sessao/blocos_ata/materias_ordem_dia.html | 10 +++++-----
.../sessao/blocos_ata/ocorrencias_da_sessao.html | 8 ++++----
5 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 236c9320d..ae786377e 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -1316,7 +1316,8 @@ def get_identificação_basica(sessao_plenaria):
'abertura': abertura, 'hora_inicio': sessao_plenaria.hora_inicio},
_('Encerramento: %(encerramento)s %(hora_fim)s') % {
'encerramento': encerramento, 'hora_fim': sessao_plenaria.hora_fim}
- ]})
+ ],
+ 'sessaoplenaria': sessao_plenaria})
def get_conteudo_multimidia(sessao_plenaria):
diff --git a/sapl/templates/relatorios/header_ata.html b/sapl/templates/relatorios/header_ata.html
index 494d2c60b..4cc43efe6 100644
--- a/sapl/templates/relatorios/header_ata.html
+++ b/sapl/templates/relatorios/header_ata.html
@@ -19,7 +19,7 @@
- {{casa}}
+ {{casa.nome}}
Sistema de Apoio ao Processo Legislativo
diff --git a/sapl/templates/relatorios/relatorio_ata.html b/sapl/templates/relatorios/relatorio_ata.html
index df927ba7f..743e13c82 100644
--- a/sapl/templates/relatorios/relatorio_ata.html
+++ b/sapl/templates/relatorios/relatorio_ata.html
@@ -37,7 +37,7 @@
- Extrato Reunião
+ Extrato Eletrônico da {{sessaoplenaria}}
{% include 'sessao/blocos_ata/identificacao_basica.html' %}
{% include 'sessao/blocos_ata/mesa_diretora.html' %}
{% include 'sessao/blocos_ata/lista_presenca.html' %}
@@ -47,6 +47,7 @@
{% include 'sessao/blocos_ata/lista_presenca_ordem_dia.html' %}
{% include 'sessao/blocos_ata/materias_ordem_dia.html' %}
{% include 'sessao/blocos_ata/oradores_explicacoes.html' %}
+ {% include 'sessao/blocos_ata/ocorrencias_da_sessao.html' %}
{% if assinatura_mesa or assinatura_presentes %}
diff --git a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
index ae1d494e2..d894e8a06 100644
--- a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
+++ b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
@@ -1,19 +1,19 @@
\ No newline at end of file
diff --git a/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html b/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html
index 0896cd9b0..3b3092d89 100644
--- a/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html
+++ b/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html
@@ -1,8 +1,8 @@
From f64a4e8d791bdac20ec958a74b9e4807dd92a71b Mon Sep 17 00:00:00 2001
From: Victor Fabre
Date: Wed, 27 Mar 2019 17:27:53 -0300
Subject: [PATCH 04/18] Fix #2663 (#2667)
---
sapl/sessao/views.py | 8 ++++----
sapl/templates/sessao/blocos_ata/assinaturas.html | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index ae786377e..4e4ad02fa 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -1445,9 +1445,9 @@ def get_presenca_ordem_do_dia(sessao_plenaria):
def get_assinaturas(sessao_plenaria):
mesa_dia = get_mesa_diretora(sessao_plenaria)['mesa']
- presidente_dia = next(iter(
+ presidente_dia = [next(iter(
[m['parlamentar'] for m in mesa_dia if m['cargo'].descricao == 'Presidente']),
- '')
+ '')]
parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter(
sessao_plenaria_id=sessao_plenaria.id
@@ -1469,11 +1469,11 @@ def get_assinaturas(sessao_plenaria):
elif config_assinatura_ata == 'M' and mesa_dia:
context.update(
{'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'})
- context.update({'assinatura_presentes': mesa_dia})
+ context.update({'assinatura_mesa': mesa_dia})
elif config_assinatura_ata == 'P' and presidente_dia:
context.update(
{'texto_assinatura': 'Assinatura do Presidente da Sessão'})
- context.update({'assinatura_presentes': presidente_dia})
+ context.update({'assinatura_mesa': presidente_dia})
return context
diff --git a/sapl/templates/sessao/blocos_ata/assinaturas.html b/sapl/templates/sessao/blocos_ata/assinaturas.html
index 990b3f8a8..9eba4ce9b 100644
--- a/sapl/templates/sessao/blocos_ata/assinaturas.html
+++ b/sapl/templates/sessao/blocos_ata/assinaturas.html
@@ -11,7 +11,7 @@
{% endfor %}
{% for p in assinatura_presentes %}
___________________________________________
- {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }}
+ {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}
{% endfor %}
From b912b03e9a0d27dc96988196be5df95dcd4c8546 Mon Sep 17 00:00:00 2001
From: Edward Ribeiro
Date: Thu, 28 Mar 2019 13:51:52 -0300
Subject: [PATCH 05/18] Release: 3.1.150
---
docker-compose.yml | 2 +-
sapl/settings.py | 2 +-
sapl/templates/base.html | 2 +-
setup.py | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index cb498a26d..5ef3b240e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,7 +11,7 @@ sapldb:
ports:
- "5432:5432"
sapl:
- image: interlegis/sapl:3.1.149
+ image: interlegis/sapl:3.1.150
restart: always
environment:
ADMIN_PASSWORD: interlegis
diff --git a/sapl/settings.py b/sapl/settings.py
index 517b76921..8bad6c92e 100644
--- a/sapl/settings.py
+++ b/sapl/settings.py
@@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/?next='
-SAPL_VERSION = '3.1.149'
+SAPL_VERSION = '3.1.150'
if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
diff --git a/sapl/templates/base.html b/sapl/templates/base.html
index a2de10343..2fa19c1cd 100644
--- a/sapl/templates/base.html
+++ b/sapl/templates/base.html
@@ -179,7 +179,7 @@
Desenvolvido pelo Interlegis em software livre e aberto.
- Release: 3.1.149
+ Release: 3.1.150
diff --git a/setup.py b/setup.py
index dbfa7fe8f..1edc89a91 100644
--- a/setup.py
+++ b/setup.py
@@ -43,7 +43,7 @@ install_requires = [
]
setup(
name='interlegis-sapl',
- version='3.1.149',
+ version='3.1.150',
packages=find_packages(),
include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',
From 0585bd7130efaa95b5718c3bebdadd3da8a51bea Mon Sep 17 00:00:00 2001
From: Edward
Date: Thu, 28 Mar 2019 17:29:13 -0300
Subject: [PATCH 06/18] =?UTF-8?q?HOT-FIX:=20remove=20refer=C3=AAncia=20dup?=
=?UTF-8?q?la=20a=20openssh-client?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index d970a4e4c..cc8d62e22 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,7 +3,7 @@ FROM alpine:3.8
ENV BUILD_PACKAGES postgresql-dev graphviz-dev graphviz build-base git pkgconfig \
python3-dev libxml2-dev jpeg-dev libressl-dev libffi-dev libxslt-dev \
nodejs py3-lxml py3-magic postgresql-client poppler-utils antiword \
- curl jq openssh-client vim openssh-client bash
+ curl jq openssh-client vim bash
RUN apk update --update-cache && apk upgrade
From 7e37308042141836943cd9744275855a5c1f004a Mon Sep 17 00:00:00 2001
From: Edward
Date: Thu, 28 Mar 2019 17:48:37 -0300
Subject: [PATCH 07/18] =?UTF-8?q?HOT-FIX:=20Remove=20coment=C3=A1rio=20de?=
=?UTF-8?q?=20Dockerfile?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Dockerfile | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index cc8d62e22..015357a40 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -32,9 +32,6 @@ RUN pip install -r /var/interlegis/sapl/requirements/dev-requirements.txt --upgr
COPY config/env_dockerfile /var/interlegis/sapl/sapl/.env
-# Configura timezone para BRT
-# RUN cp /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime && echo "America/Sao_Paulo" > /etc/timezone
-
RUN python3 manage.py collectstatic --noinput --clear
# Remove .env(fake) e sapl.db da imagem
From c9d2295033cc70ad20f49185307ce3076f8c36ed Mon Sep 17 00:00:00 2001
From: Cesar Augusto de Carvalho
Date: Fri, 29 Mar 2019 15:33:01 -0300
Subject: [PATCH 08/18] =?UTF-8?q?Fix=20Documento=20Acess=C3=B3rio=20em=20L?=
=?UTF-8?q?ote=20para=20Arquivos=20Grandes=20(#2664)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../migrations/0044_auto_20190327_1409.py | 22 +++++++++++++
sapl/materia/models.py | 1 +
sapl/materia/views.py | 32 ++++++++++++++++---
3 files changed, 51 insertions(+), 4 deletions(-)
create mode 100644 sapl/materia/migrations/0044_auto_20190327_1409.py
diff --git a/sapl/materia/migrations/0044_auto_20190327_1409.py b/sapl/materia/migrations/0044_auto_20190327_1409.py
new file mode 100644
index 000000000..5322d7833
--- /dev/null
+++ b/sapl/materia/migrations/0044_auto_20190327_1409.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-03-27 17:09
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import sapl.materia.models
+import sapl.utils
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('materia', '0043_auto_20190320_1749'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='documentoacessorio',
+ name='arquivo',
+ field=models.FileField(blank=True, max_length=255, null=True, upload_to=sapl.materia.models.anexo_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Texto Integral'),
+ ),
+ ]
diff --git a/sapl/materia/models.py b/sapl/materia/models.py
index af4cb1231..c7aaaed15 100644
--- a/sapl/materia/models.py
+++ b/sapl/materia/models.py
@@ -497,6 +497,7 @@ class DocumentoAcessorio(models.Model):
arquivo = models.FileField(
blank=True,
null=True,
+ max_length=255,
upload_to=anexo_upload_path,
verbose_name=_('Texto Integral'),
validators=[restringe_tipos_de_arquivo_txt])
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
index 696b1235a..846f367fa 100644
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -1,5 +1,10 @@
-from datetime import datetime
import logging
+import os
+import shutil
+import tempfile
+import weasyprint
+
+from datetime import datetime
from random import choice
from string import ascii_letters, digits
@@ -45,6 +50,7 @@ from sapl.materia.forms import (AnexadaForm, AutoriaForm,
from sapl.norma.models import LegislacaoCitada
from sapl.parlamentares.models import Legislatura
from sapl.protocoloadm.models import Protocolo
+from sapl.settings import MEDIA_ROOT
from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, SEPARADOR_HASH_PROPOSICAO,
gerar_hash_arquivo, get_base_url,
get_mime_type_from_file_extension, montar_row_autor,
@@ -2035,17 +2041,35 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
+ tmp_name = os.path.join(tempfile.gettempdir(), request.FILES['arquivo'].name)
+ with open(tmp_name, 'wb') as destination:
+ for chunk in request.FILES['arquivo'].chunks():
+ destination.write(chunk)
+
+ doc_data = tz.localize(datetime.strptime(
+ request.POST['data'], "%d/%m/%Y"))
for materia_id in marcadas:
doc = DocumentoAcessorio()
doc.materia_id = materia_id
doc.tipo = tipo
- doc.arquivo = request.FILES['arquivo']
doc.nome = request.POST['nome']
- doc.data = tz.localize(datetime.strptime(
- request.POST['data'], "%d/%m/%Y"))
+ doc.data = doc_data
doc.autor = request.POST['autor']
doc.ementa = request.POST['ementa']
doc.save()
+ diretorio = os.path.join(MEDIA_ROOT,
+ 'sapl/public/documentoacessorio',
+ str(doc_data.year),
+ str(doc.id))
+ if not os.path.exists(diretorio):
+ os.makedirs(diretorio)
+ file_path = os.path.join(diretorio,
+ request.FILES['arquivo'].name)
+ shutil.copy2(tmp_name, file_path)
+ doc.arquivo.name = file_path.split(MEDIA_ROOT)[1] # Retira MEDIA_ROOT do nome
+ doc.save()
+ os.remove(tmp_name)
+
msg = _('Documento(s) criado(s).')
messages.add_message(request, messages.SUCCESS, msg)
return self.get(request, self.kwargs)
From fb6832e7fb38bab0a9938fd8ef4ff9caaa7cfdc0 Mon Sep 17 00:00:00 2001
From: Cesar Augusto de Carvalho
Date: Mon, 1 Apr 2019 14:29:06 -0300
Subject: [PATCH 09/18] =?UTF-8?q?Fix=20#2665=20-=20Tramitar=20mat=C3=A9ria?=
=?UTF-8?q?s=20anexadas=20junto=20com=20as=20mat=C3=A9rias=20anexadoras=20?=
=?UTF-8?q?(#2674)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sapl/materia/views.py | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
index 846f367fa..a2366c8d9 100644
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -3,6 +3,7 @@ import os
import shutil
import tempfile
import weasyprint
+import itertools
from datetime import datetime
from random import choice
@@ -2249,8 +2250,18 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
# issue https://github.com/interlegis/sapl/issues/1123
# TODO: usar Form
urgente = request.POST['urgente'] == 'True'
- flag_error = False
- for materia_id in marcadas:
+ flag_error = False
+
+ materias_principais = [m for m in MateriaLegislativa.objects.filter(id__in=marcadas)]
+ materias_anexadas = [m.anexadas.all() for m in MateriaLegislativa.objects.filter(id__in=marcadas) if m.anexadas.all()]
+ materias_anexadas = list(itertools.chain.from_iterable(materias_anexadas))
+ tramitacao_local = int(request.POST['unidade_tramitacao_local'])
+ materias_anexadas = list(filter(lambda ma : not ma.tramitacao_set.all() or \
+ ma.tramitacao_set.last().unidade_tramitacao_destino.id == tramitacao_local,
+ materias_anexadas))
+ materias = set(materias_principais + materias_anexadas)
+
+ for materia in materias:
try:
data_tramitacao = tz.localize(datetime.strptime(
request.POST['data_tramitacao'], "%d/%m/%Y"))
@@ -2260,7 +2271,7 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
return self.get(request, self.kwargs)
t = Tramitacao(
- materia_id=materia_id,
+ materia=materia,
data_tramitacao=data_tramitacao,
data_encaminhamento=data_encaminhamento,
data_fim_prazo=data_fim_prazo,
@@ -2294,7 +2305,7 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
status = StatusTramitacao.objects.get(id=request.POST['status'])
- for materia in MateriaLegislativa.objects.filter(id__in=marcadas):
+ for materia in materias:
if status.indicador == 'F':
materia.em_tramitacao = False
elif self.primeira_tramitacao:
From 2bcaedda76a8a99e4febac0595d2d4e565b2da22 Mon Sep 17 00:00:00 2001
From: Edward Ribeiro
Date: Mon, 1 Apr 2019 14:48:45 -0300
Subject: [PATCH 10/18] =?UTF-8?q?Retira=20atributos=20class=20e=20espa?=
=?UTF-8?q?=C3=A7os=20de=20tags=20?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sapl/relatorios/views.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py
index dec1d50b7..9439b1578 100755
--- a/sapl/relatorios/views.py
+++ b/sapl/relatorios/views.py
@@ -578,6 +578,8 @@ def get_sessao_plenaria(sessao, casa):
# unescape HTML codes
# https://github.com/interlegis/sapl/issues/1046
conteudo = re.sub('style=".*?"', '', conteudo)
+ conteudo = re.sub('class=".*?"', '', conteudo)
+ conteudo = re.sub('
', '
', conteudo)
conteudo = html.unescape(conteudo)
# escape special character '&'
From 4b35e6a4fe37ba10d6ac95ae02cc220a14c61e80 Mon Sep 17 00:00:00 2001
From: Ulysses Lara
Date: Mon, 1 Apr 2019 15:09:50 -0300
Subject: [PATCH 11/18] Fix #2663 parte relacionada a turno (#2675)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Fix #2663 parte relacionada a turno
* Retira parênteses desnecessários
---
sapl/sessao/views.py | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 4e4ad02fa..9300ab9e1 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -1378,9 +1378,15 @@ def get_materias_expediente(sessao_plenaria):
ementa = m.materia.ementa
titulo = m.materia
numero = m.numero_ordem
- tramitacao = m.materia.tramitacao_set.last()
- turno = None
+ tramitacao = ''
+ tramitacoes = Tramitacao.objects.filter(materia=m.materia).order_by('-pk')
+ for aux_tramitacao in tramitacoes:
+ if aux_tramitacao.turno:
+ tramitacao = aux_tramitacao
+ break
+
+ turno = None
if tramitacao:
turno = get_turno(tramitacao.turno)
@@ -1486,7 +1492,14 @@ def get_materias_ordem_do_dia(sessao_plenaria):
ementa_observacao = o.observacao
titulo = o.materia
numero = o.numero_ordem
- tramitacao = o.materia.tramitacao_set.last()
+
+ tramitacao = ''
+ tramitacoes = Tramitacao.objects.filter(materia=o.materia).order_by('-pk')
+ for aux_tramitacao in tramitacoes:
+ if aux_tramitacao.turno:
+ tramitacao = aux_tramitacao
+ break
+
turno = None
if tramitacao:
turno = get_turno(tramitacao.turno)
From 52de1510019bdfbc77a6bcb962868bdf9356686e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Rodrigues?=
Date: Mon, 1 Apr 2019 15:11:33 -0300
Subject: [PATCH 12/18] Fix #2671 (#2673)
* Fix #2671
* Atualizar sessao/forms.py
* Atualizar sessao/forms.py
---
sapl/sessao/forms.py | 22 ++++++++++++++++++++++
sapl/sessao/views.py | 1 +
2 files changed, 23 insertions(+)
diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py
index c2532b4a1..172b37be5 100644
--- a/sapl/sessao/forms.py
+++ b/sapl/sessao/forms.py
@@ -692,7 +692,29 @@ class OradorForm(ModelForm):
self.fields['parlamentar'].queryset = Parlamentar.objects.filter(
id__in=ids).order_by('nome_parlamentar')
+
+ def clean(self):
+ super(OradorForm, self).clean()
+ cleaned_data = self.cleaned_data
+
+ if not self.is_valid():
+ return self.cleaned_data
+ sessao_id = self.initial['id_sessao']
+ numero = self.initial.get('numero')
+ numero_ordem = cleaned_data['numero_ordem']
+ ordem = Orador.objects.filter(
+ sessao_plenaria_id=sessao_id,
+ numero_ordem=numero_ordem
+ ).exists()
+
+ if ordem and numero_ordem != numero:
+ raise ValidationError(_(
+ "Já existe orador nesta posição de ordem de pronunciamento"
+ ))
+
+ return self.cleaned_data
+
class Meta:
model = Orador
exclude = ['sessao_plenaria']
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 9300ab9e1..c5a6620c4 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -620,6 +620,7 @@ class OradorCrud(OradorCrud):
def get_initial(self):
initial = super(UpdateView, self).get_initial()
initial.update({'id_sessao': self.object.sessao_plenaria.id})
+ initial.update({'numero':self.object.numero_ordem})
return initial
From 31e3cd7b4474c2273a8a8606110ec78bd772dc45 Mon Sep 17 00:00:00 2001
From: Victor Fabre
Date: Mon, 1 Apr 2019 17:29:10 -0300
Subject: [PATCH 13/18] Fix #2679 (#2680)
---
sapl/materia/forms.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py
index 4b75e134a..cf200447e 100644
--- a/sapl/materia/forms.py
+++ b/sapl/materia/forms.py
@@ -727,7 +727,7 @@ class AnexadaForm(ModelForm):
empty_label='Selecione',
)
- numero = forms.CharField(label='Número', required=True)
+ numero = forms.IntegerField(label='Número', required=True)
ano = forms.CharField(label='Ano', required=True)
@@ -751,8 +751,8 @@ class AnexadaForm(ModelForm):
ano=cleaned_data['ano'],
tipo=cleaned_data['tipo'])
except ObjectDoesNotExist:
- msg = _('A MateriaLegislativa a ser anexada (numero={}, ano={}, tipo={}) não existe no cadastro'
- ' de matérias legislativas.'.format(cleaned_data['numero'], cleaned_data['ano'], cleaned_data['tipo']))
+ msg = _('A {} {}/{} não existe no cadastro de matérias legislativas.'
+ .format(cleaned_data['tipo'], cleaned_data['numero'], cleaned_data['ano']))
self.logger.error("A matéria a ser anexada não existe no cadastro"
" de matérias legislativas.")
raise ValidationError(msg)
From 0b7ab48218e76a8cfb69e48499ab7b2779391e18 Mon Sep 17 00:00:00 2001
From: Victor Fabre
Date: Mon, 1 Apr 2019 17:29:17 -0300
Subject: [PATCH 14/18] Fix #2678 (#2681)
---
sapl/sessao/urls.py | 6 ++++++
sapl/sessao/views.py | 19 +++++++++++++++++++
.../sessao/expedientemateria_list.html | 5 ++++-
sapl/templates/sessao/ordemdia_list.html | 5 ++++-
4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py
index 4da3a761a..ba0735ec6 100644
--- a/sapl/sessao/urls.py
+++ b/sapl/sessao/urls.py
@@ -28,6 +28,8 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
remove_parlamentar_composicao,
reordernar_materias_expediente,
reordernar_materias_ordem,
+ renumerar_materias_ordem,
+ renumerar_materias_expediente,
sessao_legislativa_legislatura_ajax,
VotacaoEmBlocoOrdemDia, VotacaoEmBlocoExpediente,
VotacaoEmBlocoSimbolicaView, VotacaoEmBlocoNominalView)
@@ -75,6 +77,10 @@ urlpatterns = [
name="reordenar_expediente"),
url(r'^sessao/(?P\d+)/reordenar-ordem$', reordernar_materias_ordem,
name="reordenar_ordem"),
+ url(r'^sessao/(?P\d+)/renumerar-ordem$', renumerar_materias_ordem,
+ name="renumerar_ordem"),
+ url(r'^sessao/(?P\d+)/renumerar-materias-expediente$', renumerar_materias_expediente,
+ name="renumerar_materias_expediente"),
url(r'^sistema/sessao-plenaria/tipo/',
include(TipoSessaoCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-resultado-votacao/',
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index c5a6620c4..550b231be 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -93,6 +93,25 @@ def reordernar_materias_ordem(request, pk):
return HttpResponseRedirect(
reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}))
+def renumerar_materias_ordem(request, pk):
+ ordens = OrdemDia.objects.filter(sessao_plenaria_id=pk)
+
+ for ordem_num, o in enumerate(ordens, 1):
+ o.numero_ordem = ordem_num
+ o.save()
+
+ return HttpResponseRedirect(
+ reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}))
+
+def renumerar_materias_expediente(request, pk):
+ expedientes = ExpedienteMateria.objects.filter(sessao_plenaria_id=pk)
+
+ for exp_num, e in enumerate(expedientes, 1):
+ e.numero_ordem = exp_num
+ e.save()
+
+ return HttpResponseRedirect(
+ reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': pk}))
def verifica_presenca(request, model, spk):
logger = logging.getLogger(__name__)
diff --git a/sapl/templates/sessao/expedientemateria_list.html b/sapl/templates/sessao/expedientemateria_list.html
index a2ce5e2ab..e1bd0f781 100644
--- a/sapl/templates/sessao/expedientemateria_list.html
+++ b/sapl/templates/sessao/expedientemateria_list.html
@@ -7,7 +7,10 @@
{% if perms|get_add_perm:view %}
- {% blocktrans with verbose_name=view.verbose_name %} Ajustar Ordenação {% endblocktrans %}
+ {% blocktrans with verbose_name=view.verbose_name %} Reordenar pela precedência {% endblocktrans %}
+
+
+ {% blocktrans with verbose_name=view.verbose_name %} Renumerar Expediente {% endblocktrans %}
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %}
diff --git a/sapl/templates/sessao/ordemdia_list.html b/sapl/templates/sessao/ordemdia_list.html
index d12e3f356..bc95cf1f1 100644
--- a/sapl/templates/sessao/ordemdia_list.html
+++ b/sapl/templates/sessao/ordemdia_list.html
@@ -7,7 +7,10 @@
{% if perms|get_add_perm:view %}
- {% blocktrans with verbose_name=view.verbose_name %} Ajustar Ordenação {% endblocktrans %}
+ {% blocktrans with verbose_name=view.verbose_name %} Reordenar pela precedência {% endblocktrans %}
+
+
+ {% blocktrans with verbose_name=view.verbose_name %} Renumerar Ordem {% endblocktrans %}
{% blocktrans with verbose_name=view.verbose_name %} Adicionar Várias Matérias {% endblocktrans %}
From a64e7dbb093d7beb9f617746fa3b403457500b7f Mon Sep 17 00:00:00 2001
From: Edward Ribeiro
Date: Mon, 1 Apr 2019 17:30:17 -0300
Subject: [PATCH 15/18] HOT-FIX: adiciona assinaturas no extrato do PDF
---
sapl/relatorios/views.py | 17 +++++++++--------
sapl/templates/relatorios/relatorio_ata.html | 5 +++--
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py
index 9439b1578..deb1e885f 100755
--- a/sapl/relatorios/views.py
+++ b/sapl/relatorios/views.py
@@ -28,10 +28,10 @@ from sapl.settings import STATIC_ROOT
from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data
from sapl.sessao.views import (get_identificação_basica, get_mesa_diretora,
- get_presenca_sessao,get_expedientes,
- get_materias_expediente,get_oradores_expediente,
- get_presenca_ordem_do_dia,get_materias_ordem_do_dia,
- get_oradores_explicações_pessoais, get_ocorrencias_da_sessão)
+ get_presenca_sessao, get_expedientes,
+ get_materias_expediente, get_oradores_expediente,
+ get_presenca_ordem_do_dia, get_materias_ordem_do_dia,
+ get_oradores_explicações_pessoais, get_ocorrencias_da_sessão, get_assinaturas)
from .templates import (pdf_capa_processo_gerar,
pdf_documento_administrativo_gerar, pdf_espelho_gerar,
@@ -1258,12 +1258,13 @@ def resumo_ata_pdf(request,pk):
context.update(get_materias_ordem_do_dia(sessao_plenaria))
context.update(get_oradores_explicações_pessoais(sessao_plenaria))
context.update(get_ocorrencias_da_sessão(sessao_plenaria))
- context.update({'object':sessao_plenaria})
+ context.update(get_assinaturas(sessao_plenaria))
+ context.update({'object': sessao_plenaria})
context.update({'data': dt.today().strftime('%d/%m/%Y')})
- context.update({'rodape':rodape})
- header_context = {"casa":casa, 'logotipo':casa.logotipo, 'MEDIA_URL': MEDIA_URL}
+ context.update({'rodape': rodape})
+ header_context = {"casa": casa, 'logotipo':casa.logotipo, 'MEDIA_URL': MEDIA_URL}
- html_template = render_to_string('relatorios/relatorio_ata.html',context)
+ html_template = render_to_string('relatorios/relatorio_ata.html', context)
html_header = render_to_string('relatorios/header_ata.html', header_context)
pdf_file = make_pdf(base_url=base_url,main_template=html_template,header_template=html_header)
diff --git a/sapl/templates/relatorios/relatorio_ata.html b/sapl/templates/relatorios/relatorio_ata.html
index 743e13c82..7d6c45d7b 100644
--- a/sapl/templates/relatorios/relatorio_ata.html
+++ b/sapl/templates/relatorios/relatorio_ata.html
@@ -82,12 +82,13 @@
_____________________
- {{p.cargo}}: {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }}
+
+ {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}
{% else %}
_____________________
- {{p.parlamentar.nome_completo}} / {{ p.parlamentar|filiacao_data_filter:object.data_inicio }}
+ {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }}
|
From 8068e64be4275300c57fdf9f357350198d9a1e1c Mon Sep 17 00:00:00 2001
From: Leandro Roberto
Date: Tue, 2 Apr 2019 00:07:18 -0300
Subject: [PATCH 16/18] add endpoint get ultima_tramitacao
---
sapl/api/views.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/sapl/api/views.py b/sapl/api/views.py
index f2f146e24..f15232871 100644
--- a/sapl/api/views.py
+++ b/sapl/api/views.py
@@ -349,6 +349,23 @@ class _ProposicaoViewSet(SaplSetViews['materia']['proposicao']):
return qs
+class _MateriaLegislativaViewSet(SaplSetViews['materia']['materialegislativa']):
+
+ @action(detail=True, methods=['GET'])
+ def ultima_tramitacao(self, request, *args, **kwargs):
+
+ materia = self.get_object()
+ if not materia.tramitacao_set.exists():
+ return Response({})
+
+ ultima_tramitacao = materia.tramitacao_set.last()
+
+ serializer_class = SaplSetViews[
+ 'materia']['tramitacao'].serializer_class(ultima_tramitacao)
+
+ return Response(serializer_class.data)
+
+
class _TipoMateriaLegislativaViewSet(SaplSetViews['materia']['tipomaterialegislativa']):
@action(detail=True, methods=['POST'])
@@ -443,6 +460,8 @@ class _SessaoPlenariaViewSet(
SaplSetViews['base']['autor'] = _AutorViewSet.build_class_with_actions()
+
+SaplSetViews['materia']['materialegislativa'] = _MateriaLegislativaViewSet
SaplSetViews['materia']['proposicao'] = _ProposicaoViewSet
SaplSetViews['materia']['tipomaterialegislativa'] = _TipoMateriaLegislativaViewSet
From e523e9b23cc0b29b1e9c74312d5c1dd1a87fbc19 Mon Sep 17 00:00:00 2001
From: Leandro Roberto
Date: Tue, 2 Apr 2019 00:18:05 -0300
Subject: [PATCH 17/18] corrige classe BusinessRulesNotImplementedMixin
---
sapl/api/views.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/sapl/api/views.py b/sapl/api/views.py
index f15232871..5d2ca37eb 100644
--- a/sapl/api/views.py
+++ b/sapl/api/views.py
@@ -31,11 +31,8 @@ class BusinessRulesNotImplementedMixin:
def create(self, request, *args, **kwargs):
raise Exception(_("POST Create não implementado"))
- def put(self, request, *args, **kwargs):
- raise Exception(_("PUT Update não implementado"))
-
- def patch(self, request, *args, **kwargs):
- raise Exception(_("PATCH Partial Update não implementado"))
+ def update(self, request, *args, **kwargs):
+ raise Exception(_("PUT and PATCH não implementado"))
def delete(self, request, *args, **kwargs):
raise Exception(_("DELETE Delete não implementado"))
From dfe74c59f706f61547fa9cfb1f2d926b1d5b25f1 Mon Sep 17 00:00:00 2001
From: Leandro Roberto
Date: Tue, 2 Apr 2019 02:02:23 -0300
Subject: [PATCH 18/18] =?UTF-8?q?simplifica=20customiza=C3=A7=C3=A3o=20de?=
=?UTF-8?q?=20viewsets=20da=20api?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sapl/api/urls.py | 7 +--
sapl/api/views.py | 110 ++++++++++++++++++++++++++++------------------
2 files changed, 71 insertions(+), 46 deletions(-)
diff --git a/sapl/api/urls.py b/sapl/api/urls.py
index 3e874add2..27196146d 100644
--- a/sapl/api/urls.py
+++ b/sapl/api/urls.py
@@ -8,7 +8,7 @@ from rest_framework.routers import DefaultRouter
from sapl.api.deprecated import MateriaLegislativaViewSet, SessaoPlenariaViewSet,\
AutoresProvaveisListView, AutoresPossiveisListView, AutorListView,\
ModelChoiceView
-from sapl.api.views import SaplSetViews
+from sapl.api.views import SaplApiViewSetConstrutor
from .apps import AppConfig
@@ -21,9 +21,10 @@ router.register(r'materia$', MateriaLegislativaViewSet)
router.register(r'sessao-plenaria', SessaoPlenariaViewSet)
-for app, built_sets in SaplSetViews.items():
+for app, built_sets in SaplApiViewSetConstrutor._built_sets.items():
for view_prefix, viewset in built_sets.items():
- router.register(app + '/' + view_prefix, viewset)
+ router.register(app.label + '/' +
+ view_prefix._meta.model_name, viewset)
urlpatterns_router = router.urls
diff --git a/sapl/api/views.py b/sapl/api/views.py
index 5d2ca37eb..1cfdd1d44 100644
--- a/sapl/api/views.py
+++ b/sapl/api/views.py
@@ -22,8 +22,12 @@ from sapl.api.forms import SaplFilterSetMixin
from sapl.api.permissions import SaplModelPermissions
from sapl.api.serializers import ChoiceSerializer
from sapl.base.models import Autor, AppConfig, DOC_ADM_OSTENSIVO
-from sapl.materia.models import Proposicao, TipoMateriaLegislativa
+from sapl.materia.models import Proposicao, TipoMateriaLegislativa,\
+ MateriaLegislativa, Tramitacao
from sapl.parlamentares.models import Parlamentar
+from sapl.protocoloadm.models import DocumentoAdministrativo,\
+ DocumentoAcessorioAdministrativo, TramitacaoAdministrativo
+from sapl.sessao.models import SessaoPlenaria
from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria
@@ -38,10 +42,18 @@ class BusinessRulesNotImplementedMixin:
raise Exception(_("DELETE Delete não implementado"))
-class SaplApiViewSetConstrutor(ModelViewSet):
-
+class SaplApiViewSet(ModelViewSet):
filter_backends = (DjangoFilterBackend,)
+
+class SaplApiViewSetConstrutor():
+
+ _built_sets = {}
+
+ @classonlymethod
+ def get_class_for_model(cls, model):
+ return cls._built_sets[model._meta.app_config][model]
+
@classonlymethod
def build_class(cls):
import inspect
@@ -92,7 +104,7 @@ class SaplApiViewSetConstrutor(ModelViewSet):
model = _model
# Define uma classe padrão ModelViewSet de DRF
- class ModelSaplViewSet(cls):
+ class ModelSaplViewSet(SaplApiViewSet):
queryset = _model.objects.all()
# Utiliza o filtro customizado pela classe
@@ -116,12 +128,12 @@ class SaplApiViewSetConstrutor(ModelViewSet):
apps_sapl = [apps.apps.get_app_config(
n[5:]) for n in settings.SAPL_APPS]
for app in apps_sapl:
- built_sets[app.label] = {}
+ cls._built_sets[app] = {}
for model in app.get_models():
- built_sets[app.label][model._meta.model_name] = build(model)
+ cls._built_sets[app][model] = build(model)
- return built_sets
+SaplApiViewSetConstrutor.build_class()
"""
1. Constroi uma rest_framework.viewsets.ModelViewSet para
@@ -184,15 +196,39 @@ class SaplApiViewSetConstrutor(ModelViewSet):
}
"""
-SaplSetViews = SaplApiViewSetConstrutor.build_class()
-
# Toda Classe construida acima, pode ser redefinida e aplicado quaisquer
# das possibilidades para uma classe normal criada a partir de
# rest_framework.viewsets.ModelViewSet conforme exemplo para a classe autor
+# decorator para recuperar e transformar o default
+
+
+class customize(object):
+ def __init__(self, model):
+ self.model = model
+
+ def __call__(self, cls):
+
+ class _SaplApiViewSet(
+ cls,
+ SaplApiViewSetConstrutor._built_sets[
+ self.model._meta.app_config][self.model]
+ ):
+ pass
+
+ if hasattr(_SaplApiViewSet, 'build'):
+ _SaplApiViewSet = _SaplApiViewSet.build()
+
+ SaplApiViewSetConstrutor._built_sets[
+ self.model._meta.app_config][self.model] = _SaplApiViewSet
+ return _SaplApiViewSet
+
# Customização para AutorViewSet com implementação de actions específicas
-class _AutorViewSet(SaplSetViews['base']['autor']):
+
+
+@customize(Autor)
+class _AutorViewSet:
"""
Neste exemplo de customização do que foi criado em
SaplApiViewSetConstrutor além do ofertado por
@@ -237,7 +273,7 @@ class _AutorViewSet(SaplSetViews['base']['autor']):
return Response(serializer.data)
@classonlymethod
- def build_class_with_actions(cls):
+ def build(cls):
models_with_gr_for_autor = models_with_gr_for_model(Autor)
@@ -260,7 +296,8 @@ class _AutorViewSet(SaplSetViews['base']['autor']):
return cls
-class _ParlamentarViewSet(SaplSetViews['parlamentares']['parlamentar']):
+@customize(Parlamentar)
+class _ParlamentarViewSet:
@action(detail=True)
def proposicoes(self, request, *args, **kwargs):
"""
@@ -285,15 +322,16 @@ class _ParlamentarViewSet(SaplSetViews['parlamentares']['parlamentar']):
page = self.paginate_queryset(qs)
if page is not None:
- serializer = SaplSetViews[
- 'materia']['proposicao'].serializer_class(page, many=True)
+ serializer = SaplApiViewSetConstrutor.get_class_for_model(
+ Proposicao).serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(page, many=True)
return Response(serializer.data)
-class _ProposicaoViewSet(SaplSetViews['materia']['proposicao']):
+@customize(Proposicao)
+class _ProposicaoViewSet():
"""
list:
Retorna lista de Proposições
@@ -346,7 +384,8 @@ class _ProposicaoViewSet(SaplSetViews['materia']['proposicao']):
return qs
-class _MateriaLegislativaViewSet(SaplSetViews['materia']['materialegislativa']):
+@customize(MateriaLegislativa)
+class _MateriaLegislativaViewSet:
@action(detail=True, methods=['GET'])
def ultima_tramitacao(self, request, *args, **kwargs):
@@ -357,13 +396,14 @@ class _MateriaLegislativaViewSet(SaplSetViews['materia']['materialegislativa']):
ultima_tramitacao = materia.tramitacao_set.last()
- serializer_class = SaplSetViews[
- 'materia']['tramitacao'].serializer_class(ultima_tramitacao)
+ serializer_class = SaplApiViewSetConstrutor.get_class_for_model(
+ Tramitacao).serializer_class(ultima_tramitacao)
return Response(serializer_class.data)
-class _TipoMateriaLegislativaViewSet(SaplSetViews['materia']['tipomaterialegislativa']):
+@customize(TipoMateriaLegislativa)
+class _TipoMateriaLegislativaViewSet:
@action(detail=True, methods=['POST'])
def change_position(self, request, *args, **kwargs):
@@ -380,7 +420,8 @@ class _TipoMateriaLegislativaViewSet(SaplSetViews['materia']['tipomaterialegisla
return Response(result)
-class _DocumentoAdministrativoViewSet(SaplSetViews['protocoloadm']['documentoadministrativo']):
+@customize(DocumentoAdministrativo)
+class _DocumentoAdministrativoViewSet:
class DocumentoAdministrativoPermission(SaplModelPermissions):
def has_permission(self, request, view):
@@ -414,8 +455,8 @@ class _DocumentoAdministrativoViewSet(SaplSetViews['protocoloadm']['documentoadm
return qs
-class _DocumentoAcessorioAdministrativoViewSet(
- SaplSetViews['protocoloadm']['documentoacessorioadministrativo']):
+@customize(DocumentoAcessorioAdministrativo)
+class _DocumentoAcessorioAdministrativoViewSet:
permission_classes = (
_DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission, )
@@ -428,9 +469,8 @@ class _DocumentoAcessorioAdministrativoViewSet(
return qs
-class _TramitacaoAdministrativoViewSet(
- SaplSetViews['protocoloadm']['tramitacaoadministrativo'],
- BusinessRulesNotImplementedMixin):
+@customize(TramitacaoAdministrativo)
+class _TramitacaoAdministrativoViewSet(BusinessRulesNotImplementedMixin):
# TODO: Implementar regras de manutenção das tramitações de docs adms
permission_classes = (
@@ -444,8 +484,8 @@ class _TramitacaoAdministrativoViewSet(
return qs
-class _SessaoPlenariaViewSet(
- SaplSetViews['sessao']['sessaoplenaria']):
+@customize(SessaoPlenaria)
+class _SessaoPlenariaViewSet:
@action(detail=False)
def years(self, request, *args, **kwargs):
@@ -453,19 +493,3 @@ class _SessaoPlenariaViewSet(
serializer = ChoiceSerializer(years, many=True)
return Response(serializer.data)
-
-
-SaplSetViews['base']['autor'] = _AutorViewSet.build_class_with_actions()
-
-
-SaplSetViews['materia']['materialegislativa'] = _MateriaLegislativaViewSet
-SaplSetViews['materia']['proposicao'] = _ProposicaoViewSet
-SaplSetViews['materia']['tipomaterialegislativa'] = _TipoMateriaLegislativaViewSet
-
-SaplSetViews['parlamentares']['parlamentar'] = _ParlamentarViewSet
-
-SaplSetViews['protocoloadm']['documentoadministrativo'] = _DocumentoAdministrativoViewSet
-SaplSetViews['protocoloadm']['documentoacessorioadministrativo'] = _DocumentoAcessorioAdministrativoViewSet
-SaplSetViews['protocoloadm']['tramitacaoadministrativo'] = _TramitacaoAdministrativoViewSet
-
-SaplSetViews['sessao']['sessaoplenaria'] = _SessaoPlenariaViewSet