From e37baaa93a0a41e1a19e29b740c4b22a01171adf Mon Sep 17 00:00:00 2001 From: Cesar Carvalho Date: Thu, 22 Aug 2019 11:34:36 -0300 Subject: [PATCH] =?UTF-8?q?Adiciona=20informa=C3=A7=C3=A3o=20de=20afastame?= =?UTF-8?q?nto=20no=20relat=C3=B3rio=20de=20presen=C3=A7as?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/base/views.py | 40 ++++++++++++++----- sapl/parlamentares/forms.py | 4 +- .../parlamentares/tests/test_parlamentares.py | 40 ++++++++++++++++++- sapl/sessao/forms.py | 6 +-- sapl/sessao/views.py | 6 +-- .../base/RelatorioPresencaSessao_filter.html | 18 ++++++--- sapl/utils.py | 14 ++++--- 7 files changed, 101 insertions(+), 27 deletions(-) diff --git a/sapl/base/views.py b/sapl/base/views.py index 8797627ea..c652d9e22 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -42,11 +42,12 @@ from sapl.materia.models import (Autoria, MateriaLegislativa, Proposicao, Anexad TipoMateriaLegislativa, StatusTramitacao, UnidadeTramitacao, DocumentoAcessorio, TipoDocumento) from sapl.norma.models import (NormaJuridica, TipoNormaJuridica, NormaEstatisticas) -from sapl.parlamentares.models import Parlamentar, Legislatura, Mandato, Filiacao, SessaoLegislativa, Bancada +from sapl.parlamentares.models import (Parlamentar, Legislatura, Mandato, Filiacao, + SessaoLegislativa, Bancada, AfastamentoParlamentar) from sapl.protocoloadm.models import (Protocolo, TipoDocumentoAdministrativo, StatusTramitacaoAdministrativo, DocumentoAdministrativo, Anexado) -from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, +from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, OrdemDia, SessaoPlenariaPresenca, TipoSessaoPlenaria) from sapl.utils import (parlamentares_ativos, gerar_hash_arquivo, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, mail_service_configured, @@ -494,16 +495,35 @@ class RelatorioPresencaSessaoView(FilterView): for i, p in enumerate(parlamentares_qs): m = p.mandato_set.filter(Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__gte=_range[1]) | Q(data_inicio_mandato__lte=_range[0], data_fim_mandato__isnull=True) | - Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1]) | - # mandato suplente Q(data_inicio_mandato__gte=_range[0], data_fim_mandato__lte=_range[1])) + afastamentos = AfastamentoParlamentar.objects.filter(Q(parlamentar=p) & (Q(data_inicio__range=_range) | + Q(data_inicio__gte=_range[0], data_fim__isnull=True))) + + afast_parl_sessao = 0 + afast_parl_ordem = 0 + for afastamento in afastamentos: + if afastamento.data_fim: + afast_parl_sessao += SessaoPlenaria.objects.filter(data_inicio__range=[afastamento.data_inicio, + afastamento.data_fim]).count() + afast_parl_ordem += OrdemDia.objects.filter(sessao_plenaria__data_inicio__range=[afastamento.data_inicio, + afastamento.data_fim]).order_by('sessao_plenaria__id').\ + distinct('sessao_plenaria__id').count() + else: + afast_parl_sessao += SessaoPlenaria.objects.filter(data_inicio__gte=afastamento.data_inicio).count() + afast_parl_ordem += OrdemDia.objects.filter(sessao_plenaria__data_inicio__gte=afastamento.data_inicio).\ + order_by('sessao_plenaria__id').\ + distinct('sessao_plenaria__id').count() + + m = m.last() parlamentares_presencas.append({ 'parlamentar': p, 'titular': m.titular if m else False, 'sessao_porc': 0, - 'ordemdia_porc': 0 + 'ordemdia_porc': 0, + 'sessao_afast': afast_parl_sessao, + 'ordem_afast': afast_parl_ordem }) try: self.logger.debug( @@ -529,13 +549,15 @@ class RelatorioPresencaSessaoView(FilterView): }) if total_sessao != 0: + porc = round( + sessao_count * 100 / (total_sessao-afast_parl_sessao), 2) parlamentares_presencas[i].update( - {'sessao_porc': round( - sessao_count * 100 / total_sessao, 2)}) + {'sessao_porc': porc if porc <=100 else 100}) if total_ordemdia != 0: + porc = round( + ordemdia_count * 100 / (total_ordemdia-afast_parl_ordem), 2) parlamentares_presencas[i].update( - {'ordemdia_porc': round( - ordemdia_count * 100 / total_ordemdia, 2)}) + {'ordemdia_porc': porc if porc <=100.0 else 100.0}) context['date_range'] = _range context['total_ordemdia'] = total_ordemdia diff --git a/sapl/parlamentares/forms.py b/sapl/parlamentares/forms.py index 8d6d11922..2174f9c52 100755 --- a/sapl/parlamentares/forms.py +++ b/sapl/parlamentares/forms.py @@ -815,7 +815,9 @@ class AfastamentoParlamentarForm(ModelForm): raise ValidationError(_("Data fim do afastamento posterior ao fim" " do mandato informado.")) - if AfastamentoParlamentar.objects.last() and not AfastamentoParlamentar.objects.last().data_fim: + ultimo_afastamento = AfastamentoParlamentar.objects.last() + if ultimo_afastamento and not ultimo_afastamento.data_fim \ + and ultimo_afastamento != self.instance: self.logger.error("Existe Afastamento sem Data Fim.") raise ValidationError(_("Existe Afastamento sem Data Fim.")) diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py index 7f5961133..c29bebd5f 100644 --- a/sapl/parlamentares/tests/test_parlamentares.py +++ b/sapl/parlamentares/tests/test_parlamentares.py @@ -10,6 +10,7 @@ from sapl.parlamentares.models import (Dependente, Filiacao, Legislatura, Mandato, Parlamentar, Partido, TipoDependente, TipoAfastamento, AfastamentoParlamentar) +from sapl.utils import verifica_afastamento_parlamentar @pytest.mark.django_db(transaction=False) @@ -516,4 +517,41 @@ def test_afastamentos_form_campos_invalidos(): assert form.errors['data_inicio'] == ["Este campo é obrigatório."] assert form.errors['mandato'] == ["Este campo é obrigatório."] - assert form.errors['parlamentar'] == ["Este campo é obrigatório."] \ No newline at end of file + assert form.errors['parlamentar'] == ["Este campo é obrigatório."] + + +@pytest.mark.django_db(transaction=False) +def test_parlamentar_esta_afastado(): + parlamentar = mommy.make(Parlamentar) + mandato = mommy.make(Mandato, + parlamentar = parlamentar, + data_inicio_mandato='2017-01-01', + data_fim_mandato='2021-12-31') + afastamento = AfastamentoParlamentar.objects.create(mandato=mandato, + parlamentar=parlamentar, + data_inicio='2017-12-05', + data_fim='2017-12-12') + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-13') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-04') + + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06', '2017-12-11') + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06', '2017-12-06') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-03', '2017-12-04') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-13', '2017-12-15') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-15', '2017-12-15') + + afastamento = AfastamentoParlamentar.objects.create(mandato=mandato, + parlamentar=parlamentar, + data_inicio='2017-12-05') + + assert AfastamentoParlamentar.objects.all().count() == 2 + + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-13') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-04') + + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06', '2017-12-11') + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-06', '2017-12-06') + assert not verifica_afastamento_parlamentar(parlamentar, '2017-12-03', '2017-12-04') + assert verifica_afastamento_parlamentar(parlamentar, '2017-12-13', '2017-12-15') diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index ebc8bb1d5..dababe596 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -22,7 +22,7 @@ from sapl.parlamentares.models import Parlamentar, Mandato from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, MateriaPesquisaOrderingFilter, autor_label, autor_modal, timezone, choice_anos_com_sessaoplenaria, - FileFieldCheckMixin, verifica_ausencia_parlamentar) + FileFieldCheckMixin, verifica_afastamento_parlamentar) from .models import (ExpedienteMateria, JustificativaAusencia, Orador, OradorExpediente, OrdemDia, PresencaOrdemDia, SessaoPlenaria, @@ -602,7 +602,7 @@ class OradorForm(ModelForm): sessao = SessaoPlenaria.objects.get(id=kwargs['initial']['id_sessao']) parlamentares_ativos = Parlamentar.objects.filter(ativo=True).order_by('nome_parlamentar') for p in parlamentares_ativos: - if verifica_ausencia_parlamentar(p, sessao.data_inicio, sessao.data_fim): + if verifica_afastamento_parlamentar(p, sessao.data_inicio, sessao.data_fim): parlamentares_ativos = parlamentares_ativos.exclude(id=p.id) self.fields['parlamentar'].queryset = parlamentares_ativos @@ -650,7 +650,7 @@ class OradorExpedienteForm(ModelForm): parlamentares_ativos = Parlamentar.objects.filter(ativo=True).order_by('nome_parlamentar') for p in parlamentares_ativos: - if verifica_ausencia_parlamentar(p, sessao.data_inicio, sessao.data_fim): + if verifica_afastamento_parlamentar(p, sessao.data_inicio, sessao.data_fim): parlamentares_ativos = parlamentares_ativos.exclude(id=p.id) self.fields['parlamentar'].queryset = parlamentares_ativos diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index b76d5864a..cbb0b4e46 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -40,7 +40,7 @@ from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato, from sapl.sessao.apps import AppConfig from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm from sapl.utils import (show_results_filter_set, remover_acentos, get_client_ip, filiacao_data, - verifica_ausencia_parlamentar) + verifica_afastamento_parlamentar) from .forms import (AdicionarVariasMateriasFilterSet, ExpedienteForm, JustificativaAusenciaForm, OcorrenciaSessaoForm, ListMateriaForm, @@ -464,7 +464,7 @@ def get_presencas_generic(model, sessao, legislatura): for m in mandato: parlamentar = m.parlamentar - p_afastado = verifica_ausencia_parlamentar(parlamentar, sessao.data_inicio, sessao.data_fim) + p_afastado = verifica_afastamento_parlamentar(parlamentar, sessao.data_inicio, sessao.data_fim) if parlamentar in presentes: yield (parlamentar, True, p_afastado) else: @@ -1292,7 +1292,7 @@ class MesaView(FormMixin, DetailView): key=lambda x: remover_acentos(x.nome_parlamentar)) org_parlamentares_vagos = [ p for p in org_parlamentares_vagos if (p.ativo and - not verifica_ausencia_parlamentar(p, sessao.data_inicio, sessao.data_fim) + not verifica_afastamento_parlamentar(p, sessao.data_inicio, sessao.data_fim) )] # Se todos os cargos estiverem ocupados, a listagem de parlamentares # deve ser renderizada vazia diff --git a/sapl/templates/base/RelatorioPresencaSessao_filter.html b/sapl/templates/base/RelatorioPresencaSessao_filter.html index c3ad733af..f73abf7d3 100644 --- a/sapl/templates/base/RelatorioPresencaSessao_filter.html +++ b/sapl/templates/base/RelatorioPresencaSessao_filter.html @@ -25,20 +25,26 @@ Tipo Sessão Plenária: {{tipo}}
TOTAIS NO PERÍODO - SESSÕES: {{total_sessao}} - ORDENS DO DIA: {{total_ordemdia}}
Exibir presença das Ordens do Dia: {% if exibir_ordem %} Sim {% else %} Não {% endif %}
+
+

