Browse Source

Fix #2927 #2507 - Matérias apenas lidas e não votadas (#2953)

* Fix #2927 - Matérias apenas lidas, mas não votadas

* Adiciona Leitura para OrdemDia e cria model RegistroLeitura

* Adiciona cancelamento de leitura

* Adiciona matérias apenas lidas no painel

* Adiciona url de cancelar leitura

* Fix permissões

* Adiciona registro de usuário e ip no RegistroLeitura
pull/2940/head
Cesar Augusto de Carvalho 5 years ago
committed by Edward
parent
commit
5799669cb8
  1. 78
      sapl/painel/views.py
  2. 1
      sapl/rules/map_rules.py
  3. 56
      sapl/sessao/forms.py
  4. 62
      sapl/sessao/migrations/0046_auto_20190827_1228.py
  5. 30
      sapl/sessao/migrations/0047_auto_20190829_1253.py
  6. 53
      sapl/sessao/models.py
  7. 23
      sapl/sessao/urls.py
  8. 162
      sapl/sessao/views.py
  9. 24
      sapl/templates/painel/index.html
  10. 19
      sapl/templates/sessao/expedientemateria_form.html
  11. 2
      sapl/templates/sessao/layouts.yaml
  12. 6
      sapl/templates/sessao/votacao/leitura_form.html

78
sapl/painel/views.py

@ -21,7 +21,7 @@ from sapl.parlamentares.models import Legislatura, Parlamentar, Votante
from sapl.sessao.models import (ExpedienteMateria, OradorExpediente, OrdemDia,
PresencaOrdemDia, RegistroVotacao,
SessaoPlenaria, SessaoPlenariaPresenca,
VotoParlamentar)
VotoParlamentar, RegistroLeitura)
from sapl.utils import filiacao_data, get_client_ip, sort_lista_chave
from .models import Cronometro
@ -408,6 +408,8 @@ def get_presentes(pk, response, materia):
tipo_votacao = 'Nominal'
elif materia.tipo_votacao == 3:
tipo_votacao = 'Secreta'
elif materia.tipo_votacao == 4:
tipo_votacao = 'Leitura'
response.update({
'tipo_resultado': materia.resultado,
@ -442,15 +444,27 @@ def response_nenhuma_materia(response):
def get_votos(response, materia):
logger = logging.getLogger(__name__)
if type(materia) == OrdemDia:
if materia.tipo_votacao != 4:
registro = RegistroVotacao.objects.filter(
ordem=materia, materia=materia.materia).last()
ordem=materia, materia=materia.materia).order_by('data_hora').last()
leitura = None
else:
leitura = RegistroLeitura.objects.filter(
ordem=materia, materia=materia.materia).order_by('data_hora').last()
registro = None
tipo = 'ordem'
elif type(materia) == ExpedienteMateria:
if materia.tipo_votacao != 4:
registro = RegistroVotacao.objects.filter(
expediente=materia, materia=materia.materia).last()
expediente=materia, materia=materia.materia).order_by('data_hora').last()
leitura = None
else:
leitura = RegistroLeitura.objects.filter(
expediente=materia, materia=materia.materia).order_by('data_hora').last()
registro = None
tipo = 'expediente'
if not registro:
if not registro and not leitura:
response.update({
'numero_votos_sim': 0,
'numero_votos_nao': 0,
@ -479,7 +493,15 @@ def get_votos(response, materia):
logger.error("Votos do parlamentar (id={}) não encontrados. Retornado vazio."
.format(p['parlamentar_id']))
response['presentes'][i]['voto'] = ''
elif leitura:
response.update({
'numero_votos_sim': 0,
'numero_votos_nao': 0,
'numero_abstencoes': 0,
'registro': True,
'total_votos': 0,
'tipo_resultado': 'Matéria lida.',
})
else:
total = (registro.numero_votos_sim +
registro.numero_votos_nao +
@ -556,33 +578,33 @@ def get_dados_painel(request, pk):
# Caso não tenha nenhuma aberta,
# a matéria a ser mostrada no Painel deve ser a última votada
last_ordem_voto = RegistroVotacao.objects.filter(
ordem__sessao_plenaria=sessao).last()
ordem__sessao_plenaria=sessao).order_by('data_hora').last()
last_expediente_voto = RegistroVotacao.objects.filter(
expediente__sessao_plenaria=sessao).last()
if last_ordem_voto:
ultima_ordem_votada = last_ordem_voto.ordem
if last_expediente_voto:
ultimo_expediente_votado = last_expediente_voto.expediente
expediente__sessao_plenaria=sessao).order_by('data_hora').last()
if last_ordem_voto or last_expediente_voto:
# Se alguma ordem E algum expediente já tiver sido votado...
if last_ordem_voto and last_expediente_voto:
materia = ultima_ordem_votada\
if last_ordem_voto.pk >= last_expediente_voto.pk\
else ultimo_expediente_votado
# Caso somente um deles tenha resultado, prioriza a Ordem do Dia
elif last_ordem_voto:
materia = ultima_ordem_votada
# Caso a Ordem do dia não tenha resultado, mostra o último expediente
elif last_expediente_voto:
materia = ultimo_expediente_votado
last_ordem_leitura = RegistroLeitura.objects.filter(
ordem__sessao_plenaria=sessao).order_by('data_hora').last()
last_expediente_leitura = RegistroLeitura.objects.filter(
expediente__sessao_plenaria=sessao).order_by('data_hora').last()
# Obtém última matéria que foi votada, através do timestamp mais recente
if last_ordem_voto:
ordem_expediente = last_ordem_voto.ordem
ultimo_timestamp = last_ordem_voto.data_hora
if last_expediente_voto and last_expediente_voto.data_hora > ultimo_timestamp:
ordem_expediente = last_expediente_voto.expediente
ultimo_timestamp = last_expediente_voto.data_hora
if last_ordem_leitura and last_ordem_leitura.data_hora > ultimo_timestamp:
ordem_expediente = last_ordem_leitura.ordem
ultimo_timestamp = last_ordem_leitura.data_hora
if last_expediente_leitura and last_expediente_leitura.data_hora > ultimo_timestamp:
ordem_expediente = last_expediente_leitura.expediente
ultimo_timestamp = last_expediente_leitura.data_hora
if ordem_expediente:
return JsonResponse(get_votos(
get_presentes(pk, response, materia),
materia))
get_presentes(pk, response, ordem_expediente),
ordem_expediente))
# Retorna que não há nenhuma matéria já votada ou aberta
return response_nenhuma_materia(get_presentes(pk, response, None))

