From 5cbaae11c94d9e0f728018f975ebd66853bfcbd7 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Thu, 9 Feb 2017 16:39:06 -0200 Subject: [PATCH 01/13] CInit view e form --- sapl/parlamentares/forms.py | 91 ++++++++++++++++++- sapl/parlamentares/migrations/0037_votante.py | 31 +++++++ sapl/parlamentares/models.py | 19 ++++ sapl/parlamentares/urls.py | 5 +- sapl/parlamentares/views.py | 28 +++++- sapl/templates/parlamentares/layouts.yaml | 6 ++ sapl/templates/parlamentares/subnav.yaml | 2 + .../templates/parlamentares/votante_list.html | 16 ++++ 8 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 sapl/parlamentares/migrations/0037_votante.py create mode 100644 sapl/templates/parlamentares/votante_list.html diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 975ed7621..bd9846a5e 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -1,6 +1,9 @@ from datetime import date, timedelta +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 +11,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 +236,87 @@ 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', 'ip', + 'email', 'email_confirma'] + widgets = {'ip': forms.HiddenInput()} + + 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) + + u = User.objects.get(username=self.cleaned_data['username']) + u = User.objects.create( + username=self.cleaned_data['username'], + email=self.cleaned_data['email']) + + u.set_password(self.cleaned_data['senha']) + u.save() + + votante.user = u + votante.save() + return votante diff --git a/sapl/parlamentares/migrations/0037_votante.py b/sapl/parlamentares/migrations/0037_votante.py new file mode 100644 index 000000000..fca67dec4 --- /dev/null +++ b/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', + }, + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 34b46673c..a4c9de42b 100644 --- a/sapl/parlamentares/models.py +++ b/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,21 @@ 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) + ip = models.CharField( + verbose_name=_('IP'), max_length=30, null=True, blank=True) + + class Meta: + verbose_name = _('Votante') + verbose_name = _('Votantes') + + def __str__(self): + return self.user.username diff --git a/sapl/parlamentares/urls.py b/sapl/parlamentares/urls.py index a977992f8..1d9885053 100644 --- a/sapl/parlamentares/urls.py +++ b/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/', diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 688f067bc..874e1b23d 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -11,13 +11,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 +35,29 @@ 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 + + def get_initial(self): + initial_data = {} + initial_data['ip'] = get_client_ip(self.request) + return initial_data + + class DetailView(MasterDetailCrud.DetailView): + + def detail_create_url(self): + return None + + class FrenteList(MasterDetailCrud): model = Frente is_m2m = True diff --git a/sapl/templates/parlamentares/layouts.yaml b/sapl/templates/parlamentares/layouts.yaml index 4153aad29..385c0caf6 100644 --- a/sapl/templates/parlamentares/layouts.yaml +++ b/sapl/templates/parlamentares/layouts.yaml @@ -101,3 +101,9 @@ Frente: - data_criacao data_extincao - parlamentares - descricao + +Votante: + {% trans 'Votante' %}: + - parlamentar user + - data ip + diff --git a/sapl/templates/parlamentares/subnav.yaml b/sapl/templates/parlamentares/subnav.yaml index 6979811f9..6caf6d899 100644 --- a/sapl/templates/parlamentares/subnav.yaml +++ b/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 diff --git a/sapl/templates/parlamentares/votante_list.html b/sapl/templates/parlamentares/votante_list.html new file mode 100644 index 000000000..8c9847846 --- /dev/null +++ b/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 %} +
+ {% if view.create_url %} + + {% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %} + + {% endif %} + {% block more_buttons %}{% endblock more_buttons %} +
+ {% endif %} +{% endblock actions %} From de67f6c8aa879d5d3f64fa31d69ef482c676158a Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 10 Feb 2017 09:20:04 -0200 Subject: [PATCH 02/13] Delete user --- sapl/parlamentares/forms.py | 1 - sapl/parlamentares/views.py | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index bd9846a5e..210f2a7b8 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -309,7 +309,6 @@ class VotanteForm(ModelForm): def save(self, commit=False): votante = super(VotanteForm, self).save(commit) - u = User.objects.get(username=self.cleaned_data['username']) u = User.objects.create( username=self.cleaned_data['username'], email=self.cleaned_data['email']) diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 874e1b23d..366a08715 100644 --- a/sapl/parlamentares/views.py +++ b/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, @@ -57,6 +58,16 @@ class VotanteView(MasterDetailCrud): 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 From f3034baad879fc13f8c5c77a4ecaca19056044c8 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 10 Feb 2017 10:37:24 -0200 Subject: [PATCH 03/13] =?UTF-8?q?Cria=20grupo=20e=20permiss=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/parlamentares/apps.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sapl/parlamentares/apps.py b/sapl/parlamentares/apps.py index 41f6d0b38..dd523cd49 100644 --- a/sapl/parlamentares/apps.py +++ b/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) From 81c9ac90a6442a3140b0d8fe66d6d1b6f055c162 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 10 Feb 2017 10:45:59 -0200 Subject: [PATCH 04/13] Adiciona grupo ao usuario parlamentar --- sapl/parlamentares/forms.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 210f2a7b8..73e4f90a4 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -1,4 +1,5 @@ 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 @@ -309,13 +310,17 @@ class VotanteForm(ModelForm): 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 From 2808d7d2508adbf363926747c78dd87e24150e70 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 10 Feb 2017 11:44:41 -0200 Subject: [PATCH 05/13] =?UTF-8?q?Init=20view/template=20vota=C3=A7=C3=A3o?= =?UTF-8?q?=20nominal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/painel/urls.py | 5 ++- sapl/painel/views.py | 52 ++++++++++++++++++++++++- sapl/parlamentares/models.py | 4 +- sapl/sessao/models.py | 2 +- sapl/templates/painel/voto_nominal.html | 5 +++ 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 sapl/templates/painel/voto_nominal.html diff --git a/sapl/painel/urls.py b/sapl/painel/urls.py index d6a07112f..b617d8fec 100644 --- a/sapl/painel/urls.py +++ b/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\d+)$', votante_view, + name="voto_individual"), ] diff --git a/sapl/painel/views.py b/sapl/painel/views.py index d285137a0..2c2946621 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -9,7 +9,7 @@ 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) @@ -25,6 +25,56 @@ 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} + + # 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) + + if ordem_dia: + if ordem_dia.tipo_votacao == 2: + context.update({'materia': ordem_dia}) + presentes = PresencaOrdemDia.objects.filter(sessao_plenaria_id=pk) + elif expediente: + if expediente.tipo_votacao == 2: + context.update({'materia': expediente}) + presentes = SessaoPlenariaPresenca.objects.filter( + sessao_plenaria_id=pk) + 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: + context.update({'presente': True}) + break + + # FIXME: Verificar se usuário já votou + + return render(request, 'painel/voto_nominal.html', context) + + @user_passes_test(check_permission) def controlador_painel(request): diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index a4c9de42b..253bc94ca 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -509,8 +509,8 @@ class Votante(models.Model): verbose_name=_('IP'), max_length=30, null=True, blank=True) class Meta: - verbose_name = _('Votante') - verbose_name = _('Votantes') + verbose_name = _('Usuário') + verbose_name = _('Usuários') def __str__(self): return self.user.username diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index eb439b69c..af22e1d1d 100644 --- a/sapl/sessao/models.py +++ b/sapl/sessao/models.py @@ -160,7 +160,7 @@ class SessaoPlenaria(models.Model): if self.upload_ata: self.upload_ata.delete() - + if self.upload_anexo: self.upload_anexo.delete() diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html new file mode 100644 index 000000000..5aff93b87 --- /dev/null +++ b/sapl/templates/painel/voto_nominal.html @@ -0,0 +1,5 @@ +head_title = {{head_title}}
+sessao_id = {{sessao_id}}
+materia = {{materia}}
+permissao = {{permissao}}
+presente = {{presente}}
From ede6b907185868af628b236fd199936566fe1bb3 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 10 Feb 2017 11:53:30 -0200 Subject: [PATCH 06/13] =?UTF-8?q?Aviso=20caso=20a=20vota=C3=A7=C3=A3o=20es?= =?UTF-8?q?teja=20aberta,=20mas=20n=C3=A3o=20seja=20nominal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/painel/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 2c2946621..788103e6a 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -40,11 +40,17 @@ def votante_view(request, pk): if ordem_dia.tipo_votacao == 2: context.update({'materia': ordem_dia}) presentes = PresencaOrdemDia.objects.filter(sessao_plenaria_id=pk) + else: + context.update( + {'materia': 'A matéria aberta não é votação nominal.'}) elif expediente: if expediente.tipo_votacao == 2: context.update({'materia': expediente}) 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.'}) From 1aaba1dc4223c2ad72e60fdb9ec904f789b2cb57 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 13 Feb 2017 15:19:46 -0200 Subject: [PATCH 07/13] =?UTF-8?q?cria=20model=20pra=20vota=C3=A7=C3=A3o,?= =?UTF-8?q?=20layout,=20recupera=20dados=20do=20parlamentar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/norma/forms.py | 2 + sapl/painel/views.py | 46 ++++++++++-- sapl/parlamentares/forms.py | 5 +- .../migrations/0038_auto_20170213_1425.py | 19 +++++ .../migrations/0039_remove_votante_ip.py | 19 +++++ sapl/parlamentares/models.py | 3 +- sapl/parlamentares/views.py | 5 -- sapl/sessao/migrations/0034_votonominal.py | 39 ++++++++++ .../migrations/0035_auto_20170213_1455.py | 23 ++++++ sapl/sessao/models.py | 21 ++++++ sapl/templates/painel/voto_nominal.html | 71 +++++++++++++++++-- sapl/templates/parlamentares/layouts.yaml | 3 +- 12 files changed, 235 insertions(+), 21 deletions(-) create mode 100644 sapl/parlamentares/migrations/0038_auto_20170213_1425.py create mode 100644 sapl/parlamentares/migrations/0039_remove_votante_ip.py create mode 100644 sapl/sessao/migrations/0034_votonominal.py create mode 100644 sapl/sessao/migrations/0035_auto_20170213_1455.py diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 8e60ed8cc..6fc6ca521 100644 --- a/sapl/norma/forms.py +++ b/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'), diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 788103e6a..cbdc94335 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -1,4 +1,5 @@ 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 @@ -12,7 +13,8 @@ from sapl.painel.models import Painel 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 @@ -28,6 +30,12 @@ def check_permission(user): 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 = [] @@ -35,17 +43,20 @@ def votante_view(request, pk): # 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': ordem_dia}) + 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': expediente}) + context.update({'materia': materia, 'ementa': materia.ementa}) presentes = SessaoPlenariaPresenca.objects.filter( sessao_plenaria_id=pk) else: @@ -76,7 +87,34 @@ def votante_view(request, pk): context.update({'presente': True}) break - # FIXME: Verificar se usuário já votou + 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}) + + 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 render(request, 'painel/voto_nominal.html', context) diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 73e4f90a4..a5f23697b 100644 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -267,9 +267,8 @@ class VotanteForm(ModelForm): class Meta: model = Votante - fields = ['username', 'senha', 'senha_confirma', 'ip', - 'email', 'email_confirma'] - widgets = {'ip': forms.HiddenInput()} + fields = ['username', 'senha', 'senha_confirma', 'email', + 'email_confirma'] def __init__(self, *args, **kwargs): row1 = to_row([('username', 4), ('senha', 4), ('senha_confirma', 4)]) diff --git a/sapl/parlamentares/migrations/0038_auto_20170213_1425.py b/sapl/parlamentares/migrations/0038_auto_20170213_1425.py new file mode 100644 index 000000000..7134cef57 --- /dev/null +++ b/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'}, + ), + ] diff --git a/sapl/parlamentares/migrations/0039_remove_votante_ip.py b/sapl/parlamentares/migrations/0039_remove_votante_ip.py new file mode 100644 index 000000000..9ae65babd --- /dev/null +++ b/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', + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 253bc94ca..4fbecaab7 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -505,8 +505,7 @@ class Votante(models.Model): data = models.DateTimeField( verbose_name=_('Data'), auto_now_add=True, max_length=30, null=True, blank=True) - ip = models.CharField( - verbose_name=_('IP'), max_length=30, null=True, blank=True) + class Meta: verbose_name = _('Usuário') diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 366a08715..7d0d47306 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -48,11 +48,6 @@ class VotanteView(MasterDetailCrud): form_class = VotanteForm layout_key = None - def get_initial(self): - initial_data = {} - initial_data['ip'] = get_client_ip(self.request) - return initial_data - class DetailView(MasterDetailCrud.DetailView): def detail_create_url(self): diff --git a/sapl/sessao/migrations/0034_votonominal.py b/sapl/sessao/migrations/0034_votonominal.py new file mode 100644 index 000000000..37ab664c7 --- /dev/null +++ b/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', + }, + ), + ] diff --git a/sapl/sessao/migrations/0035_auto_20170213_1455.py b/sapl/sessao/migrations/0035_auto_20170213_1455.py new file mode 100644 index 000000000..391c293b0 --- /dev/null +++ b/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', + ), + ] diff --git a/sapl/sessao/models.py b/sapl/sessao/models.py index af22e1d1d..07cfc3791 100644 --- a/sapl/sessao/models.py +++ b/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) diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html index 5aff93b87..a4c5876e2 100644 --- a/sapl/templates/painel/voto_nominal.html +++ b/sapl/templates/painel/voto_nominal.html @@ -1,5 +1,66 @@ -head_title = {{head_title}}
-sessao_id = {{sessao_id}}
-materia = {{materia}}
-permissao = {{permissao}}
-presente = {{presente}}
+{% load i18n %} +{% load staticfiles sass_tags %} + + + + + + {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %} + + + + + + + + +