Atenção! Este relatório leva em conta os afastamentos cadastrados em Parlamentar -> Afastamentos. + A porcentagem de presença exclui períodos em que o parlamentar estava afastado.

+
- - {% if exibir_ordem %} {% endif %} + + {% if exibir_ordem %} {% endif %} - - + + + {% if exibir_ordem %} - + + {% endif %} @@ -50,9 +56,11 @@ + {% if exibir_ordem %} + {% endif %} diff --git a/sapl/utils.py b/sapl/utils.py index d16d6eb54..553415967 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1000,14 +1000,18 @@ class OverwriteStorage(FileSystemStorage): return name -def verifica_ausencia_parlamentar(parlamentar, data_inicio, data_fim=None): +def verifica_afastamento_parlamentar(parlamentar, data_inicio, data_fim=None): from sapl.parlamentares.models import AfastamentoParlamentar if data_fim: - existe_afastamento = AfastamentoParlamentar.objects.filter(parlamentar=parlamentar, - data_inicio__lte=data_inicio, - data_fim__gte=data_fim).exists() + existe_afastamento = AfastamentoParlamentar.objects.filter(Q(parlamentar=parlamentar) & + ( (Q(data_inicio__lte=data_inicio) & + Q(data_fim__gte=data_fim)) | + ( Q(data_inicio__lte=data_inicio) & + Q(data_fim__isnull=True)) + ) ).exists() else: existe_afastamento = AfastamentoParlamentar.objects.filter(parlamentar=parlamentar, - data_inicio__lte=data_inicio).exists() + data_inicio__lte=data_inicio, + data_fim__gte=data_inicio).exists() return existe_afastamento
Nome Parlamentar / Partido Titular? Ativo?SessãoOrdem do DiaSessãoOrdem do Dia
(Qtd)( % )(Qtd Presente)(Qtde Afastado)( % )(Qtd)(Qtd Presente)(Qtde Afastado) ( % )
{% if p.titular %} Sim {% else %} Não {% endif %} {% if p.parlamentar.ativo %} Sim {% else %} Não {% endif %} {{p.sessao_count}}{{p.sessao_afast}} {{p.sessao_porc}}{{p.ordemdia_count}}{{p.ordem_afast}} {{p.ordemdia_porc}}