1
sapl/rules/map_rules.py

@ -187,6 +187,7 @@ rules_group_sessao = {
(sessao.VotoParlamentar, __base__, __perms_publicas__),
(sessao.JustificativaAusencia, __base__, __perms_publicas__),
(sessao.RetiradaPauta, __base__, __perms_publicas__),
(sessao.RegistroLeitura, __base__, __perms_publicas__),
]
}

56
sapl/sessao/forms.py

@ -28,7 +28,7 @@ from .models import (Bancada, ExpedienteMateria, JustificativaAusencia,
Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca, TipoResultadoVotacao,
OcorrenciaSessao, RetiradaPauta, TipoRetiradaPauta, OradorOrdemDia, ORDENACAO_RESUMO,
ResumoOrdenacao)
ResumoOrdenacao, RegistroLeitura)
MES_CHOICES = RANGE_MESES
@ -358,6 +358,8 @@ class ExpedienteMateriaForm(ModelForm):
initial=datetime.strftime(timezone.now(), '%d/%m/%Y'),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
apenas_leitura = forms.BooleanField(label='Apenas Leitura', required=False)
class Meta:
model = ExpedienteMateria
fields = ['data_ordem', 'numero_ordem', 'tipo_materia', 'observacao',
@ -493,7 +495,7 @@ class VotacaoForm(forms.Form):
resultado_votacao = forms.CharField(label='Resultado da Votação')
def clean(self):
cleaned_data = super(VotacaoForm, self).clean()
cleaned_data = super().clean()
if not self.is_valid():
return cleaned_data
@ -598,7 +600,7 @@ class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet):
]
def __init__(self, *args, **kwargs):
super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.filters['tipo'].label = 'Tipo de Matéria'
self.filters['autoria__autor__tipo'].label = 'Tipo de Autor'
@ -1023,3 +1025,51 @@ class JustificativaAusenciaForm(ModelForm):
justificativa.materias_do_expediente.clear()
justificativa.materias_da_ordem_do_dia.clear()
return justificativa
class OrdemExpedienteLeituraForm(forms.ModelForm):
observacao = forms.CharField(required=False, label='Observação', widget=forms.Textarea,)
class Meta:
model = RegistroLeitura
fields = ['materia',
'ordem',
'expediente',
'observacao',
'user',
'ip']
widgets = {'materia': forms.HiddenInput(),
'ordem': forms.HiddenInput(),
'expediente': forms.HiddenInput(),
'user': forms.HiddenInput(),
'ip': forms.HiddenInput()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
instance = self.initial['instance']
if instance:
self.instance = instance.first()
self.fields['observacao'].initial = self.instance.observacao
row1 = to_row(
[('observacao', 12)])
actions = [HTML('<a href="{{ view.cancel_url }}"'
' class="btn btn-warning">Cancelar Leitura</a>')]
self.helper = SaplFormHelper()
self.helper.form_method = 'POST'
self.helper.layout = Layout(
Fieldset(_('Leitura de Matéria'),
HTML('''
<b>Matéria:</b> {{materia}}<br>
<b>Ementa:</b> {{materia.ementa}} <br>
'''),
row1,
form_actions(more=actions),
)
)

62
sapl/sessao/migrations/0046_auto_20190827_1228.py

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-08-27 15:28
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('materia', '0055_auto_20190816_0943'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('sessao', '0045_auto_20190816_1337'),
]
operations = [
migrations.CreateModel(
name='RegistroLeitura',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('observacao', models.TextField(blank=True, verbose_name='Observações')),
('ip', models.CharField(blank=True, default='', max_length=30, verbose_name='IP')),
('data_hora', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Data/Hora')),
],
options={
'verbose_name': 'Leitura',
'verbose_name_plural': 'Leituras',
},
),
migrations.AlterField(
model_name='expedientemateria',
name='tipo_votacao',
field=models.PositiveIntegerField(choices=[(1, 'Simbólica'), (2, 'Nominal'), (3, 'Secreta'), (4, 'Leitura')], default=1, verbose_name='Tipo de votação'),
),
migrations.AlterField(
model_name='ordemdia',
name='tipo_votacao',
field=models.PositiveIntegerField(choices=[(1, 'Simbólica'), (2, 'Nominal'), (3, 'Secreta'), (4, 'Leitura')], default=1, verbose_name='Tipo de votação'),
),
migrations.AddField(
model_name='registroleitura',
name='expediente',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.ExpedienteMateria'),
),
migrations.AddField(
model_name='registroleitura',
name='materia',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'),
),
migrations.AddField(
model_name='registroleitura',
name='ordem',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.OrdemDia'),
),
migrations.AddField(
model_name='registroleitura',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
),
]

30
sapl/sessao/migrations/0047_auto_20190829_1253.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-08-29 15:53
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sessao', '0046_auto_20190827_1228'),
]
operations = [
migrations.AlterField(
model_name='registroleitura',
name='data_hora',
field=models.DateTimeField(auto_now=True, null=True, verbose_name='Data/Hora'),
),
migrations.AlterField(
model_name='registrovotacao',
name='data_hora',
field=models.DateTimeField(auto_now=True, null=True, verbose_name='Data/Hora'),
),
migrations.AlterField(
model_name='votoparlamentar',
name='data_hora',
field=models.DateTimeField(auto_now=True, null=True, verbose_name='Data/Hora'),
),
]