{{sessao}}

+ + + + + +
Data Início: {{hora}}Hora Início: {{data}}
+

+ +
+
+

Voto: {{voto_parlamentar}}

+
+
+ +

Matéria em Votação

+ + + + +

{{materia}}

{{ementa}}

+ +

+
+ {% csrf_token %} + + + +
+ +
+ +
+
+ + diff --git a/sapl/templates/parlamentares/layouts.yaml b/sapl/templates/parlamentares/layouts.yaml index 385c0caf6..7105ce9d3 100644 --- a/sapl/templates/parlamentares/layouts.yaml +++ b/sapl/templates/parlamentares/layouts.yaml @@ -105,5 +105,4 @@ Frente: Votante: {% trans 'Votante' %}: - parlamentar user - - data ip - + - data From 57a4f20446579e359f775eb613fd004913d48880 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 13 Feb 2017 15:29:24 -0200 Subject: [PATCH 08/13] =?UTF-8?q?Redirect=20ap=C3=B3s=20post?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/painel/views.py | 4 ++++ sapl/templates/painel/voto_nominal.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index cbdc94335..30f2d6518 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -1,3 +1,5 @@ +from django.http.response import HttpResponseRedirect +from django.core.urlresolvers import reverse from datetime import date from sapl.utils import get_client_ip @@ -115,6 +117,8 @@ def votante_view(request, pk): 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) diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html index a4c5876e2..b6082d274 100644 --- a/sapl/templates/painel/voto_nominal.html +++ b/sapl/templates/painel/voto_nominal.html @@ -54,7 +54,7 @@ - + From ce651f3e610d0ff5bad7393f830e3a053b71ec38 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 13 Feb 2017 15:40:10 -0200 Subject: [PATCH 09/13] =?UTF-8?q?IF's=20para=20validar=20permiss=C3=A3o=20?= =?UTF-8?q?e=20presen=C3=A7a=20no=20template=20de=20vota=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/painel/views.py | 1 + sapl/templates/painel/voto_nominal.html | 83 ++++++++++++++----------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 30f2d6518..8e871455c 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -89,6 +89,7 @@ def votante_view(request, pk): context.update({'presente': True}) break + # Recupera o voto do parlamentar logado try: voto = VotoNominal.objects.get( sessao=sessao, diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html index b6082d274..37c01a4f0 100644 --- a/sapl/templates/painel/voto_nominal.html +++ b/sapl/templates/painel/voto_nominal.html @@ -21,46 +21,53 @@ } + {% if permissao and presenca %} + +

