Browse Source

dá func ao campo observação de OrdemDia e ExpedienteMateria (#2215)

Foram ajustados o formulário de edição do campo observação e adicionado
um migrate para limpar o campo observação nos casos em que o conteúdo é
exatamente igual a ementa, desconsiderado a caixa das letras.
Uma pequena alteração no Crud tb para tratar mais de um campo por coluna
nas listagens
pull/2224/head
Leandro Roberto da Silva 6 years ago
committed by Edward
parent
commit
4cd78fbcba
  1. 11
      sapl/crud/base.py
  2. 22
      sapl/sessao/forms.py
  3. 37
      sapl/sessao/migrations/0023_auto_20180914_1315.py
  4. 8
      sapl/sessao/models.py
  5. 16
      sapl/sessao/serializers.py
  6. 124
      sapl/sessao/views.py
  7. 2
      sapl/templates/base/relatorios_list.html
  8. 25
      sapl/templates/sessao/expedientemateria_form.html
  9. 2
      sapl/templates/sessao/layouts.yaml

11
sapl/crud/base.py

@ -17,8 +17,8 @@ from django.http.response import Http404
from django.shortcuts import redirect
from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
UpdateView)
from django.views.generic.base import ContextMixin
@ -30,6 +30,7 @@ from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL,
from sapl.settings import BASE_DIR
from sapl.utils import normalize
logger = logging.getLogger(BASE_DIR.name)
ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \
@ -411,10 +412,13 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
m = self.model
fn = fn.split('__')
for f in fn:
if not f:
continue
f = m._meta.get_field(f)
if hasattr(f, 'related_model') and f.related_model:
m = f.related_model
s.append(force_text(f.verbose_name))
if f:
s.append(force_text(f.verbose_name))
s = ' / '.join(s)
r.append(s)
return r
@ -440,6 +444,9 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
if isinstance(name, tuple):
s = ''
for j, n in enumerate(name):
if not n:
s += '<br>'
continue
m = obj
n = n.split('__')
for f in n[:-1]:

22
sapl/sessao/forms.py

