Browse Source

Merge branch '3.1.x' of https://github.com/interlegis/sapl into 2313-geracao-relatorios-estatisticas

pull/2429/head
Cesar Carvalho 7 years ago
parent
commit
b48b7b3129
  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. 7
      sapl/materia/views.py
  10. 13
      sapl/norma/fixtures/pre_popula_tipo_vinculo_norma.json
  11. 10
      sapl/norma/forms.py
  12. 2
      sapl/norma/migrations/0009_auto_20171113_1339.py
  13. 20
      sapl/norma/migrations/0015_auto_20181109_1422.py
  14. 24
      sapl/norma/migrations/0016_tipovinculonormajuridica_revoga_integramente.py
  15. 5
      sapl/norma/models.py
  16. 17
      sapl/norma/views.py
  17. 1
      sapl/painel/views.py
  18. 2
      sapl/parlamentares/forms.py
  19. 1
      sapl/parlamentares/tests/test_parlamentares.py
  20. 2
      sapl/parlamentares/views.py
  21. 12
      sapl/relatorios/templates/pdf_pauta_sessao_gerar.py
  22. 1
      sapl/relatorios/templates/pdf_pauta_sessao_preparar_pysc.py
  23. 38
      sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
  24. 230
      sapl/relatorios/views.py
  25. 2
      sapl/rules/map_rules.py
  26. 111
      sapl/sessao/forms.py
  27. 50
      sapl/sessao/migrations/0028_auto_20181031_0902.py
  28. 27
      sapl/sessao/migrations/0030_auto_20181113_1149.py
  29. 20
      sapl/sessao/migrations/0030_resumoordenacao_decimo_primeiro.py
  30. 21
      sapl/sessao/migrations/0031_auto_20181116_1849.py
  31. 20
      sapl/sessao/migrations/0031_auto_20181119_1103.py
  32. 16
      sapl/sessao/migrations/0032_merge_20181122_1527.py
  33. 66
      sapl/sessao/models.py
  34. 7
      sapl/sessao/urls.py
  35. 119
      sapl/sessao/views.py
  36. 10
      sapl/static/js/app.js
  37. 40
      sapl/static/styles/app.scss
  38. 2
      sapl/templates/base.html
  39. 5
      sapl/templates/materia/proposicao_detail.html
  40. 3
      sapl/templates/menu_tabelas_auxiliares.yaml
  41. 6
      sapl/templates/norma/layouts.yaml
  42. 4
      sapl/templates/protocoloadm/comprovante.html
  43. 6
      sapl/templates/sessao/blocos_ata/lista_presenca.html
  44. 1
      sapl/templates/sessao/blocos_ata/lista_presenca_ordem_dia.html
  45. 25
      sapl/templates/sessao/blocos_resumo/lista_presenca.html
  46. 2
      sapl/templates/sessao/blocos_resumo/materias_expediente.html
  47. 6
      sapl/templates/sessao/expedientemateria_list.html
  48. 10
      sapl/templates/sessao/layouts.yaml
  49. 6
      sapl/templates/sessao/ordemdia_list.html
  50. 4
      sapl/templates/sessao/pauta_sessao_detail.html
  51. 155
      sapl/templates/sessao/presenca.html
  52. 145
      sapl/templates/sessao/presenca_ordemdia.html
  53. 6
      sapl/templates/sessao/retiradapauta_form.html
  54. 2
      sapl/templates/sessao/subnav.yaml
  55. 1
      sapl/templates/sistema.html
  56. 2
      setup.py

2
docker-compose.yml

@ -11,7 +11,7 @@ sapldb:
ports:
- "5432:5432"
sapl:
image: interlegis/sapl:3.1.132
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

@ -129,22 +129,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

7
sapl/materia/views.py

