From 84b56a37eccf42860916a30850e501baa8ab641e Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Thu, 4 Apr 2019 15:39:29 -0300 Subject: [PATCH 01/18] HOT-FIX: fixes #2686 --- sapl/materia/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 73dcb3072..e30b756fb 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1987,7 +1987,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView): file_path = os.path.join(diretorio, request.FILES['arquivo'].name) shutil.copy2(tmp_name, file_path) - doc.arquivo.name = file_path.split(MEDIA_ROOT)[1] # Retira MEDIA_ROOT do nome + doc.arquivo.name = file_path.split(MEDIA_ROOT + "/")[1] # Retira MEDIA_ROOT do nome doc.save() os.remove(tmp_name) From 008954d9799b9ab1cf94fef66bf3966f6d0fd58e Mon Sep 17 00:00:00 2001 From: Edward Date: Sun, 7 Apr 2019 10:06:51 -0300 Subject: [PATCH 02/18] fixes #2689 (#2690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixes #2689 * Trata inexistencia de chaves * Adiciona verificação de data --- sapl/materia/forms.py | 15 ++++++++++++++- sapl/materia/views.py | 22 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 673dfd024..d6935b697 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -402,7 +402,16 @@ class RelatoriaForm(ModelForm): self.fields['composicao'].choices = [('', '---------')] + \ [(c.pk, c) for c in composicoes] - self.fields['parlamentar'].choices = [('', '---------')] + # UPDATE + if self.initial.get('composicao') and self.initial.get('parlamentar'): + parlamentares = [(p.parlamentar.id, p.parlamentar) for p in + Participacao.objects.filter(composicao__comissao_id=comissao_pk, + composicao_id=self.initial['composicao'])] + + self.fields['parlamentar'].choices = [('', '---------')] + parlamentares + # INSERT + else: + self.fields['parlamentar'].choices = [('', '---------')] def clean(self): super().clean() @@ -424,6 +433,10 @@ class RelatoriaForm(ModelForm): else: cleaned_data['comissao'] = comissao + if cleaned_data['data_designacao_relator'] < cleaned_data['composicao'].periodo.data_inicio \ + or cleaned_data['data_designacao_relator'] > cleaned_data['composicao'].periodo.data_fim: + raise ValidationError(_('Data de designação deve estar dentro do período da composição.')) + return cleaned_data diff --git a/sapl/materia/views.py b/sapl/materia/views.py index e30b756fb..6c0da0ce0 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -33,7 +33,7 @@ import sapl from sapl.base.email_utils import do_envia_email_confirmacao from sapl.base.models import Autor, CasaLegislativa, AppConfig as BaseAppConfig from sapl.base.signals import tramitacao_signal -from sapl.comissoes.models import Comissao, Participacao +from sapl.comissoes.models import Comissao, Participacao, Composicao from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT, STATUS_TA_PRIVATE) from sapl.compilacao.views import IntegracaoTaView @@ -1135,6 +1135,26 @@ class RelatoriaCrud(MasterDetailCrud): layout_key = None logger = logging.getLogger(__name__) + def get_initial(self): + relatoria = Relatoria.objects.get(id=self.kwargs['pk']) + parlamentar = relatoria.parlamentar + comissao = relatoria.comissao + composicoes = [p.composicao for p in + Participacao.objects.filter( + parlamentar=parlamentar, + composicao__comissao=comissao)] + data_designacao = relatoria.data_designacao_relator + composicao = '' + for c in composicoes: + data_inicial = c.periodo.data_inicio + data_fim = c.periodo.data_fim if c.periodo.data_fim else timezone.now().date() + if data_inicial <= data_designacao <= data_fim: + composicao = c.id + break + return {'comissao': relatoria.comissao.id, + 'parlamentar': relatoria.parlamentar.id, + 'composicao': composicao} + class TramitacaoCrud(MasterDetailCrud): model = Tramitacao From 988f2bab9e02e230ba1d9b0a4bbaa46545492abf Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Sun, 7 Apr 2019 23:31:47 -0300 Subject: [PATCH 03/18] =?UTF-8?q?add=20a=C3=A7=C3=A3o=20para=20recuperar?= =?UTF-8?q?=20mat=20anexadas=20de=20uma=20mat=C3=A9ria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/api/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sapl/api/views.py b/sapl/api/views.py index 1cfdd1d44..2eedb9464 100644 --- a/sapl/api/views.py +++ b/sapl/api/views.py @@ -401,6 +401,11 @@ class _MateriaLegislativaViewSet: return Response(serializer_class.data) + @action(detail=True, methods=['GET']) + def anexadas(self, request, *args, **kwargs): + self.queryset = self.get_object().anexadas.all() + return self.list(request, *args, **kwargs) + @customize(TipoMateriaLegislativa) class _TipoMateriaLegislativaViewSet: From 6c940d96820e7b647ef31ecc128c9e372e01cc7b Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 8 Apr 2019 09:27:52 -0300 Subject: [PATCH 04/18] update auto pep --- sapl/materia/forms.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index d6935b697..c91f8c90e 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -3,7 +3,6 @@ import logging import os from crispy_forms.bootstrap import Alert, InlineRadios -from sapl.crispy_layout_mixin import SaplFormHelper from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset, Layout, Row) from django import forms @@ -31,6 +30,7 @@ from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_PUBLIC, STATUS_TA_PRIVATE) from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, to_row) +from sapl.crispy_layout_mixin import SaplFormHelper from sapl.materia.models import (AssuntoMateria, Autoria, MateriaAssunto, MateriaLegislativa, Orgao, RegimeTramitacao, TipoDocumento, TipoProposicao, StatusTramitacao, @@ -408,7 +408,8 @@ class RelatoriaForm(ModelForm): Participacao.objects.filter(composicao__comissao_id=comissao_pk, composicao_id=self.initial['composicao'])] - self.fields['parlamentar'].choices = [('', '---------')] + parlamentares + self.fields['parlamentar'].choices = [ + ('', '---------')] + parlamentares # INSERT else: self.fields['parlamentar'].choices = [('', '---------')] @@ -435,7 +436,8 @@ class RelatoriaForm(ModelForm): if cleaned_data['data_designacao_relator'] < cleaned_data['composicao'].periodo.data_inicio \ or cleaned_data['data_designacao_relator'] > cleaned_data['composicao'].periodo.data_fim: - raise ValidationError(_('Data de designação deve estar dentro do período da composição.')) + raise ValidationError( + _('Data de designação deve estar dentro do período da composição.')) return cleaned_data @@ -465,9 +467,12 @@ class TramitacaoForm(ModelForm): super(TramitacaoForm, self).__init__(*args, **kwargs) self.fields['data_tramitacao'].initial = timezone.now().date() ust = UnidadeTramitacao.objects.select_related().all() - unidade_tramitacao_destino = [('', '---------')]+[(ut.pk, ut) for ut in ust if ut.comissao and ut.comissao.ativa] - unidade_tramitacao_destino.extend([(ut.pk, ut) for ut in ust if ut.orgao]) - unidade_tramitacao_destino.extend([(ut.pk, ut) for ut in ust if ut.parlamentar]) + unidade_tramitacao_destino = [('', '---------')] + [(ut.pk, ut) + for ut in ust if ut.comissao and ut.comissao.ativa] + unidade_tramitacao_destino.extend( + [(ut.pk, ut) for ut in ust if ut.orgao]) + unidade_tramitacao_destino.extend( + [(ut.pk, ut) for ut in ust if ut.parlamentar]) self.fields['unidade_tramitacao_destino'].choices = unidade_tramitacao_destino def clean(self): @@ -1182,6 +1187,7 @@ class AcessorioEmLoteFilterSet(django_filters.FilterSet): Fieldset(_('Documentos Acessórios em Lote'), row1, row2, form_actions(label='Pesquisar'))) + class AnexadaEmLoteFilterSet(django_filters.FilterSet): class Meta(FilterOverridesMetaMixin): @@ -1583,8 +1589,8 @@ class ProposicaoForm(FileFieldCheckMixin, forms.ModelForm): if cd['numero_materia_futuro'] and \ 'tipo' in cd and \ MateriaLegislativa.objects.filter(tipo=cd['tipo'].tipo_conteudo_related, - ano=timezone.now().year, - numero=cd['numero_materia_futuro']): + ano=timezone.now().year, + numero=cd['numero_materia_futuro']): raise ValidationError(_("A matéria {} {}/{} já existe.".format(cd['tipo'].tipo_conteudo_related.descricao, cd['numero_materia_futuro'], timezone.now().year))) @@ -2003,14 +2009,13 @@ class ConfirmarProposicaoForm(ProposicaoForm): if numeracao is None: numero['numero__max'] = 0 - if cd['numero_materia_futuro'] and not MateriaLegislativa.objects.filter(tipo=tipo, ano=ano, numero=cd['numero_materia_futuro']): max_numero = cd['numero_materia_futuro'] else: - max_numero = numero['numero__max'] + 1 if numero['numero__max'] else 1 - + max_numero = numero['numero__max'] + \ + 1 if numero['numero__max'] else 1 # dados básicos materia = MateriaLegislativa() @@ -2501,7 +2506,9 @@ class MateriaPesquisaSimplesForm(forms.Form): raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e ' 'Data Final devem ser preenchidos obrigatoriamente')) elif data_inicial > data_final: - self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial)) - raise ValidationError(_('A Data Final não pode ser menor que a Data Inicial')) + self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format( + data_final, data_inicial)) + raise ValidationError( + _('A Data Final não pode ser menor que a Data Inicial')) return cleaned_data From a5a5ba5ae6abcf99e2174fcb7eb4e9373453426a Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 8 Apr 2019 09:30:08 -0300 Subject: [PATCH 05/18] =?UTF-8?q?permite=20edi=C3=A7=C3=A3o=20de=20materia?= =?UTF-8?q?s=20anexadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/materia/forms.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index c91f8c90e..edbeed810 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -809,9 +809,11 @@ class AnexadaForm(ModelForm): self.logger.error("Matéria não pode ser anexada a si mesma.") raise ValidationError(_('Matéria não pode ser anexada a si mesma')) - is_anexada = Anexada.objects.filter(materia_principal=materia_principal, - materia_anexada=materia_anexada - ).exists() + is_anexada = Anexada.objects.filter( + materia_principal=materia_principal, + materia_anexada=materia_anexada + ).exclude(pk=self.instance.pk).exists() + if is_anexada: self.logger.error("Matéria já se encontra anexada.") raise ValidationError(_('Matéria já se encontra anexada')) From 9a89c863dd811c877311dc19f40bddbddb7c9919 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Mon, 8 Apr 2019 11:43:00 -0300 Subject: [PATCH 06/18] =?UTF-8?q?Adiciona=20bot=C3=A3o=20Adicionar=20Parla?= =?UTF-8?q?mentar=20em=20Tabelas=20Auxiliares=20(#2697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/templates/menu_tabelas_auxiliares.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sapl/templates/menu_tabelas_auxiliares.yaml b/sapl/templates/menu_tabelas_auxiliares.yaml index ced7bddf3..4f690ca00 100644 --- a/sapl/templates/menu_tabelas_auxiliares.yaml +++ b/sapl/templates/menu_tabelas_auxiliares.yaml @@ -20,6 +20,9 @@ - title: {% trans 'Pesquisar Parlamentar' %} url: sapl.parlamentares:pesquisar_parlamentar css_class: btn btn-link + - title: {% trans 'Adicionar Parlamentar' %} + url: sapl.parlamentares:parlamentar_create + css_class: btn btn-link - title: {% trans 'Legislatura' %} url: sapl.parlamentares:legislatura_list css_class: btn btn-link From 6906c620c22f48575fa5e5b438965eab3200c5ca Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 8 Apr 2019 12:54:44 -0300 Subject: [PATCH 07/18] =?UTF-8?q?Atualiza=20vers=C3=A3o=20do=20SAPL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solr/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/docker-compose.yml b/solr/docker-compose.yml index 6349c8053..71e25c76c 100644 --- a/solr/docker-compose.yml +++ b/solr/docker-compose.yml @@ -24,7 +24,7 @@ services: - "8983:8983" sapl: - image: interlegis/sapl:3.1.144 + image: interlegis/sapl:3.1.152 # build: . restart: always environment: From 7038d6f4e6f45adf8ee504cfe9f6a1b02ee1389d Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 8 Apr 2019 12:55:42 -0300 Subject: [PATCH 08/18] Fix #2656 (#2698) --- docs/solr.rst | 59 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/docs/solr.rst b/docs/solr.rst index 4c82ab68d..d5da6d889 100644 --- a/docs/solr.rst +++ b/docs/solr.rst @@ -1,27 +1,58 @@ -**ESTAS INSTRUÇÕES ESTÃO DEFASADAS. EM BREVE IREMOS DISPONIBILIZAR UM TUTORIAL MAIS ATUALIZADO DE COMO INTEGRAR O SOLR AO SAPL** - ================================ Instruções para instalar o Solr ================================ Solr é a ferramenta utilizada pelo SAPL 3.1 para indexar documentos para que possa ser feita -a Pesquisa Textual. +a Pesquisa Textual. Se a execução for mediante containers Docker então use o arquivo docker-compose.yml disponível em +*https://github.com/interlegis/sapl/blob/3.1.x/solr/docker-compose.yml* (verifique os mapeamentos de volume, e realize o +backup de seu BD antes de qualquer tentativa de substituição do arquivo docker-compose.yml em uso corrente). + +1) Faça o download da distribuição _binária_ do Apache Solr do site oficial do projeto *http://lucene.apache.org/solr* ; + +As instalações Solr suportadas até o momento vão da 7.4 à 8; + +2) Descompacte o arquivo em uma pasta do diretório (referenciada neste tutorial como $SOLR_HOME) + +3) Inicie o Solr com o comando: + + **$SOLR_HOME/bin/solr start -c** ; + +4) Por meio do browser, acesse a URL **http://localhost:8983** (ou informe o endereço da máquina onde o Solr foi instalado) + +5) Pare o servidor do SAPL; + +6) Edite o arquivo .env adicionando as seguintes linhas: + + + + USE_SOLR = True + + + SOLR_COLLECTION = sapl + + + SOLR_URL = http://localhost:8983 + + + + +(o valor do campo SOLR_URL deve corresponder à URL acessada no item 3) + +7) Entre no diretório raiz do SAPL e digite o comando: **python3 solr_api.py -c sapl -u http://localhost:8983`** + +(a URL informada acima deve ser a mesma dos itens 3 e 6) -Adicione ao arquivo ``.env`` o seguinte atributo: +8) Enquanto o Solr realiza a indexação da base de dados do SAPL, inicie em uma outra tela o SAPL; -``SOLR_URL = 'http://127.0.0.1:8983/solr'`` +9) Após realizados os passos com sucesso, nas telas de busca de Matéria Legislativa e Normas deverá aparecer um botão +de 'Busca Textual' próximo ao botão de busca tradicional. -Dentro do diretório principal siga os seguintes passos:: +**Observações:** - curl -LO https://archive.apache.org/dist/lucene/solr/4.10.2/solr-4.10.2.tgz - tar xvzf solr-4.10.2.tgz - cd solr-4.10.2 - cd example - java -jar start.jar - ./manage.py build_solr_schema --filename solr-4.10.2/example/solr/collection1/conf/schema.xml +a) Para parar o Solr execute o comando **$SOLR_HOME/bin/solr stop** +b) Para reindexar os dados do SAPL execute o comando `python3 manage.py rebuild_index` (isso irá apagar todos os dados +do Solr e indexar tudo novamente). -Após isso, deve-se parar o servidor do Solr e restartar com ``java -jar start.jar`` -**OBS: Toda vez que o código da pesquisa textual for modificado, os comandos de build_solr_schema e start.jar devem ser rodados, nessa mesma ordem.** From 2406cff37fb3ea474d5473a13a0f1fec9487cdbf Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 8 Apr 2019 13:44:54 -0300 Subject: [PATCH 09/18] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20da=20documenta?= =?UTF-8?q?=C3=A7=C3=A3o=20Solr.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/solr.rst | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/docs/solr.rst b/docs/solr.rst index d5da6d889..ae8bbdb63 100644 --- a/docs/solr.rst +++ b/docs/solr.rst @@ -2,20 +2,24 @@ Instruções para instalar o Solr ================================ -Solr é a ferramenta utilizada pelo SAPL 3.1 para indexar documentos para que possa ser feita -a Pesquisa Textual. Se a execução for mediante containers Docker então use o arquivo docker-compose.yml disponível em -*https://github.com/interlegis/sapl/blob/3.1.x/solr/docker-compose.yml* (verifique os mapeamentos de volume, e realize o -backup de seu BD antes de qualquer tentativa de substituição do arquivo docker-compose.yml em uso corrente). +Solr é uma plataforma open source de indexação e busca textual utilizada pelo SAPL 3.1 para indexar documentos (normas jurídicas, matérias legislativas e documentos acessórios). -1) Faça o download da distribuição _binária_ do Apache Solr do site oficial do projeto *http://lucene.apache.org/solr* ; +Observação: Se a execução do SAPL for mediante containers Docker então use o arquivo *docker-compose.yml* disponível em +*https://github.com/interlegis/sapl/blob/3.1.x/solr/docker-compose.yml* (verifique os mapeamentos de volume estão corretos, a verso do SAPL referenciada no arquivo docker-compose.yml, e realize o backup de seu BD **antes** de qualquer tentativa de substituição do arquivo *docker-compose.yml* em uso corrente); + +1) Faça o download da distribuição *binária* do Apache Solr do site oficial do projeto **http://lucene.apache.org/solr** + + + As instalações Solr suportadas até o momento vão da 7.4 à 8; -As instalações Solr suportadas até o momento vão da 7.4 à 8; 2) Descompacte o arquivo em uma pasta do diretório (referenciada neste tutorial como $SOLR_HOME) + 3) Inicie o Solr com o comando: - **$SOLR_HOME/bin/solr start -c** ; + **$SOLR_HOME/bin/solr start -c** + 4) Por meio do browser, acesse a URL **http://localhost:8983** (ou informe o endereço da máquina onde o Solr foi instalado) @@ -23,8 +27,6 @@ As instalações Solr suportadas até o momento vão da 7.4 à 8; 6) Edite o arquivo .env adicionando as seguintes linhas: - - USE_SOLR = True @@ -34,13 +36,11 @@ As instalações Solr suportadas até o momento vão da 7.4 à 8; SOLR_URL = http://localhost:8983 - - -(o valor do campo SOLR_URL deve corresponder à URL acessada no item 3) + (o valor do campo SOLR_URL deve corresponder à URL acessada no item 3) 7) Entre no diretório raiz do SAPL e digite o comando: **python3 solr_api.py -c sapl -u http://localhost:8983`** -(a URL informada acima deve ser a mesma dos itens 3 e 6) + (a URL informada acima deve ser a mesma dos itens 3 e 6) 8) Enquanto o Solr realiza a indexação da base de dados do SAPL, inicie em uma outra tela o SAPL; @@ -49,10 +49,7 @@ de 'Busca Textual' próximo ao botão de busca tradicional. **Observações:** -a) Para parar o Solr execute o comando **$SOLR_HOME/bin/solr stop** +* Para parar o Solr execute o comando **$SOLR_HOME/bin/solr stop** -b) Para reindexar os dados do SAPL execute o comando `python3 manage.py rebuild_index` (isso irá apagar todos os dados +* Para reindexar os dados do SAPL execute o comando **python3 manage.py rebuild_index** (isso irá apagar todos os dados do Solr e indexar tudo novamente). - - - From 431a8fc294d0a9d5cff9d608198a44c24c66faa4 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Mon, 8 Apr 2019 13:49:04 -0300 Subject: [PATCH 10/18] fix anexo norma para arquivos grandes (#2699) --- sapl/norma/forms.py | 3 +-- sapl/norma/models.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 12eee547f..5a9e1b3f6 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -298,11 +298,10 @@ class AnexoNormaJuridicaForm(FileFieldCheckMixin, ModelForm): def save(self, commit=False): anexo = self.instance anexo.ano = self.cleaned_data['norma'].ano - anexo = super(AnexoNormaJuridicaForm, self).save(commit=True) anexo.norma = self.cleaned_data['norma'] anexo.assunto_anexo = self.cleaned_data['assunto_anexo'] anexo.anexo_arquivo = self.cleaned_data['anexo_arquivo'] - anexo.save() + anexo = super(AnexoNormaJuridicaForm, self).save(commit=True) return anexo diff --git a/sapl/norma/models.py b/sapl/norma/models.py index f7fcf17e9..5a5557e5b 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -351,3 +351,20 @@ class AnexoNormaJuridica(models.Model): def __str__(self): return _('Anexo: %(anexo)s da norma %(norma)s') % { 'anexo': self.anexo_arquivo, 'norma': self.norma} + + def save(self, force_insert=False, force_update=False, using=None, + update_fields=None): + + if not self.pk and self.anexo_arquivo: + anexo_arquivo = self.anexo_arquivo + self.anexo_arquivo = None + models.Model.save(self, force_insert=force_insert, + force_update=force_update, + using=using, + update_fields=update_fields) + self.anexo_arquivo = anexo_arquivo + + return models.Model.save(self, force_insert=force_insert, + force_update=force_update, + using=using, + update_fields=update_fields) \ No newline at end of file From 34786902e63bd9a16b51f7fa3cb3f6b66ef33275 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Mon, 8 Apr 2019 13:50:14 -0300 Subject: [PATCH 11/18] =?UTF-8?q?Fix=20Verifica=C3=A7=C3=A3o=20de=20Erros?= =?UTF-8?q?=20do=20Formul=C3=A1rio=20em=20Documento=20Acess=C3=B3rio=20em?= =?UTF-8?q?=20Lote=20(#2693)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix Verificação de Erros do Formulário em Documento Acessorio em Lote * Altera o logger --- sapl/materia/views.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 6c0da0ce0..8d7278e5f 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -14,7 +14,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin -from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned +from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, ValidationError from django.core.urlresolvers import reverse from django.db.models import Max, Q from django.http import HttpResponse, JsonResponse @@ -1945,6 +1945,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView): filterset_class = AcessorioEmLoteFilterSet template_name = 'materia/em_lote/acessorio.html' permission_required = ('materia.add_documentoacessorio',) + logger = logging.getLogger(__name__) def get_context_data(self, **kwargs): context = super(DocumentoAcessorioEmLoteView, @@ -1966,6 +1967,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView): return context def post(self, request, *args, **kwargs): + username = request.user.username marcadas = request.POST.getlist('materia_id') if len(marcadas) == 0: @@ -1981,14 +1983,21 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView): msg = _('Autor tem que ter menos do que 50 caracteres.') messages.add_message(request, messages.ERROR, msg) return self.get(request, self.kwargs) - - tmp_name = os.path.join(tempfile.gettempdir(), request.FILES['arquivo'].name) + + tmp_name = os.path.join(MEDIA_ROOT, request.FILES['arquivo'].name) with open(tmp_name, 'wb') as destination: for chunk in request.FILES['arquivo'].chunks(): destination.write(chunk) + try: + doc_data = tz.localize(datetime.strptime( + request.POST['data'], "%d/%m/%Y")) + except Exception as e: + msg = _('Formato da data incorreto. O formato deve ser da forma dd/mm/aaaa.') + messages.add_message(request, messages.ERROR, msg) + self.logger.error("User={}. {}. Data inserida: {}".format(username, str(msg), request.POST['data'])) + os.remove(tmp_name) + return self.get(request, self.kwargs) - doc_data = tz.localize(datetime.strptime( - request.POST['data'], "%d/%m/%Y")) for materia_id in marcadas: doc = DocumentoAcessorio() doc.materia_id = materia_id @@ -1997,6 +2006,18 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView): doc.data = doc_data doc.autor = request.POST['autor'] doc.ementa = request.POST['ementa'] + doc.arquivo.name = tmp_name + try: + doc.clean_fields() + except ValidationError as e: + for m in [ '%s: %s' % (DocumentoAcessorio()._meta.get_field(k).verbose_name, '
'.join(v)) + for k,v in e.message_dict.items() ]: + # Insere as mensagens de erro no formato: + # 'verbose_name do nome do campo': 'mensagem de erro' + messages.add_message(request, messages.ERROR, m) + self.logger.error("User={}. {}. Nome do arquivo: {}.".format(username, str(msg), request.FILES['arquivo'].name)) + os.remove(tmp_name) + return self.get(request, self.kwargs) doc.save() diretorio = os.path.join(MEDIA_ROOT, 'sapl/public/documentoacessorio', From 80babf2b4520af1665603ad2fced2475c28d3b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Fr=C3=A1?= Date: Mon, 8 Apr 2019 13:55:49 -0300 Subject: [PATCH 12/18] Fix #2682 (#2684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #2682 * retira if desnecessário --- .../blocos_ata/identificacao_basica.html | 3 +- .../sessao/blocos_ata/lista_presenca.html | 6 ++- .../blocos_ata/lista_presenca_ordem_dia.html | 3 +- .../blocos_ata/materias_expediente.html | 51 +++++++++++-------- .../sessao/blocos_ata/materias_ordem_dia.html | 35 +++++++------ .../sessao/blocos_ata/mesa_diretora.html | 3 +- .../blocos_ata/oradores_expediente.html | 7 ++- .../blocos_ata/oradores_explicacoes.html | 5 +- 8 files changed, 65 insertions(+), 48 deletions(-) diff --git a/sapl/templates/sessao/blocos_ata/identificacao_basica.html b/sapl/templates/sessao/blocos_ata/identificacao_basica.html index a6ec9c8c0..84eeb2a11 100644 --- a/sapl/templates/sessao/blocos_ata/identificacao_basica.html +++ b/sapl/templates/sessao/blocos_ata/identificacao_basica.html @@ -2,7 +2,8 @@

