Browse Source

Fix #1183 votacao nominal intuitiva (#1188)

* Inicia a logica

* Adaptação da lógica da votação interativa

* Faz mudanças sugeridas no code review

* Ajusta separador de msg_abertas.

Ajusta separador de msg_abertas.

* Ajusta listagem de votações abertas

Ajusta listagem de votações abertas
pull/1193/head
Eduardo Calil 8 years ago
committed by Edward
parent
commit
4217b9f66a
  1. 2
      sapl/painel/urls.py
  2. 153
      sapl/painel/views.py
  3. 71
      sapl/sessao/views.py
  4. 5
      sapl/templates/base.html
  5. 18
      sapl/templates/painel/voto_nominal.html
  6. 14
      sapl/templates/sessao/sessaoplenaria_detail.html

2
sapl/painel/urls.py

@ -20,6 +20,6 @@ urlpatterns = [
url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'), url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'),
# url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())), # url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())),
url(r'^voto-individual/(?P<pk>\d+)$', votante_view, url(r'^voto-individual/$', votante_view,
name="voto_individual"), name="voto_individual"),
] ]

153
sapl/painel/views.py

@ -1,7 +1,9 @@
from datetime import date from datetime import date
from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db.models import Q
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse
from django.http.response import Http404, HttpResponseRedirect from django.http.response import Http404, HttpResponseRedirect
@ -30,18 +32,66 @@ def check_permission(user):
return user.has_module_perms(AppConfig.label) return user.has_module_perms(AppConfig.label)
def votante_view(request, pk): def votacao_aberta(request):
if not Votante.objects.filter(user=request.user).exists(): votacoes_abertas = SessaoPlenaria.objects.filter(
raise Http404('Você não tem permissão para votar') Q(ordemdia__votacao_aberta=True) |
Q(expedientemateria__votacao_aberta=True)).distinct()
context = {'head_title': str(_('Votação Individual')), 'sessao_id': pk}
if len(votacoes_abertas) > 1:
# Pega sessão msg_abertas = []
for v in votacoes_abertas:
msg_abertas.append('''<li><a href="%s">%s</a></li>''' % (
reverse('sapl.sessao:sessaoplenaria_detail',
kwargs={'pk': v.id}),
v.__str__()))
msg = _('Existe mais de uma votações aberta. Elas se encontram '
'nas seguintes Sessões: ' + ', '.join(msg_abertas) + '. '
'Para votar, peça para que o Operador feche-as.')
messages.add_message(request, messages.INFO, msg)
return None, msg
elif len(votacoes_abertas) == 1:
ordens = OrdemDia.objects.filter(
sessao_plenaria=votacoes_abertas.first(),
votacao_aberta=True)
expedientes = ExpedienteMateria.objects.filter(
sessao_plenaria=votacoes_abertas.first(),
votacao_aberta=True)
numero_materias_abertas = len(ordens) + len(expedientes)
if numero_materias_abertas > 1:
msg = _('Existe mais de uma votação aberta na Sessão: ' +
('''<li><a href="%s">%s</a></li>''' % (
reverse('sapl.sessao:sessaoplenaria_detail',
kwargs={'pk': votacoes_abertas.first().id}),
votacoes_abertas.first().__str__())) +
'Para votar, peça para que o Operador as feche.')
messages.add_message(request, messages.INFO, msg)
return None, msg
return votacoes_abertas.first(), None
def votante_view(request):
# Pega o votante relacionado ao usuário
try: try:
sessao = SessaoPlenaria.objects.get(pk=pk) votante = Votante.objects.get(user=request.user)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404() raise Http404()
context = {'head_title': str(_('Votação Individual'))}
# Verifica se usuário possui permissão para votar
if 'parlamentares.can_vote' in request.user.get_all_permissions():
context.update({'permissao': True})
# Pega sessão
sessao, msg = votacao_aberta(request)
if sessao and not msg:
pk = sessao.pk
context.update({'sessao_id': pk})
context.update({'sessao': sessao, context.update({'sessao': sessao,
'data': sessao.data_inicio, 'data': sessao.data_inicio,
'hora': sessao.hora_inicio}) 'hora': sessao.hora_inicio})
@ -53,54 +103,34 @@ def votante_view(request, pk):
# Se aberta, verifica se é nominal. ID nominal == 2 # Se aberta, verifica se é nominal. ID nominal == 2
ordem_dia = get_materia_aberta(pk) ordem_dia = get_materia_aberta(pk)
expediente = get_materia_expediente_aberta(pk) expediente = get_materia_expediente_aberta(pk)
materia = None
materia_aberta = None
if ordem_dia: if ordem_dia:
materia = ordem_dia.materia materia_aberta = ordem_dia
if ordem_dia.tipo_votacao == VOTACAO_NOMINAL: presentes = PresencaOrdemDia.objects.filter(
context.update({'materia': materia, 'ementa': materia.ementa}) sessao_plenaria_id=pk).values_list(
presentes = PresencaOrdemDia.objects.filter(sessao_plenaria_id=pk) 'parlamentar_id', flat=True).distinct()
else:
context.update(
{'materia': 'A matéria aberta não é votação nominal.'})
elif expediente: elif expediente:
materia = expediente.materia materia_aberta = expediente
if expediente.tipo_votacao == VOTACAO_NOMINAL:
context.update({'materia': materia, 'ementa': materia.ementa})
presentes = SessaoPlenariaPresenca.objects.filter( presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=pk) sessao_plenaria_id=pk).values_list(
else: 'parlamentar_id', flat=True).distinct()
context.update(
{'materia': 'A matéria aberta não é votação nominal.'})
else:
context.update(
{'materia': 'Nenhuma matéria com votação nominal aberta.'})
# Verifica se usuário possui permissão para votar if materia_aberta:
if 'parlamentares.can_vote' in request.user.get_all_permissions(): if materia_aberta.tipo_votacao == VOTACAO_NOMINAL:
context.update({'permissao': True}) context.update({'materia': materia_aberta.materia,
else: 'ementa': materia_aberta.materia.ementa})
context.update({'permissao': False})
# Verifica se usuário está presente na sessão
try:
votante = Votante.objects.get(user=request.user)
except ObjectDoesNotExist:
context.update({'error_message':
'Erro ao recuperar parlamentar ligado ao usuário'})
else:
parlamentar = votante.parlamentar parlamentar = votante.parlamentar
context.update({'presente': False}) parlamentar_presente = False
if len(presentes) > 0: if parlamentar.id in presentes:
for p in presentes: parlamentar_presente = True
if p.parlamentar.id == parlamentar.id:
context.update({'presente': True})
break
else: else:
context.update({'error_message': context.update({'error_message':
'Nenhuma matéria com votação nominal aberta.'}) 'Não há presentes na Sessão com a '
'matéria em votação.'})
# Recupera o voto do parlamentar logado if parlamentar_presente:
voto = [] voto = []
if ordem_dia: if ordem_dia:
voto = VotoParlamentar.objects.filter( voto = VotoParlamentar.objects.filter(
@ -112,10 +142,33 @@ def votante_view(request, pk):
if voto: if voto:
try: try:
voto = voto.get(parlamentar=parlamentar) voto = voto.get(parlamentar=parlamentar)
context.update({'voto_parlamentar': voto.voto})
except ObjectDoesNotExist: except ObjectDoesNotExist:
context.update({'voto_parlamentar': 'Voto não computado.'}) context.update(
{'voto_parlamentar': 'Voto não '
'computado.'})
else: else:
context.update({'voto_parlamentar': voto.voto}) context.update({'error_message':
'Você não está presente na '
'Ordem do Dia/Expediente em votação.'})
else:
context.update(
{'error_message': 'A matéria aberta não é votação '
'nominal.'})
else:
context.update(
{'error_message': 'Nenhuma matéria aberta.'})
elif not sessao and msg:
return HttpResponseRedirect('/')
else:
context.update(
{'error_message': 'Nenhuma sessão com matéria aberta.'})
else:
context.update({'permissao': False,
'error_message': 'Usuário sem permissão para votar.'})
# Salva o voto # Salva o voto
if request.method == 'POST': if request.method == 'POST':
@ -156,7 +209,7 @@ def votante_view(request, pk):
voto.save() voto.save()
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('sapl.painel:voto_individual', kwargs={'pk': pk})) reverse('sapl.painel:voto_individual'))
return render(request, 'painel/voto_nominal.html', context) return render(request, 'painel/voto_nominal.html', context)

