Browse Source

Merge pull request #906 from interlegis/762-votação-eletrônica

Fix #762 votação eletrônica
pull/907/head
Eduardo Edson Batista Cordeiro Alves 8 years ago
committed by GitHub
parent
commit
24f3e40932
  1. 2
      sapl/norma/forms.py
  2. 5
      sapl/painel/urls.py
  3. 107
      sapl/painel/views.py
  4. 30
      sapl/parlamentares/apps.py
  5. 94
      sapl/parlamentares/forms.py
  6. 31
      sapl/parlamentares/migrations/0037_votante.py
  7. 19
      sapl/parlamentares/migrations/0038_auto_20170213_1425.py
  8. 19
      sapl/parlamentares/migrations/0039_remove_votante_ip.py
  9. 17
      sapl/parlamentares/models.py
  10. 5
      sapl/parlamentares/urls.py
  11. 34
      sapl/parlamentares/views.py
  12. 39
      sapl/sessao/migrations/0034_votonominal.py
  13. 23
      sapl/sessao/migrations/0035_auto_20170213_1455.py
  14. 21
      sapl/sessao/models.py
  15. 132
      sapl/sessao/views.py
  16. 3
      sapl/templates/crud/detail.html
  17. 85
      sapl/templates/painel/voto_nominal.html
  18. 5
      sapl/templates/parlamentares/layouts.yaml
  19. 2
      sapl/templates/parlamentares/subnav.yaml
  20. 16
      sapl/templates/parlamentares/votante_list.html
  21. 14
      sapl/templates/sessao/sessaoplenaria_detail.html
  22. 1
      sapl/templates/sessao/subnav.yaml
  23. 20
      sapl/templates/sessao/votacao/nominal.html

2
sapl/norma/forms.py

@ -17,9 +17,11 @@ from sapl.utils import RANGE_ANOS, RangeWidgetOverride
from .models import (AssuntoNorma, NormaJuridica, NormaRelacionada,
TipoNormaJuridica)
def ANO_CHOICES():
return [('', '---------')] + RANGE_ANOS
def get_esferas():
return [('E', 'Estadual'),
('F', 'Federal'),

5
sapl/painel/urls.py

@ -3,7 +3,7 @@ from django.conf.urls import url
from .apps import AppConfig
from .views import (controlador_painel, cronometro_painel, get_dados_painel,
painel_mensagem_view, painel_parlamentar_view, painel_view,
painel_votacao_view)
painel_votacao_view, votante_view)
app_name = AppConfig.name
@ -19,4 +19,7 @@ urlpatterns = [
url(r'^painel/votacao$', painel_votacao_view, name='painel_votacao'),
url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'),
# url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())),
url(r'^voto-individual/(?P<pk>\d+)$', votante_view,
name="voto_individual"),
]

107
sapl/painel/views.py