@ -2179,6 +2179,10 @@ class EtiquetaPesquisaView(PermissionRequiredMixin, FormView):
if context['quantidade'] > 20:
materias = materias[:20]
for m in materias:
if len(m.ementa) > 100:
m.ementa = m.ementa[0:99] + "[...]"
context['materias'] = materias
return gerar_pdf_impressos(self.request, context,
@ -2267,7 +2271,8 @@ class FichaSelecionaView(PermissionRequiredMixin, FormView):
self.messages.add_message(self.request, messages.INFO, mensagem)
return self.render_to_response(context)
if len(materia.ementa) > 301:
materia.ementa = materia.ementa[0:300] + '[...]'
context['materia'] = materia
context['despachos'] = materia.despachoinicial_set.all().values_list(
'comissao__nome', flat=True)

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"

10
sapl/norma/forms.py

@ -64,7 +64,7 @@ class NormaFilterSet(django_filters.FilterSet):
class Meta:
model = NormaJuridica
fields = ['tipo', 'numero', 'ano', 'data',
fields = ['tipo', 'numero', 'ano', 'data', 'data_vigencia',
'data_publicacao', 'ementa', 'assuntos']
def __init__(self, *args, **kwargs):
@ -73,13 +73,14 @@ class NormaFilterSet(django_filters.FilterSet):
row1 = to_row([('tipo', 4), ('numero', 4), ('ano', 4)])
row2 = to_row([('data', 6), ('data_publicacao', 6)])
row3 = to_row([('ementa', 6), ('assuntos', 6)])
row4 = to_row([('o',6), ('indexacao', 6)])
row4 = to_row([('data_vigencia', 12)])
row5 = to_row([('o',6), ('indexacao', 6)])
self.form.helper = FormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Norma'),
row1, row2, row3, row4,
row1, row2, row3, row4, row5,
form_actions(label='Pesquisar'))
)
@ -120,6 +121,7 @@ class NormaJuridicaForm(ModelForm):
'numero_materia',
'ano_materia',
'data_publicacao',
'data_vigencia',
'veiculo_publicacao',
'pagina_inicio_publicacao',
'pagina_fim_publicacao',
@ -342,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 = [

20
sapl/norma/migrations/0015_auto_20181109_1422.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-09 16:22
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('norma', '0014_auto_20181008_1655'),
]
operations = [
migrations.AlterField(
model_name='normajuridica',
name='data_vigencia',
field=models.DateField(blank=True, null=True, verbose_name='Data Fim Vigência'),
),
]

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),
]

5
sapl/norma/models.py

@ -119,7 +119,7 @@ class NormaJuridica(models.Model):
assuntos = models.ManyToManyField(
AssuntoNorma, blank=True,
verbose_name=_('Assuntos'))
data_vigencia = models.DateField(blank=True, null=True)
data_vigencia = models.DateField(blank=True, null=True, verbose_name=_('Data Fim Vigência'))
timestamp = models.DateTimeField(null=True)
texto_articulado = GenericRelation(
@ -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]

38
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),
@ -352,11 +363,12 @@ def principal(cabecalho_dic, rodape_dic, imagem, sessao, inf_basicas_dic, lst_me
tmp += dict_ord_template[ordenacao.oitavo]
tmp += dict_ord_template[ordenacao.nono]
tmp += dict_ord_template[ordenacao.decimo]
tmp += dict_ord_template[ordenacao.decimo_primeiro]
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)

230
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,
@ -466,6 +467,29 @@ def get_espelho(mats):
return materias
def remove_html_comments(text):
"""
Assume comentários bem formados <!-- texto --> e
não aninhados como <!-- <!-- texto --> -->
:param text:
:return:
"""
clean_text = text
start = clean_text.find('<!--')
while start > -1:
end = clean_text.find('-->') + 2
output_text = []
for idx, i in enumerate(clean_text):
if not start <= idx <= end:
output_text.append(i)
clean_text = ''.join(output_text)
start = clean_text.find('<!--')
# por algum motivo usar clean_text ao invés de len(clean_text)
# não tava funcionando
return clean_text if len(clean_text) > 0 else text
def get_sessao_plenaria(sessao, casa):
inf_basicas_dic = {}
@ -515,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 = []
@ -535,6 +573,9 @@ def get_sessao_plenaria(sessao, casa):
# https://github.com/interlegis/sapl/issues/1009
conteudo = conteudo.replace('&', '&amp;')
# https://github.com/interlegis/sapl/issues/2386
conteudo = remove_html_comments(conteudo)
dic_expedientes["txt_expediente"] = conteudo
if dic_expedientes:
@ -546,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 + ' ' +
@ -559,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"] = ' '
@ -648,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
@ -661,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
@ -677,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"] = ' '
@ -704,11 +717,10 @@ def get_sessao_plenaria(sessao, casa):
if resultados:
for i in resultados:
dic_votacao["nom_resultado"] = i.tipo_resultado_votacao.nome
if votacao.observacao:
if i.observacao:
dic_votacao["votacao_observacao"] = i.observacao
else:
dic_votacao["nom_resultado"] = "Matéria não votada"
dic_votacao["votacao_observacao"] = " "
lst_votacao.append(dic_votacao)
# Lista dos oradores nas Explicações Pessoais
@ -754,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,
@ -763,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):
@ -794,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)
@ -808,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,
@ -824,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,
@ -1023,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)
@ -1031,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,
@ -1058,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()
@ -1077,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
@ -1132,30 +1127,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__),

