Browse Source

Merge branch '3.1.x' into evita-anexada-ciclica

pull/2670/head
João Rodrigues 7 years ago
committed by GitHub
parent
commit
f4576d4306
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      docker-compose.yml
  2. 58
      docs/solr.rst
  3. 16
      sapl/api/views.py
  4. 3
      sapl/comissoes/views.py
  5. 31
      sapl/materia/views.py
  6. 3
      sapl/norma/forms.py
  7. 17
      sapl/norma/models.py
  8. 19
      sapl/parlamentares/forms.py
  9. 15
      sapl/parlamentares/tests/test_parlamentares.py
  10. 23
      sapl/sessao/models.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: ports:
- "5432:5432" - "5432:5432"
sapl: sapl:
image: interlegis/sapl:3.1.152 image: interlegis/sapl:3.1.153
restart: always restart: always
environment: environment:
ADMIN_PASSWORD: interlegis 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 Instruções para instalar o Solr
================================ ================================
Solr é a ferramenta utilizada pelo SAPL 3.1 para indexar documentos para que possa ser feita 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).
a Pesquisa Textual.
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 8) Enquanto o Solr realiza a indexação da base de dados do SAPL, inicie em uma outra tela o SAPL;
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
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).

16
sapl/api/views.py

@ -27,7 +27,7 @@ from sapl.materia.models import Proposicao, TipoMateriaLegislativa,\
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
from sapl.protocoloadm.models import DocumentoAdministrativo,\ from sapl.protocoloadm.models import DocumentoAdministrativo,\
DocumentoAcessorioAdministrativo, TramitacaoAdministrativo DocumentoAcessorioAdministrativo, TramitacaoAdministrativo
from sapl.sessao.models import SessaoPlenaria from sapl.sessao.models import SessaoPlenaria, ExpedienteSessao
from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria
@ -498,3 +498,17 @@ class _SessaoPlenariaViewSet:
serializer = ChoiceSerializer(years, many=True) serializer = ChoiceSerializer(years, many=True)
return Response(serializer.data) return Response(serializer.data)
@action(detail=True)
def expedientes(self, request, *args, **kwargs):
sessao = self.get_object()
page = self.paginate_queryset(sessao.expedientesessao_set.all())
if page is not None:
serializer = SaplApiViewSetConstrutor.get_class_for_model(
ExpedienteSessao).serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(page, many=True)
return Response(serializer.data)

3
sapl/comissoes/views.py

@ -197,7 +197,8 @@ class ReuniaoCrud(MasterDetailCrud):
public = [RP_LIST, RP_DETAIL, ] public = [RP_LIST, RP_DETAIL, ]
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['data', 'nome', 'tema'] list_field_names = ['data', 'nome', 'tema', 'upload_ata']
ordering = '-data'
class ListView(MasterDetailCrud.ListView): class ListView(MasterDetailCrud.ListView):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

31
sapl/materia/views.py

