@ -1,14 +1,13 @@
from datetime import date
from datetime import date , timedelta
from django import forms
from django import forms
from django . core . exceptions import ValidationError
from django . core . exceptions import ValidationError
from django . db import transaction
from django . db import transaction
from django . db . models import Q
from django . forms import ModelForm
from django . forms import ModelForm
from django . utils . translation import ugettext_lazy as _
from django . utils . translation import ugettext_lazy as _
from floppyforms . widgets import ClearableFileInput
from floppyforms . widgets import ClearableFileInput
from sapl . utils import intervalos_tem_intersecao
from . models import ( ComposicaoColigacao , Filiacao , Legislatura , Mandato ,
from . models import ( ComposicaoColigacao , Filiacao , Legislatura , Mandato ,
Parlamentar )
Parlamentar )
@ -74,59 +73,60 @@ class ParlamentarCreateForm(ParlamentarForm):
def validar_datas ( data_filiacao , data_desfiliacao , parlamentar , filiacao ) :
def validar_datas ( data_filiacao , data_desfiliacao , parlamentar , filiacao ) :
# Verifica se data de desfiliacao é anterior a data de filiacao
# Verifica se data de desfiliacao é anterior a data de filiacao
if data_desfiliacao and data_desfiliacao < data_filiacao :
if data_desfiliacao and data_desfiliacao < data_filiacao :
error_msg = _ ( " A data de desfiliação não pode anterior \
error_msg = _ ( " A data de desfiliação não pode anterior \
à data de filiação " )
à data de filiação " )
return [ False , error_msg ]
return [ False , error_msg ]
filiacao_atual_id = filiacao . pk
filiacoes = parlamentar . filiacao_set . order_by ( ' data ' )
# recupera filiacoes em ordem crescente de data
if not filiacoes . exists ( ) :
todas_filiacoes = parlamentar . filiacao_set . all ( ) . order_by ( ' data ' )
return [ True , ' ' ]
filiacoes_id = [ parlamentar . pk for parlamentar in todas_filiacoes ]
# data ficticia de desfiliacao
# Novo registro inserido com filiacoes ja existentes
df_desfiliacao = data_desfiliacao if data_desfiliacao else date . today ( )
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
# se não puder haver filiação no mesmo dia de desfiliação, basta
# retirar os timedelta abaixo
range_livre_exigido = Q (
data__range = [ data_filiacao + timedelta ( days = 1 ) ,
df_desfiliacao - timedelta ( days = 1 ) ] ) | Q (
data_desfiliacao__range = [ data_filiacao + timedelta ( days = 1 ) ,
df_desfiliacao - timedelta ( days = 1 ) ] )
filiacao_em_edicao_id = filiacao . pk
error_msg = None
error_msg = None
for filiacoes in todas_filiacoes :
# filiação em edição não é a última e está sem data de desfiliação
# nao comparar o registro com ele mesmo
if not data_desfiliacao and filiacao_em_edicao_id and \
if filiacoes . id != filiacao_atual_id :
filiacao_em_edicao_id != filiacoes . last ( ) . pk :
error_msg = _ ( " Data de desfiliação do parlamentar não pode ser \
# Se a atualizacao eh para remover a data de desfiliacao
ausente , se existirem datas de filiação posteriores . " )
if not data_desfiliacao :
# so permite na ultima data (ou a unica)
# a filiação que está sendo inclusa não tem data de desfiliação mas
if filiacao_atual_id != filiacoes_id [ - 1 ] :
# já existe outra sem data de desfiliação
error_msg = _ ( " Data de desfiliação do parlamentar não \
elif not data_desfiliacao and not filiacao_em_edicao_id and \
pode ser ausente , se existirem datas de \
not filiacoes . last ( ) . data_desfiliacao :
filiação posteriores " )
error_msg = _ ( " O parlamentar não pode se filiar a novo partido sem \
return [ False , error_msg ]
antes se desfiliar do partido anterior . " )
else :
data_inicio = filiacoes . data
if not error_msg :
data_fim = filiacoes . data_desfiliacao
# se a filiação é uma edição, a exclui das possibilidades
if filiacao_em_edicao_id :
# Se filiacao ainda em aberto, preenche uma desfiliacao
filiacoes = filiacoes . exclude ( pk = filiacao_em_edicao_id )
# ficticia para fins de checagem de interseccao
if not data_fim :
# testa a intercessão de intervalo com outra filiação
data_fim = date . today ( )
if filiacoes . filter ( range_livre_exigido ) . exists ( ) :
error_msg = _ ( " A data de filiação e desfiliação não podem estar \
# finalmente verifica intersecao
no intervalo de outro período de filiação . " )
if intervalos_tem_intersecao ( data_inicio , data_fim ,
data_filiacao , data_desfiliacao ) :
if not error_msg :
error_msg = _ ( " A data de filiação e \
# passou pelo teste de intervalo mas a data de filiação é maior que
desfiliação não podem estar no intervalo \
# a ultima que está em aberto
de outro período de filiação " )
if filiacoes . filter ( data_desfiliacao__isnull = True ,
break
data__lte = data_filiacao ) . exists ( ) :
error_msg = _ ( " Não pode haver um registro de filiação com data de \
filiação igual ou superior a data de filiação em aberto . " )
if error_msg :
if error_msg :
return [ False , error_msg ]
return [ False , error_msg ]