diff --git a/docker-compose.yml b/docker-compose.yml
index e4cd84b21..5ef3b240e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,7 +11,7 @@ sapldb:
ports:
- "5432:5432"
sapl:
- image: interlegis/sapl:3.1.147
+ image: interlegis/sapl:3.1.150
restart: always
environment:
ADMIN_PASSWORD: interlegis
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 6a101e223..7e6189373 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -27,9 +27,7 @@ WeasyPrint==44
Pillow==5.1.0
gunicorn==19.9.0
-textract==1.5.0
pysolr==3.6.0
-whoosh==2.7.4
pyoai==2.5.0
diff --git a/sapl/api/views.py b/sapl/api/views.py
index 769196c76..f2f146e24 100644
--- a/sapl/api/views.py
+++ b/sapl/api/views.py
@@ -22,7 +22,7 @@ from sapl.api.forms import SaplFilterSetMixin
from sapl.api.permissions import SaplModelPermissions
from sapl.api.serializers import ChoiceSerializer
from sapl.base.models import Autor, AppConfig, DOC_ADM_OSTENSIVO
-from sapl.materia.models import Proposicao
+from sapl.materia.models import Proposicao, TipoMateriaLegislativa
from sapl.parlamentares.models import Parlamentar
from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria
@@ -349,6 +349,23 @@ class _ProposicaoViewSet(SaplSetViews['materia']['proposicao']):
return qs
+class _TipoMateriaLegislativaViewSet(SaplSetViews['materia']['tipomaterialegislativa']):
+
+ @action(detail=True, methods=['POST'])
+ def change_position(self, request, *args, **kwargs):
+ result = {
+ 'status': 200,
+ 'message': 'OK'
+ }
+ d = request.data
+ if 'pos_ini' in d and 'pos_fim' in d:
+ if d['pos_ini'] != d['pos_fim']:
+ pk = kwargs['pk']
+ TipoMateriaLegislativa.objects.reposicione(pk, d['pos_fim'])
+
+ return Response(result)
+
+
class _DocumentoAdministrativoViewSet(SaplSetViews['protocoloadm']['documentoadministrativo']):
class DocumentoAdministrativoPermission(SaplModelPermissions):
@@ -427,6 +444,7 @@ class _SessaoPlenariaViewSet(
SaplSetViews['base']['autor'] = _AutorViewSet.build_class_with_actions()
SaplSetViews['materia']['proposicao'] = _ProposicaoViewSet
+SaplSetViews['materia']['tipomaterialegislativa'] = _TipoMateriaLegislativaViewSet
SaplSetViews['parlamentares']['parlamentar'] = _ParlamentarViewSet
diff --git a/sapl/base/email_utils.py b/sapl/base/email_utils.py
index b41c68402..7c23dd2da 100644
--- a/sapl/base/email_utils.py
+++ b/sapl/base/email_utils.py
@@ -11,6 +11,7 @@ from sapl.materia.models import AcompanhamentoMateria
from sapl.protocoloadm.models import AcompanhamentoDocumento
from sapl.settings import EMAIL_SEND_USER
from sapl.utils import mail_service_configured
+from django.utils.translation import ugettext_lazy as _
def load_email_templates(templates, context={}):
@@ -208,8 +209,8 @@ def do_envia_email_tramitacao(base_url, tipo, doc_mat, status, unidade_destino):
# Envia email de tramitacao para usuarios cadastrados
#
+ logger = logging.getLogger(__name__)
if not mail_service_configured():
- logger = logging.getLogger(__name__)
logger.warning(_('Servidor de email não configurado.'))
return
@@ -220,6 +221,10 @@ def do_envia_email_tramitacao(base_url, tipo, doc_mat, status, unidade_destino):
destinatarios = AcompanhamentoDocumento.objects.filter(documento=doc_mat,
confirmado=True)
+ if not destinatarios:
+ logger.debug(_('Não existem destinatários cadastrados para essa matéria.'))
+ return
+
casa = CasaLegislativa.objects.first()
sender = EMAIL_SEND_USER
diff --git a/sapl/base/search_indexes.py b/sapl/base/search_indexes.py
index 0e0283ba8..359fbd44b 100644
--- a/sapl/base/search_indexes.py
+++ b/sapl/base/search_indexes.py
@@ -1,5 +1,4 @@
import os.path
-import textract
import logging
from django.db.models import F, Q, Value
@@ -11,7 +10,6 @@ from haystack.constants import Indexable
from haystack.fields import CharField
from haystack.indexes import SearchIndex
from haystack.utils import get_model_ct_tuple
-from textract.exceptions import ExtensionNotSupported
from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_PUBLIC,
STATUS_TA_PUBLIC, Dispositivo)
@@ -49,19 +47,6 @@ class TextExtractField(CharField):
data = ''
return data
- def whoosh_extraction(self, arquivo):
-
- if arquivo.path.endswith('html') or arquivo.path.endswith('xml'):
- with open(arquivo.path, 'r', encoding="utf8", errors='ignore') as f:
- content = ' '.join(f.read())
- return RemoveTag(content)
-
- else:
- return textract.process(
- arquivo.path,
- language='pt-br').decode('utf-8').replace('\n', ' ').replace(
- '\t', ' ')
-
def print_error(self, arquivo, error):
msg = 'Erro inesperado processando arquivo %s erro: %s' % (
arquivo.path, error)
@@ -80,20 +65,6 @@ class TextExtractField(CharField):
except Exception as err:
print(str(err))
self.print_error(arquivo, err)
-
- # Em ambiente de DEV utiliza-se o Whoosh
- # Como ele não possui extração, faz-se uso do textract
- else:
- try:
- self.logger.debug("Tentando whoosh_extraction no arquivo {}".format(arquivo.path))
- return self.whoosh_extraction(arquivo)
- self.print_error(arquivo)
- except ExtensionNotSupported as err:
- print(str(err))
- self.logger.error(str(err))
- except Exception as err:
- print(str(err))
- self.print_error(arquivo, str(err))
return ''
def ta_extractor(self, value):
diff --git a/sapl/base/urls.py b/sapl/base/urls.py
index 317862f18..5d12b3586 100644
--- a/sapl/base/urls.py
+++ b/sapl/base/urls.py
@@ -8,7 +8,7 @@ from django.contrib.auth.views import (password_reset, password_reset_complete,
password_reset_done)
from django.views.generic.base import RedirectView, TemplateView
-from sapl.base.views import AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_data_ultima_atualizacao
+from sapl.base.views import AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL
from .apps import AppConfig
@@ -176,7 +176,7 @@ urlpatterns = [
ListarLegislaturaInfindavelView.as_view(),
name='lista_legislatura_infindavel'),
- url(r'^sistema/data_ultima_atualizacao', get_data_ultima_atualizacao),
+ url(r'^sistema/estatisticas', get_estatistica),
# todos os sublinks de sistema devem vir acima deste
url(r'^sistema/$', permission_required('base.view_tabelas_auxiliares')
diff --git a/sapl/base/views.py b/sapl/base/views.py
index c6f982c8c..2312ab721 100644
--- a/sapl/base/views.py
+++ b/sapl/base/views.py
@@ -611,12 +611,13 @@ class RelatorioMateriasTramitacaoView(FilterView):
qs = filtra_url_materias_em_tramitacao(
qr, qs, 'tramitacao__status', 'status')
- context['object_list'] = qs
+ li = [li1 for li1 in qs if li1.tramitacao_set.last() and li1.tramitacao_set.last().status.indicador != 'F']
+ context['object_list'] = li
qtdes = {}
for tipo in TipoMateriaLegislativa.objects.all():
- qs = context['object_list']
- qtde = len(qs.filter(tipo_id=tipo.id))
+ li = context['object_list']
+ qtde = sum(1 for i in li if i.tipo_id==tipo.id)
if qtde > 0:
qtdes[tipo] = qtde
context['qtdes'] = qtdes
@@ -1234,7 +1235,9 @@ def mandato_sem_data_inicio():
return Mandato.objects.filter(data_inicio_mandato__isnull=True).order_by('parlamentar')
-def get_data_ultima_atualizacao(request):
+def get_estatistica(request):
+
+ json_dict = {}
datas = [MateriaLegislativa.objects.all().
order_by('-data_ultima_atualizacao').
@@ -1243,15 +1246,22 @@ def get_data_ultima_atualizacao(request):
NormaJuridica.objects.all().
order_by('-data_ultima_atualizacao').
values_list('data_ultima_atualizacao', flat=True).
- first()]
+ first()] # Retorna [None, None] se inexistem registros
max_data = ''
if datas[0] and datas[1]:
max_data = max(datas)
else:
- max_data = next([i for i in datas if i is not None], '')
- return JsonResponse({'data_ultima_atualizacao': max_data})
+ max_data = next(iter([i for i in datas if i is not None]), '')
+
+ json_dict["data_ultima_atualizacao"] = max_data
+ json_dict["num_materias_legislativas"] = MateriaLegislativa.objects.all().count()
+ json_dict["num_normas_juridicas "] = NormaJuridica.objects.all().count()
+ json_dict["num_parlamentares"] = Parlamentar.objects.all().count()
+ json_dict["num_sessoes_plenarias"] = SessaoPlenaria.objects.all().count()
+
+ return JsonResponse(json_dict)
class ListarMandatoSemDataInicioView(PermissionRequiredMixin, ListView):
@@ -1452,7 +1462,7 @@ class PesquisarUsuarioView(PermissionRequiredMixin, FilterView):
data = self.filterset.data
url = ''
if data:
- url = "&" + str(self.request.environ['QUERY_STRING'])
+ url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('username=') - 1
url = url[ponto_comeco:]
diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py
index 743eaa58f..d6d129b11 100644
--- a/sapl/comissoes/views.py
+++ b/sapl/comissoes/views.py
@@ -186,6 +186,7 @@ class MateriasTramitacaoListView(ListView):
context = super(
MateriasTramitacaoListView, self).get_context_data(**kwargs)
context['object'] = Comissao.objects.get(id=self.kwargs['pk'])
+ context['qtde'] = self.object_list.count()
return context
diff --git a/sapl/compilacao/forms.py b/sapl/compilacao/forms.py
index 71d6ad7e5..222a86aed 100644
--- a/sapl/compilacao/forms.py
+++ b/sapl/compilacao/forms.py
@@ -3,7 +3,6 @@ from datetime import timedelta
from crispy_forms.bootstrap import (Alert, FieldWithButtons, FormActions,
InlineCheckboxes, InlineRadios,
StrictButton)
-from sapl.crispy_layout_mixin import SaplFormHelper
from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset,
Layout, Row, Submit)
from django import forms
@@ -23,10 +22,12 @@ from sapl.compilacao.models import (NOTAS_PUBLICIDADE_CHOICES,
TipoTextoArticulado, TipoVide,
VeiculoPublicacao, Vide)
from sapl.compilacao.utils import DISPOSITIVO_SELECT_RELATED
+from sapl.crispy_layout_mixin import SaplFormHelper
from sapl.crispy_layout_mixin import SaplFormLayout, to_column, to_row,\
form_actions
from sapl.utils import YES_NO_CHOICES
+
error_messages = {
'required': _('Este campo é obrigatório'),
'invalid': _('URL inválida.')
@@ -59,6 +60,13 @@ class TipoTaForm(ModelForm):
widget=forms.RadioSelect(),
required=True)
+ rodape_global = forms.CharField(
+ label=TipoTextoArticulado._meta.get_field(
+ 'rodape_global').verbose_name,
+ widget=forms.Textarea(attrs={'id': 'texto-rico'}),
+ required=False
+ )
+
class Meta:
model = TipoTextoArticulado
fields = ['sigla',
@@ -66,10 +74,12 @@ class TipoTaForm(ModelForm):
'content_type',
'participacao_social',
'publicacao_func',
- 'perfis'
+ 'perfis',
+ 'rodape_global'
]
- widgets = {'perfis': widgets.CheckboxSelectMultiple()}
+ widgets = {'perfis': widgets.CheckboxSelectMultiple(),
+ 'rodape_global': forms.Textarea}
def __init__(self, *args, **kwargs):
@@ -84,12 +94,18 @@ class TipoTaForm(ModelForm):
('perfis', 12),
])
+ row3 = to_row([
+ ('rodape_global', 12),
+ ])
+
self.helper = SaplFormHelper()
self.helper.layout = SaplFormLayout(
Fieldset(_('Identificação Básica'),
row1, css_class="col-md-12"),
Fieldset(_('Funcionalidades'),
- row2, css_class="col-md-12"))
+ row2, css_class="col-md-12"),
+ Fieldset(_('Nota de Rodapé Global'),
+ row3, css_class="col-md-12"))
super(TipoTaForm, self).__init__(*args, **kwargs)
diff --git a/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py b/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py
new file mode 100644
index 000000000..f3b0e323b
--- /dev/null
+++ b/sapl/compilacao/migrations/0011_tipotextoarticulado_rodape_global.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-03-26 18:59
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('compilacao', '0010_auto_20181004_1939'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='tipotextoarticulado',
+ name='rodape_global',
+ field=models.TextField(default='', help_text='A cada Tipo de Texto Articulado pode ser adicionado uma nota global de rodapé!', verbose_name='Rodapé Global'),
+ ),
+ ]
diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py
index f36e406f9..f64285aee 100644
--- a/sapl/compilacao/models.py
+++ b/sapl/compilacao/models.py
@@ -149,6 +149,13 @@ class TipoTextoArticulado(models.Model):
em edição.
"""))
+ rodape_global = models.TextField(
+ verbose_name=_('Rodapé Global'),
+ help_text=_('A cada Tipo de Texto Articulado pode ser adicionado '
+ 'uma nota global de rodapé!'),
+ default=''
+ )
+
class Meta:
verbose_name = _('Tipo de Texto Articulado')
verbose_name_plural = _('Tipos de Texto Articulados')
diff --git a/sapl/crud/base.py b/sapl/crud/base.py
index 5fa4f70e5..98af2a3bb 100644
--- a/sapl/crud/base.py
+++ b/sapl/crud/base.py
@@ -2,7 +2,6 @@ import logging
from braces.views import FormMessagesMixin
from crispy_forms.bootstrap import FieldWithButtons, StrictButton
-from sapl.crispy_layout_mixin import SaplFormHelper
from crispy_forms.layout import Field, Layout
from django import forms
from django.conf.urls import url
@@ -25,6 +24,7 @@ from django.views.generic.base import ContextMixin
from django.views.generic.list import MultipleObjectMixin
from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display
+from sapl.crispy_layout_mixin import SaplFormHelper
from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL,
RP_LIST)
from sapl.settings import BASE_DIR
@@ -449,18 +449,28 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
if not n:
s += '
'
continue
+
m = obj
n = n.split('__')
for f in n[:-1]:
m = getattr(m, f)
if not m:
break
+
+ ss = ''
if m:
ss = get_field_display(m, n[-1])[1]
ss = (
('
' if '
' in ss else ' - ') + ss)\
if ss and j != 0 and s else ss
+
+ hook = 'hook_{}'.format(''.join(n))
+ if hasattr(self, hook):
+ hs, url = getattr(self, hook)(obj, ss, url)
+ s += str(hs)
+ else:
s += ss
+
r.append((s, url))
return r
@@ -571,6 +581,8 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
rmo = rmo[0]
if not isinstance(rmo, str):
rmo = rmo[0]
+ if rmo.startswith('-'):
+ rmo = rmo[1:]
fo = '%s__%s' % (fo, rmo)
fo = desc + fo
diff --git a/sapl/lexml/OAIServer.py b/sapl/lexml/OAIServer.py
index 2a5745d67..4c1d85c19 100644
--- a/sapl/lexml/OAIServer.py
+++ b/sapl/lexml/OAIServer.py
@@ -26,7 +26,7 @@ class OAILEXML:
def __call__(self, element, metadata):
data = metadata.record
- if data['metadata']:
+ if data.get('metadata'):
value = etree.XML(data['metadata'])
element.append(value)
@@ -55,7 +55,7 @@ class OAIServer:
granularity='YYYY-MM-DDThh:mm:ssZ',
compression=['identity'],
toolkit_description=False)
- if self.config['descricao']:
+ if self.config.get('descricao'):
result.add_description(self.config['descricao'])
return result
@@ -89,7 +89,7 @@ class OAIServer:
def create_header(self, record):
oai_id = self.get_oai_id(record['record']['id'])
- timestamp = record['record']['when_modified']
+ timestamp = record['record']['when_modified'] if record['record']['when_modified'] else datetime.now()
timestamp = timestamp.replace(tzinfo=None)
sets = []
deleted = record['record']['deleted']
diff --git a/sapl/lexml/views.py b/sapl/lexml/views.py
index 46945aa2c..92fee8310 100644
--- a/sapl/lexml/views.py
+++ b/sapl/lexml/views.py
@@ -18,10 +18,15 @@ class LexmlProvedorCrud(Crud):
class DetailView(Crud.DetailView):
layout_key = 'LexmlProvedorDetail'
+
def lexml_request(request):
+ request_dict = request.GET.copy()
+ if request_dict.get('batch_size'):
+ del request_dict['batch_size']
+
config = get_config(request.get_raw_uri(), int(request.GET.get('batch_size', '10')))
oai_server = OAIServerFactory(config)
- r = oai_server.handleRequest(request.GET)
+ r = oai_server.handleRequest(request_dict)
response = r.decode('UTF-8')
return HttpResponse(response, content_type='text/xml')
diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py
index 33f4d3b26..4b75e134a 100644
--- a/sapl/materia/forms.py
+++ b/sapl/materia/forms.py
@@ -1151,8 +1151,6 @@ class AnexadaEmLoteFilterSet(django_filters.FilterSet):
self.filters['tipo'].label = 'Tipo de Matéria'
self.filters['data_apresentacao'].label = 'Data (Inicial - Final)'
- self.form.fields['tipo'].required = True
- self.form.fields['data_apresentacao'].required = True
row1 = to_row([('tipo', 12)])
row2 = to_row([('data_apresentacao', 12)])
@@ -1160,7 +1158,7 @@ class AnexadaEmLoteFilterSet(django_filters.FilterSet):
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
- Fieldset(_('Matéria Anexada em Lote'),
+ Fieldset(_('Pesquisa de Matérias'),
row1, row2, form_actions(label='Pesquisar')))
@@ -2396,3 +2394,72 @@ class ExcluirTramitacaoEmLote(forms.Form):
form_actions(label='Excluir')
)
)
+
+
+class MateriaPesquisaSimplesForm(forms.Form):
+ tipo_materia = forms.ModelChoiceField(
+ label=TipoMateriaLegislativa._meta.verbose_name,
+ queryset=TipoMateriaLegislativa.objects.all(),
+ required=False,
+ empty_label='Selecione')
+
+ data_inicial = forms.DateField(
+ label='Data Inicial',
+ required=False,
+ widget=forms.DateInput(format='%d/%m/%Y')
+ )
+
+ data_final = forms.DateField(
+ label='Data Final',
+ required=False,
+ widget=forms.DateInput(format='%d/%m/%Y')
+ )
+
+ titulo = forms.CharField(
+ label='Título do Relatório',
+ required=False,
+ max_length=150)
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ row1 = to_row(
+ [('tipo_materia', 6),
+ ('data_inicial', 3),
+ ('data_final', 3)])
+
+ row2 = to_row(
+ [('titulo', 12)])
+
+ self.helper = SaplFormHelper()
+ self.helper.layout = Layout(
+ Fieldset(
+ 'Índice de Materias',
+ row1, row2,
+ form_actions(label='Pesquisar')
+ )
+ )
+
+ def clean(self):
+ super().clean()
+
+ if not self.is_valid():
+ return self.cleaned_data
+
+ cleaned_data = self.cleaned_data
+ data_inicial = cleaned_data['data_inicial']
+ data_final = cleaned_data['data_final']
+
+ if data_inicial or data_final:
+ if not (data_inicial and data_final):
+ self.logger.error("Caso pesquise por data, os campos de Data Inicial e "
+ "Data Final devem ser preenchidos obrigatoriamente")
+ raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e '
+ 'Data Final devem ser preenchidos obrigatoriamente'))
+ elif data_inicial > data_final:
+ self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial))
+ raise ValidationError(_('A Data Final não pode ser menor que a Data Inicial'))
+
+ return cleaned_data
diff --git a/sapl/materia/migrations/0042_tipomaterialegislativa_sequencia_regimental.py b/sapl/materia/migrations/0042_tipomaterialegislativa_sequencia_regimental.py
new file mode 100644
index 000000000..81d1ccbcb
--- /dev/null
+++ b/sapl/materia/migrations/0042_tipomaterialegislativa_sequencia_regimental.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-03-20 11:26
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('materia', '0041_proposicao_numero_materia_futuro'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='tipomaterialegislativa',
+ name='sequencia_regimental',
+ field=models.PositiveIntegerField(
+ default=0, help_text='A sequência regimental diz respeito ao que define o regimento da Casa Legislativa sobre qual a ordem de entrada das proposições nas Sessões Plenárias.', verbose_name='Sequência Regimental'),
+ ),
+ ]
diff --git a/sapl/materia/migrations/0043_auto_20190320_1749.py b/sapl/materia/migrations/0043_auto_20190320_1749.py
new file mode 100644
index 000000000..16c05e21b
--- /dev/null
+++ b/sapl/materia/migrations/0043_auto_20190320_1749.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-03-20 20:49
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('materia', '0042_tipomaterialegislativa_sequencia_regimental'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='tipomaterialegislativa',
+ options={'ordering': ['sequencia_regimental', 'descricao'], 'verbose_name': 'Tipo de Matéria Legislativa', 'verbose_name_plural': 'Tipos de Matérias Legislativas'},
+ ),
+ ]
diff --git a/sapl/materia/models.py b/sapl/materia/models.py
index e4ae436b9..af4cb1231 100644
--- a/sapl/materia/models.py
+++ b/sapl/materia/models.py
@@ -78,8 +78,37 @@ class TipoProposicao(models.Model):
return self.descricao
+class TipoMateriaManager(models.Manager):
+
+ def reordene(self, exclude_pk=None):
+ tipos = self.get_queryset()
+ if exclude_pk:
+ tipos = tipos.exclude(pk=exclude_pk)
+ for sr, t in enumerate(tipos, 1):
+ t.sequencia_regimental = sr
+ t.save()
+
+ def reposicione(self, pk, idx):
+ tipos = self.reordene(exclude_pk=pk)
+
+ self.get_queryset(
+ ).filter(
+ sequencia_regimental__gte=idx
+ ).update(
+ sequencia_regimental=models.F('sequencia_regimental') + 1
+ )
+
+ self.get_queryset(
+ ).filter(
+ pk=pk
+ ).update(
+ sequencia_regimental=idx
+ )
+
+
@reversion.register()
class TipoMateriaLegislativa(models.Model):
+ objects = TipoMateriaManager()
sigla = models.CharField(max_length=5, verbose_name=_('Sigla'))
descricao = models.CharField(max_length=50, verbose_name=_('Descrição '))
# XXX o que é isso ?
@@ -101,10 +130,17 @@ class TipoMateriaLegislativa(models.Model):
verbose_name=_('Sequência de numeração'),
choices=SEQUENCIA_NUMERACAO)
+ sequencia_regimental = models.PositiveIntegerField(
+ default=0,
+ verbose_name=_('Sequência Regimental'),
+ help_text=_('A sequência regimental diz respeito ao que define '
+ 'o regimento da Casa Legislativa sobre qual a ordem '
+ 'de entrada das proposições nas Sessões Plenárias.'))
+
class Meta:
verbose_name = _('Tipo de Matéria Legislativa')
verbose_name_plural = _('Tipos de Matérias Legislativas')
- ordering = ['descricao']
+ ordering = ['sequencia_regimental', 'descricao']
def __str__(self):
return self.descricao
@@ -630,10 +666,15 @@ class Relatoria(models.Model):
verbose_name_plural = _('Relatorias')
def __str__(self):
- return _('%(materia)s - %(tipo)s - %(data)s') % {
+ if self.tipo_fim_relatoria:
+ return _('%(materia)s - %(tipo)s - %(data)s') % {
+ 'materia': self.materia,
+ 'tipo': self.tipo_fim_relatoria,
+ 'data': self.data_designacao_relator.strftime("%d/%m/%Y")}
+ else:
+ return _('%(materia)s - %(data)s') % {
'materia': self.materia,
- 'tipo': self.tipo_fim_relatoria,
- 'data': self.data_designacao_relator}
+ 'data': self.data_designacao_relator.strftime("%d/%m/%Y")}
@reversion.register()
@@ -920,7 +961,8 @@ class Tramitacao(models.Model):
('B', 'primeira_votacao', _('1ª Votação')),
('C', 'segunda_terceira_votacao', _('2ª e 3ª Votação')),
('D', 'deliberacao', _('Deliberação')),
- ('E', 'primeira_segunda_votacao_urgencia', _('1ª e 2ª votações em regime de urgência'))
+ ('E', 'primeira_segunda_votacao_urgencia', _(
+ '1ª e 2ª votações em regime de urgência'))
)
diff --git a/sapl/materia/urls.py b/sapl/materia/urls.py
index aea49d89d..962dc2cff 100644
--- a/sapl/materia/urls.py
+++ b/sapl/materia/urls.py
@@ -25,7 +25,8 @@ from sapl.materia.views import (AcompanhamentoConfirmarView,
TipoProposicaoCrud, TramitacaoCrud,
TramitacaoEmLoteView, UnidadeTramitacaoCrud,
proposicao_texto, recuperar_materia,
- ExcluirTramitacaoEmLoteView, RetornarProposicao)
+ ExcluirTramitacaoEmLoteView, RetornarProposicao,
+ MateriaPesquisaSimplesView)
from sapl.norma.views import NormaPesquisaSimplesView
from sapl.protocoloadm.views import (FichaPesquisaAdmView, FichaSelecionaAdmView)
@@ -49,6 +50,9 @@ urlpatterns_impressos = [
url(r'^materia/impressos/norma-pesquisa/$',
NormaPesquisaSimplesView.as_view(),
name='impressos_norma_pesquisa'),
+ url(r'^materia/impressos/materia-pesquisa/$',
+ MateriaPesquisaSimplesView.as_view(),
+ name='impressos_materia_pesquisa'),
url(r'^materia/impressos/ficha-pesquisa-adm/$',
FichaPesquisaAdmView.as_view(),
name= 'impressos_ficha_pesquisa_adm'),
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
index 66bcb1beb..696b1235a 100644
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -3,7 +3,6 @@ import logging
from random import choice
from string import ascii_letters, digits
-from sapl.crispy_layout_mixin import SaplFormHelper
from crispy_forms.layout import HTML
from django.conf import settings
from django.contrib import messages
@@ -11,7 +10,7 @@ from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.urlresolvers import reverse
-from django.db.models import Max
+from django.db.models import Max, Q
from django.http import HttpResponse, JsonResponse
from django.http.response import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
@@ -32,6 +31,7 @@ from sapl.comissoes.models import Comissao, Participacao
from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT,
STATUS_TA_PRIVATE)
from sapl.compilacao.views import IntegracaoTaView
+from sapl.crispy_layout_mixin import SaplFormHelper
from sapl.crispy_layout_mixin import SaplFormLayout, form_actions
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud,
@@ -41,7 +41,7 @@ from sapl.materia.forms import (AnexadaForm, AutoriaForm,
ConfirmarProposicaoForm,
DevolverProposicaoForm, LegislacaoCitadaForm,
OrgaoForm, ProposicaoForm, TipoProposicaoForm,
- TramitacaoForm, TramitacaoUpdateForm)
+ TramitacaoForm, TramitacaoUpdateForm, MateriaPesquisaSimplesForm)
from sapl.norma.models import LegislacaoCitada
from sapl.parlamentares.models import Legislatura
from sapl.protocoloadm.models import Protocolo
@@ -75,9 +75,6 @@ AssuntoMateriaCrud = CrudAux.build(AssuntoMateria, 'assunto_materia')
OrigemCrud = CrudAux.build(Origem, '')
-TipoMateriaCrud = CrudAux.build(
- TipoMateriaLegislativa, 'tipo_materia_legislativa')
-
RegimeTramitacaoCrud = CrudAux.build(
RegimeTramitacao, 'regime_tramitacao')
@@ -214,7 +211,8 @@ class CriarProtocoloMateriaView(CreateView):
context['form'].fields['ano'].initial = protocolo.ano
if protocolo:
if protocolo.timestamp:
- context['form'].fields['data_apresentacao'].initial = protocolo.timestamp.date()
+ context['form'].fields['data_apresentacao'].initial = protocolo.timestamp.date(
+ )
elif protocolo.timestamp_data_hora_manual:
context['form'].fields['data_apresentacao'].initial = protocolo.timestamp_data_hora_manual.date()
elif protocolo.data:
@@ -1115,7 +1113,8 @@ class RelatoriaCrud(MasterDetailCrud):
try:
self.logger.debug("user=" + username + ". Tentando obter objeto Comissao de pk={}.".format(
context['form'].initial['comissao']))
- comissao = Comissao.objects.get(pk=context['form'].initial['comissao'])
+ comissao = Comissao.objects.get(
+ pk=context['form'].initial['comissao'])
except:
self.logger.error("user=" + username + ". Objeto Comissão de pk={} não encontrado.".format(
context['form'].initial['comissao']))
@@ -1125,12 +1124,19 @@ class RelatoriaCrud(MasterDetailCrud):
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(
context['form'].initial['comissao']))
- materia = MateriaLegislativa.objects.get(pk=self.kwargs.get('pk'))
- ano_materia = materia.ano
+ materia = MateriaLegislativa.objects.get(
+ pk=self.kwargs.get('pk'))
+ data_materia = materia.data_apresentacao
- comissao = Comissao.objects.get(pk=context['form'].initial['comissao'])
- composicoes = comissao.composicao_set.all()
- composicao = comissao.composicao_set.filter(periodo__data_inicio__year=ano_materia)
+ comissao = Comissao.objects.get(
+ pk=context['form'].initial['comissao'])
+ composicao = comissao.composicao_set.filter(
+ Q(periodo__data_fim__isnull=False,
+ periodo__data_inicio__lte=data_materia,
+ periodo__data_fim__gte=data_materia) |
+ Q(periodo__data_fim__isnull=True,
+ periodo__data_inicio__lte=data_materia)
+ )
participacoes = Participacao.objects.select_related().filter(composicao=composicao)
@@ -1182,12 +1188,15 @@ class RelatoriaCrud(MasterDetailCrud):
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(
context['form'].initial['comissao']))
- relatoria = Relatoria.objects.select_related('materia').get(pk=self.kwargs.get('pk'))
+ relatoria = Relatoria.objects.select_related(
+ 'materia').get(pk=self.kwargs.get('pk'))
ano_materia = relatoria.materia.ano
- comissao = Comissao.objects.get(pk=context['form'].initial['comissao'])
+ comissao = Comissao.objects.get(
+ pk=context['form'].initial['comissao'])
composicoes = comissao.composicao_set.all()
- composicao = comissao.composicao_set.filter(periodo__data_inicio__year=ano_materia)
+ composicao = comissao.composicao_set.filter(
+ periodo__data_inicio__year=ano_materia)
participacoes = Participacao.objects.select_related().filter(composicao=composicao)
@@ -1952,11 +1961,11 @@ class AcompanhamentoMateriaView(CreateView):
"materia",
materia,
destinatario)
-
+
self.logger.debug('user=' + usuario.username + '. Foi enviado um e-mail de confirmação. Confira sua caixa \
de mensagens e clique no link que nós enviamos para \
confirmar o acompanhamento desta matéria.')
-
+
msg = _('Foi enviado um e-mail de confirmação. Confira sua caixa \
de mensagens e clique no link que nós enviamos para \
confirmar o acompanhamento desta matéria.')
@@ -1973,7 +1982,7 @@ class AcompanhamentoMateriaView(CreateView):
return self.render_to_response(
{'form': form,
'materia': materia
- })
+ })
return HttpResponseRedirect(self.get_success_url())
else:
return self.render_to_response(
@@ -2021,6 +2030,11 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
tz = timezone.get_current_timezone()
+ if len(request.POST['autor']) > 50:
+ msg = _('Autor tem que ter menos do que 50 caracteres.')
+ messages.add_message(request, messages.ERROR, msg)
+ return self.get(request, self.kwargs)
+
for materia_id in marcadas:
doc = DocumentoAcessorio()
doc.materia_id = materia_id
@@ -2036,6 +2050,7 @@ class DocumentoAcessorioEmLoteView(PermissionRequiredMixin, FilterView):
messages.add_message(request, messages.SUCCESS, msg)
return self.get(request, self.kwargs)
+
class MateriaAnexadaEmLoteView(PermissionRequiredMixin, FilterView):
filterset_class = AnexadaEmLoteFilterSet
template_name = 'materia/em_lote/anexada.html'
@@ -2049,15 +2064,31 @@ class MateriaAnexadaEmLoteView(PermissionRequiredMixin, FilterView):
context['subnav_template_name'] = 'materia/subnav.yaml'
-
context['title'] = _('Matérias Anexadas em Lote')
+
# Verifica se os campos foram preenchidos
- if not self.filterset.form.is_valid():
+ if not self.request.GET.get('tipo', " "):
+ msg =_('Por favor, selecione um tipo de matéria.')
+ messages.add_message(self.request, messages.ERROR, msg)
+
+ if not self.request.GET.get('data_apresentacao_0', " ") or not self.request.GET.get('data_apresentacao_1', " "):
+ msg =_('Por favor, preencha as datas.')
+ messages.add_message(self.request, messages.ERROR, msg)
+
+ return context
+
+ if not self.request.GET.get('data_apresentacao_0', " ") or not self.request.GET.get('data_apresentacao_1', " "):
+ msg =_('Por favor, preencha as datas.')
+ messages.add_message(self.request, messages.ERROR, msg)
return context
qr = self.request.GET.copy()
context['object_list'] = context['object_list'].order_by(
'ano', 'numero')
+ principal = MateriaLegislativa.objects.get(pk=self.kwargs['pk'])
+ not_list = [self.kwargs['pk']] + \
+ [m for m in principal.materia_principal_set.all().values_list('materia_anexada_id', flat=True)]
+ context['object_list'] = context['object_list'].exclude(pk__in=not_list)
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['show_results'] = show_results_filter_set(qr)
@@ -2079,10 +2110,10 @@ class MateriaAnexadaEmLoteView(PermissionRequiredMixin, FilterView):
data_desanexacao = None
else:
data_desanexacao = datetime.strptime(
- request.POST['data_desanexacao'], "%d/%m/%Y").date()
+ request.POST['data_desanexacao'], "%d/%m/%Y").date()
- principal = MateriaLegislativa.objects.get(pk = kwargs['pk'])
- for materia in MateriaLegislativa.objects.filter(id__in = marcadas):
+ principal = MateriaLegislativa.objects.get(pk=kwargs['pk'])
+ for materia in MateriaLegislativa.objects.filter(id__in=marcadas):
anexada = Anexada()
anexada.materia_principal = principal
@@ -2286,13 +2317,11 @@ class ImpressosView(PermissionRequiredMixin, TemplateView):
def gerar_pdf_impressos(request, context, template_name):
template = loader.get_template(template_name)
html = template.render(context, request)
-
- pdf = weasyprint.HTML(string=html, base_url=request.build_absolute_uri()
- ).write_pdf()
+ pdf = weasyprint.HTML(
+ string=html, base_url=request.build_absolute_uri()).write_pdf()
response = HttpResponse(pdf, content_type='application/pdf')
- response['Content-Disposition'] = (
- 'inline; filename="relatorio_impressos.pdf"')
+ response['Content-Disposition'] = 'inline; filename="relatorio_impressos.pdf"'
response['Content-Transfer-Encoding'] = 'binary'
return response
@@ -2300,7 +2329,7 @@ def gerar_pdf_impressos(request, context, template_name):
class EtiquetaPesquisaView(PermissionRequiredMixin, FormView):
form_class = EtiquetaPesquisaForm
- template_name = 'materia/impressos/etiqueta.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def form_valid(self, form):
@@ -2341,7 +2370,7 @@ class EtiquetaPesquisaView(PermissionRequiredMixin, FormView):
class FichaPesquisaView(PermissionRequiredMixin, FormView):
form_class = FichaPesquisaForm
- template_name = 'materia/impressos/ficha.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def form_valid(self, form):
@@ -2359,7 +2388,7 @@ class FichaPesquisaView(PermissionRequiredMixin, FormView):
class FichaSelecionaView(PermissionRequiredMixin, FormView):
logger = logging.getLogger(__name__)
form_class = FichaSelecionaForm
- template_name = 'materia/impressos/ficha_seleciona.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def get_context_data(self, **kwargs):
@@ -2456,3 +2485,76 @@ class ExcluirTramitacaoEmLoteView(PermissionRequiredMixin, FormView):
tramitacao.delete()
return redirect(self.get_success_url())
+
+
+class MateriaPesquisaSimplesView(PermissionRequiredMixin, FormView):
+ form_class = MateriaPesquisaSimplesForm
+ template_name = 'materia/impressos/impressos_form.html'
+ permission_required = ('materia.can_access_impressos', )
+
+ def form_valid(self, form):
+ template_materia = 'materia/impressos/materias_pdf.html'
+
+ kwargs = {}
+ if form.cleaned_data.get('tipo_materia'):
+ kwargs.update({'tipo': form.cleaned_data['tipo_materia']})
+
+ if form.cleaned_data.get('data_inicial'):
+ kwargs.update({'data__gte': form.cleaned_data['data_inicial'],
+ 'data__lte': form.cleaned_data['data_final']})
+
+ materias = MateriaLegislativa.objects.filter(
+ **kwargs).order_by('-numero', 'ano')
+
+ quantidade_materias = materias.count()
+ materias = materias[:2000] if quantidade_materias > 2000 else materias
+
+ context = {'quantidade': quantidade_materias,
+ 'titulo': form.cleaned_data['titulo'],
+ 'materias': materias}
+
+ return gerar_pdf_impressos(self.request, context, template_materia)
+
+
+class TipoMateriaCrud(CrudAux):
+ model = TipoMateriaLegislativa
+
+ class DetailView(CrudAux.DetailView):
+ layout_key = 'TipoMateriaLegislativaDetail'
+
+ class DeleteView(CrudAux.DeleteView):
+ def delete(self, request, *args, **kwargs):
+ d = CrudAux.DeleteView.delete(self, request, *args, **kwargs)
+ TipoMateriaLegislativa.objects.reordene()
+ return d
+
+ class ListView(CrudAux.ListView):
+ paginate_by = None
+ layout_key = 'TipoMateriaLegislativaDetail'
+ template_name = "materia/tipomaterialegislativa_list.html"
+
+ def hook_sigla(self, obj, default, url):
+ return '{}'.format(
+ url, obj.id, obj.sigla), ''
+
+ def get(self, request, *args, **kwargs):
+ if TipoMateriaLegislativa.objects.filter(
+ sequencia_regimental=0).exists():
+ TipoMateriaLegislativa.objects.reordene()
+ return CrudAux.ListView.get(self, request, *args, **kwargs)
+
+ class CreateView(CrudAux.CreateView):
+
+ def form_valid(self, form):
+ fv = super().form_valid(form)
+
+ if not TipoMateriaLegislativa.objects.exclude(
+ sequencia_regimental=0).exists():
+ TipoMateriaLegislativa.objects.reordene()
+ else:
+ sr__max = TipoMateriaLegislativa.objects.all().aggregate(
+ Max('sequencia_regimental'))
+ self.object.sequencia_regimental = sr__max['sequencia_regimental__max'] + 1
+ self.object.save()
+
+ return fv
diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py
index 5f5e0aa37..12eee547f 100644
--- a/sapl/norma/forms.py
+++ b/sapl/norma/forms.py
@@ -392,7 +392,7 @@ class NormaPesquisaSimplesForm(forms.Form):
logger = logging.getLogger(__name__)
def __init__(self, *args, **kwargs):
- super(NormaPesquisaSimplesForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
row1 = to_row(
[('tipo_norma', 6),
@@ -405,36 +405,30 @@ class NormaPesquisaSimplesForm(forms.Form):
self.helper = SaplFormHelper()
self.helper.layout = Layout(
Fieldset(
- ('Índice de Normas'),
+ 'Índice de Normas',
row1, row2,
form_actions(label='Pesquisar')
)
)
def clean(self):
- super(NormaPesquisaSimplesForm, self).clean()
+ super().clean()
if not self.is_valid():
return self.cleaned_data
cleaned_data = self.cleaned_data
-
data_inicial = cleaned_data['data_inicial']
data_final = cleaned_data['data_final']
- if (data_inicial and data_final and
- data_inicial > data_final):
- self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(
- data_final, data_inicial))
- raise ValidationError(_(
- 'A Data Final não pode ser menor que a Data Inicial'))
- else:
- condicao1 = data_inicial and not data_final
- condicao2 = not data_inicial and data_final
- if condicao1 or condicao2:
+ if data_inicial or data_final:
+ if not(data_inicial and data_final):
self.logger.error("Caso pesquise por data, os campos de Data Inicial e "
"Data Final devem ser preenchidos obrigatoriamente")
- raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e ' +
+ raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e '
'Data Final devem ser preenchidos obrigatoriamente'))
+ elif data_inicial > data_final:
+ self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial))
+ raise ValidationError(_('A Data Final não pode ser menor que a Data Inicial'))
return cleaned_data
diff --git a/sapl/norma/views.py b/sapl/norma/views.py
index 1d0f9b28e..336c16933 100644
--- a/sapl/norma/views.py
+++ b/sapl/norma/views.py
@@ -345,12 +345,10 @@ class ImpressosView(PermissionRequiredMixin, TemplateView):
def gerar_pdf_impressos(request, context, template_name):
template = loader.get_template(template_name)
html = template.render(context, request)
- pdf = weasyprint.HTML(string=html, base_url=request.build_absolute_uri()
- ).write_pdf()
+ pdf = weasyprint.HTML(string=html, base_url=request.build_absolute_uri()).write_pdf()
response = HttpResponse(pdf, content_type='application/pdf')
- response['Content-Disposition'] = (
- 'inline; filename="relatorio_impressos.pdf"')
+ response['Content-Disposition'] = 'inline; filename="relatorio_impressos.pdf"'
response['Content-Transfer-Encoding'] = 'binary'
return response
@@ -358,29 +356,28 @@ def gerar_pdf_impressos(request, context, template_name):
class NormaPesquisaSimplesView(PermissionRequiredMixin, FormView):
form_class = NormaPesquisaSimplesForm
- template_name = 'materia/impressos/norma.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def form_valid(self, form):
- normas = NormaJuridica.objects.all().order_by(
- 'numero')
template_norma = 'materia/impressos/normas_pdf.html'
titulo = form.cleaned_data['titulo']
- if form.cleaned_data['tipo_norma']:
- normas = normas.filter(tipo=form.cleaned_data['tipo_norma'])
+ kwargs = {}
+ if form.cleaned_data.get('tipo_norma'):
+ kwargs.update({'tipo': form.cleaned_data['tipo_norma']})
- if form.cleaned_data['data_inicial']:
- normas = normas.filter(
- data__gte=form.cleaned_data['data_inicial'],
- data__lte=form.cleaned_data['data_final'])
+ if form.cleaned_data.get('data_inicial'):
+ kwargs.update({'data__gte': form.cleaned_data['data_inicial'],
+ 'data__lte': form.cleaned_data['data_final']})
- qtd_resultados = len(normas)
- if qtd_resultados > 2000:
- normas = normas[:2000]
+ normas = NormaJuridica.objects.filter(**kwargs).order_by('-numero', 'ano')
- context = {'quantidade': qtd_resultados,
+ quantidade_normas = normas.count()
+ normas = normas[:2000] if quantidade_normas > 2000 else normas
+
+ context = {'quantidade': quantidade_normas,
'titulo': titulo,
'normas': normas}
diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py
index b87831407..772f06eaa 100644
--- a/sapl/parlamentares/views.py
+++ b/sapl/parlamentares/views.py
@@ -207,7 +207,7 @@ class PesquisarParlamentarView(FilterView):
data = self.filterset.data
url = ''
if data:
- url = "&" + str(self.request.environ['QUERY_STRING'])
+ url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('nome_parlamentar=') - 1
url = url[ponto_comeco:]
diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py
index 3357a8c9e..bb5d12ed1 100755
--- a/sapl/protocoloadm/views.py
+++ b/sapl/protocoloadm/views.py
@@ -1152,7 +1152,7 @@ class ImpressosView(PermissionRequiredMixin, TemplateView):
class FichaPesquisaAdmView(PermissionRequiredMixin, FormView):
form_class = FichaPesquisaAdmForm
- template_name = 'materia/impressos/ficha.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def form_valid(self, form):
@@ -1170,7 +1170,7 @@ class FichaPesquisaAdmView(PermissionRequiredMixin, FormView):
class FichaSelecionaAdmView(PermissionRequiredMixin, FormView):
logger = logging.getLogger(__name__)
form_class = FichaSelecionaAdmForm
- template_name = 'materia/impressos/ficha_seleciona.html'
+ template_name = 'materia/impressos/impressos_form.html'
permission_required = ('materia.can_access_impressos', )
def get_context_data(self, **kwargs):
diff --git a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
index 0b5d758ca..6a39fa1c1 100644
--- a/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
+++ b/sapl/relatorios/templates/pdf_sessao_plenaria_gerar.py
@@ -6,7 +6,7 @@
"""
import os
import time
-
+import logging
from django.template.defaultfilters import safe
from django.utils.html import strip_tags
from trml2pdf import parseString
@@ -378,6 +378,7 @@ def principal(rodape_dic, imagem, inf_basicas_dic, lst_mesa, lst_presenca_sessao
"""
"""
arquivoPdf = str(int(time.time() * 100)) + ".pdf"
+ logger = logging.getLogger(__name__)
tmp = ''
tmp += '\n'
@@ -411,21 +412,37 @@ def principal(rodape_dic, imagem, inf_basicas_dic, lst_mesa, lst_presenca_sessao
'oradores_expli': oradores(lst_oradores),
'ocorr_sessao': ocorrencias(lst_ocorrencias)
}
-
+
if ordenacao:
- tmp += dict_ord_template[ordenacao.primeiro]
- tmp += dict_ord_template[ordenacao.segundo]
- tmp += dict_ord_template[ordenacao.terceiro]
- tmp += dict_ord_template[ordenacao.quarto]
- tmp += dict_ord_template[ordenacao.quinto]
- tmp += dict_ord_template[ordenacao.sexto]
- tmp += dict_ord_template[ordenacao.setimo]
- 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]
- tmp += dict_ord_template[ordenacao.decimo_segundo]
- tmp += dict_ord_template[ordenacao.decimo_terceiro]
+ try:
+ tmp += dict_ord_template[ordenacao.primeiro]
+ tmp += dict_ord_template[ordenacao.segundo]
+ tmp += dict_ord_template[ordenacao.terceiro]
+ tmp += dict_ord_template[ordenacao.quarto]
+ tmp += dict_ord_template[ordenacao.quinto]
+ tmp += dict_ord_template[ordenacao.sexto]
+ tmp += dict_ord_template[ordenacao.setimo]
+ 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]
+ tmp += dict_ord_template[ordenacao.decimo_segundo]
+ tmp += dict_ord_template[ordenacao.decimo_terceiro]
+ except KeyError as e:
+ logger.error("KeyError: " + str(e) + ". Erro ao tentar utilizar "
+ "configuração de ordenação. Utilizando ordenação padrão.")
+ tmp += inf_basicas(inf_basicas_dic)
+ tmp += mesa(lst_mesa)
+ tmp += presenca(lst_presenca_sessao, lst_ausencia_sessao)
+ tmp += expedientes(lst_expedientes)
+ tmp += expediente_materia(lst_expediente_materia)
+ tmp += expediente_materia_vot_nom(lst_expediente_materia_vot_nom)
+ tmp += oradores_expediente(lst_oradores_expediente)
+ tmp += presenca_ordem_dia(lst_presenca_ordem_dia)
+ tmp += votacao(lst_votacao)
+ tmp += votacao_vot_nom(lst_votacao_vot_nom)
+ tmp += oradores(lst_oradores)
+ tmp += ocorrencias(lst_ocorrencias)
else:
tmp += inf_basicas(inf_basicas_dic)
diff --git a/sapl/relatorios/urls.py b/sapl/relatorios/urls.py
index e31f5dcab..9ca2284a0 100644
--- a/sapl/relatorios/urls.py
+++ b/sapl/relatorios/urls.py
@@ -5,7 +5,8 @@ from .views import (relatorio_capa_processo,
relatorio_documento_administrativo, relatorio_espelho,
relatorio_etiqueta_protocolo, relatorio_materia,
relatorio_ordem_dia, relatorio_pauta_sessao,
- relatorio_protocolo, relatorio_sessao_plenaria)
+ relatorio_protocolo, relatorio_sessao_plenaria,
+ resumo_ata_pdf)
app_name = AppConfig.name
@@ -28,4 +29,6 @@ urlpatterns = [
relatorio_etiqueta_protocolo, name='relatorio_etiqueta_protocolo'),
url(r'^relatorios/pauta-sessao/(?P\d+)/$',
relatorio_pauta_sessao, name='relatorio_pauta_sessao'),
+ url(r'^relatorios/(?P\d+)/resumo_ata$',
+ resumo_ata_pdf, name='resumo_ata_pdf'),
]
diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py
index 53331eadd..dec1d50b7 100755
--- a/sapl/relatorios/views.py
+++ b/sapl/relatorios/views.py
@@ -2,12 +2,15 @@ from datetime import datetime as dt
import html
import logging
import re
+import tempfile
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404, HttpResponse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
+from django.template.loader import render_to_string
+from sapl.settings import MEDIA_URL
from sapl.base.models import Autor, CasaLegislativa
from sapl.comissoes.models import Comissao
from sapl.materia.models import (Autoria, MateriaLegislativa, Numeracao,
@@ -24,12 +27,20 @@ from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao,
from sapl.settings import STATIC_ROOT
from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data
+from sapl.sessao.views import (get_identificação_basica, get_mesa_diretora,
+ get_presenca_sessao,get_expedientes,
+ get_materias_expediente,get_oradores_expediente,
+ get_presenca_ordem_do_dia,get_materias_ordem_do_dia,
+ get_oradores_explicações_pessoais, get_ocorrencias_da_sessão)
+
from .templates import (pdf_capa_processo_gerar,
pdf_documento_administrativo_gerar, pdf_espelho_gerar,
pdf_etiqueta_protocolo_gerar, pdf_materia_gerar,
pdf_ordem_dia_gerar, pdf_pauta_sessao_gerar,
pdf_protocolo_gerar, pdf_sessao_plenaria_gerar)
+from weasyprint import HTML, CSS
+
def get_kwargs_params(request, fields):
kwargs = {}
@@ -1199,3 +1210,65 @@ def get_pauta_sessao(sessao, casa):
return (lst_expediente_materia,
lst_votacao,
inf_basicas_dic)
+
+def make_pdf(base_url,main_template,header_template,main_css='',header_css=''):
+ html = HTML(base_url=base_url, string=main_template)
+ main_doc = html.render(stylesheets=[])
+
+ def get_page_body(boxes):
+ for box in boxes:
+ if box.element_tag == 'body':
+ return box
+ return get_page_body(box.all_children())
+
+ # Template of header
+ html = HTML(base_url=base_url,string=header_template)
+ header = html.render(stylesheets=[CSS(string='@page {size:A4; margin:1cm;}')])
+
+ header_page = header.pages[0]
+ header_body = get_page_body(header_page._page_box.all_children())
+ header_body = header_body.copy_with_children(header_body.all_children())
+
+ for page in main_doc.pages:
+ page_body = get_page_body(page._page_box.all_children())
+ page_body.children += header_body.all_children()
+
+ pdf_file = main_doc.write_pdf()
+
+ return pdf_file
+
+
+def resumo_ata_pdf(request,pk):
+ base_url = request.build_absolute_uri()
+ casa = CasaLegislativa.objects.first()
+ rodape = ' '.join(get_rodape(casa))
+
+ sessao_plenaria = SessaoPlenaria.objects.get(pk=pk)
+
+ context = {}
+ context.update(get_identificação_basica(sessao_plenaria))
+ context.update(get_mesa_diretora(sessao_plenaria))
+ context.update(get_presenca_sessao(sessao_plenaria))
+ context.update(get_expedientes(sessao_plenaria))
+ context.update(get_materias_expediente(sessao_plenaria))
+ context.update(get_oradores_expediente(sessao_plenaria))
+ context.update(get_presenca_ordem_do_dia(sessao_plenaria))
+ context.update(get_materias_ordem_do_dia(sessao_plenaria))
+ context.update(get_oradores_explicações_pessoais(sessao_plenaria))
+ context.update(get_ocorrencias_da_sessão(sessao_plenaria))
+ context.update({'object':sessao_plenaria})
+ context.update({'data': dt.today().strftime('%d/%m/%Y')})
+ context.update({'rodape':rodape})
+ header_context = {"casa":casa, 'logotipo':casa.logotipo, 'MEDIA_URL': MEDIA_URL}
+
+ html_template = render_to_string('relatorios/relatorio_ata.html',context)
+ html_header = render_to_string('relatorios/header_ata.html', header_context)
+
+ pdf_file = make_pdf(base_url=base_url,main_template=html_template,header_template=html_header)
+
+ response = HttpResponse(content_type='application/pdf;')
+ response['Content-Disposition'] = 'inline; filename=relatorio.pdf'
+ response['Content-Transfer-Encoding'] = 'binary'
+ response.write(pdf_file)
+
+ return response
\ No newline at end of file
diff --git a/sapl/sessao/tests/test_sessao_view.py b/sapl/sessao/tests/test_sessao_view.py
index 17b77e8d8..edab4c6fa 100644
--- a/sapl/sessao/tests/test_sessao_view.py
+++ b/sapl/sessao/tests/test_sessao_view.py
@@ -4,7 +4,21 @@ from django.utils.translation import ugettext_lazy as _
from model_mommy import mommy
from sapl.parlamentares.models import Legislatura, SessaoLegislativa
-from sapl.sessao.models import SessaoPlenaria, TipoSessaoPlenaria
+from sapl.sessao.models import (SessaoPlenaria, TipoSessaoPlenaria,
+ IntegranteMesa, SessaoPlenariaPresenca,
+ JustificativaAusencia, ExpedienteSessao,
+ TipoExpediente, ExpedienteMateria,
+ Orador, OcorrenciaSessao)
+
+from sapl.parlamentares.models import Parlamentar, CargoMesa, Filiacao
+
+from sapl.sessao.views import (get_identificação_basica, get_conteudo_multimidia,
+ get_mesa_diretora, get_presenca_sessao,
+ get_expedientes, get_materias_expediente,
+ get_oradores_expediente, get_presenca_ordem_do_dia,
+ get_materias_ordem_do_dia, get_oradores_explicações_pessoais,
+ get_ocorrencias_da_sessão
+ )
@pytest.mark.django_db(transaction=False)
@@ -47,3 +61,90 @@ def test_incluir_sessao_errors(admin_client):
[_('Este campo é obrigatório.')])
assert (response.context_data['form'].errors['hora_inicio'] ==
[_('Este campo é obrigatório.')])
+
+@pytest.mark.django_db(transaction=False)
+class TestResumoView():
+ def setup(self):
+ self.sessao_plenaria = mommy.make(SessaoPlenaria)
+ self.parlamentar = mommy.make(Parlamentar)
+ self.cargo_mesa = mommy.make(CargoMesa)
+
+ self.integrante_mesa = IntegranteMesa(sessao_plenaria=self.sessao_plenaria,
+ parlamentar=self.parlamentar,
+ cargo=self.cargo_mesa)
+ self.integrante_mesa.save()
+
+ def test_get_identificação_basica(self):
+ id_basica = get_identificação_basica(self.sessao_plenaria)
+ info_basica = id_basica['basica']
+ assert info_basica[0] == 'Tipo de Sessão: ' + str(self.sessao_plenaria.tipo)
+
+ data_inicio = self.sessao_plenaria.data_inicio
+ abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else ''
+ assert info_basica[1] == 'Abertura: ' + abertura +' - '+ self.sessao_plenaria.hora_inicio
+
+ data_fim = self.sessao_plenaria.data_fim
+ encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else ''
+ assert info_basica[2] == 'Encerramento: ' + encerramento +' '+ self.sessao_plenaria.hora_fim
+
+ def test_get_conteudo_multimidia(self):
+ multimidia = get_conteudo_multimidia(self.sessao_plenaria)
+ url_audio = _('Audio: Indisponível')
+ multimidia_video = _('Video: Indisponível')
+
+ if self.sessao_plenaria.url_audio:
+ url_audio = _('Audio: ') + str(sessao_plenaria.url_audio)
+ if self.sessao_plenaria.url_video:
+ multimidia_video = _('Video: ') + str(sessao_plenaria.url_video)
+
+ assert multimidia == {'multimidia_audio':url_audio,
+ 'multimidia_video':multimidia_video}
+
+ def test_get_mesa_diretora(self):
+ mesa = get_mesa_diretora(self.sessao_plenaria)
+ assert mesa == {'mesa':[{
+ 'cargo': self.cargo_mesa,
+ 'parlamentar': self.parlamentar
+ }]}
+
+ def test_get_presenca_sessao(self):
+ justificativa = mommy.make(JustificativaAusencia,sessao_plenaria=self.sessao_plenaria)
+ presenca = mommy.make(SessaoPlenariaPresenca,sessao_plenaria=self.sessao_plenaria)
+
+ resposta_presenca = get_presenca_sessao(self.sessao_plenaria)
+ assert resposta_presenca['presenca_sessao'] == [presenca.parlamentar]
+ assert resposta_presenca['justificativa_ausencia'][0] == justificativa
+
+ def test_get_expedientes(self):
+ tipo_expediente = mommy.make(TipoExpediente)
+ expediente = mommy.make(ExpedienteSessao,sessao_plenaria=self.sessao_plenaria,tipo=tipo_expediente)
+
+ resposta_expediente = get_expedientes(self.sessao_plenaria)
+
+ assert resposta_expediente['expedientes'] == [{
+ 'conteudo': expediente.conteudo,
+ 'tipo': tipo_expediente
+ }]
+
+ def test_get_materias_expediente(self):
+ pass
+
+ def test_get_oradores_explicações_pessoais(self):
+ parlamentar = mommy.make(Parlamentar)
+ partido_sigla = mommy.make(Filiacao, parlamentar=parlamentar)
+ orador = mommy.make(Orador,sessao_plenaria=self.sessao_plenaria,parlamentar=parlamentar)
+
+ resultado_get_oradores = get_oradores_explicações_pessoais(self.sessao_plenaria)
+
+ assert resultado_get_oradores['oradores_explicacoes'] == [{
+ 'numero_ordem': orador.numero_ordem,
+ 'parlamentar': parlamentar,
+ 'sgl_partido': partido_sigla.partido.sigla
+ }]
+
+ def test_get_ocorrencias_da_sessão(self):
+ ocorrencia = mommy.make(OcorrenciaSessao, sessao_plenaria=self.sessao_plenaria)
+ resultado_get_ocorrencia = get_ocorrencias_da_sessão(self.sessao_plenaria)
+
+ assert resultado_get_ocorrencia['ocorrencias_da_sessao'][0] == ocorrencia
+
diff --git a/sapl/sessao/urls.py b/sapl/sessao/urls.py
index 9bcb414b6..4da3a761a 100644
--- a/sapl/sessao/urls.py
+++ b/sapl/sessao/urls.py
@@ -12,7 +12,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
PresencaOrdemDiaView, PresencaView,
ResumoOrdenacaoView, ResumoView, ResumoAtaView, RetiradaPautaCrud, SessaoCrud,
TipoJustificativaCrud, TipoExpedienteCrud, TipoResultadoVotacaoCrud,
- TipoExpedienteCrud, TipoResultadoVotacaoCrud,TipoRetiradaPautaCrud,
+ TipoExpedienteCrud, TipoResultadoVotacaoCrud, TipoRetiradaPautaCrud,
TipoSessaoCrud, VotacaoEditView,
VotacaoExpedienteEditView,
VotacaoExpedienteView, VotacaoNominalEditView,
@@ -30,7 +30,7 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
reordernar_materias_ordem,
sessao_legislativa_legislatura_ajax,
VotacaoEmBlocoOrdemDia, VotacaoEmBlocoExpediente,
- VotacaoEmBlocoSimbolicaView,VotacaoEmBlocoNominalView)
+ VotacaoEmBlocoSimbolicaView, VotacaoEmBlocoNominalView)
from .apps import AppConfig
@@ -59,9 +59,13 @@ urlpatterns = [
name='remove_parlamentar_composicao'),
url(r'^sessao/recuperar-materia/', recuperar_materia),
- url(r'^sessao/recuperar-numero-sessao/', recuperar_numero_sessao),
+ url(r'^sessao/recuperar-numero-sessao/',
+ recuperar_numero_sessao,
+ name='recuperar_numero_sessao_view'
+ ),
url(r'^sessao/sessao-legislativa-legislatura-ajax/',
- sessao_legislativa_legislatura_ajax),
+ sessao_legislativa_legislatura_ajax,
+ name='sessao_legislativa_legislatura_ajax_view'),
url(r'^sessao/(?P\d+)/(?P\d+)/abrir-votacao$',
abrir_votacao,
@@ -78,7 +82,7 @@ urlpatterns = [
url(r'^sistema/sessao-plenaria/tipo-expediente/',
include(TipoExpedienteCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-justificativa/',
- include(TipoJustificativaCrud.get_urls())),
+ include(TipoJustificativaCrud.get_urls())),
url(r'^sistema/sessao-plenaria/tipo-retirada-pauta/',
include(TipoRetiradaPautaCrud.get_urls())),
url(r'^sistema/bancada/',
@@ -123,7 +127,7 @@ urlpatterns = [
url(r'^sessao/(?P\d+)/votacao_bloco/votnom$',
VotacaoEmBlocoNominalView.as_view(), name='votacaobloconom'),
url(r'^sessao/(?P\d+)/votacao_bloco/votsimb$',
- VotacaoEmBlocoSimbolicaView.as_view(), name='votacaoblocosimb'),
+ VotacaoEmBlocoSimbolicaView.as_view(), name='votacaoblocosimb'),
url(r'^sessao/(?P\d+)/votacao_bloco_expediente$',
VotacaoEmBlocoExpediente.as_view(),
name='votacao_bloco_expediente'),
@@ -145,7 +149,7 @@ urlpatterns = [
VotacaoEditView.as_view(), name='votacaosecretaedit'),
url(r'^sessao/(?P\d+)/matordemdia/votsimb/(?P\d+)/(?P\d+)$',
VotacaoView.as_view(), name='votacaosimbolica'),
-
+
url(r'^sessao/(?P\d+)/matordemdia/votsimbbloco/$',
VotacaoView.as_view(), name='votacaosimbolicabloco'),
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 43cf1f5e8..4e4ad02fa 100755
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -63,18 +63,29 @@ TipoRetiradaPautaCrud = CrudAux.build(TipoRetiradaPauta, 'tipo_retirada_pauta')
def reordernar_materias_expediente(request, pk):
expedientes = ExpedienteMateria.objects.filter(
- sessao_plenaria_id=pk)
+ sessao_plenaria_id=pk
+ ).order_by(
+ 'materia__tipo__sequencia_regimental',
+ 'materia__ano',
+ 'materia__numero'
+ )
for exp_num, e in enumerate(expedientes, 1):
e.numero_ordem = exp_num
e.save()
+
return HttpResponseRedirect(
reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': pk}))
def reordernar_materias_ordem(request, pk):
ordens = OrdemDia.objects.filter(
- sessao_plenaria_id=pk)
+ sessao_plenaria_id=pk
+ ).order_by(
+ 'materia__tipo__sequencia_regimental',
+ 'materia__ano',
+ 'materia__numero'
+ )
for ordem_num, o in enumerate(ordens, 1):
o.numero_ordem = ordem_num
o.save()
@@ -1022,9 +1033,6 @@ class ListMateriaOrdemDiaView(FormMixin, DetailView):
return self.get(self, request, args, kwargs)
-def ordenar_integrantes_por_cargo(integrantes):
- return sorted(integrantes, key=lambda k: k['cargo'].id)
-
class MesaView(FormMixin, DetailView):
template_name = 'sessao/mesa.html'
@@ -1295,257 +1303,344 @@ def get_turno(turno):
return ''
-class ResumoView(DetailView):
- template_name = 'sessao/resumo.html'
- model = SessaoPlenaria
- logger = logging.getLogger(__name__)
+def get_identificação_basica(sessao_plenaria):
+ # =====================================================================
+ # Identificação Básica
+ data_inicio = sessao_plenaria.data_inicio
+ abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else ''
+ data_fim = sessao_plenaria.data_fim
+ encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else ''
+ return({'basica': [
+ _('Tipo de Sessão: %(tipo)s') % {'tipo': sessao_plenaria.tipo},
+ _('Abertura: %(abertura)s - %(hora_inicio)s') % {
+ 'abertura': abertura, 'hora_inicio': sessao_plenaria.hora_inicio},
+ _('Encerramento: %(encerramento)s %(hora_fim)s') % {
+ 'encerramento': encerramento, 'hora_fim': sessao_plenaria.hora_fim}
+ ],
+ 'sessaoplenaria': sessao_plenaria})
+
+
+def get_conteudo_multimidia(sessao_plenaria):
+ context = {}
+ if sessao_plenaria.url_audio:
+ context['multimidia_audio'] = _(
+ 'Audio: ') + str(sessao_plenaria.url_audio)
+ else:
+ context['multimidia_audio'] = _('Audio: Indisponível')
+ if sessao_plenaria.url_video:
+ context['multimidia_video'] = _(
+ 'Video: ') + str(sessao_plenaria.url_video)
+ else:
+ context['multimidia_video'] = _('Video: Indisponível')
+ return context
- def get(self, request, *args, **kwargs):
- self.object = self.get_object()
- context = self.get_context_data(object=self.object)
- # =====================================================================
- # Identificação Básica
- data_inicio = self.object.data_inicio
- abertura = data_inicio.strftime('%d/%m/%Y') if data_inicio else ''
+def get_mesa_diretora(sessao_plenaria):
+ mesa = IntegranteMesa.objects.filter(sessao_plenaria=sessao_plenaria).order_by('cargo_id')
+ integrantes = [{'parlamentar': m.parlamentar,
+ 'cargo': m.cargo} for m in mesa]
+ return {'mesa': integrantes}
- data_fim = self.object.data_fim
- encerramento = data_fim.strftime('%d/%m/%Y') + ' -' if data_fim else ''
- context.update({'basica': [
- _('Tipo de Sessão: %(tipo)s') % {'tipo': self.object.tipo},
- _('Abertura: %(abertura)s - %(hora_inicio)s') % {
- 'abertura': abertura, 'hora_inicio': self.object.hora_inicio},
- _('Encerramento: %(encerramento)s %(hora_fim)s') % {
- 'encerramento': encerramento, 'hora_fim': self.object.hora_fim}
- ]})
- # =====================================================================
- # Conteúdo Multimídia
- if self.object.url_audio:
- context.update({'multimidia_audio':
- _('Audio: ') + str(self.object.url_audio)})
- else:
- context.update({'multimidia_audio': _('Audio: Indisponível')})
+def get_presenca_sessao(sessao_plenaria):
+
+ parlamentares_sessao = [p.parlamentar for p in SessaoPlenariaPresenca.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
+
+ ausentes_sessao = JustificativaAusencia.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')
+
+ return ({'presenca_sessao': parlamentares_sessao,
+ 'justificativa_ausencia': ausentes_sessao})
- if self.object.url_video:
- context.update({'multimidia_video':
- _('Video: ') + str(self.object.url_video)})
+
+def get_expedientes(sessao_plenaria):
+ expediente = ExpedienteSessao.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id).order_by('tipo__nome')
+ expedientes = []
+ for e in expediente:
+ tipo = TipoExpediente.objects.get(id=e.tipo_id)
+ conteudo = e.conteudo
+ ex = {'tipo': tipo, 'conteudo': conteudo}
+ expedientes.append(ex)
+ return ({'expedientes': expedientes})
+
+
+def get_materias_expediente(sessao_plenaria):
+ materias = ExpedienteMateria.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id)
+
+ materias_expediente = []
+ for m in materias:
+
+ ementa = m.materia.ementa
+ titulo = m.materia
+ numero = m.numero_ordem
+ tramitacao = m.materia.tramitacao_set.last()
+ turno = None
+
+ if tramitacao:
+ 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:
- context.update({'multimidia_video': _('Video: Indisponível')})
+ resultado = _('Matéria não votada')
+ resultado_observacao = _(' ')
+
+ autoria = Autoria.objects.filter(materia_id=m.materia_id)
+ autor = [str(x.autor) for x in autoria]
+
+ mat = {'ementa': ementa,
+ 'titulo': titulo,
+ 'numero': numero,
+ 'turno': turno,
+ 'resultado': resultado,
+ 'resultado_observacao': resultado_observacao,
+ 'autor': autor,
+ 'numero_protocolo': m.materia.numero_protocolo,
+ 'numero_processo': m.materia.numeracao_set.last(),
+ 'observacao': m.observacao
+ }
+ materias_expediente.append(mat)
+
+ context = {'materia_expediente': materias_expediente}
+ return context
- # =====================================================================
- # Mesa Diretora
- mesa = IntegranteMesa.objects.filter(
- sessao_plenaria=self.object)
- integrantes = []
- for m in mesa:
- parlamentar = Parlamentar.objects.get(
- id=m.parlamentar_id)
- cargo = CargoMesa.objects.get(
- id=m.cargo_id)
- integrante = {'parlamentar': parlamentar, 'cargo': cargo}
- integrantes.append(integrante)
+def get_oradores_expediente(sessao_plenaria):
+ oradores = []
+ for orador in OradorExpediente.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id).order_by('numero_ordem'):
+ numero_ordem = orador.numero_ordem
+ url_discurso = orador.url_discurso
+ observacao = orador.observacao
+ parlamentar = Parlamentar.objects.get(
+ id=orador.parlamentar_id)
+ ora = {'numero_ordem': numero_ordem,
+ 'url_discurso': url_discurso,
+ 'parlamentar': parlamentar,
+ 'observacao': observacao
+ }
+ oradores.append(ora)
+ return {'oradores': oradores}
- context.update({'mesa': ordenar_integrantes_por_cargo(integrantes)})
- # =====================================================================
- # Presença Sessão
- presencas = SessaoPlenariaPresenca.objects.filter(
- sessao_plenaria_id=self.object.id
- ).order_by('parlamentar__nome_parlamentar')
+def get_presenca_ordem_do_dia(sessao_plenaria):
+ parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
- parlamentares_sessao = [p.parlamentar for p in presencas]
+ return {'presenca_ordem': parlamentares_ordem}
- 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})
+def get_assinaturas(sessao_plenaria):
+ mesa_dia = get_mesa_diretora(sessao_plenaria)['mesa']
- # =====================================================================
- # Expedientes
- expediente = ExpedienteSessao.objects.filter(
- sessao_plenaria_id=self.object.id).order_by('tipo__nome')
+ presidente_dia = [next(iter(
+ [m['parlamentar'] for m in mesa_dia if m['cargo'].descricao == 'Presidente']),
+ '')]
- expedientes = []
- for e in expediente:
- tipo = TipoExpediente.objects.get(id=e.tipo_id)
- conteudo = e.conteudo
- ex = {'tipo': tipo, 'conteudo': conteudo}
- expedientes.append(ex)
- context.update({'expedientes': expedientes})
+ parlamentares_ordem = [p.parlamentar for p in PresencaOrdemDia.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id
+ ).order_by('parlamentar__nome_parlamentar')]
- # =====================================================================
- # Matérias Expediente
- materias = ExpedienteMateria.objects.filter(
- sessao_plenaria_id=self.object.id)
+ parlamentares_mesa = [m['parlamentar'] for m in mesa_dia]
- materias_expediente = []
- for m in materias:
+ # filtra parlamentares retirando os que sao da mesa
+ parlamentares_ordem = [p for p in parlamentares_ordem if p not in parlamentares_mesa]
- ementa = m.materia.ementa
- titulo = m.materia
- numero = m.numero_ordem
- tramitacao = m.materia.tramitacao_set.last()
- turno = None
+ context = {}
- if tramitacao:
- turno = get_turno(tramitacao.turno)
+ config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata
+ if config_assinatura_ata == 'T' and parlamentares_ordem:
+ context.update(
+ {'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'})
+ context.update({'assinatura_mesa': mesa_dia,
+ 'assinatura_presentes': parlamentares_ordem})
+ elif config_assinatura_ata == 'M' and mesa_dia:
+ context.update(
+ {'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'})
+ context.update({'assinatura_mesa': mesa_dia})
+ elif config_assinatura_ata == 'P' and presidente_dia:
+ context.update(
+ {'texto_assinatura': 'Assinatura do Presidente da Sessão'})
+ context.update({'assinatura_mesa': presidente_dia})
- 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
+ return context
+
+
+def get_materias_ordem_do_dia(sessao_plenaria):
+ ordem = OrdemDia.objects.filter(sessao_plenaria_id=sessao_plenaria.id)
+ materias_ordem = []
+ for o in ordem:
+ ementa = o.materia.ementa
+ ementa_observacao = o.observacao
+ titulo = o.materia
+ numero = o.numero_ordem
+ tramitacao = o.materia.tramitacao_set.last()
+ turno = None
+ if tramitacao:
+ turno = get_turno(tramitacao.turno)
+
+ # 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 = _(' ')
+
+ voto_sim = ""
+ voto_nao = ""
+ voto_abstencoes = ""
+ voto_nominal = []
+
+ if o.tipo_votacao == 2:
+ votos = VotoParlamentar.objects.filter(ordem=o.id)
+ for voto in votos:
+ aux_voto = (voto.parlamentar.nome_completo, voto.voto)
+ voto_nominal.append(aux_voto)
+ try:
+ voto = RegistroVotacao.objects.filter(ordem=o.id).last()
+ voto_sim = voto.numero_votos_sim
+ voto_nao = voto.numero_votos_nao
+ voto_abstencoes = voto.numero_abstencoes
+ except AttributeError:
+ voto_sim = " Não Informado"
+ voto_nao = " Não Informado"
+ voto_abstencoes = " Não Informado"
+
+ autoria = Autoria.objects.filter(
+ materia_id=o.materia_id)
+ autor = [str(x.autor) for x in autoria]
+ mat = {'ementa': ementa,
+ 'ementa_observacao': ementa_observacao,
+ 'titulo': titulo,
+ 'numero': numero,
+ 'turno': turno,
+ 'resultado': resultado,
+ 'resultado_observacao': resultado_observacao,
+ 'autor': autor,
+ 'numero_protocolo': o.materia.numero_protocolo,
+ 'numero_processo': o.materia.numeracao_set.last(),
+ 'tipo_votacao': o.TIPO_VOTACAO_CHOICES[o.tipo_votacao],
+ 'voto_sim': voto_sim,
+ 'voto_nao': voto_nao,
+ 'voto_abstencoes': voto_abstencoes,
+ 'voto_nominal': voto_nominal,
+ }
+ materias_ordem.append(mat)
+
+ context = {'materias_ordem': materias_ordem}
+ return context
+
+
+def get_oradores_explicações_pessoais(sessao_plenaria):
+ oradores_explicacoes = []
+ for orador in Orador.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id).order_by('numero_ordem'):
+ for parlamentar in Parlamentar.objects.filter(
+ id=orador.parlamentar.id):
+ partido_sigla = Filiacao.objects.filter(
+ parlamentar=parlamentar).last()
+ if not partido_sigla:
+ sigla = ''
else:
- resultado = _('Matéria não votada')
- resultado_observacao = _(' ')
+ sigla = partido_sigla.partido.sigla
+ oradores = {
+ 'numero_ordem': orador.numero_ordem,
+ 'parlamentar': parlamentar,
+ 'sgl_partido': sigla
+ }
+ oradores_explicacoes.append(oradores)
+ context = {'oradores_explicacoes': oradores_explicacoes}
+ return context
- autoria = Autoria.objects.filter(materia_id=m.materia_id)
- autor = [str(x.autor) for x in autoria]
- mat = {'ementa': ementa,
- 'titulo': titulo,
- 'numero': numero,
- 'turno': turno,
- 'resultado': resultado,
- 'resultado_observacao': resultado_observacao,
- 'autor': autor,
- 'numero_protocolo': m.materia.numero_protocolo,
- 'numero_processo': m.materia.numeracao_set.last(),
- 'observacao': m.observacao
- }
- materias_expediente.append(mat)
+def get_ocorrencias_da_sessão(sessao_plenaria):
+ ocorrencias_sessao = OcorrenciaSessao.objects.filter(
+ sessao_plenaria_id=sessao_plenaria.id)
+ context = {'ocorrencias_da_sessao': ocorrencias_sessao}
+ return context
+
+
+class ResumoView(DetailView):
+ template_name = 'sessao/resumo.html'
+ model = SessaoPlenaria
+ logger = logging.getLogger(__name__)
+
+ def get_context(self, *args, **kwargs):
+ self.object = self.get_object()
+ context = self.get_context_data(object=self.object)
- context.update({'materia_expediente': materias_expediente})
-
# Votos de Votação Nominal de Matérias Expediente
materias_expediente_votacao_nominal = ExpedienteMateria.objects.filter(
sessao_plenaria_id=self.object.id,
tipo_votacao=2).order_by('-materia')
-
+
votacoes = []
- for mevn in materias_expediente_votacao_nominal:
-
+ for mevn in materias_expediente_votacao_nominal:
+
votos_materia = []
titulo_materia = mevn.materia
registro = RegistroVotacao.objects.filter(expediente=mevn)
- if registro:
+ if registro:
for vp in VotoParlamentar.objects.filter(votacao=registro).order_by('parlamentar'):
votos_materia.append(vp)
dados_votacao = {
'titulo': titulo_materia,
'votos': votos_materia
- }
+ }
votacoes.append(dados_votacao)
-
+
context.update({'votos_nominais_materia_expediente': votacoes})
-
+
+ # =====================================================================
+ # Identificação Básica
+ context.update(get_identificação_basica(self.object))
+ # =====================================================================
+ # Conteúdo Multimídia
+ context.update(get_conteudo_multimidia(self.object))
+ # =====================================================================
+ # Mesa Diretora
+ context.update(get_mesa_diretora(self.object))
+ # =====================================================================
+ # Presença Sessão
+ context.update(get_presenca_sessao(self.object))
+ # =====================================================================
+ # Expedientes
+ context.update(get_expedientes(self.object))
+ # =====================================================================
+ # Matérias Expediente
+ context.update(get_materias_expediente(self.object))
# =====================================================================
# Oradores Expediente
- oradores = []
- for orador in OradorExpediente.objects.filter(
- sessao_plenaria_id=self.object.id).order_by('numero_ordem'):
- numero_ordem = orador.numero_ordem
- url_discurso = orador.url_discurso
- observacao = orador.observacao
- parlamentar = Parlamentar.objects.get(
- id=orador.parlamentar_id)
- ora = {'numero_ordem': numero_ordem,
- 'url_discurso': url_discurso,
- 'parlamentar': parlamentar,
- 'observacao': observacao
- }
- oradores.append(ora)
-
- context.update({'oradores': oradores})
-
+ context.update(get_oradores_expediente(self.object))
# =====================================================================
# Presença Ordem do Dia
- presencas = PresencaOrdemDia.objects.filter(
- sessao_plenaria_id=self.object.id
- ).order_by('parlamentar__nome_parlamentar')
-
- parlamentares_mesa_dia = [m['parlamentar'] for m in context['mesa']]
- # composicao_mesa = ComposicaoMesa.objects.filter(sessao_legislativa=sessao)
-
- presidente_dia = ''
- for m in context['mesa']:
- if m['cargo'].descricao == 'Presidente':
- presidente_dia = [m['parlamentar']]
- break
-
- parlamentares_ordem = [p.parlamentar for p in presencas]
-
- context.update({'presenca_ordem': parlamentares_ordem})
-
- config_assinatura_ata = AppsAppConfig.objects.first().assinatura_ata
- if config_assinatura_ata == 'T' and parlamentares_ordem:
- context.update(
- {'texto_assinatura': 'Assinatura de Todos os Parlamentares Presentes na Sessão'})
- context.update({'assinatura_presentes': parlamentares_ordem})
- elif config_assinatura_ata == 'M' and parlamentares_mesa_dia:
- context.update(
- {'texto_assinatura': 'Assinatura da Mesa Diretora da Sessão'})
- context.update({'assinatura_presentes': parlamentares_mesa_dia})
- elif config_assinatura_ata == 'P' and presidente_dia:
- context.update(
- {'texto_assinatura': 'Assinatura do Presidente da Sessão'})
- context.update({'assinatura_presentes': presidente_dia})
-
+ context.update(get_presenca_ordem_do_dia(self.object))
+ # =====================================================================
+ # Assinaturas
+ context.update(get_assinaturas(self.object))
# =====================================================================
# Matérias Ordem do Dia
- ordem = OrdemDia.objects.filter(
- sessao_plenaria_id=self.object.id)
- materias_ordem = []
- for o in ordem:
- ementa = o.materia.ementa
- ementa_observacao = o.observacao
- titulo = o.materia
- numero = o.numero_ordem
- tramitacao = o.materia.tramitacao_set.last()
- turno = None
- if tramitacao:
- turno = get_turno(tramitacao.turno)
-
- # 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 = _(' ')
-
- autoria = Autoria.objects.filter(
- materia_id=o.materia_id)
- autor = [str(x.autor) for x in autoria]
-
- mat = {'ementa': ementa,
- 'ementa_observacao': ementa_observacao,
- 'titulo': titulo,
- 'numero': numero,
- 'turno': turno,
- 'resultado': resultado,
- 'resultado_observacao': resultado_observacao,
- 'autor': autor,
- 'numero_protocolo': o.materia.numero_protocolo,
- 'numero_processo': o.materia.numeracao_set.last()
- }
- materias_ordem.append(mat)
-
- context.update({'materias_ordem': materias_ordem})
-
# Votos de Votação Nominal de Matérias Ordem do Dia
materias_ordem_dia_votacao_nominal = OrdemDia.objects.filter(
sessao_plenaria_id=self.object.id,
@@ -1553,7 +1648,6 @@ class ResumoView(DetailView):
votacoes_od = []
for modvn in materias_ordem_dia_votacao_nominal:
-
votos_materia_od = []
t_materia = modvn.materia
registro_od = RegistroVotacao.objects.filter(ordem=modvn)
@@ -1566,37 +1660,16 @@ class ResumoView(DetailView):
'votos': votos_materia_od
}
votacoes_od.append(dados_votacao_od)
-
+
context.update({'votos_nominais_materia_ordem_dia': votacoes_od})
+ context.update(get_materias_ordem_do_dia(self.object))
# =====================================================================
# Oradores nas Explicações Pessoais
- oradores_explicacoes = []
- for orador in Orador.objects.filter(
- sessao_plenaria_id=self.object.id).order_by('numero_ordem'):
- for parlamentar in Parlamentar.objects.filter(
- id=orador.parlamentar.id):
- partido_sigla = Filiacao.objects.filter(
- parlamentar=parlamentar).last()
- if not partido_sigla:
- sigla = ''
- else:
- sigla = partido_sigla.partido.sigla
- oradores = {
- 'numero_ordem': orador.numero_ordem,
- 'parlamentar': parlamentar,
- 'sgl_partido': sigla
- }
- oradores_explicacoes.append(oradores)
- context.update({'oradores_explicacoes': oradores_explicacoes})
-
+ context.update(get_oradores_explicações_pessoais(self.object))
# =====================================================================
# Ocorrẽncias da Sessão
- ocorrencias_sessao = OcorrenciaSessao.objects.filter(
- sessao_plenaria_id=self.object.id)
-
- context.update({'ocorrencias_da_sessao': ocorrencias_sessao})
-
+ context.update(get_ocorrencias_da_sessão(self.object))
# =====================================================================
# Indica a ordem com a qual o template será renderizado
ordenacao = ResumoOrdenacao.objects.first()
@@ -1620,36 +1693,36 @@ class ResumoView(DetailView):
try:
context.update(
{'primeiro_ordenacao': dict_ord_template[ordenacao.primeiro],
- 'segundo_ordenacao': dict_ord_template[ordenacao.segundo],
- 'terceiro_ordenacao': dict_ord_template[ordenacao.terceiro],
- 'quarto_ordenacao': dict_ord_template[ordenacao.quarto],
- 'quinto_ordenacao': dict_ord_template[ordenacao.quinto],
- 'sexto_ordenacao': dict_ord_template[ordenacao.sexto],
- '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_primeiro_ordenacao': dict_ord_template[ordenacao.decimo_primeiro],
- 'decimo_segundo_ordenacao': dict_ord_template[ordenacao.decimo_segundo],
- 'decimo_terceiro_ordenacao': dict_ord_template[ordenacao.decimo_terceiro]})
+ 'segundo_ordenacao': dict_ord_template[ordenacao.segundo],
+ 'terceiro_ordenacao': dict_ord_template[ordenacao.terceiro],
+ 'quarto_ordenacao': dict_ord_template[ordenacao.quarto],
+ 'quinto_ordenacao': dict_ord_template[ordenacao.quinto],
+ 'sexto_ordenacao': dict_ord_template[ordenacao.sexto],
+ '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_primeiro_ordenacao': dict_ord_template[ordenacao.decimo_primeiro],
+ 'decimo_segundo_ordenacao': dict_ord_template[ordenacao.decimo_segundo],
+ 'decimo_terceiro_ordenacao': dict_ord_template[ordenacao.decimo_terceiro]})
except KeyError as e:
- self.logger.error('user=' + request.user.username + '. ' + "KeyError: " + str(e) + ". Erro "
+ self.logger.error('user=' + self.request.user.username + '. ' + "KeyError: " + str(e) + ". Erro "
"ao tentar utilizar configuração de ordenação. Utilizando ordenação padrão.")
context.update(
- {'primeiro_ordenacao': dict_ord_template['id_basica'],
- 'segundo_ordenacao': dict_ord_template['cont_mult'],
- 'terceiro_ordenacao': dict_ord_template['mesa_d'],
- 'quarto_ordenacao': dict_ord_template['lista_p'],
- 'quinto_ordenacao': dict_ord_template['exp'],
- 'sexto_ordenacao': dict_ord_template['mat_exp'],
- 'setimo_ordenacao': dict_ord_template['v_n_mat_exp'],
- 'oitavo_ordenacao': dict_ord_template['oradores_exped'],
- 'nono_ordenacao': dict_ord_template['lista_p_o_d'],
- 'decimo_ordenacao': dict_ord_template['mat_o_d'],
- 'decimo_primeiro_ordenacao': dict_ord_template['v_n_mat_o_d'],
- 'decimo_segundo_ordenacao': dict_ord_template['oradores_expli'],
- 'decimo_terceiro_ordenacao': dict_ord_template['ocorr_sessao']
- })
+ {'primeiro_ordenacao': dict_ord_template['id_basica'],
+ 'segundo_ordenacao': dict_ord_template['cont_mult'],
+ 'terceiro_ordenacao': dict_ord_template['mesa_d'],
+ 'quarto_ordenacao': dict_ord_template['lista_p'],
+ 'quinto_ordenacao': dict_ord_template['exp'],
+ 'sexto_ordenacao': dict_ord_template['mat_exp'],
+ 'setimo_ordenacao': dict_ord_template['v_n_mat_exp'],
+ 'oitavo_ordenacao': dict_ord_template['oradores_exped'],
+ 'nono_ordenacao': dict_ord_template['lista_p_o_d'],
+ 'decimo_ordenacao': dict_ord_template['mat_o_d'],
+ 'decimo_primeiro_ordenacao': dict_ord_template['v_n_mat_o_d'],
+ 'decimo_segundo_ordenacao': dict_ord_template['oradores_expli'],
+ 'decimo_terceiro_ordenacao': dict_ord_template['ocorr_sessao']
+ })
else:
context.update(
{'primeiro_ordenacao': dict_ord_template['id_basica'],
@@ -1667,6 +1740,10 @@ class ResumoView(DetailView):
'decimo_terceiro_ordenacao': dict_ord_template['ocorr_sessao']
})
+ return context
+
+ def get(self, request, *args, **kwargs):
+ context = self.get_context()
return self.render_to_response(context)
@@ -1772,6 +1849,12 @@ class OcorrenciaSessaoView(FormMixin, DetailView):
logger = logging.getLogger(__name__)
+ def get_context_data(self, **kwargs):
+ context = FormMixin.get_context_data(self, **kwargs)
+ context['title'] = 'Ocorrências da Sessão (%s)' % (
+ self.object)
+ return context
+
def delete(self):
OcorrenciaSessao.objects.filter(sessao_plenaria=self.object).delete()
@@ -3000,7 +3083,7 @@ class PesquisarSessaoPlenariaView(FilterView):
# Então a ordem da URL está diferente
data = self.filterset.data
if data and data.get('data_inicio__year') is not None:
- url = "&" + str(self.request.environ['QUERY_STRING'])
+ url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('data_inicio__year=') - 1
url = url[ponto_comeco:]
@@ -3081,6 +3164,7 @@ class AdicionarVariasMateriasExpediente(PermissionRequiredForAppCrudMixin,
self).get_context_data(**kwargs)
context['title'] = _('Pesquisar Matéria Legislativa')
+ context['root_pk'] = self.kwargs['pk']
self.filterset.form.fields['o'].label = _('Ordenação')
@@ -3414,7 +3498,7 @@ class VotacaoEmBlocoSimbolicaView(PermissionRequiredForAppCrudMixin, TemplateVie
'origem': request.POST['origem'],
'subnav_template_name': 'sessao/subnav.yaml'
}
-
+
if 'marcadas_1' in request.POST:
context.update({'resultado_votacao': TipoResultadoVotacao.objects.all(),
diff --git a/sapl/settings.py b/sapl/settings.py
index a91cfd61d..8bad6c92e 100644
--- a/sapl/settings.py
+++ b/sapl/settings.py
@@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/?next='
-SAPL_VERSION = '3.1.147'
+SAPL_VERSION = '3.1.150'
if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
@@ -95,7 +95,6 @@ INSTALLED_APPS = (
'reversion_compare',
'haystack',
- 'whoosh',
'speedinfo',
'webpack_loader',
@@ -106,8 +105,8 @@ INSTALLED_APPS = (
# Desabilita a indexação textual até encontramos uma solução para a issue
# https://github.com/interlegis/sapl/issues/2055
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.BaseSignalProcessor' # Disable auto index
-SEARCH_BACKEND = 'haystack.backends.whoosh_backend.WhooshEngine'
-SEARCH_URL = ('PATH', PROJECT_DIR.child('whoosh'))
+SEARCH_BACKEND = ''
+SEARCH_URL = ['','']
# SOLR
USE_SOLR = config('USE_SOLR', cast=bool, default=False)
diff --git a/sapl/static/sapl/css/header-relatorio.css b/sapl/static/sapl/css/header-relatorio.css
new file mode 100644
index 000000000..65f6f629d
--- /dev/null
+++ b/sapl/static/sapl/css/header-relatorio.css
@@ -0,0 +1,62 @@
+html body p {
+ border-top: 1px solid black;
+ text-align: center;
+ font-size: 11pt;
+ padding: 5px;
+ margin-top: -15px;
+}
+html body section {
+ box-sizing: border-box;
+}
+html body section dl {
+ display: flex;
+ flex-wrap: wrap;
+ rows: 2;
+ columns: 2;
+}
+html body section dt{
+ width: 50px;
+}
+html body section dd {
+ max-width:550px;
+ text-align: center;
+}
+html body section dd ul li {
+ list-style-type: none;
+ margin-left: 90px;
+ margin-bottom: -15px;
+
+}
+h2 {
+ font-size: 14pt;
+}
+h3 {
+ font-size: 10pt;
+ color: #6e6e6e;
+}
+ul {
+ padding: 0;
+ list-style: none;
+ margin-top:10px;
+}
+
+html body section dt img {
+ max-width:80px;
+ margin-left: 20px;
+ margin-left: 50px;
+
+}
+h3 {
+ font-size: 10pt;
+ color: #6e6e6e;
+}
+ul {
+ padding: 0;
+ list-style: none;
+ margin-top:10px;
+}
+
+html body section dt img {
+ max-width:80px;
+ margin-left: 20px;
+}
\ No newline at end of file
diff --git a/sapl/static/sapl/css/relatorio.css b/sapl/static/sapl/css/relatorio.css
new file mode 100644
index 000000000..c3f2ec21f
--- /dev/null
+++ b/sapl/static/sapl/css/relatorio.css
@@ -0,0 +1,56 @@
+@page{
+ margin-top: 4.5cm;
+ size: A4 portrait;
+}
+
+h2.gray-title{
+ color: gray;
+ font-size: 14pt;
+ break-after: avoid-page;
+ page-break-after: avoid;
+}
+
+h3 {
+ font-size: 10pt;
+ break-after: avoid-page;
+ page-break-after: avoid;
+}
+
+p {
+ font-size: 10pt;
+ text-align: justify;
+ text-justify: inter-word;
+}
+
+fieldset {
+ border: 0;
+}
+
+html body section {
+ box-sizing: border-box;
+}
+
+html body section dl {
+ display: flex;
+ flex-wrap: wrap;
+ columns: 5;
+}
+
+html body section dt{
+ width: 50px;
+}
+
+html body section dd {
+ text-align: center;
+}
+
+html body section dd ul li {
+ list-style-type: none;
+ margin-left: 50px;
+}
+
+fieldset {
+ page-break-after: avoid;
+ margin:5px;
+ padding:0px;
+}
\ No newline at end of file
diff --git a/sapl/templates/base.html b/sapl/templates/base.html
index 04502939f..2fa19c1cd 100644
--- a/sapl/templates/base.html
+++ b/sapl/templates/base.html
@@ -179,7 +179,7 @@
Desenvolvido pelo Interlegis em software livre e aberto.
- Release: 3.1.147
+ Release: 3.1.150
diff --git a/sapl/templates/comissoes/composicao_list.html b/sapl/templates/comissoes/composicao_list.html
index 752e0c885..bc7bf8292 100644
--- a/sapl/templates/comissoes/composicao_list.html
+++ b/sapl/templates/comissoes/composicao_list.html
@@ -1,46 +1,45 @@
{% extends "crud/list.html" %}
{% load i18n common_tags crispy_forms_tags%}
-{% block base_content %}
+{% block actions %}
{% if user.is_authenticated and perms.comissoes.add_composicao %}
-
- {% block actions %}
-
- {% endblock actions %}
-
+
{% endif %}
+{% endblock actions %}
-
+{% block extra_content %}
+
+{% endblock %}
+
+{% block container_table_list %}
{% if user.is_authenticated and perms.comissoes.add_participacao %}
-
-
- Adicionar Participação em Comissão
-
+
{% endif %}
-
-
-
-
-{% endblock base_content %}
+{% endblock %}
diff --git a/sapl/templates/comissoes/materias_em_tramitacao.html b/sapl/templates/comissoes/materias_em_tramitacao.html
index 9f197d1ce..32860df54 100644
--- a/sapl/templates/comissoes/materias_em_tramitacao.html
+++ b/sapl/templates/comissoes/materias_em_tramitacao.html
@@ -12,7 +12,7 @@
{% block detail_content %}