111
sapl/sessao/forms.py

@ -1,3 +1,4 @@
from datetime import datetime
from crispy_forms.helper import FormHelper
@ -22,11 +23,11 @@ from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato
from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES,
MateriaPesquisaOrderingFilter, autor_label,
autor_modal, timezone)
from .models import (Bancada, Bloco, ExpedienteMateria, Orador, JustificativaAusencia,
OradorExpediente, OrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoResultadoVotacao, OcorrenciaSessao,
RetiradaPauta, TipoRetiradaPauta)
from .models import (Bancada, Bloco, ExpedienteMateria, JustificativaAusencia,
Orador, OradorExpediente, OrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoJustificativa, TipoResultadoVotacao,
OcorrenciaSessao)
def recupera_anos():
@ -59,7 +60,7 @@ ORDENACAO_RESUMO = [('cont_mult', 'Conteúdo Multimídia'),
('mesa_d', 'Mesa Diretora'),
('oradores_exped', 'Oradores do Expediente'),
('oradores_expli', 'Oradores das Explicações Pessoais'),
('ocorrencia_sessao', 'Ocorrências da Sessão')]
('ocorr_sessao', 'Ocorrências da Sessão')]
class SessaoPlenariaForm(ModelForm):
@ -190,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:
@ -638,6 +733,8 @@ class ResumoOrdenacaoForm(forms.Form):
choices=ORDENACAO_RESUMO)
decimo = forms.ChoiceField(label='10°',
choices=ORDENACAO_RESUMO)
decimo_primeiro = forms.ChoiceField(label='11°',
choices=ORDENACAO_RESUMO)
def __init__(self, *args, **kwargs):
super(ResumoOrdenacaoForm, self).__init__(*args, **kwargs)
@ -662,12 +759,14 @@ class ResumoOrdenacaoForm(forms.Form):
[('nono', 12)])
row10 = to_row(
[('decimo', 12)])
row11 = to_row(
[('decimo_primeiro', 12)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_(''),
row1, row2, row3, row4, row5,
row6, row7, row8, row9, row10,
row6, row7, row8, row9, row10,row11,
form_actions(label='Atualizar'))
)

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'),
),
]

20
sapl/sessao/migrations/0030_resumoordenacao_decimo_primeiro.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-14 12:06
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sessao', '0029_auto_20181024_0952'),
]
operations = [
migrations.AddField(
model_name='resumoordenacao',
name='decimo_primeiro',
field=models.CharField(default='', max_length=30),
),
]

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'),
),
]

20
sapl/sessao/migrations/0031_auto_20181119_1103.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-11-19 13:03
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sessao', '0030_resumoordenacao_decimo_primeiro'),
]
operations = [
migrations.AlterField(
model_name='resumoordenacao',
name='decimo_primeiro',
field=models.CharField(default='Ocorrências da Sessão', max_length=30),
),
]

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 = [
]