@ -14,7 +14,7 @@ from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin 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.core.urlresolvers import reverse
from django.db.models import Max, Q from django.db.models import Max, Q
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse
@ -1945,6 +1945,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
filterset_class = AcessorioEmLoteFilterSet filterset_class = AcessorioEmLoteFilterSet
template_name = 'materia/em_lote/acessorio.html' template_name = 'materia/em_lote/acessorio.html'
permission_required = ('materia.add_documentoacessorio',) permission_required = ('materia.add_documentoacessorio',)
logger = logging.getLogger(__name__)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(DocumentoAcessorioEmLoteView, context = super(DocumentoAcessorioEmLoteView,
@ -1966,6 +1967,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
return context return context
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
username = request.user.username
marcadas = request.POST.getlist('materia_id') marcadas = request.POST.getlist('materia_id')
if len(marcadas) == 0: if len(marcadas) == 0:
@ -1981,14 +1983,21 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
msg = _('Autor tem que ter menos do que 50 caracteres.') msg = _('Autor tem que ter menos do que 50 caracteres.')
messages.add_message(request, messages.ERROR, msg) messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs) 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: with open(tmp_name, 'wb') as destination:
for chunk in request.FILES['arquivo'].chunks(): for chunk in request.FILES['arquivo'].chunks():
destination.write(chunk) 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: for materia_id in marcadas:
doc = DocumentoAcessorio() doc = DocumentoAcessorio()
doc.materia_id = materia_id doc.materia_id = materia_id
@ -1997,6 +2006,18 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
doc.data = doc_data doc.data = doc_data
doc.autor = request.POST['autor'] doc.autor = request.POST['autor']
doc.ementa = request.POST['ementa'] 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() doc.save()
diretorio = os.path.join(MEDIA_ROOT, diretorio = os.path.join(MEDIA_ROOT,
'sapl/public/documentoacessorio', 'sapl/public/documentoacessorio',

3
sapl/norma/forms.py

@ -298,11 +298,10 @@ class AnexoNormaJuridicaForm(FileFieldCheckMixin, ModelForm):
def save(self, commit=False): def save(self, commit=False):
anexo = self.instance anexo = self.instance
anexo.ano = self.cleaned_data['norma'].ano anexo.ano = self.cleaned_data['norma'].ano
anexo = super(AnexoNormaJuridicaForm, self).save(commit=True)
anexo.norma = self.cleaned_data['norma'] anexo.norma = self.cleaned_data['norma']
anexo.assunto_anexo = self.cleaned_data['assunto_anexo'] anexo.assunto_anexo = self.cleaned_data['assunto_anexo']
anexo.anexo_arquivo = self.cleaned_data['anexo_arquivo'] anexo.anexo_arquivo = self.cleaned_data['anexo_arquivo']
anexo.save() anexo = super(AnexoNormaJuridicaForm, self).save(commit=True)
return anexo return anexo

17
sapl/norma/models.py

@ -351,3 +351,20 @@ class AnexoNormaJuridica(models.Model):
def __str__(self): def __str__(self):
return _('Anexo: %(anexo)s da norma %(norma)s') % { return _('Anexo: %(anexo)s da norma %(norma)s') % {
'anexo': self.anexo_arquivo, 'norma': self.norma} '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): 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): class Meta(ParlamentarForm.Meta):
widgets = { widgets = {
'fotografia': forms.ClearableFileInput(), 'fotografia': forms.ClearableFileInput(),
@ -258,13 +246,6 @@ class ParlamentarCreateForm(ParlamentarForm):
@transaction.atomic @transaction.atomic
def save(self, commit=True): def save(self, commit=True):
parlamentar = super(ParlamentarCreateForm, self).save(commit) 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) content_type = ContentType.objects.get_for_model(Parlamentar)
object_id = parlamentar.pk object_id = parlamentar.pk
tipo = TipoAutor.objects.get(content_type=content_type) 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) @pytest.mark.django_db(transaction=False)
def test_cadastro_parlamentar(admin_client): def test_cadastro_parlamentar(admin_client):
legislatura = mommy.make(Legislatura)
url = reverse('sapl.parlamentares:parlamentar_create') url = reverse('sapl.parlamentares:parlamentar_create')
response = admin_client.get(url) response = admin_client.get(url)
@ -20,21 +19,13 @@ def test_cadastro_parlamentar(admin_client):
response = admin_client.post(url, {'nome_completo': 'Teresa Barbosa', response = admin_client.post(url, {'nome_completo': 'Teresa Barbosa',
'nome_parlamentar': 'Terezinha', 'nome_parlamentar': 'Terezinha',
'sexo': 'F', 'sexo': 'F',
'ativo': 'True', 'ativo': 'True'},
'legislatura': legislatura.id,
'data_expedicao_diploma': '2001-01-01'},
follow=True) follow=True)
[parlamentar] = Parlamentar.objects.all() [parlamentar] = Parlamentar.objects.all()
assert parlamentar.nome_parlamentar == 'Terezinha' assert parlamentar.nome_parlamentar == 'Terezinha'
assert parlamentar.sexo == 'F' assert parlamentar.sexo == 'F'
assert parlamentar.ativo is True 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) @pytest.mark.django_db(transaction=False)
@ -42,9 +33,7 @@ def test_incluir_parlamentar_errors(admin_client):
url = reverse('sapl.parlamentares:parlamentar_create') url = reverse('sapl.parlamentares:parlamentar_create')
response = admin_client.post(url) response = admin_client.post(url)
erros_esperados = {campo: ['Este campo é obrigatório.'] erros_esperados = {campo: ['Este campo é obrigatório.']
for campo in ['legislatura', for campo in ['nome_parlamentar',
'data_expedicao_diploma',
'nome_parlamentar',
'nome_completo', 'nome_completo',
'sexo', 'sexo',
]} ]}

23
sapl/sessao/models.py

@ -290,8 +290,11 @@ class TipoExpediente(models.Model):
@reversion.register() @reversion.register()
class ExpedienteSessao(models.Model): # ExpedienteSessaoPlenaria class ExpedienteSessao(models.Model): # ExpedienteSessaoPlenaria
sessao_plenaria = models.ForeignKey(SessaoPlenaria, sessao_plenaria = models.ForeignKey(
on_delete=models.CASCADE) SessaoPlenaria,
on_delete=models.CASCADE,
related_name='expedientesessao_set'
)
tipo = models.ForeignKey(TipoExpediente, on_delete=models.PROTECT) tipo = models.ForeignKey(TipoExpediente, on_delete=models.PROTECT)
conteudo = models.TextField( conteudo = models.TextField(
blank=True, verbose_name=_('Conteúdo do expediente')) blank=True, verbose_name=_('Conteúdo do expediente'))
@ -379,7 +382,7 @@ class OradorExpediente(AbstractOrador): # OradoresExpediente
@reversion.register() @reversion.register()
class OradorOrdemDia(AbstractOrador): # OradoresOrdemDia class OradorOrdemDia(AbstractOrador): # OradoresOrdemDia
class Meta: class Meta:
verbose_name = _('Orador da Ordem do Dia') verbose_name = _('Orador da Ordem do Dia')
@ -584,10 +587,14 @@ class ResumoOrdenacao(models.Model):
oitavo = models.CharField(max_length=30) oitavo = models.CharField(max_length=30)
nono = models.CharField(max_length=30) nono = models.CharField(max_length=30)
decimo = models.CharField(max_length=30) decimo = models.CharField(max_length=30)
decimo_primeiro = models.CharField(max_length=30,default="Ocorrências da Sessão") decimo_primeiro = models.CharField(
decimo_segundo = models.CharField(max_length=30, default="Votos Nominais Mat Expediente") max_length=30, default="Ocorrências da Sessão")
decimo_terceiro = models.CharField(max_length=30, default="Votos Nominais Mat Ordem Dia") decimo_segundo = models.CharField(
decimo_quarto = models.CharField(max_length=30, default="Oradores da Ordem do Dia") max_length=30, default="Votos Nominais Mat Expediente")
decimo_terceiro = models.CharField(
max_length=30, default="Votos Nominais Mat Ordem Dia")
decimo_quarto = models.CharField(
max_length=30, default="Oradores da Ordem do Dia")
class Meta: class Meta:
verbose_name = _('Ordenação do Resumo de uma Sessão') verbose_name = _('Ordenação do Resumo de uma Sessão')
@ -596,6 +603,7 @@ class ResumoOrdenacao(models.Model):
def __str__(self): def __str__(self):
return 'Ordenação do Resumo de uma Sessão' return 'Ordenação do Resumo de uma Sessão'
@reversion.register() @reversion.register()
class TipoRetiradaPauta(models.Model): class TipoRetiradaPauta(models.Model):
descricao = models.CharField(max_length=150, verbose_name=_('Descrição')) descricao = models.CharField(max_length=150, verbose_name=_('Descrição'))
@ -687,6 +695,7 @@ class JustificativaAusencia(models.Model):
using=using, using=using,
update_fields=update_fields) update_fields=update_fields)
class RetiradaPauta(models.Model): class RetiradaPauta(models.Model):
materia = models.ForeignKey(MateriaLegislativa, materia = models.ForeignKey(MateriaLegislativa,
on_delete=models.CASCADE, on_delete=models.CASCADE,

2
sapl/settings.py

@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/?next=' LOGIN_URL = '/login/?next='
SAPL_VERSION = '3.1.152' SAPL_VERSION = '3.1.153'
if DEBUG: if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

2
sapl/templates/base.html

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

3
sapl/templates/menu_tabelas_auxiliares.yaml

@ -20,6 +20,9 @@
- title: {% trans 'Pesquisar Parlamentar' %} - title: {% trans 'Pesquisar Parlamentar' %}
url: sapl.parlamentares:pesquisar_parlamentar url: sapl.parlamentares:pesquisar_parlamentar
css_class: btn btn-link css_class: btn btn-link
- title: {% trans 'Adicionar Parlamentar' %}
url: sapl.parlamentares:parlamentar_create
css_class: btn btn-link
- title: {% trans 'Legislatura' %} - title: {% trans 'Legislatura' %}
url: sapl.parlamentares:legislatura_list url: sapl.parlamentares:legislatura_list
css_class: btn btn-link css_class: btn btn-link

1
sapl/templates/norma/normajuridica_form.html

@ -30,7 +30,6 @@
for (i = 0; i < fields.length; i++) { for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_materia); $(fields[i]).change(recuperar_materia);
} }
recuperar_materia();
function recuperar_norma() { function recuperar_norma() {
var tipo = $("#id_tipo").val(); var tipo = $("#id_tipo").val();

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

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

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

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

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

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

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

@ -1,27 +1,36 @@
<fieldset> <fieldset>
<p align="justify"> <p align="justify">
{% if materia_expediente %} {% if materia_expediente %}
<strong>Matérias do Expediente: </strong> <strong>Matérias do Expediente: </strong>
{% for m in materia_expediente %} {% for m in materia_expediente %}
<b>{{m.numero}} - {{m.titulo}}</b> <b>{{m.numero}} - {{m.titulo}}</b>,
{{m.ementa|safe}}
{% if m.turno %} Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }},
Turno: {{m.turno}} {% if m.numero_protocolo %}
{% endif %} Número de Protocolo: {{ m.numero_protocolo }},
{% endif %}
Autor{{ m.autor|length|pluralize:"es" }}: {{ m.autor|join:', ' }} {% if m.numero_processo %}
Processo: {{ m.numero_processo }},
{% if m.numero_protocolo %} {% endif %}
Número de Protocolo: {{ m.numero_protocolo }} {%if m.turno %}
{% endif %} Turno: {{m.turno}},
{%endif %}
{% if m.numero_processo %} {%if m.tipo_votacao %}
Processo: {{ m.numero_processo }} Tipo: {{m.tipo_votacao}},
{% endif %} Sim: {{ m.voto_sim }},
Não: {{ m.voto_nao }},
{{m.ementa|safe}} Abstenções: {{m.voto_abstencoes}},
{{m.resultado}} {{m.resultado_observacao}}</td> {% endif %}
{% endfor %} 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 %} {% endif %}
</p> </p>
</fieldset> </fieldset>

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

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

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

@ -4,7 +4,8 @@
<strong>Mesa Diretora: </strong> <strong>Mesa Diretora: </strong>
{% for m in mesa %} {% for m in mesa %}
{{m.cargo}}: {{m.cargo}}:
{{m.parlamentar.nome_completo}} / {{ m.parlamentar.filiacao_atual }} ; {{m.parlamentar.nome_completo}} / {{ m.parlamentar.filiacao_atual }}
{% if not forloop.last %} ; {% endif %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</p> </p>

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

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

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

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

2
setup.py

@ -43,7 +43,7 @@ install_requires = [
] ]
setup( setup(
name='interlegis-sapl', name='interlegis-sapl',
version='3.1.152', version='3.1.153',
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',

2
solr/docker-compose.yml

@ -24,7 +24,7 @@ services:
- "8983:8983" - "8983:8983"
sapl: sapl:
image: interlegis/sapl:3.1.144 image: interlegis/sapl:3.1.152
# build: . # build: .
restart: always restart: always
environment: environment:

Loading…
Cancel
Save