Identificação Básica: {% for b in basica %} - {{b}} ; + {{b}} + {% if not forloop.last %} ; {% endif %} {% endfor %}

\ No newline at end of file diff --git a/sapl/templates/sessao/blocos_ata/lista_presenca.html b/sapl/templates/sessao/blocos_ata/lista_presenca.html index 329fde406..1efc2c8ea 100644 --- a/sapl/templates/sessao/blocos_ata/lista_presenca.html +++ b/sapl/templates/sessao/blocos_ata/lista_presenca.html @@ -5,7 +5,8 @@ {% if presenca_sessao %} Lista de Presença na Sessão: {% for p in presenca_sessao %} - {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} ; + {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

@@ -13,7 +14,8 @@ {% if justificativa_ausencia %} Justificativas de Ausências na Sessão: {% for j in justificativa_ausencia %} - {{j.parlamentar.nome_completo}} / {{ j.tipo_ausencia }} ; + {{j.parlamentar.nome_completo}} / {{ j.tipo_ausencia }} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html b/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html index d6c8014ca..855d1be6f 100644 --- a/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html +++ b/sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html @@ -5,7 +5,8 @@ {% if presenca_ordem %} Lista de Presença na Ordem do Dia: {% for p in presenca_ordem %} - {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} ; + {{p.nome_completo}} / {{ p|filiacao_data_filter:object.data_inicio }} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/materias_expediente.html b/sapl/templates/sessao/blocos_ata/materias_expediente.html index 7613448fc..3ccc3fb84 100644 --- a/sapl/templates/sessao/blocos_ata/materias_expediente.html +++ b/sapl/templates/sessao/blocos_ata/materias_expediente.html @@ -1,27 +1,36 @@

- {% if materia_expediente %} + {% if materia_expediente %} Matérias do Expediente: - {% for m in materia_expediente %} - {{m.numero}} - {{m.titulo}} - - {% if m.turno %} - Turno: {{m.turno}} - {% endif %} - - Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} - - {% if m.numero_protocolo %} - Número de Protocolo: {{ m.numero_protocolo }} - {% endif %} - - {% if m.numero_processo %} - Processo: {{ m.numero_processo }} - {% endif %} - - {{m.ementa|safe}} - {{m.resultado}} {{m.resultado_observacao}} - {% endfor %} + {% for m in materia_expediente %} + {{m.numero}} - {{m.titulo}}, + {{m.ementa|safe}} + Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}, + {% if m.numero_protocolo %} + Número de Protocolo: {{ m.numero_protocolo }}, + {% endif %} + {% if m.numero_processo %} + Processo: {{ m.numero_processo }}, + {% endif %} + {%if m.turno %} + Turno: {{m.turno}}, + {%endif %} + {%if m.tipo_votacao %} + Tipo: {{m.tipo_votacao}}, + Sim: {{ m.voto_sim }}, + Não: {{ m.voto_nao }}, + Abstenções: {{m.voto_abstencoes}}, + {% endif %} + Resultado: {{m.resultado}} + {% if m.resultado_observacao %} - {{m.resultado_observacao}} {% endif %} + {% if m.voto_nominal%} + Votos Nominais : + {% for voto in m.voto_nominal %} + {{voto.0}} - {{voto.1}} + {% if not forloop.last %} ; {% endif %} + {% endfor %} + {% endif %} + {% endfor %} {% endif %}

