diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 267bb15cb..c52bfba2d 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -24,7 +24,7 @@ import django_filters from .models import (ComposicaoColigacao, Filiacao, Frente, Legislatura, Mandato, Parlamentar, Votante, Bloco, Bancada, CargoBloco, - CargoBlocoPartido) + CargoBlocoPartido, AfastamentoParlamentar, TipoAfastamento) class ImageThumbnailFileInput(ClearableFileInput): @@ -87,6 +87,12 @@ class MandatoForm(ModelForm): 'tipo_afastamento', 'observacao', 'parlamentar'] widgets = {'parlamentar': forms.HiddenInput()} + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.fields['tipo_afastamento'].queryset = TipoAfastamento.objects.filter(indicador='F') + + def clean(self): super(MandatoForm, self).clean() @@ -673,6 +679,8 @@ class BancadaForm(ModelForm): nome=bancada.nome ) return bancada + + class CargoBlocoForm(ModelForm): class Meta: model = CargoBloco @@ -736,4 +744,79 @@ class CargoBlocoPartidoForm(ModelForm): 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)) + + +class AfastamentoParlamentarForm(ModelForm): + logger = logging.getLogger(__name__) + + class Meta: + model = AfastamentoParlamentar + fields = ['data_inicio', 'data_fim', 'mandato', + 'tipo_afastamento', 'observacao', 'parlamentar'] + widgets = {'parlamentar': forms.HiddenInput()} + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not (self.instance and self.instance.pk): + parlamentar = kwargs['initial']['parlamentar'] + self.fields['mandato'].queryset = Mandato.objects.filter(parlamentar=parlamentar) + + self.fields['tipo_afastamento'].queryset = TipoAfastamento.objects.filter(indicador='A') + + def clean(self): + super(AfastamentoParlamentarForm, self).clean() + + if not self.is_valid(): + return self.cleaned_data + + data = self.cleaned_data + + mandato = data['mandato'] + + data_inicio_mandato = mandato.data_inicio_mandato + data_fim_mandato = mandato.data_fim_mandato + data_inicio_afastamento = data['data_inicio'] + data_fim_afastamento = data['data_fim'] + + if data_inicio_afastamento < data_inicio_mandato: + self.logger.error("Data início de afastamento ({}) anterior ao inicio" + " do mandato informado ({})." + .format(data_inicio_afastamento, data_inicio_mandato)) + raise ValidationError(_("Data início do afastamento anterior ao início" + " do mandato informado.")) + + if data_fim_mandato and data_inicio_afastamento > data_fim_mandato: + self.logger.error("Data início de afastamento ({}) posterior ao fim" + " do mandato informado ({} a {})." + .format(data_inicio_afastamento, data_fim_mandato)) + raise ValidationError(_("Data início do afastamento posterior ao fim" + " do mandato informado.")) + + if data_fim_afastamento: + if data_fim_afastamento < data_inicio_afastamento: + self.logger.error("Data fim de afastamento ({}) menor que data início" + " do afastamento ({})." + .format(data_fim_afastamento, data_inicio_afastamento)) + raise ValidationError(_("Data fim do afastamento menor que data início do" + " afastamento.")) + + if data_fim_afastamento < data_inicio_mandato: + self.logger.error("Data fim de afastamento ({}) anterior ao início" + " do mandato informado ({} a {})." + .format(data_fim_afastamento, data_inicio_mandato)) + raise ValidationError(_("Data fim do afastamento anterior ao início" + " do mandato informado.")) + + if data_fim_mandato and data_fim_afastamento > data_fim_mandato: + self.logger.error("Data fim de afastamento ({}) posterior ao fim" + " do mandato informado ({} a {})." + .format(data_inicio_afastamento, data_fim_mandato)) + raise ValidationError(_("Data fim do afastamento posterior ao fim" + " do mandato informado.")) + + if AfastamentoParlamentar.objects.last() and not AfastamentoParlamentar.objects.last().data_fim: + self.logger.error("Existe Afastamento sem Data Fim.") + raise ValidationError(_("Existe Afastamento sem Data Fim.")) + + return self.cleaned_data diff --git a/sapl/parlamentares/migrations/0033_afastamentoparlamentar.py b/sapl/parlamentares/migrations/0033_afastamentoparlamentar.py new file mode 100644 index 000000000..212d1803b --- /dev/null +++ b/sapl/parlamentares/migrations/0033_afastamentoparlamentar.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-08-01 15:35 +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='AfastamentoParlamentar', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('data_inicio', models.DateField(null=True, verbose_name='Início do Afastamento')), + ('data_fim', models.DateField(blank=True, null=True, verbose_name='Fim do Afastamento')), + ('observacao', models.TextField(blank=True, verbose_name='Observação')), + ('mandato', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Mandato', verbose_name='Mandato')), + ('parlamentar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Parlamentar')), + ('tipo_afastamento', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parlamentares.TipoAfastamento', verbose_name='Tipo de Afastamento')), + ], + options={ + 'verbose_name': 'Afastamento', + 'verbose_name_plural': 'Afastamentos', + }, + ), + ] diff --git a/sapl/parlamentares/models.py b/sapl/parlamentares/models.py index eeab386ee..d97995044 100644 --- a/sapl/parlamentares/models.py +++ b/sapl/parlamentares/models.py @@ -727,7 +727,6 @@ class CargoBancada(models.Model): def __str__(self): return self.nome_cargo - class CargoBlocoPartido(models.Model): class Meta: verbose_name = _('Vinculo bloco parlamentar') @@ -748,3 +747,32 @@ class CargoBlocoPartido(models.Model): data_inicio = models.DateField(verbose_name=_('Data Início')) data_fim = models.DateField(blank=True, null=True, verbose_name=_('Data Fim')) + + +@reversion.register() +class AfastamentoParlamentar(models.Model): + parlamentar = models.ForeignKey(Parlamentar, on_delete=models.CASCADE) + mandato = models.ForeignKey(Mandato, on_delete=models.CASCADE, + verbose_name=_('Mandato')) + tipo_afastamento = models.ForeignKey(TipoAfastamento, + on_delete=models.PROTECT, + verbose_name=_('Tipo de Afastamento'), + blank=True, + null=True) + data_inicio = models.DateField(verbose_name=_('Início do Afastamento'), + blank=False, + null=True) + data_fim = models.DateField(verbose_name=_('Fim do Afastamento'), + blank=True, + null=True) + observacao = models.TextField(verbose_name=_('Observação'), + blank=True) + + class Meta: + verbose_name = _('Afastamento') + verbose_name_plural = _('Afastamentos') + + def __str__(self): + return _('%(parlamentar)s %(legislatura)s') % { + 'parlamentar': self.parlamentar, 'legislatura': self.mandato.legislatura + } diff --git a/sapl/parlamentares/urls.py b/sapl/parlamentares/urls.py index de0007239..b062ab54b 100644 --- a/sapl/parlamentares/urls.py +++ b/sapl/parlamentares/urls.py @@ -12,6 +12,7 @@ from sapl.parlamentares.views import (CargoMesaCrud, ColigacaoCrud, RelatoriaParlamentarCrud, SessaoLegislativaCrud, TipoAfastamentoCrud, TipoDependenteCrud, + AfastamentoParlamentarCrud, TipoMilitarCrud, VotanteView, altera_field_mesa, altera_field_mesa_public_view, @@ -42,7 +43,7 @@ urlpatterns = [ ParticipacaoParlamentarCrud.get_urls() + ProposicaoParlamentarCrud.get_urls() + RelatoriaParlamentarCrud.get_urls() + FrenteList.get_urls() + - VotanteView.get_urls() + VotanteView.get_urls() + AfastamentoParlamentarCrud.get_urls() )), url(r'^parlamentar/lista$', lista_parlamentares, name='lista_parlamentares'), diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 6cd9a572f..8c6986418 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -38,13 +38,13 @@ from .forms import (FiliacaoForm, FrenteForm, LegislaturaForm, MandatoForm, ParlamentarCreateForm, ParlamentarForm, VotanteForm, ParlamentarFilterSet, VincularParlamentarForm, BlocoForm, CargoBlocoForm, CargoBlocoPartidoForm, - BancadaForm) + BancadaForm, AfastamentoParlamentarForm) from .models import (Bancada, CargoBancada, CargoMesa, Coligacao, ComposicaoColigacao, ComposicaoMesa, Dependente, Filiacao, Frente, Legislatura, Mandato, NivelInstrucao, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, TipoAfastamento, TipoDependente, Votante, - Bloco, CargoBlocoPartido, HistoricoPartido, CargoBloco) + Bloco, CargoBlocoPartido, HistoricoPartido, CargoBloco, AfastamentoParlamentar) CargoBancadaCrud = CrudAux.build(CargoBancada, '') @@ -1298,3 +1298,40 @@ def deleta_vinculo_parlamentar_bloco(request,pk): 'sapl.parlamentares:bloco_detail', kwargs={'pk': pk_bloco}) ) + +class AfastamentoParlamentarCrud(PermissionRequiredMixin, MasterDetailCrud): + model = AfastamentoParlamentar + parent_field = 'parlamentar' + public = [RP_DETAIL, RP_LIST] + list_field_names = ['mandato__legislatura', + 'data_inicio', + 'data_fim', + 'tipo_afastamento'] + + class ListView(MasterDetailCrud.ListView): + ordering = ('-mandato__legislatura__numero', '-data_inicio') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + rows = context['rows'] + + coluna_coligacao = 2 + coluna_votos_recebidos = 3 + for row in rows: + if not row[coluna_coligacao][0]: + row[coluna_coligacao] = (' ', None) + + if not row[coluna_votos_recebidos][0]: + row[coluna_votos_recebidos] = (' ', None) + + return context + + class CreateView(MasterDetailCrud.CreateView): + form_class = AfastamentoParlamentarForm + + def get_initial(self): + parlamentar = Parlamentar.objects.get(pk=self.kwargs['pk']) + return {'parlamentar': parlamentar} + + class UpdateView(MasterDetailCrud.UpdateView): + form_class = AfastamentoParlamentarForm diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index eb0be21b8..0cee4885f 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -287,6 +287,7 @@ rules_group_geral = { (parlamentares.Bloco, __base__, __perms_publicas__), (parlamentares.CargoBloco, __base__, __perms_publicas__), (parlamentares.CargoBlocoPartido, __base__, __perms_publicas__), + (parlamentares.AfastamentoParlamentar, __base__, __perms_publicas__), (sessao.TipoSessaoPlenaria, __base__, __perms_publicas__), (sessao.TipoResultadoVotacao, __base__, __perms_publicas__), diff --git a/sapl/templates/parlamentares/layouts.yaml b/sapl/templates/parlamentares/layouts.yaml index 4a717e559..8014fc381 100644 --- a/sapl/templates/parlamentares/layouts.yaml +++ b/sapl/templates/parlamentares/layouts.yaml @@ -151,3 +151,9 @@ CargoBloco: - nome - unico - descricao + +AfastamentoParlamentar: + {% trans 'Afastamento' %}: + - data_inicio data_fim + - mandato tipo_afastamento + - observacao diff --git a/sapl/templates/parlamentares/subnav.yaml b/sapl/templates/parlamentares/subnav.yaml index 9199589fc..aec17d8a1 100644 --- a/sapl/templates/parlamentares/subnav.yaml +++ b/sapl/templates/parlamentares/subnav.yaml @@ -3,6 +3,8 @@ url: parlamentar_detail - title: {% trans 'Mandatos' %} url: mandato_list +- title: {% trans 'Afastamentos' %} + url: afastamentoparlamentar_list - title: {% trans 'Matérias' %} url: parlamentar_materias - title: {% trans 'Filiações Partidárias' %}