{{sessao}}

+ + + + + +
Hora Início: {{hora}}Data Início: {{data}}
+

- -

{{sessao}}

- - - - - -
Data Início: {{hora}}Hora Início: {{data}}
-

- -
-
-

Voto: {{voto_parlamentar}}

-
-
- -

Matéria em Votação

- - - - -

{{materia}}

{{ementa}}

+
+
+

Voto: {{voto_parlamentar}}

+
+
-

-
- {% csrf_token %} +

Matéria em Votação

- - + + +
- -
- -

{{materia}}

{{ementa}}

-
- + +

+
+ {% csrf_token %} + + + +
+ +
+ +
+
+ + {% elif not permissao %} +

Usuário sem permissão para participar de votações.

+ {% elif not presenca %} +

Usuário não presente na Sessão Plenária.

+ {% else %} +

Usuário não presente na Sessão Plenária e sem permissão para votações.

+ {% endif %} From a62dedefce3f06b0b04c5691f75882931204327e Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 13 Feb 2017 15:50:18 -0200 Subject: [PATCH 10/13] Fix nome da variavel --- sapl/painel/views.py | 3 ++- sapl/templates/painel/voto_nominal.html | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 8e871455c..123b1c63e 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -85,7 +85,7 @@ def votante_view(request, pk): context.update({'presente': False}) if len(presentes) > 0: for p in presentes: - if p.parlamentar.id == parlamentar: + if p.parlamentar.id == parlamentar.id: context.update({'presente': True}) break @@ -100,6 +100,7 @@ def votante_view(request, pk): else: context.update({'voto_parlamentar': voto.voto}) + # Salva o voto if request.method == 'POST': try: voto = VotoNominal.objects.get( diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html index 37c01a4f0..56cd6e611 100644 --- a/sapl/templates/painel/voto_nominal.html +++ b/sapl/templates/painel/voto_nominal.html @@ -21,7 +21,7 @@ } - {% if permissao and presenca %} + {% if permissao and presente %}