@ -1,4 +1,7 @@
from django.http.response import HttpResponseRedirect
from django.core.urlresolvers import reverse
from datetime import date
from sapl.utils import get_client_ip
from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import ObjectDoesNotExist
@ -9,10 +12,11 @@ from django.utils.translation import ugettext_lazy as _
from sapl.crud.base import Crud
from sapl.painel.apps import AppConfig
from sapl.painel.models import Painel
from sapl.parlamentares.models import Filiacao
from sapl.parlamentares.models import Filiacao, Votante
from sapl.sessao.models import (ExpedienteMateria, OrdemDia, PresencaOrdemDia,
RegistroVotacao, SessaoPlenaria,
SessaoPlenariaPresenca, VotoParlamentar)
SessaoPlenariaPresenca, VotoNominal,
VotoParlamentar)
from .models import Cronometro
@ -25,6 +29,105 @@ def check_permission(user):
return user.has_module_perms(AppConfig.label)
def votante_view(request, pk):
context = {'head_title': str(_('Votação Individual')), 'sessao_id': pk}
# Pega sessão
sessao = SessaoPlenaria.objects.get(pk=pk)
context.update({'sessao': sessao,
'data': sessao.data_inicio,
'hora': sessao.hora_inicio})
# Inicializa presentes
presentes = []
# Verifica votação aberta
# Se aberta, verifica se é nominal. ID nominal == 2
ordem_dia = get_materia_aberta(pk)
expediente = get_materia_expediente_aberta(pk)
materia = None
if ordem_dia:
materia = ordem_dia.materia
if ordem_dia.tipo_votacao == 2:
context.update({'materia': materia, 'ementa': materia.ementa})
presentes = PresencaOrdemDia.objects.filter(sessao_plenaria_id=pk)
else:
context.update(
{'materia': 'A matéria aberta não é votação nominal.'})
elif expediente:
materia = expediente.materia
if expediente.tipo_votacao == 2:
context.update({'materia': materia, 'ementa': materia.ementa})
presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=pk)
else:
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 'parlamentares.can_vote' in request.user.get_all_permissions():
context.update({'permissao': True})
else:
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
context.update({'presente': False})
if len(presentes) > 0:
for p in presentes:
if p.parlamentar.id == parlamentar.id:
context.update({'presente': True})
break
else:
context.update({'error_message':
'Nenhuma matéria com votação nominal aberta.'})
# Recupera o voto do parlamentar logado
try:
voto = VotoNominal.objects.get(
sessao=sessao,
parlamentar=parlamentar,
materia=materia)
except ObjectDoesNotExist:
context.update({'voto_parlamentar': 'Voto não computado.'})
else:
context.update({'voto_parlamentar': voto.voto})
# Salva o voto
if request.method == 'POST':
try:
voto = VotoNominal.objects.get(
sessao=sessao,
parlamentar=parlamentar,
materia=materia)
except ObjectDoesNotExist:
voto = VotoNominal.objects.create(
sessao=sessao,
parlamentar=parlamentar,
materia=materia,
voto=request.POST['voto'],
ip=get_client_ip(request),
user=request.user)
else:
voto.voto = request.POST['voto']
voto.ip = get_client_ip(request)
voto.save()
return HttpResponseRedirect(
reverse('sapl.painel:voto_individual', kwargs={'pk': pk}))
return render(request, 'painel/voto_nominal.html', context)
@user_passes_test(check_permission)
def controlador_painel(request):

30
sapl/parlamentares/apps.py

@ -1,8 +1,38 @@
from django import apps
from django.db.models.signals import post_migrate
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ObjectDoesNotExist
def criar_grupo(permission):
from django.contrib.auth.models import Group
g = Group.objects.get_or_create(name='Votante')
g[0].permissions.add(permission)
def criar_permissao(sender, **kwargs):
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
try:
content_type = ContentType.objects.get(
app_label='parlamentares',
model='Votante')
except ObjectDoesNotExist:
content_type = ContentType.objects.create(
app_label='parlamentares',
model='Votante')
p = Permission.objects.get_or_create(
name='Can Vote', codename='can_vote', content_type=content_type)
criar_grupo(p[0])
class AppConfig(apps.AppConfig):
name = 'sapl.parlamentares'
label = 'parlamentares'
verbose_name = _('Parlamentares')
def ready(self):
post_migrate.connect(criar_permissao, sender=self)

94
sapl/parlamentares/forms.py

