|
|
@ -1,6 +1,6 @@ |
|
|
|
import re |
|
|
|
import traceback |
|
|
|
from collections import OrderedDict, defaultdict |
|
|
|
from collections import OrderedDict, defaultdict, namedtuple |
|
|
|
from datetime import date |
|
|
|
from functools import lru_cache, partial |
|
|
|
from itertools import groupby |
|
|
@ -8,18 +8,16 @@ from operator import xor |
|
|
|
from subprocess import PIPE, call |
|
|
|
|
|
|
|
import pkg_resources |
|
|
|
import pytz |
|
|
|
import reversion |
|
|
|
import yaml |
|
|
|
from django.apps import apps |
|
|
|
from django.apps.config import AppConfig |
|
|
|
from django.contrib.auth import get_user_model |
|
|
|
from django.contrib.auth.models import Group |
|
|
|
from django.contrib.contenttypes.models import ContentType |
|
|
|
from django.core.exceptions import ObjectDoesNotExist |
|
|
|
from django.db import connections, transaction |
|
|
|
from django.db.models import Max, Q |
|
|
|
from django.db.models.base import ModelBase |
|
|
|
from pytz import timezone |
|
|
|
from unipath import Path |
|
|
|
|
|
|
|
from sapl.base.models import AppConfig as AppConf |
|
|
@ -27,8 +25,8 @@ from sapl.base.models import Autor, TipoAutor, cria_models_tipo_autor |
|
|
|
from sapl.comissoes.models import Comissao, Composicao, Participacao |
|
|
|
from sapl.legacy.models import NormaJuridica as OldNormaJuridica |
|
|
|
from sapl.legacy.models import TipoNumeracaoProtocolo |
|
|
|
from sapl.materia.models import (AcompanhamentoMateria, Proposicao, |
|
|
|
StatusTramitacao, TipoDocumento, |
|
|
|
from sapl.materia.models import (AcompanhamentoMateria, MateriaLegislativa, |
|
|
|
Proposicao, StatusTramitacao, TipoDocumento, |
|
|
|
TipoMateriaLegislativa, TipoProposicao, |
|
|
|
Tramitacao) |
|
|
|
from sapl.norma.models import (AssuntoNorma, NormaJuridica, NormaRelacionada, |
|
|
@ -117,12 +115,31 @@ models_novos_para_antigos = { |
|
|
|
for model in field_renames} |
|
|
|
models_novos_para_antigos[Composicao] = models_novos_para_antigos[Participacao] |
|
|
|
|
|
|
|
content_types = {model: ContentType.objects.get( |
|
|
|
app_label=model._meta.app_label, model=model._meta.model_name) |
|
|
|
for model in field_renames} |
|
|
|
|
|
|
|
campos_novos_para_antigos = { |
|
|
|
model._meta.get_field(nome_novo): nome_antigo |
|
|
|
for model, renames in field_renames.items() |
|
|
|
for nome_novo, nome_antigo in renames.items()} |
|
|
|
|
|
|
|
# campos de Composicao (de Comissao) |
|
|
|
for nome_novo, nome_antigo in (('comissao', 'cod_comissao'), |
|
|
|
('periodo', 'cod_periodo_comp')): |
|
|
|
campos_novos_para_antigos[ |
|
|
|
Composicao._meta.get_field(nome_novo)] = nome_antigo |
|
|
|
|
|
|
|
|
|
|
|
# campos virtuais de Proposicao para funcionarem com get_fk_related |
|
|
|
CampoFalso = namedtuple('CampoFalso', ['model', 'related_model']) |
|
|
|
CAMPOS_FALSOS_PROPOSICAO = { |
|
|
|
TipoMateriaLegislativa: CampoFalso(Proposicao, MateriaLegislativa), |
|
|
|
TipoDocumento: CampoFalso(Proposicao, DocumentoAdministrativo) |
|
|
|
} |
|
|
|
for campo_falso in CAMPOS_FALSOS_PROPOSICAO.values(): |
|
|
|
campos_novos_para_antigos[campo_falso] = 'cod_mat_ou_doc' |
|
|
|
|
|
|
|
|
|
|
|
# MIGRATION ################################################################# |
|
|
|
|
|
|
@ -168,10 +185,14 @@ class ForeignKeyFaltando(ObjectDoesNotExist): |
|
|
|
campo = campos_novos_para_antigos[self.field] |
|
|
|
_, tabela, campos_pk = get_estrutura_legado(self.field.model) |
|
|
|
pk = {c: getattr(self.old, c) for c in campos_pk} |
|
|
|
sql = 'select * from {} where {}'.format( |
|
|
|
tabela, |
|
|
|
' and '.join(['{} = {}'.format(k, v) for k, v in pk.items()])) |
|
|
|
return OrderedDict((('campo', campo), |
|
|
|
('valor', self.valor), |
|
|
|
('tabela', tabela), |
|
|
|
('pk', pk))) |
|
|
|
('pk', pk), |
|
|
|
('sql', sql))) |
|
|
|
|
|
|
|
|
|
|
|
@lru_cache() |
|
|
@ -180,8 +201,8 @@ def _get_all_ids_from_model(model): |
|
|
|
return set(model.objects.values_list('id', flat=True)) |
|
|
|
|
|
|
|
|
|
|
|
def get_fk_related(field, old, old_field_name): |
|
|
|
valor = getattr(old, old_field_name) |
|
|
|
def get_fk_related(field, old): |
|
|
|
valor = getattr(old, campos_novos_para_antigos[field]) |
|
|
|
if valor is None and field.null: |
|
|
|
return None |
|
|
|
if valor in _get_all_ids_from_model(field.related_model): |
|
|
@ -679,208 +700,197 @@ def dict_representer(dumper, data): |
|
|
|
yaml.add_representer(OrderedDict, dict_representer) |
|
|
|
|
|
|
|
|
|
|
|
class DataMigrator: |
|
|
|
# configura timezone de migração |
|
|
|
nome_banco_legado = DATABASES['legacy']['NAME'] |
|
|
|
match = re.match('sapl_cm_(.*)', nome_banco_legado) |
|
|
|
sigla_casa = match.group(1) |
|
|
|
with open(PATH_TABELA_TIMEZONES, 'r') as arq: |
|
|
|
tabela_timezones = yaml.load(arq) |
|
|
|
municipio, uf, nome_timezone = tabela_timezones[sigla_casa] |
|
|
|
if nome_timezone: |
|
|
|
timezone = pytz.timezone(nome_timezone) |
|
|
|
else: |
|
|
|
timezone = get_timezone(municipio, uf) |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
self.choice_valida = {} |
|
|
|
|
|
|
|
# configura timezone de migração |
|
|
|
self.nome_banco_legado = DATABASES['legacy']['NAME'] |
|
|
|
match = re.match('sapl_cm_(.*)', self.nome_banco_legado) |
|
|
|
sigla_casa = match.group(1) |
|
|
|
with open(PATH_TABELA_TIMEZONES, 'r') as arq: |
|
|
|
tabela_timezones = yaml.load(arq) |
|
|
|
municipio, uf, nome_timezone = tabela_timezones[sigla_casa] |
|
|
|
if nome_timezone: |
|
|
|
self.timezone = timezone(nome_timezone) |
|
|
|
else: |
|
|
|
self.timezone = get_timezone(municipio, uf) |
|
|
|
|
|
|
|
def populate_renamed_fields(self, new, old): |
|
|
|
renames = field_renames[type(new)] |
|
|
|
|
|
|
|
for field in new._meta.fields: |
|
|
|
old_field_name = renames.get(field.name) |
|
|
|
if old_field_name: |
|
|
|
field_type = field.get_internal_type() |
|
|
|
|
|
|
|
if field_type == 'ForeignKey': |
|
|
|
fk_field_name = '{}_id'.format(field.name) |
|
|
|
value = get_fk_related(field, old, old_field_name) |
|
|
|
setattr(new, fk_field_name, value) |
|
|
|
else: |
|
|
|
value = getattr(old, old_field_name) |
|
|
|
|
|
|
|
if (field_type in ['CharField', 'TextField'] |
|
|
|
and value in [None, 'None']): |
|
|
|
value = '' |
|
|
|
|
|
|
|
# adiciona timezone faltante aos campos com tempo |
|
|
|
# os campos TIMESTAMP do mysql são gravados em UTC |
|
|
|
# os DATETIME e TIME não têm timezone |
|
|
|
def campo_tempo_sem_timezone(tipo): |
|
|
|
return (field_type == tipo |
|
|
|
and value and not value.tzinfo) |
|
|
|
if campo_tempo_sem_timezone('DateTimeField'): |
|
|
|
value = self.timezone.localize(value) |
|
|
|
if campo_tempo_sem_timezone('TimeField'): |
|
|
|
value = value.replace(tzinfo=self.timezone) |
|
|
|
|
|
|
|
setattr(new, field.name, value) |
|
|
|
|
|
|
|
def migrar(self, obj=appconfs, interativo=True): |
|
|
|
# warning: model/app migration order is of utmost importance |
|
|
|
|
|
|
|
uniformiza_banco() |
|
|
|
|
|
|
|
# excluindo database antigo. |
|
|
|
if interativo: |
|
|
|
info('Todos os dados do banco serão excluidos. ' |
|
|
|
'Recomendamos que faça backup do banco sapl ' |
|
|
|
'antes de continuar.') |
|
|
|
info('Deseja continuar? [s/n]') |
|
|
|
resposta = input() |
|
|
|
if resposta.lower() in ['s', 'sim', 'y', 'yes']: |
|
|
|
pass |
|
|
|
def populate_renamed_fields(new, old): |
|
|
|
renames = field_renames[type(new)] |
|
|
|
|
|
|
|
for field in new._meta.fields: |
|
|
|
old_field_name = renames.get(field.name) |
|
|
|
if old_field_name: |
|
|
|
field_type = field.get_internal_type() |
|
|
|
|
|
|
|
if field_type == 'ForeignKey': |
|
|
|
fk_field_name = '{}_id'.format(field.name) |
|
|
|
value = get_fk_related(field, old) |
|
|
|
setattr(new, fk_field_name, value) |
|
|
|
else: |
|
|
|
info('Migração cancelada.') |
|
|
|
return 0 |
|
|
|
info('Excluindo entradas antigas do banco destino.') |
|
|
|
call([PROJECT_DIR.child('manage.py'), 'flush', |
|
|
|
'--database=default', '--no-input'], stdout=PIPE) |
|
|
|
|
|
|
|
# apaga tipos de autor padrão (criados no flush acima) |
|
|
|
TipoAutor.objects.all().delete() |
|
|
|
|
|
|
|
fill_vinculo_norma_juridica() |
|
|
|
fill_dados_basicos() |
|
|
|
info('Começando migração: %s...' % obj) |
|
|
|
try: |
|
|
|
ocorrencias.clear() |
|
|
|
dir_ocorrencias = DIR_RESULTADOS.child(date.today().isoformat()) |
|
|
|
dir_ocorrencias.mkdir(parents=True) |
|
|
|
self._do_migrate(obj) |
|
|
|
except Exception as e: |
|
|
|
ocorrencias['traceback'] = str(traceback.format_exc()) |
|
|
|
raise e |
|
|
|
finally: |
|
|
|
# grava ocorrências |
|
|
|
arq_ocorrencias = dir_ocorrencias.child( |
|
|
|
self.nome_banco_legado + '.yaml') |
|
|
|
with open(arq_ocorrencias, 'w') as arq: |
|
|
|
dump = yaml.dump(dict(ocorrencias), allow_unicode=True) |
|
|
|
arq.write(dump.replace('\n- ', '\n\n- ')) |
|
|
|
info('Ocorrências salvas em\n {}'.format(arq_ocorrencias)) |
|
|
|
|
|
|
|
# recria tipos de autor padrão que não foram criados pela migração |
|
|
|
cria_models_tipo_autor() |
|
|
|
|
|
|
|
def _do_migrate(self, obj): |
|
|
|
if isinstance(obj, AppConfig): |
|
|
|
models = [model for model in obj.models.values() |
|
|
|
if model in field_renames] |
|
|
|
|
|
|
|
if obj.label == 'materia': |
|
|
|
# Devido à referência TipoProposicao.tipo_conteudo_related |
|
|
|
# a migração de TipoProposicao precisa ser feita |
|
|
|
# após TipoMateriaLegislativa e TipoDocumento |
|
|
|
# (porém antes de Proposicao) |
|
|
|
models.remove(TipoProposicao) |
|
|
|
pos_tipo_proposicao = max( |
|
|
|
models.index(TipoMateriaLegislativa), |
|
|
|
models.index(TipoDocumento)) + 1 |
|
|
|
models.insert(pos_tipo_proposicao, TipoProposicao) |
|
|
|
assert models.index(TipoProposicao) < models.index(Proposicao) |
|
|
|
|
|
|
|
self._do_migrate(models) |
|
|
|
elif isinstance(obj, ModelBase): |
|
|
|
self.migrate_model(obj) |
|
|
|
elif hasattr(obj, '__iter__'): |
|
|
|
for item in obj: |
|
|
|
self._do_migrate(item) |
|
|
|
value = getattr(old, old_field_name) |
|
|
|
|
|
|
|
if (field_type in ['CharField', 'TextField'] |
|
|
|
and value in [None, 'None']): |
|
|
|
value = '' |
|
|
|
|
|
|
|
# adiciona timezone faltante aos campos com tempo |
|
|
|
# os campos TIMESTAMP do mysql são gravados em UTC |
|
|
|
# os DATETIME e TIME não têm timezone |
|
|
|
def campo_tempo_sem_timezone(tipo): |
|
|
|
return (field_type == tipo |
|
|
|
and value and not value.tzinfo) |
|
|
|
if campo_tempo_sem_timezone('DateTimeField'): |
|
|
|
value = timezone.localize(value) |
|
|
|
if campo_tempo_sem_timezone('TimeField'): |
|
|
|
value = value.replace(tzinfo=timezone) |
|
|
|
|
|
|
|
setattr(new, field.name, value) |
|
|
|
|
|
|
|
|
|
|
|
def migrar_dados(interativo=True): |
|
|
|
uniformiza_banco() |
|
|
|
|
|
|
|
# excluindo database antigo. |
|
|
|
if interativo: |
|
|
|
info('Todos os dados do banco serão excluidos. ' |
|
|
|
'Recomendamos que faça backup do banco sapl ' |
|
|
|
'antes de continuar.') |
|
|
|
info('Deseja continuar? [s/n]') |
|
|
|
resposta = input() |
|
|
|
if resposta.lower() in ['s', 'sim', 'y', 'yes']: |
|
|
|
pass |
|
|
|
else: |
|
|
|
info('Migração cancelada.') |
|
|
|
return 0 |
|
|
|
info('Excluindo entradas antigas do banco destino.') |
|
|
|
call([PROJECT_DIR.child('manage.py'), 'flush', |
|
|
|
'--database=default', '--no-input'], stdout=PIPE) |
|
|
|
|
|
|
|
# apaga tipos de autor padrão (criados no flush acima) |
|
|
|
TipoAutor.objects.all().delete() |
|
|
|
|
|
|
|
fill_vinculo_norma_juridica() |
|
|
|
fill_dados_basicos() |
|
|
|
info('Começando migração: ...') |
|
|
|
try: |
|
|
|
ocorrencias.clear() |
|
|
|
dir_ocorrencias = DIR_RESULTADOS.child(date.today().isoformat()) |
|
|
|
dir_ocorrencias.mkdir(parents=True) |
|
|
|
migrar_todos_os_models() |
|
|
|
except Exception as e: |
|
|
|
ocorrencias['traceback'] = str(traceback.format_exc()) |
|
|
|
raise e |
|
|
|
finally: |
|
|
|
# grava ocorrências |
|
|
|
arq_ocorrencias = dir_ocorrencias.child( |
|
|
|
nome_banco_legado + '.yaml') |
|
|
|
with open(arq_ocorrencias, 'w') as arq: |
|
|
|
dump = yaml.dump(dict(ocorrencias), allow_unicode=True) |
|
|
|
arq.write(dump.replace('\n- ', '\n\n- ')) |
|
|
|
info('Ocorrências salvas em\n {}'.format(arq_ocorrencias)) |
|
|
|
|
|
|
|
# recria tipos de autor padrão que não foram criados pela migração |
|
|
|
cria_models_tipo_autor() |
|
|
|
|
|
|
|
|
|
|
|
def move_para_depois_de(lista, movido, referencias): |
|
|
|
indice_inicial = lista.index(movido) |
|
|
|
lista.remove(movido) |
|
|
|
indice_apos_refs = max(lista.index(r) for r in referencias) + 1 |
|
|
|
lista.insert(max(indice_inicial, indice_apos_refs), movido) |
|
|
|
return lista |
|
|
|
|
|
|
|
|
|
|
|
def migrar_todos_os_models(): |
|
|
|
models = [model for app in appconfs for model in app.models.values() |
|
|
|
if model in field_renames] |
|
|
|
# Devido à referência TipoProposicao.tipo_conteudo_related |
|
|
|
# a migração de TipoProposicao precisa ser feita |
|
|
|
# após TipoMateriaLegislativa e TipoDocumento |
|
|
|
# (porém antes de Proposicao) |
|
|
|
move_para_depois_de(models, TipoProposicao, |
|
|
|
[TipoMateriaLegislativa, TipoDocumento]) |
|
|
|
assert models.index(TipoProposicao) < models.index(Proposicao) |
|
|
|
move_para_depois_de(models, Proposicao, |
|
|
|
[MateriaLegislativa, DocumentoAdministrativo]) |
|
|
|
|
|
|
|
for model in models: |
|
|
|
migrar_model(model) |
|
|
|
|
|
|
|
|
|
|
|
def migrar_model(model): |
|
|
|
print('Migrando %s...' % model.__name__) |
|
|
|
|
|
|
|
model_legado, tabela_legado, campos_pk_legado = \ |
|
|
|
get_estrutura_legado(model) |
|
|
|
|
|
|
|
if len(campos_pk_legado) == 1: |
|
|
|
# a pk no legado tem um único campo |
|
|
|
nome_pk = model_legado._meta.pk.name |
|
|
|
if 'ind_excluido' in {f.name for f in model_legado._meta.fields}: |
|
|
|
# se o model legado tem o campo ind_excluido |
|
|
|
# enumera apenas os não excluídos |
|
|
|
old_records = model_legado.objects.filter(~Q(ind_excluido=1)) |
|
|
|
else: |
|
|
|
raise TypeError( |
|
|
|
'Parameter must be a Model, AppConfig or a sequence of them') |
|
|
|
|
|
|
|
def migrate_model(self, model): |
|
|
|
print('Migrando %s...' % model.__name__) |
|
|
|
|
|
|
|
model_legado, tabela_legado, campos_pk_legado = \ |
|
|
|
get_estrutura_legado(model) |
|
|
|
|
|
|
|
if len(campos_pk_legado) == 1: |
|
|
|
# a pk no legado tem um único campo |
|
|
|
nome_pk = model_legado._meta.pk.name |
|
|
|
if 'ind_excluido' in {f.name for f in model_legado._meta.fields}: |
|
|
|
# se o model legado tem o campo ind_excluido |
|
|
|
# enumera apenas os não excluídos |
|
|
|
old_records = model_legado.objects.filter(~Q(ind_excluido=1)) |
|
|
|
old_records = model_legado.objects.all() |
|
|
|
old_records = old_records.order_by(nome_pk) |
|
|
|
|
|
|
|
def get_id_do_legado(old): |
|
|
|
return getattr(old, nome_pk) |
|
|
|
else: |
|
|
|
# a pk no legado tem mais de um campo |
|
|
|
old_records = iter_sql_records(tabela_legado) |
|
|
|
get_id_do_legado = None |
|
|
|
|
|
|
|
ajuste_antes_salvar = AJUSTE_ANTES_SALVAR.get(model) |
|
|
|
ajuste_depois_salvar = AJUSTE_DEPOIS_SALVAR.get(model) |
|
|
|
|
|
|
|
# convert old records to new ones |
|
|
|
with transaction.atomic(): |
|
|
|
novos = [] |
|
|
|
sql_delete_legado = '' |
|
|
|
for old in old_records: |
|
|
|
new = model() |
|
|
|
try: |
|
|
|
populate_renamed_fields(new, old) |
|
|
|
if ajuste_antes_salvar: |
|
|
|
ajuste_antes_salvar(new, old) |
|
|
|
except ForeignKeyFaltando as e: |
|
|
|
# tentamos preencher uma FK e o ojeto relacionado |
|
|
|
# não existe |
|
|
|
# então este é um objeo órfão: simplesmente ignoramos |
|
|
|
warn('fk', e.msg, e.dados) |
|
|
|
continue |
|
|
|
else: |
|
|
|
old_records = model_legado.objects.all() |
|
|
|
old_records = old_records.order_by(nome_pk) |
|
|
|
if get_id_do_legado: |
|
|
|
new.id = get_id_do_legado(old) |
|
|
|
|
|
|
|
def get_id_do_legado(old): |
|
|
|
return getattr(old, nome_pk) |
|
|
|
else: |
|
|
|
# a pk no legado tem mais de um campo |
|
|
|
old_records = iter_sql_records(tabela_legado) |
|
|
|
get_id_do_legado = None |
|
|
|
|
|
|
|
ajuste_antes_salvar = AJUSTE_ANTES_SALVAR.get(model) |
|
|
|
ajuste_depois_salvar = AJUSTE_DEPOIS_SALVAR.get(model) |
|
|
|
|
|
|
|
# convert old records to new ones |
|
|
|
with transaction.atomic(): |
|
|
|
novos = [] |
|
|
|
sql_delete_legado = '' |
|
|
|
for old in old_records: |
|
|
|
new = model() |
|
|
|
try: |
|
|
|
self.populate_renamed_fields(new, old) |
|
|
|
if ajuste_antes_salvar: |
|
|
|
ajuste_antes_salvar(new, old) |
|
|
|
except ForeignKeyFaltando as e: |
|
|
|
# tentamos preencher uma FK e o ojeto relacionado |
|
|
|
# não existe |
|
|
|
# então este é um objeo órfão: simplesmente ignoramos |
|
|
|
warn('fk', e.msg, e.dados) |
|
|
|
continue |
|
|
|
else: |
|
|
|
if get_id_do_legado: |
|
|
|
new.id = get_id_do_legado(old) |
|
|
|
|
|
|
|
new.clean() # valida model |
|
|
|
novos.append(new) # guarda para salvar |
|
|
|
|
|
|
|
# acumula deleção do registro no legado |
|
|
|
sql_delete_legado += 'delete from {} where {};\n'.format( |
|
|
|
tabela_legado, |
|
|
|
' and '.join( |
|
|
|
'{} = "{}"'.format(campo, |
|
|
|
getattr(old, campo)) |
|
|
|
for campo in campos_pk_legado)) |
|
|
|
|
|
|
|
# salva novos registros |
|
|
|
with reversion.create_revision(): |
|
|
|
model.objects.bulk_create(novos) |
|
|
|
reversion.set_comment('Objetos criados pela migração') |
|
|
|
new.clean() # valida model |
|
|
|
novos.append(new) # guarda para salvar |
|
|
|
|
|
|
|
if ajuste_depois_salvar: |
|
|
|
ajuste_depois_salvar() |
|
|
|
# acumula deleção do registro no legado |
|
|
|
sql_delete_legado += 'delete from {} where {};\n'.format( |
|
|
|
tabela_legado, |
|
|
|
' and '.join( |
|
|
|
'{} = "{}"'.format(campo, |
|
|
|
getattr(old, campo)) |
|
|
|
for campo in campos_pk_legado)) |
|
|
|
|
|
|
|
# se configuramos ids explicitamente devemos reiniciar a sequence |
|
|
|
if get_id_do_legado: |
|
|
|
last_pk = get_last_pk(model) |
|
|
|
reinicia_sequence(model, last_pk + 1) |
|
|
|
# salva novos registros |
|
|
|
with reversion.create_revision(): |
|
|
|
model.objects.bulk_create(novos) |
|
|
|
reversion.set_comment('Objetos criados pela migração') |
|
|
|
|
|
|
|
# apaga registros migrados do legado |
|
|
|
if sql_delete_legado: |
|
|
|
exec_legado(sql_delete_legado) |
|
|
|
if ajuste_depois_salvar: |
|
|
|
ajuste_depois_salvar() |
|
|
|
|
|
|
|
# se configuramos ids explicitamente devemos reiniciar a sequence |
|
|
|
if get_id_do_legado: |
|
|
|
last_pk = get_last_pk(model) |
|
|
|
reinicia_sequence(model, last_pk + 1) |
|
|
|
|
|
|
|
def migrar_dados(obj=appconfs, interativo=True): |
|
|
|
dm = DataMigrator() |
|
|
|
dm.migrar(obj, interativo) |
|
|
|
# apaga registros migrados do legado |
|
|
|
if sql_delete_legado: |
|
|
|
exec_legado(sql_delete_legado) |
|
|
|
|
|
|
|
|
|
|
|
# MIGRATION_ADJUSTMENTS ##################################################### |
|
|
@ -993,9 +1003,8 @@ def adjust_parlamentar(new, old): |
|
|
|
|
|
|
|
def adjust_participacao(new, old): |
|
|
|
comissao_id, periodo_id = [ |
|
|
|
get_fk_related(Composicao._meta.get_field(name), old, old_field_name) |
|
|
|
for name, old_field_name in (('comissao', 'cod_comissao'), |
|
|
|
('periodo', 'cod_periodo_comp'))] |
|
|
|
get_fk_related(Composicao._meta.get_field(name), old) |
|
|
|
for name in ('comissao', 'periodo')] |
|
|
|
with reversion.create_revision(): |
|
|
|
composicao, _ = Composicao.objects.get_or_create( |
|
|
|
comissao_id=comissao_id, periodo_id=periodo_id) |
|
|
@ -1003,11 +1012,6 @@ def adjust_participacao(new, old): |
|
|
|
new.composicao = composicao |
|
|
|
|
|
|
|
|
|
|
|
def adjust_proposicao_antes_salvar(new, old): |
|
|
|
if new.data_envio: |
|
|
|
new.ano = new.data_envio.year |
|
|
|
|
|
|
|
|
|
|
|
def adjust_normarelacionada(new, old): |
|
|
|
new.tipo_vinculo = TipoVinculoNormaJuridica.objects.get( |
|
|
|
sigla=old.tip_vinculo) |
|
|
@ -1042,14 +1046,14 @@ def adjust_tipoafastamento(new, old): |
|
|
|
new.indicador = 'F' |
|
|
|
|
|
|
|
|
|
|
|
MODEL_TIPO_MATERIA_OU_DOCUMENTO = {'M': TipoMateriaLegislativa, |
|
|
|
'D': TipoDocumento} |
|
|
|
TIPO_MATERIA_OU_TIPO_DOCUMENTO = {'M': TipoMateriaLegislativa, |
|
|
|
'D': TipoDocumento} |
|
|
|
|
|
|
|
|
|
|
|
def adjust_tipoproposicao(new, old): |
|
|
|
"Aponta para o tipo relacionado de matéria ou documento" |
|
|
|
value = old.tip_mat_ou_doc |
|
|
|
model_tipo = MODEL_TIPO_MATERIA_OU_DOCUMENTO[old.ind_mat_ou_doc] |
|
|
|
model_tipo = TIPO_MATERIA_OU_TIPO_DOCUMENTO[old.ind_mat_ou_doc] |
|
|
|
tipo = model_tipo.objects.filter(pk=value) |
|
|
|
if tipo: |
|
|
|
new.tipo_conteudo_related = tipo[0] |
|
|
@ -1060,6 +1064,16 @@ def adjust_tipoproposicao(new, old): |
|
|
|
label={'ind_mat_ou_doc': old.ind_mat_ou_doc}) |
|
|
|
|
|
|
|
|
|
|
|
def adjust_proposicao_antes_salvar(new, old): |
|
|
|
if new.data_envio: |
|
|
|
new.ano = new.data_envio.year |
|
|
|
if old.cod_mat_ou_doc: |
|
|
|
tipo_mat_ou_doc = type(new.tipo.tipo_conteudo_related) |
|
|
|
campo_falso = CAMPOS_FALSOS_PROPOSICAO[tipo_mat_ou_doc] |
|
|
|
new.content_type = content_types[campo_falso.related_model] |
|
|
|
new.object_id = get_fk_related(campo_falso, old) |
|
|
|
|
|
|
|
|
|
|
|
def adjust_statustramitacao(new, old): |
|
|
|
if old.ind_fim_tramitacao: |
|
|
|
new.indicador = 'F' |
|
|
|