From 22cdcdb90c8570da2abaac873935e579250b68f9 Mon Sep 17 00:00:00 2001 From: Ulysses Lara Date: Thu, 1 Aug 2019 18:24:33 -0300 Subject: [PATCH] 1392 aprimorar estrutura de bloco (#2776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adicionando cargo bloco Criando telas para vincular parlamentar a bloco Adicionando validações Adicionando paginas de editar e deletar vinculo com bloco Adicionando validações e confimação de deletar vinculo com bloco Resolvendo problemas relatados no pr Resolvendo problemas relatados no pr Adiciona migrations Merge de migrations conflitantes Arrumando erro bloco_pk Arrumando erros relatados no pr Melhorando readonly parlamentares * Corrigindo migrations * Corrigindo erro de data atual --- sapl/parlamentares/forms.py | 70 +++++++++++++- .../migrations/0031_auto_20190614_1203.py | 5 +- .../migrations/0033_auto_20190712_1132.py | 36 +++++++ sapl/parlamentares/models.py | 34 +++++++ sapl/parlamentares/urls.py | 18 +++- sapl/parlamentares/views.py | 95 ++++++++++++++++--- sapl/rules/map_rules.py | 2 + sapl/templates/menu_tabelas_auxiliares.yaml | 3 + .../templates/parlamentares/detail_bloco.html | 59 ++++++++++++ sapl/templates/parlamentares/layouts.yaml | 8 +- .../vincula_parlamentar_ao_bloco.html | 37 ++++++++ 11 files changed, 345 insertions(+), 22 deletions(-) create mode 100644 sapl/parlamentares/migrations/0033_auto_20190712_1132.py create mode 100644 sapl/templates/parlamentares/detail_bloco.html create mode 100644 sapl/templates/parlamentares/vincula_parlamentar_ao_bloco.html diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 6f8b47c85..1292bceff 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -15,7 +15,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from floppyforms.widgets import ClearableFileInput from image_cropping.widgets import CropWidget, ImageCropWidget -from sapl.utils import FileFieldCheckMixin +from sapl.utils import FileFieldCheckMixin, filiacao_data, intervalos_tem_intersecao from sapl.base.models import Autor, TipoAutor from sapl.crispy_layout_mixin import form_actions, to_row @@ -23,7 +23,8 @@ from sapl.rules import SAPL_GROUP_VOTANTE import django_filters from .models import (ComposicaoColigacao, Filiacao, Frente, Legislatura, - Mandato, Parlamentar, Votante, Bloco, Bancada) + Mandato, Parlamentar, Votante, Bloco, Bancada, CargoBloco, + CargoBlocoPartido) class ImageThumbnailFileInput(ClearableFileInput): @@ -586,7 +587,6 @@ class VincularParlamentarForm(forms.Form): class BlocoForm(ModelForm): - class Meta: model = Bloco fields = ['nome', 'partidos', 'data_criacao', @@ -671,3 +671,67 @@ class BancadaForm(ModelForm): nome=bancada.nome ) return bancada +class CargoBlocoForm(ModelForm): + class Meta: + model = CargoBloco + fields = '__all__' + +class CargoBlocoPartidoForm(ModelForm): + + class Meta: + model = CargoBlocoPartido + fields = ['cargo','parlamentar','data_inicio','data_fim'] + + + def __init__(self, *args, **kwargs): + super(CargoBlocoPartidoForm, self).__init__(*args, **kwargs) + bloco_pk = self.initial['bloco_pk'] + if bloco_pk: + self.bloco = Bloco.objects.get(pk=bloco_pk) + partidos = self.bloco.partidos.all().values_list('id', flat=True) + parlamentares_filiacao = Filiacao.objects.select_related('partido').filter(partido__in=partidos).values_list('parlamentar', flat=True) + self.fields['parlamentar'].queryset = Parlamentar.objects.filter(id__in=parlamentares_filiacao) + + if self.instance and self.instance.pk: + self.fields['parlamentar'].widget.attrs['disabled'] = 'disabled' + self.fields['parlamentar'].required = False + + + def clean(self): + super(CargoBlocoPartidoForm, self).clean() + cleaned_data = self.cleaned_data + + aux_data_fim = cleaned_data['data_fim'] if cleaned_data['data_fim'] else (cleaned_data['data_inicio'] + timedelta(days=1)) + + if cleaned_data['cargo'].unico: + for vinculo in CargoBlocoPartido.objects.filter(bloco=self.bloco): + if not vinculo.data_fim: + vinculo.data_fim = timezone.now().date() + if intervalos_tem_intersecao(cleaned_data['data_inicio'], + aux_data_fim, + vinculo.data_inicio, + vinculo.data_fim) and vinculo.cargo.unico and \ + not(self.instance and self.instance.id == vinculo.id): + raise ValidationError("Cargo unico já é utilizado nesse período.") + + if aux_data_fim <= cleaned_data['data_inicio']: + raise ValidationError("Data Inicial deve ser anterior a data final.") + + if self.instance and self.instance.pk: + self.cleaned_data['parlamentar'] = self.instance.parlamentar + else: + self.cleaned_data['parlamentar'] = self.cleaned_data.get('parlamentar') + + fora_de_mandato = True + for mandato in Mandato.objects.filter(parlamentar=self.cleaned_data.get('parlamentar')): + if not intervalos_tem_intersecao(mandato.data_inicio_mandato, + cleaned_data['data_inicio'], + aux_data_fim, + mandato.legislatura.data_fim): + fora_de_mandato = False + if fora_de_mandato: + raise ValidationError("Data de inicio e fim fora de periodo do mandato do parlamentar.") + + if self.instance.pk and (cleaned_data['parlamentar'].id != self.instance.parlamentar.id): + raise ValidationError("Não é possivel alterar o parlamentar " + str(self.instance.parlamentar)) + diff --git a/sapl/parlamentares/migrations/0031_auto_20190614_1203.py b/sapl/parlamentares/migrations/0031_auto_20190614_1203.py index 34882b3b0..a35d9e502 100644 --- a/sapl/parlamentares/migrations/0031_auto_20190614_1203.py +++ b/sapl/parlamentares/migrations/0031_auto_20190614_1203.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.20 on 2019-06-14 15:03 +# Generated by Django 1.11.20 on 2019-05-31 14:09 from __future__ import unicode_literals -from django.db import migrations +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): diff --git a/sapl/parlamentares/migrations/0033_auto_20190712_1132.py b/sapl/parlamentares/migrations/0033_auto_20190712_1132.py new file mode 100644 index 000000000..45cfe337d --- /dev/null +++ b/sapl/parlamentares/migrations/0033_auto_20190712_1132.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-07-12 14:32 +from __future__ import unicode_literals +from django.db import migrations, models +import django.db.models.deletion + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0032_auto_20190619_1509'), + ] + + operations = [ + migrations.CreateModel( + name='CargoBloco', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nome', models.CharField(max_length=80, verbose_name='Nome do Cargo')), + ('unico', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Cargo Único')), + ('descricao', models.TextField(blank=True, verbose_name='Descrição')), + ], + options={'ordering': ['nome'], 'verbose_name': 'Cargo de Bloco', 'verbose_name_plural': 'Cargos de Bloco'}, + ), + migrations.CreateModel( + name='CargoBlocoPartido', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('data_inicio', models.DateField(verbose_name='Data Início')), + ('data_fim', models.DateField(blank=True, null=True, verbose_name='Data Fim')), + ('bloco', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Bloco')), + ('cargo', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.CargoBloco')), + ('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Parlamentar')), + ], + options={'ordering': ['data_inicio'], 'verbose_name': 'Vinculo bloco parlamentar', 'verbose_name_plural': 'Vinculos bloco parlamentar'}, + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index e3b5de74d..eeab386ee 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -694,6 +694,18 @@ class Bancada(models.Model): verbose_name_plural = _('Bancadas Parlamentares') ordering = ('-legislatura__numero', ) +class CargoBloco(models.Model): + class Meta: + verbose_name = _('Cargo de Bloco') + verbose_name_plural = _('Cargos de Bloco') + ordering = ['nome'] + + nome = models.CharField( + max_length=80, verbose_name=_('Nome do Cargo')) + unico = models.BooleanField( + choices=YES_NO_CHOICES, verbose_name=_('Cargo Único'), default=True) + descricao = models.TextField(blank=True, verbose_name=_('Descrição')) + def __str__(self): return self.nome @@ -714,3 +726,25 @@ class CargoBancada(models.Model): def __str__(self): return self.nome_cargo + + +class CargoBlocoPartido(models.Model): + class Meta: + verbose_name = _('Vinculo bloco parlamentar') + verbose_name_plural = _('Vinculos bloco parlamentar') + ordering = ['data_inicio'] + + bloco = models.ForeignKey( + Bloco, + on_delete=models.PROTECT) + + cargo = models.ForeignKey( + CargoBloco, + on_delete=models.PROTECT) + + parlamentar = models.ForeignKey( + Parlamentar, + on_delete=models.PROTECT) + + data_inicio = models.DateField(verbose_name=_('Data Início')) + data_fim = models.DateField(blank=True, null=True, verbose_name=_('Data Fim')) diff --git a/sapl/parlamentares/urls.py b/sapl/parlamentares/urls.py index 0c9a89ca6..de0007239 100644 --- a/sapl/parlamentares/urls.py +++ b/sapl/parlamentares/urls.py @@ -21,12 +21,16 @@ from sapl.parlamentares.views import (CargoMesaCrud, ColigacaoCrud, remove_parlamentar_composicao, lista_parlamentares, parlamentares_filiados, - BlocoCrud, - PesquisarParlamentarView, + BlocoCrud, CargoBlocoCrud, + PesquisarParlamentarView, VincularParlamentarView, deleta_historico_partido, + edita_vinculo_parlamentar_bloco, + deleta_vinculo_parlamentar_bloco, + vincula_parlamentar_ao_bloco, get_sessoes_legislatura) + from .apps import AppConfig app_name = AppConfig.name @@ -66,7 +70,15 @@ urlpatterns = [ url(r'^sistema/bloco/', include(BlocoCrud.get_urls())), - + url(r'^sistema/cargo-bloco/', + include(CargoBlocoCrud.get_urls())), + url(r'^sistema/vincula-parlamentar-ao-bloco/(?P\d+)/', + vincula_parlamentar_ao_bloco,name='vincula_parlamentar_ao_bloco'), + url(r'^sistema/edita-vinculo-parlamentar-bloco/(?P\d+)/', + edita_vinculo_parlamentar_bloco,name='edita-vinculo-parlamentar-bloco'), + url(r'^sistema/deleta-vinculo-parlamentar-bloco/(?P\d+)/', + deleta_vinculo_parlamentar_bloco,name='deleta-vinculo-parlamentar-bloco'), + url(r'^sistema/frente/', include(FrenteCrud.get_urls())), url(r'^sistema/frente/atualiza-lista-parlamentares', diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index db2865052..6cd9a572f 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -11,7 +11,7 @@ from django.db.models import F, Q from django.db.models.aggregates import Count from django.http import JsonResponse from django.http.response import HttpResponseRedirect -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404 from django.templatetags.static import static from django.utils import timezone from django.utils.datastructures import MultiValueDictKeyError @@ -33,14 +33,18 @@ from sapl.materia.models import Autoria, Proposicao, Relatoria from sapl.parlamentares.apps import AppConfig from sapl.utils import (parlamentares_ativos, show_results_filter_set) -from .forms import (BancadaForm, FiliacaoForm, FrenteForm, LegislaturaForm, MandatoForm, - ParlamentarCreateForm, ParlamentarForm, VotanteForm, ParlamentarFilterSet, - VincularParlamentarForm, BlocoForm) + +from .forms import (FiliacaoForm, FrenteForm, LegislaturaForm, MandatoForm, + ParlamentarCreateForm, ParlamentarForm, VotanteForm, + ParlamentarFilterSet, VincularParlamentarForm, + BlocoForm, CargoBlocoForm, CargoBlocoPartidoForm, + BancadaForm) + from .models import (Bancada, CargoBancada, CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa, Dependente, Filiacao, Frente, Legislatura, Mandato, NivelInstrucao, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, TipoAfastamento, TipoDependente, Votante, - Bloco, HistoricoPartido) + Bloco, CargoBlocoPartido, HistoricoPartido, CargoBloco) CargoBancadaCrud = CrudAux.build(CargoBancada, '') @@ -1172,6 +1176,17 @@ def altera_field_mesa_public_view(request): 'msg': ('', 1)}) +def deleta_historico_partido(request, pk): + historico = HistoricoPartido.objects.get(pk=pk) + pk_partido = historico.partido.pk + historico.delete() + + return HttpResponseRedirect( + reverse( + 'sapl.parlamentares:partido_detail', + kwargs={'pk': pk_partido})) + + class VincularParlamentarView(PermissionRequiredMixin, FormView): logger = logging.getLogger(__name__) form_class = VincularParlamentarForm @@ -1209,15 +1224,41 @@ class BlocoCrud(CrudAux): return reverse('sapl.parlamentares:bloco_list') -def deleta_historico_partido(request, pk): - historico = HistoricoPartido.objects.get(pk=pk) - pk_partido = historico.partido.pk - historico.delete() - - return HttpResponseRedirect( + class DetailView(CrudAux.DetailView): + def get_template_names(self): + return ['parlamentares/detail_bloco.html'] + + def get_context_data(self, **kwargs): + context = super(BlocoCrud.DetailView, + self).get_context_data(**kwargs) + + context['vinculados'] = CargoBlocoPartido.objects.filter(bloco=self.object) + + return context + + +class CargoBlocoCrud(CrudAux): + model = CargoBloco + + class CreateView(CrudAux.CreateView): + form_class = CargoBlocoForm + +def vincula_parlamentar_ao_bloco(request,pk): + template_name = "parlamentares/vincula_parlamentar_ao_bloco.html" + if request.method == 'POST': + form = CargoBlocoPartidoForm(request.POST,initial={'bloco_pk': pk}) + if form.is_valid(): + vinculo = form.save(commit=False) + vinculo.bloco = Bloco.objects.get(pk=pk) + vinculo.save() + return HttpResponseRedirect( reverse( - 'sapl.parlamentares:partido_detail', - kwargs={'pk': pk_partido})) + 'sapl.parlamentares:bloco_detail', + kwargs={'pk': pk})) + else: + form = CargoBlocoPartidoForm(initial={'bloco_pk': pk}) + + return render(request, template_name, {'form': form,'pk':pk}) def get_sessoes_legislatura(request): @@ -1229,3 +1270,31 @@ def get_sessoes_legislatura(request): json_response['sessoes_legislativas'].append( (s.id, str(s)) ) return JsonResponse(json_response) + + +def edita_vinculo_parlamentar_bloco(request,pk): + template_name = "parlamentares/vincula_parlamentar_ao_bloco.html" + vinculo = get_object_or_404(CargoBlocoPartido, pk=pk) + if request.method == 'POST': + form = CargoBlocoPartidoForm(request.POST,instance=vinculo, initial={'bloco_pk':vinculo.bloco.pk}) + if form.is_valid(): + vinculo = form.save(commit=True) + return HttpResponseRedirect( + reverse( + 'sapl.parlamentares:bloco_detail', + kwargs={'pk': vinculo.bloco.pk})) + else: + form = CargoBlocoPartidoForm(instance=vinculo, initial={'bloco_pk':vinculo.bloco.pk}) + + return render(request, template_name, {'form': form,'pk':vinculo.bloco.pk}) + + +def deleta_vinculo_parlamentar_bloco(request,pk): + vinculo = get_object_or_404(CargoBlocoPartido, pk=pk) + pk_bloco = vinculo.bloco.pk + vinculo.delete() + return HttpResponseRedirect( + reverse( + 'sapl.parlamentares:bloco_detail', + kwargs={'pk': pk_bloco}) + ) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 20da36fe6..eb0be21b8 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -285,6 +285,8 @@ rules_group_geral = { (parlamentares.Bancada, __base__, __perms_publicas__), (parlamentares.CargoBancada, __base__, __perms_publicas__), (parlamentares.Bloco, __base__, __perms_publicas__), + (parlamentares.CargoBloco, __base__, __perms_publicas__), + (parlamentares.CargoBlocoPartido, __base__, __perms_publicas__), (sessao.TipoSessaoPlenaria, __base__, __perms_publicas__), (sessao.TipoResultadoVotacao, __base__, __perms_publicas__), diff --git a/sapl/templates/menu_tabelas_auxiliares.yaml b/sapl/templates/menu_tabelas_auxiliares.yaml index bb0abff74..e423741ee 100644 --- a/sapl/templates/menu_tabelas_auxiliares.yaml +++ b/sapl/templates/menu_tabelas_auxiliares.yaml @@ -80,6 +80,9 @@ - title: {% trans 'Bloco Parlamentar' %} url: sapl.parlamentares:bloco_list css_class: btn btn-link + - title: {% trans 'Cargo de Bloco Parlamentar' %} + url: sapl.parlamentares:cargobloco_list + css_class: btn btn-link - title: {% trans 'Módulo Proposições' %} css_class: head_title children: diff --git a/sapl/templates/parlamentares/detail_bloco.html b/sapl/templates/parlamentares/detail_bloco.html new file mode 100644 index 000000000..ff559ee09 --- /dev/null +++ b/sapl/templates/parlamentares/detail_bloco.html @@ -0,0 +1,59 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags cropping %} +{% block actions %} + {{ block.super }} + +{% endblock actions %} + +{% block table_content %} +{{ block.super }} +

Integrantes

+ + + + + + + + + + + + + {% for vinculo in vinculados%} + + + + + + + + + + + {% endfor %} + +
ParlamentarCargoData de InicioData FinalEditarDeletar
{{vinculo.parlamentar}}{{vinculo.cargo}}{{vinculo.data_inicio}}{% if vinculo.data_fim %}{{vinculo.data_fim}}{% else %}Sem data final{% endif %}EditarDeletar
+ +{% endblock table_content %} diff --git a/sapl/templates/parlamentares/layouts.yaml b/sapl/templates/parlamentares/layouts.yaml index a2a1b3aab..4a717e559 100644 --- a/sapl/templates/parlamentares/layouts.yaml +++ b/sapl/templates/parlamentares/layouts.yaml @@ -144,4 +144,10 @@ Bloco: - nome - data_criacao data_extincao - partidos - - descricao \ No newline at end of file + - descricao + +CargoBloco: + {% trans 'Cargo' %}: + - nome + - unico + - descricao diff --git a/sapl/templates/parlamentares/vincula_parlamentar_ao_bloco.html b/sapl/templates/parlamentares/vincula_parlamentar_ao_bloco.html new file mode 100644 index 000000000..af2604ffd --- /dev/null +++ b/sapl/templates/parlamentares/vincula_parlamentar_ao_bloco.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% load i18n common_tags%} +{% load crispy_forms_tags %} + +{% block base_content %} + +
+{% csrf_token %} +{% for error in form.non_field_errors %} + +{% endfor %} +
+
+
+ {{ form.cargo|as_crispy_field }} +
+
+ {{ form.parlamentar|as_crispy_field }} +
+
+
+
+ {{ form.data_inicio|as_crispy_field }} +
+
+ {{ form.data_fim|as_crispy_field }} +
+
+
+ +Cancelar + + +
+{% endblock base_content %}