Browse Source

Merge commit '13ec4603' (= 3.1.153) into migracao

migracao
Marcio Mazza 6 years ago
parent
commit
031fcf9216
  1. 2
      docker-compose.yml
  2. 58
      docs/solr.rst
  3. 5
      sapl/api/views.py
  4. 3
      sapl/comissoes/views.py
  5. 52
      sapl/materia/forms.py
  6. 55
      sapl/materia/views.py
  7. 3
      sapl/norma/forms.py
  8. 17
      sapl/norma/models.py
  9. 19
      sapl/parlamentares/forms.py
  10. 15
      sapl/parlamentares/tests/test_parlamentares.py
  11. 2
      sapl/settings.py
  12. 2
      sapl/templates/base.html
  13. 3
      sapl/templates/menu_tabelas_auxiliares.yaml
  14. 1
      sapl/templates/norma/normajuridica_form.html
  15. 3
      sapl/templates/sessao/blocos_ata/identificacao_basica.html
  16. 6
      sapl/templates/sessao/blocos_ata/lista_presenca.html
  17. 3
      sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html
  18. 51
      sapl/templates/sessao/blocos_ata/materias_expediente.html
  19. 35
      sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
  20. 3
      sapl/templates/sessao/blocos_ata/mesa_diretora.html
  21. 7
      sapl/templates/sessao/blocos_ata/oradores_expediente.html
  22. 5
      sapl/templates/sessao/blocos_ata/oradores_explicacoes.html
  23. 2
      setup.py
  24. 2
      solr/docker-compose.yml

2
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

58
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).

5
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:

3
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__)

52
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

55
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, '</br>'.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)

3
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

17
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)

19
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)

15
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',
]}

2
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'

2
sapl/templates/base.html

@ -179,7 +179,7 @@
<small>
Desenvolvido pelo <a href="http://www.interlegis.leg.br/">Interlegis</a> em software livre e aberto.
</small>
<span>Release: 3.1.152</span>
<span>Release: 3.1.153</span>
</p>
</div>
<div class="col-md-4">

3
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

1
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();

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

@ -2,7 +2,8 @@
<p align="justify">
<strong>Identificação Básica: </strong>
{% for b in basica %}
{{b}} ;
{{b}}
{% if not forloop.last %} ; {% endif %}
{% endfor %}
</p>
</fieldset>

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

@ -5,7 +5,8 @@
{% if presenca_sessao %}
<strong>Lista de Presença na Sessão: </strong>
{% 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 %}
</p>
@ -13,7 +14,8 @@
{% if justificativa_ausencia %}
<strong>Justificativas de Ausências na Sessão: </strong>
{% 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 %}
</p>

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

@ -5,7 +5,8 @@
{% if presenca_ordem %}
<strong>Lista de Presença na Ordem do Dia: </strong>
{% 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 %}
</p>

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

@ -1,27 +1,36 @@
<fieldset>
<p align="justify">
{% if materia_expediente %}
{% if materia_expediente %}
<strong>Matérias do Expediente: </strong>
{% for m in materia_expediente %}
<b>{{m.numero}} - {{m.titulo}}</b>
{% if m.turno %}
Turno: {{m.turno}}
{% endif %}
Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
{% if m.numero_protocolo %}
Número de Protocolo: {{ m.numero_protocolo }}
{% endif %}
{% if m.numero_processo %}
Processo: {{ m.numero_processo }}
{% endif %}
{{m.ementa|safe}}
{{m.resultado}} {{m.resultado_observacao}}</td>
{% endfor %}
{% for m in materia_expediente %}
<b>{{m.numero}} - {{m.titulo}}</b>,
{{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:</b> {{m.resultado}}
{% if m.resultado_observacao %} - {{m.resultado_observacao}} {% endif %}
{% if m.voto_nominal%}
<b>Votos Nominais :</b>
{% for voto in m.voto_nominal %}
{{voto.0}} - {{voto.1}}
{% if not forloop.last %} ; {% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
</p>
</fieldset>

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

@ -2,29 +2,32 @@
<p align="justify">
<strong>Matérias da Ordem do Dia: </strong>
{% for m in materias_ordem %}
<b>{{m.numero}} - {{m.titulo}}</b>
Descrição: {{m.ementa|safe}}
Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }}
<b>{{m.numero}} - {{m.titulo}}</b>,
{{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:</b> {{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:</b> {{m.resultado}}
{% if m.resultado_observacao %} - {{m.resultado_observacao}} {% endif %}
{% if m.voto_nominal%}
<b>Votos Nominais :</b>
{% for voto in m.voto_nominal %}
/ {{voto.0}} - {{voto.1}}
{% endfor %};
{% endif %}
{% endfor %}
</p>
{{voto.0}} - {{voto.1}}
{% if not forloop.last %} ; {% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</fieldset>

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

@ -4,7 +4,8 @@
<strong>Mesa Diretora: </strong>
{% 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 %}
</p>

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

@ -3,10 +3,9 @@
{% if oradores %}
<strong>Oradores do Expediente: </strong>
{% for o in oradores %}
<div><b>{{o.numero_ordem}}</b> - {{o.parlamentar.nome_completo}}</div>
<div>{{o.url_discurso}}</div>
<div>{{o.observacao}}</div>
</br>
<b>{{o.numero_ordem}}</b> - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }}
{% if o.observacao %} - {{o.observacao}} {% endif %}
{% if not forloop.last %} ; {% endif %}
{% endfor %}
{% endif %}
</p>

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

@ -3,8 +3,9 @@
{% if oradores_explicacoes %}
<strong>Oradores das Explicações Pessoais: </strong>
{% for o in oradores_explicacoes %}
<b>{{o.numero_ordem}}</b> - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }} ;
{{o.url_discurso}}
<b>{{o.numero_ordem}}</b> - {{o.parlamentar.nome_completo}} / {{ o.parlamentar.filiacao_atual }}
{% if o.observacao %} - {{o.observacao}} {% endif %}
{% if not forloop.last %} ; {% endif %}
{% endfor %}
{% endif %}
</p>

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

2
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:

Loading…
Cancel
Save