Browse Source

merge

pull/2416/head
Cesar Carvalho 7 years ago
parent
commit
066a58b850
  1. 2
      docker-compose.yml
  2. 35
      sapl/base/migrations/0024_auto_20181126_1534.py
  3. 21
      sapl/base/migrations/0025_auto_20181126_1648.py
  4. 20
      sapl/base/migrations/0026_auto_20181126_1727.py
  5. 8
      sapl/base/models.py
  6. 5
      sapl/base/templatetags/common_tags.py
  7. 26
      sapl/legacy/migracao_documentos.py
  8. 2
      sapl/legacy/scripts/exporta_zope/exporta_zope.py
  9. 13
      sapl/norma/fixtures/pre_popula_tipo_vinculo_norma.json
  10. 2
      sapl/norma/forms.py
  11. 2
      sapl/norma/migrations/0009_auto_20171113_1339.py
  12. 22
      sapl/norma/migrations/0016_tipovinculonormajuridica_revoga_integramente.py
  13. 3
      sapl/norma/models.py
  14. 17
      sapl/norma/views.py
  15. 1
      sapl/painel/views.py
  16. 2
      sapl/parlamentares/forms.py
  17. 1
      sapl/parlamentares/tests/test_parlamentares.py
  18. 2
      sapl/parlamentares/views.py
  19. 12
      sapl/relatorios/templates/pdf_pauta_sessao_gerar.py
  20. 1
      sapl/relatorios/templates/pdf_pauta_sessao_preparar_pysc.py
  21. 37
      sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
  22. 185
      sapl/relatorios/views.py
  23. 2
      sapl/rules/map_rules.py
  24. 96
      sapl/sessao/forms.py
  25. 50
      sapl/sessao/migrations/0028_auto_20181031_0902.py
  26. 27
      sapl/sessao/migrations/0030_auto_20181113_1149.py
  27. 21
      sapl/sessao/migrations/0031_auto_20181116_1849.py
  28. 16
      sapl/sessao/migrations/0032_merge_20181122_1527.py
  29. 65
      sapl/sessao/models.py
  30. 7
      sapl/sessao/urls.py
  31. 104
      sapl/sessao/views.py
  32. 2
      sapl/static/js/app.js
  33. 503
      sapl/static/styles/app.css
  34. 1136
      sapl/static/styles/compilacao.css
  35. 2
      sapl/templates/base.html
  36. 3
      sapl/templates/materia/proposicao_detail.html
  37. 3
      sapl/templates/menu_tabelas_auxiliares.yaml
  38. 2
      sapl/templates/norma/layouts.yaml
  39. 6
      sapl/templates/sessao/blocos_ata/lista_presenca.html
  40. 25
      sapl/templates/sessao/blocos_resumo/lista_presenca.html
  41. 10
      sapl/templates/sessao/layouts.yaml
  42. 6
      sapl/templates/sessao/retiradapauta_form.html
  43. 2
      sapl/templates/sessao/subnav.yaml
  44. 1
      sapl/templates/sistema.html
  45. 2
      setup.py

2
docker-compose.yml

@ -11,7 +11,7 @@ sapldb:
ports: ports:
- "5432:5432" - "5432:5432"
sapl: sapl:
image: interlegis/sapl:3.1.134 image: interlegis/sapl:3.1.137
restart: always restart: always
environment: environment:
ADMIN_PASSWORD: interlegis ADMIN_PASSWORD: interlegis

35
sapl/base/migrations/0024_auto_20181126_1534.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-26 17:34
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0023_auto_20181105_1804'),
]
operations = [
migrations.AlterField(
model_name='appconfig',
name='cronometro_aparte',
field=models.DurationField(blank=True, null=True, verbose_name='Cronômetro do Aparte'),
),
migrations.AlterField(
model_name='appconfig',
name='cronometro_consideracoes',
field=models.DurationField(blank=True, null=True, verbose_name='Cronômetro de Considerações Finais'),
),
migrations.AlterField(
model_name='appconfig',
name='cronometro_discurso',
field=models.DurationField(blank=True, null=True, verbose_name='Cronômetro do Discurso'),
),
migrations.AlterField(
model_name='appconfig',
name='cronometro_ordem',
field=models.DurationField(blank=True, null=True, verbose_name='Cronômetro da Ordem'),
),
]

21
sapl/base/migrations/0025_auto_20181126_1648.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-26 18:48
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0024_auto_20181126_1534'),
]
operations = [
migrations.AlterField(
model_name='appconfig',
name='cronometro_discurso',
field=models.DurationField(blank=True, default=datetime.timedelta(0, 2400), null=True, verbose_name='Cronômetro do Discurso'),
),
]

20
sapl/base/migrations/0026_auto_20181126_1727.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-26 19:27
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0025_auto_20181126_1648'),
]
operations = [
migrations.AlterField(
model_name='appconfig',
name='cronometro_discurso',
field=models.DurationField(blank=True, null=True, verbose_name='Cronômetro do Discurso'),
),
]

8
sapl/base/models.py

@ -121,22 +121,22 @@ class AppConfig(models.Model):
verbose_name=_('Quem deve assina a ata'), verbose_name=_('Quem deve assina a ata'),
max_length=1, choices=ASSINATURA_ATA_CHOICES, default='T') max_length=1, choices=ASSINATURA_ATA_CHOICES, default='T')
cronometro_discurso = models.TimeField( cronometro_discurso = models.DurationField(
verbose_name=_('Cronômetro do Discurso'), verbose_name=_('Cronômetro do Discurso'),
blank=True, blank=True,
null=True) null=True)
cronometro_aparte = models.TimeField( cronometro_aparte = models.DurationField(
verbose_name=_('Cronômetro do Aparte'), verbose_name=_('Cronômetro do Aparte'),
blank=True, blank=True,
null=True) null=True)
cronometro_ordem = models.TimeField( cronometro_ordem = models.DurationField(
verbose_name=_('Cronômetro da Ordem'), verbose_name=_('Cronômetro da Ordem'),
blank=True, blank=True,
null=True) null=True)
cronometro_consideracoes = models.TimeField( cronometro_consideracoes = models.DurationField(
verbose_name=_('Cronômetro de Considerações Finais'), verbose_name=_('Cronômetro de Considerações Finais'),
blank=True, blank=True,
null=True) null=True)

5
sapl/base/templatetags/common_tags.py

@ -229,10 +229,7 @@ def cronometro_to_seconds(value):
if not AppConfig.attr('cronometro_' + value): if not AppConfig.attr('cronometro_' + value):
return 0 return 0
m, s, x = AppConfig.attr( return AppConfig.attr('cronometro_' + value).seconds
'cronometro_' + value).isoformat().split(':')
return 60 * int(m) + int(s)
@register.filter @register.filter

26
sapl/legacy/migracao_documentos.py

@ -1,6 +1,6 @@
import os import os
import shutil
import re import re
import shutil
from glob import glob from glob import glob
from os.path import join from os.path import join
@ -189,3 +189,27 @@ def migrar_documentos(repo):
print('\n#### Encerrado ####\n\n' print('\n#### Encerrado ####\n\n'
'{} documentos sobraram sem ser migrados!!!'.format( '{} documentos sobraram sem ser migrados!!!'.format(
len(sobrando))) len(sobrando)))
def corrigir_documentos_para_existentes(repo):
for model, campos_bases in DOCS.items():
if model == Parlamentar:
continue
for campo, base_origem in campos_bases:
print('#### Corrigindo {} de {} ####'.format(campo,
model.__name__))
upload_to = model._meta.get_field(campo).upload_to
for obj in model.objects.all():
if getattr(obj, campo):
continue
dir_upload_to = os.path.join(
repo.working_dir, upload_to(obj, ''))
achados = glob(dir_upload_to + '*')
if achados:
assert len(achados) == 1, 'Mais de um doc achado'
[achado] = achados
destino = upload_to(obj, os.path.basename(achado))
print('-- {}'.format(destino))
setattr(obj, campo, destino)
obj.save()

2
sapl/legacy/scripts/exporta_zope/exporta_zope.py

@ -93,7 +93,7 @@ def br(obj):
def guess_extension(fullname, buffer): def guess_extension(fullname, buffer):
# um corte de apenas 1024 impediu a detecção correta de .docx # um corte de apenas 1024 impediu a detecção correta de .docx
mime = magic.from_buffer(buffer[:4096], mime=True) mime = magic.from_buffer(buffer, mime=True)
extensao = EXTENSOES.get(mime) extensao = EXTENSOES.get(mime)
if extensao is not None: if extensao is not None:
return extensao return extensao

13
sapl/norma/fixtures/pre_popula_tipo_vinculo_norma.json