66
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
@ -575,6 +576,7 @@ class ResumoOrdenacao(models.Model):
oitavo = models.CharField(max_length=30)
nono = models.CharField(max_length=30)
decimo = models.CharField(max_length=30)
decimo_primeiro = models.CharField(max_length=30,default="Ocorrências da Sessão")
class Meta:
verbose_name = _('Ordenação do Resumo de uma Sessão')
@ -583,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):
@ -661,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,
@ -39,7 +40,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'),
@ -76,6 +77,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/',

119
sapl/sessao/views.py

@ -1,3 +1,4 @@
from operator import itemgetter
import logging
from re import sub
@ -42,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):
@ -196,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]
@ -220,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:
@ -293,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()
@ -783,8 +797,8 @@ class PresencaView(FormMixin, PresencaMixin, DetailView):
sessao.sessao_plenaria = self.object
sessao.parlamentar = Parlamentar.objects.get(id=p)
sessao.save()
username = request.user.username
self.logger.info("user=" + username + ". SessaoPlenariaPresenca salva com sucesso (parlamentar_id={})!".format(p))
username = request.user.username
self.logger.info("user=" + username + ". SessaoPlenariaPresenca salva com sucesso (parlamentar_id={})!".format(p))
msg = _('Presença em Sessão salva com sucesso!')
messages.add_message(request, messages.SUCCESS, msg)
@ -832,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({
@ -1335,7 +1342,13 @@ 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})
# =====================================================================
# Expedientes
@ -1368,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 = _(' ')
@ -1387,7 +1403,8 @@ class ResumoView(DetailView):
'resultado_observacao': resultado_observacao,
'autor': autor,
'numero_protocolo': m.materia.numero_protocolo,
'numero_processo': m.materia.numeracao_set.last()
'numero_processo': m.materia.numeracao_set.last(),
'observacao': m.observacao
}
materias_expediente.append(mat)
@ -1459,9 +1476,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 = _(' ')
@ -1541,7 +1562,8 @@ class ResumoView(DetailView):
'setimo_ordenacao': dict_ord_template[ordenacao.setimo],
'oitavo_ordenacao': dict_ord_template[ordenacao.oitavo],
'nono_ordenacao': dict_ord_template[ordenacao.nono],
'decimo_ordenacao': dict_ord_template[ordenacao.decimo]})
'decimo_ordenacao': dict_ord_template[ordenacao.decimo],
'decimo_primeiro_ordenacao': dict_ord_template[ordenacao.decimo_primeiro]})
else:
context.update(
{'primeiro_ordenacao': dict_ord_template['id_basica'],
@ -2744,6 +2766,7 @@ class PautaSessaoDetailView(DetailView):
mat = {'id': m.materia_id,
'ementa': ementa,
'observacao': m.observacao,
'titulo': titulo,
'numero': numero,
'resultado': resultado,
@ -2807,6 +2830,7 @@ class PautaSessaoDetailView(DetailView):
mat = {'id': o.materia_id,
'ementa': ementa,
'observacao': o.observacao,
'titulo': titulo,
'numero': numero,
'resultado': resultado,
@ -3096,7 +3120,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:
@ -3135,7 +3159,7 @@ def mudar_ordem_materia_sessao(request):
materia_1.numero_ordem = posicao_final
materia_1.save()
return
return JsonResponse({}, safe=False)
class JustificativaAusenciaCrud(MasterDetailCrud):
@ -3215,3 +3239,38 @@ class JustificativaAusenciaCrud(MasterDetailCrud):
class DeleteView(MasterDetailCrud.DeleteView):
pass
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

10
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() {
@ -192,20 +192,12 @@ function OptionalCustomFrontEnd() {
_label = $('<label[for='+this.id+']/>').insertBefore(this)
}
}
/*var _controls = _label.closest('.controls');
if (!_controls.length) {
_controls = $('<div class="controls"/>').insertBefore(_label)
_controls.append(_label)
}*/
if (this.type === "checkbox") {
_label.addClass('checkbox-inline');
_label.prepend(_this);
_this.checkbox();
}
else if (this.type === "radio") {
_label.addClass('radio-inline');
_label.prepend(_this);
_this.radio();

40
sapl/static/styles/app.scss

@ -222,21 +222,49 @@ nav {
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px;
.checkbox, .radio, .checkbox-inline, .radio-inline {
padding: 8px 8px 8px 36px;
margin: 0;
line-height: 1.6;
display: block;
&:hover {
background-color: #d6e1e5;
}
.icons {
top: auto;
left: 8px;
}
}
.checkbox-inline, .radio-inline {
display: inline-block;
}
.help-block {
margin: $grid-gutter-width / 2;
padding: $grid-gutter-width / 2;
border: 2px dashed #d6e1e5;
}
}
.controls-radio-checkbox__old {
padding: 0px;
border: 1px solid #d6e1e5;
border-radius: 4px;
min-height: 20px;
label {
padding: 5px;
padding: 0;
line-height: 2.7;
padding-left: 36px;
.icons {
top: 5px;
top: 8px;
left: 8px;
}
&.checkbox-inline, &.radio-inline {
padding: 8px;
padding-left: 36px;
&.checkbox-inline, &.radio-inline, {
padding-right: 8px;
.icons {
top: 8px;
left: 8px;
@ -244,7 +272,7 @@ nav {
}
}
.checkbox, .radio, .checkbox-inline, .radio-inline {
margin: 0;
margin: 0;
&:hover {
background-color: #d6e1e5;
}

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.132</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

6
sapl/templates/norma/layouts.yaml

@ -17,7 +17,7 @@ NormaJuridica:
- tipo numero ano
- data esfera_federacao complemento
- materia
- data_publicacao veiculo_publicacao pagina_inicio_publicacao pagina_fim_publicacao
- data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao
- texto_integral
- ementa
- indexacao
@ -35,7 +35,7 @@ NormaJuridicaCreate:
- tipo ano numero
- data esfera_federacao complemento
- tipo_materia numero_materia ano_materia
- data_publicacao veiculo_publicacao pagina_inicio_publicacao pagina_fim_publicacao
- data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao
- texto_integral
- ementa
- indexacao
@ -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' %}:

4
sapl/templates/protocoloadm/comprovante.html

@ -3,7 +3,7 @@
{% load static %}
{% block detail_content %}
<style>
<style xmlns:max-width="http://www.w3.org/1999/xhtml">
table {
width: 100%;
}
@ -25,7 +25,7 @@
<table>
<tr><td colspan="2" align="center">
<img height="150" width="150"
<img height="90" width="90"
src="{% if logotipo %}{{ MEDIA_URL }}{{ logotipo }}{% else %}{% static 'img/logo.png' %}{% endif %}"
alt="Logotipo"
class="img-responsive visible-lg-inline-block vcenter">

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>

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

@ -7,4 +7,5 @@
{{p.nome_parlamentar}} / {{ p|filiacao_data_filter:object.data_inicio }} ;
{% 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>

2
sapl/templates/sessao/blocos_resumo/materias_expediente.html

@ -33,7 +33,7 @@
<b>Processo:</b> {{ m.numero_processo }}
{% endif %}
</td>
<td>{{m.ementa|safe}}</td>
<td>{{m.ementa|safe}}<br/>{{m.observacao}}</td>
<td><b>{{m.resultado}}</b><br/>{{m.resultado_observacao}}</td>
</tr>
{% endfor %}

6
sapl/templates/sessao/expedientemateria_list.html

@ -22,6 +22,12 @@
var pk_sessao = {{root_pk}};
var pk_list = {{ object_list|to_list_pk|safe }};
$(document).on('keyup', (e) => {
if (e.keyCode == 86){
window.open("{% url 'sapl.painel:voto_individual' %}",'Voto Individual','width=1000, height=800, scrollbars=yes');
};
});
$('tbody').sortable({
start: function(event, ui) {

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

6
sapl/templates/sessao/ordemdia_list.html

@ -22,6 +22,12 @@
var pk_sessao = {{root_pk}};
var pk_list = {{ object_list|to_list_pk|safe }};
$(document).on('keyup', (e) => {
if (e.keyCode == 86){
window.open("{% url 'sapl.painel:voto_individual' %}",'Voto Individual','width=1000, height=800, scrollbars=yes');
};
});
$('tbody').sortable({
start: function(event, ui) {

4
sapl/templates/sessao/pauta_sessao_detail.html

@ -34,7 +34,7 @@
<br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</td>
<td style="width:70%;">{{m.ementa|safe}}</td>
<td style="width:70%;">{{m.ementa|safe}}<br>{{m.observacao|safe}}</td>
<td style="width:10%;">{{m.situacao}}</td>
</tr>
{% endfor %}
@ -62,7 +62,7 @@
<br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</td>
<td style="width:70%;">{{m.ementa|safe}}</td>
<td style="width:70%;">{{m.ementa|safe}}<br>{{m.observacao|safe}}</td>
<td style="width:10%;">{{m.situacao}}</td>
</tr>
{% endfor %}

155
sapl/templates/sessao/presenca.html

@ -5,91 +5,90 @@
{% block actions %}{% endblock %}
{% block detail_content %}
{% if perms|get_add_perm:view %}
<form method="POST">
{% csrf_token %}
<div class="controls">
<div class="checkbox">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(event)" /> Marcar/Desmarcar Todos
</label>
</div>
</div>
<br />
<div class="controls">
<div class="checkbox">
<label for="id_ativos">
<input type="checkbox" name="ativos" id="id_ativos" onchange="escondeInativos()" checked /> Exibir somente parlamentares ativos
</label>
</div>
</div>
<br />
<div class="controls">
{% for parlamentar, check in view.get_presencas %}
{% if parlamentar.ativo %}
<div class="checkbox">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_ativos" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% else %}
<div class="checkbox inativos" style="display:none;">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_inativos" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% endif %}
{% endfor %}
<form method="POST">
{% csrf_token %}
<div class="controls">
<div class="checkbox">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(event)" /> Marcar/Desmarcar Todos
</label>
</div>
<br />
<input type="submit" value="Salvar" class="btn btn-primary" />
</form>
{% else %}
<div class="row">
<div class="col-md-6"><h2>Parlamentares presentes</div>
</div>
</br>
</div>
<br />
<div class="controls">
<div class="checkbox">
<label for="id_ativos">
<input type="checkbox" name="ativos" id="id_ativos" onchange="escondeInativos()" checked /> Exibir somente
parlamentares ativos
</label>
</div>
</div>
<br />
<div class="controls ">
{% for parlamentar, check in view.get_presencas %}
{% if check %}
<div class="row">
<div class="col-md-6"><label for="parlamentar"> - {{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}</label></div>
</div>
{% endif %}
{% if parlamentar.ativo %}
<div class="checkbox">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_ativos" value="{{ parlamentar.id }}"
{% if check %} checked {% endif %}>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% else %}
<div class="checkbox inativos" style="display:none;">
<label for="id_presenca_{{forloop.counter}}" class="inativos" style="display:none;">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_inativos" value="{{ parlamentar.id }}"
{% if check %} checked {% endif %}>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
<br />
<input type="submit" value="Salvar" class="btn btn-primary" />
</form>
{% endif %}
{% else %}
<div class="row">
<div class="col-md-6">
<h2>Parlamentares presentes
</div>
</div>
<br />
{% for parlamentar, check in view.get_presencas %}
{% if check %}
<div class="row">
<div class="col-md-6">
<label for="parlamentar"> - {{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock detail_content %}
{% block extra_js %}
<script language="JavaScript">
function checkAll(event) {
$('[name=presenca_ativos]').each(function() {
$(this).prop('checked', event.target.checked ? 'checked': null);
$(this).trigger('click');
});
if (($('[name=ativos]').is(':checked')) == false) {
$('[name=presenca_inativos]').each(function() {
$(this).prop('checked', event.target.checked ? 'checked': null);
$(this).trigger('click');
});
}
}
function escondeInativos() {
$(".inativos").toggle();
}
</script>
<script language="JavaScript">
function checkAll(event) {
$('[name=presenca_ativos]').each(function () {
$(this).prop('checked', event.target.checked ? 'checked' : null);
$(this).trigger('click');
});
if (($('[name=ativos]').is(':checked')) == false) {
$('[name=presenca_inativos]').each(function () {
$(this).prop('checked', event.target.checked ? 'checked' : null);
$(this).trigger('click');
});
}
}
function escondeInativos() {
$(".inativos").toggle();
}
</script>
{% endblock %}

145
sapl/templates/sessao/presenca_ordemdia.html

@ -7,90 +7,93 @@
{% block detail_content %}
{% if perms|get_add_perm:view %}
<form method="POST">
{% csrf_token %}
<div class="controls">
<div class="checkbox">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(event)" /> Marcar/Desmarcar Todos
</label>
</div>
<form method="POST">
{% csrf_token %}
<div class="controls">
<div class="checkbox">
<label for="id_check_all">
<input type="checkbox" id="id_check_all" onchange="checkAll(event)" /> Marcar/Desmarcar Todos
</label>
</div>
</div>
<br />
<br />
<div class="controls">
<div class="checkbox">
<label for="id_ativos">
<input type="checkbox" name="ativos" id="id_ativos" onchange="escondeInativos()" checked /> Exibir somente parlamentares ativos
</label>
</div>
<div class="controls">
<div class="checkbox">
<label for="id_ativos">
<input type="checkbox" name="ativos" id="id_ativos" onchange="escondeInativos()" checked /> Exibir somente
parlamentares ativos
</label>
</div>
</div>
<br />
<div class="controls">
{% for parlamentar, check in view.get_presencas_ordem %}
{% if parlamentar.ativo %}
<div class="checkbox">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_ativos" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% else %}
<div class="checkbox inativos" style="display:none;">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_inativos" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/>
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
<br />
<br />
<input type="submit" value="Salvar" class="btn btn-primary" />
</form>
<div class="controls">
{% for parlamentar, check in view.get_presencas_ordem %}
{% if parlamentar.ativo %}
<div class="checkbox">
<label for="id_presenca_{{forloop.counter}}">
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_ativos" value="{{ parlamentar.id }}"
{% if check %} checked {% endif %} />
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% else %}
<div class="checkbox inativos" style="display:none;">
<label for="id_presenca_{{forloop.counter}}" >
<input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca_inativos" value="{{ parlamentar.id }}"
{% if check %} checked {% endif %} />
{{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}
</label>
</div>
{% endif %}
{% endfor %}
</div>
<br />
<input type="submit" value="Salvar" class="btn btn-primary" />
</form>
{% else %}
<div class="row">
<div class="col-md-6"><h2>Parlamentares presentes</div>
</div>
</br>
{% for parlamentar, check in view.get_presencas_ordem %}
{% if check %}
<div class="row">
<div class="col-md-6"><label for="parlamentar"> - {{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}</label></div>
</div>
{% endif %}
{% endfor %}
<div class="row">
<div class="col-md-6">
<h2>Parlamentares presentes
</div>
</div>
<br/>
{% for parlamentar, check in view.get_presencas_ordem %}
{% if check %}
<div class="row">
<div class="col-md-6"><label for="parlamentar"> - {{ parlamentar.nome_parlamentar }} / {{ parlamentar|filiacao_data_filter:object.data_inicio }}</label></div>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock detail_content %}
{% block extra_js %}
<script language="JavaScript">
function checkAll(event) {
$('[name=presenca_ativos]').each(function() {
$(this).prop('checked', event.target.checked ? 'checked': null);
$(this).trigger('click');
});
if (($('[name=ativos]').is(':checked')) == false) {
$('[name=presenca_inativos]').each(function() {
$(this).prop('checked', event.target.checked ? 'checked': null);
$(this).trigger('click');
});
}
}
function escondeInativos() {
$(".inativos").toggle();
}
</script>
<script language="JavaScript">
function checkAll(event) {
$('[name=presenca_ativos]').each(function () {
$(this).prop('checked', event.target.checked ? 'checked' : null);
$(this).trigger('click');
});
if (($('[name=ativos]').is(':checked')) == false) {
$('[name=presenca_inativos]').each(function () {
$(this).prop('checked', event.target.checked ? 'checked' : null);
$(this).trigger('click');
});
}
}
function escondeInativos() {
$(".inativos").toggle();
}
</script>
{% endblock %}

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.132',
version='3.1.137',
packages=find_packages(),
include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',

Loading…
Cancel
Save