71
sapl/sessao/views.py

@ -6,6 +6,7 @@ from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import Q
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.http import JsonResponse from django.http import JsonResponse
from django.http.response import Http404, HttpResponseRedirect from django.http.response import Http404, HttpResponseRedirect
@ -81,49 +82,44 @@ def reordernar_materias_ordem(request, pk):
reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk})) reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk}))
@permission_required('sessao.change_expedientemateria') def verifica_votacoes_abertas(request, model, pk):
def abrir_votacao_expediente_view(request, pk, spk): votacoes_abertas = SessaoPlenaria.objects.filter(
existe_expediente_aberto = ExpedienteMateria.objects.filter( Q(ordemdia__votacao_aberta=True) |
sessao_plenaria_id=spk, votacao_aberta=True Q(expedientemateria__votacao_aberta=True)).distinct()
).exists()
existe_ordem_aberta = OrdemDia.objects.filter( if votacoes_abertas:
sessao_plenaria_id=spk, votacao_aberta=True msg_abertas = []
).exists() for v in votacoes_abertas:
msg_abertas.append('''<li><a href="%s">%s</a></li>''' % (
if existe_expediente_aberto or existe_ordem_aberta: reverse('sapl.sessao:sessaoplenaria_detail',
msg = _('Já existe uma matéria com votação aberta. Para abrir ' kwargs={'pk': v.id}),
'outra, termine ou feche a votação existente.') v.__str__()))
msg = _('Já existem votações abertas nas seguintes Sessões: ' +
', '.join(msg_abertas) + '. Para abrir '
'outra, termine ou feche as votações abertas.')
messages.add_message(request, messages.INFO, msg) messages.add_message(request, messages.INFO, msg)
else: else:
expediente = ExpedienteMateria.objects.get(id=pk) materia_votacao = model.objects.get(id=pk)
expediente.votacao_aberta = True materia_votacao.votacao_aberta = True
expediente.save() materia_votacao.save()
@permission_required('sessao.change_expedientemateria')
def abrir_votacao_expediente_view(request, pk, spk):
verifica_votacoes_abertas(request, ExpedienteMateria, pk)
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': spk})) reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': spk}))
@permission_required('sessao.change_ordemdia') @permission_required('sessao.change_ordemdia')
def abrir_votacao_ordem_view(request, pk, spk): def abrir_votacao_ordem_view(request, pk, spk):
existe_ordem_aberta = OrdemDia.objects.filter( verifica_votacoes_abertas(request, OrdemDia, pk)
sessao_plenaria_id=spk, votacao_aberta=True
).exists()
existe_expediente_aberto = ExpedienteMateria.objects.filter(
sessao_plenaria_id=spk, votacao_aberta=True
).exists()
if existe_ordem_aberta or existe_expediente_aberto:
msg = _('Já existe uma matéria com votação aberta. Para abrir '
'outra, termine ou feche a votação existente.')
messages.add_message(request, messages.INFO, msg)
else:
ordem = OrdemDia.objects.get(id=pk)
ordem.votacao_aberta = True
ordem.save()
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('sapl.sessao:ordemdia_list', kwargs={'pk': spk})) reverse('sapl.sessao:ordemdia_list', kwargs={'pk': spk}))
def put_link_materia(context): def put_link_materia(context):
for i, row in enumerate(context['rows']): for i, row in enumerate(context['rows']):
materia = context['object_list'][i].materia materia = context['object_list'][i].materia
@ -133,6 +129,7 @@ def put_link_materia(context):
context['rows'][i][1] = (row[1][0], url_materia) context['rows'][i][1] = (row[1][0], url_materia)
return context return context
def get_presencas_generic(model, sessao, legislatura): def get_presencas_generic(model, sessao, legislatura):
presencas = model.objects.filter( presencas = model.objects.filter(
sessao_plenaria=sessao) sessao_plenaria=sessao)
@ -1753,6 +1750,18 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
materia_votacao.votacao_aberta = False materia_votacao.votacao_aberta = False
materia_votacao.save() materia_votacao.save()
# Verifica se existe algum VotoParlamentar sem RegistroVotacao
# Por exemplo, se algum parlamentar votar e sua presença for
# removida da ordem do dia/expediente antes da conclusão da
# votação
if self.ordem:
VotoParlamentar.objects.filter(
ordem=ordem,
votacao__isnull=True).delete()
elif self.expediente:
VotoParlamentar.objects.filter(
expediente=expediente,
votacao__isnull=True).delete()
return self.form_valid(form) return self.form_valid(form)
else: else:
return self.form_invalid(form) return self.form_invalid(form)