\ No newline at end of file diff --git a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html index d894e8a06..a167e01a1 100644 --- a/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html +++ b/sapl/templates/sessao/blocos_ata/materias_ordem_dia.html @@ -2,29 +2,32 @@

Matérias da Ordem do Dia: {% for m in materias_ordem %} - {{m.numero}} - {{m.titulo}} - Descrição: {{m.ementa|safe}} - Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} + {{m.numero}} - {{m.titulo}}, + {{m.ementa|safe}} + Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}, {% if m.numero_protocolo %} - Número de Protocolo: {{ m.numero_protocolo }} + Número de Protocolo: {{ m.numero_protocolo }}, {% endif %} {% if m.numero_processo %} - Processo:{{ m.numero_processo }} + Processo: {{ m.numero_processo }}, {% endif %} {%if m.turno %} - Turno: {{m.turno}} + Turno: {{m.turno}}, {%endif %} - Tipo: {{m.tipo_votacao}} - Sim:{{m.voto_sim}} - Não:{{m.voto_nao}} - Abstenções:{{m.voto_abstencoes}} - Resultado: {{m.resultado}} {{m.resultado_observacao}} + {%if m.tipo_votacao %} + Tipo: {{m.tipo_votacao}}, + Sim: {{ m.voto_sim }}, + Não: {{ m.voto_nao }}, + Abstenções: {{m.voto_abstencoes}}, + {% endif %} + Resultado: {{m.resultado}} + {% if m.resultado_observacao %} - {{m.resultado_observacao}} {% endif %} {% if m.voto_nominal%} Votos Nominais : {% for voto in m.voto_nominal %} - / {{voto.0}} - {{voto.1}} - {% endfor %}; - {% endif %} - {% endfor %} -