@ -1,6 +1,7 @@
[ [
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Altera o(a)", "descricao_ativa": "Altera o(a)",
"descricao_passiva": "Alterado(a) pelo(a)", "descricao_passiva": "Alterado(a) pelo(a)",
"sigla": "A" "sigla": "A"
@ -10,6 +11,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "True",
"descricao_ativa": "Revoga integralmente o(a)", "descricao_ativa": "Revoga integralmente o(a)",
"descricao_passiva": "Revogado(a) integralmente pelo(a)", "descricao_passiva": "Revogado(a) integralmente pelo(a)",
"sigla": "R" "sigla": "R"
@ -19,6 +21,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Revoga parcialmente o(a)", "descricao_ativa": "Revoga parcialmente o(a)",
"descricao_passiva": "Revogado(a) parcialmente pelo(a)", "descricao_passiva": "Revogado(a) parcialmente pelo(a)",
"sigla": "P" "sigla": "P"
@ -28,6 +31,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "True",
"descricao_ativa": "Revoga integralmente por consolida\u00e7\u00e3o", "descricao_ativa": "Revoga integralmente por consolida\u00e7\u00e3o",
"descricao_passiva": "Revogado(a) integralmente por consolida\u00e7\u00e3o", "descricao_passiva": "Revogado(a) integralmente por consolida\u00e7\u00e3o",
"sigla": "T" "sigla": "T"
@ -37,6 +41,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Norma correlata", "descricao_ativa": "Norma correlata",
"descricao_passiva": "Norma correlata", "descricao_passiva": "Norma correlata",
"sigla": "C" "sigla": "C"
@ -46,6 +51,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Ressalva o(a)", "descricao_ativa": "Ressalva o(a)",
"descricao_passiva": "Ressalvada pelo(a)", "descricao_passiva": "Ressalvada pelo(a)",
"sigla": "S" "sigla": "S"
@ -55,6 +61,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Reedita o(a)", "descricao_ativa": "Reedita o(a)",
"descricao_passiva": "Reeditada pelo(a)", "descricao_passiva": "Reeditada pelo(a)",
"sigla": "E" "sigla": "E"
@ -64,6 +71,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Reedita com altera\u00e7\u00e3o o(a)", "descricao_ativa": "Reedita com altera\u00e7\u00e3o o(a)",
"descricao_passiva": "Reeditada com altera\u00e7\u00e3o pelo(a)", "descricao_passiva": "Reeditada com altera\u00e7\u00e3o pelo(a)",
"sigla": "I" "sigla": "I"
@ -73,6 +81,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Regulamenta o(a)", "descricao_ativa": "Regulamenta o(a)",
"descricao_passiva": "Regulamentada pelo(a)", "descricao_passiva": "Regulamentada pelo(a)",
"sigla": "G" "sigla": "G"
@ -82,6 +91,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Suspende parcialmente o(a)", "descricao_ativa": "Suspende parcialmente o(a)",
"descricao_passiva": "Suspenso(a) parcialmente pelo(a)", "descricao_passiva": "Suspenso(a) parcialmente pelo(a)",
"sigla": "K" "sigla": "K"
@ -91,6 +101,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Suspende integralmente o(a)", "descricao_ativa": "Suspende integralmente o(a)",
"descricao_passiva": "Suspenso(a) integralmente pelo(a)", "descricao_passiva": "Suspenso(a) integralmente pelo(a)",
"sigla": "L" "sigla": "L"
@ -100,6 +111,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Julga integralmente inconstitucional", "descricao_ativa": "Julga integralmente inconstitucional",
"descricao_passiva": "Julgada integralmente inconstitucional", "descricao_passiva": "Julgada integralmente inconstitucional",
"sigla": "N" "sigla": "N"
@ -109,6 +121,7 @@
}, },
{ {
"fields": { "fields": {
"revoga_integralmente": "False",
"descricao_ativa": "Julga parcialmente inconstitucional", "descricao_ativa": "Julga parcialmente inconstitucional",
"descricao_passiva": "Julgada parcialmente inconstitucional", "descricao_passiva": "Julgada parcialmente inconstitucional",
"sigla": "O" "sigla": "O"

2
sapl/norma/forms.py

@ -344,6 +344,8 @@ class NormaRelacionadaForm(ModelForm):
def save(self, commit=False): def save(self, commit=False):
relacionada = super(NormaRelacionadaForm, self).save(commit) relacionada = super(NormaRelacionadaForm, self).save(commit)
relacionada.norma_relacionada = self.cleaned_data['norma_relacionada'] relacionada.norma_relacionada = self.cleaned_data['norma_relacionada']
relacionada.norma_relacionada.data_vigencia = relacionada.norma_principal.data
relacionada.norma_relacionada.save()
relacionada.save() relacionada.save()
return relacionada return relacionada

2
sapl/norma/migrations/0009_auto_20171113_1339.py

@ -9,7 +9,7 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('norma', '0008_normajuridica_popula_tipo_vinculo_norma'), ('norma', '0007_auto_20170904_1708'),
] ]
operations = [ operations = [

22
sapl/norma/migrations/0008_normajuridica_popula_tipo_vinculo_norma.py → sapl/norma/migrations/0016_tipovinculonormajuridica_revoga_integramente.py

@ -1,14 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-23 14:51
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
from django.core.management import call_command from django.core.management import call_command
from django.db import migrations from django.db import migrations, models
def gera_tipo_vinculo(apps, schema_editor): def gera_tipo_vinculo(apps, schema_editor):
TipoVinculoNormaJuridica = apps.get_model("norma", "TipoVinculoNormaJuridica") TipoVinculoNormaJuridica = apps.get_model(
"norma", "TipoVinculoNormaJuridica")
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
tipo_vinculos = TipoVinculoNormaJuridica.objects.all().exists() tipo_vinculos = TipoVinculoNormaJuridica.objects.all().exists()
@ -22,18 +24,28 @@ def gera_tipo_vinculo(apps, schema_editor):
) )
) )
else: else:
fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures')) fixture_dir = os.path.abspath(os.path.join(
# pega tipo_vinculo_norma_juridica listados em fixtures/pre_popula_tipo_vinculo_norma.json os.path.dirname(__file__), '../fixtures'))
# pega tipo_vinculo_norma_juridica listados em
# fixtures/pre_popula_tipo_vinculo_norma.json
fixture_filename = 'pre_popula_tipo_vinculo_norma.json' fixture_filename = 'pre_popula_tipo_vinculo_norma.json'
fixture_file = os.path.join(fixture_dir, fixture_filename) fixture_file = os.path.join(fixture_dir, fixture_filename)
call_command('loaddata', fixture_file) call_command('loaddata', fixture_file)
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('norma', '0007_auto_20170904_1708'), ('norma', '0015_auto_20181109_1422'),
] ]
operations = [ operations = [
migrations.AddField(
model_name='tipovinculonormajuridica',
name='revoga_integralmente',
field=models.BooleanField(choices=[(
True, 'Sim'), (False, 'Não')], default=False, verbose_name='Revoga Integralmente?'),
),
migrations.RunPython(gera_tipo_vinculo), migrations.RunPython(gera_tipo_vinculo),
] ]

3
sapl/norma/models.py

@ -258,6 +258,9 @@ class TipoVinculoNormaJuridica(models.Model):
max_length=50, blank=True, verbose_name=_('Descrição Ativa')) max_length=50, blank=True, verbose_name=_('Descrição Ativa'))
descricao_passiva = models.CharField( descricao_passiva = models.CharField(
max_length=50, blank=True, verbose_name=_('Descrição Passiva')) max_length=50, blank=True, verbose_name=_('Descrição Passiva'))
revoga_integralmente = models.BooleanField(verbose_name=_('Revoga Integralmente?'),
choices=YES_NO_CHOICES,
default=False)
class Meta: class Meta:
verbose_name = _('Tipo de Vínculo entre Normas Jurídicas') verbose_name = _('Tipo de Vínculo entre Normas Jurídicas')

17
sapl/norma/views.py

@ -37,7 +37,7 @@ TipoNormaCrud = CrudAux.build(
list_field_names=['sigla', 'descricao', 'equivalente_lexml']) list_field_names=['sigla', 'descricao', 'equivalente_lexml'])
TipoVinculoNormaJuridicaCrud = CrudAux.build( TipoVinculoNormaJuridicaCrud = CrudAux.build(
TipoVinculoNormaJuridica, '', TipoVinculoNormaJuridica, '',
list_field_names=['sigla', 'descricao_ativa', 'descricao_passiva']) list_field_names=['sigla', 'descricao_ativa', 'descricao_passiva', 'revoga_integralmente'])
class NormaRelacionadaCrud(MasterDetailCrud): class NormaRelacionadaCrud(MasterDetailCrud):
@ -274,16 +274,19 @@ def recuperar_norma(request):
def recuperar_numero_norma(request): def recuperar_numero_norma(request):
tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo']) tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo'])
ano = request.GET.get('ano', '') ano = request.GET.get('ano', '')
param = {'tipo': tipo} param = {'tipo': tipo,
param['ano'] = ano if ano else timezone.now().year 'ano': ano if ano else timezone.now().year
}
norma = NormaJuridica.objects.filter(**param).order_by( norma = NormaJuridica.objects.filter(**param).order_by(
'tipo', 'ano', 'numero').values_list('numero', 'ano').last() 'tipo', 'ano', 'numero').values_list('numero', flat=True)
if norma: if norma:
response = JsonResponse({'numero': int(re.sub("[^0-9].*", '', norma[0])) + 1, numeros = sorted([int(re.sub("[^0-9].*", '', n)) for n in norma])
'ano': norma[1]}) next_num = numeros.pop() + 1
response = JsonResponse({'numero': next_num,
'ano': param['ano']})
else: else:
response = JsonResponse( response = JsonResponse(
{'numero': 1, 'ano': ano}) {'numero': 1, 'ano': param['ano']})
return response return response

1
sapl/painel/views.py

@ -340,7 +340,6 @@ def cronometro_painel(request):
def get_cronometro_status(request, name): def get_cronometro_status(request, name):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
username = request.user.username username = request.user.username
try: try:
logger.debug("user=" + username + ". Tentando obter cronometro.") logger.debug("user=" + username + ". Tentando obter cronometro.")
cronometro = request.session[name] cronometro = request.session[name]

2
sapl/parlamentares/forms.py

@ -136,7 +136,7 @@ class MandatoForm(ModelForm):
existe_mandato = Mandato.objects.filter( existe_mandato = Mandato.objects.filter(
parlamentar=data['parlamentar'], parlamentar=data['parlamentar'],
legislatura=data['legislatura']).exists() legislatura=data['legislatura']).exists()
if existe_mandato: if existe_mandato and data['titular']:
self.logger.error("Mandato nesta legislatura (parlamentar={}, legislatura={}) já existe." self.logger.error("Mandato nesta legislatura (parlamentar={}, legislatura={}) já existe."
.format(data['parlamentar'], data['legislatura'])) .format(data['parlamentar'], data['legislatura']))
raise ValidationError(_('Mandato nesta legislatura já existe.')) raise ValidationError(_('Mandato nesta legislatura já existe.'))

1
sapl/parlamentares/tests/test_parlamentares.py

@ -178,6 +178,7 @@ def test_mandato_form_duplicado():
'legislatura': str(legislatura.pk), 'legislatura': str(legislatura.pk),
'data_expedicao_diploma': '01/07/2015', 'data_expedicao_diploma': '01/07/2015',
'data_inicio_mandato': legislatura.data_inicio, 'data_inicio_mandato': legislatura.data_inicio,
'titular':True,
}) })
assert not form.is_valid() assert not form.is_valid()

2
sapl/parlamentares/views.py

@ -498,7 +498,7 @@ class ParlamentarCrud(Crud):
if legislatura_id >= 0: if legislatura_id >= 0:
return queryset.filter( return queryset.filter(
mandato__legislatura_id=legislatura_id).annotate( mandato__legislatura_id=legislatura_id).annotate(
mandato_titular=F('mandato__titular')) mandato_titular=F('mandato__titular')).distinct()
else: else:
try: try:
self.logger.debug("user=" + username + ". Tentando obter o mais recente registro do objeto Legislatura.") self.logger.debug("user=" + username + ". Tentando obter o mais recente registro do objeto Legislatura.")

12
sapl/relatorios/templates/pdf_pauta_sessao_gerar.py