@ -1,6 +1,5 @@
from datetime import datetime
import django_filters
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button, Fieldset, Layout
from django import forms
@ -9,6 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import transaction
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
import django_filters
from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import form_actions, to_row
@ -98,7 +98,6 @@ class SessaoPlenariaForm(ModelForm):
else: # create
raise error
# Condições da verificação
abertura_entre_leg = leg.data_inicio <= abertura <= leg.data_fim
abertura_entre_sl = sl.data_inicio <= abertura <= sl.data_fim
@ -112,7 +111,8 @@ class SessaoPlenariaForm(ModelForm):
if encerramento < abertura:
raise ValidationError("A data de encerramento não pode ser "
"anterior a data de abertura.")
# Verifica se a data de abertura está entre a data de início e fim da legislatura
# Verifica se a data de abertura está entre a data de início e fim
# da legislatura
if abertura_entre_leg and encerramento_entre_leg:
if abertura_entre_sl and encerramento_entre_sl:
pass
@ -164,7 +164,6 @@ class SessaoPlenariaForm(ModelForm):
"datas de início e fim tanto Legislatura "
"quanto da Sessão Legislativa.")
# Verificações com a data de encerramento vazia
else:
if abertura_entre_leg:
@ -454,7 +453,6 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
# pré-popula o campo do formulário com o ano corrente
self.form.fields['data_inicio__year'].initial = timezone.now().year
row1 = to_row(
[('data_inicio__year', 3),
('data_inicio__month', 3),
@ -569,13 +567,14 @@ class OradorExpedienteForm(ModelForm):
def __init__(self, *args, **kwargs):
super(OradorExpedienteForm, self).__init__(*args, **kwargs)
legislatura_vigente = SessaoPlenaria.objects.get(pk=kwargs['initial']['id_sessao']).legislatura
legislatura_vigente = SessaoPlenaria.objects.get(
pk=kwargs['initial']['id_sessao']).legislatura
if legislatura_vigente:
self.fields['parlamentar'].queryset = \
Parlamentar.objects.filter(ativo=True,
mandato__legislatura=legislatura_vigente
).order_by('nome_parlamentar')
).order_by('nome_parlamentar')
def clean(self):
super(OradorExpedienteForm, self).clean()
@ -585,11 +584,11 @@ class OradorExpedienteForm(ModelForm):
return self.cleaned_data
sessao_id = self.initial['id_sessao']
numero = self.initial.get('numero') # Retorna None se inexistente
numero = self.initial.get('numero') # Retorna None se inexistente
ordem = OradorExpediente.objects.filter(
sessao_plenaria_id=sessao_id,
numero_ordem=cleaned_data['numero_ordem']
).exists()
sessao_plenaria_id=sessao_id,
numero_ordem=cleaned_data['numero_ordem']
).exists()
if ordem and (cleaned_data['numero_ordem'] != numero):
raise ValidationError(_(
@ -597,7 +596,6 @@ class OradorExpedienteForm(ModelForm):
return self.cleaned_data
class Meta:
model = OradorExpediente
exclude = ['sessao_plenaria']

37
sapl/sessao/migrations/0023_auto_20180914_1315.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-09-14 16:15
from __future__ import unicode_literals
from django.db import migrations, models
def limpa_observacao_igual_ementa(apps, schema_editor):
ExpedienteMateria = apps.get_model('sessao', 'ExpedienteMateria')
OrdemDia = apps.get_model('sessao', 'OrdemDia')
q = models.Q(observacao__iexact=models.F('materia__ementa'))
ExpedienteMateria.objects.filter(q).update(observacao='')
OrdemDia.objects.filter(q).update(observacao='')
class Migration(migrations.Migration):
dependencies = [
('sessao', '0022_auto_20180618_1625'),
]
operations = [
migrations.AlterField(
model_name='expedientemateria',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.AlterField(
model_name='ordemdia',
name='observacao',
field=models.TextField(blank=True, verbose_name='Observação'),
),
migrations.RunPython(limpa_observacao_igual_ementa),
]

8
sapl/sessao/models.py

@ -1,10 +1,10 @@
from operator import xor
import reversion
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
import reversion
from sapl.base.models import Autor
from sapl.materia.models import MateriaLegislativa
@ -237,7 +237,7 @@ class AbstractOrdemDia(models.Model):
verbose_name=_('Matéria'))
data_ordem = models.DateField(verbose_name=_('Data da Sessão'))
observacao = models.TextField(
blank=True, verbose_name=_('Ementa'))
blank=True, verbose_name=_('Observação'))
numero_ordem = models.PositiveIntegerField(verbose_name=_('Nº Ordem'))
resultado = models.TextField(blank=True, verbose_name=_('Resultado'))
tipo_votacao = models.PositiveIntegerField(
@ -254,6 +254,10 @@ class AbstractOrdemDia(models.Model):
class Meta:
abstract = True
@property
def ementa(self):
return self.materia.ementa
def __str__(self):
return 'Ordem do Dia/Expediente: %s - %s em %s' % (
self.numero_ordem, self.materia, self.sessao_plenaria)

16
sapl/sessao/serializers.py

@ -1,19 +1,3 @@
from rest_framework import serializers
from .models import SessaoPlenaria
class SessaoPlenariaSerializer(serializers.Serializer):
class Meta:
model = SessaoPlenaria
fields = ('tipo',
'sessao_legislativa',
'legislatura',
'data_inicio',
'hora_inicio',
'hora_fim',
'url_video',
'iniciada',
'finalizada'
)

124
sapl/sessao/views.py

@ -1,5 +1,5 @@
from re import sub
from operator import itemgetter
from re import sub
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
@ -49,6 +49,7 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente,
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
CargoBancadaCrud = CrudAux.build(CargoBancada, '')
@ -325,9 +326,9 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'mid': obj.materia_id})
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
resultado_descricao,
resultado_observacao))
(url,
resultado_descricao,
resultado_observacao))
else:
if obj.tipo_votacao == 2:
@ -338,7 +339,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=expediente'
'?&materia=expediente'
else:
url = reverse(
'sapl.sessao:votacao_nominal_transparencia',
@ -346,12 +347,12 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=ordem'
'?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
resultado_descricao,
resultado_observacao))
(url,
resultado_descricao,
resultado_observacao))
elif obj.tipo_votacao == 1:
if is_expediente:
@ -361,7 +362,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=expediente'
'?&materia=expediente'
else:
url = reverse(
'sapl.sessao:votacao_simbolica_transparencia',
@ -369,7 +370,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id}) + \
'?&materia=ordem'
'?&materia=ordem'
resultado = ('<a href="%s">%s<br/>%s</a>' %
(url,
@ -377,8 +378,8 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
resultado_observacao))
else:
resultado = ('%s<br/>%s' %
(resultado_descricao,
resultado_observacao))
(resultado_descricao,
resultado_observacao))
context['rows'][i][3] = (resultado, None)
return context
@ -389,7 +390,8 @@ def get_presencas_generic(model, sessao, legislatura):
presentes = [p.parlamentar for p in presencas]
presentes = sorted(presentes, key=lambda x: remover_acentos(x.nome_parlamentar))
presentes = sorted(
presentes, key=lambda x: remover_acentos(x.nome_parlamentar))
mandato = Mandato.objects.filter(
legislatura=legislatura).order_by('parlamentar__nome_parlamentar')
@ -408,7 +410,8 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
public = [RP_LIST, RP_DETAIL]
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia', 'materia__ementa',
list_field_names = ['numero_ordem', 'materia',
('materia__ementa', '', 'observacao'),
'resultado']
class CreateView(MasterDetailCrud.CreateView):
@ -439,17 +442,18 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return initial
class DetailView(MasterDetailCrud.DetailView):
layout_key = 'OrdemDiaDetail'
class ListView(MasterDetailCrud.ListView):
paginate_by = None
ordering = ['numero_ordem', 'materia', 'resultado']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
has_permition = self.request.user.has_module_perms(AppConfig.label)
return customize_link_materia(context, self.kwargs['pk'], has_permition, False)
def recuperar_materia(request):
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia'])
numero = request.GET['numero_materia']
@ -463,7 +467,7 @@ def recuperar_materia(request):
'id': materia.id,
'indexacao': materia.indexacao})
except ObjectDoesNotExist:
response = JsonResponse({'ementa': '', 'id': 0, 'indexacao':''})
response = JsonResponse({'ementa': '', 'id': 0, 'indexacao': ''})
return response
@ -476,7 +480,8 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia',
'materia__ementa', 'resultado']
('materia__ementa', '', 'observacao'),
'resultado']
class ListView(MasterDetailCrud.ListView):
paginate_by = None
@ -544,7 +549,6 @@ class OradorExpedienteCrud(OradorCrud):
return reverse('sapl.sessao:oradorexpediente_list',
kwargs={'pk': self.kwargs['pk']})
class UpdateView(MasterDetailCrud.UpdateView):
form_class = OradorExpedienteForm
@ -669,10 +673,10 @@ class SessaoCrud(Crud):
return {
'legislatura': legislatura,
'sessao_legislativa': legislatura.sessaolegislativa_set.filter(
legislatura_id=legislatura.id,
data_inicio__year=timezone.now().year
).first()
}
legislatura_id=legislatura.id,
data_inicio__year=timezone.now().year
).first()
}
else:
msg = _('Cadastre alguma legislatura antes de adicionar ' +
'uma sessão plenária!')
@ -778,7 +782,8 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
cronometro_discurso = AppsAppConfig.attr('cronometro_discurso')
cronometro_aparte = AppsAppConfig.attr('cronometro_aparte')
cronometro_ordem = AppsAppConfig.attr('cronometro_ordem')
cronometro_consideracoes = AppsAppConfig.attr('cronometro_consideracoes')
cronometro_consideracoes = AppsAppConfig.attr(
'cronometro_consideracoes')
if (not cronometro_discurso or not cronometro_aparte
or not cronometro_ordem or not cronometro_consideracoes):
@ -999,15 +1004,18 @@ class MesaView(FormMixin, DetailView):
cargos_vagos = list(set(cargos) - set(cargos_ocupados))
# FIX-ME: tem formas melhores de fazer isso, poupando linhas.
parlamentares = Legislatura.objects.get(id=sessao.legislatura_id).mandato_set.all()
parlamentares = Legislatura.objects.get(
id=sessao.legislatura_id).mandato_set.all()
parlamentares_ocupados = [m.parlamentar for m in mesa]
parlamentares_vagos = list(
set(
[p.parlamentar for p in parlamentares]) - set(
parlamentares_ocupados))
org_parlamentares_vagos = parlamentares_vagos
org_parlamentares_vagos.sort(key=lambda x: remover_acentos(x.nome_parlamentar))
org_parlamentares_vagos = [p for p in org_parlamentares_vagos if p.ativo]
org_parlamentares_vagos.sort(
key=lambda x: remover_acentos(x.nome_parlamentar))
org_parlamentares_vagos = [
p for p in org_parlamentares_vagos if p.ativo]
# Se todos os cargos estiverem ocupados, a listagem de parlamentares
# deve ser renderizada vazia
if not cargos_vagos:
@ -1159,15 +1167,15 @@ class ResumoOrdenacaoView(PermissionRequiredMixin, FormView):
ordenacao = ResumoOrdenacao.objects.first()
if ordenacao:
initial.update({'primeiro': ordenacao.primeiro,
'segundo': ordenacao.segundo,
'terceiro': ordenacao.terceiro,
'quarto': ordenacao.quarto,
'quinto': ordenacao.quinto,
'sexto': ordenacao.sexto,
'setimo': ordenacao.setimo,
'oitavo': ordenacao.oitavo,
'nono': ordenacao.nono,
'decimo': ordenacao.decimo})
'segundo': ordenacao.segundo,
'terceiro': ordenacao.terceiro,
'quarto': ordenacao.quarto,
'quinto': ordenacao.quinto,
'sexto': ordenacao.sexto,
'setimo': ordenacao.setimo,
'oitavo': ordenacao.oitavo,
'nono': ordenacao.nono,
'decimo': ordenacao.decimo})
return initial
def form_valid(self, form):
@ -1328,7 +1336,7 @@ class ResumoView(DetailView):
ora = {'numero_ordem': numero_ordem,
'url_discurso': url_discurso,
'parlamentar': parlamentar,
'observacao' : observacao
'observacao': observacao
}
oradores.append(ora)
@ -1478,8 +1486,8 @@ class ExpedienteView(FormMixin, DetailView):
for tipo, conteudo in zip(list_tipo, list_conteudo):
ExpedienteSessao.objects.filter(
sessao_plenaria_id=self.object.id,
tipo_id=tipo).delete()
sessao_plenaria_id=self.object.id,
tipo_id=tipo).delete()
expediente = ExpedienteSessao()
expediente.sessao_plenaria_id = self.object.id
@ -1825,7 +1833,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
elif self.expediente:
expediente_id = kwargs['oid']
try:
materia_votacao = ExpedienteMateria.objects.get(id=expediente_id)
materia_votacao = ExpedienteMateria.objects.get(
id=expediente_id)
except ObjectDoesNotExist:
raise Http404()
@ -1923,7 +1932,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
return self.form_invalid(form)
def form_invalid(self, form):
errors_tuple = [(form[e].label, form.errors[e]) for e in form.errors if e in form.fields]
errors_tuple = [(form[e].label, form.errors[e])
for e in form.errors if e in form.fields]
error_message = '''<ul>'''
for e in errors_tuple:
error_message += '''<li><b>%s</b>: %s</li>''' % (e[0], e[1][0])
@ -2000,8 +2010,10 @@ class VotacaoNominalEditAbstract(SessaoPermissionMixin):
elif self.expediente:
expediente_id = kwargs['oid']
expediente = ExpedienteMateria.objects.filter(id=expediente_id).last()
votacao = RegistroVotacao.objects.filter(expediente_id=expediente_id).last()
expediente = ExpedienteMateria.objects.filter(
id=expediente_id).last()
votacao = RegistroVotacao.objects.filter(
expediente_id=expediente_id).last()
if not expediente or not votacao:
raise Http404()
@ -2120,9 +2132,11 @@ class VotacaoNominalTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else:
raise Http404()
@ -2203,18 +2217,20 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
materia_votacao = self.request.GET.get('materia', None)
if materia_votacao == 'ordem':
votacao = RegistroVotacao.objects.filter(ordem=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
ordem=self.kwargs['oid']).last()
elif materia_votacao == 'expediente':
votacao = RegistroVotacao.objects.filter(expediente=self.kwargs['oid']).last()
votacao = RegistroVotacao.objects.filter(
expediente=self.kwargs['oid']).last()
else:
raise Http404()
context['votacao'] = votacao
registro_votacao = {'numero_votos_sim': votacao.numero_votos_sim,
'numero_votos_nao': votacao.numero_votos_nao,
'numero_abstencoes': votacao.numero_abstencoes}
context.update({'registro_votacao':registro_votacao})
'numero_votos_nao': votacao.numero_votos_nao,
'numero_abstencoes': votacao.numero_abstencoes}
context.update({'registro_votacao': registro_votacao})
votacao_existente = {'observacao': sub(
'&nbsp;', ' ', strip_tags(votacao.observacao)),
@ -2230,6 +2246,7 @@ class VotacaoSimbolicaTransparenciaDetailView(TemplateView):
for tipo in TipoResultadoVotacao.objects.all():
yield tipo
class VotacaoExpedienteView(SessaoPermissionMixin):
"""
@ -2413,7 +2430,8 @@ class VotacaoExpedienteEditView(SessaoPermissionMixin):
expediente_id = kwargs['oid']
if int(request.POST['anular_votacao']) == 1:
RegistroVotacao.objects.filter(expediente_id=expediente_id).delete()
RegistroVotacao.objects.filter(
expediente_id=expediente_id).delete()
expediente = ExpedienteMateria.objects.get(
sessao_plenaria_id=self.object.id,
@ -2452,10 +2470,10 @@ class PautaSessaoView(TemplateView):
sessao = SessaoPlenaria.objects.order_by("-data_inicio").first()
if not sessao:
return self.render_to_response({})
return self.render_to_response({})
return HttpResponseRedirect(
reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao.pk}))
reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao.pk}))
class PautaSessaoDetailView(DetailView):

2
sapl/templates/base/relatorios_list.html

@ -50,5 +50,5 @@
</tr>
</tbody>
</table>
</fieldset
</fieldset>
{% endblock base_content %}

25
sapl/templates/sessao/expedientemateria_form.html

@ -6,7 +6,7 @@
{% block extra_js %}
<script language="Javascript">
document.getElementById("id_observacao").readOnly = true;
//document.getElementById("id_observacao").readOnly = true;
function recuperar_materia() {
var tipo_materia = $("#id_tipo_materia").val()
@ -14,18 +14,29 @@
var ano_materia = $("#id_ano_materia").val()
if (tipo_materia && numero_materia && ano_materia) {
$.get("/sessao/recuperar-materia",{tipo_materia: tipo_materia,
numero_materia: numero_materia,
ano_materia: ano_materia},
function(data, status) {
$("#id_observacao").val(data.ementa);
});
$.get("/sessao/recuperar-materia", {
tipo_materia: tipo_materia,
numero_materia: numero_materia,
ano_materia: ano_materia
},
function(data, status) {
if ($(".ementa-materia").length === 0) {
$("#div_id_tipo_materia").closest('.row-fluid').after(
$('<div class="row-fluid"/>').append(
$('<div class="col-xs-12"/>').append(
$('<div class="alert alert-info ementa-materia"/>').html(data.ementa))))
}
else {
$('.ementa-materia').html(data.ementa)
}
});
}
}
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]
for (i = 0; i < fields.length; i++) {
$(fields[i]).change(recuperar_materia);
}
recuperar_materia()
</script>
{% endblock %}

2
sapl/templates/sessao/layouts.yaml

@ -56,12 +56,14 @@ OrdemDia:
ExpedienteMateriaDetail:
{% trans 'Matérias do Expediente' %}:
- materia
- ementa
- tipo_votacao
- observacao
OrdemDiaDetail:
{% trans 'Matérias da Ordem do Dia' %}:
- materia
- ementa
- tipo_votacao
- observacao

Loading…
Cancel
Save