From 61feb0b09c30e9931deb3356b954c782974126f7 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 9 May 2016 19:47:46 -0300 Subject: [PATCH] =?UTF-8?q?Fix=20#402=20-=20checagem=20de=20filia=C3=A7?= =?UTF-8?q?=C3=A3o=20partid=C3=A1ria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parlamentares/forms.py | 116 +++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/parlamentares/forms.py b/parlamentares/forms.py index ead139e7b..97f5bb07f 100644 --- a/parlamentares/forms.py +++ b/parlamentares/forms.py @@ -1,3 +1,5 @@ +from datetime import date + from django import forms from django.core.exceptions import ValidationError from django.db import transaction @@ -6,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _ from floppyforms.widgets import ClearableFileInput import sapl +from sapl.utils import intervalos_tem_intersecao from .models import Filiacao, Legislatura, Mandato, Parlamentar @@ -50,59 +53,72 @@ class ParlamentarCreateForm(ParlamentarForm): return parlamentar -def validate(data, data_desfiliacao, parlamentar, filiacao): - data_filiacao = data - data_desfiliacao = data_desfiliacao +def validar_datas(data_filiacao, data_desfiliacao, parlamentar, filiacao): - # Dá erro caso a data de desfiliação seja anterior a de filiação + # Verifica se data de desfiliacao é anterior a data de filiacao if data_desfiliacao and data_desfiliacao < data_filiacao: error_msg = _("A data de desfiliação não pode anterior \ - à data de filiação") + à data de filiação") return [False, error_msg] - # Esse bloco garante que não haverá intersecção entre os - # períodos de filiação - id_filiacao_atual = filiacao.pk - todas_filiacoes = parlamentar.filiacao_set.all() - - for filiacoes in todas_filiacoes: - if (not filiacoes.data_desfiliacao and - filiacoes.id != id_filiacao_atual): - error_msg = _("O parlamentar não pode se filiar a algum partido \ - sem antes se desfiliar do partido anterior") - return [False, error_msg] - + filiacao_atual_id = filiacao.pk + # recupera filiacoes em ordem crescente de data + todas_filiacoes = parlamentar.filiacao_set.all().order_by('data') + filiacoes_id = [parlamentar.pk for parlamentar in todas_filiacoes] + + # Novo registro inserido com filiacoes ja existentes + if filiacao_atual_id not in filiacoes_id and len(filiacoes_id) > 0: + ultima_filiacao = todas_filiacoes.last() + # Se ultima filiacao aberta e insercao posterior a esta filiacao + if (not ultima_filiacao.data_desfiliacao and + data_filiacao >= ultima_filiacao.data): + error_msg = _("O parlamentar não pode se filiar \ + a novo partido sem antes se \ + desfiliar do partido anterior") + return [False, error_msg] + + primeira_filiacao = todas_filiacoes.first() + + # se novo registro tem data de desfiliacao aberta + # e eh anterior a primeira data de filiacao já existente. + if (not data_desfiliacao and + data_filiacao <= primeira_filiacao.data): + error_msg = _("O parlamentar não pode se filiar \ + ,sem uma data de desfiliação, \ + a algum partido anterior") + return [False, error_msg] + + # checa intervalos de interseccao error_msg = None for filiacoes in todas_filiacoes: - if filiacoes.id != id_filiacao_atual: - - data_init = filiacoes.data - data_fim = filiacoes.data_desfiliacao - - if data_init <= data_filiacao < data_fim: - - error_msg = _("A data de filiação e \ - desfiliação não podem estar no intervalo \ - de outro período de filiação") - break - - if (data_desfiliacao and - data_init < data_desfiliacao < data_fim): - - error_msg = _("A data de filiação e \ - desfiliação não podem estar no intervalo \ - de outro período de filiação") - break - - if (data_desfiliacao and - data_filiacao <= data_init and - data_desfiliacao >= data_fim): - - error_msg = _("A data de filiação e \ - desfiliação não podem estar no intervalo \ - de outro período de filiação") - break - + # nao comparar o registro com ele mesmo + if filiacoes.id != filiacao_atual_id: + + # Se a atualizacao eh para remover a data de desfiliacao + if not data_desfiliacao: + # so permite na ultima data (ou a unica) + if filiacao_atual_id != filiacoes_id[-1]: + error_msg = _("Data de desfiliação do parlamentar não \ + pode ser ausente, se existirem datas de \ + filiação posteriores") + return [False, error_msg] + else: + data_inicio = filiacoes.data + data_fim = filiacoes.data_desfiliacao + + # Se ainda desfiliado, preenche uma desfiliacao ficticia + # para fins de checagem de interseccao + if not data_fim: + data_fim = date.today() + + + # finalmente verifica intersecao + if intervalos_tem_intersecao(data_inicio, data_fim, + data_filiacao, data_desfiliacao): + error_msg = _("A data de filiação e \ + desfiliação não podem estar no intervalo \ + de outro período de filiação") + break if error_msg: return [False, error_msg] @@ -122,10 +138,10 @@ class FiliacaoForm(ModelForm): return self.errors filiacao = super(FiliacaoForm, self).save(commit=False) - validacao = validate(self.cleaned_data['data'], - self.cleaned_data['data_desfiliacao'], - filiacao.parlamentar, - filiacao) + validacao = validar_datas(self.cleaned_data['data'], + self.cleaned_data['data_desfiliacao'], + filiacao.parlamentar, + filiacao) if not validacao[0]: raise ValidationError(validacao[1])