53
sapl/sessao/models.py

@ -311,6 +311,7 @@ class AbstractOrdemDia(models.Model):
(1, 'simbolica', 'Simbólica'),
(2, 'nominal', 'Nominal'),
(3, 'secreta', 'Secreta'),
(4, 'leitura', 'Leitura')
)
sessao_plenaria = models.ForeignKey(SessaoPlenaria,
@ -560,7 +561,7 @@ class RegistroVotacao(models.Model):
default='')
data_hora = models.DateTimeField(
verbose_name=_('Data/Hora'),
auto_now_add=True,
auto_now=True,
blank=True,
null=True)
@ -611,7 +612,7 @@ class VotoParlamentar(models.Model): # RegistroVotacaoParlamentar
default='')
data_hora = models.DateTimeField(
verbose_name=_('Data/Hora'),
auto_now_add=True,
auto_now=True,
blank=True,
null=True)
@ -880,3 +881,51 @@ class RetiradaPauta(models.Model):
'ReritadaPauta deve ter exatamente um dos campos '
'ordem ou expediente preenchido. Ambos estão preenchidos: '
'{}, {}'. format(self.ordem, self.expediente))
@reversion.register()
class RegistroLeitura(models.Model):
materia = models.ForeignKey(MateriaLegislativa, on_delete=models.CASCADE)
ordem = models.ForeignKey(OrdemDia,
blank=True,
null=True,
on_delete=models.CASCADE)
expediente = models.ForeignKey(ExpedienteMateria,
blank=True,
null=True,
on_delete=models.CASCADE)
observacao = models.TextField(
blank=True, verbose_name=_('Observações'))
user = models.ForeignKey(get_settings_auth_user_model(),
on_delete=models.PROTECT,
null=True,
blank=True)
ip = models.CharField(verbose_name=_('IP'),
max_length=30,
blank=True,
default='')
data_hora = models.DateTimeField(
verbose_name=_('Data/Hora'),
auto_now=True,
blank=True,
null=True)
class Meta:
verbose_name = _('Leitura')
verbose_name_plural = _('Leituras')
def __str__(self):
return _('Leitura - '
'Matéria: %(materia)s') % {
'materia': self.materia}
def clean(self):
"""Exatamente um dos campos ordem ou expediente deve estar preenchido.
"""
# TODO remover esse método quando OrdemDia e ExpedienteMateria
# forem reestruturados e os campos ordem e expediente forem unificados
if not xor(bool(self.ordem), bool(self.expediente)):
raise ValidationError(
'RegistroLeitura deve ter exatamente um dos campos '
'ordem ou expediente preenchido. Ambos estão preenchidos: '
'{}, {}'. format(self.ordem, self.expediente))

