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.
240 lines
8.0 KiB
240 lines
8.0 KiB
import mimetypes
|
|
import os
|
|
import re
|
|
|
|
import magic
|
|
|
|
from django.db.models.signals import post_delete, post_save
|
|
from sapl.base.models import CasaLegislativa
|
|
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 DocumentoAdministrativo
|
|
from sapl.protocoloadm.models import DocumentoAcessorioAdministrativo
|
|
from sapl.sessao.models import SessaoPlenaria
|
|
from sapl.settings import MEDIA_ROOT
|
|
from sapl.utils import delete_texto, save_texto
|
|
|
|
|
|
# MIGRAÇÃO DE DOCUMENTOS ###################################################
|
|
EXTENSOES = {
|
|
'application/msword': '.doc',
|
|
'application/pdf': '.pdf',
|
|
'application/vnd.oasis.opendocument.text': '.odt',
|
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx', # noqa
|
|
'application/xml': '.xml',
|
|
'application/zip': '.zip',
|
|
'image/jpeg': '.jpeg',
|
|
'image/png': '.png',
|
|
'text/html': '.html',
|
|
'text/rtf': '.rtf',
|
|
'text/x-python': '.py',
|
|
'text/plain': '.ksh',
|
|
'text/plain': '.c',
|
|
'text/plain': '.h',
|
|
'text/plain': '.txt',
|
|
'text/plain': '.bat',
|
|
'text/plain': '.pl',
|
|
'text/plain': '.asc',
|
|
'text/plain': '.text',
|
|
'text/plain': '.pot',
|
|
'text/plain': '.brf',
|
|
'text/plain': '.srt',
|
|
|
|
# sem extensao
|
|
'application/octet-stream': '', # binário
|
|
'inode/x-empty': '', # vazio
|
|
}
|
|
|
|
DOCS = {
|
|
CasaLegislativa: [(
|
|
'logotipo',
|
|
'props_sapl/logo_casa.gif',
|
|
'casa/logotipo/logo_casa.gif')],
|
|
Parlamentar: [(
|
|
'fotografia',
|
|
'parlamentar/fotos/{}_foto_parlamentar',
|
|
'parlamentar/{0}/{0}_foto_parlamentar{1}')],
|
|
MateriaLegislativa: [(
|
|
'texto_original',
|
|
'materia/{}_texto_integral',
|
|
'materialegislativa/{0}/{0}_texto_integral{1}')],
|
|
DocumentoAcessorio: [(
|
|
'arquivo',
|
|
'materia/{}',
|
|
'documentoacessorio/{0}/{0}{1}')],
|
|
NormaJuridica: [(
|
|
'texto_integral',
|
|
'norma_juridica/{}_texto_integral',
|
|
'normajuridica/{0}/{0}_texto_integral{1}')],
|
|
SessaoPlenaria: [
|
|
('upload_ata',
|
|
'ata_sessao/{}_ata_sessao',
|
|
'sessaoplenaria/{0}/ata/{0}_ata_sessao{1}'),
|
|
('upload_anexo',
|
|
'anexo_sessao/{}_texto_anexado',
|
|
'sessaoplenaria/{0}/anexo/{0}_texto_anexado{1}')
|
|
],
|
|
Proposicao: [(
|
|
'texto_original',
|
|
'proposicao/{}',
|
|
'proposicao/{0}/{0}{1}')],
|
|
DocumentoAdministrativo: [(
|
|
'texto_integral',
|
|
'administrativo/{}_texto_integral',
|
|
'documentoadministrativo/{0}/{0}_texto_integral{1}')
|
|
],
|
|
DocumentoAcessorioAdministrativo: [(
|
|
'arquivo',
|
|
'administrativo/{}',
|
|
'documentoacessorioadministrativo/{0}/{0}_acessorio_administrativo{1}')
|
|
],
|
|
}
|
|
|
|
DOCS = {tipo: [(campo,
|
|
os.path.join('sapl_documentos', origem),
|
|
os.path.join('sapl', destino))
|
|
for campo, origem, destino in campos]
|
|
for tipo, campos in DOCS.items()}
|
|
|
|
|
|
def em_media(caminho):
|
|
return os.path.join(MEDIA_ROOT, caminho)
|
|
|
|
|
|
def mover_documento(origem, destino):
|
|
origem, destino = [em_media(c) if not os.path.isabs(c) else c
|
|
for c in (origem, destino)]
|
|
os.makedirs(os.path.dirname(destino), exist_ok=True)
|
|
os.rename(origem, destino)
|
|
|
|
|
|
def get_casa_legislativa():
|
|
casa = CasaLegislativa.objects.first()
|
|
if not casa:
|
|
casa = CasaLegislativa.objects.create(**{k: 'PREENCHER...' for k in [
|
|
'codigo', 'nome', 'sigla', 'endereco', 'cep', 'municipio', 'uf',
|
|
]})
|
|
return casa
|
|
|
|
|
|
def migrar_docs_logo():
|
|
print('#### Migrando logotipo da casa ####')
|
|
[(_, origem, destino)] = DOCS[CasaLegislativa]
|
|
props_sapl = os.path.dirname(origem)
|
|
|
|
# a pasta props_sapl deve conter apenas o origem e metadatas!
|
|
# Edit: Aparentemente há diretório que contém properties ao invés de
|
|
# metadata. O assert foi modificado para essa situação.
|
|
assert set(os.listdir(em_media(props_sapl))) < {
|
|
'logo_casa.gif', '.metadata', 'logo_casa.gif.metadata',
|
|
'.properties', 'logo_casa.gif.properties', '.objects'}
|
|
|
|
mover_documento(origem, destino)
|
|
casa = get_casa_legislativa()
|
|
casa.logotipo = destino
|
|
casa.save()
|
|
|
|
|
|
def get_extensao(caminho):
|
|
mime = magic.from_file(caminho, mime=True)
|
|
try:
|
|
return EXTENSOES[mime]
|
|
except KeyError as e:
|
|
raise Exception('\n'.join([
|
|
'Extensão não conhecida para o arquivo:',
|
|
caminho,
|
|
'E mimetype:',
|
|
mime,
|
|
' Algumas possibilidades são:', ] +
|
|
[" '{}': '{}',".format(mime, ext)
|
|
for ext in mimetypes.guess_all_extensions(mime)] +
|
|
['Atualize o código do dicionário EXTENSOES!']
|
|
)) from e
|
|
|
|
|
|
def migrar_docs_por_ids(tipo):
|
|
for campo, base_origem, base_destino in DOCS[tipo]:
|
|
print('#### Migrando {} de {} ####'.format(campo, tipo.__name__))
|
|
|
|
dir_origem, nome_origem = os.path.split(em_media(base_origem))
|
|
pat = re.compile('^{}$'.format(nome_origem.format('(\d+)')))
|
|
|
|
if not os.path.isdir(dir_origem):
|
|
print(' >>> O diretório {} não existe! Abortado.'.format(
|
|
dir_origem))
|
|
continue
|
|
|
|
for arq in os.listdir(dir_origem):
|
|
match = pat.match(arq)
|
|
if match:
|
|
origem = os.path.join(dir_origem, match.group(0))
|
|
id = match.group(1)
|
|
extensao = get_extensao(origem)
|
|
destino = base_destino.format(id, extensao)
|
|
mover_documento(origem, destino)
|
|
|
|
# associa documento ao objeto
|
|
try:
|
|
obj = tipo.objects.get(pk=id)
|
|
setattr(obj, campo, destino)
|
|
obj.save()
|
|
except tipo.DoesNotExist:
|
|
msg = ' {} (pk={}) não encontrado para documento em [{}]'
|
|
print(msg.format(
|
|
tipo.__name__, id, destino))
|
|
|
|
|
|
def desconecta_sinais_indexacao():
|
|
post_save.disconnect(save_texto, NormaJuridica)
|
|
post_save.disconnect(save_texto, DocumentoAcessorio)
|
|
post_save.disconnect(save_texto, MateriaLegislativa)
|
|
post_delete.disconnect(delete_texto, NormaJuridica)
|
|
post_delete.disconnect(delete_texto, DocumentoAcessorio)
|
|
post_delete.disconnect(delete_texto, MateriaLegislativa)
|
|
|
|
|
|
def conecta_sinais_indexacao():
|
|
post_save.connect(save_texto, NormaJuridica)
|
|
post_save.connect(save_texto, DocumentoAcessorio)
|
|
post_save.connect(save_texto, MateriaLegislativa)
|
|
post_delete.connect(delete_texto, NormaJuridica)
|
|
post_delete.connect(delete_texto, DocumentoAcessorio)
|
|
post_delete.connect(delete_texto, MateriaLegislativa)
|
|
|
|
|
|
def migrar_documentos():
|
|
# precisamos excluir os sinais de post_save e post_delete para não que o
|
|
# computador não trave com a criação de threads desnecessárias
|
|
desconecta_sinais_indexacao()
|
|
|
|
# aqui supomos que uma pasta chamada sapl_documentos está em MEDIA_ROOT
|
|
# com o conteúdo da pasta de mesmo nome do zope
|
|
# Os arquivos da pasta serão movidos para a nova estrutura e a pasta será
|
|
# apagada
|
|
migrar_docs_logo()
|
|
for tipo in [
|
|
Parlamentar,
|
|
MateriaLegislativa,
|
|
DocumentoAcessorio,
|
|
NormaJuridica,
|
|
SessaoPlenaria,
|
|
Proposicao,
|
|
DocumentoAdministrativo,
|
|
DocumentoAcessorioAdministrativo,
|
|
]:
|
|
migrar_docs_por_ids(tipo)
|
|
|
|
sobrando = [os.path.join(dir, file)
|
|
for (dir, _, files) in os.walk(em_media('sapl_documentos'))
|
|
for file in files]
|
|
if sobrando:
|
|
print('\n#### Encerrado ####\n\n'
|
|
'{} documentos sobraram sem ser migrados!!!'.format(
|
|
len(sobrando)))
|
|
for doc in sobrando:
|
|
print(' {}'. format(doc))
|
|
#
|
|
# reconexão dos sinais desligados no inicio da migração de documentos
|
|
conecta_sinais_indexacao()
|
|
|