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. 24
      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. 201
      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. 5
      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. 2
      sapl/templates/sessao/resumo_ata.html
  43. 6
      sapl/templates/sessao/retiradapauta_form.html
  44. 2
      sapl/templates/sessao/subnav.yaml
  45. 1
      sapl/templates/sistema.html
  46. 2
      setup.py

2
docker-compose.yml

@ -11,7 +11,7 @@ sapldb:
ports:
- "5432:5432"
sapl:
image: interlegis/sapl:3.1.134
image: interlegis/sapl:3.1.137
restart: always
environment:
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'),
max_length=1, choices=ASSINATURA_ATA_CHOICES, default='T')
cronometro_discurso = models.TimeField(
cronometro_discurso = models.DurationField(
verbose_name=_('Cronômetro do Discurso'),
blank=True,
null=True)
cronometro_aparte = models.TimeField(
cronometro_aparte = models.DurationField(
verbose_name=_('Cronômetro do Aparte'),
blank=True,
null=True)
cronometro_ordem = models.TimeField(
cronometro_ordem = models.DurationField(
verbose_name=_('Cronômetro da Ordem'),
blank=True,
null=True)
cronometro_consideracoes = models.TimeField(
cronometro_consideracoes = models.DurationField(
verbose_name=_('Cronômetro de Considerações Finais'),
blank=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):
return 0
m, s, x = AppConfig.attr(
'cronometro_' + value).isoformat().split(':')
return 60 * int(m) + int(s)
return AppConfig.attr('cronometro_' + value).seconds
@register.filter

26
sapl/legacy/migracao_documentos.py

@ -1,6 +1,6 @@
import os
import shutil
import re
import shutil
from glob import glob
from os.path import join
@ -189,3 +189,27 @@ def migrar_documentos(repo):
print('\n#### Encerrado ####\n\n'
'{} documentos sobraram sem ser migrados!!!'.format(
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):
# 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)
if extensao is not None:
return extensao

13
sapl/norma/fixtures/pre_popula_tipo_vinculo_norma.json

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

2
sapl/norma/forms.py

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

2
sapl/norma/migrations/0009_auto_20171113_1339.py

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

24
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 -*-
# Generated by Django 1.10.8 on 2018-11-23 14:51
from __future__ import unicode_literals
import os
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):
TipoVinculoNormaJuridica = apps.get_model("norma", "TipoVinculoNormaJuridica")
TipoVinculoNormaJuridica = apps.get_model(
"norma", "TipoVinculoNormaJuridica")
db_alias = schema_editor.connection.alias
tipo_vinculos = TipoVinculoNormaJuridica.objects.all().exists()
@ -19,21 +21,31 @@ def gera_tipo_vinculo(apps, schema_editor):
print("Carga de {} não efetuada. Já Existem {} cadastrados...".format(
TipoVinculoNormaJuridica._meta.verbose_name,
TipoVinculoNormaJuridica._meta.verbose_name_plural
)
)
)
else:
fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
# pega tipo_vinculo_norma_juridica listados em fixtures/pre_popula_tipo_vinculo_norma.json
fixture_dir = os.path.abspath(os.path.join(
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_file = os.path.join(fixture_dir, fixture_filename)
call_command('loaddata', fixture_file)
class Migration(migrations.Migration):
dependencies = [
('norma', '0007_auto_20170904_1708'),
('norma', '0015_auto_20181109_1422'),
]
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),
]

3
sapl/norma/models.py

@ -258,6 +258,9 @@ class TipoVinculoNormaJuridica(models.Model):
max_length=50, blank=True, verbose_name=_('Descrição Ativa'))
descricao_passiva = models.CharField(
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:
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'])
TipoVinculoNormaJuridicaCrud = CrudAux.build(
TipoVinculoNormaJuridica, '',
list_field_names=['sigla', 'descricao_ativa', 'descricao_passiva'])
list_field_names=['sigla', 'descricao_ativa', 'descricao_passiva', 'revoga_integralmente'])
class NormaRelacionadaCrud(MasterDetailCrud):
@ -274,16 +274,19 @@ def recuperar_norma(request):
def recuperar_numero_norma(request):
tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo'])
ano = request.GET.get('ano', '')
param = {'tipo': tipo}
param['ano'] = ano if ano else timezone.now().year
param = {'tipo': tipo,
'ano': ano if ano else timezone.now().year
}
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:
response = JsonResponse({'numero': int(re.sub("[^0-9].*", '', norma[0])) + 1,
'ano': norma[1]})
numeros = sorted([int(re.sub("[^0-9].*", '', n)) for n in norma])
next_num = numeros.pop() + 1
response = JsonResponse({'numero': next_num,
'ano': param['ano']})
else:
response = JsonResponse(
{'numero': 1, 'ano': ano})
{'numero': 1, 'ano': param['ano']})
return response

1
sapl/painel/views.py

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

2
sapl/parlamentares/forms.py

@ -136,7 +136,7 @@ class MandatoForm(ModelForm):
existe_mandato = Mandato.objects.filter(
parlamentar=data['parlamentar'],
legislatura=data['legislatura']).exists()
if existe_mandato:
if existe_mandato and data['titular']:
self.logger.error("Mandato nesta legislatura (parlamentar={}, legislatura={}) já existe."
.format(data['parlamentar'], data['legislatura']))
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),
'data_expedicao_diploma': '01/07/2015',
'data_inicio_mandato': legislatura.data_inicio,
'titular':True,
})
assert not form.is_valid()