+ {{voto.0}} - {{voto.1}} + {% if not forloop.last %} ; {% endif %} + {% endfor %} + {% endif %} + {% endfor %} \ No newline at end of file diff --git a/sapl/templates/sessao/blocos_ata/mesa_diretora.html b/sapl/templates/sessao/blocos_ata/mesa_diretora.html index fb27b0fcc..2d2de86d7 100644 --- a/sapl/templates/sessao/blocos_ata/mesa_diretora.html +++ b/sapl/templates/sessao/blocos_ata/mesa_diretora.html @@ -4,7 +4,8 @@ Mesa Diretora: {% for m in mesa %} {{m.cargo}}: - {{m.parlamentar.nome_completo}} / {{ m.parlamentar.filiacao_atual }} ; + {{m.parlamentar.nome_completo}} / {{ m.parlamentar.filiacao_atual }} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/oradores_expediente.html b/sapl/templates/sessao/blocos_ata/oradores_expediente.html index bc39db224..f85b27895 100644 --- a/sapl/templates/sessao/blocos_ata/oradores_expediente.html +++ b/sapl/templates/sessao/blocos_ata/oradores_expediente.html @@ -3,10 +3,9 @@ {% if oradores %} Oradores do Expediente: {% for o in oradores %} -
{{o.numero_ordem}} - {{o.parlamentar.nome_completo}}
-
{{o.url_discurso}}
-
{{o.observacao}}
-
+ {{o.numero_ordem}} - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }} + {% if o.observacao %} - {{o.observacao}} {% endif %} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