23
sapl/sessao/urls.py

@ -34,7 +34,10 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
sessao_legislativa_legislatura_ajax,
VotacaoEmBlocoOrdemDia, VotacaoEmBlocoExpediente,
VotacaoEmBlocoSimbolicaView, VotacaoEmBlocoNominalView,
recuperar_nome_tipo_sessao)
recuperar_nome_tipo_sessao,
ExpedienteLeituraView,
OrdemDiaLeituraView,
retirar_leitura)
from .apps import AppConfig
@ -150,13 +153,11 @@ urlpatterns = [
PesquisarSessaoPlenariaView.as_view(), name='pesquisar_sessao'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votnom/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoNominalView.as_view(), name='votacaonominal'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votnom'
'/edit/(?P<oid>\d+)/(?P<mid>\d+)$',
url(r'^sessao/(?P<pk>\d+)/matordemdia/votnom/edit/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoNominalEditView.as_view(), name='votacaonominaledit'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsec/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoView.as_view(), name='votacaosecreta'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsec'
'/view/(?P<oid>\d+)/(?P<mid>\d+)$',
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsec/view/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoEditView.as_view(), name='votacaosecretaedit'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoView.as_view(), name='votacaosimbolica'),
@ -164,8 +165,7 @@ urlpatterns = [
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimbbloco/$',
VotacaoView.as_view(), name='votacaosimbolicabloco'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb'
'/view/(?P<oid>\d+)/(?P<mid>\d+)$',
url(r'^sessao/(?P<pk>\d+)/matordemdia/votsimb/view/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoEditView.as_view(), name='votacaosimbolicaedit'),
url(r'^sessao/(?P<pk>\d+)/matexp/votnom/(?P<oid>\d+)/(?P<mid>\d+)$',
VotacaoNominalExpedienteView.as_view(), name='votacaonominalexp'),
@ -192,4 +192,13 @@ urlpatterns = [
url(r'^sessao/mudar-ordem-materia-sessao/',
mudar_ordem_materia_sessao,
name='mudar_ordem_materia_sessao'),
url(r'^sessao/(?P<pk>\d+)/matexp/leitura/(?P<oid>\d+)/(?P<mid>\d+)$',
ExpedienteLeituraView.as_view(), name='leituraexp'),
url(r'^sessao/(?P<pk>\d+)/matordemdia/leitura/(?P<oid>\d+)/(?P<mid>\d+)$',
OrdemDiaLeituraView.as_view(), name='leituraod'),
url(r'^sessao/(?P<pk>\d+)/(?P<iso>\d+)/(?P<oid>\d+)/retirar-leitura$',
retirar_leitura, name='retirar_leitura'),
]

162
sapl/sessao/views.py

@ -34,7 +34,7 @@ from sapl.materia.views import MateriaLegislativaPesquisaView
from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato,
Parlamentar, SessaoLegislativa)
from sapl.sessao.apps import AppConfig
from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm
from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm, OrdemExpedienteLeituraForm
from sapl.utils import show_results_filter_set, remover_acentos, get_client_ip
from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm,
@ -49,7 +49,8 @@ from .models import (Bancada, CargoBancada, CargoMesa,
PresencaOrdemDia, RegistroVotacao, ResumoOrdenacao,
SessaoPlenaria, SessaoPlenariaPresenca, TipoExpediente,
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar, TipoRetiradaPauta,
RetiradaPauta, TipoJustificativa, JustificativaAusencia, OradorOrdemDia, ORDENACAO_RESUMO)
RetiradaPauta, TipoJustificativa, JustificativaAusencia, OradorOrdemDia,
ORDENACAO_RESUMO, RegistroLeitura)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
@ -142,12 +143,12 @@ def verifica_votacoes_abertas(request):
kwargs={'pk': v.id}),
v.__str__()))
username = request.user.username
logger.info('user=' + username + '. Já existem votações abertas nas seguintes Sessões: ' +
logger.info('user=' + username + '. Já existem votações ou leituras abertas nas seguintes Sessões: ' +
', '.join(msg_abertas) + '. Para abrir '
'outra, termine ou feche as votações abertas.')
msg = _('Já existem votações abertas nas seguintes Sessões: ' +
'outra, termine ou feche as votações ou leituras abertas.')
msg = _('Já existem votações ou leituras abertas nas seguintes Sessões: ' +
', '.join(msg_abertas) + '. Para abrir '
'outra, termine ou feche as votações abertas.')
'outra, termine ou feche as votações ou leituras abertas.')
messages.add_message(request, messages.INFO, msg)
return False
@ -254,7 +255,11 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
materia=obj.materia).exists()
exist_retirada = obj.retiradapauta_set.filter(
materia=obj.materia).exists()
if not exist_resultado and not exist_retirada:
exist_leitura = obj.registroleitura_set.filter(
materia=obj.materia).exists()
if (obj.tipo_votacao != 4 and not exist_resultado and not exist_retirada) or\
(obj.tipo_votacao == 4 and not exist_leitura):
if obj.votacao_aberta:
url = ''
if is_expediente:
@ -276,6 +281,13 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
elif obj.tipo_votacao == 4:
url = reverse('sapl.sessao:leituraexp',
kwargs={
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
else:
if obj.tipo_votacao == 1:
url = reverse('sapl.sessao:votacaosimbolica',
@ -295,13 +307,28 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
elif obj.tipo_votacao == 4:
url = reverse('sapl.sessao:leituraod',
kwargs={
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
if has_permission:
if obj.tipo_votacao != 4:
btn_registrar = '''
<form action="%s">
<input type="submit" class="btn btn-primary"
value="Registrar Votação" />
</form>''' % (
url)
else:
btn_registrar = '''
<form action="%s">
<input type="submit" class="btn btn-primary"
value="Registrar Leitura" />
</form>''' % (
url)
resultado = btn_registrar
else:
@ -319,12 +346,20 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
}) + '?tipo_materia=ordem'
if has_permission:
if not obj.tipo_votacao == 4:
btn_abrir = '''
Matéria não votada<br />
<a href="%s"
class="btn btn-primary"
role="button">Abrir Votação</a>''' % (url)
resultado = btn_abrir
else:
btn_abrir = '''
Matéria não lida<br />
<a href="%s"
class="btn btn-primary"
role="button">Abrir para Leitura</a>''' % (url)
resultado = btn_abrir
else:
resultado = '''Não há resultado'''
@ -341,10 +376,16 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
retirada_observacao))
else:
resultado = obj.registrovotacao_set.filter(
if obj.tipo_votacao == 4:
resultado = obj.registroleitura_set.filter(
materia_id=obj.materia_id).last()
resultado_descricao = resultado.tipo_resultado_votacao.nome
resultado_descricao = "Matéria lida"
resultado_observacao = resultado.observacao
else:
resultado = obj.registrovotacao_set.filter(
materia_id=obj.materia_id).last()
resultado_descricao = obj.resultado
resultado_observacao = obj.observacao
if has_permission:
url = ''
@ -368,6 +409,12 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
elif obj.tipo_votacao == 4:
url = reverse('sapl.sessao:leituraexp',
kwargs={
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
else:
if obj.tipo_votacao == 1:
url = reverse('sapl.sessao:votacaosimbolicaedit',
@ -387,8 +434,14 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
elif obj.tipo_votacao == 4:
url = reverse('sapl.sessao:leituraod',
kwargs={
'pk': obj.sessao_plenaria_id,
'oid': obj.pk,
'mid': obj.materia_id})
resultado = ('<a href="%s">%s<br/>%s</a>' %
resultado = ('<a href="%s">%s<br/><br/>%s</a>' %
(url,
resultado_descricao,
resultado_observacao))
@ -4325,3 +4378,92 @@ class RetiradaPautaCrud(MasterDetailCrud):
class DeleteView(MasterDetailCrud.DeleteView):
pass
class AbstractLeituraView(FormView):
template_name = 'sessao/votacao/leitura_form.html'
success_url = '/'
form_class = OrdemExpedienteLeituraForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['materia'] = MateriaLegislativa.objects.get(id=self.kwargs['mid'])
return context
def get_initial(self):
initial = super().get_initial()
materia = MateriaLegislativa.objects.get(id=self.kwargs['mid'])
initial['materia'] = materia
initial['materia__ementa'] = materia.ementa
if self.expediente:
expediente = ExpedienteMateria.objects.get(id=self.kwargs['oid'])
instance = RegistroLeitura.objects.filter(materia=materia, expediente=expediente)
initial['expediente'] = expediente
else:
ordem = OrdemDia.objects.get(id=self.kwargs['oid'])
instance = RegistroLeitura.objects.filter(materia=materia, ordem=ordem)
initial['ordem'] = ordem
initial['instance'] = instance
initial['user'] = self.request.user
initial['ip'] = get_client_ip(self.request)
return initial
def form_valid(self, form):
if self.expediente:
model = ExpedienteMateria
else:
model = OrdemDia
ordem_expediente = model.objects.get(id=self.kwargs['oid'])
ordem_expediente.resultado = "Matéria lida"
ordem_expediente.votacao_aberta = False
ordem_expediente.save()
form.save()
return super().form_valid(form)
def get_success_url(self):
pk = self.kwargs['pk']
if self.expediente:
url = reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': pk})
else:
url = reverse('sapl.sessao:ordemdia_list',
kwargs={'pk': pk})
return url
def cancel_url(self):
url = reverse('sapl.sessao:retirar_leitura',
kwargs={
'pk': self.kwargs['pk'],
'iso': 1 if not self.expediente else 0,
'oid': self.kwargs['oid']})
return url
class ExpedienteLeituraView(AbstractLeituraView):
expediente = True
class OrdemDiaLeituraView(AbstractLeituraView):
expediente = False
@permission_required('sessao.change_expedientemateria',
'sessao.change_ordemdia')
def retirar_leitura(request, pk, iso, oid):
is_ordem = bool(int(iso))
if not is_ordem:
ordem_expediente = ExpedienteMateria.objects.get(id=oid)
RegistroLeitura.objects.filter(materia=ordem_expediente.materia, expediente=ordem_expediente).delete()
succ_url = reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': pk})
else:
ordem_expediente = OrdemDia.objects.get(id=oid)
RegistroLeitura.objects.filter(materia=ordem_expediente.materia, ordem=ordem_expediente).delete()
succ_url = reverse('sapl.sessao:ordemdia_list',
kwargs={'pk': pk})
ordem_expediente.resultado = ""
ordem_expediente.votacao_aberta = False
ordem_expediente.save()
return HttpResponseRedirect(succ_url)

24
sapl/templates/painel/index.html

@ -99,6 +99,7 @@
<div class="col-md-6 text-center painel" id="obs_materia_div">
<h2 class="text-subtitle" id="mat_em_votacao">Matéria em Votação</h2>
<span id="materia_legislativa_texto" class="text-value"></span>
<br>
<span id="observacao_materia" class="text-value"></span>
</div>
@ -421,23 +422,40 @@
else{
$("#observacao_materia").text('');
}
if (data['tipo_resultado'] && data['status_painel'] == true){
$("#resultado_votacao").text(data["tipo_resultado"]);
if(data['tipo_votacao'] != 'Leitura'){
$("#resultado_votacao").css("color", "#45919D");
$("#mat_em_votacao").text("Matéria em Votação");
$("#resultado_votacao_div").show();
}
else{
$("#resultado_votacao_div").hide();
$("#mat_em_votacao").text("Matéria em Leitura");
}
console.log(data["tipo_resultado"], data['tipo_votacao']);
$("#resultado_votacao").text(data["tipo_resultado"]);
var resultado_votacao_upper = $("#resultado_votacao").text().toUpperCase();
console.log(resultado_votacao_upper, data['tipo_resultado']);
if (resultado_votacao_upper.search("APROV") != -1){
$("#resultado_votacao").css("color", "green");
$("#mat_em_votacao").text("Matéria Votada");
}
if (resultado_votacao_upper.search("REJEIT") != -1){
else if (resultado_votacao_upper.search("REJEIT") != -1){
$("#resultado_votacao").css("color", "red");
$("#mat_em_votacao").text("Matéria Votada");
}
else if (resultado_votacao_upper.search("LIDA") != -1){
$("#mat_em_votacao").text("Matéria Lida");
}
}
else{
$("#resultado_votacao").text('');
if(data['tipo_votacao'] != 'Leitura')
$("#mat_em_votacao").text("Matéria em Votação");
else{
$("#mat_em_votacao").text("Matéria em Leitura");
}
}
},
error: function(err) {

19
sapl/templates/sessao/expedientemateria_form.html

@ -32,11 +32,26 @@
});
}
}
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]
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()
recuperar_materia();
$(document).ready(function(){
$("select[name='tipo_votacao']").children("option[value='4']").remove();
$('#id_apenas_leitura').change(function(event){
$('#div_id_tipo_votacao').toggle();
if($('#id_apenas_leitura').prop('checked')){
$("select[name='tipo_votacao']").append(new Option('Leitura', '4'));
$("select[name='tipo_votacao']").val('4');
}
else{
$("select[name='tipo_votacao']").children("option[value='4']").remove();
$("select[name='tipo_votacao']").val('1');
}
})
});
</script>
{% endblock %}

2
sapl/templates/sessao/layouts.yaml

@ -59,6 +59,7 @@ ExpedienteMateria:
- data_ordem numero_ordem
- tipo_materia numero_materia ano_materia
- tipo_votacao
- apenas_leitura
- observacao
OrdemDia:
@ -66,6 +67,7 @@ OrdemDia:
- data_ordem numero_ordem
- tipo_materia numero_materia ano_materia
- tipo_votacao
- apenas_leitura
- observacao
ExpedienteMateriaDetail:

6
sapl/templates/sessao/votacao/leitura_form.html

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% load i18n crispy_forms_tags %}
{% block base_content %}
{% crispy form %}
{% endblock base_content %}
Loading…
Cancel
Save