2
sapl/parlamentares/views.py

@ -498,7 +498,7 @@ class ParlamentarCrud(Crud):
if legislatura_id >= 0:
return queryset.filter(
mandato__legislatura_id=legislatura_id).annotate(
mandato_titular=F('mandato__titular'))
mandato_titular=F('mandato__titular')).distinct()
else:
try:
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:
tmp += '<tr><td><para style="P3"><b>' + str(expediente_materia['num_ordem']) + '</b> - ' + \
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'
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">' + \
str(expediente_materia['des_situacao']) + '</para></td></tr>\n'
@ -151,10 +151,10 @@ def votacao(lst_votacao):
votacao["tipo_materia"] + ' No. ' + \
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_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'
tmp += '<td><para style="P4">' + \
str(votacao['txt_ementa']) + '</para></td>\n'
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="P3">' + \
str(votacao['des_situacao']) + '</para></td></tr>\n'
@ -162,7 +162,7 @@ def votacao(lst_votacao):
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]
autor = context.zsql.autor_obter_zsql(
cod_autor=autoria.cod_autor)
if len(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> ' + \
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> ' + \
dat_fim_sessao + ' <b>- </b> ' + hr_fim_sessao + '</para>\n'
@ -144,7 +142,7 @@ def mesa(lst_mesa):
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">' + \
str(presenca['nom_parlamentar']) + '/' + \
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
@ -169,7 +180,7 @@ def expedientes(lst_expedientes):
tmp += '\t\t<para style="P2">\n'
tmp += '\t\t\t<font color="white"> </font>\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/> ' + \
expediente['nom_expediente'] + ': </b></para>\n' + \
'<para style="P3">' + \
@ -191,10 +202,10 @@ def expediente_materia(lst_expediente_materia):
tmp += '<blockTable style="repeater" repeatRows="1">\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:
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[
'des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + str(expediente_materia['nom_autor']) + '</para></td>\n'
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>'+ expediente_materia['num_autores'] + ': </b>' + str(expediente_materia['nom_autor']) + '</para></td>\n'
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>' + \
str(expediente_materia['nom_resultado']) + \
'</b></para>\n' + '<para style="P3">'
@ -254,8 +265,8 @@ def votacao(lst_votacao):
tmp += '<blockTable style="repeater" repeatRows="1">\n'
tmp += '<tr><td >Matéria</td><td>Ementa</td><td>Resultado da Votação</td></tr>\n'
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[
'des_turno']) + '</para>\n' + '<para style="P3"><b>Autor: </b>' + str(votacao['nom_autor']) + '</para></td>\n'
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>'+ votacao['num_autores'] +': </b>' + str(votacao['nom_autor']) + '</para></td>\n'
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="P3"><b>' + \
@ -296,7 +307,7 @@ def ocorrencias(lst_ocorrencias):
tmp += '\t\t<para style="P2">\n'
tmp += '\t\t\t<font color="white"> </font>\n'
tmp += '\t\t</para>\n'
for idx, ocorrencia in enumerate(lst_ocorrencias):
for ocorrencia in lst_ocorrencias:
tmp += '\t\t<para style="P3">' + \
str(ocorrencia.conteudo) + '</para>\n'
tmp += '\t\t<para style="P2">\n'
@ -305,7 +316,7 @@ def ocorrencias(lst_ocorrencias):
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"
@ -331,7 +342,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me
'cont_mult': '',
'exp': expedientes(lst_expedientes),
'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),
'mat_exp': expediente_materia(lst_expediente_materia),
'mat_o_d': votacao(lst_votacao),
@ -357,7 +368,7 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me
else:
tmp += inf_basicas(inf_basicas_dic)
tmp += mesa(lst_mesa)
tmp += presenca(lst_presenca_sessao)
tmp += presenca(lst_presenca_sessao,lst_ausencia_sessao)
tmp += expedientes(lst_expedientes)
tmp += expediente_materia(lst_expediente_materia)
tmp += oradores_expediente(lst_oradores_expediente)

201
sapl/relatorios/views.py

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

2
sapl/rules/map_rules.py

@ -172,6 +172,7 @@ rules_group_sessao = {
(sessao.RegistroVotacao, __base__),
(sessao.VotoParlamentar, __base__),
(sessao.JustificativaAusencia, __base__),
(sessao.RetiradaPauta, __base__)
]
}
@ -269,6 +270,7 @@ rules_group_geral = {
(sessao.JustificativaAusencia, __base__),
(sessao.Bloco, __base__),
(sessao.ResumoOrdenacao, __base__),
(sessao.TipoRetiradaPauta, __base__),
(lexml.LexmlProvedor, __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,
Orador, OradorExpediente, OrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao,
OcorrenciaSessao, RegistroVotacao)
OcorrenciaSessao, RegistroVotacao, RetiradaPauta, TipoRetiradaPauta)
def recupera_anos():
@ -191,6 +191,100 @@ class SessaoPlenariaForm(ModelForm):
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 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.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
import reversion
@ -584,6 +585,18 @@ class ResumoOrdenacao(models.Model):
def __str__(self):
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()
class TipoJustificativa(models.Model):
@ -662,3 +675,55 @@ class JustificativaAusencia(models.Model):
force_update=force_update,
using=using,
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,
PesquisarSessaoPlenariaView,
PresencaOrdemDiaView, PresencaView,
ResumoOrdenacaoView, ResumoView, ResumoAtaView, SessaoCrud,
ResumoOrdenacaoView, ResumoView, ResumoAtaView, RetiradaPautaCrud, SessaoCrud,
TipoJustificativaCrud, TipoExpedienteCrud, TipoResultadoVotacaoCrud,
TipoExpedienteCrud, TipoResultadoVotacaoCrud,TipoRetiradaPautaCrud,
TipoSessaoCrud, VotacaoEditView,
VotacaoExpedienteEditView,
VotacaoExpedienteView, VotacaoNominalEditView,
@ -41,7 +42,7 @@ urlpatterns = [
OradorExpedienteCrud.get_urls() +
ExpedienteMateriaCrud.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'),
@ -78,6 +79,8 @@ urlpatterns = [
include(TipoExpedienteCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-justificativa/',
include(TipoJustificativaCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-retirada-pauta/',
include(TipoRetiradaPautaCrud.get_urls())),
url(r'^sistema/bancada/',
include(BancadaCrud.get_urls())),
url(r'^sistema/bloco/',

104
sapl/sessao/views.py

@ -43,24 +43,22 @@ from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, BlocoForm,
MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet,
PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet,
SessaoPlenariaForm, VotacaoEditForm, VotacaoForm,
VotacaoNominalForm)
from .models import (Bancada, Bloco, CargoBancada, CargoMesa, ExpedienteMateria,
ExpedienteSessao, JustificativaAusencia, OcorrenciaSessao, IntegranteMesa,
VotacaoNominalForm, RetiradaPautaForm)
from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
ExpedienteMateria, ExpedienteSessao, OcorrenciaSessao, IntegranteMesa,
MateriaLegislativa, Orador, OradorExpediente, OrdemDia,
PresencaOrdemDia, RegistroVotacao, ResumoOrdenacao,
SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente,
TipoJustificativa, TipoResultadoVotacao, TipoSessaoPlenaria,
VotoParlamentar)
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar, TipoRetiradaPauta,
RetiradaPauta, TipoJustificativa, JustificativaAusencia)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
TipoJustificativaCrud = CrudAux.build(TipoJustificativa, 'tipo_justificativa')
CargoBancadaCrud = CrudAux.build(CargoBancada, '')
TipoResultadoVotacaoCrud = CrudAux.build(
TipoResultadoVotacao, 'tipo_resultado_votacao')
TipoResultadoVotacaoCrud = CrudAux.build(TipoResultadoVotacao, 'tipo_resultado_votacao')
TipoRetiradaPautaCrud = CrudAux.build(TipoRetiradaPauta, 'tipo_retirada_pauta')
def reordernar_materias_expediente(request, pk):
@ -197,7 +195,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'-data_tramitacao'
).first()
turno = ' '
if tramitacao is not None:
if tramitacao:
for t in Tramitacao.TURNO_CHOICES:
if t[0] == tramitacao.turno:
turno = t[1]
@ -221,7 +219,9 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
exist_resultado = obj.registrovotacao_set.filter(
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:
url = ''
if is_expediente:
@ -294,6 +294,19 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
resultado = btn_abrir
else:
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:
resultado = obj.registrovotacao_set.filter(
materia_id=obj.materia_id).last()
@ -833,17 +846,10 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
messages.add_message(self.request, messages.ERROR, msg)
else:
m, s, x = cronometro_discurso.isoformat().split(':')
cronometro_discurso = int(m) * 60 + int(s)
m, s, x = cronometro_aparte.isoformat().split(':')
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)
cronometro_discurso = cronometro_discurso.seconds
cronometro_aparte = cronometro_aparte.seconds
cronometro_ordem = cronometro_ordem.seconds
cronometro_consideracoes = cronometro_consideracoes.seconds
context = TemplateView.get_context_data(self, **kwargs)
context.update({
@ -1336,7 +1342,12 @@ class ResumoView(DetailView):
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)
rv = m.registrovotacao_set.first()
rp = m.retiradapauta_set.filter(materia=m.materia).first()
if rv:
resultado = rv.tipo_resultado_votacao.nome
resultado_observacao = rv.observacao
elif rp:
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else:
resultado = _('Matéria não votada')
resultado_observacao = _(' ')
@ -1461,9 +1475,13 @@ class ResumoView(DetailView):
# Verificar resultado
rv = o.registrovotacao_set.filter(materia=o.materia).first()
rp = o.retiradapauta_set.filter(materia=o.materia).first()
if rv:
resultado = rv.tipo_resultado_votacao.nome
resultado_observacao = rv.observacao
elif rp:
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else:
resultado = _('Matéria não votada')
resultado_observacao = _(' ')
@ -3099,7 +3117,7 @@ def mudar_ordem_materia_sessao(request):
elif materia == 'ordem':
materia = OrdemDia
else:
return
return JsonResponse({}, safe=False)
# Testa se existe alguma matéria na posição recebida
try:
@ -3138,7 +3156,7 @@ def mudar_ordem_materia_sessao(request):
materia_1.numero_ordem = posicao_final
materia_1.save()
return
return JsonResponse({}, safe=False)
class JustificativaAusenciaCrud(MasterDetailCrud):
@ -3676,3 +3694,37 @@ class VotacaoEmBlocoNominalView(TemplateView):
'origem': self.request.POST['origem']})
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:"__/__/____"});
$('.hora').mask("00:00", {placeholder:"hh:mm"});
$('.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() {

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>
Desenvolvido pelo <a href="http://www.interlegis.leg.br/">Interlegis</a> em software livre e aberto.
</small>
<span>Release: 3.1.134</span>
<span>Release: 3.1.137</span>
</p>
</div>
<div class="col-md-4">

5
sapl/templates/materia/proposicao_detail.html

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

3
sapl/templates/menu_tabelas_auxiliares.yaml

@ -152,6 +152,9 @@
- title: {% trans 'Tipo de Expediente' %}
url: sapl.sessao:tipoexpediente_list
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' %}
url: sapl.sessao:resumo_ordenacao
css_class: btn btn-link

2
sapl/templates/norma/layouts.yaml

@ -58,7 +58,7 @@ LegislacaoCitadaDetail:
TipoVinculoNormaJuridica:
{% trans 'Tipo de Vínculo entre Normas Jurídicas' %}:
- sigla:2 descricao_ativa descricao_passiva
- sigla:2 descricao_ativa descricao_passiva revoga_integralmente
NormaRelacionada:
{% 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 }} ;
{% endfor %}
</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>

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>
{% endfor %}
</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>

10
sapl/templates/sessao/layouts.yaml

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

2
sapl/templates/sessao/resumo_ata.html

@ -19,6 +19,6 @@
{% include 'sessao/blocos_ata/'|add:oitavo_ordenacao %}
{% include 'sessao/blocos_ata/'|add:nono_ordenacao %}
{% include 'sessao/blocos_ata/'|add:decimo_ordenacao %}
{% include 'sessao/blocos_ata/'|add:decimo_primeiro_ordenacao %}
{% include 'sessao/blocos_ata/'|add:decimo_primeiro_ordenacao %}
{% include 'sessao/blocos_ata/assinaturas.html' %}
{% endblock detail_content %}

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
- title: {% trans 'Ocorrências da Sessão' %}
url: ocorrencia_sessao
- title: {% trans 'Retirada de Pauta'%}
url: retiradapauta_list
- title: {% trans 'Expedientes' %}
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: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: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:tipojustificativa' %}" class="btn btn-link">Tipo de Justificativa de Ausência</a></div>
</div>

2
setup.py

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

Loading…
Cancel
Save