diff --git a/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html b/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html index 5af2b9ff2..98a454d78 100644 --- a/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html +++ b/sapl/templates/sessao/blocos_ata/oradores_explicacoes.html @@ -3,8 +3,9 @@ {% if oradores_explicacoes %} Oradores das Explicações Pessoais: {% for o in oradores_explicacoes %} - {{o.numero_ordem}} - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }} ; - {{o.url_discurso}} + {{o.numero_ordem}} - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }} + {% if o.observacao %} - {{o.observacao}} {% endif %} + {% if not forloop.last %} ; {% endif %} {% endfor %} {% endif %}

From 6694b1f3181695d5f1d60e77e360881d90b29989 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 8 Apr 2019 14:42:33 -0300 Subject: [PATCH 13/18] HOT-FIX: conserta cadastro de parlamentar em 3.1.x --- sapl/parlamentares/forms.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index e1e773d9b..f52cea871 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -236,18 +236,6 @@ class ParlamentarFilterSet(django_filters.FilterSet): class ParlamentarCreateForm(ParlamentarForm): - legislatura = forms.ModelChoiceField( - label=_('Legislatura'), - required=True, - queryset=Legislatura.objects.all().order_by('-data_inicio'), - empty_label='----------', - ) - - data_expedicao_diploma = forms.DateField( - label=_('Expedição do Diploma'), - required=True, - ) - class Meta(ParlamentarForm.Meta): widgets = { 'fotografia': forms.ClearableFileInput(), @@ -258,13 +246,6 @@ class ParlamentarCreateForm(ParlamentarForm): @transaction.atomic def save(self, commit=True): parlamentar = super(ParlamentarCreateForm, self).save(commit) - legislatura = self.cleaned_data['legislatura'] - Mandato.objects.create( - parlamentar=parlamentar, - legislatura=legislatura, - data_inicio_mandato=legislatura.data_inicio, - data_fim_mandato=legislatura.data_fim, - data_expedicao_diploma=self.cleaned_data['data_expedicao_diploma']) content_type = ContentType.objects.get_for_model(Parlamentar) object_id = parlamentar.pk tipo = TipoAutor.objects.get(content_type=content_type) From a8b336285a345f6885586fd2110afb3f7a86900a Mon Sep 17 00:00:00 2001 From: Cesar Carvalho Date: Mon, 8 Apr 2019 15:06:18 -0300 Subject: [PATCH 14/18] HOTFIX - Corrige testes de cadastro de parlamentar --- sapl/parlamentares/tests/test_parlamentares.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py index e7b885871..7ab76760c 100644 --- a/sapl/parlamentares/tests/test_parlamentares.py +++ b/sapl/parlamentares/tests/test_parlamentares.py @@ -11,7 +11,6 @@ from sapl.parlamentares.models import (Dependente, Filiacao, Legislatura, @pytest.mark.django_db(transaction=False) def test_cadastro_parlamentar(admin_client): - legislatura = mommy.make(Legislatura) url = reverse('sapl.parlamentares:parlamentar_create') response = admin_client.get(url) @@ -20,9 +19,7 @@ def test_cadastro_parlamentar(admin_client): response = admin_client.post(url, {'nome_completo': 'Teresa Barbosa', 'nome_parlamentar': 'Terezinha', 'sexo': 'F', - 'ativo': 'True', - 'legislatura': legislatura.id, - 'data_expedicao_diploma': '2001-01-01'}, + 'ativo': 'True'}, follow=True) [parlamentar] = Parlamentar.objects.all() @@ -32,9 +29,6 @@ def test_cadastro_parlamentar(admin_client): # o primeiro mandato é criado [mandato] = Mandato.objects.all() assert mandato.parlamentar == parlamentar - assert str(mandato.data_expedicao_diploma) == '2001-01-01' - assert mandato.legislatura == legislatura - assert mandato.data_fim_mandato == legislatura.data_fim @pytest.mark.django_db(transaction=False) @@ -42,9 +36,7 @@ def test_incluir_parlamentar_errors(admin_client): url = reverse('sapl.parlamentares:parlamentar_create') response = admin_client.post(url) erros_esperados = {campo: ['Este campo é obrigatório.'] - for campo in ['legislatura', - 'data_expedicao_diploma', - 'nome_parlamentar', + for campo in ['nome_parlamentar', 'nome_completo', 'sexo', ]} From a5bb2f8d9ce2dff5ee8a0dc9b7af3dd694fb916c Mon Sep 17 00:00:00 2001 From: Cesar Carvalho Date: Mon, 8 Apr 2019 15:21:22 -0300 Subject: [PATCH 15/18] Corrige teste do parlamentar --- sapl/parlamentares/tests/test_parlamentares.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py index 7ab76760c..e5f607a09 100644 --- a/sapl/parlamentares/tests/test_parlamentares.py +++ b/sapl/parlamentares/tests/test_parlamentares.py @@ -26,9 +26,6 @@ def test_cadastro_parlamentar(admin_client): assert parlamentar.nome_parlamentar == 'Terezinha' assert parlamentar.sexo == 'F' assert parlamentar.ativo is True - # o primeiro mandato é criado - [mandato] = Mandato.objects.all() - assert mandato.parlamentar == parlamentar @pytest.mark.django_db(transaction=False) From cbe65f9ec47bc91e221b616c3cddf170621c9cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Fr=C3=A1?= Date: Mon, 8 Apr 2019 15:33:17 -0300 Subject: [PATCH 16/18] =?UTF-8?q?Reuni=C3=A3o=20comiss=C3=A3o=20(#2692)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #2682 * retira if desnecessário * Fix #2691 --- sapl/comissoes/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py index 7b8a6fd1d..1db8d23df 100644 --- a/sapl/comissoes/views.py +++ b/sapl/comissoes/views.py @@ -197,7 +197,8 @@ class ReuniaoCrud(MasterDetailCrud): public = [RP_LIST, RP_DETAIL, ] class BaseMixin(MasterDetailCrud.BaseMixin): - list_field_names = ['data', 'nome', 'tema'] + list_field_names = ['data', 'nome', 'tema', 'upload_ata'] + ordering = '-data' class ListView(MasterDetailCrud.ListView): logger = logging.getLogger(__name__) From 8d5a7f8869793fd6717a78899feb99200fa4bf61 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 8 Apr 2019 16:52:31 -0300 Subject: [PATCH 17/18] HOT-FIX: Fixes #2694 --- sapl/templates/norma/normajuridica_form.html | 1 - 1 file changed, 1 deletion(-) diff --git a/sapl/templates/norma/normajuridica_form.html b/sapl/templates/norma/normajuridica_form.html index 8f5b5a6df..4c29fc98b 100644 --- a/sapl/templates/norma/normajuridica_form.html +++ b/sapl/templates/norma/normajuridica_form.html @@ -30,7 +30,6 @@ for (i = 0; i < fields.length; i++) { $(fields[i]).change(recuperar_materia); } - recuperar_materia(); function recuperar_norma() { var tipo = $("#id_tipo").val(); From 13ec4603877c74e06a6510cae592ffcec8ada663 Mon Sep 17 00:00:00 2001 From: VictorFabreF Date: Tue, 9 Apr 2019 09:50:06 -0300 Subject: [PATCH 18/18] Release: 3.1.153 --- docker-compose.yml | 2 +- sapl/settings.py | 2 +- sapl/templates/base.html | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index edc04b07e..e2dfb6824 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ sapldb: ports: - "5432:5432" sapl: - image: interlegis/sapl:3.1.152 + image: interlegis/sapl:3.1.153 restart: always environment: ADMIN_PASSWORD: interlegis diff --git a/sapl/settings.py b/sapl/settings.py index 057e8ec75..af1b8d697 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*'] LOGIN_REDIRECT_URL = '/' LOGIN_URL = '/login/?next=' -SAPL_VERSION = '3.1.152' +SAPL_VERSION = '3.1.153' if DEBUG: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/sapl/templates/base.html b/sapl/templates/base.html index 3048f83b2..b19ec673e 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -179,7 +179,7 @@ Desenvolvido pelo Interlegis em software livre e aberto. - Release: 3.1.152 + Release: 3.1.153

diff --git a/setup.py b/setup.py index c2818b7ab..f5cffaeb6 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ install_requires = [ ] setup( name='interlegis-sapl', - version='3.1.152', + version='3.1.153', packages=find_packages(), include_package_data=True, license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',