@ -1,6 +1,10 @@
from datetime import date, timedelta
from django.contrib.auth.models import Group
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Fieldset, Layout
from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import Q
@ -8,8 +12,10 @@ from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from floppyforms.widgets import ClearableFileInput
from sapl.crispy_layout_mixin import form_actions, to_row
from .models import (ComposicaoColigacao, Filiacao, Frente, Legislatura,
Mandato, Parlamentar)
Mandato, Parlamentar, Votante)
class ImageThumbnailFileInput(ClearableFileInput):
@ -231,3 +237,89 @@ class FrenteForm(ModelForm):
class Meta:
model = Frente
fields = '__all__'
class VotanteForm(ModelForm):
senha = forms.CharField(
max_length=20,
label=_('Senha'),
required=True,
widget=forms.PasswordInput())
senha_confirma = forms.CharField(
max_length=20,
label=_('Confirmar Senha'),
required=True,
widget=forms.PasswordInput())
username = forms.CharField(
label=_('Usuário'),
required=True,
max_length=30)
email = forms.EmailField(
required=True,
label=_('Email'))
email_confirma = forms.EmailField(
required=True,
label=_('Confirmar Email'))
class Meta:
model = Votante
fields = ['username', 'senha', 'senha_confirma', 'email',
'email_confirma']
def __init__(self, *args, **kwargs):
row1 = to_row([('username', 4), ('senha', 4), ('senha_confirma', 4)])
row2 = to_row([('email', 6), ('email_confirma', 6)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Votante'),
row1, row2, form_actions(save_label='Salvar'))
)
super(VotanteForm, self).__init__(*args, **kwargs)
def valida_igualdade(self, texto1, texto2, msg):
if texto1 != texto2:
raise ValidationError(msg)
return True
def clean(self):
cd = self.cleaned_data
if ('senha' not in cd or 'senha_confirma' not in cd or
not cd['senha'] or not cd['senha_confirma']):
raise ValidationError(_(
'A senha e sua confirmação devem ser informadas.'))
msg = _('As senhas não conferem.')
self.valida_igualdade(cd['senha'], cd['senha_confirma'], msg)
if ('email' not in cd or 'email_confirma' not in cd or
not cd['email'] or not cd['email_confirma']):
raise ValidationError(_(
'O email e sua confirmação devem ser informados.'))
msg = _('Os emails não conferem.')
self.valida_igualdade(cd['email'], cd['email_confirma'], msg)
return self.cleaned_data
@transaction.atomic
def save(self, commit=False):
votante = super(VotanteForm, self).save(commit)
# Cria user
u = User.objects.create(
username=self.cleaned_data['username'],
email=self.cleaned_data['email'])
u.set_password(self.cleaned_data['senha'])
u.save()
# Adiciona user ao grupo
g = Group.objects.filter(name='Votante')[0]
u.groups.add(g)
votante.user = u
votante.save()
return votante

31
sapl/parlamentares/migrations/0037_votante.py

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-02-09 15:18
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 = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('parlamentares', '0036_partido_logo_partido'),
]
operations = [
migrations.CreateModel(
name='Votante',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('data', models.DateTimeField(auto_now_add=True, max_length=30, null=True, verbose_name='Data')),
('ip', models.CharField(blank=True, max_length=30, null=True, verbose_name='IP')),
('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parlamentar', to='parlamentares.Parlamentar', verbose_name='Parlamentar')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'Votantes',
},
),
]

19
sapl/parlamentares/migrations/0038_auto_20170213_1425.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-02-13 14:25
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0037_votante'),
]
operations = [
migrations.AlterModelOptions(
name='votante',
options={'verbose_name': 'Usuários'},
),
]

19
sapl/parlamentares/migrations/0039_remove_votante_ip.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-02-13 14:26
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0038_auto_20170213_1425'),
]
operations = [
migrations.RemoveField(
model_name='votante',
name='ip',
),
]

17
sapl/parlamentares/models.py

@ -1,5 +1,6 @@
from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
@ -495,3 +496,19 @@ class Frente(models.Model):
def __str__(self):
return self.nome
class Votante(models.Model):
parlamentar = models.ForeignKey(
Parlamentar, verbose_name=_('Parlamentar'), related_name='parlamentar')
user = models.ForeignKey(User, verbose_name=_('User'), related_name='user')
data = models.DateTimeField(
verbose_name=_('Data'), auto_now_add=True,
max_length=30, null=True, blank=True)
class Meta:
verbose_name = _('Usuário')
verbose_name_plural = _('Usuários')
def __str__(self):
return self.user.username

5
sapl/parlamentares/urls.py

