From fd304d040932d5948c3200284de96fc30a30afa1 Mon Sep 17 00:00:00 2001 From: Edward Date: Wed, 11 May 2016 09:48:57 -0300 Subject: [PATCH] =?UTF-8?q?Fix=20#402=20-=20checagem=20de=20filia=C3=A7?= =?UTF-8?q?=C3=A3o=20partid=C3=A1ria=20(#423)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #402 - checagem de filiação partidária * WIP * WIP * WIP * WIP --- parlamentares/forms.py | 104 +++++++++++++++++++++-------------------- protocoloadm/views.py | 2 +- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/parlamentares/forms.py b/parlamentares/forms.py index ead139e7b..984ade37c 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,60 @@ 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] + + # 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 filiacao ainda em aberto, 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 +126,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]) diff --git a/protocoloadm/views.py b/protocoloadm/views.py index 19e67e9ba..5f874ef78 100644 --- a/protocoloadm/views.py +++ b/protocoloadm/views.py @@ -4,7 +4,7 @@ from datetime import date, datetime from braces.views import FormValidMessageMixin from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse -from django.db.models import Q, Max +from django.db.models import Max, Q from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _