mirror of https://github.com/interlegis/sapl.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
8.7 KiB
215 lines
8.7 KiB
import os
|
|
import re
|
|
import shutil
|
|
from glob import glob
|
|
from os.path import join
|
|
|
|
import yaml
|
|
from django.db import transaction
|
|
from image_cropping.fields import ImageCropField
|
|
|
|
from sapl.base.models import CasaLegislativa
|
|
from sapl.comissoes.models import Reuniao
|
|
from sapl.legacy.migracao_dados import EXISTE_REUNIAO_NO_LEGADO, exec_legado
|
|
from sapl.materia.models import (DocumentoAcessorio, MateriaLegislativa,
|
|
Proposicao)
|
|
from sapl.norma.models import NormaJuridica
|
|
from sapl.parlamentares.models import Parlamentar
|
|
from sapl.protocoloadm.models import (DocumentoAcessorioAdministrativo,
|
|
DocumentoAdministrativo)
|
|
from sapl.sessao.models import SessaoPlenaria
|
|
|
|
# MIGRAÇÃO DE DOCUMENTOS ###################################################
|
|
|
|
|
|
DOCS = {
|
|
Parlamentar: [('fotografia', 'parlamentar/fotos/{}_foto_parlamentar')],
|
|
MateriaLegislativa: [('texto_original', 'materia/{}_texto_integral')],
|
|
DocumentoAcessorio: [('arquivo', 'materia/{}')],
|
|
NormaJuridica: [('texto_integral', 'norma_juridica/{}_texto_integral')],
|
|
SessaoPlenaria: [('upload_pauta', 'pauta_sessao/{}_pauta_sessao'),
|
|
('upload_ata', 'ata_sessao/{}_ata_sessao'),
|
|
('upload_anexo', 'anexo_sessao/{}_texto_anexado')],
|
|
Proposicao: [('texto_original', 'proposicao/{}')],
|
|
DocumentoAdministrativo: [('texto_integral',
|
|
'administrativo/{}_texto_integral')],
|
|
DocumentoAcessorioAdministrativo: [('arquivo', 'administrativo/{}')],
|
|
}
|
|
|
|
# acrescenta reuniões (que só existem no sapl 3.0)
|
|
if EXISTE_REUNIAO_NO_LEGADO:
|
|
DOCS[Reuniao] = [('upload_pauta', 'reuniao_comissao/{}_pauta'),
|
|
('upload_ata', 'reuniao_comissao/{}_ata')]
|
|
|
|
|
|
DOCS = {model: [(campo, join('sapl_documentos', origem))
|
|
for campo, origem in campos]
|
|
for model, campos in DOCS.items()}
|
|
|
|
|
|
def mover_documento(repo, origem, destino, ignora_origem_ausente=False):
|
|
origem, destino = [join(repo.working_dir, c) if not os.path.isabs(c) else c
|
|
for c in (origem, destino)]
|
|
if ignora_origem_ausente and not os.path.exists(origem):
|
|
print('Origem ignorada ao mover documento: {}'.format(origem))
|
|
return
|
|
# apaga destino, se houver, e renomeia origem para destino
|
|
if os.path.exists(destino):
|
|
if os.path.isdir(destino):
|
|
shutil.rmtree(destino)
|
|
else:
|
|
os.remove(destino)
|
|
os.makedirs(os.path.dirname(destino), exist_ok=True)
|
|
os.rename(origem, destino)
|
|
|
|
|
|
def migrar_logotipo(repo, casa, propriedades):
|
|
print('.... Migrando logotipo da casa ....')
|
|
campo, origem = 'logotipo', 'sapl_documentos/props_sapl/{}.*'
|
|
# a extensão do logo pode ter sido ajustada pelo tipo real do arquivo
|
|
nome_nas_propriedades = os.path.splitext(propriedades['id_logo'])[0]
|
|
arquivos = glob(
|
|
join(repo.working_dir, origem.format(nome_nas_propriedades)))
|
|
if arquivos:
|
|
assert len(arquivos) == 1, 'Há mais de um logotipo para a casa'
|
|
[logo] = arquivos
|
|
destino = join(CasaLegislativa._meta.get_field(campo).upload_to,
|
|
os.path.basename(logo))
|
|
mover_documento(repo, logo, destino)
|
|
casa.logotipo = destino
|
|
|
|
|
|
def migrar_propriedades_da_casa(repo):
|
|
print('#### Migrando propriedades da casa ####')
|
|
caminho = join(repo.working_dir, 'sapl_documentos/propriedades.yaml')
|
|
repo.git.execute('git annex get'.split() + [caminho])
|
|
with open(caminho, 'r') as arquivo:
|
|
propriedades = yaml.safe_load(arquivo)
|
|
casa = CasaLegislativa.objects.first()
|
|
if not casa:
|
|
casa = CasaLegislativa()
|
|
campos_para_propriedades = [('codigo', 'cod_casa'),
|
|
('nome', 'nom_casa'),
|
|
('sigla', 'sgl_casa'),
|
|
('endereco', 'end_casa'),
|
|
('cep', 'num_cep'),
|
|
('telefone', 'num_tel'),
|
|
('fax', 'num_fax'),
|
|
('endereco_web', 'end_web_casa'),
|
|
('email', 'end_email_casa'),
|
|
('sigla', 'sgl_casa'),
|
|
('informacao_geral', 'txt_informacao_geral')]
|
|
for campo, prop in campos_para_propriedades:
|
|
setattr(casa, campo, propriedades[prop])
|
|
|
|
# localidade
|
|
sql_localidade = '''
|
|
select nom_localidade, sgl_uf from localidade
|
|
where cod_localidade = {}'''.format(propriedades['cod_localidade'])
|
|
[(casa.municipio, casa.uf)] = exec_legado(sql_localidade)
|
|
|
|
# logotipo
|
|
migrar_logotipo(repo, casa, propriedades)
|
|
|
|
casa.save()
|
|
|
|
|
|
def migrar_docs_por_ids(repo, model):
|
|
|
|
for campo, base_origem in DOCS[model]:
|
|
print('#### Migrando {} de {} ####'.format(campo, model.__name__))
|
|
|
|
dir_origem, nome_origem = os.path.split(
|
|
join(repo.working_dir, base_origem))
|
|
nome_origem = nome_origem.format('(\d+)')
|
|
pat = re.compile('^{}\.\w+$'.format(nome_origem))
|
|
if not os.path.isdir(dir_origem):
|
|
print(' >>> O diretório {} não existe! Abortado.'.format(
|
|
dir_origem))
|
|
continue
|
|
|
|
matches = [pat.match(arq) for arq in os.listdir(dir_origem)]
|
|
ids_origens = [(int(m.group(1)),
|
|
join(dir_origem, m.group(0)))
|
|
for m in matches if m]
|
|
objetos = {obj.id: obj for obj in model.objects.all()}
|
|
upload_to = model._meta.get_field(campo).upload_to
|
|
tem_cropping = isinstance(model._meta.get_field(campo), ImageCropField)
|
|
|
|
with transaction.atomic():
|
|
for id, origem in ids_origens:
|
|
# associa documento ao objeto
|
|
obj = objetos.get(id)
|
|
if obj:
|
|
destino = upload_to(obj, os.path.basename(origem))
|
|
mover_documento(repo, origem, destino)
|
|
setattr(obj, campo, destino)
|
|
if tem_cropping:
|
|
# conserta link do git annex (antes do commit)
|
|
# pois o conteúdo das imagens é acessado pelo cropping
|
|
repo.git.add(destino)
|
|
repo.git.execute('git annex fix'.split() + [destino])
|
|
obj.save()
|
|
else:
|
|
msg = ' {} (pk={}) não encontrado para documento em [{}]'
|
|
print(msg.format(model.__name__, id, origem))
|
|
|
|
|
|
def migrar_documentos(repo):
|
|
# aqui supomos que as pastas XSLT e sapl_documentos estão em
|
|
# <repo.working_dir> com o conteúdo exportado do zope
|
|
# Os arquivos das pastas serão (git) MOVIDOS para a nova estrutura!
|
|
#
|
|
# Isto significa que para rodar novamente esta função é preciso
|
|
# restaurar o repo ao estado anterior
|
|
|
|
mover_documento(repo, 'XSLT', 'sapl/public/XSLT',
|
|
ignora_origem_ausente=True)
|
|
|
|
migrar_propriedades_da_casa(repo)
|
|
|
|
# garante que o conteúdo das fotos dos parlamentares esteja presente
|
|
# (necessário para o cropping de imagem)
|
|
if os.path.exists(
|
|
os.path.join(repo.working_dir, 'sapl_documentos/parlamentar')):
|
|
repo.git.execute('git annex get sapl_documentos/parlamentar'.split())
|
|
|
|
for model in DOCS:
|
|
migrar_docs_por_ids(repo, model)
|
|
|
|
# versiona modificações
|
|
repo.git.add('-A', '.')
|
|
repo.index.commit('Migração dos documentos completa')
|
|
|
|
sobrando = [join(dir, file)
|
|
for (dir, _, files) in os.walk(join(repo.working_dir,
|
|
'sapl_documentos'))
|
|
for file in files]
|
|
if sobrando:
|
|
print('\n#### Encerrado ####\n\n'
|
|
'{} documentos sobraram sem ser migrados!!!'.format(
|
|
len(sobrando)))
|
|
|
|
|
|
def corrigir_documentos_para_existentes(repo):
|
|
|
|
for model, campos_bases in DOCS.items():
|
|
if model == Parlamentar:
|
|
continue
|
|
for campo, base_origem in campos_bases:
|
|
print('#### Corrigindo {} de {} ####'.format(campo,
|
|
model.__name__))
|
|
upload_to = model._meta.get_field(campo).upload_to
|
|
for obj in model.objects.all():
|
|
if getattr(obj, campo):
|
|
continue
|
|
dir_upload_to = os.path.join(
|
|
repo.working_dir, upload_to(obj, ''))
|
|
achados = glob(dir_upload_to + '*')
|
|
if achados:
|
|
assert len(achados) == 1, 'Mais de um doc achado'
|
|
[achado] = achados
|
|
destino = upload_to(obj, os.path.basename(achado))
|
|
print('-- {}'.format(destino))
|
|
setattr(obj, campo, destino)
|
|
obj.save()
|
|
|