From 522769dcdbd7dff05fd80d9196cc2620cb10980f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Cantu=C3=A1ria?= Date: Mon, 21 Dec 2020 13:01:53 -0300 Subject: [PATCH] Adiciona Cargo para Bloco Parlamentar (#3284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adiciona vínculo de Parlamentar com Cargo de Bloco --- sapl/parlamentares/forms.py | 30 ++++++++- .../0033_bloco_blococargo_blocomembro.py | 52 +++++++++++++++ sapl/parlamentares/models.py | 64 +++++++++++++++++-- sapl/parlamentares/urls.py | 9 ++- sapl/parlamentares/views.py | 50 +++++++++++++-- sapl/rules/map_rules.py | 2 + sapl/templates/menu_tabelas_auxiliares.yaml | 3 + .../templates/parlamentares/bloco_detail.html | 9 +++ .../parlamentares/blocomembro_list.html | 9 +++ sapl/templates/parlamentares/layouts.yaml | 18 +++++- 10 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 sapl/parlamentares/migrations/0033_bloco_blococargo_blocomembro.py create mode 100644 sapl/templates/parlamentares/bloco_detail.html create mode 100644 sapl/templates/parlamentares/blocomembro_list.html diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 287c83875..bf7355a88 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -23,7 +23,7 @@ from sapl.rules import SAPL_GROUP_VOTANTE import django_filters from .models import (Coligacao, ComposicaoColigacao, Filiacao, Frente, Legislatura, - Mandato, Parlamentar, Partido, Votante, Bloco, FrenteParlamentar) + Mandato, Parlamentar, Partido, Votante, Bloco, FrenteParlamentar, BlocoMembro) class ImageThumbnailFileInput(ClearableFileInput): @@ -702,4 +702,30 @@ class BlocoForm(ModelForm): tipo=tipo, nome=bloco.nome ) - return bloco \ No newline at end of file + return bloco + + +class BlocoMembroForm(ModelForm): + logger = logging.getLogger(__name__) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['bloco'].widget = forms.HiddenInput() + + class Meta: + model = BlocoMembro + fields = '__all__' + + def clean(self): + cd = super().clean() + if not self.is_valid(): + return self.cleaned_data + + if cd['cargo'].cargo_unico \ + and BlocoMembro.objects.filter(bloco=cd['bloco'], cargo=cd['cargo'], data_saida__isnull=True)\ + .exclude(pk=self.instance.pk).exists(): + raise ValidationError(_("Cargo único já ocupado por outro membro.")) + elif not cd['data_saida'] and BlocoMembro.objects.filter(parlamentar=cd['parlamentar'], data_saida__isnull=True).exists(): + raise ValidationError(_("Parlamentar já é membro do bloco parlamentar.")) + + return cd diff --git a/sapl/parlamentares/migrations/0033_bloco_blococargo_blocomembro.py b/sapl/parlamentares/migrations/0033_bloco_blococargo_blocomembro.py new file mode 100644 index 000000000..ffce3b960 --- /dev/null +++ b/sapl/parlamentares/migrations/0033_bloco_blococargo_blocomembro.py @@ -0,0 +1,52 @@ +# Generated by Django 2.2.13 on 2020-10-05 13:15 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0032_frente_parlamentar'), + ] + + operations = [ + migrations.CreateModel( + name='BlocoCargo', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nome_cargo', models.CharField(max_length=120, verbose_name='Cargo do bloco parlamentar')), + ('cargo_unico', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Cargo único?')), + ], + options={ + 'verbose_name': 'Cargo de Bloco Parlamentar', + 'verbose_name_plural': 'Cargos de Bloco Parlamentar', + 'ordering': ('cargo_unico', 'nome_cargo'), + }, + ), + migrations.AlterModelOptions( + name='bloco', + options={'ordering': ('partidos__nome', 'nome'), 'verbose_name': 'Bloco Parlamentar', 'verbose_name_plural': 'Blocos Parlamentares'}, + ), + migrations.AlterField( + model_name='bloco', + name='nome', + field=models.CharField(max_length=120, verbose_name='Nome do Bloco'), + ), + migrations.CreateModel( + name='BlocoMembro', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('data_entrada', models.DateField(verbose_name='Data Entrada')), + ('data_saida', models.DateField(blank=True, null=True, verbose_name='Data Saída')), + ('bloco', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Bloco', verbose_name='Bloco parlamentar')), + ('cargo', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.BlocoCargo', verbose_name='Cargo na bloco parlamentar')), + ('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Parlamentar', verbose_name='Parlamentar')), + ], + options={ + 'verbose_name': 'Membro de bloco parlamentar', + 'verbose_name_plural': 'Membros de bloco parlamentar', + 'ordering': ('bloco', 'parlamentar', 'cargo'), + }, + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index 7e35168d8..c02c4677a 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -634,14 +634,21 @@ class Bloco(models.Model): * blocos podem existir por mais de uma legislatura ''' nome = models.CharField( - max_length=80, verbose_name=_('Nome do Bloco')) + max_length=120, + verbose_name=_('Nome do Bloco')) partidos = models.ManyToManyField( - Partido, blank=True, verbose_name=_('Partidos')) + Partido, + blank=True, + verbose_name=_('Partidos')) data_criacao = models.DateField( - blank=False, null=True, verbose_name=_('Data Criação')) + blank=False, null=True, + verbose_name=_('Data Criação')) data_extincao = models.DateField( - blank=True, null=True, verbose_name=_('Data Dissolução')) - descricao = models.TextField(blank=True, verbose_name=_('Descrição')) + blank=True, null=True, + verbose_name=_('Data Dissolução')) + descricao = models.TextField( + blank=True, + verbose_name=_('Descrição')) # campo conceitual de reversão genérica para o model Autor que dá a # o meio possível de localização de tipos de autores. @@ -661,3 +668,50 @@ class Bloco(models.Model): def __str__(self): return self.nome + + +@reversion.register() +class BlocoCargo(models.Model): + nome_cargo = models.CharField( + max_length=120, + verbose_name=_('Cargo do bloco parlamentar')) + cargo_unico = models.BooleanField( + default=False, + choices=YES_NO_CHOICES, + verbose_name=_('Cargo único?')) + + class Meta: + verbose_name = _('Cargo de Bloco Parlamentar') + verbose_name_plural = _('Cargos de Bloco Parlamentar') + ordering = ('cargo_unico', 'nome_cargo',) + + def __str__(self): + return f"{self.nome_cargo}" + + +@reversion.register() +class BlocoMembro(models.Model): + bloco = models.ForeignKey( + Bloco, + verbose_name=_('Bloco parlamentar'), + on_delete=models.CASCADE) + parlamentar = models.ForeignKey( + Parlamentar, + verbose_name=_('Parlamentar'), + on_delete=models.CASCADE) + cargo = models.ForeignKey( + BlocoCargo, + verbose_name=_('Cargo na bloco parlamentar'), + on_delete=models.PROTECT) + data_entrada = models.DateField(verbose_name=_('Data Entrada')) + data_saida = models.DateField( + blank=True, null=True, + verbose_name=_('Data Saída')) + + class Meta: + verbose_name = _('Membro de bloco parlamentar') + verbose_name_plural = _('Membros de bloco parlamentar') + ordering = ('bloco', 'parlamentar', 'cargo') + + def __str__(self): + return f"{self.parlamentar} - {self.cargo.nome_cargo} - {self.bloco}" diff --git a/sapl/parlamentares/urls.py b/sapl/parlamentares/urls.py index 016b33c2d..5cf7b40b6 100644 --- a/sapl/parlamentares/urls.py +++ b/sapl/parlamentares/urls.py @@ -22,7 +22,8 @@ from sapl.parlamentares.views import (CargoMesaCrud, ColigacaoCrud, parlamentares_filiados, BlocoCrud, PesquisarParlamentarView, VincularParlamentarView, get_sessoes_legislatura, FrenteCargoCrud, FrenteParlamentarCrud, - get_parlamentar_frentes, PesquisarColigacaoView, PesquisarPartidoView) + get_parlamentar_frentes, PesquisarColigacaoView, PesquisarPartidoView, + BlocoCargoCrud, BlocoMembroCrud) from .apps import AppConfig @@ -55,6 +56,12 @@ urlpatterns = [ url(r'^sistema/bloco/', include(BlocoCrud.get_urls())), + url(r'^sistema/coligacao/', include(ColigacaoCrud.get_urls() + ComposicaoColigacaoCrud.get_urls())), + + url(r'^sistema/bloco/', include(BlocoCrud.get_urls())), + url(r'^sistema/bloco-cargo/', include(BlocoCargoCrud.get_urls())), + url(r'^sistema/bloco-membros/', include(BlocoMembroCrud.get_urls())), + url(r'^sistema/frente/', include(FrenteCrud.get_urls())), url(r'^sistema/frente-cargo/', include(FrenteCargoCrud.get_urls())), url(r'^sistema/frente-parlamentares/', include(FrenteParlamentarCrud.get_urls())), diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index df7dd0fbd..d65f3f395 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -36,24 +36,24 @@ from sapl.utils import (parlamentares_ativos, show_results_filter_set) from .forms import (ColigacaoFilterSet, FiliacaoForm, FrenteForm, LegislaturaForm, MandatoForm, ParlamentarCreateForm, ParlamentarForm, VotanteForm, ParlamentarFilterSet, PartidoFilterSet, VincularParlamentarForm, - BlocoForm, FrenteParlamentarForm) + BlocoForm, FrenteParlamentarForm, BlocoMembroForm) from .models import (CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa, Dependente, Filiacao, Frente, Legislatura, Mandato, NivelInstrucao, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, TipoAfastamento, TipoDependente, Votante, - Bloco, FrenteCargo, FrenteParlamentar) + Bloco, FrenteCargo, FrenteParlamentar, BlocoCargo, BlocoMembro) FrenteCargoCrud = CrudAux.build(FrenteCargo, 'frente_cargo') +BlocoCargoCrud = CrudAux.build(BlocoCargo, 'bloco_cargo') CargoMesaCrud = CrudAux.build(CargoMesa, 'cargo_mesa') TipoDependenteCrud = CrudAux.build(TipoDependente, 'tipo_dependente') NivelInstrucaoCrud = CrudAux.build(NivelInstrucao, 'nivel_instrucao') TipoAfastamentoCrud = CrudAux.build(TipoAfastamento, 'tipo_afastamento') TipoMilitarCrud = CrudAux.build(SituacaoMilitar, 'tipo_situa_militar') -DependenteCrud = MasterDetailCrud.build( - Dependente, 'parlamentar', 'dependente') +DependenteCrud = MasterDetailCrud.build(Dependente, 'parlamentar', 'dependente') class SessaoLegislativaCrud(CrudAux): @@ -1283,6 +1283,48 @@ class BlocoCrud(CrudAux): return reverse('sapl.parlamentares:bloco_list') +class BlocoMembroCrud(MasterDetailCrud): + model = BlocoMembro + parent_field = 'bloco' + help_topic = 'bloco_membros' + public = [RP_LIST, RP_DETAIL] + + class CreateView(MasterDetailCrud.CreateView): + form_class = BlocoMembroForm + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['subnav_template_name'] = '' + return context + + def get_initial(self): + self.initial['bloco'] = Bloco.objects.get(pk=self.kwargs['pk']) + return self.initial + + class UpdateView(MasterDetailCrud.UpdateView): + form_class = BlocoMembroForm + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['subnav_template_name'] = '' + return context + + class DetailView(MasterDetailCrud.DetailView): + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['subnav_template_name'] = '' + return context + + class ListView(MasterDetailCrud.ListView): + layout_key = 'BlocoMembroList' + ordering = ('-cargo__cargo_unico', 'parlamentar') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['subnav_template_name'] = '' + return context + + def get_sessoes_legislatura(request): legislatura_id = request.GET['legislatura'] diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index ad34fe1b1..9cd52c706 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -286,6 +286,8 @@ rules_group_geral = { (parlamentares.FrenteParlamentar, __base__, __perms_publicas__), (parlamentares.Votante, __base__, __perms_publicas__), (parlamentares.Bloco, __base__, __perms_publicas__), + (parlamentares.BlocoCargo, __base__, __perms_publicas__), + (parlamentares.BlocoMembro, __base__, __perms_publicas__), (sessao.CargoBancada, __base__, __perms_publicas__), diff --git a/sapl/templates/menu_tabelas_auxiliares.yaml b/sapl/templates/menu_tabelas_auxiliares.yaml index 9e8f0e454..aecd4ace8 100644 --- a/sapl/templates/menu_tabelas_auxiliares.yaml +++ b/sapl/templates/menu_tabelas_auxiliares.yaml @@ -92,6 +92,9 @@ - title: {% trans 'Bloco Parlamentar' %} url: sapl.parlamentares:bloco_list css_class: btn btn-link + - title: {% trans 'Cargo de Bloco Parlamentar' %} + url: sapl.parlamentares:blococargo_list + css_class: btn btn-link - title: {% trans 'Módulo Proposições' %} css_class: head_title children: diff --git a/sapl/templates/parlamentares/bloco_detail.html b/sapl/templates/parlamentares/bloco_detail.html new file mode 100644 index 000000000..347b1d162 --- /dev/null +++ b/sapl/templates/parlamentares/bloco_detail.html @@ -0,0 +1,9 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% load crispy_forms_tags cropping %} +{% block actions %} + {{ block.super }} +
+ Listar Membros Filiados +
+{% endblock actions %} \ No newline at end of file diff --git a/sapl/templates/parlamentares/blocomembro_list.html b/sapl/templates/parlamentares/blocomembro_list.html new file mode 100644 index 000000000..495886f3e --- /dev/null +++ b/sapl/templates/parlamentares/blocomembro_list.html @@ -0,0 +1,9 @@ +{% extends "crud/list.html" %} +{% load i18n %} +{% load common_tags %} + +{% block more_buttons %} + + Bloco Parlamentar + +{% endblock more_buttons %} \ No newline at end of file diff --git a/sapl/templates/parlamentares/layouts.yaml b/sapl/templates/parlamentares/layouts.yaml index 9d9ee6ce3..0064d8bfd 100644 --- a/sapl/templates/parlamentares/layouts.yaml +++ b/sapl/templates/parlamentares/layouts.yaml @@ -148,4 +148,20 @@ Bloco: - nome - data_criacao data_extincao - partidos - - descricao \ No newline at end of file + - descricao + +BlocoCargo: + {% trans 'Cargo' %}: + - nome_cargo cargo_unico:4 + +BlocoMembro: + {% trans 'Membro'%}: + - bloco + - cargo:4 parlamentar + - data_entrada data_saida + +BlocoMembroList: + {% trans 'Membros'%}: + - id + - cargo:4 parlamentar + - data_entrada data_saida