Browse Source

Merge branch 'migracao' into 3.1.x

pull/2188/head
Marcio Mazza 6 years ago
parent
commit
a1d67c0a35
  1. 1
      requirements/migration-requirements.txt
  2. 12
      sapl/legacy/management/commands/ressucitar_deps.py
  3. 122
      sapl/legacy/migracao_dados.py
  4. 19
      sapl/legacy/scripts/exporta_zope/exporta_zope.py
  5. 2
      sapl/legacy/scripts/recria_um_db_postgres.sh
  6. 343
      sapl/legacy/scripts/ressucita_dependencias.py
  7. 25
      sapl/legacy/test_renames.py

1
requirements/migration-requirements.txt

@ -2,3 +2,4 @@
GitPython
mysqlclient==1.3.12
pyaml
texttable

12
sapl/legacy/management/commands/ressucitar_deps.py

@ -0,0 +1,12 @@
from django.core.management.base import BaseCommand
from sapl.legacy.scripts.ressucita_dependencias import adiciona_ressucitar
class Command(BaseCommand):
help = 'Ressucita dependências apagadas ' \
'que são necessárias para migrar outros registros'
def handle(self, *args, **options):
adiciona_ressucitar()

122
sapl/legacy/migracao_dados.py

@ -34,8 +34,9 @@ from sapl.legacy.models import NormaJuridica as OldNormaJuridica
from sapl.legacy.models import TipoNumeracaoProtocolo
from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO,
NOME_BANCO_LEGADO)
from sapl.materia.models import (AcompanhamentoMateria, MateriaLegislativa,
Proposicao, StatusTramitacao, TipoDocumento,
from sapl.materia.models import (AcompanhamentoMateria, DocumentoAcessorio,
MateriaLegislativa, Proposicao,
StatusTramitacao, TipoDocumento,
TipoMateriaLegislativa, TipoProposicao,
Tramitacao)
from sapl.norma.models import (AssuntoNorma, NormaJuridica, NormaRelacionada,
@ -157,7 +158,7 @@ class CampoVirtual(namedtuple('CampoVirtual', 'model related_model')):
CAMPOS_VIRTUAIS_PROPOSICAO = {
TipoMateriaLegislativa: CampoVirtual(Proposicao, MateriaLegislativa),
TipoDocumento: CampoVirtual(Proposicao, DocumentoAdministrativo)
TipoDocumento: CampoVirtual(Proposicao, DocumentoAcessorio)
}
for campo_virtual in CAMPOS_VIRTUAIS_PROPOSICAO.values():
campos_novos_para_antigos[campo_virtual] = 'cod_mat_ou_doc'
@ -215,6 +216,13 @@ def get_estrutura_legado(model):
return model_legado, tabela_legado, campos_pk_legado
def com_aspas_se_necessario(valor):
if isinstance(valor, int):
return valor
else:
return '"{}"'.format(valor)
class ForeignKeyFaltando(ObjectDoesNotExist):
'Uma FK aponta para um registro inexistente'
@ -232,7 +240,9 @@ class ForeignKeyFaltando(ObjectDoesNotExist):
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()]))
' and '.join([
'{} = {}'.format(k, com_aspas_se_necessario(v))
for k, v in pk.items()]))
return OrderedDict((('campo', campo),
('valor', self.valor),
('tabela', tabela),
@ -366,8 +376,8 @@ def reverte_exclusao_de_autores_referenciados_no_legado():
where ind_excluido <> 1)
'''.format(parlamentar=tabela, cod_parlamentar=fk)
if autores_referenciados:
sql += ' and cod_autor not in {}'.format(
tuple(autores_referenciados))
sql += ' and cod_autor not in ({})'.format(
', '.join(map(str, autores_referenciados)))
exec_legado(sql)
@ -502,6 +512,9 @@ def checa_registros_votacao_ambiguos_e_remove_nao_usados():
# interrompe migração se houver registros ambíguos
ambiguos = ordem.intersection(expediente)
como_resolver = get_como_resolver_registro_votacao_ambiguo()
ambiguos = ambiguos - set(como_resolver)
if ambiguos:
warn('registro_votacao_ambiguos',
'Existe(m) RegistroVotacao ambíguo(s): {cod_votacao}',
@ -527,6 +540,9 @@ PROPAGACOES_DE_EXCLUSAO = [
('parlamentar', 'composicao_mesa', 'cod_parlamentar'),
('parlamentar', 'composicao_comissao', 'cod_parlamentar'),
# coligacao
('coligacao', 'composicao_coligacao', 'cod_coligacao'),
# comissao
('comissao', 'composicao_comissao', 'cod_comissao'),
('periodo_comp_comissao', 'composicao_comissao', 'cod_periodo_comp'),
@ -535,6 +551,9 @@ PROPAGACOES_DE_EXCLUSAO = [
('sessao_plenaria', 'ordem_dia', 'cod_sessao_plen'),
('sessao_plenaria', 'expediente_materia', 'cod_sessao_plen'),
('sessao_plenaria', 'expediente_sessao_plenaria', 'cod_sessao_plen'),
('sessao_plenaria', 'sessao_plenaria_presenca', 'cod_sessao_plen'),
('sessao_plenaria', 'ordem_dia_presenca', 'cod_sessao_plen'),
# as consultas no código do sapl 2.5
# votacao_ordem_dia_obter_zsql e votacao_expediente_materia_obter_zsql
# indicam que os registros de votação de matérias excluídas não são
@ -551,6 +570,11 @@ PROPAGACOES_DE_EXCLUSAO = [
('materia_legislativa', 'documento_acessorio', 'cod_materia'),
('materia_legislativa', 'numeracao', 'cod_materia'),
('materia_legislativa', 'expediente_materia', 'cod_materia'),
('materia_legislativa', 'ordem_dia', 'cod_materia'),
('materia_legislativa', 'acomp_materia', 'cod_materia'),
('materia_legislativa', 'despacho_inicial', 'cod_materia'),
('materia_legislativa', 'legislacao_citada', 'cod_materia'),
('materia_legislativa', 'relatoria', 'cod_materia'),
# norma
('norma_juridica', 'vinculo_norma_juridica', 'cod_norma_referente'),
@ -576,9 +600,19 @@ def propaga_exclusoes(propagacoes):
exec_legado(sql)
def uniformiza_banco():
exec_legado('SET SESSION sql_mode = "";') # desliga checagens do mysql
def corrige_unidades_tramitacao_destino_vazia_como_anterior():
"""Se uma unidade de tramitação estiver vazia no legado a configura
como a anterior"""
for tabela_tramitacao in ['tramitacao', 'tramitacao_administrativo']:
exec_legado('''
update {}
set cod_unid_tram_dest = cod_unid_tram_local
where cod_unid_tram_dest is null;
'''.format(tabela_tramitacao))
def uniformiza_banco():
propaga_exclusoes(PROPAGACOES_DE_EXCLUSAO)
checa_registros_votacao_ambiguos_e_remove_nao_usados()
propaga_exclusoes(PROPAGACOES_DE_EXCLUSAO_REGISTROS_VOTACAO)
@ -669,6 +703,7 @@ sessao_plenaria_presenca | dat_sessao = NULL | dat_sessao = 0
reverte_exclusao_de_autores_referenciados_no_legado()
anula_tipos_origem_externa_invalidos()
corrige_unidades_tramitacao_destino_vazia_como_anterior()
class Record:
@ -728,19 +763,21 @@ def fill_vinculo_norma_juridica():
def fill_dados_basicos():
# Ajusta sequencia numérica e cria base.AppConfig
letra = 'A'
try:
# Ajusta sequencia numérica de protocolo e cria base.AppConfig
if (TipoNumeracaoProtocolo._meta.db_table in TABELAS_LEGADO
and TipoNumeracaoProtocolo.objects.exists()):
# se este banco legado tem a a configuração de numeração de protocolo
tipo = TipoNumeracaoProtocolo.objects.latest('dat_inicial_protocolo')
if 'POR ANO' in tipo.des_numeracao_protocolo:
letra = 'A'
elif 'POR LEGISLATURA' in tipo.des_numeracao_protocolo:
letra = 'L'
elif 'CONSECUTIVO' in tipo.des_numeracao_protocolo:
letra = 'U'
except Exception as e:
pass
appconf = AppConf(sequencia_numeracao=letra)
descricao = tipo.des_numeracao_protocolo
if 'POR ANO' in descricao:
sequencia_numeracao = 'A'
elif 'POR LEGISLATURA' in descricao:
sequencia_numeracao = 'L'
elif 'CONSECUTIVO' in descricao:
sequencia_numeracao = 'U'
else:
sequencia_numeracao = 'A'
appconf = AppConf(sequencia_numeracao=sequencia_numeracao)
appconf.save()
@ -804,6 +841,11 @@ def roda_comando_shell(cmd):
assert res == 0, 'O comando falhou: {}'.format(cmd)
def get_arquivo_ajustes_pre_migracao():
return DIR_DADOS_MIGRACAO.child(
'ajustes_pre_migracao', '{}.sql'.format(sigla_casa))
def migrar_dados(apagar_do_legado=False):
try:
ocorrencias.clear()
@ -817,9 +859,12 @@ def migrar_dados(apagar_do_legado=False):
normaliza_dump_mysql(arq_dump)
roda_comando_shell('mysql -uroot < {}'.format(arq_dump))
# desliga checagens do mysql
# e possibilita inserir valor zero em campos de autoincremento
exec_legado('SET SESSION sql_mode = "NO_AUTO_VALUE_ON_ZERO";')
# executa ajustes pré-migração, se existirem
arq_ajustes_pre_migracao = DIR_DADOS_MIGRACAO.child(
'ajustes_pre_migracao', '{}.sql'.format(sigla_casa))
arq_ajustes_pre_migracao = get_arquivo_ajustes_pre_migracao()
if arq_ajustes_pre_migracao.exists():
exec_legado(arq_ajustes_pre_migracao.read_file())
@ -845,9 +890,11 @@ def migrar_dados(apagar_do_legado=False):
ocorrencias.default_factory = None
arq_ocorrencias = Path(REPO.working_dir, 'ocorrencias.yaml')
with open(arq_ocorrencias, 'w') as arq:
pyaml.dump(ocorrencias, arq, vspacing=1)
pyaml.dump(ocorrencias, arq, vspacing=1, width=200)
REPO.git.add([arq_ocorrencias.name])
info('Ocorrências salvas em\n {}'.format(arq_ocorrencias))
if not ocorrencias:
info('NÃO HOUVE OCORRÊNCIAS !!!')
# recria tipos de autor padrão que não foram criados pela migração
cria_models_tipo_autor()
@ -880,7 +927,7 @@ def get_models_a_migrar():
[TipoMateriaLegislativa, TipoDocumento])
assert models.index(TipoProposicao) < models.index(Proposicao)
move_para_depois_de(models, Proposicao,
[MateriaLegislativa, DocumentoAdministrativo])
[MateriaLegislativa, DocumentoAcessorio])
return models
@ -1014,9 +1061,16 @@ pois não existe protocolo no sistema com este número no ano {ano_original}.
'ano_original': ano_original,
'nota': nota})
else:
# Se não achamos mesmo no ano anteriro
# colocamos no número externo
new.numero_externo = old.num_protocolo
nota = NOTA_DOCADM + '''
Não existe no sistema nenhum protocolo com estes dados
e portanto nenhum protocolo foi vinculado a este documento.'''
e portanto nenhum protocolo foi vinculado a este documento.
Colocamos então o número de protocolo no campo "número externo".
'''
nota = nota.format(
num_protocolo=old.num_protocolo,
ano_original=ano_original)
@ -1106,12 +1160,14 @@ def adjust_protocolo_antes_salvar(new, old):
{'cod_protocolo': old.cod_protocolo})
ARQUIVO_COMO_RESOLVER_REGISTRO_VOTACAO_AMBIGUO = \
'como_resolver_registro_votacao_ambiguo.yaml'
def get_arquivo_resolve_registro_votacao():
return DIR_DADOS_MIGRACAO.child(
'ajustes_pre_migracao',
'{}_resolve_registro_votacao_ambiguo.yaml'.format(sigla_casa))
def get_como_resolver_registro_votacao_ambiguo():
path = DIR_REPO.child(ARQUIVO_COMO_RESOLVER_REGISTRO_VOTACAO_AMBIGUO)
path = get_arquivo_resolve_registro_votacao()
if path.exists():
return yaml.load(path.read_file())
else:
@ -1140,7 +1196,7 @@ def adjust_registrovotacao_antes_salvar(new, old):
raise Exception('''
Registro de Votação ambíguo: {}
Resolva criando o arquivo {}'''.format(
new.id, ARQUIVO_COMO_RESOLVER_REGISTRO_VOTACAO_AMBIGUO))
new.id, get_arquivo_resolve_registro_votacao()))
def adjust_tipoafastamento(new, old):
@ -1160,7 +1216,7 @@ def set_generic_fk(new, campo_virtual, old):
def adjust_tipoproposicao(new, old):
"Aponta para o tipo relacionado de matéria ou documento"
if old.tip_mat_ou_doc:
if old.tip_mat_ou_doc is not None:
campo_virtual = CAMPOS_VIRTUAIS_TIPO_PROPOSICAO[old.ind_mat_ou_doc]
set_generic_fk(new, campo_virtual, old)
@ -1168,7 +1224,7 @@ def adjust_tipoproposicao(new, old):
def adjust_proposicao_antes_salvar(new, old):
if new.data_envio:
new.ano = new.data_envio.year
if old.cod_mat_ou_doc:
if old.cod_mat_ou_doc is not None:
tipo_mat_ou_doc = type(new.tipo.tipo_conteudo_related)
campo_virtual = CAMPOS_VIRTUAIS_PROPOSICAO[tipo_mat_ou_doc]
set_generic_fk(new, campo_virtual, old)
@ -1279,7 +1335,11 @@ def adjust_tiporesultadovotacao(new, old):
new.natureza = TipoResultadoVotacao.NATUREZA_CHOICES.aprovado
elif 'rejeita' in new.nome.lower():
new.natureza = TipoResultadoVotacao.NATUREZA_CHOICES.rejeitado
elif 'retirado' in new.nome.lower():
new.natureza = TipoResultadoVotacao.NATUREZA_CHOICES.rejeitado
else:
if new.nome != 'DESCONHECIDO':
# ignoramos a natureza de item criado pela migração
warn('natureza_desconhecida_tipo_resultadovotacao',
'Não foi possível identificar a natureza do '
'tipo de resultado de votação [{pk}: "{nome}"]',

19
sapl/legacy/scripts/exporta_zope/exporta_zope.py

@ -27,6 +27,7 @@ from ZODB.POSException import POSKeyError
from variaveis_comuns import DIR_DADOS_MIGRACAO, TAG_ZOPE
EXTENSOES = {
# docs
'application/msword': '.doc',
'application/pdf': '.pdf',
'application/vnd.oasis.opendocument.text': '.odt',
@ -36,12 +37,25 @@ EXTENSOES = {
'application/vnd.ms-powerpoint': '.ppt',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx', # noqa
'application/vnd.oasis.opendocument.spreadsheet': '.ods',
'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx', # noqa
'application/vnd.oasis.opendocument.graphics': '.odg',
# incertos... associamos a extensão mais provável
'application/vnd.ms-office': '.doc',
'text/x-c++': '.cpp',
# outros
'application/xml': '.xml',
'text/xml': '.xml',
'application/zip': '.zip',
'application/x-rar': '.rar',
'application/x-dosexec': '.exe',
'message/rfc822': '.mht',
'text/richtext': '.rtx',
'application/gzip': '.gz',
'image/vnd.dwg': '*.dwg',
# media
'image/jpeg': '.jpeg',
'image/png': '.png',
'image/gif': '.gif',
@ -58,9 +72,8 @@ EXTENSOES = {
'image/x-ms-bmp': '.bmp',
'video/x-ms-asf': '.asf',
'audio/mpeg': '.mp3',
# TODO rever...
'text/richtext': '.rtf',
'video/x-flv': '.flv',
'video/quicktime': '.mov',
# sem extensao
'application/octet-stream': '', # binário

2
sapl/legacy/scripts/recria_um_db_postgres.sh

@ -1,6 +1,8 @@
# (Re)cria um db postgres
# uso: recria_um_db_postgres <NOME DO BANCO>
set -e # Exit immediately if a command exits with a non-zero status
echo "Database $1"
sudo -u postgres psql -c "drop DATABASE if exists $1"
sudo -u postgres psql -c "CREATE DATABASE $1 WITH OWNER = sapl ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'pt_BR.UTF-8' LC_CTYPE = 'pt_BR.UTF-8' CONNECTION LIMIT = -1 TEMPLATE template0;"

343
sapl/legacy/scripts/ressucita_dependencias.py

@ -1,43 +1,206 @@
from textwrap import dedent
import texttable
import yaml
from unipath import Path
from sapl.legacy.migracao_dados import DIR_REPO, exec_legado
fks_legado = '''
autor cod_parlamentar parlamentar
autor tip_autor tipo_autor
autoria cod_autor autor
expediente_materia cod_materia materia_legislativa
ordem_dia cod_materia materia_legislativa
legislacao_citada cod_norma norma_juridica
oradores cod_parlamentar parlamentar
oradores_expediente cod_parlamentar parlamentar
ordem_dia_presenca cod_parlamentar parlamentar
protocolo cod_autor autor
registro_votacao tip_resultado_votacao tipo_resultado_votacao
registro_votacao_parlamentar cod_parlamentar parlamentar
registro_votacao_parlamentar cod_votacao registro_votacao
sessao_legislativa num_legislatura legislatura
sessao_plenaria_presenca cod_parlamentar parlamentar
from sapl.legacy.migracao_dados import (PROPAGACOES_DE_EXCLUSAO,
campos_novos_para_antigos, exec_legado,
get_arquivo_ajustes_pre_migracao,
models_novos_para_antigos)
from sapl.legacy_migration_settings import (DIR_DADOS_MIGRACAO, DIR_REPO,
NOME_BANCO_LEGADO)
def stripsplit(ll):
return [l.split() for l in ll.strip().splitlines()]
def _tab_legado(model):
return models_novos_para_antigos[model]._meta.db_table
fks_legado = {
(_tab_legado(m), campos_novos_para_antigos[f]): _tab_legado(f.related_model) # noqa
for m in models_novos_para_antigos
for f in m._meta.fields
if f in campos_novos_para_antigos and f.related_model}
# acrescenta mapeamentos que não existem em campos_novos_para_antigos
for tabela_origem, campo, tabela_destino in [
['autor', 'cod_parlamentar', 'parlamentar'],
['autor', 'cod_comissao', 'comissao'],
['autor', 'cod_partido', 'partido']]:
fks_legado[(tabela_origem, campo)] = tabela_destino
urls = '''
autor /sistema/autor
cargo_comissao /sistema/comissao/cargo
legislatura /sistema/parlamentar/legislatura
materia_legislativa /materia
norma_juridica /norma
parlamentar /parlamentar
sessao_legislativa /sistema/mesa-diretora/sessao-legislativa
sessao_plenaria /sessao
status_tramitacao /sistema/materia/status-tramitacao
tipo_autor /sistema/autor/tipo
tipo_expediente /sistema/sessao-plenaria/tipo-expediente
tipo_proposicao /sistema/proposicao/tipo
tipo_resultado_votacao /sistema/sessao-plenaria/tipo-resultado-votacao
unidade_tramitacao /sistema/materia/unidade-tramitacao
tipo_documento /sistema/materia/tipo-documento
orgao /sistema/materia/orgao
tipo_sessao_plenaria /sistema/sessao-plenaria/tipo
cargo_mesa /sistema/mesa-diretora/cargo-mesa
documento_administrativo /docadm
tipo_materia_legislativa /sistema/materia/tipo
tipo_norma_juridica /sistema/norma/tipo
comissao /comissao
registro_votacao ?????????
'''
fks_legado = [l.split() for l in fks_legado.strip().splitlines()]
fks_legado = {(o, c): t for (o, c, t) in fks_legado}
urls = dict(stripsplit(urls))
def get_tabela_campo_tipo_proposicao(tip_proposicao):
[(ind_mat_ou_doc,)] = exec_legado('''
select ind_mat_ou_doc from tipo_proposicao where tip_proposicao = {};
'''.format(tip_proposicao))
if ind_mat_ou_doc == 'M':
return 'tipo_materia_legislativa', 'tip_materia'
elif ind_mat_ou_doc == 'D':
return 'tipo_documento', 'tip_documento'
else:
raise(Exception('ind_mat_ou_doc inválido'))
CAMPOS_ORIGEM_PARA_ALVO = {
'cod_unid_tram_dest': 'cod_unid_tramitacao',
'cod_unid_tram_local': 'cod_unid_tramitacao',
'tip_id_basica': 'tip_materia',
}
def get_excluido(fk):
campo, valor, tabela_origem = [fk[k] for k in ('campo', 'valor', 'tabela')]
tabela_origem, campo, valor = [fk[k] for k in ('tabela', 'campo', 'valor')]
if tabela_origem == 'tipo_proposicao':
tip_proposicao = fk['pk']['tip_proposicao']
tabela_alvo, campo = get_tabela_campo_tipo_proposicao(tip_proposicao)
elif tabela_origem == 'proposicao' and campo == 'cod_mat_ou_doc':
[(ind_mat_ou_doc,)] = exec_legado('''
select ind_mat_ou_doc from
proposicao p inner join tipo_proposicao t
on p.tip_proposicao = t.tip_proposicao
where cod_proposicao = {};
'''.format(fk['pk']['cod_proposicao']))
if ind_mat_ou_doc == 'M':
tabela_alvo, campo = 'materia_legislativa', 'cod_materia'
elif ind_mat_ou_doc == 'D':
tabela_alvo, campo = 'documento_acessorio', 'cod_documento'
else:
raise(Exception('ind_mat_ou_doc inválido'))
else:
tabela_alvo = fks_legado[(tabela_origem, campo)]
# troca nome de campo pelo correspondente na tabela alvo
campo = CAMPOS_ORIGEM_PARA_ALVO.get(campo, campo)
sql = 'select ind_excluido, t.* from {} t where {} = {}'.format(
tabela_alvo, campo, valor)
res = list(exec_legado(sql))
return tabela_origem, campo, valor, tabela_alvo, res
def get_dependencias_a_ressucitar():
def get_desc_materia(cod_materia):
sql = '''
select t.sgl_tipo_materia, t.des_tipo_materia,
m.num_ident_basica, m.ano_ident_basica
from materia_legislativa m inner join tipo_materia_legislativa t
on m.tip_id_basica = t.tip_materia
where cod_materia = {};
'''.format(cod_materia)
return list(exec_legado(sql))[0]
def get_link_proposicao(cod_proposicao, slug):
url_base = get_url(slug)
return 'http://{}/cadastros/proposicao/proposicao_mostrar_proc?cod_proposicao={}'.format( # noqa
url_base, cod_proposicao)
def get_apaga_materias_de_proposicoes(fks, slug):
refs_materias = [['id proposicao', 'sigla tipo matéria',
'tipo matéria', 'número matéria', 'ano matéria']]
sqls = []
cods_proposicoes = []
for fk in fks:
cod_proposicao = fk['pk']['cod_proposicao']
cods_proposicoes.append(cod_proposicao)
assert fk['campo'] == 'cod_materia'
up = 'update proposicao set cod_materia = NULL where cod_proposicao = {};' # noqa
refs_materias.append(
[cod_proposicao, *get_desc_materia(fk['valor'])])
sqls.append(up.format(cod_proposicao))
table = texttable.Texttable()
table.set_cols_width([10, 10, 50, 10, 10])
table.set_deco(table.VLINES | table.HEADER)
table.add_rows(refs_materias)
links = '\n'.join([get_link_proposicao(p, slug)
for p in cods_proposicoes])
sqls = '\n'.join(sqls)
if not sqls:
return ''
else:
return '''
/* REFERÊNCIAS A MATÉRIAS APAGADAS DE PROPOSIÇÕES
ATENÇÃO
As seguintes proposições apontaram no passado para matérias
e esses apontamentos foram em algum momento retirados.
Elas foram migradas da forma com estão agora: sem apontar para nenhuma matéria.
Entretanto, talvez você deseje rever esses apontamentos.
Segue então uma lista dos apontamentos anteriores que detectamos.
{}
Para facilitar sua conferência, seguem os links para as proposições envolvidas:
{}
*/
{}
'''.format(table.draw(), links, sqls)
def get_dependencias_a_ressucitar(slug):
ocorrencias = yaml.load(
Path(DIR_REPO.child('ocorrencias.yaml').read_file()))
fks = ocorrencias['fk']
excluidos = [get_excluido(fk) for fk in fks]
fks_faltando = ocorrencias.get('fk')
if not fks_faltando:
return [], [], []
proposicoes_para_materia = [
fk for fk in fks_faltando
if fk['tabela'] == 'proposicao' and fk['campo'] == 'cod_materia']
preambulo = get_apaga_materias_de_proposicoes(
proposicoes_para_materia, slug)
propagacoes = {(o, c) for t, o, c in PROPAGACOES_DE_EXCLUSAO}
fks_faltando = [fk for fk in fks_faltando
if fk not in proposicoes_para_materia
and (fk['tabela'], fk['campo']) not in propagacoes]
excluidos = [get_excluido(fk) for fk in fks_faltando]
desexcluir, criar = [
set([(tabela_alvo, campo, valor)
for tabela_origem, campo, valor, tabela_alvo, res in excluidos
@ -48,12 +211,132 @@ def get_dependencias_a_ressucitar():
# o registro não existe
lambda res: not res
)]
return desexcluir, criar
return preambulo, desexcluir, criar
SQLS_CRIACAO = [
('tipo_proposicao', '''
insert into tipo_materia_legislativa (
tip_materia, sgl_tipo_materia, des_tipo_materia, ind_num_automatica,
quorum_minimo_votacao, ind_excluido)
values (0, "DESC", "DESCONHECIDO", 0, 0, 0);
insert into tipo_proposicao (
tip_proposicao, des_tipo_proposicao, ind_mat_ou_doc, tip_mat_ou_doc,
nom_modelo, ind_excluido)
values ({}, "DESCONHECIDO", "M", 0, "DESCONHECIDO", 0);
''', ['tipo_materia_legislativa', 0]
),
('tipo_resultado_votacao', '''
insert into tipo_resultado_votacao (
tip_resultado_votacao, nom_resultado, ind_excluido)
values ({}, "DESCONHECIDO", 0);
'''),
('tipo_autor', '''
insert into tipo_autor (tip_autor, des_tipo_autor, ind_excluido)
values ({}, "DESCONHECIDO", 0);
'''),
('unidade_tramitacao', '''
insert into unidade_tramitacao (cod_unid_tramitacao, cod_comissao, cod_orgao, cod_parlamentar, ind_excluido)
values ({}, NULL, NULL, NULL, 0);
'''),
]
SQLS_CRIACAO = {k: (dedent(sql.strip()), extras)
for k, sql, *extras in SQLS_CRIACAO}
def criar_sessao_legislativa(campo, valor):
assert campo == 'cod_sessao_leg'
[(num_legislatura,)] = exec_legado(
'select min(num_legislatura) from legislatura where ind_excluido <> 1')
return '''
insert into sessao_legislativa (
cod_sessao_leg, num_legislatura, num_sessao_leg, tip_sessao_leg,
dat_inicio, dat_fim, dat_inicio_intervalo, dat_fim_intervalo,
ind_excluido) values ({}, {}, 0, "O",
"1900-01-01", "1900-01-02", "1900-01-01", "1900-01-02", 0);
'''.format(valor, num_legislatura)
def get_sqls_desexcluir_criar(desexcluir, criar):
sqls_desexcluir = [
'update {} set ind_excluido = 0 where {} = {};'.format(
def get_link(tabela_alvo, valor, slug):
url_base = get_url(slug)
return 'http://{}{}/{}'.format(url_base, urls[tabela_alvo], valor)
def get_sql_desexcluir(tabela_alvo, campo, valor, slug):
sql = 'update {} set ind_excluido = 0 where {} = {};'.format(
tabela_alvo, campo, valor)
for tabela_alvo, campo, valor in desexcluir]
return '\n'.join(sqls_desexcluir)
return sql, [get_link(tabela_alvo, valor, slug)]
def get_sql_criar(tabela_alvo, campo, valor, slug):
if tabela_alvo == 'sessao_legislativa':
sql = criar_sessao_legislativa(campo, valor)
extras = []
else:
sql, extras = SQLS_CRIACAO[tabela_alvo]
sql = sql.format(valor)
links = [get_link(tabela_alvo, valor, slug)]
for tabela_extra, valor_extra in extras:
links.insert(0, get_link(tabela_extra, valor_extra, slug))
return sql, links
TEMPLATE_RESSUCITADOS = '''{}
/* RESSUCITADOS
SOBRE REGISTROS QUE ESTAVAM APAGADOS E FORAM RESTAURADOS
Os registros que listamos a seguir estavam excluídos (ou simplesmente não existiam) no sistema antigo e precisaram ser restaurados (ou criados) para completarmos a migração. Foi necessário fazer isso pois outros registros ativos no sistema apontam para eles.
Vocês agora podem decidir mantê-los, ajustá-los ou excluí-los. Segue a lista:
{}
Se a opção for por excluir um desses registros novamente, note que será possível fazer isso quando nada mais no sistema fizer referência a ele.
Ao tentar excluir um registro usado em outras partes do sistema, você verá uma lista dos itens que apontam para ele de alguma forma. Para conseguir excluir você deve editar cada dos dos itens dependentes lista mostrada, retirando ou trocando a referência ao que deseja excluir.
*/
{}
'''
def get_url(slug):
return 'sapl.{}.leg.br'.format(slug.replace('-', '.'))
def get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug):
sqls_links = [get_sql(*(args + (slug,)))
for itens, get_sql in ((desexcluir, get_sql_desexcluir),
(criar, get_sql_criar))
for args in itens]
if not sqls_links:
return ''
else:
sqls, links = zip(*sqls_links)
links = [l for ll in links for l in ll] # flatten
sqls, links = ['\n'.join(sorted(s)) for s in [sqls, links]]
return TEMPLATE_RESSUCITADOS.format(preambulo, links, sqls)
def get_ressucitar(slug):
preambulo, desexcluir, criar = get_dependencias_a_ressucitar(slug)
return get_sqls_desexcluir_criar(preambulo, desexcluir, criar, slug)
def get_slug():
arq = DIR_DADOS_MIGRACAO.child('siglas_para_slugs.yaml')
with open(arq, 'r') as arq:
siglas_para_slugs = yaml.load(arq)
sigla = NOME_BANCO_LEGADO[-3:]
return siglas_para_slugs[sigla]
def adiciona_ressucitar():
sqls = get_ressucitar(get_slug())
if sqls.strip():
arq_ajustes_pre_migracao = get_arquivo_ajustes_pre_migracao()
conteudo = arq_ajustes_pre_migracao.read_file()
arq_ajustes_pre_migracao.write_file('{}\n{}'.format(conteudo, sqls))

25
sapl/legacy/test_renames.py

@ -5,12 +5,13 @@ from sapl.base.models import AppConfig, Autor, CasaLegislativa, TipoAutor
from sapl.comissoes.models import \
DocumentoAcessorio as DocumentoAcessorioComissoes
from sapl.comissoes.models import Comissao, Composicao, Participacao, Reuniao
from sapl.legacy.migracao_dados import appconfs, get_renames, legacy_app
from sapl.materia.models import (AcompanhamentoMateria, DocumentoAcessorio,
MateriaLegislativa, Proposicao,
TipoMateriaLegislativa, TipoProposicao,
Tramitacao)
from sapl.norma.models import (NormaJuridica, NormaRelacionada,
TipoVinculoNormaJuridica)
from sapl.norma.models import (AnexoNormaJuridica, NormaJuridica,
NormaRelacionada, TipoVinculoNormaJuridica)
from sapl.parlamentares.models import (Frente, Mandato, Parlamentar, Partido,
TipoAfastamento, Votante)
from sapl.protocoloadm.models import DocumentoAdministrativo
@ -20,14 +21,12 @@ from sapl.sessao.models import (Bancada, Bloco, CargoBancada,
SessaoPlenaria, TipoResultadoVotacao,
VotoParlamentar)
from .migracao_dados import appconfs, get_renames, legacy_app
RENAMING_IGNORED_MODELS = [
Votante, Frente, Bancada, CargoBancada, Bloco, # parlamentares
Votante, Frente, Bancada, Bloco, Votante, # parlamentares
Composicao, Reuniao, DocumentoAcessorioComissoes, # commissoes
AppConfig, CasaLegislativa, # base
ResumoOrdenacao, # sessao
TipoVinculoNormaJuridica, # norma
CargoBancada, ResumoOrdenacao, # sessao
AnexoNormaJuridica, TipoVinculoNormaJuridica, # norma
]
@ -49,15 +48,16 @@ RENAMING_IGNORED_FIELDS = [
'upload_ata',
'upload_anexo',
'upload_pauta'}),
(ExpedienteMateria, {'votacao_aberta'}),
(OrdemDia, {'votacao_aberta'}),
(ExpedienteMateria, {'votacao_aberta', 'registro_aberto'}),
(OrdemDia, {'votacao_aberta', 'registro_aberto'}),
(NormaJuridica, {'texto_integral', 'data_ultima_atualizacao', 'assuntos'}),
(Parlamentar, {
'uf_residencia', 'municipio_residencia', 'cropping', 'fotografia'}),
(Partido, {'logo_partido'}),
(Partido, {'logo_partido', 'observacao'}),
(MateriaLegislativa, {
'autores', 'anexadas', 'data_ultima_atualizacao', 'texto_original'}),
(DocumentoAdministrativo, {'protocolo', 'texto_integral'}),
(DocumentoAdministrativo, {
'protocolo', 'numero_externo', 'texto_integral'}),
(Mandato, {'titular', 'data_fim_mandato', 'data_inicio_mandato'}),
(TipoMateriaLegislativa, {'sequencia_numeracao'}),
(TipoAutor, {'content_type'}),
@ -71,6 +71,9 @@ RENAMING_IGNORED_FIELDS = [
(AcompanhamentoMateria, {'confirmado', 'data_cadastro', 'usuario'}),
(Autor, {'user', 'content_type', 'object_id', 'autor_related'}),
(Comissao, {'ativa'}),
(Reuniao, {'url_audio', 'url_video', 'local_reuniao', 'upload_anexo',
'periodo', 'upload_pauta', 'tema', 'hora_fim', 'upload_ata',
'nome', 'hora_inicio'})
]

Loading…
Cancel
Save