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 %} +