{{sessao}}

@@ -65,7 +65,7 @@ {% elif not permissao %}

Usuário sem permissão para participar de votações.

- {% elif not presenca %} + {% elif not presente %}

Usuário não presente na Sessão Plenária.

{% else %}

Usuário não presente na Sessão Plenária e sem permissão para votações.

From 72392890032c74f64af379285821254228b5586e Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Tue, 14 Feb 2017 15:45:28 -0200 Subject: [PATCH 11/13] =?UTF-8?q?Vota=C3=A7=C3=A3o=20expediente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/sessao/views.py | 79 ++++++++++++++-------- sapl/templates/painel/index.html | 2 +- sapl/templates/sessao/votacao/nominal.html | 26 ++++--- 3 files changed, 69 insertions(+), 38 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 2e63bc286..b88ad5f1c 100644 --- a/sapl/sessao/views.py +++ b/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') @@ -1486,15 +1487,7 @@ class VotacaoNominalEditView(SessaoPermissionMixin): ordem.votacao_aberta = False ordem.save() - try: - votacao = VotoParlamentar.objects.filter( - votacao_id=registro.id) - for v in votacao: - v.delete() - except: - pass - - registro.delete() + trySessaoPe() return self.form_valid(form) @@ -1521,7 +1514,7 @@ class VotacaoNominalExpedienteView(SessaoPermissionMixin): 'ementa': sub( ' ', ' ', 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 +1529,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 +1564,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 == 'Nã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 +1597,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 +1615,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 +1624,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 +1686,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, diff --git a/sapl/templates/painel/index.html b/sapl/templates/painel/index.html index a68f3b8b9..a91179cfc 100644 --- a/sapl/templates/painel/index.html +++ b/sapl/templates/painel/index.html @@ -279,4 +279,4 @@ })(); }); - \ No newline at end of file + diff --git a/sapl/templates/sessao/votacao/nominal.html b/sapl/templates/sessao/votacao/nominal.html index 9bc54a73a..576608e9c 100644 --- a/sapl/templates/sessao/votacao/nominal.html +++ b/sapl/templates/sessao/votacao/nominal.html @@ -20,18 +20,24 @@ Voltar {% else %}
+
+
+
+
+ Votos
{% for parlamentar in parlamentares %} -
{{parlamentar.nome_parlamentar}}
-
- -
+
{{parlamentar.0.nome_parlamentar}}
+
+ {% if parlamentar.1 %} {% endif %} + +
{% endfor %}
@@ -56,7 +62,7 @@

