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/docs/solr.rst b/docs/solr.rst index 4c82ab68d..ae8bbdb63 100644 --- a/docs/solr.rst +++ b/docs/solr.rst @@ -1,27 +1,55 @@ -**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. +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). + +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; + + +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 + -Adicione ao arquivo ``.env`` o seguinte atributo: + (o valor do campo SOLR_URL deve corresponder à URL acessada no item 3) -``SOLR_URL = 'http://127.0.0.1:8983/solr'`` +7) Entre no diretório raiz do SAPL e digite o comando: **python3 solr_api.py -c sapl -u http://localhost:8983`** -Dentro do diretório principal siga os seguintes passos:: + (a URL informada acima deve ser a mesma dos itens 3 e 6) - 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 +8) Enquanto o Solr realiza a indexação da base de dados do SAPL, inicie em uma outra tela o SAPL; +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. -Após isso, deve-se parar o servidor do Solr e restartar com ``java -jar start.jar`` +**Observações:** +* Para parar o Solr execute o comando **$SOLR_HOME/bin/solr stop** -**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.** +* 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). 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: 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__) diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 673dfd024..edbeed810 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, @@ -402,7 +402,17 @@ 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 +434,11 @@ 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 @@ -452,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): @@ -791,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')) @@ -1169,6 +1189,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): @@ -1570,8 +1591,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))) @@ -1990,14 +2011,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() @@ -2488,7 +2508,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 diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 73dcb3072..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 @@ -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 @@ -1925,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, @@ -1946,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: @@ -1961,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 @@ -1977,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', @@ -1987,7 +2028,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) 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 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) diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py index e7b885871..e5f607a09 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,21 +19,13 @@ 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() 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 - 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 +33,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', ]} 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/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 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(); 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 %}

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', 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: