From d0f6f7d43adc58267f016d143062b8d86f348286 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 1 Sep 2018 16:41:23 -0300 Subject: [PATCH 01/88] Acrescenta mais links p a msg de ressucitados --- sapl/legacy/scripts/ressucita_dependencias.py | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 7b37c1977..daa4ed126 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -34,29 +34,36 @@ for tabela_origem, campo, tabela_destino in [ urls = ''' -autor /sistema/autor -cargo_comissao /sistema/comissao/cargo -legislatura /sistema/parlamentar/legislatura -materia_legislativa /materia -norma_juridica /norma -parlamentar /parlamentar -sessao_legislativa /sistema/mesa-diretora/sessao-legislativa -sessao_plenaria /sessao -status_tramitacao /sistema/materia/status-tramitacao -tipo_autor /sistema/autor/tipo -tipo_expediente /sistema/sessao-plenaria/tipo-expediente -tipo_proposicao /sistema/proposicao/tipo -tipo_resultado_votacao /sistema/sessao-plenaria/tipo-resultado-votacao -unidade_tramitacao /sistema/materia/unidade-tramitacao -tipo_documento /sistema/materia/tipo-documento -orgao /sistema/materia/orgao -tipo_sessao_plenaria /sistema/sessao-plenaria/tipo -cargo_mesa /sistema/mesa-diretora/cargo-mesa -documento_administrativo /docadm -tipo_materia_legislativa /sistema/materia/tipo -tipo_norma_juridica /sistema/norma/tipo -comissao /comissao -registro_votacao ????????? +autor /sistema/autor +cargo_comissao /sistema/comissao/cargo +legislatura /sistema/parlamentar/legislatura +materia_legislativa /materia +norma_juridica /norma +parlamentar /parlamentar +sessao_legislativa /sistema/mesa-diretora/sessao-legislativa +sessao_plenaria /sessao +status_tramitacao /sistema/materia/status-tramitacao +tipo_autor /sistema/autor/tipo +tipo_expediente /sistema/sessao-plenaria/tipo-expediente +tipo_proposicao /sistema/proposicao/tipo +tipo_resultado_votacao /sistema/sessao-plenaria/tipo-resultado-votacao +unidade_tramitacao /sistema/materia/unidade-tramitacao +tipo_documento /sistema/materia/tipo-documento +orgao /sistema/materia/orgao +tipo_sessao_plenaria /sistema/sessao-plenaria/tipo +cargo_mesa /sistema/mesa-diretora/cargo-mesa +documento_administrativo /docadm +tipo_materia_legislativa /sistema/materia/tipo +tipo_norma_juridica /sistema/norma/tipo +comissao /comissao +assunto_materia /sistema/assunto-materia +coligacao /sistema/coligacao +nivel_instrucao /sistema/parlamentar/nivel-instrucao +partido /sistema/parlamentar/partido +regime_tramitacao /sistema/materia/regime-tramitacao +tipo_comissao /sistema/comissao/tipo +tipo_documento_administrativo /sistema/tipo-documento-adm +registro_votacao /admin/sessao/registrovotacao ''' urls = dict(stripsplit(urls)) From bbf79299b380d83a7e764d744ed38795b931a693 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 1 Sep 2018 17:13:57 -0300 Subject: [PATCH 02/88] =?UTF-8?q?Adiciona=20cria=C3=A7=C3=A3o=20de=20autor?= =?UTF-8?q?=20ao=20ressucitar=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/.flake8 | 3 +++ sapl/legacy/scripts/ressucita_dependencias.py | 21 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 sapl/legacy/scripts/.flake8 diff --git a/sapl/legacy/scripts/.flake8 b/sapl/legacy/scripts/.flake8 new file mode 100644 index 000000000..977657542 --- /dev/null +++ b/sapl/legacy/scripts/.flake8 @@ -0,0 +1,3 @@ +[flake8] +ignore = E501 + diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index daa4ed126..7f51de9f7 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -221,6 +221,13 @@ def get_dependencias_a_ressucitar(slug): return preambulo, desexcluir, criar +# deve ser idempotente pois é usada na criação de autor +# por isso o ON DUPLICATE KEY UPDATE +SQL_INSERT_TIPO_AUTOR = ''' + insert into tipo_autor (tip_autor, des_tipo_autor, ind_excluido) + values ({}, "DESCONHECIDO", 0) ON DUPLICATE KEY UPDATE ind_excluido = 0; + ''' + SQLS_CRIACAO = [ ('tipo_proposicao', ''' insert into tipo_materia_legislativa ( @@ -239,14 +246,18 @@ SQLS_CRIACAO = [ tip_resultado_votacao, nom_resultado, ind_excluido) values ({}, "DESCONHECIDO", 0); '''), - ('tipo_autor', ''' - insert into tipo_autor (tip_autor, des_tipo_autor, ind_excluido) - values ({}, "DESCONHECIDO", 0); - '''), + ('tipo_autor', SQL_INSERT_TIPO_AUTOR), ('unidade_tramitacao', ''' - insert into unidade_tramitacao (cod_unid_tramitacao, cod_comissao, cod_orgao, cod_parlamentar, ind_excluido) + insert into unidade_tramitacao ( + cod_unid_tramitacao, cod_comissao, cod_orgao, cod_parlamentar, ind_excluido) values ({}, NULL, NULL, NULL, 0); '''), + ('autor', SQL_INSERT_TIPO_AUTOR.format(0) + ''' + insert into autor ( + cod_autor, cod_partido, cod_comissao, cod_parlamentar, tip_autor, + nom_autor, des_cargo, col_username, ind_excluido) + values ({}, 0, 0, 0, 0, "DESCONHECIDO", "DESCONHECIDO", NULL, 0); + ''') ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From 537c72ce9ebc5765c9f98c7047062990c416236c Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 1 Sep 2018 17:26:31 -0300 Subject: [PATCH 03/88] =?UTF-8?q?Adiciona=20cria=C3=A7=C3=A3o=20de=20tipo?= =?UTF-8?q?=20documento=20ao=20ressucitar=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 7f51de9f7..a4c517088 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -257,7 +257,11 @@ SQLS_CRIACAO = [ cod_autor, cod_partido, cod_comissao, cod_parlamentar, tip_autor, nom_autor, des_cargo, col_username, ind_excluido) values ({}, 0, 0, 0, 0, "DESCONHECIDO", "DESCONHECIDO", NULL, 0); - ''') + '''), + ('tipo_documento', ''' + insert into tipo_documento (tip_documento, des_tipo_documento, ind_excluido) + values ({}, "DESCONHECIDO", 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From c829d47d4ca1e2a4ff73d44efde7d1516d3fa301 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 3 Sep 2018 11:07:35 -0300 Subject: [PATCH 04/88] =?UTF-8?q?Propaga=20mais=20exclus=C3=B5es=20ao=20mi?= =?UTF-8?q?grar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index 40b8a1ddc..c8a4026f7 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -539,6 +539,8 @@ PROPAGACOES_DE_EXCLUSAO = [ ('parlamentar', 'mandato', 'cod_parlamentar'), ('parlamentar', 'composicao_mesa', 'cod_parlamentar'), ('parlamentar', 'composicao_comissao', 'cod_parlamentar'), + # no 2.5 os parlamentares excluídos não são listados na presença da sessão + ('parlamentar', 'sessao_plenaria_presenca', 'cod_parlamentar'), # coligacao ('coligacao', 'composicao_coligacao', 'cod_coligacao'), @@ -553,6 +555,9 @@ PROPAGACOES_DE_EXCLUSAO = [ ('sessao_plenaria', 'expediente_sessao_plenaria', 'cod_sessao_plen'), ('sessao_plenaria', 'sessao_plenaria_presenca', 'cod_sessao_plen'), ('sessao_plenaria', 'ordem_dia_presenca', 'cod_sessao_plen'), + ('sessao_plenaria', 'mesa_sessao_plenaria', 'cod_sessao_plen'), + ('sessao_plenaria', 'oradores', 'cod_sessao_plen'), + ('sessao_plenaria', 'oradores_expediente', 'cod_sessao_plen'), # as consultas no código do sapl 2.5 # votacao_ordem_dia_obter_zsql e votacao_expediente_materia_obter_zsql From fa93d8875c0ed6d92627e1fee31a7b60794a67e1 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 3 Sep 2018 11:08:45 -0300 Subject: [PATCH 05/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index a4c517088..1221721b0 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -64,6 +64,7 @@ regime_tramitacao /sistema/materia/regime-tramitacao tipo_comissao /sistema/comissao/tipo tipo_documento_administrativo /sistema/tipo-documento-adm registro_votacao /admin/sessao/registrovotacao +tipo_dependente /sistema/parlamentar/tipo-dependente ''' urls = dict(stripsplit(urls)) @@ -262,6 +263,18 @@ SQLS_CRIACAO = [ insert into tipo_documento (tip_documento, des_tipo_documento, ind_excluido) values ({}, "DESCONHECIDO", 0); '''), + ('partido', ''' + insert into partido (cod_partido, sgl_partido, nom_partido, dat_criacao, dat_extincao, ind_excluido) + values ({}, "DESC", "DESCONHECIDO", NULL, NULL, 0); + '''), + ('legislatura', ''' + insert into legislatura (num_legislatura, dat_inicio, dat_fim, dat_eleicao, ind_excluido) + values ({}, "1/1/1", "1/1/1", "1/1/1", 0); + '''), + ('cargo_mesa', ''' + insert into cargo_mesa (cod_cargo, des_cargo, ind_unico, ind_excluido) + values ({}, "DESCONHECIDO", 0, 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From c18c336b47f5171aeed9798aad9c1d7ff607969d Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 3 Sep 2018 11:58:38 -0300 Subject: [PATCH 06/88] =?UTF-8?q?Propaga=20mais=20exclus=C3=B5es=20ao=20mi?= =?UTF-8?q?grar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index c8a4026f7..e6d4fb783 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -541,6 +541,8 @@ PROPAGACOES_DE_EXCLUSAO = [ ('parlamentar', 'composicao_comissao', 'cod_parlamentar'), # no 2.5 os parlamentares excluídos não são listados na presença da sessão ('parlamentar', 'sessao_plenaria_presenca', 'cod_parlamentar'), + # no 2.5 os parlamentares excluídos não são listados na mesa da sessão + ('parlamentar', 'mesa_sessao_plenaria', 'cod_parlamentar'), # coligacao ('coligacao', 'composicao_coligacao', 'cod_coligacao'), From 716770233e907bd39a650da40144bdd3dae5217b Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 3 Sep 2018 15:05:54 -0300 Subject: [PATCH 07/88] =?UTF-8?q?Propaga=20mais=20exclus=C3=B5es=20ao=20mi?= =?UTF-8?q?grar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index e6d4fb783..894541e22 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -541,7 +541,9 @@ PROPAGACOES_DE_EXCLUSAO = [ ('parlamentar', 'composicao_comissao', 'cod_parlamentar'), # no 2.5 os parlamentares excluídos não são listados na presença da sessão ('parlamentar', 'sessao_plenaria_presenca', 'cod_parlamentar'), - # no 2.5 os parlamentares excluídos não são listados na mesa da sessão + # ... nem na presença da ordem do dia + ('parlamentar', 'ordem_dia_presenca', 'cod_parlamentar'), + # ... nem na mesa da sessão ('parlamentar', 'mesa_sessao_plenaria', 'cod_parlamentar'), # coligacao From 2f28a56295cc88c772cae160dd321bb6b2d8a54a Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Tue, 4 Sep 2018 10:39:47 -0300 Subject: [PATCH 08/88] =?UTF-8?q?Retira=20repeti=C3=A7=C3=B5es=20ao=20ress?= =?UTF-8?q?ucitar=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 1221721b0..e4b397406 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -1,15 +1,16 @@ +from collections import OrderedDict from textwrap import dedent -import texttable import yaml -from unipath import Path +import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) +from unipath import Path def stripsplit(ll): @@ -19,6 +20,7 @@ def stripsplit(ll): def _tab_legado(model): return models_novos_para_antigos[model]._meta.db_table + fks_legado = { (_tab_legado(m), campos_novos_para_antigos[f]): _tab_legado(f.related_model) # noqa for m in models_novos_para_antigos @@ -342,6 +344,10 @@ def get_url(slug): return 'sapl.{}.leg.br'.format(slug.replace('-', '.')) +def sem_repeticoes_mantendo_ordem(sequencia): + return OrderedDict.fromkeys(sequencia).keys() + + def get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug): sqls_links = [get_sql(*(args + (slug,))) for itens, get_sql in ((desexcluir, get_sql_desexcluir), @@ -351,7 +357,15 @@ def get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug): return '' else: sqls, links = zip(*sqls_links) - links = [l for ll in links for l in ll] # flatten + + sqls = [dedent(s.strip()) + ';' + for sql in sqls + for s in sql.split(';') if s.strip()] + sqls = sem_repeticoes_mantendo_ordem(sqls) + + links = (l for ll in links for l in ll) # flatten + links = sem_repeticoes_mantendo_ordem(links) + sqls, links = ['\n'.join(sorted(s)) for s in [sqls, links]] return TEMPLATE_RESSUCITADOS.format(preambulo, links, sqls) From 18a3ef857e18360307351cc2625edb5bcf440fde Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 8 Sep 2018 12:51:20 -0300 Subject: [PATCH 09/88] =?UTF-8?q?Propaga=20mais=20exclus=C3=B5es=20ao=20mi?= =?UTF-8?q?grar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index 894541e22..14cf59285 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -584,6 +584,8 @@ PROPAGACOES_DE_EXCLUSAO = [ ('materia_legislativa', 'despacho_inicial', 'cod_materia'), ('materia_legislativa', 'legislacao_citada', 'cod_materia'), ('materia_legislativa', 'relatoria', 'cod_materia'), + ('materia_legislativa', 'materia_assunto', 'cod_materia'), + # norma ('norma_juridica', 'vinculo_norma_juridica', 'cod_norma_referente'), From a8fb5ee542d00ac490c7c912ee85f610948a8976 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 8 Sep 2018 12:51:50 -0300 Subject: [PATCH 10/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index e4b397406..fa7832b6c 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -1,16 +1,16 @@ from collections import OrderedDict from textwrap import dedent +import texttable import yaml +from unipath import Path -import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) -from unipath import Path def stripsplit(ll): @@ -277,6 +277,10 @@ SQLS_CRIACAO = [ insert into cargo_mesa (cod_cargo, des_cargo, ind_unico, ind_excluido) values ({}, "DESCONHECIDO", 0, 0); '''), + ('orgao', ''' + insert into orgao (cod_orgao, nom_orgao, sgl_orgao, ind_unid_deliberativa, end_orgao, num_tel_orgao, ind_excluido) + values ({}, "DESCONHECIDO", "DESC", 0, NULL, NULL, 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From a0392926af65c9a780d801cf5fd23c8a3217cce4 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 8 Sep 2018 13:02:14 -0300 Subject: [PATCH 11/88] =?UTF-8?q?Apaga=20refs=20a=20mat=C3=A9rias=20inexis?= =?UTF-8?q?tes=20em=20norma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index 14cf59285..ece005482 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -716,6 +716,12 @@ sessao_plenaria_presenca | dat_sessao = NULL | dat_sessao = 0 anula_tipos_origem_externa_invalidos() corrige_unidades_tramitacao_destino_vazia_como_anterior() + # matérias inexistentes não são mostradas em norma jurídica => apagamos + exec_legado('''update norma_juridica set cod_materia = NULL + where cod_materia not in ( + select cod_materia from materia_legislativa + where ind_excluido <> 1);''') + class Record: pass From 238a39eeedf7f5cc95cd18503c0f3fdefd58c444 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 8 Sep 2018 14:05:05 -0300 Subject: [PATCH 12/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index fa7832b6c..6dc5cf989 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -1,16 +1,16 @@ from collections import OrderedDict from textwrap import dedent -import texttable import yaml -from unipath import Path +import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) +from unipath import Path def stripsplit(ll): @@ -67,6 +67,7 @@ tipo_comissao /sistema/comissao/tipo tipo_documento_administrativo /sistema/tipo-documento-adm registro_votacao /admin/sessao/registrovotacao tipo_dependente /sistema/parlamentar/tipo-dependente +origem /sistema/materia/origem ''' urls = dict(stripsplit(urls)) @@ -87,6 +88,7 @@ CAMPOS_ORIGEM_PARA_ALVO = { 'cod_unid_tram_dest': 'cod_unid_tramitacao', 'cod_unid_tram_local': 'cod_unid_tramitacao', 'tip_id_basica': 'tip_materia', + 'cod_local_origem_externa': 'cod_origem', } From 6a3365c9332dc971a3168387d0708f2c9d1a890f Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 8 Sep 2018 18:17:14 -0300 Subject: [PATCH 13/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 6dc5cf989..4a780a3fc 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -68,6 +68,7 @@ tipo_documento_administrativo /sistema/tipo-documento-adm registro_votacao /admin/sessao/registrovotacao tipo_dependente /sistema/parlamentar/tipo-dependente origem /sistema/materia/origem +documento_acessorio /materia/documentoacessorio ''' urls = dict(stripsplit(urls)) From a4b7b46bbc8242da75acc101dd0d0a1b6ebf393c Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 10 Sep 2018 09:31:23 -0300 Subject: [PATCH 14/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 4a780a3fc..1484abb59 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -1,16 +1,16 @@ from collections import OrderedDict from textwrap import dedent +import texttable import yaml +from unipath import Path -import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) -from unipath import Path def stripsplit(ll): @@ -284,6 +284,10 @@ SQLS_CRIACAO = [ insert into orgao (cod_orgao, nom_orgao, sgl_orgao, ind_unid_deliberativa, end_orgao, num_tel_orgao, ind_excluido) values ({}, "DESCONHECIDO", "DESC", 0, NULL, NULL, 0); '''), + ('origem', ''' + insert into origem (cod_origem, sgl_origem, nom_origem, ind_excluido) + values ({}, "DESC", "DESCONHECIDO", 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From bc8e41aca8c6d6f70d1e672f6175e89a98597286 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 10 Sep 2018 11:32:06 -0300 Subject: [PATCH 15/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 1484abb59..6949b06c0 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -234,6 +234,14 @@ SQL_INSERT_TIPO_AUTOR = ''' values ({}, "DESCONHECIDO", 0) ON DUPLICATE KEY UPDATE ind_excluido = 0; ''' +# deve ser idempotente pois é usada na criação de comissao +# por isso o ON DUPLICATE KEY UPDATE +SQL_INSERT_TIPO_COMISSAO = ''' + insert into tipo_comissao (tip_comissao, nom_tipo_comissao, sgl_natureza_comissao, sgl_tipo_comissao, des_dispositivo_regimental, ind_excluido) + values ({}, "DESCONHECIDO", "P", "DESC", NULL, 0) + ON DUPLICATE KEY UPDATE ind_excluido = 0; + ''' + SQLS_CRIACAO = [ ('tipo_proposicao', ''' insert into tipo_materia_legislativa ( @@ -288,6 +296,12 @@ SQLS_CRIACAO = [ insert into origem (cod_origem, sgl_origem, nom_origem, ind_excluido) values ({}, "DESC", "DESCONHECIDO", 0); '''), + ('tipo_comissao', SQL_INSERT_TIPO_COMISSAO), + ('comissao', SQL_INSERT_TIPO_COMISSAO.format(0) + ''' + insert into comissao (cod_comissao, tip_comissao, nom_comissao, sgl_comissao, dat_criacao, + ind_unid_deliberativa, ind_excluido) + values ({}, 0, "DESCONHECIDO", "DESC", "1-1-1", 0, 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From d252fca69bf750b86f76eedb282d752c05a3510f Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Tue, 11 Sep 2018 15:19:38 -0300 Subject: [PATCH 16/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 6949b06c0..7bac40713 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -69,6 +69,7 @@ registro_votacao /admin/sessao/registrovotacao tipo_dependente /sistema/parlamentar/tipo-dependente origem /sistema/materia/origem documento_acessorio /materia/documentoacessorio +tipo_fim_relatoria /sistema/materia/tipo-fim-relatoria ''' urls = dict(stripsplit(urls)) From eafe16b47d926c9ff4b78ada5cc94bd8ae5fa055 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 13 Sep 2018 12:23:02 -0300 Subject: [PATCH 17/88] =?UTF-8?q?Configura=20TIME=5FZONE=20automaticamente?= =?UTF-8?q?=20na=20migra=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 25 ++++++------------------- sapl/legacy_migration_settings.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index ece005482..776348f50 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -33,7 +33,8 @@ from sapl.comissoes.models import Comissao, Composicao, Participacao, Reuniao from sapl.legacy.models import NormaJuridica as OldNormaJuridica from sapl.legacy.models import TipoNumeracaoProtocolo from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, - NOME_BANCO_LEGADO) + NOME_BANCO_LEGADO, PYTZ_TIMEZONE, + SIGLA_CASA) from sapl.materia.models import (AcompanhamentoMateria, DocumentoAcessorio, MateriaLegislativa, Proposicao, StatusTramitacao, TipoDocumento, @@ -50,7 +51,6 @@ from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, OrdemDia, from sapl.utils import normalize from .scripts.normaliza_dump_mysql import normaliza_dump_mysql -from .timezonesbrasil import get_timezone # YAML SETUP ############################################################### @@ -807,19 +807,6 @@ def reinicia_sequence(model, id): REPO = git.Repo.init(DIR_REPO) -# configura timezone de migração -match = re.match('sapl_cm_(.*)', NOME_BANCO_LEGADO) -sigla_casa = match.group(1) -PATH_TABELA_TIMEZONES = DIR_DADOS_MIGRACAO.child('tabela_timezones.yaml') -with open(PATH_TABELA_TIMEZONES, 'r') as arq: - tabela_timezones = yaml.load(arq) -municipio, uf, nome_timezone = tabela_timezones[sigla_casa] -if nome_timezone: - timezone = pytz.timezone(nome_timezone) -else: - timezone = get_timezone(municipio, uf) - - def populate_renamed_fields(new, old): renames = field_renames[type(new)] @@ -846,9 +833,9 @@ def populate_renamed_fields(new, old): return (field_type == tipo and value and not value.tzinfo) if campo_tempo_sem_timezone('DateTimeField'): - value = timezone.localize(value) + value = PYTZ_TIMEZONE.localize(value) if campo_tempo_sem_timezone('TimeField'): - value = value.replace(tzinfo=timezone) + value = value.replace(tzinfo=PYTZ_TIMEZONE) setattr(new, field.name, value) @@ -860,7 +847,7 @@ def roda_comando_shell(cmd): def get_arquivo_ajustes_pre_migracao(): return DIR_DADOS_MIGRACAO.child( - 'ajustes_pre_migracao', '{}.sql'.format(sigla_casa)) + 'ajustes_pre_migracao', '{}.sql'.format(SIGLA_CASA)) def migrar_dados(apagar_do_legado=False): @@ -1180,7 +1167,7 @@ def adjust_protocolo_antes_salvar(new, old): def get_arquivo_resolve_registro_votacao(): return DIR_DADOS_MIGRACAO.child( 'ajustes_pre_migracao', - '{}_resolve_registro_votacao_ambiguo.yaml'.format(sigla_casa)) + '{}_resolve_registro_votacao_ambiguo.yaml'.format(SIGLA_CASA)) def get_como_resolver_registro_votacao_ambiguo(): diff --git a/sapl/legacy_migration_settings.py b/sapl/legacy_migration_settings.py index 96f6a83ad..ce0029937 100644 --- a/sapl/legacy_migration_settings.py +++ b/sapl/legacy_migration_settings.py @@ -1,10 +1,14 @@ import os +import re +import pytz +import yaml from decouple import Config, RepositoryEnv from dj_database_url import parse as db_url from sapl.legacy.scripts.exporta_zope.variaveis_comuns import \ DIR_DADOS_MIGRACAO +from sapl.legacy.timezonesbrasil import get_timezone from .settings import * # flake8: noqa @@ -43,3 +47,18 @@ NOME_BANCO_LEGADO = DATABASES['legacy']['NAME'] DIR_REPO = Path(DIR_DADOS_MIGRACAO, 'repos', NOME_BANCO_LEGADO) MEDIA_ROOT = DIR_REPO + + +# configura timezone de migração +match = re.match('sapl_cm_(.*)', NOME_BANCO_LEGADO) +SIGLA_CASA = match.group(1) +_PATH_TABELA_TIMEZONES = DIR_DADOS_MIGRACAO.child('tabela_timezones.yaml') +with open(_PATH_TABELA_TIMEZONES, 'r') as arq: + tabela_timezones = yaml.load(arq) +municipio, uf, nome_timezone = tabela_timezones[SIGLA_CASA] +if nome_timezone: + PYTZ_TIMEZONE = pytz.timezone(nome_timezone) +else: + PYTZ_TIMEZONE = get_timezone(municipio, uf) + +TIME_ZONE = PYTZ_TIMEZONE.zone From 5d9b103c4a47d0ab6b5850a6b271d73a944b17b2 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 13 Sep 2018 14:25:17 -0300 Subject: [PATCH 18/88] Corrige ajuste de timezone ao migrar --- sapl/legacy/migracao_dados.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index 776348f50..ae4d4b158 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -826,15 +826,16 @@ def populate_renamed_fields(new, old): and value in [None, 'None']): value = '' - # adiciona timezone faltante aos campos com tempo - # os campos TIMESTAMP do mysql são gravados em UTC - # os DATETIME e TIME não têm timezone - def campo_tempo_sem_timezone(tipo): - return (field_type == tipo - and value and not value.tzinfo) - if campo_tempo_sem_timezone('DateTimeField'): - value = PYTZ_TIMEZONE.localize(value) - if campo_tempo_sem_timezone('TimeField'): + # ajusta tempos segundo timezone + # os campos TIMESTAMP do mysql são gravados em UTC + # os DATETIME e TIME não têm timezone + + if field_type == 'DateTimeField' and value: + # as datas armazenadas no legado na verdade são naive + sem_tz = value.replace(tzinfo=None) + value = PYTZ_TIMEZONE.localize(sem_tz).astimezone(pytz.utc) + + if field_type == 'TimeField' and value: value = value.replace(tzinfo=PYTZ_TIMEZONE) setattr(new, field.name, value) From 7f5cc4cdc5f0ac590f8fa6350735185c0ce619f4 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 13 Sep 2018 14:26:26 -0300 Subject: [PATCH 19/88] =?UTF-8?q?Expande=20ressucitar=20depend=C3=AAncias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressucita_dependencias.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressucita_dependencias.py index 7bac40713..9810924a9 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressucita_dependencias.py @@ -303,6 +303,10 @@ SQLS_CRIACAO = [ ind_unid_deliberativa, ind_excluido) values ({}, 0, "DESCONHECIDO", "DESC", "1-1-1", 0, 0); '''), + ('parlamentar', ''' + insert into parlamentar (cod_parlamentar, nom_completo, nom_parlamentar, sex_parlamentar, cod_casa, ind_ativo, ind_unid_deliberativa, ind_excluido) + values ({}, "DESCONHECIDO", "DESCONHECIDO", "M", 0, 0, 0, 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From f25a4c9011a68e6994556dac21390d3906fa699a Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 13 Sep 2018 15:20:42 -0300 Subject: [PATCH 20/88] =?UTF-8?q?Retira=20associa=C3=A7=C3=A3o=20de=20doc?= =?UTF-8?q?=20a=20protocolo=20do=20ano=20seguinte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Associávamos o documento administrativo a um protocolo no ano seguinte quando não encontrávamos protocolo no ano do documento. Isso estava gerando várias associações erradas então abolimos. --- sapl/legacy/migracao_dados.py | 71 ++++++++++------------------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index ae4d4b158..1be1f6e96 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -1031,65 +1031,34 @@ def adjust_acompanhamentomateria(new, old): new.confirmado = True -NOTA_DOCADM = ''' -## NOTA DE MIGRAÇÃO DE DADOS DO SAPL 2.5 ## -O número de protocolo original deste documento era [{num_protocolo}], ano {ano_original}. -'''.strip() # noqa - - def adjust_documentoadministrativo(new, old): if old.num_protocolo: - nota = None - ano_original = new.ano - protocolo = Protocolo.objects.filter( - numero=old.num_protocolo, ano=new.ano) - if not protocolo: - # tentamos encontrar o protocolo no ano seguinte - ano_novo = ano_original + 1 - protocolo = Protocolo.objects.filter(numero=old.num_protocolo, - ano=ano_novo) - if protocolo: - nota = NOTA_DOCADM + ''' -O protocolo vinculado é o de mesmo número, porém do ano seguinte ({ano_novo}), -pois não existe protocolo no sistema com este número no ano {ano_original}. -''' - nota = nota.strip().format(num_protocolo=old.num_protocolo, - ano_original=ano_original, - ano_novo=ano_novo) - msg = 'PROTOCOLO ENCONTRADO APENAS PARA O ANO SEGUINTE!!!!! '\ - 'DocumentoAdministrativo: {cod_documento}, '\ - 'numero_protocolo: {num_protocolo}, '\ - 'ano doc adm: {ano_original}' - warn('protocolo_ano_seguinte', msg, - {'cod_documento': old.cod_documento, - 'num_protocolo': old.num_protocolo, - 'ano_original': ano_original, - 'nota': nota}) - else: - # Se não achamos mesmo no ano anteriro - # colocamos no número externo - new.numero_externo = old.num_protocolo + numero, ano = old.num_protocolo, new.ano + # False < True => o primeiro será o protocolo não anulado + protocolos = Protocolo.objects.filter( + numero=numero, ano=ano).order_by('anulado') + if protocolos: + new.protocolo = protocolos[0] + else: + # Se não achamos o protocolo registramos no número externo + new.numero_externo = numero + + nota = ''' +## NOTA DE MIGRAÇÃO DE DADOS DO SAPL 2.5 ## +O número de protocolo original deste documento era [{numero}], ano [{ano}]. - nota = NOTA_DOCADM + ''' Não existe no sistema nenhum protocolo com estes dados e portanto nenhum protocolo foi vinculado a este documento. Colocamos então o número de protocolo no campo "número externo". ''' - nota = nota.format( - num_protocolo=old.num_protocolo, - ano_original=ano_original) - msg = 'Protocolo {num_protocolo} faltando (referenciado ' \ - 'no documento administrativo {cod_documento})' - warn('protocolo_faltando', msg, - {'num_protocolo': old.num_protocolo, - 'cod_documento': old.cod_documento, - 'nota': nota}) - if protocolo: - assert len(protocolo) == 1, 'mais de um protocolo encontrado' - [new.protocolo] = protocolo - # adiciona nota ao final da observação - if nota: + nota = nota.strip().format(numero=numero, ano=ano) + msg = 'Protocolo {numero} faltando (referenciado ' \ + 'no documento administrativo {cod_documento})' + warn('protocolo_faltando', msg, + {'numero': numero, + 'cod_documento': old.cod_documento, + 'nota': nota}) new.observacao += ('\n\n' if new.observacao else '') + nota From 7f8d692161d0bc8fe8615c919ae31a2bb0877fa0 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Tue, 18 Sep 2018 15:44:48 -0300 Subject: [PATCH 21/88] =?UTF-8?q?Estende=20exporta=C3=A7=C3=A3o=20de=20doc?= =?UTF-8?q?s=20para=20instala=C3=A7=C3=B5es=20de=20fora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/exporta_zope/exporta_zope.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sapl/legacy/scripts/exporta_zope/exporta_zope.py b/sapl/legacy/scripts/exporta_zope/exporta_zope.py index 8f3b1eb4a..529fb3d62 100755 --- a/sapl/legacy/scripts/exporta_zope/exporta_zope.py +++ b/sapl/legacy/scripts/exporta_zope/exporta_zope.py @@ -381,18 +381,30 @@ def _dump_sapl(data_fs_path, documentos_fs_path, destino, salvar, mtimes): sapl = find_sapl(app) # extrai usuários com suas senhas e perfis dump_usuarios(sapl, destino, salvar) + + # extrai folhas XSLT (primeira tentativa) + if 'XSLT' in sapl: + dump_folder(br(sapl['XSLT']), destino, salvar, mtimes) + finally: close_db() app, close_db = get_app(documentos_fs_path) + try: sapl = find_sapl(app) - # extrai folhas XSLT - if 'XSLT' in sapl: - dump_folder(br(sapl['XSLT']), destino, salvar, mtimes) + if sapl == {'id': 'sapl'}: + # em algumas instalações sapl_documentos está direto na raiz + docs = br(app['sapl_documentos']) + else: + # caso mais comum + docs = br(sapl['sapl_documentos']) + + # extrai folhas XSLT (segunda tentativa) + if 'XSLT' in sapl: + dump_folder(br(sapl['XSLT']), destino, salvar, mtimes) # extrai documentos - docs = br(sapl['sapl_documentos']) with logando_nao_identificados(): dump_folder(docs, destino, salvar, mtimes) dump_propriedades(docs, destino, salvar) From 9d1d85fbabb83179d58441e26dd1cb689a451802 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Tue, 18 Sep 2018 16:08:43 -0300 Subject: [PATCH 22/88] =?UTF-8?q?Estende=20exporta=C3=A7=C3=A3o=20de=20doc?= =?UTF-8?q?s=20p=20DtmlMethod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/exporta_zope/exporta_zope.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sapl/legacy/scripts/exporta_zope/exporta_zope.py b/sapl/legacy/scripts/exporta_zope/exporta_zope.py index 529fb3d62..682296f4b 100755 --- a/sapl/legacy/scripts/exporta_zope/exporta_zope.py +++ b/sapl/legacy/scripts/exporta_zope/exporta_zope.py @@ -298,6 +298,8 @@ DUMP_FUNCTIONS = { 'Image': dump_file, 'DTML Method': partial(dump_file, get_conteudo=get_conteudo_dtml_method), + 'DTMLMethod': partial(dump_file, + get_conteudo=get_conteudo_dtml_method), 'Folder': partial(dump_folder, enum=enumerate_folder), 'BTreeFolder2': partial(dump_folder, enum=enumerate_btree), 'SDE-Document': partial(dump_sde, tipo='sde.document'), From 5b79c2555e8c1056bb24276ef5b610b76664f620 Mon Sep 17 00:00:00 2001 From: VictorFabreF Date: Wed, 19 Sep 2018 17:56:39 -0300 Subject: [PATCH 23/88] =?UTF-8?q?HOT-FIX:=20remo=C3=A7=C3=A3o=20de=20par?= =?UTF-8?q?=C3=A2metro=20desnecess=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/comissoes/forms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapl/comissoes/forms.py b/sapl/comissoes/forms.py index c51f89a68..94d9b081f 100644 --- a/sapl/comissoes/forms.py +++ b/sapl/comissoes/forms.py @@ -69,9 +69,9 @@ class PeriodoForm(forms.ModelForm): if not data_fim: data_fim = data_inicio - legislatura = Legislatura.objects.filter(Q(data_inicio__lte=data_inicio, + legislatura = Legislatura.objects.filter(data_inicio__lte=data_inicio, data_fim__gte=data_fim, - )) + ) if not legislatura: raise ValidationError('O período informado ' From 4aa0e5c3b89ae9839e35360ccec59cd7906b770a Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Thu, 20 Sep 2018 12:18:49 -0300 Subject: [PATCH 24/88] fix #1827 (#2234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [WIP - DON'T MERGE] fix #1827 * Adiciona parâmetros necessários para mostrar DebugToolbar --- requirements/dev-requirements.txt | 2 +- requirements/requirements.txt | 23 ++++++++++------------- sapl/base/tests/teststub_urls.py | 8 +++----- sapl/comissoes/tests/test_comissoes.py | 1 + sapl/materia/forms.py | 2 +- sapl/sessao/forms.py | 2 +- sapl/sessao/views.py | 18 +++++++++++++++--- sapl/settings.py | 15 ++++++++------- sapl/test_urls.py | 2 +- sapl/urls.py | 6 ++++++ 10 files changed, 47 insertions(+), 32 deletions(-) diff --git a/requirements/dev-requirements.txt b/requirements/dev-requirements.txt index 49ded787e..dba8788b2 100644 --- a/requirements/dev-requirements.txt +++ b/requirements/dev-requirements.txt @@ -2,7 +2,7 @@ autopep8==1.2.4 beautifulsoup4==4.6.0 -django-debug-toolbar==1.5 +django-debug-toolbar==1.8 ipdb==0.10.1 pdbpp==0.9.2 pip-review==0.4 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 6d9d79d66..f93a0ee00 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,24 +1,21 @@ dj-database-url==0.4.1 django-haystack==2.6.0 -django>=1.9,<1.10 -# TODO O django-admin-bootstrapped 2.5.7 não inseriu a mudança que permite -# 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>=1.10,<1.11 +git+git://github.com/rubgombar1/django-admin-bootstrapped.git django-bootstrap3==7.0.1 -django-bower==5.1.0 +django-bower==5.2.0 django-braces==1.9.0 django-compressor==2.0 -django-crispy-forms==1.6.0 -django-extensions==1.6.7 -django-extra-views==0.8.0 +django-crispy-forms==1.6.1 +django-extensions==1.9.8 +django-extra-views==0.11.0 django-filter==0.15.3 django-floppyforms==1.6.2 -django-model-utils==2.5 -django-sass-processor==0.5.4 +django-model-utils==3.1.1 +django-sass-processor==0.5.8 djangorestframework==3.4.0 -drfdocs==0.0.11 -easy-thumbnails==2.3 +git+git://github.com/jasperlittle/django-rest-framework-docs +easy-thumbnails==2.5 django-image-cropping==1.1.0 git+git://github.com/interlegis/trml2pdf.git libsass==0.11.1 diff --git a/sapl/base/tests/teststub_urls.py b/sapl/base/tests/teststub_urls.py index 9796768f2..8b66d6586 100644 --- a/sapl/base/tests/teststub_urls.py +++ b/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 sapl.urls import urlpatterns as original_patterns -ptrn = patterns('', - url(r'^zzzz$', +ptrn = [url(r'^zzzz$', TemplateView.as_view( - template_name='index.html'), name='zzzz')) - + template_name='index.html'), name='zzzz')] urlpatterns = original_patterns + ptrn diff --git a/sapl/comissoes/tests/test_comissoes.py b/sapl/comissoes/tests/test_comissoes.py index 4d12ba810..d2f8b0bd1 100644 --- a/sapl/comissoes/tests/test_comissoes.py +++ b/sapl/comissoes/tests/test_comissoes.py @@ -74,6 +74,7 @@ def test_incluir_comissao_submit(admin_client): 'nome': 'Comissão Teste', 'sigla': 'CT', 'data_criacao': '2016-03-22', + 'unidade_deliberativa': True, 'salvar': 'salvar'}, follow=True) assert response.status_code == 200 diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index c353b862f..4853ef45a 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1161,7 +1161,7 @@ class TipoProposicaoSelect(Select): str(data_has_perfil), force_text(option_label)) - def render_options(self, choices, selected_choices): + def render_options(self, selected_choices): # Normalize to strings. selected_choices = set(force_text(v) for v in selected_choices) output = [] diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index f7308f62e..a5d86e8fd 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -422,7 +422,7 @@ class VotacaoForm(forms.Form): class VotacaoNominalForm(forms.Form): resultado_votacao = forms.ModelChoiceField(label='Resultado da Votação', - required=True, + required=False, queryset=TipoResultadoVotacao.objects.all()) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 32813f84a..f9317c0d7 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1838,9 +1838,6 @@ class VotacaoNominalAbstract(SessaoPermissionMixin): except ObjectDoesNotExist: raise Http404() - if 'cancelar-votacao' in request.POST: - fechar_votacao_materia(materia_votacao) - return self.form_valid(form) if form.is_valid(): votos_sim = 0 @@ -1848,6 +1845,21 @@ class VotacaoNominalAbstract(SessaoPermissionMixin): abstencoes = 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'): v = votos.split(':') voto = v[0] diff --git a/sapl/settings.py b/sapl/settings.py index 12865c501..aa17fe3b7 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -116,11 +116,7 @@ HAYSTACK_CONNECTIONS = { }, } - -if DEBUG: - INSTALLED_APPS += ('debug_toolbar', 'rest_framework_docs',) - -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = [ 'reversion.middleware.RevisionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', @@ -131,8 +127,13 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', '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 = { 'default': { diff --git a/sapl/test_urls.py b/sapl/test_urls.py index 851b1995b..23e0c9544 100644 --- a/sapl/test_urls.py +++ b/sapl/test_urls.py @@ -56,7 +56,7 @@ def create_perms_post_migrate(sapl_app_config): ctype = ContentType.objects.get_for_model(klass) 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)) all_perms = set(Permission.objects.filter( diff --git a/sapl/urls.py b/sapl/urls.py index 07f382013..904b4357e 100644 --- a/sapl/urls.py +++ b/sapl/urls.py @@ -70,6 +70,12 @@ urlpatterns = [ # http://stackoverflow.com/questions/35510373/ if settings.DEBUG: + import debug_toolbar + + urlpatterns += [ + url(r'^__debug__/', include(debug_toolbar.urls)), + + ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) From 4cf795b88078c82cfc171bf56d7ead1736ad2af9 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 20 Sep 2018 15:05:07 -0300 Subject: [PATCH 25/88] =?UTF-8?q?HOT-FIX:=20materializa=20string=20em=20re?= =?UTF-8?q?lat=C3=B3rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/relatorios/templates/pdf_pauta_sessao_gerar.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py index 621b8fb75..31636401e 100755 --- a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py +++ b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py @@ -145,10 +145,10 @@ def votacao(lst_votacao): tmp += '\n' tmp += 'MatériaEmentaSituação\n' for votacao in lst_votacao: - tmp += '' + str(votacao['num_ordem']) + ' - ' + votacao['id_materia'] + '\n' + 'Processo: ' + votacao[ - 'des_numeracao'] + '\n' + 'Turno: ' + votacao['des_turno'] + '\n' + 'Autor: ' + votacao['nom_autor'] + '\n' + tmp += '' + str(votacao['num_ordem']) + ' - ' + str(votacao['id_materia']) + '\n' + 'Processo: ' + str(votacao[ + 'des_numeracao']) + '\n' + 'Turno: ' + str(votacao['des_turno']) + '\n' + 'Autor: ' + str(votacao['nom_autor']) + '\n' tmp += '' + \ - votacao['txt_ementa'] + '\n' + str(votacao['txt_ementa']) + '\n' tmp += '' + \ str(votacao['des_situacao']) + '\n' From f6289416f124d107cc9a41fe0af59680a1280ac8 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 20 Sep 2018 15:05:34 -0300 Subject: [PATCH 26/88] Release: 3.1.119 --- docker-compose.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c049fc404..6e9f2a00f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.118 + image: interlegis/sapl:3.1.119 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/setup.py b/setup.py index e2ae3d768..095a47380 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.118', + version='3.1.119', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From ee6285ce7e7175f0091cb79b51caa2aa5055a8af Mon Sep 17 00:00:00 2001 From: Edward Date: Thu, 20 Sep 2018 16:13:00 -0300 Subject: [PATCH 27/88] HOT-FIX: conserta erro django-bower + Django 1.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Os parâmetros do django-bower para o Django 1.10 aparentemente mudararam. Desta forma, é necessário remover os não utilizados. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d1a9ca29f..95782b591 100644 --- a/Dockerfile +++ b/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 -RUN python3 manage.py bower_install -- --allow-root --no-input && \ +RUN python3 manage.py bower_install --allow-root && \ python3 manage.py compilescss RUN python3 manage.py collectstatic --noinput --clear From 3e0f667bee94a6995309e9055c6c07faccb5fee9 Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Thu, 20 Sep 2018 16:37:58 -0300 Subject: [PATCH 28/88] Fix #2238 (#2239) --- sapl/protocoloadm/forms.py | 6 +++--- sapl/protocoloadm/views.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 8f80a5632..9985f522f 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -884,7 +884,7 @@ class DesvincularMateriaForm(forms.Form): def pega_ultima_tramitacao_adm(): return TramitacaoAdministrativo.objects.values( - 'materia_id').annotate(data_encaminhamento=Max( + 'documento_id').annotate(data_encaminhamento=Max( 'data_encaminhamento'), id=Max('id')).values_list('id', flat=True) @@ -901,7 +901,7 @@ def filtra_tramitacao_adm_destino(destino): return TramitacaoAdministrativo.objects.filter( id__in=lista, unidade_tramitacao_destino=destino).distinct().values_list( - 'materia_id', flat=True) + 'documento_id', flat=True) def filtra_tramitacao_adm_destino_and_status(status, destino): @@ -910,4 +910,4 @@ def filtra_tramitacao_adm_destino_and_status(status, destino): id__in=lista, status=status, unidade_tramitacao_destino=destino).distinct().values_list( - 'materia_id', flat=True) + 'documento_id', flat=True) diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index a084f899c..d58b1e11b 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -568,18 +568,19 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin, 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( - 'tramitacao__unidade_tramitacao_destino') + 'tramitacaoadministrativo__unidade_tramitacao_destino') qs = self.get_queryset() qs = qs.prefetch_related("documentoacessorioadministrativo_set", - "tramitacaoadministrativo_set", - "tipo", - "tramitacaoadministrativo_set__status", - "tramitacaoadministrativo_set__unidade_tramitacao_local", - "tramitacaoadministrativo_set__unidade_tramitacao_destino") + "tramitacaoadministrativo_set", + "tipo", + "tramitacaoadministrativo_set__status", + "tramitacaoadministrativo_set__unidade_tramitacao_local", + "tramitacaoadministrativo_set__unidade_tramitacao_destino") if status_tramitacao and unidade_destino: lista = filtra_tramitacao_adm_destino_and_status(status_tramitacao, From dc208c540bb67225c9bfe82cbce410ef9c2d767f Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Thu, 20 Sep 2018 16:50:10 -0300 Subject: [PATCH 29/88] Fix #2230 recuperar espera federacao no update (#2240) --- sapl/norma/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sapl/norma/views.py b/sapl/norma/views.py index 2cb4455c9..beae10d4d 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -236,6 +236,7 @@ class NormaCrud(Crud): initial['tipo_materia'] = norma.materia.tipo initial['ano_materia'] = norma.materia.ano initial['numero_materia'] = norma.materia.numero + initial['esfera_federacao'] = norma.esfera_federacao return initial From e79194bd6d9ab622f6e725cf92bb942a72a40520 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Sun, 23 Sep 2018 10:08:51 -0300 Subject: [PATCH 30/88] Fix #2242 (#2243) --- sapl/materia/forms.py | 5 +++++ sapl/materia/tests/test_materia_form.py | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 4853ef45a..2745b5c72 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -346,6 +346,11 @@ class RelatoriaForm(ModelForm): class TramitacaoForm(ModelForm): + urgente = forms.ChoiceField(required=True, + choices=YES_NO_CHOICES, + initial=False, + label=_("Urgente?")) + class Meta: model = Tramitacao fields = ['data_tramitacao', diff --git a/sapl/materia/tests/test_materia_form.py b/sapl/materia/tests/test_materia_form.py index 944cabf00..b67ef2733 100644 --- a/sapl/materia/tests/test_materia_form.py +++ b/sapl/materia/tests/test_materia_form.py @@ -196,8 +196,9 @@ def test_valida_campos_obrigatorios_tramitacao_form(): assert errors['status'] == [_('Este campo é obrigatório.')] assert errors['data_tramitacao'] == [_('Este campo é obrigatório.')] assert errors['unidade_tramitacao_destino'] == [_('Este campo é obrigatório.')] + assert errors['urgente'] == [_('Este campo é obrigatório.')] - assert len(errors) == 5 + assert len(errors) == 6 @pytest.mark.django_db(transaction=False) @@ -213,8 +214,9 @@ def test_valida_campos_obrigatorios_tramitacao_update_form(): assert errors['status'] == [_('Este campo é obrigatório.')] assert errors['data_tramitacao'] == [_('Este campo é obrigatório.')] assert errors['unidade_tramitacao_destino'] == [_('Este campo é obrigatório.')] + assert errors['urgente'] == [_('Este campo é obrigatório.')] - assert len(errors) == 5 + assert len(errors) == 6 @pytest.mark.django_db(transaction=False) From 2c6a3258607cf5017f957a616f2dffde293e4f02 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 24 Sep 2018 09:15:31 -0300 Subject: [PATCH 31/88] =?UTF-8?q?HOT-FIX:=20corrige=20erro=20de=20atualiza?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20dict?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/settings.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sapl/settings.py b/sapl/settings.py index aa17fe3b7..af5264896 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -234,7 +234,8 @@ LANGUAGES = ( TIME_ZONE = config('TZ', default='America/Sao_Paulo') if not TIME_ZONE: - raise ValueError('TIMEZONE env variable undefined in .env settings file! Leaving...') + raise ValueError( + 'TIMEZONE env variable undefined in .env settings file! Leaving...') USE_I18N = True USE_L10N = True @@ -305,15 +306,13 @@ if DEBUG and LOGGING_CONSOLE: # Descomentar linha abaixo fará com que logs aparecam, inclusive SQL # LOGGING['handlers']['console']['level'] = 'DEBUG' LOGGING['loggers']['django']['level'] = 'DEBUG' - LOGGING.update({ - 'formatters': { - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(pathname)s ' - '%(funcName)s %(message)s' - }, - 'simple': { - 'format': '%(levelname)s %(message)s' - }, + LOGGING['formatters'].update({ + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(pathname)s ' + '%(funcName)s %(message)s' + }, + 'simple': { + 'format': '%(levelname)s %(message)s' }, }) LOGGING['handlers']['console']['formatter'] = 'verbose' From 4f23ea38c5693d26c3010644a9c66433586cc7d2 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 24 Sep 2018 09:28:18 -0300 Subject: [PATCH 32/88] HOT-FIX: teste de igualdade que passou a ser acusado pelo django 1.10 --- .../compilacao/dispositivo_form_search_fragment.html | 4 ++-- sapl/templates/compilacao/layout/dispositivo_radio.html | 2 +- sapl/templates/compilacao/text_notificacoes.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sapl/templates/compilacao/dispositivo_form_search_fragment.html b/sapl/templates/compilacao/dispositivo_form_search_fragment.html index a66b59245..95d91a2cf 100644 --- a/sapl/templates/compilacao/dispositivo_form_search_fragment.html +++ b/sapl/templates/compilacao/dispositivo_form_search_fragment.html @@ -64,7 +64,7 @@
{{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} - {% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} + {% if dpt.rotulo or dpt.nivel == 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ df.tipo_dispositivo.rotulo_prefixo_html|safe }} - {% if df.rotulo or df.nivel = 1%}{{ df.rotulo }}{%else%}[{{ df|nomenclatura}} {% trans "de" %} {{ df.dispositivo_pai.rotulo }}] - {% endif %} + {% if df.rotulo or df.nivel == 1%}{{ df.rotulo }}{%else%}[{{ df|nomenclatura}} {% trans "de" %} {{ df.dispositivo_pai.rotulo }}] - {% endif %} {{ df.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ df.tipo_dispositivo.texto_prefixo_html|safe }}{%if df.texto %}{{ df.texto|safe }}{%else%}{%if not df.tipo_dispositivo.dispositivo_de_articulacao %} {% endif %}{% endif %} {% if df.ta_publicado_id %} diff --git a/sapl/templates/compilacao/layout/dispositivo_radio.html b/sapl/templates/compilacao/layout/dispositivo_radio.html index 93d10eef1..797e8885b 100644 --- a/sapl/templates/compilacao/layout/dispositivo_radio.html +++ b/sapl/templates/compilacao/layout/dispositivo_radio.html @@ -23,7 +23,7 @@
{{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} - {% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} + {% if dpt.rotulo or dpt.nivel == 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }}
{{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} - {% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}}{% if dpt.dispositivo_pai_id %} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}{% endif %}] - {% endif %} + {% if dpt.rotulo or dpt.nivel == 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}}{% if dpt.dispositivo_pai_id %} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}{% endif %}] - {% endif %} {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }} Date: Mon, 24 Sep 2018 10:19:39 -0300 Subject: [PATCH 33/88] add texto nos detalhes da norma caso texto seja utilizado --- sapl/compilacao/views.py | 2 + .../compilacao/text_list__embedded.html | 105 ++++++++++++++++++ .../templates/norma/normajuridica_detail.html | 28 ++++- 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 sapl/templates/compilacao/text_list__embedded.html diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index a9ebf3fa4..5d4a81ef2 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -900,6 +900,8 @@ class TextView(CompMixin, ListView): def get(self, request, *args, **kwargs): if 'print' in request.GET: self.template_name = 'compilacao/text_list__print_version.html' + if 'embedded' in request.GET: + self.template_name = 'compilacao/text_list__embedded.html' return ListView.get(self, request, *args, **kwargs) def get_context_data(self, **kwargs): diff --git a/sapl/templates/compilacao/text_list__embedded.html b/sapl/templates/compilacao/text_list__embedded.html new file mode 100644 index 000000000..f5235751b --- /dev/null +++ b/sapl/templates/compilacao/text_list__embedded.html @@ -0,0 +1,105 @@ +{% extends "base.html" %} +{% load i18n %} +{% load compilacao_filters %} +{% load common_tags %} +{% load staticfiles %} +{% load sass_tags %} + +{% block head_content %} + +{% endblock %} + +{% block navigation %}{% endblock %} + +{% block main_header %}{% endblock %} +{% block title %}{% endblock %} +{% block sections_nav %}{% endblock %} +{% block extra_sections_nav %}{% endblock %} +{% block actions %}{% endblock %} +{% block dsp_actions %}{% endblock %} + +{% block detail_content %}{% endblock %} +{% block footer_container %}{% endblock %} + +{% block base_content %} + +
+ + {% if object_list %} +
+
+ a + A +
+
+ {% endif %} + + {% for key, values in view.get_vigencias.items %} + {% if forloop.first %} + + + + {% if view.inicio_vigencia and view.fim_vigencia %} + {% blocktrans with inicio_vigencia=view.inicio_vigencia fim_vigencia=view.fim_vigencia%} + Vigência entre {{inicio_vigencia}} e {{fim_vigencia}}. + {% endblocktrans%} + {% else%} + {% blocktrans with inicio_vigencia=dispositivo.inicio_vigencia%} + Vigência a partir de {{inicio_vigencia}}. + {% endblocktrans%} + {% endif %} +
+ {% if view.ta_vigencia %} + {% trans 'Dada por '%}{{ta_pub_list|lookup:view.ta_vigencia}} + {% elif view.ta_vigencia and view.ta_vigencia != 0%} + {% trans 'Dada por '%}{{dispositivo.ta_publicado}} + {% endif %} +
+ {% endif%} + {% endfor %} + {% else %} +
  • + +
  • + {% endif %} + {% endfor %} + + + {% include 'compilacao/text_list_bloco.html'%} +
    +{% endblock base_content %} + +{% block foot_js %} + + + + {% if perms.compilacao.add_nota %} + + {% endif %} +{% endblock %} diff --git a/sapl/templates/norma/normajuridica_detail.html b/sapl/templates/norma/normajuridica_detail.html index c2d236a96..9ff25494e 100644 --- a/sapl/templates/norma/normajuridica_detail.html +++ b/sapl/templates/norma/normajuridica_detail.html @@ -1,5 +1,5 @@ {% extends "crud/detail.html" %} -{% load i18n common_tags%} +{% load i18n common_tags staticfiles%} {% block detail_content %} {% for fieldset in view.layout_display %} @@ -76,4 +76,30 @@ {% endif %}
    + + {% if object.texto_articulado.exists %} +
    +
    +
    +
    +

    {%trans 'Texto Multivigente' %}

    +
    +
    +
    + {% endif %} {% endblock detail_content %} + +{% block extra_js %} +{% if object.texto_articulado.exists %} + +{% endif %} +{% endblock extra_js %} From de7a1ca2bb4c428c75642b8130b38324a4dac5af Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 24 Sep 2018 10:44:48 -0300 Subject: [PATCH 34/88] Fix #2121 e parte da #2220 --- sapl/compilacao/models.py | 5 +++- .../compilacao/text_list__embedded.html | 27 +++---------------- .../templates/norma/normajuridica_detail.html | 6 ++--- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index ff6cbdab1..812e48e27 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -266,10 +266,13 @@ class TextoArticulado(TimestampedMixin): user.has_perm( 'compilacao.change_your_dispositivo_edicao_dinamica')) - def has_view_permission(self, request): + def has_view_permission(self, request=None): if self.privacidade in (STATUS_TA_IMMUTABLE_PUBLIC, STATUS_TA_PUBLIC): return True + if not request: + return False + if request.user in self.owners.all(): return True diff --git a/sapl/templates/compilacao/text_list__embedded.html b/sapl/templates/compilacao/text_list__embedded.html index f5235751b..a448c9dd4 100644 --- a/sapl/templates/compilacao/text_list__embedded.html +++ b/sapl/templates/compilacao/text_list__embedded.html @@ -1,4 +1,3 @@ -{% extends "base.html" %} {% load i18n %} {% load compilacao_filters %} {% load common_tags %} @@ -9,20 +8,6 @@ {% endblock %} -{% block navigation %}{% endblock %} - -{% block main_header %}{% endblock %} -{% block title %}{% endblock %} -{% block sections_nav %}{% endblock %} -{% block extra_sections_nav %}{% endblock %} -{% block actions %}{% endblock %} -{% block dsp_actions %}{% endblock %} - -{% block detail_content %}{% endblock %} -{% block footer_container %}{% endblock %} - -{% block base_content %} -
    {% if object_list %} @@ -93,13 +78,9 @@ {% include 'compilacao/text_list_bloco.html'%}
    -{% endblock base_content %} - -{% block foot_js %} - - + + {% if perms.compilacao.add_nota %} - - {% endif %} -{% endblock %} + + {% endif %} \ No newline at end of file diff --git a/sapl/templates/norma/normajuridica_detail.html b/sapl/templates/norma/normajuridica_detail.html index 9ff25494e..0ead31671 100644 --- a/sapl/templates/norma/normajuridica_detail.html +++ b/sapl/templates/norma/normajuridica_detail.html @@ -77,7 +77,7 @@
    - {% if object.texto_articulado.exists %} + {% if object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %}
    @@ -90,13 +90,13 @@ {% endblock detail_content %} {% block extra_js %} -{% if object.texto_articulado.exists %} +{% if object.texto_articulado.exists and object.texto_articulado.first.has_view_permission %} -{% endblock %} \ No newline at end of file +{% endblock %} From f80df1ec10110a74e04da280c0ea99d355eca8e2 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Wed, 26 Sep 2018 10:24:42 -0300 Subject: [PATCH 47/88] Fix #2258 --- .../migrations/0009_auto_20180926_1015.py | 20 +++++++++++++++++++ sapl/compilacao/models.py | 2 +- sapl/static/styles/compilacao.scss | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 sapl/compilacao/migrations/0009_auto_20180926_1015.py diff --git a/sapl/compilacao/migrations/0009_auto_20180926_1015.py b/sapl/compilacao/migrations/0009_auto_20180926_1015.py new file mode 100644 index 000000000..813358623 --- /dev/null +++ b/sapl/compilacao/migrations/0009_auto_20180926_1015.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-09-26 13:15 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0008_auto_20180924_1724'), + ] + + operations = [ + migrations.AlterField( + model_name='tipodispositivo', + name='class_css', + field=models.CharField(blank=True, max_length=256, verbose_name='Classe CSS'), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index d165976e6..efb834c51 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -602,7 +602,7 @@ class TipoDispositivo(BaseModel): max_length=50, unique=True, verbose_name=_('Nome')) class_css = models.CharField( blank=True, - max_length=20, + max_length=256, verbose_name=_('Classe CSS')) rotulo_prefixo_html = models.TextField( blank=True, diff --git a/sapl/static/styles/compilacao.scss b/sapl/static/styles/compilacao.scss index c2e7ed7ad..60500e24c 100644 --- a/sapl/static/styles/compilacao.scss +++ b/sapl/static/styles/compilacao.scss @@ -290,6 +290,7 @@ a:link:after, a:visited:after { margin-top: 0.6em; font-size: 1.15em; } + .page-break { page-break-before: always; } .bloco_alteracao { padding-left: 10%; @@ -303,9 +304,9 @@ a:link:after, a:visited:after { a, table, table td { color: #018 !important; } - } + .dn { /* Notas de Dispositivo*/ font-weight: normal; position: relative; From 4a241c2d4326877de7fc50ff051b51d6b09c3e29 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Wed, 26 Sep 2018 13:59:52 -0300 Subject: [PATCH 48/88] =?UTF-8?q?ajusta=20comportamento=20na=20altera?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20dispositivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/compilacao/views.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index dc8dc42c8..82b5cbd10 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -2592,13 +2592,7 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, history = dispositivo_a_alterar.history() for d in history: - """FIXME: A comparação "<" deverá ser mudada para - "<=" caso seja necessário permitir duas alterações - com mesmo inicio_vigencia no mesmo dispositivo. Neste Caso, - a sequencia correta ficará a cargo dos reposicionamentos e - (a ser implementado) entre dispositivos de mesmo nível, - """ - if d.inicio_vigencia < bloco_alteracao.inicio_vigencia: + if d.inicio_vigencia <= bloco_alteracao.inicio_vigencia: dispositivo_a_alterar = d break From e566e3a09726690371d07f724a53b3d0d7053aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Sconetto?= Date: Wed, 26 Sep 2018 15:18:06 -0300 Subject: [PATCH 49/88] Add print exception on CSS (#2259) Fix #2254 --- sapl/static/styles/app.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 046aa58e4..760830cbd 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -604,6 +604,12 @@ p { } } +@media print { + a[href]:after { + content: none !important; + } +} + /* Estilização da Listagem de Votos em sessões plenárias */ #styleparlamentar { From 1e79d8b1d1d61c959b4cc56cb13105ee9fefa4db Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Wed, 26 Sep 2018 16:58:41 -0300 Subject: [PATCH 50/88] Release: 3.1.121 --- docker-compose.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5c5dc08be..b559eff7e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.120 + image: interlegis/sapl:3.1.121 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/setup.py b/setup.py index 3191572f2..e31740a2b 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.120', + version='3.1.121', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 8c38e061cdfc4ad8c0b0a6fae1706f1120c8accc Mon Sep 17 00:00:00 2001 From: Mariana Mendes Date: Fri, 28 Sep 2018 10:43:24 -0300 Subject: [PATCH 51/88] Resolving issue #2265 (#2269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to fix 'Pauta Sessão PDF' error Co-authored-by: Mariana Mendes --- sapl/relatorios/views.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index c602e991b..1bc62befa 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -741,16 +741,7 @@ def get_sessao_plenaria(sessao, casa): def get_turno(dic, materia, sessao_data_inicio): descricao_turno = ' ' descricao_tramitacao = ' ' - tramitacao = Tramitacao.objects.filter(materia=materia, - turno__isnull=False, - data_tramitacao__lte=sessao_data_inicio, - ).exclude(turno__exact='' - ).select_related( - 'materia', - 'status', - 'materia__tipo').order_by( - '-data_tramitacao' - ).first() + tramitacao = None if tramitacao is None: tramitacao = materia.tramitacao_set.last() @@ -759,7 +750,7 @@ def get_turno(dic, materia, sessao_data_inicio): if t[0] == tramitacao.turno: descricao_turno = t[1] break - descricao_tramitacao = tramitacao.status.descricao if tramitacao.status else ' ' + descricao_tramitacao = tramitacao.status.descricao if tramitacao.status else 'Não informada' return (descricao_turno, descricao_tramitacao) From bb03aff449261087ae62326bd7c37ac78091a874 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 1 Oct 2018 15:31:06 -0300 Subject: [PATCH 52/88] HOT-FIX: impede norma somente com letras --- sapl/norma/forms.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index afcc052cd..5fa26f0fd 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -132,15 +132,21 @@ class NormaJuridicaForm(ModelForm): if not self.is_valid(): return cleaned_data + + import re + has_digits = re.sub('[^0-9]', '', cleaned_data['numero']) + if not has_digits: + raise ValidationError('Número de norma não pode conter somente letras') + if self.instance.numero != cleaned_data['numero']: norma = NormaJuridica.objects.filter(ano=cleaned_data['ano'], - numero=cleaned_data['numero'], - tipo=cleaned_data['tipo']).exists() + numero=cleaned_data['numero'], + tipo=cleaned_data['tipo']).exists() if norma: raise ValidationError("Já existe uma norma de mesmo Tipo, Ano " "e Número no sistema") if (cleaned_data['tipo_materia'] and - cleaned_data['numero_materia'] and + cleaned_data['numero_materia'] and cleaned_data['ano_materia']): try: materia = MateriaLegislativa.objects.get( From 13071caea50bb416402b2afd811270b20690dc26 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 4 Oct 2018 11:50:32 -0300 Subject: [PATCH 53/88] Corrige palavra --- .../{ressucitar_deps.py => ressuscitar_deps.py} | 6 +++--- ...ependencias.py => ressuscita_dependencias.py} | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) rename sapl/legacy/management/commands/{ressucitar_deps.py => ressuscitar_deps.py} (54%) rename sapl/legacy/scripts/{ressucita_dependencias.py => ressuscita_dependencias.py} (97%) diff --git a/sapl/legacy/management/commands/ressucitar_deps.py b/sapl/legacy/management/commands/ressuscitar_deps.py similarity index 54% rename from sapl/legacy/management/commands/ressucitar_deps.py rename to sapl/legacy/management/commands/ressuscitar_deps.py index 70900e887..ea219330c 100644 --- a/sapl/legacy/management/commands/ressucitar_deps.py +++ b/sapl/legacy/management/commands/ressuscitar_deps.py @@ -1,12 +1,12 @@ from django.core.management.base import BaseCommand -from sapl.legacy.scripts.ressucita_dependencias import adiciona_ressucitar +from sapl.legacy.scripts.ressuscita_dependencias import adiciona_ressuscitar class Command(BaseCommand): - help = 'Ressucita dependências apagadas ' \ + help = 'Ressuscita dependências apagadas ' \ 'que são necessárias para migrar outros registros' def handle(self, *args, **options): - adiciona_ressucitar() + adiciona_ressuscitar() diff --git a/sapl/legacy/scripts/ressucita_dependencias.py b/sapl/legacy/scripts/ressuscita_dependencias.py similarity index 97% rename from sapl/legacy/scripts/ressucita_dependencias.py rename to sapl/legacy/scripts/ressuscita_dependencias.py index 9810924a9..ebde7c73a 100644 --- a/sapl/legacy/scripts/ressucita_dependencias.py +++ b/sapl/legacy/scripts/ressuscita_dependencias.py @@ -194,7 +194,7 @@ Para facilitar sua conferência, seguem os links para as proposições envolvida '''.format(table.draw(), links, sqls) -def get_dependencias_a_ressucitar(slug): +def get_dependencias_a_ressuscitar(slug): ocorrencias = yaml.load( Path(DIR_REPO.child('ocorrencias.yaml').read_file())) fks_faltando = ocorrencias.get('fk') @@ -349,8 +349,8 @@ def get_sql_criar(tabela_alvo, campo, valor, slug): return sql, links -TEMPLATE_RESSUCITADOS = '''{} -/* RESSUCITADOS +TEMPLATE_RESSUSCITADOS = '''{} +/* RESSUSCITADOS SOBRE REGISTROS QUE ESTAVAM APAGADOS E FORAM RESTAURADOS @@ -397,11 +397,11 @@ def get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug): links = sem_repeticoes_mantendo_ordem(links) sqls, links = ['\n'.join(sorted(s)) for s in [sqls, links]] - return TEMPLATE_RESSUCITADOS.format(preambulo, links, sqls) + return TEMPLATE_RESSUSCITADOS.format(preambulo, links, sqls) -def get_ressucitar(slug): - preambulo, desexcluir, criar = get_dependencias_a_ressucitar(slug) +def get_ressuscitar(slug): + preambulo, desexcluir, criar = get_dependencias_a_ressuscitar(slug) return get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug) @@ -413,8 +413,8 @@ def get_slug(): return siglas_para_slugs[sigla] -def adiciona_ressucitar(): - sqls = get_ressucitar(get_slug()) +def adiciona_ressuscitar(): + sqls = get_ressuscitar(get_slug()) if sqls.strip(): arq_ajustes_pre_migracao = get_arquivo_ajustes_pre_migracao() conteudo = arq_ajustes_pre_migracao.read_file() From f3c7960478a247b6c3d97c2df42d00dd2907fe77 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 4 Oct 2018 15:07:06 -0300 Subject: [PATCH 54/88] Adiciona campo de release na tela principal --- release.sh | 4 ++++ sapl/templates/base.html | 1 + 2 files changed, 5 insertions(+) diff --git a/release.sh b/release.sh index cc3a172b5..958e91b21 100755 --- a/release.sh +++ b/release.sh @@ -13,6 +13,10 @@ function bump_version { sed -e s/$VERSION/$NEXT_VERSION/g setup.py > tmp2 mv tmp2 setup.py + + + sed -e s/$VERSION/$NEXT_VERSION/g sapl/templates/base.html > tmp3 + mv tmp3 sapl/templates/base.html } function commit_and_push { diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 8c4e24b6c..850669307 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -184,6 +184,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. + release: 3.1.122

    From 3c86de16528f6bdc4748aac2a39994b2be4eb8df Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Thu, 4 Oct 2018 15:34:26 -0300 Subject: [PATCH 55/88] corrige detalhes de front-end --- sapl/static/styles/_header.scss | 7 +- sapl/static/styles/_home_index.scss | 188 ++++++++ sapl/static/styles/app.scss | 656 +++++++++++----------------- sapl/templates/base.html | 2 +- sapl/templates/index.html | 295 +++++++------ 5 files changed, 596 insertions(+), 552 deletions(-) create mode 100644 sapl/static/styles/_home_index.scss diff --git a/sapl/static/styles/_header.scss b/sapl/static/styles/_header.scss index e5fa310a3..b04c99494 100644 --- a/sapl/static/styles/_header.scss +++ b/sapl/static/styles/_header.scss @@ -2,9 +2,4 @@ $logo-height: 0.8 * $navbar-height; $logo-margin: ($navbar-height - $logo-height) / 2; -.logo img { - width: $logo-height; - height: $logo-height; - margin: $logo-margin $navbar-padding-horizontal; -} - +$footer-height : 140px; diff --git a/sapl/static/styles/_home_index.scss b/sapl/static/styles/_home_index.scss new file mode 100644 index 000000000..d85ce05a3 --- /dev/null +++ b/sapl/static/styles/_home_index.scss @@ -0,0 +1,188 @@ + +.container-home { + position: relative; + padding: 2em 1.5em 1.5em 1.5em; + max-width: 1000px; + margin: 0 auto; + a:hover { + color: #444; + -webkit-transition: 0.3s ease-in; + -moz-transition: 0.3s ease-in; + -o-transition: 0.3s ease-in + } + + #homeIndex { + text-align: center; + } + + .homeBanner span { + color: white; + font-size: 32px; + font-weight: 600; + display: inline-block; + vertical-align: middle; + padding: 2px 45px 4px; + border: 2px solid; + } + + .homeBanner::after { + display: inline-block; + vertical-align: middle; + height: 100%; + } + + .homeBlock { + display: inline-block; + position: relative; + background-color: #F3F3F3; + width: 190px; + height: 260px; + margin: 3px; + text-align: center; + font-size: 0; + overflow: hidden; + } + + .homeBlock > a { + display: block; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + } + + .homeBlock::after { + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; + overflow: visible; + clear: none; + visibility: initial; + } + + .homeContent { + position: relative; + padding: 10px; + text-align: justify; + font-size: 14px; + color: #FFF; + opacity: 0; + transition: opacity 0.5s ease; + display: inline-block; + vertical-align: middle; + } + + .homeContent p { + display: block; + line-height: 13px; + font-size: 80%; + color: white; + } + + .homeIcon { + position: relative; + display: inline-block; + width: 105px; + height: 105px; + border-radius: 50%; + background: #364347; + z-index: 1; + } + + .homeIcon::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + background: #364347; + top: 0; + left: 0; + transform: scale(0.95); + transition: transform 0.6s ease; + } + + .homeIcon img { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + right: 0; + left: 0; + transition: opacity 0.4s 0.4s ease; + } + + .homeFront { + position: absolute; + top: 46%; + width: 100%; + font-size: 0; + transform: translateY(-60%); + + } + + .homeFront h2 { + position: absolute; + margin-top: 18px; + font-size: 22px; + font-weight: 700; + color: #595959 !important; + width: 100%; + padding: 0 6%; + z-index: 0; + } + + .homeTitle { + display: block; + height: 32px; + text-align: center; + width: 100%; + opacity: 0; + transition: opacity 0.4s ease; + } + + .homeTitle::before { + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; + } + + .homeTitle h2 { + display: inline-block; + vertical-align: middle; + max-width: 110px; + font-size: 14px; + color: white !important; + line-height: 1em; + } + + .homeTitle img { + display: inline-block; + vertical-align: middle; + height: 30px; + margin-right: 5px; + } + + .homeBlock:hover .homeIcon::before { + transform: scale(3.6) translateY(7px); + } + + .homeBlock:hover .homeContent{ + opacity: 1; + transition-delay: 0.2s; + } + + .homeBlock:hover .homeIcon img { + opacity: 0; + transition-duration: 0.2s; + transition-delay: 0s; + } + + .homeBlock:hover .homeTitle { + opacity: 1; + } + +} \ No newline at end of file diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 760830cbd..f8980133e 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -1,73 +1,18 @@ - @import "bootstrap/variables.scss"; -@import "header"; -.vcenter { - display: inline-block; - vertical-align: middle; - float: none; - padding: 10px; -} - -nav { - &.navbar { - border-radius: 0; - font-size: 15px; - } - .navbar-nav { - & > li { - & > a { - padding-top: 0px; - padding-bottom: 0px; - line-height: $grid-gutter-width * 2.5; - &:hover { - background-color: $link-hover-color; - } - } - &:nth-child(2) { - & > .dropdown-menu { - right: auto; - } - } +@import "header"; - } - &:last-child { - & > li:last-child { - a { - padding-right: 0px; - } - } - } - } -} -.masthead { - padding: 10px; - .nav { - clear:both; - } - .navbar-brand { - color: $headings-color; - font-size: 24px; - img.img-responsive { - height: 95px; - margin-right: $navbar-padding-horizontal; - } - small { - color: #93A4AA; - font-size: 75%; - line-height: 25px; - } - } -} +@import "home_index"; -.navbar { - margin-bottom: 0; +html, body { + position: relative; + min-height: 100%; } -.navbar-brand { - padding: 0px; +h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a { + margin: 0; + padding: 0; } -// ADJUST DRUNKEN PARROT STYLES ######################################## h1, .h1 { font-size: 30px; } @@ -87,21 +32,41 @@ h6, .h6 { font-size: 12px; } -.page-header { - margin: 20px 0px 10px; +p { + margin: 0.5em 0; + .control-label { + font-weight: bold; + } } -.btn:hover, .btn:focus { - color: inherit; +label { + margin-bottom: 0; + line-height: 1; +} + +fieldset { + fieldset { + font-size: 95%; + legend { + font-size: 18px; + } + } +} + +.page-header { + margin: 20px 0px 10px; } .caret { - /* Por padrão caret aponta para baixo*/ &.top { transform: rotate(180deg); } } +.btn:hover, .btn:focus { + color: inherit; +} + .btn-default { &.btn-excluir { color: $btn-danger-bg; @@ -113,68 +78,19 @@ h6, .h6 { } } -.controls-file { - padding: 10px; - border: 1px solid #d6e1e5; - border-radius: 4px; - - label.checkbox-inline { - margin: 0px; - display: block; - } -} - -.help-block-danger { - margin: $grid-gutter-width / 2; - padding: $grid-gutter-width / 2; - border: 2px dashed #f00; -} - -.controls-radio-checkbox { - padding: 0px; - border: 1px solid #d6e1e5; - border-radius: 4px; - min-height: 20px; - .help-block { - margin: $grid-gutter-width / 2; - padding: $grid-gutter-width / 2; - border: 2px dashed #d6e1e5; - } - - label { - padding: 5px; - .icons { - top: 5px; - left: 8px; - } - &.checkbox-inline, &.radio-inline { - padding: 8px; - padding-left: 36px; - .icons { - top: 8px; - left: 8px; - } - } +.btn-cancel-iframe { + position: relative; + text-align: right; + opacity: 0.5; + &:hover { + opacity: 1; } - .checkbox, .radio, .checkbox-inline, .radio-inline { - margin: 0; - &:hover { - background-color: #d6e1e5; - } + a { + padding: 10px; + display: inline-block; } } - -// #### CRUD DETAIL ######################################## -p.control-label { - font-weight: bold; -} - -// copied from bootstrap _forms.scss legend -// using @extend would require importing parts of bootstrap again and overriding drunken parrot css -// @import "bootstrap/mixins.scss"; -// @import "bootstrap/forms.scss"; - .legend { display: block; width: 100%; @@ -190,42 +106,27 @@ p.control-label { .grid-gutter-width-right { margin-right: $grid-gutter-width / 2; } -// #### footer ########################################### -// based on http://getbootstrap.com/examples/sticky-footer -$footer-height : 140px; -html { - position: relative; - min-height: 100%; -} -body { - margin-bottom: $footer-height + 20px; -} -.footer { - position: absolute; - bottom: 0; - width: 100%; - /* Set the fixed height of the footer here */ - height: $footer-height; - background: #364347 none repeat scroll 0% 0%; - color: white; - text-align: center; - p { - color: white; - margin-top: 10px; - } - .container { - padding-top: 25px; +.controls-file { + padding: 10px; + border: 1px solid #d6e1e5; + border-radius: 4px; + label.checkbox-inline { + margin: 0px; + display: block; } } -label { - margin-bottom: 0; - line-height: 1; +.help-block-danger { + margin: $grid-gutter-width / 2; + padding: $grid-gutter-width / 2; + border: 2px dashed #f00; } + .control-label { margin: 0; } + .form-control-static { padding-top: 0; min-height: auto; @@ -234,8 +135,6 @@ label { } } - -// #### pagination ######################################## .pagination { padding-top: 25px; } @@ -246,15 +145,6 @@ label { } } -fieldset { - fieldset { - font-size: 95%; - legend { - font-size: 18px; - } - } -} - .avatar-parlamentar { height: 128px; width: 128px; @@ -262,228 +152,120 @@ fieldset { display: table; } -/* INDEX */ -#conteudo { - position: relative; - padding: 2em 1.5em 1.5em 1.5em; - overflow: hidden; - font-size: 100%; - text-align: left; - min-height: 350px; - max-width: 1000px; - margin: 0 auto; -} -#conteudo a:hover { - color: #444; - -webkit-transition: 0.3s ease-in; - -moz-transition: 0.3s ease-in; - -o-transition: 0.3s ease-in -} - -#homeIndex { - text-align: center; -} - -.homeBanner span { - color: white; - font-size: 32px; - font-weight: 600; - display: inline-block; - vertical-align: middle; - padding: 2px 45px 4px; - border: 2px solid; -} - -.homeBanner::after { - display: inline-block; - vertical-align: middle; - height: 100%; -} - -.homeBlock { - display: inline-block; - position: relative; - background-color: #F3F3F3; - width: 190px; - height: 260px; - margin: 3px; - text-align: center; - font-size: 0; - overflow: hidden; -} - -.homeBlock > a { - display: block; - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; -} - -.homeBlock::after { - content: ''; - display: inline-block; - vertical-align: middle; - height: 100%; - overflow: visible; - clear: none; - visibility: initial; -} - -.homeContent { - position: relative; - padding: 10px; - text-align: justify; - font-size: 14px; - color: #FFF; - opacity: 0; - transition: opacity 0.5s ease; - display: inline-block; - vertical-align: middle; -} - -.homeContent p { - display: block; - line-height: 13px; - font-size: 80%; - color: white; -} - -.homeIcon { - position: relative; - display: inline-block; - width: 105px; - height: 105px; - border-radius: 50%; - background: #364347; - z-index: 1; -} - -.homeIcon::before { - content: ''; - position: absolute; - width: 100%; - height: 100%; - border-radius: 50%; - background: #364347; - top: 0; - left: 0; - transform: scale(0.95); - transition: transform 0.6s ease; -} - -.homeIcon img { - position: absolute; - margin: auto; - top: 0; - bottom: 0; - right: 0; - left: 0; - transition: opacity 0.4s 0.4s ease; -} - -.homeFront { - position: absolute; - top: 46%; - width: 100%; - font-size: 0; - transform: translateY(-60%); - -} - -.homeFront h2 { - position: absolute; - margin-top: 18px; - font-size: 22px; - font-weight: 700; - color: #595959 !important; - width: 100%; - padding: 0 6%; - z-index: 0; -} - -.homeTitle { - display: block; - height: 32px; - text-align: center; - width: 100%; - opacity: 0; - transition: opacity 0.4s ease; -} - -.homeTitle::before { - content: ''; - display: inline-block; - vertical-align: middle; - height: 100%; -} -.homeTitle h2 { - display: inline-block; - vertical-align: middle; - max-width: 110px; - font-size: 14px; - color: white !important; - line-height: 1em; -} - -.homeTitle img { - display: inline-block; - vertical-align: middle; - height: 30px; - margin-right: 5px; -} - -.homeBlock:hover .homeIcon::before { - transform: scale(3.6) translateY(7px); -} - -.homeBlock:hover .homeContent{ - opacity: 1; - transition-delay: 0.2s; -} - -.homeBlock:hover .homeIcon img { - opacity: 0; - transition-duration: 0.2s; - transition-delay: 0s; +.masthead { + padding: 10px; + .nav { + clear:both; + } + .navbar-brand { + padding: 0px; + color: $headings-color; + font-size: 24px; + img.img-responsive { + height: 95px; + margin-right: $navbar-padding-horizontal; + } + small { + color: #93A4AA; + font-size: 75%; + line-height: 25px; + } + .vcenter { + display: inline-block; + vertical-align: middle; + float: none; + padding: 10px; + } + } } -.homeBlock:hover .homeTitle { - opacity: 1; -} +nav { + &.navbar { + margin-bottom: 0; + border-radius: 0; + font-size: 15px; + } + .navbar-nav { + & > li { + & > a { + padding-top: 0px; + padding-bottom: 0px; + line-height: $grid-gutter-width * 2.5; + &:hover { + background-color: $link-hover-color; + } + } + &:nth-child(2) { + & > .dropdown-menu { + right: auto; + } + } -h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a { - margin: 0; - padding: 0; + } + &:last-child { + & > li:last-child { + a { + padding-right: 0px; + } + } + } + } } -p { - margin: 0.5em 0; -} -/* FIM INDEX */ +.controls-radio-checkbox { + padding: 0px; + border: 1px solid #d6e1e5; + border-radius: 4px; + min-height: 20px; + .help-block { + margin: $grid-gutter-width / 2; + padding: $grid-gutter-width / 2; + border: 2px dashed #d6e1e5; + } -/* TEMPLATE AJUDA */ -.manual li { - display: list-item; - line-height: 1.5em; - padding-right: 0; -} -.manual li a { - background-color: transparent; - border: none; - border-radius: none; - padding: 0; + label { + padding: 5px; + .icons { + top: 5px; + left: 8px; + } + &.checkbox-inline, &.radio-inline { + padding: 8px; + padding-left: 36px; + .icons { + top: 8px; + left: 8px; + } + } + } + .checkbox, .radio, .checkbox-inline, .radio-inline { + margin: 0; + &:hover { + background-color: #d6e1e5; + } + } } -.manual, .manual ul { +.manual { + &, & ul { padding-left: 1.5em; list-style-type: none; margin-top: 0; font-size: 100%; + } + li { + display: list-item; + line-height: 1.5em; + padding-right: 0; + a { + background-color: transparent; + border: none; + border-radius: none; + padding: 0; + } + } } -/* FIM TEMPLATE AJUDA */ .container-tabaux { .sidebar-tabaux { @@ -558,29 +340,43 @@ p { } } -.btn-cancel-iframe { - position: relative; - text-align: right; - opacity: 0.5; - &:hover { - opacity: 1; +#styleparlamentar { + border: 0px solid #d6e1e5; + border-top-color: rgb(214, 225, 229); + border-right-color: rgb(214, 225, 229); + border-bottom-color: rgb(214, 225, 229); + border-left-color: rgb(214, 225, 229); + border-image-source: initial; + border-image-slice: initial; + border-image-repeat: initial; + font-size: 16px; + line-height: 1.467; + padding: 7px 12px; + height: 40px; + -webkit-appearance: none; + border-radius: 4px; + -webkit-box-shadow: none; + box-shadow: none; + margin-left: 1.0em; +} + +.footer { + background: #364347; + color: white; + text-align: center; + p { + color: white; + margin-top: 10px; } - a { - padding: 10px; - display: inline-block; + .container { + padding-top: 25px; } } - @media (max-width: 1199px) { - .masthead { - .navbar-brand { - font-size: 22px; - img.img-responsive { - height: 60px; - width: 60px; - margin-right: $navbar-padding-horizontal / 2; - } + nav { + .container { + width: auto !important; } } .navbar-nav > li > a { @@ -589,14 +385,70 @@ p { } } + @media (max-width: 1091px) { + .container { + width: auto; + } .navbar-nav > li > a { padding-left: $grid-gutter-width / 4; padding-right: $grid-gutter-width / 4; } + .masthead { + .navbar-brand { + font-size: 22px; + img.img-responsive { + height: 60px; + margin-right: $navbar-padding-horizontal / 2; + } + } + } } +@media (max-width: 991px) { + .caret { + margin-left: 1px; + } + .navbar-nav > li > a { + padding-left: 4px; + padding-right: 4px; + } + .table{ + width: auto; + white-space: normal; + display:block; + overflow-x: auto; + } +} +@media (max-width: 767px) { + nav { + .navbar-nav > li > a { + line-height: 2.5; + } + .navbar-right { + position: absolute; + top: 0; + margin: 10px; + & > li { + vertical-align: top; + display: inline-block; + a { + padding-left: 10px; + padding-right: 10px; + } + } + .pesquisa.open { + ul { + position: absolute; + } + } + .navbar-form { + margin: 8px 0; + } + } + } +} @media (min-width: 1092px) and (max-width: 1199px) { .container { @@ -609,25 +461,3 @@ p { content: none !important; } } - -/* Estilização da Listagem de Votos em sessões plenárias */ - -#styleparlamentar { - border: 0px solid #d6e1e5; - border-top-color: rgb(214, 225, 229); - border-right-color: rgb(214, 225, 229); - border-bottom-color: rgb(214, 225, 229); - border-left-color: rgb(214, 225, 229); - border-image-source: initial; - border-image-slice: initial; - border-image-repeat: initial; - font-size: 16px; - line-height: 1.467; - padding: 7px 12px; - height: 40px; - -webkit-appearance: none; - border-radius: 4px; - -webkit-box-shadow: none; - box-shadow: none; - margin-left: 1.0em; -} diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 850669307..ae84f0164 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -193,7 +193,7 @@

    - Conteúdo e dados sob licença Creative Commons 4.0 Atribuir Fonte - Compartilhar Igual + Conteúdo e dados sob licença Creative Commons 4.0
    Atribuir Fonte - Compartilhar Igual

    diff --git a/sapl/templates/index.html b/sapl/templates/index.html index 7eab8dbc0..bbcfb97e2 100644 --- a/sapl/templates/index.html +++ b/sapl/templates/index.html @@ -1,164 +1,195 @@ {% extends "base.html" %} {% load i18n staticfiles %} -{% block title%} - - -
    -
    -
    -
    -
    -
    - Mesa Diretora -
    -

    Mesa Diretora

    -
    -
    -
    - +{% block title %} + +{% endblock title %} +{% block base_content%} +
    +
    +
    +
    +
    + Mesa Diretora +

    Mesa Diretora

    -

    - Órgão colegiado, composto de no mínimo três membros efetivos - Presidente e 1° e 2° Secretários - a quem cabe a direção dos trabalhos legislativos. Os parlamentares integrantes da Mesa Diretora são eleitos por seus pares na primeira reunião de instalação do período legislativo, para um mandato de um a dois anos. -

    +
    +
    + +

    Mesa Diretora

    +
    +

    + Órgão colegiado, composto de no mínimo três membros efetivos - Presidente e 1° e 2° Secretários - a + quem cabe a direção dos trabalhos legislativos. Os parlamentares integrantes da Mesa Diretora são + eleitos por seus pares na primeira reunião de instalação do período legislativo, para um mandato de + um + a dois anos. +

    +
    +
    - -
    -
    -
    -
    - Comissões -
    -

    Comissões

    -
    -
    -
    - +
    +
    +
    + Comissões +

    Comissões

    -

    - Órgãos da Casa Legislativa, de natureza técnica especializada e que têm por objetivo prestar melhores esclarecimentos aos parlamentares para a tomada de decisões. Assim, as comissões elaboram estudos, pareceres a respeito de determinados projetos de lei e investigação de irregularidades sobre fato determinado. -

    +
    +
    + +

    Comissões

    +
    +

    + Órgãos da Casa Legislativa, de natureza técnica especializada e que têm por objetivo prestar + melhores + esclarecimentos aos parlamentares para a tomada de decisões. Assim, as comissões elaboram estudos, + pareceres a respeito de determinados projetos de lei e investigação de irregularidades sobre fato + determinado. +

    +
    +
    - -
    -
    -
    -
    - Parlamentares -
    -

    Parlamentares

    -
    -
    -
    - +
    +
    +
    + Parlamentares +

    Parlamentares

    -

    - O Poder Legislativo, exercido pelo sistema de representação, tem nos parlamentares a sua expressão máxima. Devem transformar os anseios de seus representados em ações diretas, na forma de leis ou buscando junto do Executivo obras e atos que beneficiem a sua comunidade. Possuem funções legisladora, administrativa, julgadora e de fiscalização sobre a conduta do Executivo. -

    +
    +
    + +

    Parlamentares

    +
    +

    + O Poder Legislativo, exercido pelo sistema de representação, tem nos parlamentares a sua expressão + máxima. Devem transformar os anseios de seus representados em ações diretas, na forma de leis ou + buscando junto do Executivo obras e atos que beneficiem a sua comunidade. Possuem funções + legisladora, + administrativa, julgadora e de fiscalização sobre a conduta do Executivo. +

    +
    +
    - -
    -
    -
    -
    - Pautas das Sessões -
    -

    Pautas das Sessões

    +
    +
    +
    + Pautas das Sessões +
    +

    Pautas das Sessões

    +
    +
    +
    + +

    Pautas das
    Sessões

    +
    +

    + Utilizadas para se determinar quais matérias serão discutidas e votadas. A responsabilidade pela + elaboração das Pautas, que incluem Expediente e Ordem do Dia, é definida no Regimento Interno que, + em + geral, dá poderes ao Presidente da Casa Legislativa para a sua elaboração. Também, pode ficar a + cargo + de um colégio de líderes dos partidos políticos. +

    +
    +
    -
    -
    - -

    Pautas das
    Sessões

    -
    -

    - Utilizadas para se determinar quais matérias serão discutidas e votadas. A responsabilidade pela elaboração das Pautas, que incluem Expediente e Ordem do Dia, é definida no Regimento Interno que, em geral, dá poderes ao Presidente da Casa Legislativa para a sua elaboração. Também, pode ficar a cargo de um colégio de líderes dos partidos políticos. -

    -
    - -
    -
    -
    -
    - Sessão Plenária -
    -

    Sessão Plenária

    -
    -
    -
    - +
    +
    +
    + Sessão Plenária +

    Sessão Plenária

    -

    - Foro apropriado para a tomada de decisões sobre os projetos de lei e outras matérias legislativas ou administrativas, aprovadas ou rejeitadas em votação pelos parlamentares. É dirigida pela Mesa Diretora de acordo com o Regimento Interno da Casa. As decisões votadas em Plenário são soberanas e prevalecem sobre interesses ou vontades individuais. -

    +
    +
    + +

    Sessão Plenária

    +
    +

    + Foro apropriado para a tomada de decisões sobre os projetos de lei e outras matérias legislativas + ou + administrativas, aprovadas ou rejeitadas em votação pelos parlamentares. É dirigida pela Mesa + Diretora + de acordo com o Regimento Interno da Casa. As decisões votadas em Plenário são soberanas e + prevalecem + sobre interesses ou vontades individuais. +

    +
    +
    - -
    -
    -
    -
    - Matérias Legislativas -
    -

    Matérias Legislativas

    -
    -
    -
    - -

    Matérias
    Legislativas

    -
    -

    - Têm início com o processo de criação de leis e a apresentação de projetos no Poder Legislativo. Na apreciação de matérias, podem haver eventuais conflitos de interpretação ou de entendimento entre o que estabelece o Regimento Interno da Casa e a Lei Orgânica do Município. Nestes casos, prevalece a Lei Orgânica. -

    +
    +
    +
    + Matérias Legislativas +
    +

    Matérias Legislativas

    +
    +
    +
    + +

    Matérias
    Legislativas

    +
    +

    + Têm início com o processo de criação de leis e a apresentação de projetos no Poder Legislativo. Na + apreciação de matérias, podem haver eventuais conflitos de interpretação ou de entendimento entre o + que + estabelece o Regimento Interno da Casa e a Lei Orgânica do Município. Nestes casos, prevalece a Lei + Orgânica. +

    +
    +
    - -
    -
    -
    -
    - Normas Jurídicas -
    -

    Normas Jurídicas

    -
    -
    -
    - +
    +
    +
    + Normas Jurídicas +

    Normas Jurídicas

    -

    - Nos Municípios, referem-se às emendas à Lei Orgânica, às leis complementares, às leis ordinárias, aos decretos legislativos e às resoluções. -

    -
    - -
    - -
    -
    -
    - Relatórios +
    +
    + +

    Normas Jurídicas

    +
    +

    + Nos Municípios, referem-se às emendas à Lei Orgânica, às leis complementares, às leis ordinárias, + aos + decretos legislativos e às resoluções. +

    -

    Relatórios

    +
    -
    -
    - + +
    +
    +
    + Relatórios +

    Relatórios

    -

    - Contém informações estatísticas sobre a produção legislativa dos parlamentares e da Casa, dispostas e agrupadas de diferentes formas de acordo com parâmetros fornecidos. -

    +
    +
    + +

    Relatórios

    +
    +

    + Contém informações estatísticas sobre a produção legislativa dos parlamentares e da Casa, dispostas + e + agrupadas de diferentes formas de acordo com parâmetros fornecidos. +

    +
    +
    - -
    -
    +
    -{% endblock %} +{% endblock %} \ No newline at end of file From cdc18d079408b85bfc50bc5b4ef8d43e323ed7de Mon Sep 17 00:00:00 2001 From: Edward Date: Thu, 4 Oct 2018 16:23:00 -0300 Subject: [PATCH 56/88] =?UTF-8?q?Ajusta=20footer=20com=20vers=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/templates/base.html b/sapl/templates/base.html index ae84f0164..1953032a3 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -184,7 +184,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - release: 3.1.122 + Release: 3.1.121

    From 248683b5a543f3ed31d3af1571d8db15ac93e157 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Fri, 5 Oct 2018 09:06:41 -0300 Subject: [PATCH 57/88] Apaga destino antes de mover documento ao migrar --- sapl/legacy/migracao_documentos.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sapl/legacy/migracao_documentos.py b/sapl/legacy/migracao_documentos.py index 66ada19fc..2c9e00842 100644 --- a/sapl/legacy/migracao_documentos.py +++ b/sapl/legacy/migracao_documentos.py @@ -1,4 +1,5 @@ import os +import shutil import re from glob import glob from os.path import join @@ -52,6 +53,12 @@ def mover_documento(repo, origem, destino, ignora_origem_ausente=False): if ignora_origem_ausente and not os.path.exists(origem): print('Origem ignorada ao mover documento: {}'.format(origem)) return + # apaga destino, se houver, e renomeia origem para destino + if os.path.exists(destino): + if os.path.isdir(destino): + shutil.rmtree(destino) + else: + os.remove(destino) os.makedirs(os.path.dirname(destino), exist_ok=True) os.rename(origem, destino) From 563d3db75dcbd6f2b59b062702bc24dc02cf61f3 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Fri, 5 Oct 2018 11:07:20 -0300 Subject: [PATCH 58/88] Fix #2282 (#2283) --- sapl/parlamentares/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 207bc2bc7..6ae314785 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -142,7 +142,7 @@ class LegislaturaForm(ModelForm): pk = self.instance.pk - ultima_legislatura = Legislatura.objects.filter(data_inicio__lte=data_inicio + ultima_legislatura = Legislatura.objects.filter(data_inicio__lt=data_inicio ).order_by('-data_inicio').first() proxima_legislatura = Legislatura.objects.filter(data_fim__gt=data_fim ).order_by('data_fim').first() From 86e5bda7d6fb1c43f643978898379f567ca6b267 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Fri, 5 Oct 2018 11:07:43 -0300 Subject: [PATCH 59/88] Fix #2279 (#2280) --- .../migrations/0010_auto_20181004_1939.py | 20 +++++++++++++++++++ sapl/compilacao/models.py | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 sapl/compilacao/migrations/0010_auto_20181004_1939.py diff --git a/sapl/compilacao/migrations/0010_auto_20181004_1939.py b/sapl/compilacao/migrations/0010_auto_20181004_1939.py new file mode 100644 index 000000000..76b2de609 --- /dev/null +++ b/sapl/compilacao/migrations/0010_auto_20181004_1939.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-10-04 22:39 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0009_auto_20180926_1015'), + ] + + operations = [ + migrations.AlterField( + model_name='textoarticulado', + name='numero', + field=models.CharField(max_length=8, verbose_name='Número'), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index efb834c51..3d5b7a679 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -186,7 +186,8 @@ class TextoArticulado(TimestampedMixin): data = models.DateField(blank=True, null=True, verbose_name=_('Data')) ementa = models.TextField(verbose_name=_('Ementa')) observacao = models.TextField(blank=True, verbose_name=_('Observação')) - numero = models.PositiveIntegerField(verbose_name=_('Número')) + numero = models.CharField( + max_length=8,verbose_name=_('Número')) ano = models.PositiveSmallIntegerField(verbose_name=_('Ano')) tipo_ta = models.ForeignKey( TipoTextoArticulado, From 7ca93743d36a659f6af9560149f39f0e3567f589 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 5 Oct 2018 11:07:07 -0300 Subject: [PATCH 60/88] ajuste de front-end --- sapl/static/styles/app.scss | 26 ++++++++++++++----- sapl/templates/comissoes/composicao_list.html | 4 ++- sapl/templates/crud/detail_detail.html | 20 ++++++++------ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index f8980133e..099392fde 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -4,10 +4,13 @@ @import "home_index"; -html, body { +html { position: relative; min-height: 100%; } +body { + margin-bottom: 160px; +} h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a { margin: 0; @@ -364,6 +367,9 @@ nav { background: #364347; color: white; text-align: center; + position: absolute; + width: 100%; + bottom: 0px; p { color: white; margin-top: 10px; @@ -406,6 +412,12 @@ nav { } @media (max-width: 991px) { + body { + margin: 0; + } + .footer { + position: relative; + } .caret { margin-left: 1px; } @@ -413,12 +425,6 @@ nav { padding-left: 4px; padding-right: 4px; } - .table{ - width: auto; - white-space: normal; - display:block; - overflow-x: auto; - } } @media (max-width: 767px) { @@ -448,6 +454,12 @@ nav { } } } + .table{ + width: auto; + white-space: normal; + display:block; + overflow-x: auto; + } } @media (min-width: 1092px) and (max-width: 1199px) { diff --git a/sapl/templates/comissoes/composicao_list.html b/sapl/templates/comissoes/composicao_list.html index 29071c85d..3f543b0c5 100644 --- a/sapl/templates/comissoes/composicao_list.html +++ b/sapl/templates/comissoes/composicao_list.html @@ -37,7 +37,9 @@
    {% endif %} -
    + +
    +
    diff --git a/sapl/templates/crud/detail_detail.html b/sapl/templates/crud/detail_detail.html index b2312ec51..bddb962f0 100644 --- a/sapl/templates/crud/detail_detail.html +++ b/sapl/templates/crud/detail_detail.html @@ -63,14 +63,18 @@ {% endfor %} {% endfor %} {% endblock detail_content %} -
    - {% if view.detail_set_create_url %} - - {% blocktrans with verbose_name=view.verbose_name_set %} Adicionar {{ verbose_name }} {% endblocktrans %} - - {% endif %} - {% block more_buttons %}{% endblock more_buttons %} -
    + +
    + {% if view.detail_set_create_url %} + + {% blocktrans with verbose_name=view.verbose_name_set %} Adicionar {{ verbose_name }} {% endblocktrans %} + + {% endif %} + {% block more_buttons %}{% endblock more_buttons %} +
    + +
    +
    {% if not rows %}

    {{ NO_ENTRIES_MSG }}

    From 419b6d18dc36ce599913e969b1b2f86dc578b4d5 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Fri, 5 Oct 2018 11:31:47 -0300 Subject: [PATCH 61/88] Corrige insert de ressuscitar --- sapl/legacy/scripts/ressuscita_dependencias.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sapl/legacy/scripts/ressuscita_dependencias.py b/sapl/legacy/scripts/ressuscita_dependencias.py index ebde7c73a..19cb875d8 100644 --- a/sapl/legacy/scripts/ressuscita_dependencias.py +++ b/sapl/legacy/scripts/ressuscita_dependencias.py @@ -1,16 +1,16 @@ from collections import OrderedDict from textwrap import dedent -import texttable import yaml -from unipath import Path +import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) +from unipath import Path def stripsplit(ll): @@ -265,7 +265,7 @@ SQLS_CRIACAO = [ ('unidade_tramitacao', ''' insert into unidade_tramitacao ( cod_unid_tramitacao, cod_comissao, cod_orgao, cod_parlamentar, ind_excluido) - values ({}, NULL, NULL, NULL, 0); + values ({}, NULL, NULL, 0, 0); '''), ('autor', SQL_INSERT_TIPO_AUTOR.format(0) + ''' insert into autor ( From e49eb8fab82747a564fecfe6360526c9da070f16 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Fri, 5 Oct 2018 11:32:21 -0300 Subject: [PATCH 62/88] =?UTF-8?q?Apaga=20refs=20a=20mats=20e=20docs=20inex?= =?UTF-8?q?istentes=20em=20proposi=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao_dados.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sapl/legacy/migracao_dados.py b/sapl/legacy/migracao_dados.py index 1be1f6e96..1def7f9c3 100644 --- a/sapl/legacy/migracao_dados.py +++ b/sapl/legacy/migracao_dados.py @@ -623,6 +623,36 @@ def corrige_unidades_tramitacao_destino_vazia_como_anterior(): '''.format(tabela_tramitacao)) +def apaga_ref_a_mats_e_docs_inexistentes_em_proposicoes(): + # as referencias a matérias e documentos apagados não aparecem no 3.1 + # além do que, se ressuscitássemos essas matérias e docs, + # não seria possível apagá-los, + # pois é impossível para um usuário não autor acessar as proposicões + # para apagar a referências antes + exec_legado(''' + update proposicao set cod_materia = NULL where cod_materia not in ( + select cod_materia from materia_legislativa + where ind_excluido <> 1); + ''') + props_sem_mats = list(primeira_coluna(exec_legado(''' + select cod_proposicao from proposicao p inner join tipo_proposicao t + on p.tip_proposicao = t.tip_proposicao + where t.ind_mat_ou_doc = 'M' and cod_mat_ou_doc not in ( + select cod_materia from materia_legislativa + where ind_excluido <> 1) + '''))) + props_sem_docs = list(primeira_coluna(exec_legado(''' + select cod_proposicao from proposicao p inner join tipo_proposicao t + on p.tip_proposicao = t.tip_proposicao + where t.ind_mat_ou_doc = 'D' and cod_mat_ou_doc not in ( + select cod_documento from documento_acessorio + where ind_excluido <> 1); + '''))) + exec_legado_em_subconjunto(''' + update proposicao set cod_mat_ou_doc = NULL + where cod_proposicao in {}''', props_sem_mats + props_sem_docs) + + def uniformiza_banco(): propaga_exclusoes(PROPAGACOES_DE_EXCLUSAO) checa_registros_votacao_ambiguos_e_remove_nao_usados() @@ -722,6 +752,8 @@ sessao_plenaria_presenca | dat_sessao = NULL | dat_sessao = 0 select cod_materia from materia_legislativa where ind_excluido <> 1);''') + apaga_ref_a_mats_e_docs_inexistentes_em_proposicoes() + class Record: pass From 79dfe5f68210f0eaa99eb57871a96d60e763bfa7 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Fri, 5 Oct 2018 12:25:11 -0300 Subject: [PATCH 63/88] Fix #2284 (#2285) --- sapl/sessao/forms.py | 3 ++- sapl/sessao/tests/test_sessao.py | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index f7308f62e..5d36ba99a 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -86,7 +86,8 @@ class SessaoPlenariaForm(ModelForm): sessoes = SessaoPlenaria.objects.filter(numero=num, sessao_legislativa=sl, legislatura=leg, - tipo=tipo).\ + tipo=tipo, + data_inicio__year=abertura.year).\ values_list('id', flat=True) qtd_sessoes = len(sessoes) diff --git a/sapl/sessao/tests/test_sessao.py b/sapl/sessao/tests/test_sessao.py index 1715cd0ae..c1af4fc7e 100644 --- a/sapl/sessao/tests/test_sessao.py +++ b/sapl/sessao/tests/test_sessao.py @@ -51,17 +51,17 @@ def test_numero_duplicado_sessao_plenaria_form(): legislatura = mommy.make(Legislatura) sessao = mommy.make(SessaoLegislativa) tipo = mommy.make(TipoSessaoPlenaria) - mommy.make(SessaoPlenaria, - legislatura=legislatura, - sessao_legislativa=sessao, - tipo=tipo, - numero=1) + sessao_plenaria = mommy.make(SessaoPlenaria, + legislatura=legislatura, + sessao_legislativa=sessao, + tipo=tipo, + numero=1) form = forms.SessaoPlenariaForm(data={'legislatura': str(legislatura.pk), 'numero': '1', 'tipo': str(tipo.pk), 'sessao_legislativa': str(sessao.pk), - 'data_inicio': '10/11/2017', + 'data_inicio': sessao_plenaria.data_inicio, 'hora_inicio': '10:10' }) From 76f4771895e7e6000884fc5fce4f0df2dfc05468 Mon Sep 17 00:00:00 2001 From: Edward Date: Fri, 5 Oct 2018 15:36:25 -0300 Subject: [PATCH 64/88] Fixes #2288 (#2289) --- sapl/relatorios/templates/pdf_pauta_sessao_gerar.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py index 31636401e..f1a827e35 100755 --- a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py +++ b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py @@ -21,6 +21,7 @@ def cabecalho(inf_basicas_dic, imagem): tmp += '\t\t\t\t\n' tmp += '\t\t\t\tSistema de Apoio ao Processo Legislativo\n' tmp += '\t\t\t\t\n' + import ipdb; ipdb.set_trace() tmp += '\t\t\t\tPauta da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da \n' tmp += '\t\t\t\t' + \ From 9144e1786ec8e1027e6ce4fcee8bbc89c40f57fb Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 5 Oct 2018 15:39:41 -0300 Subject: [PATCH 65/88] HOT-FIX: conserta commit #76f477 --- sapl/relatorios/templates/pdf_pauta_sessao_gerar.py | 1 - sapl/relatorios/views.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py index f1a827e35..31636401e 100755 --- a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py +++ b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py @@ -21,7 +21,6 @@ def cabecalho(inf_basicas_dic, imagem): tmp += '\t\t\t\t\n' tmp += '\t\t\t\tSistema de Apoio ao Processo Legislativo\n' tmp += '\t\t\t\t\n' - import ipdb; ipdb.set_trace() tmp += '\t\t\t\tPauta da ' + str(inf_basicas_dic['num_sessao_plen']) + 'ª Reunião ' + str(inf_basicas_dic['nom_sessao']) + ' da ' + str( inf_basicas_dic['num_sessao_leg']) + 'ª Sessão Legislativa da \n' tmp += '\t\t\t\t' + \ diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 1bc62befa..4d273b6da 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -1019,7 +1019,7 @@ def get_pauta_sessao(sessao, casa): inf_basicas_dic["nom_sessao"] = sessao.tipo.nome inf_basicas_dic["num_sessao_plen"] = sessao.numero inf_basicas_dic["num_legislatura"] = sessao.legislatura - inf_basicas_dic["num_sessao_leg"] = sessao.legislatura + inf_basicas_dic["num_sessao_leg"] = sessao.sessao_legislativa.numero inf_basicas_dic["dat_inicio_sessao"] = sessao.data_inicio inf_basicas_dic["hr_inicio_sessao"] = sessao.hora_inicio inf_basicas_dic["dat_fim_sessao"] = sessao.data_fim From 9172e98c45ecb2da20c455ce68290830445f2c85 Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Fri, 5 Oct 2018 15:45:48 -0300 Subject: [PATCH 66/88] Fix #2286 (#2287) * Fix #2286 * more pythonic --- sapl/materia/forms.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 77ccca5d6..6f6a544cd 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -245,7 +245,7 @@ class MateriaLegislativaForm(ModelForm): primeiro_autor = True else: primeiro_autor = False - + materia = super(MateriaLegislativaForm, self).save(commit) materia.save() @@ -281,6 +281,20 @@ class UnidadeTramitacaoForm(ModelForm): raise ValidationError(msg) return cleaned_data + def save(self, commit=False): + unidade = super(UnidadeTramitacaoForm, self).save(commit) + cd = self.cleaned_data + + if not cd.get('orgao'): + unidade.orgao = None + if not cd.get('parlamentar'): + unidade.parlamentar = None + if not cd.get('comissao'): + unidade.comissao = None + + unidade.save() + return unidade + class AcompanhamentoMateriaForm(ModelForm): From ae8adafa96a8db4fe98d94f9473087cd5fc012f9 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Fri, 5 Oct 2018 17:27:49 -0300 Subject: [PATCH 67/88] Release: 3.1.122 --- docker-compose.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b559eff7e..1bfcf65f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.121 + image: interlegis/sapl:3.1.122 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/setup.py b/setup.py index e31740a2b..fac072615 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.121', + version='3.1.122', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 4062dc842b1c23d7940f58be82ef9595c3047a29 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Tue, 9 Oct 2018 15:18:23 -0300 Subject: [PATCH 68/88] Fix #2281 (#2290) * Fix #2281 * Inclui novo model em regras de acesso --- sapl/norma/forms.py | 50 ++++++++++++++++++- .../migrations/0014_auto_20181008_1655.py | 40 +++++++++++++++ sapl/norma/models.py | 29 +++++++++++ sapl/norma/urls.py | 5 +- sapl/norma/views.py | 37 +++++++++++++- sapl/rules/map_rules.py | 2 + sapl/templates/norma/autorianorma_form.html | 47 +++++++++++++++++ sapl/templates/norma/layouts.yaml | 4 ++ sapl/templates/norma/subnav.yaml | 3 +- 9 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 sapl/norma/migrations/0014_auto_20181008_1655.py create mode 100644 sapl/templates/norma/autorianorma_form.html diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 5fa26f0fd..818d6ba38 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -5,17 +5,18 @@ from crispy_forms.layout import Fieldset, Layout from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models -from django.forms import ModelForm, widgets +from django.forms import ModelForm, widgets, ModelChoiceField from django.utils import timezone from django.utils.translation import ugettext_lazy as _ +from sapl.base.models import Autor, TipoAutor from sapl.crispy_layout_mixin import form_actions, to_row from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.settings import MAX_DOC_UPLOAD_SIZE from sapl.utils import NormaPesquisaOrderingFilter, RANGE_ANOS, RangeWidgetOverride from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, - TipoNormaJuridica) + TipoNormaJuridica, AutoriaNorma) def ANO_CHOICES(): @@ -191,6 +192,51 @@ class NormaJuridicaForm(ModelForm): return norma +class AutoriaNormaForm(ModelForm): + + tipo_autor = ModelChoiceField(label=_('Tipo Autor'), + required=False, + queryset=TipoAutor.objects.all(), + empty_label=_('Selecione'),) + + data_relativa = forms.DateField( + widget=forms.HiddenInput(), required=False) + + def __init__(self, *args, **kwargs): + super(AutoriaNormaForm, self).__init__(*args, **kwargs) + + row1 = to_row([('tipo_autor', 4), + ('autor', 4), + ('primeiro_autor', 4)]) + + self.helper = FormHelper() + self.helper.layout = Layout( + Fieldset(_('Autoria'), + row1, 'data_relativa', form_actions(label='Salvar'))) + + if not kwargs['instance']: + self.fields['autor'].choices = [] + + class Meta: + model = AutoriaNorma + fields = ['tipo_autor', 'autor', 'primeiro_autor', 'data_relativa'] + + def clean(self): + cd = super(AutoriaNormaForm, self).clean() + + if not self.is_valid(): + return self.cleaned_data + + autorias = AutoriaNorma.objects.filter( + norma=self.instance.norma, autor=cd['autor']) + pk = self.instance.pk + + if ((not pk and autorias.exists()) or + (pk and autorias.exclude(pk=pk).exists())): + raise ValidationError(_('Esse Autor já foi cadastrado.')) + + return cd + class AnexoNormaJuridicaForm(ModelForm): class Meta: model = AnexoNormaJuridica diff --git a/sapl/norma/migrations/0014_auto_20181008_1655.py b/sapl/norma/migrations/0014_auto_20181008_1655.py new file mode 100644 index 000000000..da9bf4add --- /dev/null +++ b/sapl/norma/migrations/0014_auto_20181008_1655.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-10-08 19:55 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0021_appconfig_esfera_federacao'), + ('norma', '0013_anexonormajuridica_assunto_anexo'), + ] + + operations = [ + migrations.CreateModel( + name='AutoriaNorma', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('primeiro_autor', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Primeiro Autor')), + ('autor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.Autor', verbose_name='Autor')), + ('norma', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.NormaJuridica', verbose_name='Matéria Legislativa')), + ], + options={ + 'ordering': ('-primeiro_autor', 'autor__nome'), + 'verbose_name': 'Autoria', + 'verbose_name_plural': 'Autorias', + }, + ), + migrations.AddField( + model_name='normajuridica', + name='autores', + field=models.ManyToManyField(through='norma.AutoriaNorma', to='base.Autor'), + ), + migrations.AlterUniqueTogether( + name='autorianorma', + unique_together=set([('autor', 'norma')]), + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index e4e3677b3..46f34a0ef 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from model_utils import Choices import reversion +from sapl.base.models import Autor from sapl.compilacao.models import TextoArticulado from sapl.materia.models import MateriaLegislativa from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, @@ -129,6 +130,12 @@ class NormaJuridica(models.Model): auto_now=True, verbose_name=_('Data')) + autores = models.ManyToManyField( + Autor, + through='AutoriaNorma', + through_fields=('norma', 'autor'), + symmetrical=False) + class Meta: verbose_name = _('Norma Jurídica') verbose_name_plural = _('Normas Jurídicas') @@ -184,6 +191,28 @@ class NormaJuridica(models.Model): update_fields=update_fields) +@reversion.register() +class AutoriaNorma(models.Model): + autor = models.ForeignKey(Autor, + verbose_name=_('Autor'), + on_delete=models.CASCADE) + norma = models.ForeignKey( + NormaJuridica, on_delete=models.CASCADE, + verbose_name=_('Matéria Legislativa')) + primeiro_autor = models.BooleanField(verbose_name=_('Primeiro Autor'), + choices=YES_NO_CHOICES, + default=False) + + class Meta: + verbose_name = _('Autoria') + verbose_name_plural = _('Autorias') + unique_together = (('autor', 'norma'), ) + ordering = ('-primeiro_autor', 'autor__nome') + + def __str__(self): + return _('Autoria: %(autor)s - %(norma)s') % { + 'autor': self.autor, 'norma': self.norma} + @reversion.register() class LegislacaoCitada(models.Model): materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE) diff --git a/sapl/norma/urls.py b/sapl/norma/urls.py index d943f71e8..800707915 100644 --- a/sapl/norma/urls.py +++ b/sapl/norma/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import include, url from sapl.norma.views import (AnexoNormaJuridicaCrud,AssuntoNormaCrud, NormaCrud, NormaPesquisaView, NormaRelacionadaCrud, NormaTaView, TipoNormaCrud, TipoVinculoNormaJuridicaCrud, recuperar_norma, - recuperar_numero_norma) + recuperar_numero_norma, AutoriaNormaCrud) from .apps import AppConfig @@ -13,7 +13,8 @@ app_name = AppConfig.name urlpatterns = [ url(r'^norma/', include(NormaCrud.get_urls() + NormaRelacionadaCrud.get_urls() + - AnexoNormaJuridicaCrud.get_urls())), + AnexoNormaJuridicaCrud.get_urls() + + AutoriaNormaCrud.get_urls())), # Integração com Compilação url(r'^norma/(?P[0-9]+)/ta$', NormaTaView.as_view(), name='norma_ta'), diff --git a/sapl/norma/views.py b/sapl/norma/views.py index beae10d4d..b91aec2a5 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -21,9 +21,9 @@ from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, from sapl.utils import show_results_filter_set from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, - NormaPesquisaSimplesForm, NormaRelacionadaForm) + NormaPesquisaSimplesForm, NormaRelacionadaForm, AutoriaNormaForm) from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, - TipoNormaJuridica, TipoVinculoNormaJuridica) + TipoNormaJuridica, TipoVinculoNormaJuridica, AutoriaNorma) # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') @@ -274,6 +274,39 @@ def recuperar_numero_norma(request): return response +class AutoriaNormaCrud(MasterDetailCrud): + model = AutoriaNorma + parent_field = 'norma' + help_topic = 'despacho_autoria' + public = [RP_LIST, RP_DETAIL] + list_field_names = ['autor', 'autor__tipo__descricao', 'primeiro_autor'] + + class LocalBaseMixin(): + form_class = AutoriaNormaForm + + @property + def layout_key(self): + return None + + class CreateView(LocalBaseMixin, MasterDetailCrud.CreateView): + + def get_initial(self): + initial = super().get_initial() + norma = NormaJuridica.objects.get(id=self.kwargs['pk']) + initial['data_relativa'] = norma.data + initial['autor'] = [] + return initial + + class UpdateView(LocalBaseMixin, MasterDetailCrud.UpdateView): + + def get_initial(self): + initial = super().get_initial() + initial.update({ + 'data_relativa': self.object.norma.data_apresentacao, + 'tipo_autor': self.object.autor.tipo.id, + }) + return initial + class ImpressosView(PermissionRequiredMixin, TemplateView): template_name = 'materia/impressos/impressos.html' permission_required = ('materia.can_access_impressos', ) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index bba114149..e4ea00f2c 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -116,6 +116,7 @@ rules_group_materia = { (materia.Numeracao, __base__), (materia.Tramitacao, __base__), (norma.LegislacaoCitada, __base__), + (norma.AutoriaNorma, __base__), (compilacao.Dispositivo, __base__ + [ 'change_dispositivo_edicao_dinamica', @@ -136,6 +137,7 @@ rules_group_norma = { (norma.NormaJuridica, __base__), (norma.NormaRelacionada, __base__), (norma.AnexoNormaJuridica, __base__), + (norma.AutoriaNorma, __base__), # Publicacao está com permissão apenas para norma e não para matéria # e proposições apenas por análise do contexto, não é uma limitação diff --git a/sapl/templates/norma/autorianorma_form.html b/sapl/templates/norma/autorianorma_form.html new file mode 100644 index 000000000..35338c9de --- /dev/null +++ b/sapl/templates/norma/autorianorma_form.html @@ -0,0 +1,47 @@ +{% extends "crud/form.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load common_tags %} + +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/sapl/templates/norma/layouts.yaml b/sapl/templates/norma/layouts.yaml index 0075317c1..d881ae186 100644 --- a/sapl/templates/norma/layouts.yaml +++ b/sapl/templates/norma/layouts.yaml @@ -70,3 +70,7 @@ NormaRelacionadaDetail: {% trans 'Norma Relacionada' %}: - norma_relacionada - tipo_vinculo + +AutoriaNorma: + {% trans 'Autoria' %}: + - autor primeiro_autor \ No newline at end of file diff --git a/sapl/templates/norma/subnav.yaml b/sapl/templates/norma/subnav.yaml index 9358787ff..f85433e72 100644 --- a/sapl/templates/norma/subnav.yaml +++ b/sapl/templates/norma/subnav.yaml @@ -7,7 +7,8 @@ check_permission: norma.list_normarelacionada - title: {% trans 'Anexos da Norma' %} url: anexonormajuridica_list - +- title: {% trans 'Autoria' %} + url: autorianorma_list # Opção adicionada para chamar o TextoArticulado da norma. # para integração foram necessárias apenas criar a url norma_ta em urls.py # e a view NormaTaView(IntegracaoTaView) em views.py From a6fc9879d3148acd41f7d3f8d24a7e6723a488c9 Mon Sep 17 00:00:00 2001 From: AndreSouto Date: Tue, 9 Oct 2018 15:19:01 -0300 Subject: [PATCH 69/88] Fixes #2030 (#2277) * Fixes #2030 * Fixes #2030 * Fixes #2030 --- .../templates/pdf_sessao_plenaria_gerar.py | 28 +++++++- sapl/relatorios/views.py | 37 ++++++++-- sapl/rules/map_rules.py | 41 +++++------ sapl/sessao/forms.py | 11 ++- .../migrations/0024_ocorrenciasessao.py | 28 ++++++++ .../migrations/0025_auto_20180919_1116.py | 21 ++++++ sapl/sessao/models.py | 15 ++++ sapl/sessao/urls.py | 6 +- sapl/sessao/views.py | 70 +++++++++++++++++-- .../blocos_ata/ocorrencias_da_sessao.html | 6 ++ .../blocos_resumo/ocorrencias_da_sessao.html | 6 ++ sapl/templates/sessao/ocorrencia_sessao.html | 32 +++++++++ sapl/templates/sessao/resumo.html | 2 + sapl/templates/sessao/resumo_ata.html | 1 + sapl/templates/sessao/subnav.yaml | 2 + 15 files changed, 270 insertions(+), 36 deletions(-) create mode 100644 sapl/sessao/migrations/0024_ocorrenciasessao.py create mode 100644 sapl/sessao/migrations/0025_auto_20180919_1116.py create mode 100644 sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html create mode 100644 sapl/templates/sessao/blocos_resumo/ocorrencias_da_sessao.html create mode 100644 sapl/templates/sessao/ocorrencia_sessao.html diff --git a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py index 1c01bfb08..1f0f6482c 100644 --- a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py +++ b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py @@ -6,6 +6,9 @@ """ import time +from django.template.defaultfilters import safe +from django.utils.html import strip_tags + from sapl.sessao.models import ResumoOrdenacao from trml2pdf import parseString @@ -284,7 +287,25 @@ def oradores(lst_oradores): return tmp -def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_mesa, lst_presenca_sessao, lst_expedientes, lst_expediente_materia, lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, lst_oradores): +def ocorrencias(lst_ocorrencias): + """ + + """ + tmp = '' + tmp += '\t\tOcorrências da Sessão\n' + tmp += '\t\t\n' + tmp += '\t\t\t \n' + tmp += '\t\t\n' + for idx, ocorrencia in enumerate(lst_ocorrencias): + tmp += '\t\t' + \ + str(ocorrencia.conteudo) + '\n' + tmp += '\t\t\n' + tmp += '\t\t\t \n' + tmp += '\t\t\n' + return tmp + + +def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_mesa, lst_presenca_sessao, lst_expedientes, lst_expediente_materia, lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, lst_oradores, lst_ocorrencias): """ """ arquivoPdf = str(int(time.time() * 100)) + ".pdf" @@ -316,7 +337,8 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me 'mat_o_d': votacao(lst_votacao), 'mesa_d': mesa(lst_mesa), 'oradores_exped': oradores_expediente(lst_oradores_expediente), - 'oradores_expli': oradores(lst_oradores) + 'oradores_expli': oradores(lst_oradores), + 'ocorr_sessao': ocorrencias(lst_ocorrencias) } if ordenacao: @@ -330,6 +352,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me tmp += dict_ord_template[ordenacao.oitavo] tmp += dict_ord_template[ordenacao.nono] tmp += dict_ord_template[ordenacao.decimo] + else: tmp += inf_basicas(inf_basicas_dic) tmp += mesa(lst_mesa) @@ -340,6 +363,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me tmp += presenca_ordem_dia(lst_presenca_ordem_dia) tmp += votacao(lst_votacao) tmp += oradores(lst_oradores) + tmp += ocorrencias(lst_ocorrencias) tmp += '\t\n' tmp += '\n' diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 4d273b6da..2f48f627f 100644 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -17,7 +17,7 @@ from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo, from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, IntegranteMesa, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, - SessaoPlenariaPresenca) + SessaoPlenariaPresenca, OcorrenciaSessao) from sapl.settings import STATIC_ROOT from sapl.utils import LISTA_DE_UFS, ExtraiTag, TrocaTag, filiacao_data @@ -514,13 +514,13 @@ def get_sessao_plenaria(sessao, casa): dic_presenca['sgl_partido'] = partido_sigla lst_presenca_sessao.append(dic_presenca) + # Exibe os Expedientes lst_expedientes = [] expedientes = ExpedienteSessao.objects.filter( sessao_plenaria=sessao).order_by('tipo__nome') for e in expedientes: - dic_expedientes = {} dic_expedientes["nom_expediente"] = e.tipo.nome conteudo = e.conteudo @@ -539,6 +539,7 @@ def get_sessao_plenaria(sessao, casa): if dic_expedientes: lst_expedientes.append(dic_expedientes) + # Lista das matérias do Expediente, incluindo o resultado das votacoes lst_expediente_materia = [] for expediente_materia in ExpedienteMateria.objects.filter( @@ -727,6 +728,28 @@ def get_sessao_plenaria(sessao, casa): dic_oradores['sgl_partido'] = sigla lst_oradores.append(dic_oradores) + # Ocorrências da Sessão + lst_ocorrencias = [] + ocorrencias = OcorrenciaSessao.objects.filter( + sessao_plenaria=sessao) + + for o in ocorrencias: + conteudo = o.conteudo + + # unescape HTML codes + # https://github.com/interlegis/sapl/issues/1046 + conteudo = re.sub('style=".*?"', '', conteudo) + conteudo = html.unescape(conteudo) + + # escape special character '&' + # https://github.com/interlegis/sapl/issues/1009 + conteudo = conteudo.replace('&', '&') + + o.conteudo = conteudo + + lst_ocorrencias.append(o) + + return (inf_basicas_dic, lst_mesa, lst_presenca_sessao, @@ -735,7 +758,8 @@ def get_sessao_plenaria(sessao, casa): lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, - lst_oradores) + lst_oradores, + lst_ocorrencias) def get_turno(dic, materia, sessao_data_inicio): @@ -785,7 +809,9 @@ def relatorio_sessao_plenaria(request, pk): lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, - lst_oradores) = get_sessao_plenaria(sessao, casa) + lst_oradores, + lst_ocorrencias) = get_sessao_plenaria(sessao, casa) + for idx in range(len(lst_expedientes)): txt_expedientes = lst_expedientes[idx]['txt_expediente'] @@ -806,7 +832,8 @@ def relatorio_sessao_plenaria(request, pk): lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, - lst_oradores) + lst_oradores, + lst_ocorrencias) response.write(pdf) return response diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index e4ea00f2c..47a43d9e1 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -1,23 +1,3 @@ -from sapl.base import models as base -from sapl.comissoes import models as comissoes -from sapl.compilacao import models as compilacao -from sapl.lexml import models as lexml -from sapl.materia import models as materia -from sapl.norma import models as norma -from sapl.painel import models as painel -from sapl.parlamentares import models as parlamentares -from sapl.protocoloadm import models as protocoloadm -from sapl.audiencia import models as audiencia -from sapl.rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST, - SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, - SAPL_GROUP_AUTOR, SAPL_GROUP_COMISSOES, - SAPL_GROUP_GERAL, SAPL_GROUP_LOGIN_SOCIAL, - SAPL_GROUP_MATERIA, SAPL_GROUP_NORMA, - SAPL_GROUP_PAINEL, SAPL_GROUP_PARLAMENTAR, - SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO, - SAPL_GROUP_VOTANTE) -from sapl.sessao import models as sessao - """ Todas as permissões do django framework seguem o padrão @@ -46,6 +26,26 @@ negócio trabalham com os cinco radiais de permissão e com qualquer outro tipo de permissão customizada, nesta ordem de precedência. """ +from sapl.audiencia import models as audiencia +from sapl.base import models as base +from sapl.comissoes import models as comissoes +from sapl.compilacao import models as compilacao +from sapl.lexml import models as lexml +from sapl.materia import models as materia +from sapl.norma import models as norma +from sapl.painel import models as painel +from sapl.parlamentares import models as parlamentares +from sapl.protocoloadm import models as protocoloadm +from sapl.rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST, + SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, + SAPL_GROUP_AUTOR, SAPL_GROUP_COMISSOES, + SAPL_GROUP_GERAL, SAPL_GROUP_LOGIN_SOCIAL, + SAPL_GROUP_MATERIA, SAPL_GROUP_NORMA, + SAPL_GROUP_PAINEL, SAPL_GROUP_PARLAMENTAR, + SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO, + SAPL_GROUP_VOTANTE) +from sapl.sessao import models as sessao + __base__ = [RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE] __listdetailchange__ = [RP_LIST, RP_DETAIL, RP_CHANGE] @@ -161,6 +161,7 @@ rules_group_sessao = { (sessao.SessaoPlenaria, __base__), (sessao.SessaoPlenariaPresenca, __base__), (sessao.ExpedienteMateria, __base__), + (sessao.OcorrenciaSessao, __base__), (sessao.IntegranteMesa, __base__), (sessao.ExpedienteSessao, __base__), (sessao.Orador, __base__), diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 5d36ba99a..96e85b9d8 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -22,7 +22,7 @@ from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, from .models import (Bancada, Bloco, ExpedienteMateria, Orador, OradorExpediente, OrdemDia, SessaoPlenaria, - SessaoPlenariaPresenca, TipoResultadoVotacao) + SessaoPlenariaPresenca, TipoResultadoVotacao, OcorrenciaSessao) def recupera_anos(): @@ -54,7 +54,8 @@ ORDENACAO_RESUMO = [('cont_mult', 'Conteúdo Multimídia'), ('mat_o_d', 'Matérias da Ordem do Dia'), ('mesa_d', 'Mesa Diretora'), ('oradores_exped', 'Oradores do Expediente'), - ('oradores_expli', 'Oradores das Explicações Pessoais')] + ('oradores_expli', 'Oradores das Explicações Pessoais'), + ('ocorrencia_sessao', 'Ocorrências da Sessão')] class SessaoPlenariaForm(ModelForm): @@ -412,6 +413,12 @@ class MesaForm(forms.Form): class ExpedienteForm(forms.Form): conteudo = forms.CharField(required=False, widget=forms.Textarea) +class OcorrenciaSessaoForm(ModelForm): + class Meta: + model = OcorrenciaSessao + fields = ['conteudo'] + + class VotacaoForm(forms.Form): votos_sim = forms.CharField(label='Sim') diff --git a/sapl/sessao/migrations/0024_ocorrenciasessao.py b/sapl/sessao/migrations/0024_ocorrenciasessao.py new file mode 100644 index 000000000..6c612363f --- /dev/null +++ b/sapl/sessao/migrations/0024_ocorrenciasessao.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2018-09-18 13:44 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0023_auto_20180914_1315'), + ] + + operations = [ + migrations.CreateModel( + name='OcorrenciaSessao', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('conteudo', models.TextField(blank=True, verbose_name='Ocorrências da Sessão Plenária')), + ('sessao_plenaria', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sessao.SessaoPlenaria')), + ], + options={ + 'verbose_name_plural': 'Ocorrências da Sessão Plenaria', + 'verbose_name': 'Ocorrência da Sessão Plenaria', + }, + ), + ] diff --git a/sapl/sessao/migrations/0025_auto_20180919_1116.py b/sapl/sessao/migrations/0025_auto_20180919_1116.py new file mode 100644 index 000000000..fa4c0a435 --- /dev/null +++ b/sapl/sessao/migrations/0025_auto_20180919_1116.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-09-19 14:16 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0024_ocorrenciasessao'), + ] + + operations = [ + migrations.AlterField( + model_name='ocorrenciasessao', + name='sessao_plenaria', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='sessao.SessaoPlenaria'), + ), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index 11047ed9e..7f8ea0882 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -301,6 +301,21 @@ class ExpedienteSessao(models.Model): # ExpedienteSessaoPlenaria return '%s - %s' % (self.tipo, self.sessao_plenaria) +@reversion.register() +class OcorrenciaSessao(models.Model): # OcorrenciaSessaoPlenaria + sessao_plenaria = models.OneToOneField(SessaoPlenaria, + on_delete=models.PROTECT) + conteudo = models.TextField( + blank=True, verbose_name=_('Ocorrências da Sessão Plenária')) + + class Meta: + verbose_name = _('Ocorrência da Sessão Plenaria') + verbose_name_plural = _('Ocorrências da Sessão Plenaria') + + def __str__(self): + return '%s - %s' % (self.sessao_plenaria, self.conteudo) + + @reversion.register() class IntegranteMesa(models.Model): # MesaSessaoPlenaria sessao_plenaria = models.ForeignKey(SessaoPlenaria, diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py index 201623824..1e3e4ae43 100644 --- a/sapl/sessao/urls.py +++ b/sapl/sessao/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import include, url from sapl.sessao.views import (AdicionarVariasMateriasExpediente, AdicionarVariasMateriasOrdemDia, BancadaCrud, BlocoCrud, CargoBancadaCrud, - ExpedienteMateriaCrud, ExpedienteView, + ExpedienteMateriaCrud, ExpedienteView, OcorrenciaSessaoView, MateriaOrdemDiaCrud, MesaView, OradorCrud, OradorExpedienteCrud, PainelView, PautaSessaoDetailView, PautaSessaoView, @@ -100,6 +100,8 @@ urlpatterns = [ # Subnav sessão url(r'^sessao/(?P\d+)/expediente$', ExpedienteView.as_view(), name='expediente'), + url(r'^sessao/(?P\d+)/ocorrencia_sessao$', + OcorrenciaSessaoView.as_view(), name='ocorrencia_sessao'), url(r'^sessao/(?P\d+)/presenca$', PresencaView.as_view(), name='presenca'), url(r'^sessao/(?P\d+)/painel$', @@ -110,7 +112,7 @@ urlpatterns = [ url(r'^sessao/(?P\d+)/resumo$', ResumoView.as_view(), name='resumo'), url(r'^sessao/(?P\d+)/resumo_ata$', - ResumoAtaView.as_view(), name='resumo_ata'), + ResumoAtaView.as_view(), name='resumo_ata'), url(r'^sessao/pesquisar-sessao$', PesquisarSessaoPlenariaView.as_view(), name='pesquisar_sessao'), url(r'^sessao/(?P\d+)/matordemdia/votnom/(?P\d+)/(?P\d+)$', diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index d64f3dba0..6cc9300fb 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -37,13 +37,13 @@ from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm from sapl.utils import show_results_filter_set, remover_acentos from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, BlocoForm, - ExpedienteForm, ListMateriaForm, MesaForm, + ExpedienteForm, OcorrenciaSessaoForm, ListMateriaForm, MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet, PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet, SessaoPlenariaForm, VotacaoEditForm, VotacaoForm, VotacaoNominalForm) from .models import (Bancada, Bloco, CargoBancada, CargoMesa, - ExpedienteMateria, ExpedienteSessao, IntegranteMesa, + ExpedienteMateria, ExpedienteSessao, OcorrenciaSessao, IntegranteMesa, MateriaLegislativa, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, RegistroVotacao, ResumoOrdenacao, SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente, @@ -1175,7 +1175,8 @@ class ResumoOrdenacaoView(PermissionRequiredMixin, FormView): 'setimo': ordenacao.setimo, 'oitavo': ordenacao.oitavo, 'nono': ordenacao.nono, - 'decimo': ordenacao.decimo}) + 'decimo': ordenacao.decimo, + 'decimo_primeiro': ordenacao.decimo_primeiro}) return initial def form_valid(self, form): @@ -1191,6 +1192,7 @@ class ResumoOrdenacaoView(PermissionRequiredMixin, FormView): ordenacao.oitavo = form.cleaned_data['oitavo'] ordenacao.nono = form.cleaned_data['nono'] ordenacao.decimo = form.cleaned_data['decimo'] + ordenacao.decimo_primeiro = form.cleaned_data['decimo_primeiro'] ordenacao.save() @@ -1280,6 +1282,7 @@ class ResumoView(DetailView): ex = {'tipo': tipo, 'conteudo': conteudo} expedientes.append(ex) context.update({'expedientes': expedientes}) + # ===================================================================== # Matérias Expediente materias = ExpedienteMateria.objects.filter( @@ -1413,6 +1416,12 @@ class ResumoView(DetailView): oradores_explicacoes.append(oradores) context.update({'oradores_explicacoes': oradores_explicacoes}) + # ===================================================================== + # Ocorrẽncias da Sessão + ocorrencias_sessao = OcorrenciaSessao.objects.filter(sessao_plenaria_id=self.object.id) + + context.update({'ocorrencias_da_sessao': ocorrencias_sessao}) + # ===================================================================== # Indica a ordem com a qual o template será renderizado ordenacao = ResumoOrdenacao.objects.first() @@ -1426,7 +1435,8 @@ class ResumoView(DetailView): 'mat_o_d': 'materias_ordem_dia.html', 'mesa_d': 'mesa_diretora.html', 'oradores_exped': 'oradores_expediente.html', - 'oradores_expli': 'oradores_explicacoes.html' + 'oradores_expli': 'oradores_explicacoes.html', + 'ocorr_sessao': 'ocorrencias_da_sessao.html' } if ordenacao: @@ -1452,12 +1462,16 @@ class ResumoView(DetailView): 'setimo_ordenacao': dict_ord_template['oradores_exped'], 'oitavo_ordenacao': dict_ord_template['lista_p_o_d'], 'nono_ordenacao': dict_ord_template['mat_o_d'], - 'decimo_ordenacao': dict_ord_template['oradores_expli']}) + 'decimo_ordenacao': dict_ord_template['oradores_expli'], + 'decimo_primeiro_ordenacao': dict_ord_template['ocorr_sessao']}) return self.render_to_response(context) + + class ResumoAtaView(ResumoView): template_name = 'sessao/resumo_ata.html' + class ExpedienteView(FormMixin, DetailView): template_name = 'sessao/expediente.html' form_class = ExpedienteForm @@ -1537,6 +1551,52 @@ class ExpedienteView(FormMixin, DetailView): return reverse('sapl.sessao:expediente', kwargs={'pk': pk}) + +class OcorrenciaSessaoView(FormMixin, DetailView): + template_name = 'sessao/ocorrencia_sessao.html' + form_class = OcorrenciaSessaoForm + model = SessaoPlenaria + + def delete(self): + OcorrenciaSessao.objects.filter(sessao_plenaria=self.object).delete() + + msg = _('Registro deletado com sucesso') + messages.add_message(self.request, messages.SUCCESS, msg) + + def save(self,form): + conteudo = form.cleaned_data['conteudo'] + + OcorrenciaSessao.objects.filter(sessao_plenaria=self.object).delete() + + ocorrencia = OcorrenciaSessao() + ocorrencia.sessao_plenaria_id = self.object.id + ocorrencia.conteudo = conteudo + ocorrencia.save() + + msg = _('Registro salvo com sucesso') + messages.add_message(self.request, messages.SUCCESS, msg) + + @method_decorator(permission_required('sessao.add_ocorrenciasessao')) + def post(self, request, *args, **kwargs): + self.object = self.get_object() + form = OcorrenciaSessaoForm(request.POST) + + if not form.is_valid(): + return self.form_invalid(form) + + if request.POST.get('delete'): + self.delete() + + elif request.POST.get('save'): + self.save(form) + + return self.form_valid(form) + + def get_success_url(self): + pk = self.kwargs['pk'] + return reverse('sapl.sessao:ocorrencia_sessao', kwargs={'pk': pk}) + + class VotacaoEditView(SessaoPermissionMixin): ''' diff --git a/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html b/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html new file mode 100644 index 000000000..b1385e7c2 --- /dev/null +++ b/sapl/templates/sessao/blocos_ata/ocorrencias_da_sessao.html @@ -0,0 +1,6 @@ +
    +

    + Ocorrências da Sessão: + {{object.ocorrenciasessao.conteudo|safe}} +

    +
    diff --git a/sapl/templates/sessao/blocos_resumo/ocorrencias_da_sessao.html b/sapl/templates/sessao/blocos_resumo/ocorrencias_da_sessao.html new file mode 100644 index 000000000..c56a1bb69 --- /dev/null +++ b/sapl/templates/sessao/blocos_resumo/ocorrencias_da_sessao.html @@ -0,0 +1,6 @@ +
    + Ocorrências da Sessão +
    +

    {{object.ocorrenciasessao.conteudo|safe}}

    +
    +
    \ No newline at end of file diff --git a/sapl/templates/sessao/ocorrencia_sessao.html b/sapl/templates/sessao/ocorrencia_sessao.html new file mode 100644 index 000000000..0daa921d8 --- /dev/null +++ b/sapl/templates/sessao/ocorrencia_sessao.html @@ -0,0 +1,32 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load common_tags %} + +{% block actions %}{% endblock %} + +{% block title %}Ocorrências da Sessão ({{ object }}) {% endblock %} + +{% block detail_content %} + {% if perms|get_add_perm:view %} +
    + {% csrf_token %} +
    + +
    + + + + {% else %} + {{object.ocorrenciasessao.conteudo|safe}} + {% endif %} +{% endblock detail_content %} + + +{% block extra_js %} + {% if perms|get_add_perm:view %} + + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/sapl/templates/sessao/resumo.html b/sapl/templates/sessao/resumo.html index b5831bdca..c7c2070ce 100644 --- a/sapl/templates/sessao/resumo.html +++ b/sapl/templates/sessao/resumo.html @@ -50,5 +50,7 @@ {% include 'sessao/blocos_resumo/'|add:decimo_ordenacao %}


    + {% include 'sessao/blocos_resumo/'|add:decimo_primeiro_ordenacao %} +


    {% endblock detail_content %} diff --git a/sapl/templates/sessao/resumo_ata.html b/sapl/templates/sessao/resumo_ata.html index a842b3f40..e1c1000a9 100644 --- a/sapl/templates/sessao/resumo_ata.html +++ b/sapl/templates/sessao/resumo_ata.html @@ -19,5 +19,6 @@ {% 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/'|add:decimo_primeiro_ordenacao %} {% include 'sessao/blocos_ata/assinaturas.html' %} {% endblock detail_content %} \ No newline at end of file diff --git a/sapl/templates/sessao/subnav.yaml b/sapl/templates/sessao/subnav.yaml index 236d57c4c..0a98b8a3b 100644 --- a/sapl/templates/sessao/subnav.yaml +++ b/sapl/templates/sessao/subnav.yaml @@ -10,6 +10,8 @@ url: presenca - title: {% trans 'Explicações Pessoais' %} url: orador_list + - title: {% trans 'Ocorrências da Sessão' %} + url: ocorrencia_sessao - title: {% trans 'Expedientes' %} children: From b6b3aec18841f3293789eb64523fcbe6f98be3e0 Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Tue, 9 Oct 2018 15:20:55 -0300 Subject: [PATCH 70/88] Fix #2252 Acompanhamento de Documento Administrativo (#2257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #2252 * Muda mensagens de ERROR para WARNING in quando da erro no envio do email na tramitação * Muda mensagens de ERROR para WARNING in quando da erro no envio do email na tramitação * Fixing travis errors * Fix tests * Update acompanhar_documento.txt * Update email_utils.py * Update receivers.py * Update test_email_templates.py * adicionados testes de template dos email de acompanhamento * tirar duplicidade --- sapl/{materia => base}/email_utils.py | 134 ++++++++----- sapl/base/receivers.py | 42 ++++ sapl/{materia => base}/signals.py | 0 sapl/materia/apps.py | 2 +- sapl/materia/receivers.py | 29 --- sapl/materia/tests/test_email_templates.py | 2 +- sapl/materia/views.py | 15 +- sapl/protocoloadm/apps.py | 3 + sapl/protocoloadm/forms.py | 27 ++- .../0008_acompanhamentodocumento.py | 32 +++ sapl/protocoloadm/models.py | 27 +++ .../tests/test_docadm_email_templates.py | 65 +++++++ sapl/protocoloadm/urls.py | 14 +- sapl/protocoloadm/views.py | 184 +++++++++++++++++- sapl/rules/map_rules.py | 1 + sapl/rules/tests/test_rules.py | 4 + .../templates/email/acompanhar_documento.html | 25 +++ sapl/templates/email/acompanhar_documento.txt | 16 ++ sapl/templates/email/tramitacao.html | 2 + sapl/templates/email/tramitacao.txt | 4 +- .../acompanhamento_documento.html | 21 ++ .../documentoadministrativo_filter.html | 3 + 22 files changed, 553 insertions(+), 99 deletions(-) rename sapl/{materia => base}/email_utils.py (56%) create mode 100644 sapl/base/receivers.py rename sapl/{materia => base}/signals.py (100%) delete mode 100644 sapl/materia/receivers.py create mode 100644 sapl/protocoloadm/migrations/0008_acompanhamentodocumento.py create mode 100644 sapl/protocoloadm/tests/test_docadm_email_templates.py create mode 100644 sapl/templates/email/acompanhar_documento.html create mode 100644 sapl/templates/email/acompanhar_documento.txt create mode 100644 sapl/templates/protocoloadm/acompanhamento_documento.html diff --git a/sapl/materia/email_utils.py b/sapl/base/email_utils.py similarity index 56% rename from sapl/materia/email_utils.py rename to sapl/base/email_utils.py index 3dc6b220d..737449e57 100644 --- a/sapl/materia/email_utils.py +++ b/sapl/base/email_utils.py @@ -8,7 +8,8 @@ from django.utils import timezone from sapl.base.models import CasaLegislativa from sapl.settings import EMAIL_SEND_USER -from .models import AcompanhamentoMateria +from sapl.materia.models import AcompanhamentoMateria +from sapl.protocoloadm.models import AcompanhamentoDocumento def load_email_templates(templates, context={}): @@ -61,56 +62,73 @@ def enviar_emails(sender, recipients, messages): fail_silently=False) -def criar_email_confirmacao(base_url, casa_legislativa, materia, hash_txt=''): +def criar_email_confirmacao(base_url, casa_legislativa, doc_mat, tipo, hash_txt=''): if not casa_legislativa: raise ValueError("Casa Legislativa é obrigatória") - if not materia: - raise ValueError("Matéria é obrigatória") + if not doc_mat: + if tipo == "materia": + msg = "Matéria é obrigatória" + else: + msg = "Documento é obrigatório" + raise ValueError(msg) # FIXME i18n - casa_nome = (casa_legislativa.nome + ' de ' + - casa_legislativa.municipio + '-' + - casa_legislativa.uf) + casa_nome = ("{} de {} - {}".format(casa_legislativa.nome, + casa_legislativa.municipio, + casa_legislativa.uf)) + + if tipo == "materia": + doc_mat_url = reverse('sapl.materia:materialegislativa_detail', + kwargs={'pk': doc_mat.id}) + confirmacao_url = reverse('sapl.materia:acompanhar_confirmar', + kwargs={'pk': doc_mat.id}) + ementa = doc_mat.ementa + autores = [autoria.autor.nome for autoria in doc_mat.autoria_set.all()] + else: + doc_mat_url = reverse('sapl.protocoloadm:documentoadministrativo_detail', + kwargs={'pk': doc_mat.id}) + confirmacao_url = reverse('sapl.protocoloadm:acompanhar_confirmar', + kwargs={'pk': doc_mat.id}) + ementa = doc_mat.assunto + autores = "" - materia_url = reverse('sapl.materia:materialegislativa_detail', - kwargs={'pk': materia.id}) - confirmacao_url = reverse('sapl.materia:acompanhar_confirmar', - kwargs={'pk': materia.id}) - autores = [] - for autoria in materia.autoria_set.all(): - autores.append(autoria.autor.nome) templates = load_email_templates(['email/acompanhar.txt', 'email/acompanhar.html'], {"casa_legislativa": casa_nome, "logotipo": casa_legislativa.logotipo, - "descricao_materia": materia.ementa, + "descricao_materia": ementa, "autoria": autores, "hash_txt": hash_txt, "base_url": base_url, - "materia": str(materia), - "materia_url": materia_url, + "materia": str(doc_mat), + "materia_url": doc_mat_url, "confirmacao_url": confirmacao_url, }) return templates -def do_envia_email_confirmacao(base_url, casa, materia, destinatario): +def do_envia_email_confirmacao(base_url, casa, tipo, doc_mat, destinatario): # # Envia email de confirmacao para atualizações de tramitação # sender = EMAIL_SEND_USER # FIXME i18n - subject = "[SAPL] " + str(materia) + " - Ative o Acompanhamento da Materia" + if tipo == "materia": + msg = " - Ative o Acompanhamento da Matéria" + else: + msg = " - Ative o Acompanhamento de Documento" + subject = "[SAPL] {} {}".format(str(doc_mat), msg) messages = [] recipients = [] email_texts = criar_email_confirmacao(base_url, casa, - materia, + doc_mat, + tipo, destinatario.hash,) recipients.append(destinatario.email) messages.append({ @@ -123,30 +141,41 @@ def do_envia_email_confirmacao(base_url, casa, materia, destinatario): enviar_emails(sender, recipients, messages) -def criar_email_tramitacao(base_url, casa_legislativa, materia, status, +def criar_email_tramitacao(base_url, casa_legislativa, tipo, doc_mat, status, unidade_destino, hash_txt=''): if not casa_legislativa: raise ValueError("Casa Legislativa é obrigatória") - if not materia: - raise ValueError("Matéria é obrigatória") + if not doc_mat: + if tipo == "materia": + msg = "Matéria é obrigatória" + else: + msg = "Documento é obrigatório" + raise ValueError(msg) # FIXME i18n - casa_nome = (casa_legislativa.nome + ' de ' + - casa_legislativa.municipio + '-' + - casa_legislativa.uf) - - url_materia = reverse('sapl.materia:tramitacao_list', - kwargs={'pk': materia.id}) - url_excluir = reverse('sapl.materia:acompanhar_excluir', - kwargs={'pk': materia.id}) + casa_nome = ("{} de {} - {}".format(casa_legislativa.nome, + casa_legislativa.municipio, + casa_legislativa.uf)) + if tipo == "materia": + doc_mat_url = reverse('sapl.materia:tramitacao_list', + kwargs={'pk': doc_mat.id}) + url_excluir = reverse('sapl.materia:acompanhar_excluir', + kwargs={'pk': doc_mat.id}) + + ementa = doc_mat.ementa + autores = [autoria.autor.nome for autoria in doc_mat.autoria_set.all()] + tramitacao = doc_mat.tramitacao_set.last() - autores = [] - for autoria in materia.autoria_set.all(): - autores.append(autoria.autor.nome) - - tramitacao = materia.tramitacao_set.last() + else: + doc_mat_url = reverse('sapl.protocoloadm:tramitacaoadministrativo_list', + kwargs={'pk': doc_mat.id}) + url_excluir = reverse('sapl.protocoloadm:acompanhar_excluir', + kwargs={'pk': doc_mat.id}) + autores = "" + ementa = doc_mat.assunto + tramitacao = doc_mat.tramitacaoadministrativo_set.last() templates = load_email_templates(['email/tramitacao.txt', 'email/tramitacao.html'], @@ -154,34 +183,42 @@ def criar_email_tramitacao(base_url, casa_legislativa, materia, status, "data_registro": dt.strftime( timezone.now(), "%d/%m/%Y"), - "cod_materia": materia.id, + "cod_materia": doc_mat.id, "logotipo": casa_legislativa.logotipo, - "descricao_materia": materia.ementa, + "descricao_materia": ementa, "autoria": autores, "data": tramitacao.data_tramitacao, "status": status, "localizacao": unidade_destino, "texto_acao": tramitacao.texto, "hash_txt": hash_txt, - "materia": str(materia), + "materia": str(doc_mat), "base_url": base_url, - "materia_url": url_materia, + "materia_url": doc_mat_url, "excluir_url": url_excluir}) return templates -def do_envia_email_tramitacao(base_url, materia, status, unidade_destino): +def do_envia_email_tramitacao(base_url, tipo, doc_mat, status, unidade_destino): # # Envia email de tramitacao para usuarios cadastrados # - destinatarios = AcompanhamentoMateria.objects.filter(materia=materia, - confirmado=True) + if tipo == "materia": + destinatarios = AcompanhamentoMateria.objects.filter(materia=doc_mat, + confirmado=True) + else: + destinatarios = AcompanhamentoDocumento.objects.filter(documento=doc_mat, + confirmado=True) + casa = CasaLegislativa.objects.first() sender = EMAIL_SEND_USER - # FIXME i18n - subject = "[SAPL] " + str(materia) + \ - " - Acompanhamento de Materia Legislativa" + # FIXME i18nn + if tipo == "materia": + msg = " - Acompanhamento de Matéria Legislativa" + else: + msg = " - Acompanhamento de Documento" + subject = "[SAPL] {} {}".format(str(doc_mat), msg) connection = get_connection() connection.open() @@ -190,10 +227,11 @@ def do_envia_email_tramitacao(base_url, materia, status, unidade_destino): try: email_texts = criar_email_tramitacao(base_url, casa, - materia, + tipo, + doc_mat, status, unidade_destino, - destinatario.hash,) + destinatario.hash) email = EmailMultiAlternatives( subject, diff --git a/sapl/base/receivers.py b/sapl/base/receivers.py new file mode 100644 index 000000000..b2176be14 --- /dev/null +++ b/sapl/base/receivers.py @@ -0,0 +1,42 @@ +from django.db.models.signals import post_delete, post_save +from django.dispatch import receiver + +from sapl.materia.models import Tramitacao +from sapl.protocoloadm.models import TramitacaoAdministrativo +from sapl.base.signals import tramitacao_signal +from sapl.utils import get_base_url + +from sapl.base.email_utils import do_envia_email_tramitacao + + +@receiver(tramitacao_signal) +def handle_tramitacao_signal(sender, **kwargs): + tramitacao = kwargs.get("post") + request = kwargs.get("request") + if 'protocoloadm' in str(sender): + doc_mat = tramitacao.documento + tipo = "documento" + elif 'materia' in str(sender): + tipo = "materia" + doc_mat = tramitacao.materia + + do_envia_email_tramitacao( + get_base_url(request), + tipo, + doc_mat, + tramitacao.status, + tramitacao.unidade_tramitacao_destino) + + +@receiver(post_delete) +def status_tramitacao_materia(sender, instance, **kwargs): + if isinstance(sender, TramitacaoAdministrativo): + if instance.status.indicador == 'F': + materia = instance.materia + materia.em_tramitacao = True + materia.save() + elif isinstance(sender, TramitacaoAdministrativo): + if instance.status.indicador == 'F': + documento = instance.documento + documento.tramitacao = True + documento.save() diff --git a/sapl/materia/signals.py b/sapl/base/signals.py similarity index 100% rename from sapl/materia/signals.py rename to sapl/base/signals.py diff --git a/sapl/materia/apps.py b/sapl/materia/apps.py index bb4f72f73..2cc3559ae 100644 --- a/sapl/materia/apps.py +++ b/sapl/materia/apps.py @@ -8,4 +8,4 @@ class AppConfig(apps.AppConfig): verbose_name = _('Matéria') def ready(self): - from . import receivers + from sapl.base import receivers diff --git a/sapl/materia/receivers.py b/sapl/materia/receivers.py deleted file mode 100644 index 945c6636e..000000000 --- a/sapl/materia/receivers.py +++ /dev/null @@ -1,29 +0,0 @@ -from django.db.models.signals import post_delete, post_save -from django.dispatch import receiver - -from sapl.materia.models import Tramitacao -from sapl.materia.signals import tramitacao_signal -from sapl.utils import get_base_url - -from .email_utils import do_envia_email_tramitacao - - -@receiver(tramitacao_signal) -def handle_tramitacao_signal(sender, **kwargs): - tramitacao = kwargs.get("post") - request = kwargs.get("request") - materia = tramitacao.materia - - do_envia_email_tramitacao( - get_base_url(request), - materia, - tramitacao.status, - tramitacao.unidade_tramitacao_destino) - - -@receiver(post_delete, sender=Tramitacao) -def status_tramitacao_materia(sender, instance, **kwargs): - if instance.status.indicador == 'F': - materia = instance.materia - materia.em_tramitacao = True - materia.save() diff --git a/sapl/materia/tests/test_email_templates.py b/sapl/materia/tests/test_email_templates.py index aac13cbb7..32b2f7ec8 100644 --- a/sapl/materia/tests/test_email_templates.py +++ b/sapl/materia/tests/test_email_templates.py @@ -1,6 +1,6 @@ from django.core import mail -from sapl.materia.email_utils import enviar_emails, load_email_templates +from sapl.base.email_utils import enviar_emails, load_email_templates def test_email_template_loading(): diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 9e738dbe9..767726a97 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -46,7 +46,7 @@ from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, get_mime_type_from_file_extension, montar_row_autor, show_results_filter_set) -from .email_utils import do_envia_email_confirmacao +from sapl.base.email_utils import do_envia_email_confirmacao from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, AdicionarVariasAutoriasFilterSet, DespachoInicialForm, DocumentoAcessorioForm, EtiquetaPesquisaForm, @@ -65,7 +65,7 @@ from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria, RegimeTramitacao, Relatoria, StatusTramitacao, TipoDocumento, TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao, Tramitacao, UnidadeTramitacao) -from .signals import tramitacao_signal +from sapl.base.signals import tramitacao_signal AssuntoMateriaCrud = CrudAux.build(AssuntoMateria, 'assunto_materia') @@ -1114,7 +1114,7 @@ class TramitacaoCrud(MasterDetailCrud): 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) + messages.add_message(self.request, messages.WARNING, msg) return HttpResponseRedirect(self.get_success_url()) return super().form_valid(form) @@ -1141,7 +1141,7 @@ class TramitacaoCrud(MasterDetailCrud): msg = _('Tramitação atualizada, 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) + messages.add_message(self.request, messages.WARNING, msg) return HttpResponseRedirect(self.get_success_url()) return super().form_valid(form) @@ -1683,6 +1683,7 @@ class AcompanhamentoMateriaView(CreateView): do_envia_email_confirmacao(base_url, casa, + "materia", materia, destinatario) @@ -1876,9 +1877,9 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView): 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) + 'de matéria não enviado. A não configuração do servidor de e-mail ' + 'impede o envio de aviso de tramitação') + messages.add_message(self.request, messages.WARNING, msg) status = StatusTramitacao.objects.get(id=request.POST['status']) diff --git a/sapl/protocoloadm/apps.py b/sapl/protocoloadm/apps.py index 8697e58d9..98e28ea36 100644 --- a/sapl/protocoloadm/apps.py +++ b/sapl/protocoloadm/apps.py @@ -6,3 +6,6 @@ class AppConfig(apps.AppConfig): name = 'sapl.protocoloadm' label = 'protocoloadm' verbose_name = _('Protocolo Administrativo') + + def ready(self): + from sapl.base import receivers diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 9985f522f..8c441ad93 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -2,7 +2,7 @@ import django_filters from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper -from crispy_forms.layout import HTML, Button, Fieldset, Layout +from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout from django import forms from django.core.exceptions import (MultipleObjectsReturned, ObjectDoesNotExist, ValidationError) @@ -19,7 +19,8 @@ from sapl.materia.models import (MateriaLegislativa, TipoMateriaLegislativa, from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter, RangeWidgetOverride, autor_label, autor_modal) -from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, +from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, + DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) @@ -39,6 +40,28 @@ EM_TRAMITACAO = [('', '---------'), (0, 'Sim'), (1, 'Não')] +class AcompanhamentoDocumentoForm(ModelForm): + + class Meta: + model = AcompanhamentoDocumento + fields = ['email'] + + def __init__(self, *args, **kwargs): + + row1 = to_row([('email', 10)]) + + row1.append( + Column(form_actions(label='Cadastrar'), css_class='col-md-2') + ) + + self.helper = FormHelper() + self.helper.layout = Layout( + Fieldset( + _('Acompanhamento de Documento por e-mail'), row1 + ) + ) + super(AcompanhamentoDocumentoForm, self).__init__(*args, **kwargs) + class ProtocoloFilterSet(django_filters.FilterSet): diff --git a/sapl/protocoloadm/migrations/0008_acompanhamentodocumento.py b/sapl/protocoloadm/migrations/0008_acompanhamentodocumento.py new file mode 100644 index 000000000..dcc25ed45 --- /dev/null +++ b/sapl/protocoloadm/migrations/0008_acompanhamentodocumento.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-09-27 15:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0007_auto_20180924_1724'), + ] + + operations = [ + migrations.CreateModel( + name='AcompanhamentoDocumento', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('usuario', models.CharField(max_length=50)), + ('email', models.EmailField(max_length=100, verbose_name='E-mail')), + ('data_cadastro', models.DateField(auto_now_add=True)), + ('hash', models.CharField(max_length=8)), + ('confirmado', models.BooleanField(default=False)), + ('documento', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='protocoloadm.DocumentoAdministrativo')), + ], + options={ + 'verbose_name_plural': 'Acompanhamentos de Documento', + 'verbose_name': 'Acompanhamento de Documento', + }, + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 52bd9ad22..908aac542 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -298,3 +298,30 @@ class TramitacaoAdministrativo(models.Model): return _('%(documento)s - %(status)s') % { 'documento': self.documento, 'status': self.status } + +@reversion.register() +class AcompanhamentoDocumento(models.Model): + usuario = models.CharField(max_length=50) + documento = models.ForeignKey(DocumentoAdministrativo, on_delete=models.CASCADE) + email = models.EmailField( + max_length=100, verbose_name=_('E-mail')) + data_cadastro = models.DateField(auto_now_add=True) + hash = models.CharField(max_length=8) + confirmado = models.BooleanField(default=False) + + class Meta: + verbose_name = _('Acompanhamento de Documento') + verbose_name_plural = _('Acompanhamentos de Documento') + + def __str__(self): + if self.data_cadastro is None: + return _('%(documento)s - %(email)s') % { + 'documento': self.documento, + 'email': self.email + } + else: + return _('%(documento)s - %(email)s - Registrado em: %(data)s') % { + 'documento': self.documento, + 'email': self.email, + 'data': str(self.data_cadastro.strftime('%d/%m/%Y')) + } diff --git a/sapl/protocoloadm/tests/test_docadm_email_templates.py b/sapl/protocoloadm/tests/test_docadm_email_templates.py new file mode 100644 index 000000000..ec79098fa --- /dev/null +++ b/sapl/protocoloadm/tests/test_docadm_email_templates.py @@ -0,0 +1,65 @@ +from django.core import mail + +from sapl.base.email_utils import enviar_emails, load_email_templates + + +def test_email_template_loading(): + expected = "Hello Django" + emails = load_email_templates(['email/test_tramitacao.html'], + context={"name": "Django"}) + + # strip \n and \r to compare with expected + actual = emails[0].replace('\n', '').replace('\r', '') + + assert actual == expected + + +def test_html_email_body_with_materia(): + templates = load_email_templates(['email/tramitacao.txt', + 'email/tramitacao.html'], + {"image": 'img/logo.png', + "casa_legislativa": + "Assembléia Parlamentar", + "data_registro": "25/02/2016", + "cod_materia": "1", + "descricao_materia": "Assunto de teste", + "data": "25/02/2016", + "status": "Arquivado", + "texto_acao": "Deliberado", + "hash_txt": "abc01f", + "materia_id": "794", + "base_url": "http://localhost:8000", + "materia_url": + "/docadm/764/acompanhar-documento", + "excluir_url": + "/docadm/764/acompanhar-excluir"}) + + assert len(templates) == 2 + + +def test_enviar_email_distintos(): + NUM_MESSAGES = 10 + messages = [{'recipient': 'user-' + str(i) + '@test.com', + 'subject': 'subject: ' + str(i), + 'txt_message': 'txt: ' + str(i), + 'html_message': '', + } for i in range(NUM_MESSAGES)] + + recipients = [m['recipient'] for m in messages] + + enviar_emails('test@sapl.com', recipients, messages) + assert len(mail.outbox) == NUM_MESSAGES + + +def test_enviar_same_email(): + NUM_MESSAGES = 10 + messages = [{'recipient': 'user-' + str(i) + '@test.com', + 'subject': 'subject: ' + str(i), + 'txt_message': 'txt: ' + str(i), + 'html_message': '', + } for i in range(NUM_MESSAGES)] + + recipients = [m['recipient'] for m in messages] + + enviar_emails('test@sapl.com', recipients, [messages[0]]) + assert len(mail.outbox) == 1 diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index 8ed9216f2..67d5edb65 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -1,6 +1,9 @@ from django.conf.urls import include, url -from sapl.protocoloadm.views import (AnularProtocoloAdmView, +from sapl.protocoloadm.views import (AcompanhamentoDocumentoView, + AcompanhamentoConfirmarView, + AcompanhamentoExcluirView, + AnularProtocoloAdmView, ComprovanteProtocoloView, CriarDocumentoProtocolo, DocumentoAcessorioAdministrativoCrud, @@ -56,6 +59,15 @@ urlpatterns_protocolo = [ url(r'^protocoloadm/(?P\d+)/protocolo-mostrar$', ProtocoloMostrarView.as_view(), name='protocolo_mostrar'), + url(r'^docadm/(?P\d+)/acompanhar-documento/$', + AcompanhamentoDocumentoView.as_view(), name='acompanhar_documento'), + url(r'^docadm/(?P\d+)/acompanhar-confirmar$', + AcompanhamentoConfirmarView.as_view(), + name='acompanhar_confirmar'), + url(r'^docadm/(?P\d+)/acompanhar-excluir$', + AcompanhamentoExcluirView.as_view(), + name='acompanhar_excluir'), + url(r'^protocoloadm/(?P\d+)/continuar$', diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index d58b1e11b..67ea62d5d 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -1,3 +1,6 @@ +from datetime import datetime +from random import choice +from string import ascii_letters, digits from braces.views import FormValidMessageMixin from django.contrib import messages @@ -18,25 +21,30 @@ from django.views.generic.edit import FormView from django_filters.views import FilterView import sapl -from sapl.base.models import Autor +from sapl.base.models import Autor, CasaLegislativa from sapl.comissoes.models import Comissao from sapl.crud.base import Crud, CrudAux, MasterDetailCrud, make_pagination from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.parlamentares.models import Legislatura, Parlamentar from sapl.protocoloadm.models import Protocolo -from sapl.utils import (create_barcode, get_client_ip, +from sapl.utils import (create_barcode, get_base_url, get_client_ip, get_mime_type_from_file_extension, show_results_filter_set) - -from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm, +from sapl.base.email_utils import do_envia_email_confirmacao +from .forms import (AcompanhamentoDocumentoForm, AnularProcoloAdmForm, + DocumentoAcessorioAdministrativoForm, DocumentoAdministrativoFilterSet, DocumentoAdministrativoForm, ProtocoloDocumentForm, ProtocoloFilterSet, ProtocoloMateriaForm, - TramitacaoAdmEditForm, TramitacaoAdmForm, DesvincularDocumentoForm, DesvincularMateriaForm, - filtra_tramitacao_adm_destino_and_status, filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status) -from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, - StatusTramitacaoAdministrativo, + TramitacaoAdmEditForm, TramitacaoAdmForm, + DesvincularDocumentoForm, DesvincularMateriaForm, + filtra_tramitacao_adm_destino_and_status, + filtra_tramitacao_adm_destino, filtra_tramitacao_adm_status) +from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, + DocumentoAdministrativo, StatusTramitacaoAdministrativo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) +from sapl.base.signals import tramitacao_signal + TipoDocumentoAdministrativoCrud = CrudAux.build( TipoDocumentoAdministrativo, '') @@ -89,6 +97,136 @@ def doc_texto_integral(request, pk): return response raise Http404 +class AcompanhamentoConfirmarView(TemplateView): + + def get_redirect_url(self, email): + msg = _('Este documento está sendo acompanhado pelo e-mail: %s') % ( + email) + messages.add_message(self.request, messages.SUCCESS, msg) + return reverse('sapl.protocoloadm:documentoadministrativo_detail', + kwargs={'pk': self.kwargs['pk']}) + + def get(self, request, *args, **kwargs): + documento_id = kwargs['pk'] + hash_txt = request.GET.get('hash_txt', '') + + try: + acompanhar = AcompanhamentoDocumento.objects.get( + documento_id=documento_id, + hash=hash_txt) + except ObjectDoesNotExist: + raise Http404() + # except MultipleObjectsReturned: + # A melhor solução deve ser permitir que a exceção + # (MultipleObjectsReturned) seja lançada e vá para o log, + # pois só poderá ser causada por um erro de desenvolvimente + + acompanhar.confirmado = True + acompanhar.save() + + return HttpResponseRedirect(self.get_redirect_url(acompanhar.email)) + + +class AcompanhamentoExcluirView(TemplateView): + + def get_success_url(self): + msg = _('Você parou de acompanhar este Documento.') + messages.add_message(self.request, messages.INFO, msg) + return reverse('sapl.protocoloadm:documentoadministrativo_detail', + kwargs={'pk': self.kwargs['pk']}) + + def get(self, request, *args, **kwargs): + materia_id = kwargs['pk'] + hash_txt = request.GET.get('hash_txt', '') + + try: + AcompanhamentoDocumento.objects.get(documento_id=documento_id, + hash=hash_txt).delete() + except ObjectDoesNotExist: + pass + + return HttpResponseRedirect(self.get_success_url()) + + +class AcompanhamentoDocumentoView(CreateView): + template_name = "protocoloadm/acompanhamento_documento.html" + + def get_random_chars(self): + s = ascii_letters + digits + return ''.join(choice(s) for i in range(choice([6, 7]))) + + def get(self, request, *args, **kwargs): + pk = self.kwargs['pk'] + documento = DocumentoAdministrativo.objects.get(id=pk) + + return self.render_to_response( + {'form': AcompanhamentoDocumentoForm(), + 'documento': documento}) + + def post(self, request, *args, **kwargs): + form = AcompanhamentoDocumentoForm(request.POST) + pk = self.kwargs['pk'] + documento = DocumentoAdministrativo.objects.get(id=pk) + + if form.is_valid(): + email = form.cleaned_data['email'] + usuario = request.user + + hash_txt = self.get_random_chars() + + acompanhar = AcompanhamentoDocumento.objects.get_or_create( + documento=documento, + email=form.data['email']) + + # Se o segundo elemento do retorno do get_or_create for True + # quer dizer que o elemento não existia + if acompanhar[1]: + acompanhar = acompanhar[0] + acompanhar.hash = hash_txt + acompanhar.usuario = usuario.username + acompanhar.confirmado = False + acompanhar.save() + + base_url = get_base_url(request) + + destinatario = AcompanhamentoDocumento.objects.get( + documento=documento, + email=email, + confirmado=False) + casa = CasaLegislativa.objects.first() + + do_envia_email_confirmacao(base_url, + casa, + "documento", + documento, + destinatario) + + msg = _('Foi enviado um e-mail de confirmação. Confira sua caixa \ + de mensagens e clique no link que nós enviamos para \ + confirmar o acompanhamento deste documento.') + messages.add_message(request, messages.SUCCESS, msg) + + # Caso esse Acompanhamento já exista + # avisa ao usuário que esse documento já está sendo acompanhado + else: + msg = _('Este e-mail já está acompanhando esse documento.') + messages.add_message(request, messages.INFO, msg) + + return self.render_to_response( + {'form': form, + 'documento': documento, + 'error': _('Esse documento já está\ + sendo acompanhada por este e-mail.')}) + return HttpResponseRedirect(self.get_success_url()) + else: + return self.render_to_response( + {'form': form, + 'documento': documento}) + + def get_success_url(self): + return reverse('sapl.protocoloadm:documentoadministrativo_detail', + kwargs={'pk': self.kwargs['pk']}) + class DocumentoAdministrativoMixin: @@ -686,8 +824,38 @@ class TramitacaoAdmCrud(MasterDetailCrud): 'unidade_tramitacao_local'].widget.attrs['disabled'] = True return context + def form_valid(self, form): + self.object = form.save() + + try: + tramitacao_signal.send(sender=TramitacaoAdministrativo, + post=self.object, + request=self.request) + except Exception as e: + # TODO log error + msg = _('Tramitação criada, mas e-mail de acompanhamento ' + 'de documento não enviado. A não configuração do' + ' servidor de e-mail impede o envio de aviso de tramitação') + messages.add_message(self.request, messages.WARNING, msg) + return HttpResponseRedirect(self.get_success_url()) + return super().form_valid(form) + class UpdateView(MasterDetailCrud.UpdateView): form_class = TramitacaoAdmEditForm + def form_valid(self, form): + self.object = form.save() + try: + tramitacao_signal.send(sender=TramitacaoAdministrativo, + post=self.object, + request=self.request) + except Exception as e: + # TODO log error + msg = _('Tramitação criada, mas e-mail de acompanhamento ' + 'de documento não enviado. A não configuração do' + ' servidor de e-mail impede o envio de aviso de tramitação') + messages.add_message(self.request, messages.WARNING, msg) + return HttpResponseRedirect(self.get_success_url()) + return super().form_valid(form) class ListView(DocumentoAdministrativoMixin, MasterDetailCrud.ListView): diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 47a43d9e1..1a2d1fe8b 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -302,6 +302,7 @@ rules_group_anonymous = { 'group': SAPL_GROUP_ANONYMOUS, 'rules': [ (materia.AcompanhamentoMateria, [RP_ADD, RP_DELETE]), + (protocoloadm.AcompanhamentoDocumento, [RP_ADD, RP_DELETE]), ] } diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index 07302bae5..e1ed7f7e4 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -11,6 +11,7 @@ from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, TipoDispositivo, TipoDispositivoRelationship) from sapl.materia.models import AcompanhamentoMateria +from sapl.protocoloadm.models import AcompanhamentoDocumento from sapl.rules import SAPL_GROUPS, map_rules from sapl.test_urls import create_perms_post_migrate from scripts.lista_permissions_in_decorators import \ @@ -61,6 +62,7 @@ __fp__in__test_permission_of_models_in_rules_patterns = { PerfilEstruturalTextoArticulado], map_rules.RP_CHANGE: [AcompanhamentoMateria, + AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], @@ -71,11 +73,13 @@ __fp__in__test_permission_of_models_in_rules_patterns = { PerfilEstruturalTextoArticulado], map_rules.RP_LIST: [AcompanhamentoMateria, + AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], map_rules.RP_DETAIL: [AcompanhamentoMateria, + AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado] diff --git a/sapl/templates/email/acompanhar_documento.html b/sapl/templates/email/acompanhar_documento.html new file mode 100644 index 000000000..f90558568 --- /dev/null +++ b/sapl/templates/email/acompanhar_documento.html @@ -0,0 +1,25 @@ +{% load i18n %} +{% load static %} + + +

    {{casa_legislativa}} +
    + Sistema de Apoio ao Processo Legislativo +

    + +

    Registramos seu pedido para acompanhamento por e-mail do documento administrativo identificado a seguir:

    +{{documento}} - {{descricao_documento}}
    +{{assunto}}
    + +

    +

    Para garantia de sua privacidade, solicitamos que ative o recebimento das futuras mensagens clicando no link:

    + +

    + {{base_url}}{{confirmacao_url}}?hash_txt={{hash_txt}} +

    +
    +
    +

    Caso não tenha realizado o cadastramento em nosso sistema, favor desconsiderar a presente mensagem
    +Esta é uma mensagem automática. Por favor, não responda.

    + + diff --git a/sapl/templates/email/acompanhar_documento.txt b/sapl/templates/email/acompanhar_documento.txt new file mode 100644 index 000000000..eab05d7d1 --- /dev/null +++ b/sapl/templates/email/acompanhar_documento.txt @@ -0,0 +1,16 @@ +{{casa_legislativa}} + +Sistema de Apoio ao Processo Legislativo + +>Registramos seu pedido para acompanhamento por e-mail do documento administrativo identificado a seguir: + +{{base_url}}{{documento_url}} - {{documento}} - {{descricao_documento}} + +{{assunto}} + +Para garantia de sua privacidade, solicitamos que ative o recebimento das futuras mensagens acessando no link: + +{{base_url}}{{url_confirmar}}?hash_txt={{hash_txt}} + +Caso não tenha realizado o cadastramento em nosso sistema, favor desconsiderar a presente mensagem +Esta é uma mensagem automática. Por favor, não responda. diff --git a/sapl/templates/email/tramitacao.html b/sapl/templates/email/tramitacao.html index 4b30a1dc5..362fc563a 100644 --- a/sapl/templates/email/tramitacao.html +++ b/sapl/templates/email/tramitacao.html @@ -13,10 +13,12 @@

    {{materia}} - {{descricao_materia}}

    +{% if autoria %} Autoria:
    {% for autor in autoria %} {{ autor }}
    {% endfor %} +{% endif %}

    diff --git a/sapl/templates/email/tramitacao.txt b/sapl/templates/email/tramitacao.txt index f0a06687a..bb68a87a0 100644 --- a/sapl/templates/email/tramitacao.txt +++ b/sapl/templates/email/tramitacao.txt @@ -8,12 +8,12 @@ A seguinte matéria, de seu interesse, sofreu Tramitação registrada em {{data_ Matéria: {{materia}} - {{descricao_materia}} {{url_materia}} - +{% if autoria %} Autoria: {% for autor in autoria %} {{ autor }} {% endfor %} - +{% endif %} Data da ação: {{data}} Status: {{status}} diff --git a/sapl/templates/protocoloadm/acompanhamento_documento.html b/sapl/templates/protocoloadm/acompanhamento_documento.html new file mode 100644 index 000000000..b6526cc52 --- /dev/null +++ b/sapl/templates/protocoloadm/acompanhamento_documento.html @@ -0,0 +1,21 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% block actions %} {% endblock %} +{% block detail_content %} + +

    Acompanhamento de Documento

    +
    +
    +
    Tipo: {{documento.tipo.sigla}} - {{documento.tipo.descricao}}
    +
    Número: {{documento.numero}}
    +
    Ano: {{documento.ano}}
    + +
    +
    +
    Assunto: {{documento.assunto|safe}}
    +
    + +{% if error %}
    {{ error }}
    {% endif %} +{% crispy form %} +{% endblock %} diff --git a/sapl/templates/protocoloadm/documentoadministrativo_filter.html b/sapl/templates/protocoloadm/documentoadministrativo_filter.html index e87962273..6dbd95276 100644 --- a/sapl/templates/protocoloadm/documentoadministrativo_filter.html +++ b/sapl/templates/protocoloadm/documentoadministrativo_filter.html @@ -63,6 +63,9 @@ {% if d.texto_integral %} Texto Integral
    {% endif %} + {% if d.tramitacao %} + Acompanhar Documento + {% endif %} From e7c8491499cbc00780d9489ef9fdb9933b309168 Mon Sep 17 00:00:00 2001 From: Edward Date: Tue, 9 Oct 2018 17:54:49 -0300 Subject: [PATCH 71/88] HOT-FIX: conserta estouro de campo em protocolo (#2291) --- sapl/materia/forms.py | 3 +-- .../migrations/0008_auto_20181009_1741.py | 20 +++++++++++++++++++ sapl/protocoloadm/models.py | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 sapl/protocoloadm/migrations/0008_auto_20181009_1741.py diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 6f6a544cd..b244af69a 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1855,14 +1855,13 @@ class ConfirmarProposicaoForm(ProposicaoForm): else: # numeracao == 'U' ou não informada nm = Protocolo.objects.all().aggregate(Max('numero')) - protocolo = Protocolo() protocolo.numero = (nm['numero__max'] + 1) if nm['numero__max'] else 1 protocolo.ano = timezone.now().year protocolo.tipo_protocolo = '1' - protocolo.interessado = str(proposicao.autor) + protocolo.interessado = str(proposicao.autor)[:200] # tamanho máximo 200 protocolo.autor = proposicao.autor protocolo.assunto_ementa = proposicao.descricao protocolo.numero_paginas = cd['numero_de_paginas'] diff --git a/sapl/protocoloadm/migrations/0008_auto_20181009_1741.py b/sapl/protocoloadm/migrations/0008_auto_20181009_1741.py new file mode 100644 index 000000000..0ea354a29 --- /dev/null +++ b/sapl/protocoloadm/migrations/0008_auto_20181009_1741.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-10-09 20:41 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0007_auto_20180924_1724'), + ] + + operations = [ + migrations.AlterField( + model_name='protocolo', + name='interessado', + field=models.CharField(blank=True, max_length=200, verbose_name='Interessado'), + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 908aac542..aa4e7c0c2 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -67,7 +67,7 @@ class Protocolo(models.Model): blank=True, null=True, verbose_name=_('Tipo de Protocolo')) tipo_processo = models.PositiveIntegerField() interessado = models.CharField( - max_length=60, blank=True, verbose_name=_('Interessado')) + max_length=200, blank=True, verbose_name=_('Interessado')) autor = models.ForeignKey(Autor, blank=True, null=True, From ade8dd037dae91a43a213ab43b3606934b408d46 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 9 Oct 2018 17:55:30 -0300 Subject: [PATCH 72/88] Release: 3.1.123 --- docker-compose.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1bfcf65f5..f14200c76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.122 + image: interlegis/sapl:3.1.123 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/setup.py b/setup.py index fac072615..1fb1a39e9 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.122', + version='3.1.123', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From be9d2964960bb1fe24f4a21b956bdcb1da6b8e4c Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 9 Oct 2018 17:58:18 -0300 Subject: [PATCH 73/88] Bump release version on base template --- sapl/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 1953032a3..7cbf02352 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -184,7 +184,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - Release: 3.1.121 + Release: 3.1.123

    From 6c1404a1c3180b04bcbfbcb739b042f132055de7 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Wed, 10 Oct 2018 08:11:58 -0300 Subject: [PATCH 74/88] HOT-FIX: error travis --- sapl/protocoloadm/migrations/0009_merge.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 sapl/protocoloadm/migrations/0009_merge.py diff --git a/sapl/protocoloadm/migrations/0009_merge.py b/sapl/protocoloadm/migrations/0009_merge.py new file mode 100644 index 000000000..b59fca714 --- /dev/null +++ b/sapl/protocoloadm/migrations/0009_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-10-10 11:10 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0008_acompanhamentodocumento'), + ('protocoloadm', '0008_auto_20181009_1741'), + ] + + operations = [ + ] From feb2eb9397f847df7a6883b7ecd0e1079f4629fc Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Wed, 10 Oct 2018 09:20:44 -0300 Subject: [PATCH 75/88] Bump release version on base template --- sapl/templates/base.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 7cbf02352..c7cfd8b69 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -29,7 +29,7 @@
    - + {% if not request|has_iframe %} {% block navigation %}
    @@ -252,7 +252,7 @@ From 16cc7fd289093dff86a89cfff517ee50d89ba522 Mon Sep 17 00:00:00 2001 From: Victor Fabre Date: Wed, 10 Oct 2018 09:22:18 -0300 Subject: [PATCH 76/88] Release: 3.1.124 --- docker-compose.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f14200c76..b9d6d10ed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.123 + image: interlegis/sapl:3.1.124 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/setup.py b/setup.py index 1fb1a39e9..0b7838be2 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.123', + version='3.1.124', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', From 660810b7a4ca5a87e95fd3b32a29b9eeb06490e7 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Wed, 10 Oct 2018 18:45:44 -0300 Subject: [PATCH 77/88] =?UTF-8?q?Adiciona=20url=20p=20tipo=20de=20situa?= =?UTF-8?q?=C3=A7=C3=A3o=20militar=20ao=20ressuscitar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/scripts/ressuscita_dependencias.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sapl/legacy/scripts/ressuscita_dependencias.py b/sapl/legacy/scripts/ressuscita_dependencias.py index 19cb875d8..32b7986d7 100644 --- a/sapl/legacy/scripts/ressuscita_dependencias.py +++ b/sapl/legacy/scripts/ressuscita_dependencias.py @@ -1,16 +1,16 @@ from collections import OrderedDict from textwrap import dedent +import texttable import yaml +from unipath import Path -import texttable from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO, campos_novos_para_antigos, exec_legado, get_arquivo_ajustes_pre_migracao, models_novos_para_antigos) from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO, NOME_BANCO_LEGADO) -from unipath import Path def stripsplit(ll): @@ -70,6 +70,7 @@ tipo_dependente /sistema/parlamentar/tipo-dependente origem /sistema/materia/origem documento_acessorio /materia/documentoacessorio tipo_fim_relatoria /sistema/materia/tipo-fim-relatoria +tipo_situacao_militar /sistema/parlamentar/tipo-militar ''' urls = dict(stripsplit(urls)) From 6a6f98dbb44c87271dc3778c1fe88bda1c225e86 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Wed, 10 Oct 2018 18:46:08 -0300 Subject: [PATCH 78/88] =?UTF-8?q?Melhora=20feedback=20ao=20fazer=20scrapin?= =?UTF-8?q?g=20de=20proposi=C3=A7=C3=A3o=20sde?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/legacy/migracao.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sapl/legacy/migracao.py b/sapl/legacy/migracao.py index c4c183b84..94fd25930 100644 --- a/sapl/legacy/migracao.py +++ b/sapl/legacy/migracao.py @@ -70,12 +70,13 @@ def scrap_sde(url, usuario, senha=None): {'__ac_name': usuario, '__ac_password': senha}) assert res.status_code == 200 - url_proposicao = '{}/sapl_documentos/proposicao/{}/renderXML?xsl=__default__' # noqa + url_proposicao_tmpl = '{}/sapl_documentos/proposicao/{}/renderXML?xsl=__default__' # noqa total = Proposicao.objects.count() for num, proposicao in enumerate(Proposicao.objects.all()): pk = proposicao.pk - res = session.get(url_proposicao.format(url, pk)) - print("pk: {} status: {} (progresso: {:.2%})".format( - pk, res.status_code, num / total)) + url_proposicao = url_proposicao_tmpl.format(url, pk) + res = session.get(url_proposicao) + print("pk: {} status: {} {} (progresso: {:.2%})".format( + pk, res.status_code, url_proposicao, num / total)) if res.status_code == 200: salva_conteudo_do_sde(proposicao, res.content) From 9ade9c230201fd009dff6822f8b97a9093b76f48 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Wed, 10 Oct 2018 19:23:45 -0300 Subject: [PATCH 79/88] Adiciona insert a ressuscitar --- sapl/legacy/scripts/ressuscita_dependencias.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sapl/legacy/scripts/ressuscita_dependencias.py b/sapl/legacy/scripts/ressuscita_dependencias.py index 32b7986d7..5e12efc01 100644 --- a/sapl/legacy/scripts/ressuscita_dependencias.py +++ b/sapl/legacy/scripts/ressuscita_dependencias.py @@ -308,6 +308,9 @@ SQLS_CRIACAO = [ insert into parlamentar (cod_parlamentar, nom_completo, nom_parlamentar, sex_parlamentar, cod_casa, ind_ativo, ind_unid_deliberativa, ind_excluido) values ({}, "DESCONHECIDO", "DESCONHECIDO", "M", 0, 0, 0, 0); '''), + ('tipo_sessao_plenaria', ''' + insert into tipo_sessao_plenaria (tip_sessao, nom_sessao, ind_excluido, num_minimo) values ({}, "DESCONHECIDO", 0, 0); + '''), ] SQLS_CRIACAO = {k: (dedent(sql.strip()), extras) for k, sql, *extras in SQLS_CRIACAO} From beddd718cdf78894e2de12d6158c5e575c909ce7 Mon Sep 17 00:00:00 2001 From: Edward Date: Thu, 11 Oct 2018 13:29:21 -0300 Subject: [PATCH 80/88] Bump Postgres version --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b9d6d10ed..dc3c58dfd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ sapldb: - image: postgres:9.6.8-alpine + image: postgres:10.5-alpine restart: always environment: POSTGRES_PASSWORD: sapl From adc4246994b784b9b4367b0443aca0613ef20551 Mon Sep 17 00:00:00 2001 From: Talitha Pumar Date: Mon, 15 Oct 2018 09:20:38 -0300 Subject: [PATCH 81/88] Paginas personalizadas de erro (Melhorar a mensagem) (#2294) * paginas personalizadas de erro * Update 500.html --- sapl/templates/404.html | 171 ++++++++++++++++++++++++++++++++++++++++ sapl/templates/500.html | 135 +++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 sapl/templates/404.html create mode 100644 sapl/templates/500.html diff --git a/sapl/templates/404.html b/sapl/templates/404.html new file mode 100644 index 000000000..484a2a8f2 --- /dev/null +++ b/sapl/templates/404.html @@ -0,0 +1,171 @@ +{% load i18n staticfiles sass_tags menus %} +{% load common_tags %} + + + + + + + + + {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %} + + {% block head_content %} + + + {# Styles #} + + + + + + + + + {# Scripts #} + {# modernizr must be in head (see http://modernizr.com/docs/#installing) #} + {% endblock %} + + + +
    + + {% if not request|has_iframe %} + {% block navigation %} + + {% endblock navigation %} + + {# Header #} + {% block main_header %} +
    + +
    + {% endblock main_header %} + {% else %} +
    + +
    +
    +
    +
    + {% subnav %} +
    +
    +
    + {% endif %} +
    + +

    {% trans 'Página não encontrada! Erro 404' %}

    +
    +
    + {% block base_content %} + {% endblock %} + {% if not request|has_iframe %} + {% block footer_container %} + +
    + {% endblock footer_container %} + {% endif %} + + {% block foot_js %} + + + + + + + + + + + + + + + + + + + + + {% block extra_js %}{% endblock %} + + + + {% endblock foot_js %} + + diff --git a/sapl/templates/500.html b/sapl/templates/500.html new file mode 100644 index 000000000..ab1afae4f --- /dev/null +++ b/sapl/templates/500.html @@ -0,0 +1,135 @@ +{% load i18n staticfiles sass_tags menus %} +{% load common_tags %} + + + + + + + + + {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %} + + {% block head_content %} + + + {# Styles #} + + + + + + + + + {# Scripts #} + {# modernizr must be in head (see http://modernizr.com/docs/#installing) #} + {% endblock %} + + + +
    + + {% block navigation %} + + {% endblock navigation %} + + {# Header #} + {% block main_header %} +
    +
    + +
    + {% block sections_nav %} {% subnav %} {% endblock sections_nav %} +
    +
    +
    + {% endblock main_header %} + +
    + +

    {% trans 'Ocorreu um erro inesperado! Erro 500' %}

    +
    +
    + {% block base_content %} + {% endblock %} + {% block footer_container %} + +
    + {% endblock footer_container %} + + {% block foot_js %} + + + + + + + + + + + + + + + + + + + + + {% block extra_js %}{% endblock %} + + {% endblock foot_js %} + + From 3258080531a9172f200f119459b45608c1bb77af Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 15 Oct 2018 13:46:20 -0300 Subject: [PATCH 82/88] Fixes #2133 (#2299) --- sapl/base/templatetags/common_tags.py | 13 +++++++++++++ sapl/templates/base.html | 2 +- sapl/templates/crud/detail.html | 16 +++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 71f63e130..440f747a4 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -198,6 +198,19 @@ def url(value): return True return False +@register.filter +def audio_url(value): + return True if url(value) and value.endswith("mp3") else False + + +@register.filter +def video_url(value): + return True if url(value) and value.endswith("mp4") else False + +@register.filter +def file_extension(value): + import pathlib + return pathlib.Path(value).suffix.replace('.', '') @register.filter def cronometro_to_seconds(value): diff --git a/sapl/templates/base.html b/sapl/templates/base.html index c7cfd8b69..b93260845 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -1,6 +1,6 @@ + {% load i18n staticfiles sass_tags menus %} {% load common_tags %} - diff --git a/sapl/templates/crud/detail.html b/sapl/templates/crud/detail.html index 4a1cad276..c1b2c6445 100644 --- a/sapl/templates/crud/detail.html +++ b/sapl/templates/crud/detail.html @@ -65,7 +65,21 @@

    {{ column.verbose_name }}

    - {% if column.text|url %} + {% if column.text|audio_url %} +
    + +
    + {% elif column.text|video_url %} +
    + +
    + {% elif column.text|url %} {% else %}
    {{ column.text|safe|default:"" }}
    From 81531b7c44ab50dc07768aa245e73afb025a0afb Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 15 Oct 2018 15:55:12 -0300 Subject: [PATCH 83/88] Fixes #2300 (#2301) --- .../relatorios/templates/pdf_pauta_sessao_gerar.py | 14 ++++++++++---- sapl/relatorios/views.py | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py index 31636401e..15a4147d6 100755 --- a/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py +++ b/sapl/relatorios/templates/pdf_pauta_sessao_gerar.py @@ -122,8 +122,10 @@ def expediente_materia(lst_expediente_materia): tmp += '\n' tmp += '
    \n' for expediente_materia in lst_expediente_materia: - tmp += '\n' + tmp += '\n' txt_ementa = expediente_materia['txt_ementa'].replace('&', '&') tmp += '\n' tmp += '\n' for votacao in lst_votacao: - tmp += '\n' + tmp += '\n' tmp += '\n' tmp += '