- + From 52878ee090c96dd2b5559eaf1761f259e4c40b60 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Tue, 14 Feb 2017 15:50:26 -0200 Subject: [PATCH 12/13] =?UTF-8?q?Vota=C3=A7=C3=A3o=20ordem=20dia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/sessao/views.py | 61 +++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b88ad5f1c..8a7bdd353 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1317,7 +1317,7 @@ class VotacaoNominalView(SessaoPermissionMixin): 'ementa': sub( ' ', ' ', 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} @@ -1332,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) @@ -1350,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 == 'Nã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: @@ -1385,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() @@ -1410,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( @@ -1420,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(): @@ -1475,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, From c5ef699b1302be4cf8d8c39b396a58fc6a833d88 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Tue, 14 Feb 2017 16:15:46 -0200 Subject: [PATCH 13/13] =?UTF-8?q?Adiciona=20bot=C3=A3o=20para=20votar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/painel/views.py | 3 +++ sapl/parlamentares/models.py | 3 +-- sapl/sessao/views.py | 8 +++++++- sapl/templates/crud/detail.html | 3 +++ sapl/templates/painel/voto_nominal.html | 18 +++++++++++++++--- .../sessao/sessaoplenaria_detail.html | 14 ++++++++++++++ sapl/templates/sessao/subnav.yaml | 1 + 7 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 sapl/templates/sessao/sessaoplenaria_detail.html diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 123b1c63e..854197b16 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -88,6 +88,9 @@ def votante_view(request, pk): 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: diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 4fbecaab7..a03d63c24 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -506,10 +506,9 @@ class Votante(models.Model): verbose_name=_('Data'), auto_now_add=True, max_length=30, null=True, blank=True) - class Meta: verbose_name = _('Usuário') - verbose_name = _('Usuários') + verbose_name_plural = _('Usuários') def __str__(self): return self.user.username diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 8a7bdd353..132b43fda 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -1518,7 +1518,13 @@ class VotacaoNominalEditView(SessaoPermissionMixin): ordem.votacao_aberta = False ordem.save() - trySessaoPe() + try: + votacao = VotoParlamentar.objects.filter( + votacao_id=registro.id) + for v in votacao: + v.delete() + except: + pass return self.form_valid(form) diff --git a/sapl/templates/crud/detail.html b/sapl/templates/crud/detail.html index f425ed791..89d8862aa 100644 --- a/sapl/templates/crud/detail.html +++ b/sapl/templates/crud/detail.html @@ -32,6 +32,9 @@ {% endif %} {% endblock sub_actions %} + {% block extra_actions %} + {% endblock extra_actions %} +
{% block editions %} {% if view.update_url or view.delete_url %} diff --git a/sapl/templates/painel/voto_nominal.html b/sapl/templates/painel/voto_nominal.html index 56cd6e611..faa2e87b7 100644 --- a/sapl/templates/painel/voto_nominal.html +++ b/sapl/templates/painel/voto_nominal.html @@ -64,10 +64,22 @@ {% elif not permissao %} -

Usuário sem permissão para participar de votações.

+ {% if error_message %} +

{{error_message}}

+ {% else %} +

Usuário sem permissão para participar de votações.

+ {% endif %} {% elif not presente %} -

Usuário não presente na Sessão Plenária.

+ {% if error_message %} +

{{error_message}}

+ {% else %} +

Usuário não presente na Sessão Plenária.

+ {% endif %} {% else %} -

Usuário não presente na Sessão Plenária e sem permissão para votações.

+ {% if error_message %} +

{{error_message}}

+ {% else %} +

Usuário não presente na Sessão Plenária e sem permissão para votações.

+ {% endif %} {% endif %} diff --git a/sapl/templates/sessao/sessaoplenaria_detail.html b/sapl/templates/sessao/sessaoplenaria_detail.html new file mode 100644 index 000000000..bd6c66ab4 --- /dev/null +++ b/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 %} + +{% endif %} +{% endblock extra_actions %} diff --git a/sapl/templates/sessao/subnav.yaml b/sapl/templates/sessao/subnav.yaml index ac08302f4..f45d7e71d 100644 --- a/sapl/templates/sessao/subnav.yaml +++ b/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