5
sapl/templates/base.html

@ -63,6 +63,11 @@
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a>{{user.username}}</a></li> <li><a>{{user.username}}</a></li>
{% if 'parlamentares.can_vote' in request.user.get_all_permissions %}
<li><a href="{% url 'sapl.painel:voto_individual' %}">
Votar Matéria
</a></li>
{% endif %}
<li><a href="{% url 'sapl.base:logout' %}">Sair</a></li> <li><a href="{% url 'sapl.base:logout' %}">Sair</a></li>
</ul> </ul>
</li> </li>

18
sapl/templates/painel/voto_nominal.html

@ -21,7 +21,7 @@
} }
</style> </style>
</head> </head>
{% if permissao and presente %} {% if not error_message %}
<body> <body>
<h1><b><font color="#4FA64D"><p align="center">{{sessao}}</p></font></b></h1> <h1><b><font color="#4FA64D"><p align="center">{{sessao}}</p></font></b></h1>
<table style="width:100%"> <table style="width:100%">
@ -74,23 +74,7 @@
</form> </form>
</body> </body>
{% elif not permissao %}
{% if error_message %}
<h2><font color="red"><p align="center" style="font-family:Verdana">{{error_message}}</p></font></h2>
{% else %}
<h2><font color="red"><p align="center" style="font-family:Verdana">Usuário sem permissão para participar de votações.</p></font></h2>
{% endif %}
{% elif not presente %}
{% if error_message %}
<h2><font color="red"><p align="center" style="font-family:Verdana">{{error_message}}</p></font></h2>
{% else %} {% else %}
<h2><font color="red"><p align="center" style="font-family:Verdana">Usuário não presente na Sessão Plenária.</p></font></h2>
{% endif %}
{% else %}
{% if error_message %}
<h2><font color="red"><p align="center" style="font-family:Verdana">{{error_message}}</p></font></h2> <h2><font color="red"><p align="center" style="font-family:Verdana">{{error_message}}</p></font></h2>
{% else %}
<h2><font color="red"><p align="center" style="font-family:Verdana">Usuário não presente na Sessão Plenária e sem permissão para votações.</p></font></h2>
{% endif %}
{% endif %} {% endif %}
</html> </html>

14
sapl/templates/sessao/sessaoplenaria_detail.html

@ -1,14 +0,0 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block extra_actions %}
{% if 'parlamentares.can_vote' in request.user.get_all_permissions %}
<div class="actions btn-group btn-group-sm" role="group">
<a href="{% url 'sapl.painel:voto_individual' object.pk %}" class="btn btn-default">
Votar Matéria
</a>
</div>
{% endif %}
{% endblock extra_actions %}
Loading…
Cancel
Save