@ -11,7 +11,7 @@ from sapl.parlamentares.views import (CargoMesaCrud, ColigacaoCrud,
RelatoriaParlamentarCrud,
SessaoLegislativaCrud,
TipoAfastamentoCrud, TipoDependenteCrud,
TipoMilitarCrud)
TipoMilitarCrud, VotanteView)
from .apps import AppConfig
@ -23,7 +23,8 @@ urlpatterns = [
FiliacaoCrud.get_urls() + MandatoCrud.get_urls() +
ParticipacaoParlamentarCrud.get_urls() +
ProposicaoParlamentarCrud.get_urls() +
RelatoriaParlamentarCrud.get_urls() + FrenteList.get_urls()
RelatoriaParlamentarCrud.get_urls() + FrenteList.get_urls() +
VotanteView.get_urls()
)),
url(r'^sistema/coligacao/',

34
sapl/parlamentares/views.py

@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
from django.utils.datastructures import MultiValueDictKeyError
from django.utils.translation import ugettext_lazy as _
from django.views.generic import FormView
from django.http.response import HttpResponseRedirect
from sapl.comissoes.models import Participacao
from sapl.crud.base import (RP_CHANGE, RP_DETAIL, RP_LIST, Crud, CrudAux,
@ -11,13 +12,14 @@ from sapl.crud.base import (RP_CHANGE, RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud)
from sapl.materia.models import Proposicao, Relatoria
from sapl.parlamentares.apps import AppConfig
from sapl.utils import get_client_ip
from .forms import (FiliacaoForm, LegislaturaCreateForm, LegislaturaUpdateForm,
ParlamentarCreateForm, ParlamentarForm)
ParlamentarCreateForm, ParlamentarForm, VotanteForm)
from .models import (CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa,
Dependente, Filiacao, Frente, Legislatura, Mandato,
NivelInstrucao, Parlamentar, Partido, SessaoLegislativa,
SituacaoMilitar, TipoAfastamento, TipoDependente)
SituacaoMilitar, TipoAfastamento, TipoDependente, Votante)
CargoMesaCrud = CrudAux.build(CargoMesa, 'cargo_mesa')
PartidoCrud = CrudAux.build(Partido, 'partidos')
@ -34,6 +36,34 @@ DependenteCrud = MasterDetailCrud.build(
Dependente, 'parlamentar', 'dependente')
class VotanteView(MasterDetailCrud):
model = Votante
parent_field = 'parlamentar'
UpdateView = None
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['user']
class CreateView(MasterDetailCrud.CreateView):
form_class = VotanteForm
layout_key = None
class DetailView(MasterDetailCrud.DetailView):
def detail_create_url(self):
return None
class DeleteView(MasterDetailCrud.DeleteView):
def delete(self, *args, **kwargs):
obj = self.get_object()
if obj.user:
obj.user.delete()
return HttpResponseRedirect(
reverse('sapl.parlamentares:votante_list',
kwargs={'pk': obj.parlamentar.pk}))
class FrenteList(MasterDetailCrud):
model = Frente
is_m2m = True

39
sapl/sessao/migrations/0034_votonominal.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-02-13 14:37
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 = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('materia', '0075_auto_20170203_1019'),
('parlamentares', '0039_remove_votante_ip'),
('sessao', '0033_merge'),
]
operations = [
migrations.CreateModel(
name='VotoNominal',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('voto', models.CharField(max_length=10, verbose_name='Voto')),
('ip', models.CharField(max_length=30, verbose_name='IP')),
('data_hora', models.DateTimeField(auto_now_add=True, verbose_name='Data/Hora')),
('expediente', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.ExpedienteMateria')),
('materia', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa')),
('ordem', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sessao.OrdemDia')),
('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Parlamentar')),
('sessao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sessao.SessaoPlenaria')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Registro do Voto do Parlamentar',
'verbose_name_plural': 'Registros dos Votos dos Parlamentares',
},
),
]

23
sapl/sessao/migrations/0035_auto_20170213_1455.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2017-02-13 14:55
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sessao', '0034_votonominal'),
]
operations = [
migrations.RemoveField(
model_name='votonominal',
name='expediente',
),
migrations.RemoveField(
model_name='votonominal',
name='ordem',
),
]