@ -124,10 +124,10 @@ def expediente_materia(lst_expediente_materia):
for expediente_materia in lst_expediente_materia: for expediente_materia in lst_expediente_materia:
tmp += '<tr><td><para style="P3"><b>' + str(expediente_materia['num_ordem']) + '</b> - ' + \ tmp += '<tr><td><para style="P3"><b>' + str(expediente_materia['num_ordem']) + '</b> - ' + \
expediente_materia["tipo_materia"] + ' No. ' + \ expediente_materia["tipo_materia"] + ' No. ' + \
expediente_materia['id_materia'] + '</para>\n' + '<para style="P3"><b>Autor: </b>' + \ expediente_materia['id_materia'] + '</para>\n' + '<para style="P3"><b>' + expediente_materia['num_autores'] + ': </b>' + \
expediente_materia['nom_autor'] + '</para></td>\n' expediente_materia['nom_autor'] + '</para></td>\n'
txt_ementa = expediente_materia['txt_ementa'].replace('&', '&amp;') txt_ementa = expediente_materia['txt_ementa'].replace('&', '&amp;')
tmp += '<td><para style="P4">' + txt_ementa + '</para></td>\n' tmp += '<td><para style="P4">' + txt_ementa + '</para>' + '<para style="P4">' + expediente_materia['ordem_observacao'] + '</para></td>\n'
tmp += '<td><para style="P3">' + \ tmp += '<td><para style="P3">' + \
str(expediente_materia['des_situacao']) + '</para></td></tr>\n' str(expediente_materia['des_situacao']) + '</para></td></tr>\n'
@ -151,10 +151,10 @@ def votacao(lst_votacao):
votacao["tipo_materia"] + ' No. ' + \ votacao["tipo_materia"] + ' No. ' + \
str(votacao['id_materia']) + '</para>\n' + '<para style="P3"><b>Processo: </b>' + \ str(votacao['id_materia']) + '</para>\n' + '<para style="P3"><b>Processo: </b>' + \
str(votacao['des_numeracao']) + '</para>\n' + '<para style="P3"><b>Turno: </b>' + \ str(votacao['des_numeracao']) + '</para>\n' + '<para style="P3"><b>Turno: </b>' + \
str(votacao['des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + \ str(votacao['des_turno']) + '</para>\n' + '<para style="P3"><b>'+votacao['num_autores']+': </b>' + \
str(votacao['nom_autor']) + '</para></td>\n' str(votacao['nom_autor']) + '</para></td>\n'
tmp += '<td><para style="P4">' + \ txt_ementa = votacao['txt_ementa'].replace('&', '&amp;')
str(votacao['txt_ementa']) + '</para></td>\n' tmp += '<td><para style="P4">' + txt_ementa + '</para>' + '<para style="P4">' + votacao['ordem_observacao'] + '</para></td>\n'
tmp += '<td><para style="P3">' + \ tmp += '<td><para style="P3">' + \
str(votacao['des_situacao']) + '</para></td></tr>\n' str(votacao['des_situacao']) + '</para></td></tr>\n'
@ -162,7 +162,7 @@ def votacao(lst_votacao):
return tmp return tmp
def principal(cabecalho_dic, rodape_dic, sessao, imagem, inf_basicas_dic, lst_expediente_materia, lst_votacao): def principal(rodape_dic, imagem, inf_basicas_dic, lst_expediente_materia, lst_votacao):
""" """
""" """

1
sapl/relatorios/templates/pdf_pauta_sessao_preparar_pysc.py

@ -121,6 +121,7 @@ if context.REQUEST['data'] != '':
autoria = autoria[0] autoria = autoria[0]
autor = context.zsql.autor_obter_zsql( autor = context.zsql.autor_obter_zsql(
cod_autor=autoria.cod_autor) cod_autor=autoria.cod_autor)
if len(autor) > 0: if len(autor) > 0:
autor = autor[0] autor = autor[0]

37
sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py

@ -120,8 +120,6 @@ def inf_basicas(inf_basicas_dic):
tmp += '\t\t<para style="P2" spaceAfter="5"><b>Abertura: </b> ' + \ tmp += '\t\t<para style="P2" spaceAfter="5"><b>Abertura: </b> ' + \
dat_inicio_sessao + ' <b>- </b> ' + hr_inicio_sessao + '</para>\n' dat_inicio_sessao + ' <b>- </b> ' + hr_inicio_sessao + '</para>\n'
data_fim_sessao = dat_fim_sessao + ' <b>- </b> ' if dat_fim_sessao else ''
tmp += '\t\t<para style="P2" spaceAfter="5"><b>Encerramento: </b> ' + \ tmp += '\t\t<para style="P2" spaceAfter="5"><b>Encerramento: </b> ' + \
dat_fim_sessao + ' <b>- </b> ' + hr_fim_sessao + '</para>\n' dat_fim_sessao + ' <b>- </b> ' + hr_fim_sessao + '</para>\n'
@ -144,7 +142,7 @@ def mesa(lst_mesa):
return tmp return tmp
def presenca(lst_presenca_sessao): def presenca(lst_presenca_sessao,lst_ausencia_sessao):
""" """
""" """
@ -157,6 +155,19 @@ def presenca(lst_presenca_sessao):
tmp += '\t\t<para style="P2" spaceAfter="5">' + \ tmp += '\t\t<para style="P2" spaceAfter="5">' + \
str(presenca['nom_parlamentar']) + '/' + \ str(presenca['nom_parlamentar']) + '/' + \
str(presenca['sgl_partido']) + '</para>\n' str(presenca['sgl_partido']) + '</para>\n'
tmp += '\t\t<para style="P1">Justificativas de Ausência da Sessão</para>\n'
tmp += '\t\t<para style="P2">\n'
tmp += '\t\t\t<font color="white"> <br/></font>\n'
tmp += '\t\t</para>\n'
tmp += '<blockTable style="repeater" repeatRows="1">\n'
tmp += '<tr><td >Parlamentar</td><td>Justificativa</td><td>Ausente em</td></tr>\n'
for ausencia in lst_ausencia_sessao:
tmp += '<tr><td>' + \
str(ausencia['parlamentar']) + '</td><td> ' + \
str(ausencia['justificativa']) + '</td><td>' + \
str(ausencia['tipo']) + '</td></tr>\n'
tmp += '</blockTable>'
return tmp return tmp
@ -169,7 +180,7 @@ def expedientes(lst_expedientes):
tmp += '\t\t<para style="P2">\n' tmp += '\t\t<para style="P2">\n'
tmp += '\t\t\t<font color="white"> </font>\n' tmp += '\t\t\t<font color="white"> </font>\n'
tmp += '\t\t</para>\n' tmp += '\t\t</para>\n'
for idx, expediente in enumerate(lst_expedientes): for expediente in lst_expedientes:
tmp += '\t\t<para style="P2"><b>' + '<br/> ' + \ tmp += '\t\t<para style="P2"><b>' + '<br/> ' + \
expediente['nom_expediente'] + ': </b></para>\n' + \ expediente['nom_expediente'] + ': </b></para>\n' + \
'<para style="P3">' + \ '<para style="P3">' + \
@ -191,10 +202,10 @@ def expediente_materia(lst_expediente_materia):
tmp += '<blockTable style="repeater" repeatRows="1">\n' tmp += '<blockTable style="repeater" repeatRows="1">\n'
tmp += '<tr><td >Matéria</td><td>Ementa</td><td>Resultado da Votação</td></tr>\n' tmp += '<tr><td >Matéria</td><td>Ementa</td><td>Resultado da Votação</td></tr>\n'
for expediente_materia in lst_expediente_materia: for expediente_materia in lst_expediente_materia:
tmp += '<tr><td><para style="P3"><b>' + str(expediente_materia['num_ordem']) + '</b> - ' + expediente_materia['id_materia'] + '</para>\n' + '<para style="P3"><b>Turno: </b>' + str(expediente_materia[ tmp += '<tr><td><para style="P3"><b>' + str(expediente_materia['num_ordem']) + '</b> - ' + expediente_materia['id_materia'] + '</para>\n' + '<para style="P3"><b>Turno: </b>' + expediente_materia[
'des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + str(expediente_materia['nom_autor']) + '</para></td>\n' 'des_turno'] + '</para>\n' + '<para style="P3"><b>'+ expediente_materia['num_autores'] + ': </b>' + str(expediente_materia['nom_autor']) + '</para></td>\n'
txt_ementa = expediente_materia['txt_ementa'].replace('&', '&amp;') txt_ementa = expediente_materia['txt_ementa'].replace('&', '&amp;')
tmp += '<td><para style="P4">' + txt_ementa + '</para></td>\n' tmp += '<td><para style="P4">' + txt_ementa + '</para>' + '<para style="P4">' + expediente_materia['ordem_observacao'] + '</para></td>\n'
tmp += '<td><para style="P3"><b>' + \ tmp += '<td><para style="P3"><b>' + \
str(expediente_materia['nom_resultado']) + \ str(expediente_materia['nom_resultado']) + \
'</b></para>\n' + '<para style="P3">' '</b></para>\n' + '<para style="P3">'
@ -254,8 +265,8 @@ def votacao(lst_votacao):
tmp += '<blockTable style="repeater" repeatRows="1">\n' tmp += '<blockTable style="repeater" repeatRows="1">\n'
tmp += '<tr><td >Matéria</td><td>Ementa</td><td>Resultado da Votação</td></tr>\n' tmp += '<tr><td >Matéria</td><td>Ementa</td><td>Resultado da Votação</td></tr>\n'
for votacao in lst_votacao: for votacao in lst_votacao:
tmp += '<tr><td><para style="P3"><b>' + str(votacao['num_ordem']) + '</b> - ' + votacao['id_materia'] + '</para>\n' + '<para style="P3"><b>Turno:</b> ' + str(votacao[ tmp += '<tr><td><para style="P3"><b>' + str(votacao['num_ordem']) + '</b> - ' + votacao['id_materia'] + '</para>\n' + '<para style="P3"><b>Turno:</b> ' + votacao[
'des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + str(votacao['nom_autor']) + '</para></td>\n' 'des_turno'] + '</para>\n' + '<para style="P3"><b>'+ votacao['num_autores'] +': </b>' + str(votacao['nom_autor']) + '</para></td>\n'
txt_ementa = votacao['txt_ementa'].replace('&', '&amp;') txt_ementa = votacao['txt_ementa'].replace('&', '&amp;')
tmp += '<td><para style="P4">' + txt_ementa + '</para>' + '<para style="P4">' + votacao['ordem_observacao'] + '</para></td>\n' tmp += '<td><para style="P4">' + txt_ementa + '</para>' + '<para style="P4">' + votacao['ordem_observacao'] + '</para></td>\n'
tmp += '<td><para style="P3"><b>' + \ tmp += '<td><para style="P3"><b>' + \
@ -296,7 +307,7 @@ def ocorrencias(lst_ocorrencias):
tmp += '\t\t<para style="P2">\n' tmp += '\t\t<para style="P2">\n'
tmp += '\t\t\t<font color="white"> </font>\n' tmp += '\t\t\t<font color="white"> </font>\n'
tmp += '\t\t</para>\n' tmp += '\t\t</para>\n'
for idx, ocorrencia in enumerate(lst_ocorrencias): for ocorrencia in lst_ocorrencias:
tmp += '\t\t<para style="P3">' + \ tmp += '\t\t<para style="P3">' + \
str(ocorrencia.conteudo) + '</para>\n' str(ocorrencia.conteudo) + '</para>\n'
tmp += '\t\t<para style="P2">\n' tmp += '\t\t<para style="P2">\n'
@ -305,7 +316,7 @@ def ocorrencias(lst_ocorrencias):
return tmp return tmp
def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_mesa, lst_presenca_sessao, lst_expedientes, lst_expediente_materia, lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, lst_oradores, lst_ocorrencias): def principal(rodape_dic, imagem, inf_basicas_dic, lst_mesa, lst_presenca_sessao, lst_ausencia_sessao, lst_expedientes, lst_expediente_materia, lst_oradores_expediente, lst_presenca_ordem_dia, lst_votacao, lst_oradores, lst_ocorrencias):
""" """
""" """
arquivoPdf = str(int(time.time() * 100)) + ".pdf" arquivoPdf = str(int(time.time() * 100)) + ".pdf"
@ -331,7 +342,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me
'cont_mult': '', 'cont_mult': '',
'exp': expedientes(lst_expedientes), 'exp': expedientes(lst_expedientes),
'id_basica': inf_basicas(inf_basicas_dic), 'id_basica': inf_basicas(inf_basicas_dic),
'lista_p': presenca(lst_presenca_sessao), 'lista_p': presenca(lst_presenca_sessao,lst_ausencia_sessao),
'lista_p_o_d': presenca_ordem_dia(lst_presenca_ordem_dia), 'lista_p_o_d': presenca_ordem_dia(lst_presenca_ordem_dia),
'mat_exp': expediente_materia(lst_expediente_materia), 'mat_exp': expediente_materia(lst_expediente_materia),
'mat_o_d': votacao(lst_votacao), 'mat_o_d': votacao(lst_votacao),
@ -357,7 +368,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me
else: else:
tmp += inf_basicas(inf_basicas_dic) tmp += inf_basicas(inf_basicas_dic)
tmp += mesa(lst_mesa) tmp += mesa(lst_mesa)
tmp += presenca(lst_presenca_sessao) tmp += presenca(lst_presenca_sessao,lst_ausencia_sessao)
tmp += expedientes(lst_expedientes) tmp += expedientes(lst_expedientes)
tmp += expediente_materia(lst_expediente_materia) tmp += expediente_materia(lst_expediente_materia)
tmp += oradores_expediente(lst_oradores_expediente) tmp += oradores_expediente(lst_oradores_expediente)

185
sapl/relatorios/views.py

@ -16,11 +16,12 @@ from sapl.parlamentares.models import CargoMesa, Filiacao, Parlamentar
from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo, from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo,
TramitacaoAdministrativo) TramitacaoAdministrativo)
from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao, from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao,
IntegranteMesa, Orador, OradorExpediente, IntegranteMesa, JustificativaAusencia,
Orador, OradorExpediente,
OrdemDia, PresencaOrdemDia, SessaoPlenaria, OrdemDia, PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, OcorrenciaSessao) SessaoPlenariaPresenca, OcorrenciaSessao)
from sapl.settings import STATIC_ROOT from sapl.settings import STATIC_ROOT
from sapl.utils import LISTA_DE_UFS, ExtraiTag, TrocaTag, filiacao_data from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data
from .templates import (pdf_capa_processo_gerar, from .templates import (pdf_capa_processo_gerar,
pdf_documento_administrativo_gerar, pdf_espelho_gerar, pdf_documento_administrativo_gerar, pdf_espelho_gerar,
@ -538,6 +539,20 @@ def get_sessao_plenaria(sessao, casa):
dic_presenca['sgl_partido'] = partido_sigla dic_presenca['sgl_partido'] = partido_sigla
lst_presenca_sessao.append(dic_presenca) lst_presenca_sessao.append(dic_presenca)
# Lista de ausencias na sessão
lst_ausencia_sessao = []
ausencia = JustificativaAusencia.objects.filter(
sessao_plenaria=sessao).order_by('parlamentar__nome_parlamentar')
for ausente in ausencia:
dic_ausencia = {}
dic_ausencia['parlamentar'] = ausente.parlamentar
dic_ausencia['justificativa'] = ausente.tipo_ausencia
if ausente.ausencia == 1:
dic_ausencia['tipo'] = 'Matéria'
else:
dic_ausencia['tipo'] = 'Sessão'
lst_ausencia_sessao.append(dic_ausencia)
# Exibe os Expedientes # Exibe os Expedientes
lst_expedientes = [] lst_expedientes = []
@ -572,9 +587,7 @@ def get_sessao_plenaria(sessao, casa):
for expediente_materia in ExpedienteMateria.objects.filter( for expediente_materia in ExpedienteMateria.objects.filter(
sessao_plenaria=sessao): sessao_plenaria=sessao):
# seleciona os detalhes de uma matéria # seleciona os detalhes de uma matéria
materia = MateriaLegislativa.objects.filter( materia = expediente_materia.materia
id=expediente_materia.materia.id).first()
dic_expediente_materia = {} dic_expediente_materia = {}
dic_expediente_materia["num_ordem"] = expediente_materia.numero_ordem dic_expediente_materia["num_ordem"] = expediente_materia.numero_ordem
dic_expediente_materia["id_materia"] = (materia.tipo.sigla + ' ' + dic_expediente_materia["id_materia"] = (materia.tipo.sigla + ' ' +
@ -585,40 +598,27 @@ def get_sessao_plenaria(sessao, casa):
numeracao = Numeracao.objects.filter( numeracao = Numeracao.objects.filter(
materia=expediente_materia.materia).first() materia=expediente_materia.materia).first()
if numeracao is not None: if numeracao:
dic_expediente_materia["des_numeracao"] = ( dic_expediente_materia["des_numeracao"] = (
str(numeracao.numero_materia) + '/' + str( str(numeracao.numero_materia) + '/' + str(
numeracao.ano_materia)) numeracao.ano_materia))
turno, _ = get_turno(dic_expediente_materia, materia, sessao.data_inicio) turno, _ = get_turno(materia)
dic_expediente_materia["des_turno"] = turno dic_expediente_materia["des_turno"] = turno
dic_expediente_materia["txt_ementa"] = str(materia.ementa) dic_expediente_materia["txt_ementa"] = str(materia.ementa)
dic_expediente_materia["ordem_observacao"] = expediente_materia.observacao dic_expediente_materia["ordem_observacao"] = expediente_materia.observacao
dic_expediente_materia["nom_autor"] = ' '
dic_expediente_materia["nom_resultado"] = '' dic_expediente_materia["nom_resultado"] = ''
autoria = Autoria.objects.filter( dic_expediente_materia["nom_autor"] = ''
materia=materia, primeiro_autor=True).first() autoria = materia.autoria_set.all()
dic_expediente_materia['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
if autoria is not None: if autoria:
autor = Autor.objects.filter(id=autoria.autor.id) for a in autoria:
if a.autor.nome:
if autor is not None: dic_expediente_materia['nom_autor'] += a.autor.nome + ', '
autor = autor.first() dic_expediente_materia['nom_autor'] = dic_expediente_materia['nom_autor'][:-2]
if autor.tipo == 'Parlamentar':
parlamentar = Parlamentar.objects.filter(
id=autor.parlamentar.id)
dic_expediente_materia["nom_autor"] = str(
parlamentar.nome_completo)
elif autor.tipo == 'Comissao':
comissao = Comissao.objects.filter(id=autor.comissao.id)
dic_expediente_materia["nom_autor"] = str(comissao)
else: else:
dic_expediente_materia["nom_autor"] = str(autor.nome)
elif autoria is None:
dic_expediente_materia["nom_autor"] = 'Desconhecido' dic_expediente_materia["nom_autor"] = 'Desconhecido'
dic_expediente_materia["votacao_observacao"] = ' ' dic_expediente_materia["votacao_observacao"] = ' '
@ -674,9 +674,7 @@ def get_sessao_plenaria(sessao, casa):
for votacao in OrdemDia.objects.filter( for votacao in OrdemDia.objects.filter(
sessao_plenaria=sessao): sessao_plenaria=sessao):
# seleciona os detalhes de uma matéria # seleciona os detalhes de uma matéria
materia = MateriaLegislativa.objects.filter( materia = votacao.materia
id=votacao.materia.id).first()
dic_votacao = {} dic_votacao = {}
dic_votacao["nom_resultado"] = '' dic_votacao["nom_resultado"] = ''
dic_votacao["num_ordem"] = votacao.numero_ordem dic_votacao["num_ordem"] = votacao.numero_ordem
@ -687,15 +685,15 @@ def get_sessao_plenaria(sessao, casa):
str(materia.ano)) str(materia.ano))
dic_votacao["des_numeracao"] = ' ' dic_votacao["des_numeracao"] = ' '
numeracao = Numeracao.objects.filter( numeracao = materia.numeracao_set.first()
materia=votacao.materia).first() if numeracao:
if numeracao is not None:
dic_votacao["des_numeracao"] = ( dic_votacao["des_numeracao"] = (
str(numeracao.numero_materia) + str(numeracao.numero_materia) +
'/' + '/' +
str(numeracao.ano_materia)) str(numeracao.ano_materia))
turno, _ = get_turno(dic_votacao, materia, sessao.data_inicio) turno, _ = get_turno(materia)
dic_votacao["des_turno"] = turno dic_votacao["des_turno"] = turno
@ -703,26 +701,15 @@ def get_sessao_plenaria(sessao, casa):
dic_votacao["txt_ementa"] = html.unescape(materia.ementa) dic_votacao["txt_ementa"] = html.unescape(materia.ementa)
dic_votacao["ordem_observacao"] = html.unescape(votacao.observacao) dic_votacao["ordem_observacao"] = html.unescape(votacao.observacao)
dic_votacao["nom_autor"] = ' ' dic_votacao["nom_autor"] = ''
autoria = Autoria.objects.filter( autoria = materia.autoria_set.all()
materia=materia, primeiro_autor=True).first() dic_votacao['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
if autoria:
if autoria is not None: for a in autoria:
autor = Autor.objects.filter(id=autoria.autor.id) if a.autor.nome:
if autor is not None: dic_votacao['nom_autor'] += a.autor.nome + ', '
autor = autor.first() dic_votacao['nom_autor'] = dic_votacao['nom_autor'][:-2]
if autor.tipo == 'Parlamentar':
parlamentar = Parlamentar.objects.filter(
id=autor.parlamentar.id)
dic_votacao["nom_autor"] = str(parlamentar.nome_completo)
elif autor.tipo == 'Comissao':
comissao = Comissao.objects.filter(
id=autor.comissao.id)
dic_votacao["nom_autor"] = str(comissao)
else: else:
dic_votacao["nom_autor"] = str(autor.nome)
elif autoria is None:
dic_votacao["nom_autor"] = 'Desconhecido' dic_votacao["nom_autor"] = 'Desconhecido'
dic_votacao["votacao_observacao"] = ' ' dic_votacao["votacao_observacao"] = ' '
@ -779,6 +766,7 @@ def get_sessao_plenaria(sessao, casa):
return (inf_basicas_dic, return (inf_basicas_dic,
lst_mesa, lst_mesa,
lst_presenca_sessao, lst_presenca_sessao,
lst_ausencia_sessao,
lst_expedientes, lst_expedientes,
lst_expediente_materia, lst_expediente_materia,
lst_oradores_expediente, lst_oradores_expediente,
@ -788,20 +776,19 @@ def get_sessao_plenaria(sessao, casa):
lst_ocorrencias) lst_ocorrencias)
def get_turno(dic, materia, sessao_data_inicio): def get_turno(materia):
descricao_turno = ' ' descricao_turno = ''
descricao_tramitacao = ' ' descricao_tramitacao = ''
tramitacao = None
if tramitacao is None:
tramitacao = materia.tramitacao_set.last() tramitacao = materia.tramitacao_set.last()
if tramitacao is not None: if tramitacao:
if tramitacao.turno:
for t in Tramitacao.TURNO_CHOICES: for t in Tramitacao.TURNO_CHOICES:
if t[0] == tramitacao.turno: if t[0] == tramitacao.turno:
descricao_turno = t[1] descricao_turno = str(t[1])
break break
descricao_tramitacao = tramitacao.status.descricao if tramitacao.status else 'Não informada' descricao_tramitacao = tramitacao.status.descricao if tramitacao.status else 'Não informada'
return (descricao_turno, descricao_tramitacao) return descricao_turno, descricao_tramitacao
def relatorio_sessao_plenaria(request, pk): def relatorio_sessao_plenaria(request, pk):
@ -819,7 +806,6 @@ def relatorio_sessao_plenaria(request, pk):
if not casa: if not casa:
raise Http404 raise Http404
cabecalho = get_cabecalho(casa)
rodape = get_rodape(casa) rodape = get_rodape(casa)
imagem = get_imagem(casa) imagem = get_imagem(casa)
@ -833,6 +819,7 @@ def relatorio_sessao_plenaria(request, pk):
(inf_basicas_dic, (inf_basicas_dic,
lst_mesa, lst_mesa,
lst_presenca_sessao, lst_presenca_sessao,
lst_ausencia_sessao,
lst_expedientes, lst_expedientes,
lst_expediente_materia, lst_expediente_materia,
lst_oradores_expediente, lst_oradores_expediente,
@ -849,13 +836,12 @@ def relatorio_sessao_plenaria(request, pk):
lst_expedientes[idx]['txt_expediente'] = txt_expedientes lst_expedientes[idx]['txt_expediente'] = txt_expedientes
pdf = pdf_sessao_plenaria_gerar.principal( pdf = pdf_sessao_plenaria_gerar.principal(
cabecalho,
rodape, rodape,
imagem, imagem,
None,
inf_basicas_dic, inf_basicas_dic,
lst_mesa, lst_mesa,
lst_presenca_sessao, lst_presenca_sessao,
lst_ausencia_sessao,
lst_expedientes, lst_expedientes,
lst_expediente_materia, lst_expediente_materia,
lst_oradores_expediente, lst_oradores_expediente,
@ -1048,7 +1034,6 @@ def relatorio_pauta_sessao(request, pk):
casa = CasaLegislativa.objects.first() casa = CasaLegislativa.objects.first()
cabecalho = get_cabecalho(casa)
rodape = get_rodape(casa) rodape = get_rodape(casa)
imagem = get_imagem(casa) imagem = get_imagem(casa)
@ -1056,9 +1041,7 @@ def relatorio_pauta_sessao(request, pk):
lst_expediente_materia, lst_votacao, inf_basicas_dic = get_pauta_sessao( lst_expediente_materia, lst_votacao, inf_basicas_dic = get_pauta_sessao(
sessao, casa) sessao, casa)
pdf = pdf_pauta_sessao_gerar.principal(cabecalho, pdf = pdf_pauta_sessao_gerar.principal(rodape,
rodape,
sessao,
imagem, imagem,
inf_basicas_dic, inf_basicas_dic,
lst_expediente_materia, lst_expediente_materia,
@ -1083,8 +1066,7 @@ def get_pauta_sessao(sessao, casa):
inf_basicas_dic["nom_camara"] = casa.nome inf_basicas_dic["nom_camara"] = casa.nome
lst_expediente_materia = [] lst_expediente_materia = []
for expediente_materia in ExpedienteMateria.objects.filter( for expediente_materia in ExpedienteMateria.objects.filter(sessao_plenaria=sessao):
data_ordem=sessao.data_inicio, sessao_plenaria=sessao):
materia = MateriaLegislativa.objects.filter( materia = MateriaLegislativa.objects.filter(
id=expediente_materia.materia.id).first() id=expediente_materia.materia.id).first()
@ -1102,34 +1084,22 @@ def get_pauta_sessao(sessao, casa):
dic_expediente_materia["des_numeracao"] = ' ' dic_expediente_materia["des_numeracao"] = ' '
numeracao = Numeracao.objects.filter(materia=materia) numeracao = Numeracao.objects.filter(materia=materia)
if numeracao is not None: if numeracao:
numeracao = numeracao.first() numeracao = numeracao.first()
dic_expediente_materia["des_numeracao"] = str(numeracao) dic_expediente_materia["des_numeracao"] = str(numeracao)
dic_expediente_materia["nom_autor"] = ' ' dic_expediente_materia["nom_autor"] = ''
autoria = Autoria.objects.filter( autoria = materia.autoria_set.all()
materia=materia, primeiro_autor=True).first() dic_expediente_materia['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
if autoria:
if autoria is not None: for a in autoria:
autor = Autor.objects.filter(id=autoria.autor.id) if a.autor.nome:
dic_expediente_materia['nom_autor'] += a.autor.nome + ', '
if autor is not None: dic_expediente_materia['nom_autor'] = dic_expediente_materia['nom_autor'][:-2]
autor = autor.first()
if autor.tipo == 'Parlamentar':
parlamentar = Parlamentar.objects.filter(
id=autor.parlamentar.id)
dic_expediente_materia["nom_autor"] = str(
parlamentar.nome_completo)
elif autor.tipo == 'Comissao':
comissao = Comissao.objects.filter(id=autor.comissao.id)
dic_expediente_materia["nom_autor"] = str(comissao)
else: else:
dic_expediente_materia["nom_autor"] = str(autor.nome)
elif autoria is None:
dic_expediente_materia["nom_autor"] = 'Desconhecido' dic_expediente_materia["nom_autor"] = 'Desconhecido'
turno, tramitacao = get_turno(dic_expediente_materia, materia, sessao.data_inicio) turno, tramitacao = get_turno(materia)
dic_expediente_materia["des_turno"] = turno dic_expediente_materia["des_turno"] = turno
dic_expediente_materia["des_situacao"] = tramitacao dic_expediente_materia["des_situacao"] = tramitacao
@ -1156,30 +1126,19 @@ def get_pauta_sessao(sessao, casa):
dic_votacao["des_numeracao"] = str( dic_votacao["des_numeracao"] = str(
numeracao.numero_materia) + '/' + str(numeracao.ano_materia) numeracao.numero_materia) + '/' + str(numeracao.ano_materia)
turno, tramitacao = get_turno(dic_votacao, materia, sessao.data_inicio) turno, tramitacao = get_turno(materia)
dic_votacao["des_turno"] = turno dic_votacao["des_turno"] = turno
dic_votacao["des_situacao"] = tramitacao dic_votacao["des_situacao"] = tramitacao
dic_votacao["nom_autor"] = ' ' dic_votacao["nom_autor"] = ''
autoria = Autoria.objects.filter( autoria = materia.autoria_set.all()
materia=materia, primeiro_autor=True).first() dic_votacao['num_autores'] = 'Autores' if len(autoria) > 1 else 'Autor'
if autoria:
if autoria is not None: for a in autoria:
autor = Autor.objects.filter(id=autoria.autor.id) if a.autor.nome:
if autor is not None: dic_votacao['nom_autor'] += a.autor.nome + ', '
autor = autor.first() dic_votacao['nom_autor'] = dic_votacao['nom_autor'][:-2]
if autor.tipo == 'Parlamentar':
parlamentar = Parlamentar.objects.filter(
id=autor.parlamentar.id)
dic_votacao["nom_autor"] = str(parlamentar.nome_completo)
elif autor.tipo == 'Comissao':
comissao = Comissao.objects.filter(
id=autor.comissao.id)
dic_votacao["nom_autor"] = str(comissao)
else: else:
dic_votacao["nom_autor"] = str(autor.nome)
elif autoria is None:
dic_votacao["nom_autor"] = 'Desconhecido' dic_votacao["nom_autor"] = 'Desconhecido'
lst_votacao.append(dic_votacao) lst_votacao.append(dic_votacao)

2
sapl/rules/map_rules.py

@ -172,6 +172,7 @@ rules_group_sessao = {
(sessao.RegistroVotacao, __base__), (sessao.RegistroVotacao, __base__),
(sessao.VotoParlamentar, __base__), (sessao.VotoParlamentar, __base__),
(sessao.JustificativaAusencia, __base__), (sessao.JustificativaAusencia, __base__),
(sessao.RetiradaPauta, __base__)
] ]
} }
@ -269,6 +270,7 @@ rules_group_geral = {
(sessao.JustificativaAusencia, __base__), (sessao.JustificativaAusencia, __base__),
(sessao.Bloco, __base__), (sessao.Bloco, __base__),
(sessao.ResumoOrdenacao, __base__), (sessao.ResumoOrdenacao, __base__),
(sessao.TipoRetiradaPauta, __base__),
(lexml.LexmlProvedor, __base__), (lexml.LexmlProvedor, __base__),
(lexml.LexmlPublicador, __base__), (lexml.LexmlPublicador, __base__),

96
sapl/sessao/forms.py

@ -27,7 +27,7 @@ from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES,
from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia, from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia,
Orador, OradorExpediente, OrdemDia, SessaoPlenaria, Orador, OradorExpediente, OrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao, SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao,
OcorrenciaSessao, RegistroVotacao) OcorrenciaSessao, RegistroVotacao, RetiradaPauta, TipoRetiradaPauta)
def recupera_anos(): def recupera_anos():
@ -191,6 +191,100 @@ class SessaoPlenariaForm(ModelForm):
return self.cleaned_data return self.cleaned_data
class RetiradaPautaForm(ModelForm):
tipo_de_retirada = forms.ModelChoiceField(required=True,
empty_label='------------',
queryset=TipoRetiradaPauta.objects.all())
expediente = forms.ModelChoiceField(required=False,
label='Matéria do Expediente',
queryset=ExpedienteMateria.objects.all())
ordem = forms.ModelChoiceField(required=False,
label='Matéria da Ordem do Dia',
queryset=OrdemDia.objects.all())
materia = forms.ModelChoiceField(required=False,
widget=forms.HiddenInput(),
queryset=MateriaLegislativa.objects.all())
class Meta:
model = RetiradaPauta
fields = ['ordem',
'expediente',
'parlamentar',
'tipo_de_retirada',
'data',
'observacao',
'materia']
def __init__(self, *args, **kwargs):
row1 = to_row([('tipo_de_retirada', 5),
('parlamentar', 4),
('data', 3)])
row2 = to_row([('ordem', 6),
('expediente', 6)])
row3 = to_row([('observacao',12)])
self.helper = FormHelper()
self.helper.layout = SaplFormLayout(
Fieldset(_('Retirada de Pauta'),
row1, row2, row3))
q = Q(sessao_plenaria=kwargs['initial']['sessao_plenaria'])
ordens = OrdemDia.objects.filter(q)
expedientes = ExpedienteMateria.objects.filter(q)
retiradas_ordem = [r.ordem for r in RetiradaPauta.objects.filter(q, ordem__in=ordens)]
retiradas_expediente = [r.expediente for r in RetiradaPauta.objects.filter(q, expediente__in=expedientes)]
setOrdem = set(ordens) - set(retiradas_ordem)
setExpediente = set(expedientes) - set(retiradas_expediente)
super(RetiradaPautaForm, self).__init__(
*args, **kwargs)
if self.instance.pk:
setOrdem = set(ordens)
setExpediente = set(expedientes)
presencas = SessaoPlenariaPresenca.objects.filter(
q).order_by('parlamentar__nome_parlamentar')
presentes = [p.parlamentar for p in presencas]
self.fields['expediente'].choices = [
(None, "------------")] + [(e.id, e.materia) for e in setExpediente]
self.fields['ordem'].choices = [
(None, "------------")] + [(o.id, o.materia) for o in setOrdem]
self.fields['parlamentar'].choices = [
(None, "------------")] + [(p.id, p) for p in presentes]
def clean(self):
super(RetiradaPautaForm, self).clean()
if not self.is_valid():
return self.cleaned_data
sessao_plenaria = self.instance.sessao_plenaria
if self.cleaned_data['data'] < sessao_plenaria.data_inicio:
raise ValidationError(_("Data de retirada de pauta anterior à abertura da Sessão."))
if sessao_plenaria.data_fim and self.cleaned_data['data'] > sessao_plenaria.data_fim:
raise ValidationError(_("Data de retirada de pauta posterior ao encerramento da Sessão."))
if self.cleaned_data['ordem'] and self.cleaned_data['ordem'].registrovotacao_set.exists():
raise ValidationError(_("Essa matéria já foi votada, portanto não pode ser retirada de pauta."))
elif self.cleaned_data['expediente'] and self.cleaned_data['expediente'].registrovotacao_set.exists():
raise ValidationError(_("Essa matéria já foi votada, portanto não pode ser retirada de pauta."))
return self.cleaned_data
def save(self, commit=False):
retirada = super(RetiradaPautaForm, self).save(commit=False)
if retirada.ordem:
retirada.materia = retirada.ordem.materia
elif retirada.expediente:
retirada.materia = retirada.expediente.materia
retirada.save()
return retirada
class BancadaForm(ModelForm): class BancadaForm(ModelForm):
class Meta: class Meta:

50
sapl/sessao/migrations/0028_auto_20181031_0902.py

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-10-31 12:02
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('materia', '0032_auto_20181022_1743'),
('parlamentares', '0025_auto_20180924_1724'),
('sessao', '0029_auto_20181024_0952'),
]
operations = [
migrations.CreateModel(
name='RetiradaPauta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('observacao', models.TextField(blank=True, verbose_name='Observações')),
('expediente', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.ExpedienteMateria')),
('materia', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa')),
('ordem', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.OrdemDia')),
('parlamentar', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Parlamentar', verbose_name='Requerente')),
],
options={
'verbose_name_plural': 'Retirada de Pauta',
'verbose_name': 'Retirada de Pauta',
},
),
migrations.CreateModel(
name='TipoRetiradaPauta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('descricao', models.CharField(max_length=150, verbose_name='Descrição')),
],
options={
'verbose_name_plural': 'Tipos de Retirada de Pauta',
'verbose_name': 'Tipo de Retidara de Pauta',
'ordering': ['descricao'],
},
),
migrations.AddField(
model_name='retiradapauta',
name='tipo_de_retirada',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sessao.TipoRetiradaPauta', verbose_name='Motivo de Retirada de Pauta'),
),
]

27
sapl/sessao/migrations/0030_auto_20181113_1149.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-13 13:49
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('sessao', '0028_auto_20181031_0902'),
]
operations = [
migrations.AddField(
model_name='retiradapauta',
name='data',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Data'),
),
migrations.AddField(
model_name='retiradapauta',
name='sessao_plenaria',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.SessaoPlenaria', verbose_name='Sessão Plenária'),
),
]

21
sapl/sessao/migrations/0031_auto_20181116_1849.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-16 20:49
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sessao', '0030_auto_20181113_1149'),
]
operations = [
migrations.AlterField(
model_name='retiradapauta',
name='materia',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa', verbose_name='Matéria'),
),
]

16
sapl/sessao/migrations/0032_merge_20181122_1527.py

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-22 17:27
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sessao', '0031_auto_20181116_1849'),
('sessao', '0031_auto_20181119_1103'),
]
operations = [
]

65
sapl/sessao/models.py

@ -2,6 +2,7 @@ from operator import xor
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from model_utils import Choices from model_utils import Choices
import reversion import reversion
@ -584,6 +585,18 @@ 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()
class TipoRetiradaPauta(models.Model):
descricao = models.CharField(max_length=150, verbose_name=_('Descrição'))
class Meta:
verbose_name = _('Tipo de Retidara de Pauta')
verbose_name_plural = _('Tipos de Retirada de Pauta')
ordering = ['descricao']
def __str__(self):
return self.descricao
@reversion.register() @reversion.register()
class TipoJustificativa(models.Model): class TipoJustificativa(models.Model):
@ -662,3 +675,55 @@ class JustificativaAusencia(models.Model):
force_update=force_update, force_update=force_update,
using=using, using=using,
update_fields=update_fields) update_fields=update_fields)
class RetiradaPauta(models.Model):
materia = models.ForeignKey(MateriaLegislativa,
on_delete=models.CASCADE,
verbose_name=_('Matéria'))
sessao_plenaria = models.ForeignKey(SessaoPlenaria,
on_delete=models.CASCADE,
verbose_name=_('Sessão Plenária'),
blank=True,
null=True)
ordem = models.ForeignKey(OrdemDia,
blank=True,
null=True,
on_delete=models.CASCADE)
expediente = models.ForeignKey(ExpedienteMateria,
blank=True,
null=True,
on_delete=models.CASCADE)
data = models.DateField(verbose_name=_('Data'),
default=timezone.now)
observacao = models.TextField(blank=True,
verbose_name=_('Observações'))
parlamentar = models.ForeignKey(Parlamentar,
on_delete=models.PROTECT,
verbose_name=_('Requerente'),
blank=True,
null=True)
tipo_de_retirada = models.ForeignKey(TipoRetiradaPauta,
on_delete=models.PROTECT,
verbose_name=_('Motivo de Retirada de Pauta'))
class Meta:
verbose_name = _('Retirada de Pauta')
verbose_name_plural = _('Retirada de Pauta')
def __str__(self):
return _('Ordem: %(ordem)s - Requerente: %(requerente)s - '
'Matéria: %(materia)s') % {
'ordem': self.ordem,
'requerente': self.parlamentar,
'materia': self.materia}
def clean(self):
"""Exatamente um dos campos ordem ou expediente deve estar preenchido.
"""
# TODO remover esse método quando OrdemDia e ExpedienteMateria
# forem reestruturados e os campos ordem e expediente forem unificados
if not xor(bool(self.ordem), bool(self.expediente)):
raise ValidationError(
'ReritadaPauta deve ter exatamente um dos campos '
'ordem ou expediente preenchido. Ambos estão preenchidos: '
'{}, {}'. format(self.ordem, self.expediente))

7
sapl/sessao/urls.py

@ -10,8 +10,9 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
PesquisarPautaSessaoView, PesquisarPautaSessaoView,
PesquisarSessaoPlenariaView, PesquisarSessaoPlenariaView,
PresencaOrdemDiaView, PresencaView, PresencaOrdemDiaView, PresencaView,
ResumoOrdenacaoView, ResumoView, ResumoAtaView, SessaoCrud, ResumoOrdenacaoView, ResumoView, ResumoAtaView, RetiradaPautaCrud, SessaoCrud,
TipoJustificativaCrud, TipoExpedienteCrud, TipoResultadoVotacaoCrud, TipoJustificativaCrud, TipoExpedienteCrud, TipoResultadoVotacaoCrud,
TipoExpedienteCrud, TipoResultadoVotacaoCrud,TipoRetiradaPautaCrud,
TipoSessaoCrud, VotacaoEditView, TipoSessaoCrud, VotacaoEditView,
VotacaoExpedienteEditView, VotacaoExpedienteEditView,
VotacaoExpedienteView, VotacaoNominalEditView, VotacaoExpedienteView, VotacaoNominalEditView,
@ -41,7 +42,7 @@ urlpatterns = [
OradorExpedienteCrud.get_urls() + OradorExpedienteCrud.get_urls() +
ExpedienteMateriaCrud.get_urls() + ExpedienteMateriaCrud.get_urls() +
JustificativaAusenciaCrud.get_urls() + JustificativaAusenciaCrud.get_urls() +
MateriaOrdemDiaCrud.get_urls())), MateriaOrdemDiaCrud.get_urls() + RetiradaPautaCrud.get_urls())),
url(r'^sessao/(?P<pk>\d+)/mesa$', MesaView.as_view(), name='mesa'), url(r'^sessao/(?P<pk>\d+)/mesa$', MesaView.as_view(), name='mesa'),
@ -78,6 +79,8 @@ urlpatterns = [
include(TipoExpedienteCrud.get_urls())), include(TipoExpedienteCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-justificativa/', url(r'^sistema/sessao-plenaria/tipo-justificativa/',
include(TipoJustificativaCrud.get_urls())), include(TipoJustificativaCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-retirada-pauta/',
include(TipoRetiradaPautaCrud.get_urls())),
url(r'^sistema/bancada/', url(r'^sistema/bancada/',
include(BancadaCrud.get_urls())), include(BancadaCrud.get_urls())),
url(r'^sistema/bloco/', url(r'^sistema/bloco/',

104
sapl/sessao/views.py

@ -43,24 +43,22 @@ from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, BlocoForm,
MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet, MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet,
PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet, PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet,
SessaoPlenariaForm, VotacaoEditForm, VotacaoForm, SessaoPlenariaForm, VotacaoEditForm, VotacaoForm,
VotacaoNominalForm) VotacaoNominalForm, RetiradaPautaForm)
from .models import (Bancada, Bloco, CargoBancada, CargoMesa, ExpedienteMateria, from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
ExpedienteSessao, JustificativaAusencia, OcorrenciaSessao, IntegranteMesa, ExpedienteMateria, ExpedienteSessao, OcorrenciaSessao, IntegranteMesa,
MateriaLegislativa, Orador, OradorExpediente, OrdemDia, MateriaLegislativa, Orador, OradorExpediente, OrdemDia,
PresencaOrdemDia, RegistroVotacao, ResumoOrdenacao, PresencaOrdemDia, RegistroVotacao, ResumoOrdenacao,
SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente, SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente,
TipoJustificativa, TipoResultadoVotacao, TipoSessaoPlenaria, TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar, TipoRetiradaPauta,
VotoParlamentar) RetiradaPauta, TipoJustificativa, JustificativaAusencia)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria') TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente') TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa') TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa')
CargoBancadaCrud = CrudAux.build(CargoBancada, '') CargoBancadaCrud = CrudAux.build(CargoBancada, '')
TipoResultadoVotacaoCrud = CrudAux.build(TipoResultadoVotacao, 'tipo_resultado_votacao')
TipoRetiradaPautaCrud = CrudAux.build(TipoRetiradaPauta, 'tipo_retirada_pauta')
TipoResultadoVotacaoCrud = CrudAux.build(
TipoResultadoVotacao, 'tipo_resultado_votacao')
def reordernar_materias_expediente(request, pk): def reordernar_materias_expediente(request, pk):
@ -197,7 +195,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'-data_tramitacao' '-data_tramitacao'
).first() ).first()
turno = ' ' turno = ' '
if tramitacao is not None: if tramitacao:
for t in Tramitacao.TURNO_CHOICES: for t in Tramitacao.TURNO_CHOICES:
if t[0] == tramitacao.turno: if t[0] == tramitacao.turno:
turno = t[1] turno = t[1]
@ -221,7 +219,9 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
exist_resultado = obj.registrovotacao_set.filter( exist_resultado = obj.registrovotacao_set.filter(
materia=obj.materia).exists() materia=obj.materia).exists()
if not exist_resultado: exist_retirada = obj.retiradapauta_set.filter(
materia=obj.materia).exists()
if not exist_resultado and not exist_retirada:
if obj.votacao_aberta: if obj.votacao_aberta:
url = '' url = ''
if is_expediente: if is_expediente:
@ -294,6 +294,19 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
resultado = btn_abrir resultado = btn_abrir
else: else:
resultado = '''Não há resultado''' resultado = '''Não há resultado'''
elif exist_retirada:
retirada = obj.retiradapauta_set.filter(
materia_id=obj.materia_id).last()
retirada_descricao = retirada.tipo_de_retirada.descricao
retirada_observacao = retirada.observacao
url = reverse('sapl.sessao:retiradapauta_detail',
kwargs={'pk': retirada.id})
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
retirada_descricao,
retirada_observacao))
else: else:
resultado = obj.registrovotacao_set.filter( resultado = obj.registrovotacao_set.filter(
materia_id=obj.materia_id).last() materia_id=obj.materia_id).last()
@ -833,17 +846,10 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
messages.add_message(self.request, messages.ERROR, msg) messages.add_message(self.request, messages.ERROR, msg)
else: else:
m, s, x = cronometro_discurso.isoformat().split(':') cronometro_discurso = cronometro_discurso.seconds
cronometro_discurso = int(m) * 60 + int(s) cronometro_aparte = cronometro_aparte.seconds
cronometro_ordem = cronometro_ordem.seconds
m, s, x = cronometro_aparte.isoformat().split(':') cronometro_consideracoes = cronometro_consideracoes.seconds
cronometro_aparte = int(m) * 60 + int(s)
m, s, x = cronometro_ordem.isoformat().split(':')
cronometro_ordem = int(m) * 60 + int(s)
m, s, x = cronometro_consideracoes.isoformat().split(':')
cronometro_consideracoes = int(m) * 60 + int(s)
context = TemplateView.get_context_data(self, **kwargs) context = TemplateView.get_context_data(self, **kwargs)
context.update({ context.update({
@ -1336,7 +1342,12 @@ class ResumoView(DetailView):
parlamentares_sessao = [p.parlamentar for p in presencas] parlamentares_sessao = [p.parlamentar for p in presencas]
context.update({'presenca_sessao': parlamentares_sessao}) ausentes_sessao = JustificativaAusencia.objects.filter(
sessao_plenaria_id=self.object.id
).order_by('parlamentar__nome_parlamentar')
context.update({'presenca_sessao': parlamentares_sessao,
'justificativa_ausencia': ausentes_sessao})
# ===================================================================== # =====================================================================
@ -1370,10 +1381,13 @@ class ResumoView(DetailView):
turno = get_turno(tramitacao.turno) turno = get_turno(tramitacao.turno)
rv = m.registrovotacao_set.first() rv = m.registrovotacao_set.first()
rp = m.retiradapauta_set.filter(materia=m.materia).first()
if rv: if rv:
resultado = rv.tipo_resultado_votacao.nome resultado = rv.tipo_resultado_votacao.nome
resultado_observacao = rv.observacao resultado_observacao = rv.observacao
elif rp:
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else: else:
resultado = _('Matéria não votada') resultado = _('Matéria não votada')
resultado_observacao = _(' ') resultado_observacao = _(' ')
@ -1461,9 +1475,13 @@ class ResumoView(DetailView):
# Verificar resultado # Verificar resultado
rv = o.registrovotacao_set.filter(materia=o.materia).first() rv = o.registrovotacao_set.filter(materia=o.materia).first()
rp = o.retiradapauta_set.filter(materia=o.materia).first()
if rv: if rv:
resultado = rv.tipo_resultado_votacao.nome resultado = rv.tipo_resultado_votacao.nome
resultado_observacao = rv.observacao resultado_observacao = rv.observacao
elif rp:
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else: else:
resultado = _('Matéria não votada') resultado = _('Matéria não votada')
resultado_observacao = _(' ') resultado_observacao = _(' ')
@ -3099,7 +3117,7 @@ def mudar_ordem_materia_sessao(request):
elif materia == 'ordem': elif materia == 'ordem':
materia = OrdemDia materia = OrdemDia
else: else:
return return JsonResponse({}, safe=False)
# Testa se existe alguma matéria na posição recebida # Testa se existe alguma matéria na posição recebida
try: try:
@ -3138,7 +3156,7 @@ def mudar_ordem_materia_sessao(request):
materia_1.numero_ordem = posicao_final materia_1.numero_ordem = posicao_final
materia_1.save() materia_1.save()
return return JsonResponse({}, safe=False)
class JustificativaAusenciaCrud(MasterDetailCrud): class JustificativaAusenciaCrud(MasterDetailCrud):
@ -3676,3 +3694,37 @@ class VotacaoEmBlocoNominalView(TemplateView):
'origem': self.request.POST['origem']}) 'origem': self.request.POST['origem']})
return self.render_to_response(context) return self.render_to_response(context)
class RetiradaPautaCrud(MasterDetailCrud):
model = RetiradaPauta
public = [RP_LIST, RP_DETAIL, ]
parent_field = 'sessao_plenaria'
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['tipo_de_retirada', 'materia', 'observacao', 'parlamentar']
class ListView(MasterDetailCrud.ListView):
paginate_by = 10
class CreateView(MasterDetailCrud.CreateView):
form_class = RetiradaPautaForm
layout_key = None
def get_initial(self):
sessao_plenaria = SessaoPlenaria.objects.get(id=self.kwargs['pk'])
return {'sessao_plenaria': sessao_plenaria}
def get_success_url(self):
return reverse('sapl.sessao:retiradapauta_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView):
form_class = RetiradaPautaForm
layout_key = None
def get_initial(self):
sessao_plenaria = RetiradaPauta.objects.get(id=self.kwargs['pk']).sessao_plenaria
return {'sessao_plenaria': sessao_plenaria}
class DeleteView(MasterDetailCrud.DeleteView):
pass

2
sapl/static/js/app.js

@ -47,7 +47,7 @@ function refreshMask() {
$('.dateinput').mask('00/00/0000', {placeholder:"__/__/____"}); $('.dateinput').mask('00/00/0000', {placeholder:"__/__/____"});
$('.hora').mask("00:00", {placeholder:"hh:mm"}); $('.hora').mask("00:00", {placeholder:"hh:mm"});
$('.hora_hms').mask("00:00:00", {placeholder:"hh:mm:ss"}); $('.hora_hms').mask("00:00:00", {placeholder:"hh:mm:ss"});
$('.cronometro').mask("00:00", {placeholder:"mm:ss"}); $('.cronometro').mask("00:00:00", {placeholder:"hh:mm:ss"});
} }
function autorModal() { function autorModal() {

503
sapl/static/styles/app.css

@ -0,0 +1,503 @@
.container-home {
position: relative;
padding: 2em 1.5em 1.5em 1.5em;
max-width: 1000px;
margin: 0 auto; }
.container-home a:hover {
color: #444;
-webkit-transition: 0.3s ease-in;
-moz-transition: 0.3s ease-in;
-o-transition: 0.3s ease-in; }
.container-home #homeIndex {
text-align: center; }
.container-home .homeBanner span {
color: white;
font-size: 32px;
font-weight: 600;
display: inline-block;
vertical-align: middle;
padding: 2px 45px 4px;
border: 2px solid; }
.container-home .homeBanner::after {
display: inline-block;
vertical-align: middle;
height: 100%; }
.container-home .homeBlock {
display: inline-block;
position: relative;
background-color: #F3F3F3;
width: 190px;
height: 260px;
margin: 3px;
text-align: center;
font-size: 0;
overflow: hidden; }
.container-home .homeBlock > a {
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0; }
.container-home .homeBlock::after {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
overflow: visible;
clear: none;
visibility: initial; }
.container-home .homeContent {
position: relative;
padding: 10px;
text-align: justify;
font-size: 14px;
color: #FFF;
opacity: 0;
transition: opacity 0.5s ease;
display: inline-block;
vertical-align: middle; }
.container-home .homeContent p {
display: block;
line-height: 13px;
font-size: 80%;
color: white; }
.container-home .homeIcon {
position: relative;
display: inline-block;
width: 105px;
height: 105px;
border-radius: 50%;
background: #364347;
z-index: 1; }
.container-home .homeIcon::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background: #364347;
top: 0;
left: 0;
transform: scale(0.95);
transition: transform 0.6s ease; }
.container-home .homeIcon img {
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
left: 0;
transition: opacity 0.4s 0.4s ease; }
.container-home .homeFront {
position: absolute;
top: 46%;
width: 100%;
font-size: 0;
transform: translateY(-60%); }
.container-home .homeFront h2 {
position: absolute;
margin-top: 18px;
font-size: 22px;
font-weight: 700;
color: #595959 !important;
width: 100%;
padding: 0 6%;
z-index: 0; }
.container-home .homeTitle {
display: block;
height: 32px;
text-align: center;
width: 100%;
opacity: 0;
transition: opacity 0.4s ease; }
.container-home .homeTitle::before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%; }
.container-home .homeTitle h2 {
display: inline-block;
vertical-align: middle;
max-width: 110px;
font-size: 14px;
color: white !important;
line-height: 1em; }
.container-home .homeTitle img {
display: inline-block;
vertical-align: middle;
height: 30px;
margin-right: 5px; }
.container-home .homeBlock:hover .homeIcon::before {
transform: scale(3.6) translateY(7px); }
.container-home .homeBlock:hover .homeContent {
opacity: 1;
transition-delay: 0.2s; }
.container-home .homeBlock:hover .homeIcon img {
opacity: 0;
transition-duration: 0.2s;
transition-delay: 0s; }
.container-home .homeBlock:hover .homeTitle {
opacity: 1; }
html {
position: relative;
min-height: 100%; }
body {
margin-bottom: 160px; }
h1, h2, h3, h4, h5, h6, form, dl, dt, dd, p, div, img, a {
margin: 0;
padding: 0; }
h1, .h1 {
font-size: 30px; }
h2, .h2 {
font-size: 24px; }
h3, .h3 {
font-size: 20px; }
h4, .h4 {
font-size: 16px; }
h5, .h5 {
font-size: 14px; }
h6, .h6 {
font-size: 12px; }
p {
margin: 0.5em 0; }
p .control-label {
font-weight: bold; }
label {
margin-bottom: 0;
line-height: 1; }
fieldset fieldset {
font-size: 95%; }
fieldset fieldset legend {
font-size: 18px; }
.page-header {
margin: 20px 0px 10px; }
.caret.top {
transform: rotate(180deg); }
.btn:hover, .btn:focus {
color: inherit; }
.btn-default.btn-excluir {
color: #d9534f; }
.btn-default.btn-excluir:hover {
color: #fff;
border-color: #de6764;
background-color: #de6764; }
.btn-cancel-iframe {
position: relative;
text-align: right;
opacity: 0.5; }
.btn-cancel-iframe:hover {
opacity: 1; }
.btn-cancel-iframe a {
padding: 10px;
display: inline-block; }
.legend {
display: block;
width: 100%;
padding: 0;
margin-bottom: 20px;
font-size: 21px;
line-height: inherit;
color: #333333;
border: 0;
border-bottom: 1px solid #e5e5e5;
clear: both; }
.grid-gutter-width-right {
margin-right: 15px; }
.controls-file {
padding: 10px;
border: 1px solid #d6e1e5;
border-radius: 4px; }
.controls-file label.checkbox-inline {
margin: 0px;
display: block; }
.help-block-danger {
margin: 15px;
padding: 15px;
border: 2px dashed #f00; }
.control-label {
margin: 0; }
.form-control-static {
padding-top: 0;
min-height: auto; }
.form-control-static img {
max-width: 100%; }
.pagination {
padding-top: 25px; }
.modal .alert {
margin-bottom: 0; }
.avatar-parlamentar {
height: 128px;
width: 128px;
margin: 0 auto;
display: table; }
.masthead {
padding: 10px; }
.masthead .nav {
clear: both; }
.masthead .navbar-brand {
padding: 0px;
color: inherit;
font-size: 24px; }
.masthead .navbar-brand img.img-responsive {
height: 95px;
margin-right: 15px;
display: inline-block; }
.masthead .navbar-brand small {
color: #93A4AA;
font-size: 75%;
line-height: 25px; }
.masthead .navbar-brand .vcenter {
display: inline-block;
vertical-align: middle;
float: none;
padding: 10px; }
nav.navbar {
margin-bottom: 0;
border-radius: 0;
font-size: 15px; }
nav .navbar-nav > li > a {
padding-top: 0px;
padding-bottom: 0px;
line-height: 75px; }
nav .navbar-nav > li > a:hover {
background-color: #23527c; }
nav .navbar-nav > li:nth-child(2) > .dropdown-menu {
right: auto; }
nav .navbar-nav:last-child > li:last-child a {
padding-right: 0px; }
.controls-radio-checkbox {
padding: 0px;
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px; }
.controls-radio-checkbox .checkbox, .controls-radio-checkbox .radio, .controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline {
padding: 8px 8px 8px 36px;
margin: 0;
line-height: 1.6;
display: block; }
.controls-radio-checkbox .checkbox:hover, .controls-radio-checkbox .radio:hover, .controls-radio-checkbox .checkbox-inline:hover, .controls-radio-checkbox .radio-inline:hover {
background-color: #d6e1e5; }
.controls-radio-checkbox .checkbox .icons, .controls-radio-checkbox .radio .icons, .controls-radio-checkbox .checkbox-inline .icons, .controls-radio-checkbox .radio-inline .icons {
top: auto;
left: 8px; }
.controls-radio-checkbox .checkbox-inline, .controls-radio-checkbox .radio-inline {
display: inline-block; }
.controls-radio-checkbox .help-block {
margin: 15px;
padding: 15px;
border: 2px dashed #d6e1e5; }
.controls-radio-checkbox__old {
padding: 0px;
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px; }
.controls-radio-checkbox__old label {
padding: 0;
line-height: 2.7;
padding-left: 36px; }
.controls-radio-checkbox__old label .icons {
top: 8px;
left: 8px; }
.controls-radio-checkbox__old label.checkbox-inline, .controls-radio-checkbox__old label.radio-inline {
padding-right: 8px; }
.controls-radio-checkbox__old label.checkbox-inline .icons, .controls-radio-checkbox__old label.radio-inline .icons {
top: 8px;
left: 8px; }
.controls-radio-checkbox__old .checkbox, .controls-radio-checkbox__old .radio, .controls-radio-checkbox__old .checkbox-inline, .controls-radio-checkbox__old .radio-inline {
margin: 0; }
.controls-radio-checkbox__old .checkbox:hover, .controls-radio-checkbox__old .radio:hover, .controls-radio-checkbox__old .checkbox-inline:hover, .controls-radio-checkbox__old .radio-inline:hover {
background-color: #d6e1e5; }
.manual, .manual ul {
padding-left: 1.5em;
list-style-type: none;
margin-top: 0;
font-size: 100%; }
.manual li {
display: list-item;
line-height: 1.5em;
padding-right: 0; }
.manual li a {
background-color: transparent;
border: none;
border-radius: none;
padding: 0; }
.container-tabaux .sidebar-tabaux {
background: #fafafa;
margin-top: -70px;
padding: 10px;
border: 1px solid #eee; }
.container-tabaux .sidebar-tabaux .navbar-right {
margin: 0; }
.container-tabaux .sidebar-tabaux .nav-pills > li + li {
margin-left: 0px; }
.container-tabaux .sidebar-tabaux li {
width: 100%; }
.container-tabaux .sidebar-tabaux span {
display: none; }
.container-tabaux .sidebar-tabaux .dropdown-menu {
padding: 0px;
right: 10px;
margin-top: -5px;
overflow: hidden; }
.container-tabaux .sidebar-tabaux .dropdown-menu a {
border: 0px; }
.container-tabaux ul {
list-style: none;
padding: 0; }
.container-tabaux .list {
font-family: "SourceSansProSemiBold", Helvetica, Arial, sans-serif;
font-size: 0px;
display: table;
width: 100%;
margin: 0; }
.container-tabaux .list ul {
display: table;
width: 100%;
margin: 0; }
.container-tabaux .list li {
width: calc(50%);
display: inline-block;
position: relative; }
.container-tabaux .list > li {
width: 100%;
border-bottom: 1px solid #eee;
padding-bottom: 20px;
margin-bottom: 20px; }
.container-tabaux .list .head_title {
color: #364347;
font-size: 2.4rem;
text-transform: none; }
.container-tabaux .list a span {
display: none; }
#styleparlamentar {
border: 0px solid #d6e1e5;
border-top-color: #d6e1e5;
border-right-color: #d6e1e5;
border-bottom-color: #d6e1e5;
border-left-color: #d6e1e5;
border-image-source: initial;
border-image-slice: initial;
border-image-repeat: initial;
font-size: 16px;
line-height: 1.467;
padding: 7px 12px;
height: 40px;
-webkit-appearance: none;
border-radius: 4px;
-webkit-box-shadow: none;
box-shadow: none;
margin-left: 1.0em; }
.footer {
background: #364347;
color: white;
text-align: center;
position: absolute;
width: 100%;
bottom: 0px; }
.footer p {
color: white;
margin-top: 10px; }
.footer .container {
padding-top: 25px; }
@media (max-width: 1199px) {
nav .container {
width: auto !important; }
.navbar-nav > li > a {
padding-left: 10.71429px;
padding-right: 10.71429px; } }
@media (max-width: 1091px) {
.container {
width: auto; }
.navbar-nav > li > a {
padding-left: 7.5px;
padding-right: 7.5px; }
.masthead .navbar-brand {
font-size: 22px; }
.masthead .navbar-brand img.img-responsive {
height: 60px;
margin-right: 7.5px; } }
@media (max-width: 991px) {
body {
margin: 0; }
.footer {
position: relative; }
.caret {
margin-left: 1px; }
.navbar-nav > li > a {
padding-left: 4px;
padding-right: 4px; } }
@media (max-width: 767px) {
nav .navbar-nav > li > a {
line-height: 2.5; }
nav .navbar-right {
position: absolute;
top: 0;
margin: 10px; }
nav .navbar-right > li {
vertical-align: top;
display: inline-block; }
nav .navbar-right > li a {
padding-left: 10px;
padding-right: 10px; }
nav .navbar-right .pesquisa.open ul {
position: absolute; }
nav .navbar-right .navbar-form {
margin: 8px 0; }
.table {
width: auto;
white-space: normal;
display: block;
overflow-x: auto; } }
@media (min-width: 1092px) and (max-width: 1199px) {
.container {
width: 1070px; } }
@media print {
a[href]:after {
content: none !important; } }

1136
sapl/static/styles/compilacao.css

File diff suppressed because it is too large

2
sapl/templates/base.html

@ -184,7 +184,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.134</span> <span>Release: 3.1.137</span>
</p> </p>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">

3
sapl/templates/materia/proposicao_detail.html

@ -158,10 +158,11 @@
</br> </br>
Texto Original Texto Original
</br> </br>
&nbsp;&nbsp;&nbsp;&nbsp; {% if object.materia_de_vinculo.texto_original %}
<a href="{{object.materia_de_vinculo.texto_original.url}}"> <a href="{{object.materia_de_vinculo.texto_original.url}}">
{{object.materia_de_vinculo.texto_original| to_str | split:"/" | get_last_item_from_list:-1}} {{object.materia_de_vinculo.texto_original| to_str | split:"/" | get_last_item_from_list:-1}}
</a> </a>
{% endif %}
</br> </br>
</div> </div>
</div> </div>

3
sapl/templates/menu_tabelas_auxiliares.yaml

@ -152,6 +152,9 @@
- title: {% trans 'Tipo de Expediente' %} - title: {% trans 'Tipo de Expediente' %}
url: sapl.sessao:tipoexpediente_list url: sapl.sessao:tipoexpediente_list
css_class: btn btn-link css_class: btn btn-link
- title: {% trans 'Tipo de Retirada de Pauta' %}
url: sapl.sessao:tiporetiradapauta_list
css_class: btn btn-link
- title: {% trans 'Ordenação do Resumo' %} - title: {% trans 'Ordenação do Resumo' %}
url: sapl.sessao:resumo_ordenacao url: sapl.sessao:resumo_ordenacao
css_class: btn btn-link css_class: btn btn-link

2
sapl/templates/norma/layouts.yaml

@ -58,7 +58,7 @@ LegislacaoCitadaDetail:
TipoVinculoNormaJuridica: TipoVinculoNormaJuridica:
{% trans 'Tipo de Vínculo entre Normas Jurídicas' %}: {% trans 'Tipo de Vínculo entre Normas Jurídicas' %}:
- sigla:2 descricao_ativa descricao_passiva - sigla:2 descricao_ativa descricao_passiva revoga_integralmente
NormaRelacionada: NormaRelacionada:
{% trans 'Norma Relacionada' %}: {% trans 'Norma Relacionada' %}:

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

@ -7,4 +7,10 @@
{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ; {{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ;
{% endfor %} {% endfor %}
</p> </p>
<p align="justify">
<strong>Justificativas de Ausências na Sessão: </strong>
{% for j in justificativa_ausencia %}
{{j.parlamentar}} / {{ j.tipo_ausencia }} ;
{% endfor %}
</p>
</fieldset> </fieldset>

25
sapl/templates/sessao/blocos_resumo/lista_presenca.html

@ -7,4 +7,29 @@
<div class="col-md-12">{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }}</div> <div class="col-md-12">{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }}</div>
{% endfor %} {% endfor %}
</div> </div>
</br></br></br>
<div class="row">
<legend>Justificativas de Ausência na Sessão</legend>
<table class="table">
<thead>
<tr>
<th>Parlamentar</th>
<th>Justificativa</th>
<th>Ausente em</th>
</tr>
</thead>
<tbody>
{% for j in justificativa_ausencia %}
<tr>
<td> {{ j.parlamentar }} </td>
<td> {{ j.tipo_ausencia }} </td>
{% if j.ausencia == 1 %}
<td> Matéria </td>
{% else %}
<td> Sessão </td>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</fieldset> </fieldset>

10
sapl/templates/sessao/layouts.yaml

@ -99,3 +99,13 @@ JustificativaAusencia:
- materias_do_expediente - materias_do_expediente
- materias_da_ordem_do_dia - materias_da_ordem_do_dia
- observacao - observacao
TipoRetiradaPauta:
{% trans 'Tipo Retirada Pauta'%}:
- descricao
RetiradaPauta:
{% trans 'Retirada de Pauta' %}:
- tipo_de_retirada materia
- data parlamentar
- observacao

6
sapl/templates/sessao/retiradapauta_form.html

@ -0,0 +1,6 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block detail_content %}
{% crispy form %}
{% endblock detail_content %}

2
sapl/templates/sessao/subnav.yaml

@ -14,6 +14,8 @@
url: orador_list url: orador_list
- title: {% trans 'Ocorrências da Sessão' %} - title: {% trans 'Ocorrências da Sessão' %}
url: ocorrencia_sessao url: ocorrencia_sessao
- title: {% trans 'Retirada de Pauta'%}
url: retiradapauta_list
- title: {% trans 'Expedientes' %} - title: {% trans 'Expedientes' %}
children: children:

1
sapl/templates/sistema.html

@ -104,6 +104,7 @@
<div class="col-md-6"><a href="{% url 'sapl.sessao:tiposessaoplenaria_list' %}" class="btn btn-link">Tipo de Sessão Plenária</a></div> <div class="col-md-6"><a href="{% url 'sapl.sessao:tiposessaoplenaria_list' %}" class="btn btn-link">Tipo de Sessão Plenária</a></div>
<div class="col-md-6"><a href="{% url 'sapl.sessao:tiporesultadovotacao_list' %}" class="btn btn-link">Tipo de Resultado da Votação</a></div> <div class="col-md-6"><a href="{% url 'sapl.sessao:tiporesultadovotacao_list' %}" class="btn btn-link">Tipo de Resultado da Votação</a></div>
<div class="col-md-6"><a href="{% url 'sapl.sessao:tipoexpediente_list' %}" class="btn btn-link">Tipo de Expediente</a></div> <div class="col-md-6"><a href="{% url 'sapl.sessao:tipoexpediente_list' %}" class="btn btn-link">Tipo de Expediente</a></div>
<div class="col-md-6"><a href="{% url 'sapl.sessao:tiporetiradapauta_list' %}" class="btn btn-link">Tipo de Retirada de Pauta</a></div>
<div class="col-md-6"><a href="{% url 'sapl.sessao:resumo_ordenacao' %}" class="btn btn-link">Ordenação do Resumo</a></div> <div class="col-md-6"><a href="{% url 'sapl.sessao:resumo_ordenacao' %}" class="btn btn-link">Ordenação do Resumo</a></div>
<div class="col-md-6"><a href="{% url 'sapl.sessao:tipojustificativa' %}" class="btn btn-link">Tipo de Justificativa de Ausência</a></div> <div class="col-md-6"><a href="{% url 'sapl.sessao:tipojustificativa' %}" class="btn btn-link">Tipo de Justificativa de Ausência</a></div>
</div> </div>

2
setup.py

@ -52,7 +52,7 @@ install_requires = [
] ]
setup( setup(
name='interlegis-sapl', name='interlegis-sapl',
version='3.1.134', version='3.1.137',
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',

Loading…
Cancel
Save