21
sapl/sessao/models.py

@ -1,3 +1,4 @@
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
@ -375,6 +376,26 @@ class VotoParlamentar(models.Model): # RegistroVotacaoParlamentar
'votacao': self.votacao, 'parlamentar': self.parlamentar}
class VotoNominal(models.Model):
parlamentar = models.ForeignKey(Parlamentar)
voto = models.CharField(verbose_name=_('Voto'), max_length=10)
sessao = models.ForeignKey(SessaoPlenaria)
materia = models.ForeignKey(MateriaLegislativa)
user = models.ForeignKey(User)
ip = models.CharField(verbose_name=_('IP'), max_length=30)
data_hora = models.DateTimeField(
verbose_name=_('Data/Hora'), auto_now_add=True)
class Meta:
verbose_name = _('Registro do Voto do Parlamentar')
verbose_name_plural = _('Registros dos Votos dos Parlamentares')
def __str__(self):
return self.Parlamentar, self.voto
class SessaoPlenariaPresenca(models.Model):
sessao_plenaria = models.ForeignKey(SessaoPlenaria)
parlamentar = models.ForeignKey(Parlamentar)

132
sapl/sessao/views.py

@ -3,7 +3,7 @@ from re import sub
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.forms.utils import ErrorList
from django.http import JsonResponse
@ -42,7 +42,8 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
MateriaLegislativa, Orador, OradorExpediente, OrdemDia,
PresencaOrdemDia, RegistroVotacao, SessaoPlenaria,
SessaoPlenariaPresenca, TipoExpediente,
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar)
TipoResultadoVotacao, TipoSessaoPlenaria, VotoNominal,
VotoParlamentar)
TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria')
TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente')
@ -1316,7 +1317,7 @@ class VotacaoNominalView(SessaoPermissionMixin):
'ementa': sub(
'&nbsp;', ' ', strip_tags(ordem.observacao))}
context = {'materia': materia, 'object': self.get_object(),
'parlamentares': self.get_parlamentares(),
'parlamentares': self.get_parlamentares(ordem.materia),
'tipos': self.get_tipos_votacao(),
'total': total}
@ -1331,6 +1332,21 @@ class VotacaoNominalView(SessaoPermissionMixin):
form = VotacaoNominalForm(request.POST)
if 'cancelar-votacao' in request.POST:
sessao = self.object
materia = ordem.materia
presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=expediente.sessao_plenaria_id)
for p in presentes:
try:
voto = VotoNominal.objects.get(
parlamentar=p.parlamentar,
sessao=self.object.pk,
materia=materia)
except ObjectDoesNotExist:
pass
else:
voto.delete()
ordem.votacao_aberta = False
ordem.save()
return self.form_valid(form)
@ -1349,13 +1365,13 @@ class VotacaoNominalView(SessaoPermissionMixin):
voto = v[0]
parlamentar_id = v[1]
if(voto == 'sim'):
if(voto == 'Sim'):
votos_sim += 1
elif(voto == 'nao'):
elif(voto == 'o'):
votos_nao += 1
elif(voto == 'abstencao'):
elif(voto == 'Abstenção'):
abstencoes += 1
elif(voto == 'nao_votou'):
elif(voto == 'Não Votou'):
nao_votou += 1
try:
@ -1384,14 +1400,7 @@ class VotacaoNominalView(SessaoPermissionMixin):
parlamentar_id = v[1]
voto_parlamentar = VotoParlamentar()
if voto == 'sim':
voto_parlamentar.voto = _('Sim')
elif voto == 'nao':
voto_parlamentar.voto = _('Não')
elif voto == 'abstencao':
voto_parlamentar.voto = _('Abstenção')
elif voto == 'nao_votou':
voto_parlamentar.voto = _('Não Votou')
voto_parlamentar.voto = voto
voto_parlamentar.parlamentar_id = parlamentar_id
voto_parlamentar.votacao_id = votacao.id
voto_parlamentar.save()
@ -1409,7 +1418,7 @@ class VotacaoNominalView(SessaoPermissionMixin):
else:
return self.form_invalid(form)
def get_parlamentares(self):
def get_parlamentares(self, materia):
self.object = self.get_object()
presencas = PresencaOrdemDia.objects.filter(
@ -1419,7 +1428,15 @@ class VotacaoNominalView(SessaoPermissionMixin):
for parlamentar in Parlamentar.objects.filter(ativo=True):
if parlamentar in presentes:
yield parlamentar
try:
voto = VotoNominal.objects.get(
parlamentar=parlamentar,
sessao=self.object.pk,
materia=materia)
except ObjectDoesNotExist:
yield [parlamentar, None]
else:
yield [parlamentar, voto.voto]
def get_tipos_votacao(self):
for tipo in TipoResultadoVotacao.objects.all():
@ -1474,6 +1491,21 @@ class VotacaoNominalEditView(SessaoPermissionMixin):
materia_id = kwargs['oid']
ordem_id = kwargs['mid']
sessao = self.object
ordem = ExpedienteMateria.objects.get(id=ordem_id)
presentes = PresencaOrdemDia.objects.filter(
sessao_plenaria_id=ordem.sessao_plenaria_id)
for p in presentes:
try:
voto = VotoNominal.objects.get(
parlamentar=p.parlamentar,
sessao=self.object.pk,
materia=materia_id)
except ObjectDoesNotExist:
pass
else:
voto.delete()
if(int(request.POST['anular_votacao']) == 1):
registro = RegistroVotacao.objects.get(
materia_id=materia_id,
@ -1494,8 +1526,6 @@ class VotacaoNominalEditView(SessaoPermissionMixin):
except:
pass
registro.delete()
return self.form_valid(form)
def get_tipos_votacao(self):
@ -1521,7 +1551,7 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
'ementa': sub(
'&nbsp;', ' ', strip_tags(expediente.observacao))}
context = {'materia': materia, 'object': self.get_object(),
'parlamentares': self.get_parlamentares(),
'parlamentares': self.get_parlamentares(expediente.materia),
'tipos': self.get_tipos_votacao(),
'total': total}
@ -1536,6 +1566,23 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
form = VotacaoNominalForm(request.POST)
if 'cancelar-votacao' in request.POST:
sessao = self.object
expediente_id = kwargs['mid']
expediente = ExpedienteMateria.objects.get(id=expediente_id)
materia = expediente.materia
presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=expediente.sessao_plenaria_id)
for p in presentes:
try:
voto = VotoNominal.objects.get(
parlamentar=p.parlamentar,
sessao=self.object.pk,
materia=materia)
except ObjectDoesNotExist:
pass
else:
voto.delete()
expediente.votacao_aberta = False
expediente.save()
return self.form_valid(form)
@ -1554,13 +1601,13 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
voto = v[0]
parlamentar_id = v[1]
if(voto == 'sim'):
if(voto == 'Sim'):
votos_sim += 1
elif(voto == 'nao'):
elif(voto == 'o'):
votos_nao += 1
elif(voto == 'abstencao'):
elif(voto == 'Abstenção'):
abstencoes += 1
elif(voto == 'nao_votou'):
elif(voto == 'Não Votou'):
nao_votou += 1
try:
@ -1587,14 +1634,7 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
parlamentar_id = v[1]
voto_parlamentar = VotoParlamentar()
if(voto == 'sim'):
voto_parlamentar.voto = _('Sim')
elif(voto == 'nao'):
voto_parlamentar.voto = _('Não')
elif(voto == 'abstencao'):
voto_parlamentar.voto = _('Abstenção')
elif(voto == 'nao_votou'):
voto_parlamentar.voto = _('Não Votou')
voto_parlamentar.voto = voto
voto_parlamentar.parlamentar_id = parlamentar_id
voto_parlamentar.votacao_id = votacao.id
voto_parlamentar.save()
@ -1612,9 +1652,8 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
else:
return self.form_invalid(form)
def get_parlamentares(self):
def get_parlamentares(self, materia):
self.object = self.get_object()
presencas = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=self.object.id
)
@ -1622,7 +1661,15 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin):
for parlamentar in Parlamentar.objects.filter(ativo=True):
if parlamentar in presentes:
yield parlamentar
try:
voto = VotoNominal.objects.get(
parlamentar=parlamentar,
sessao=self.object.pk,
materia=materia)
except ObjectDoesNotExist:
yield [parlamentar, None]
else:
yield [parlamentar, voto.voto]
def get_tipos_votacao(self):
for tipo in TipoResultadoVotacao.objects.all():
@ -1676,6 +1723,21 @@ class VotacaoNominalExpedienteEditView(SessaoPermissionMixin):
materia_id = kwargs['oid']
expediente_id = kwargs['mid']
sessao = self.object
expediente = ExpedienteMateria.objects.get(id=expediente_id)
presentes = SessaoPlenariaPresenca.objects.filter(
sessao_plenaria_id=expediente.sessao_plenaria_id)
for p in presentes:
try:
voto = VotoNominal.objects.get(
parlamentar=p.parlamentar,
sessao=self.object.pk,
materia=materia_id)
except ObjectDoesNotExist:
pass
else:
voto.delete()
if(int(request.POST['anular_votacao']) == 1):
registro = RegistroVotacao.objects.get(
materia_id=materia_id,

3
sapl/templates/crud/detail.html

@ -32,6 +32,9 @@
{% endif %}
{% endblock sub_actions %}
{% block extra_actions %}
{% endblock extra_actions %}
<div class="editons pull-right">
{% block editions %}
{% if view.update_url or view.delete_url %}

85
sapl/templates/painel/voto_nominal.html

@ -0,0 +1,85 @@
{% load i18n %}
{% load staticfiles sass_tags %}
<!DOCTYPE HTML>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="{% sass_src 'bootstrap-sass/assets/stylesheets/_bootstrap.scss' %}" type="text/css">
<title>{% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="{% static 'jquery/dist/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.runner.js' %}"></script>
<style type="text/css">
@media screen {
body {
background: #1c1b1b;
}
ul, li {
list-style-type: none;
}
}
</style>
</head>
{% if permissao and presente %}
<body>
<h1><b><font color="#4FA64D"><p align="center">{{sessao}}</p></font></b></h1>
<table style="width:100%">
<tr>
<th style="text-align:center"><font color="white" size="4">Hora Início: {{hora}}</font></th>
<th style="text-align:center"><font color="white" size="4">Data Início: {{data}}</font></th>
</tr>
</table>
<h1><font color="white"><p align="center"><span id="relogio"></span></p></font></h1>
</br>
</br>
<h2><font color="red"><p align="center" style="font-family:Verdana">Voto: {{voto_parlamentar}}</p></font></h2>
</br>
</br>
<h2><font color="#459170"><p align="center" style="font-family:Verdana">Matéria em Votação</p></font></h2>
<table style="width:75%; border:1px;" align="center">
<tr><th style="text-align:center"><h4><font color="white">{{materia}}</font></th></tr>
<tr><th style="text-align:center"><h4><font color="white">{{ementa}}</font></th></tr>
<tr><th style="text-align:center"><font color="#45919D"><span id="resultado_votacao"></span></font></th></tr>
</table>
<br /><br />
<form method='POST'>
{% csrf_token %}
<table style="width:75%; border:1px;" align="center">
<tr><th style="text-align:center">
<select id="voto" name="voto" style="width:30%;">
<option value="">Selecione</option>
<option value="Sim">Sim</option>
<option value="Não">Não</option>
<option value="Abstenção">Abstenção</option>
</select>
</th></tr>
<tr><th style="text-align:center">
<input type="submit" value="Votar" name="Votar" style="width:10%;"/>
</th></tr>
</table>
</form>
</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 %}
<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>
{% 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 %}
</html>

5
sapl/templates/parlamentares/layouts.yaml

@ -101,3 +101,8 @@ Frente:
- data_criacao data_extincao
- parlamentares
- descricao
Votante:
{% trans 'Votante' %}:
- parlamentar user
- data

2
sapl/templates/parlamentares/subnav.yaml

@ -16,3 +16,5 @@
url: relatoria_parlamentar_list
- title: {% trans 'Frentes' %}
url: frente_parlamentar_list
- title: {% trans 'Usuário' %}
url: votante_list

16
sapl/templates/parlamentares/votante_list.html

@ -0,0 +1,16 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block actions %}
{% if not rows %}
<div class="actions btn-group pull-right btn-group-lg" role="group">
{% if view.create_url %}
<a href="{{ view.create_url }}" class="btn btn-default">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
{% endif %}
{% block more_buttons %}{% endblock more_buttons %}
</div>
{% endif %}
{% endblock actions %}

14
sapl/templates/sessao/sessaoplenaria_detail.html

@ -0,0 +1,14 @@
{% 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 %}

1
sapl/templates/sessao/subnav.yaml

@ -30,5 +30,6 @@
- title: {% trans 'Painel Eletrônico' %}
url: painel
{% if not 'painel_aberto'|get_config_attr %}check_permission: painel.list_painel{%endif%}
- title: {% trans 'Resumo' %}
url: resumo

20
sapl/templates/sessao/votacao/nominal.html

@ -20,16 +20,22 @@
<a href="{% url 'sapl.sessao:sessaoplenaria_detail' object.pk %}" class="btn btn-warning">Voltar</a>
{% else %}
<fieldset class="form-group">
<div class="row">
<div class="col-md-12"><input type="button" value="Atualizar Votos" onClick="window.location.href=window.location.href" class="btn btn-primary sm"></div>
</div>
<br />
<legend>Votos</legend>
<div class="row">
{% for parlamentar in parlamentares %}
<div class="col-md-6">{{parlamentar.nome_parlamentar}}</div>
<div class="col-md-6">{{parlamentar.0.nome_parlamentar}}</div>
<div class="col-md-6">
<select id="voto_parlamentar" name="voto_parlamentar" class="form-control">
<option value="sim:{{parlamentar.id}}">Sim</option>
<option value="nao:{{parlamentar.id}}">Não</option>
<option value="abstencao:{{parlamentar.id}}">Abstenção</option>
<option value="nao_votou:{{parlamentar.id}}">Não Votou</option>
{% if parlamentar.1 %} <input type="hidden" name="voto_parlamentar" value="{{parlamentar.1}}:{{parlamentar.0.id}}" /> {% endif %}
<select id="voto_parlamentar" name="voto_parlamentar" class="form-control" {% if parlamentar.1 %} disabled {% endif %}>
<option value="Não Votou:{{parlamentar.0.id}}">Não Votou</option>
<option value="Sim:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Sim' %} selected {% endif %}>Sim</option>
<option value="Não:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Não' %} selected {% endif %}>Não</option>
<option value="Abstenção:{{parlamentar.0.id}}" {% if parlamentar.1 == 'Abstenção' %} selected {% endif %}>Abstenção</option>
</select>
</div>
{% endfor %}
@ -56,7 +62,7 @@
</div>
<br /><br />
<input type="submit" id="salvar-votacao" name="salvar-votacao" value="Salvar" class="btn btn-primary" />
<input type="submit" id="salvar-votacao" name="salvar-votacao" value="Fechar Votação" class="btn btn-primary" />
<input type="submit" id="cancelar-votacao" name="cancelar-votacao" value="Cancelar Votação" class="btn btn-warning" />
</fieldset>
</form>

Loading…
Cancel
Save