mirror of https://github.com/interlegis/sapl.git
committed by
GitHub
252 changed files with 5416 additions and 2994 deletions
@ -1,17 +1,17 @@ |
|||||
#!/bin/bash |
#!/bin/bash |
||||
|
|
||||
# Check if there's some debug breakpoint in codebase |
# Verifica se um breakpoint foi esquecido no código |
||||
me=`basename "$0"` |
me=`basename "$0"` |
||||
stmts=`grep --exclude=$me -r -l "ipdb.set_trace()" * | wc -l` |
busca=`grep --color=auto --exclude=$me --exclude=ipython_log.py* -r -l "pdb.set_trace()" .` |
||||
if [ $stmts != '0' ] |
|
||||
|
if [ ! -z "$busca" ] |
||||
then |
then |
||||
echo "==================================================================" |
echo "============================================================================" |
||||
echo "ERROR: ipdb.set_trace() call in codebase! Remove, please." |
echo "ERROR: pdb.set_trace() encontrado nos seguintes arquivos. Remova, por favor." |
||||
grep --exclude=$me -r -n "ipdb.set_trace()" * |
echo "$busca" |
||||
echo "==================================================================" |
echo "============================================================================" |
||||
fi |
fi |
||||
|
|
||||
# QA checks: run this before every commit |
# ./manage.py check |
||||
./manage.py check |
# flake8 --exclude='ipython_log.py*,migrations,templates' . |
||||
flake8 --exclude='ipython_log.py*,migrations,templates' . |
# isort --recursive --check-only --skip='migrations' --skip='templates' --skip='ipython_log.py' . |
||||
isort --recursive --check-only --skip='migrations' --skip='templates' --skip='ipython_log.py' . |
|
||||
|
|||||
@ -0,0 +1,34 @@ |
|||||
|
Créditos do SAPL - até versão 2.5 |
||||
|
================================= |
||||
|
|
||||
|
Obrigado aos colaboradores: |
||||
|
|
||||
|
- Adriano Gomes |
||||
|
- Angelo Marcondes Neto |
||||
|
- Claudio Morale |
||||
|
- Daniel C. Azevedo |
||||
|
- Davi Lima de Medeiros |
||||
|
- Edson Ma |
||||
|
- Fernando Ciciliati Júnior |
||||
|
- Gustavo Lepri |
||||
|
- Halison Casimiro |
||||
|
- Helder Vieira |
||||
|
- Jean Rodrigo Ferri |
||||
|
- João Lima |
||||
|
- José Borges |
||||
|
- Leandro Roberto |
||||
|
- Leonardo Caballero |
||||
|
- Luciano Di Fázio |
||||
|
- Luis Fernando Pires Machado |
||||
|
- Marcio Mazza |
||||
|
- Marcos Fragomeni |
||||
|
- Maria Cristina André de Mello |
||||
|
- Marta Maria Pincowsca Cardoso Maia |
||||
|
- Paulo Fernandes de Souza Júnior |
||||
|
- Petronio Barbosa Carvalho |
||||
|
- Ricardo Esperandio |
||||
|
- Rodrigo Barbosa Luz |
||||
|
- Sesóstris Vieira |
||||
|
- Sérgio Damiati |
||||
|
- Wilton Souza Alencar |
||||
|
- Wu Man Qi |
||||
@ -1,111 +0,0 @@ |
|||||
Instruções para Importação da base mysql 2.5 |
|
||||
============================================ |
|
||||
|
|
||||
|
|
||||
Para entrar no ambiente virtual:: |
|
||||
|
|
||||
workon sapl |
|
||||
|
|
||||
|
|
||||
|
|
||||
Instalar Dependências:: |
|
||||
|
|
||||
pip3 install -r requirements/migration-requirements.txt |
|
||||
|
|
||||
Criar um arquivo sapl/legacy/.env com o seguinte conteúdo (parametros de acesso ao banco 2.5):: |
|
||||
|
|
||||
DATABASE_URL = mysql://[usuario do mysql]:[senha do myuysql]@[host]:[porta]/[banco] |
|
||||
|
|
||||
|
|
||||
o conteúdo do arquivo será semelhante a isso:: |
|
||||
|
|
||||
DATABASE_URL = mysql://sapl:sapl@localhost:3306/interlegis |
|
||||
|
|
||||
|
|
||||
Posteriormente rodar a seguinte sequencia de comandos estando no ambiente virtual:: |
|
||||
|
|
||||
./manage.py shell --settings=sapl.legacy_migration_settings |
|
||||
|
|
||||
%run sapl/legacy/migration.py |
|
||||
|
|
||||
migrate() |
|
||||
|
|
||||
|
|
||||
Migração de documentos do sapl 2.5 |
|
||||
---------------------------------- |
|
||||
|
|
||||
No sapl 2.5 todos os documentos ficavam armazenados no ZODB (o banco do Zope). |
|
||||
No sapl 3.1 eles ficam no sistema de arquivos convencional e portanto precisam: |
|
||||
|
|
||||
1. ser exportados para o sistema de arquivos |
|
||||
2. ser vinculados ao novo banco importado para o sapl 3.1 |
|
||||
|
|
||||
|
|
||||
Exportar os documentos para o sistema de arquivos |
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
||||
|
|
||||
Siga os seguintes passos: |
|
||||
|
|
||||
1. Instale o `Products.FSDump` no sapl 2.5. |
|
||||
|
|
||||
Para isso basta colocar a pasta `Products/FSDump` do projeto https://github.com/zopefoundation/Products.FSDump na pasta `Products` da instalação do sapl 2.5 e reiniciar o Zope. |
|
||||
|
|
||||
A pasta a ser instalada é a seguinte: |
|
||||
https://github.com/zopefoundation/Products.FSDump/tree/master/Products/FSDump |
|
||||
|
|
||||
2. Na ZMI, na pasta `sapl_documentos`, adicione um objeto do tipo `Dumper`: |
|
||||
|
|
||||
- Em `Filesystem path` escolha uma pasta do sistema de arquivos local para onde os arquivos serão copiados |
|
||||
- Desmarque a opção `Use .metadata file` |
|
||||
- Clique no botão `Add` |
|
||||
|
|
||||
3. Use o objeto `Dumper` criado para exportar os arquivos: |
|
||||
|
|
||||
- Clique no objeto `Dumper` criado para ver suas opções |
|
||||
- Confira seus parametros e clique em `Change and Dump` |
|
||||
- Aguarde a exportação dos arquivos e verifique que foram copiados para a pasta indicada |
|
||||
|
|
||||
|
|
||||
Vincular os documentos ao novo banco do sapl 3.1 |
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
||||
|
|
||||
1. Primeiramente migre o banco do sapl 2.5 para o sapl 3.1 |
|
||||
|
|
||||
2. Copie a pasta exportada `sapl_documentos` dentro da pasta `media` da instalação do sapl 3.1 |
|
||||
|
|
||||
3. De forma semelhante ao realizado na migração do banco, dentro no mesmo ambiente virtual, rode os seguintes comandos:: |
|
||||
|
|
||||
./manage.py shell --settings=sapl.legacy_migration_settings |
|
||||
|
|
||||
%run sapl/legacy/migracao_documentos.py |
|
||||
|
|
||||
migrar_documentos() |
|
||||
|
|
||||
|
|
||||
Para indexar os arquivos para pesquisa textual |
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
||||
1. workon sapl |
|
||||
2. ./manage.py rebuild_index |
|
||||
|
|
||||
|
|
||||
Dependendo da quantidade de arquivos a serem indexados, pode ser listado o seguinte erro 'Too many open files' |
|
||||
|
|
||||
Isto está ligado a quantidade máxima de aquivos que podem ser abertos ao mesmo tempo pelo sistema operacional |
|
||||
|
|
||||
Para aumentar este limite:: |
|
||||
|
|
||||
sudo nano /etc/security/limits.conf |
|
||||
* soft nofile 9000 |
|
||||
* hard nofile 65000 |
|
||||
|
|
||||
|
|
||||
sudo nano /etc/pam.d/common-session |
|
||||
session required pam_limits.so |
|
||||
|
|
||||
Após reiniciar, verificar se foram carregados os novos parâmetros com o comando:: |
|
||||
ulimit -a |
|
||||
|
|
||||
deve ser apresentado o seguinte:: |
|
||||
open files (-n) 9000 |
|
||||
|
|
||||
|
|
||||
@ -1,9 +1,9 @@ |
|||||
-r test-requirements.txt |
-r test-requirements.txt |
||||
autopep8==1.2.4 |
autopep8==1.2.4 |
||||
beautifulsoup4==4.4.1 |
beautifulsoup4==4.6.0 |
||||
django-debug-toolbar==1.5 |
django-debug-toolbar==1.5 |
||||
ipdb==0.10.1 |
ipdb==0.10.1 |
||||
pip-review==0.4 |
pip-review==0.4 |
||||
pygraphviz==1.3.1 |
pygraphviz==1.3.1 |
||||
pytest-ipdb==0.1-prerelease2 |
pytest-ipdb==0.1-prerelease2 |
||||
pipdeptree |
pipdeptree==0.10.1 |
||||
|
|||||
@ -1,2 +1,2 @@ |
|||||
-r dev-requirements.txt |
-r dev-requirements.txt |
||||
mysqlclient |
mysqlclient==1.3.12 |
||||
|
|||||
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-10-16 20:06 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('base', '0008_auto_20170814_1409'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='appconfig', |
||||
|
name='mostrar_brasao_painel', |
||||
|
field=models.BooleanField(default=False, verbose_name='Mostrar brasão da Casa no painel?'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,19 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-10-18 16:50 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('base', '0009_appconfig_mostrar_brasao_painel'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RemoveField( |
||||
|
model_name='appconfig', |
||||
|
name='painel_aberto', |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,19 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-11-21 11:58 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('base', '0010_remove_appconfig_painel_aberto'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='appconfig', |
||||
|
options={'ordering': ('-id',), 'permissions': (('menu_sistemas', 'Renderizar Menu Sistemas'), ('view_tabelas_auxiliares', 'Visualizar Tabelas Auxiliares')), 'verbose_name': 'Configurações da Aplicação', 'verbose_name_plural': 'Configurações da Aplicação'}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-12-05 11:17 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('base', '0011_auto_20171121_0958'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='tipoautor', |
||||
|
name='descricao', |
||||
|
field=models.CharField(help_text='Obs: Não crie tipos de autores semelhante aos tipos fixos. ', max_length=50, verbose_name='Descrição'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,9 @@ |
|||||
|
|
||||
|
from django import template |
||||
|
|
||||
|
register = template.Library() |
||||
|
|
||||
|
|
||||
|
@register.filter |
||||
|
def tipoautor_contenttype_list(tipo): |
||||
|
return 'sapl.'+tipo.content_type.app_label+':'+tipo.content_type.model+'_list' |
||||
@ -0,0 +1,35 @@ |
|||||
|
import pytest |
||||
|
from django.core.urlresolvers import reverse |
||||
|
from django.utils.translation import ugettext_lazy as _ |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_incluir_casa_legislativa_errors(admin_client): |
||||
|
|
||||
|
response = admin_client.post(reverse('sapl.base:casalegislativa_create'), |
||||
|
{'salvar': 'salvar'}, |
||||
|
follow=True) |
||||
|
|
||||
|
assert (response.context_data['form'].errors['nome'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
assert (response.context_data['form'].errors['sigla'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
assert (response.context_data['form'].errors['endereco'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
assert (response.context_data['form'].errors['cep'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
assert (response.context_data['form'].errors['municipio'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
assert (response.context_data['form'].errors['uf'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_incluir_tipo_autor_errors(admin_client): |
||||
|
|
||||
|
response = admin_client.post(reverse('sapl.base:tipoautor_create'), |
||||
|
{'salvar': 'salvar'}, |
||||
|
follow=True) |
||||
|
|
||||
|
assert (response.context_data['form'].errors['descricao'] == |
||||
|
[_('Este campo é obrigatório.')]) |
||||
@ -0,0 +1,19 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-12-04 18:58 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('comissoes', '0002_auto_20170809_1236'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='comissao', |
||||
|
options={'ordering': ['nome'], 'verbose_name': 'Comissão', 'verbose_name_plural': 'Comissões'}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,25 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-10-31 15:27 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('compilacao', '0003_auto_20170825_1136'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='tipotextoarticulado', |
||||
|
name='participacao_social', |
||||
|
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Participação Social'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='tipotextoarticulado', |
||||
|
name='publicacao_func', |
||||
|
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Histórico de Publicação'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,54 @@ |
|||||
|
import base64 |
||||
|
import hashlib |
||||
|
|
||||
|
from django.contrib.auth.hashers import PBKDF2PasswordHasher, make_password |
||||
|
from django.utils.encoding import force_bytes |
||||
|
|
||||
|
|
||||
|
def to_base64(source): |
||||
|
return base64.b64encode(source).decode('utf-8') |
||||
|
|
||||
|
|
||||
|
class ZopeSHA1PasswordHasher(PBKDF2PasswordHasher): |
||||
|
""" |
||||
|
The SHA1 password hashing algorithm used by Zope. |
||||
|
Zope uses `password + salt`, Django has `salt + password`. |
||||
|
Pre encode with SHA1 in this order and PBKDF2 afterwards. |
||||
|
|
||||
|
based on https://www.fourdigits.nl/blog/converting-plone-data-to-django/ |
||||
|
""" |
||||
|
|
||||
|
algorithm = "zope_sha1_pbkdf2" |
||||
|
|
||||
|
def encode(self, password, salt, iterations=None): |
||||
|
assert password is not None |
||||
|
assert salt |
||||
|
password = force_bytes(password) |
||||
|
decoded_salt = base64.b64decode(salt) |
||||
|
|
||||
|
# this is what is stored in zope |
||||
|
hashed = hashlib.sha1(password + decoded_salt).digest() + decoded_salt |
||||
|
hashed = to_base64(hashed) |
||||
|
|
||||
|
# encode again with the standard method |
||||
|
return super().encode(hashed, salt, iterations) |
||||
|
|
||||
|
|
||||
|
def get_salt_from_zope_sha1(data): |
||||
|
intermediate = base64.b64decode(data) |
||||
|
salt = intermediate[20:].strip() |
||||
|
return to_base64(salt) |
||||
|
|
||||
|
|
||||
|
ZOPE_SHA1_PREFIX = '{SSHA}' |
||||
|
|
||||
|
|
||||
|
def zope_encoded_password_to_django(encoded): |
||||
|
if encoded.startswith(ZOPE_SHA1_PREFIX): |
||||
|
data = encoded[len(ZOPE_SHA1_PREFIX):] |
||||
|
salt = get_salt_from_zope_sha1(data) |
||||
|
hasher = ZopeSHA1PasswordHasher() |
||||
|
return super(ZopeSHA1PasswordHasher, hasher).encode(data, salt) |
||||
|
else: |
||||
|
# assume it's a plain password and use the default hashing |
||||
|
return make_password(encoded) |
||||
@ -0,0 +1,79 @@ |
|||||
|
from django.contrib.auth.models import Group, User |
||||
|
|
||||
|
from sapl.settings import MEDIA_ROOT |
||||
|
|
||||
|
PERFIL_LEGADO_PARA_NOVO = {legado: Group.objects.get(name=novo) |
||||
|
for legado, novo in [ |
||||
|
('Autor', 'Autor'), |
||||
|
('Operador', 'Operador Geral'), |
||||
|
('Operador Comissao', 'Operador de Comissões'), |
||||
|
('Operador Materia', 'Operador de Matéria'), |
||||
|
('Operador Modulo Administrativo', 'Operador Administrativo'), |
||||
|
('Operador Norma', 'Operador de Norma Jurídica'), |
||||
|
('Operador Parlamentar', 'Parlamentar'), |
||||
|
('Operador Protocolo', 'Operador de Protocolo Administrativo'), |
||||
|
('Operador Sessao Plenaria', 'Operador de Sessão Plenária'), |
||||
|
('Parlamentar', 'Votante'), |
||||
|
] |
||||
|
} |
||||
|
|
||||
|
ADMINISTRADORES = {'Administrador', 'Manager'} |
||||
|
|
||||
|
IGNORADOS = { |
||||
|
# sem significado fora do zope |
||||
|
'Alterar Senha', 'Authenticated', 'Owner', |
||||
|
|
||||
|
# obsoletos (vide docs a seguir) |
||||
|
'Operador Mesa Diretora', |
||||
|
'Operador Ordem Dia', |
||||
|
'Operador Tabela Auxiliar', |
||||
|
'Operador Lexml', |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def migra_usuarios(): |
||||
|
""" |
||||
|
Lê o arquivo media/USERS e importa os usuários nele listados, |
||||
|
com senhas e perfis. |
||||
|
Os usuários são criados se necessário e seus perfis ajustados. |
||||
|
|
||||
|
Os seguintes perfis no legado não correspondem a nenhum no código atual |
||||
|
e estão sendo **ignorados**: |
||||
|
|
||||
|
* Operador Mesa Diretora |
||||
|
Apenas **8 usuários**, em todas as bases, têm esse perfil |
||||
|
e não têm nem "Operador" nem "Operador Sessao Plenaria" |
||||
|
|
||||
|
* Operador Ordem Dia |
||||
|
Apenas **16 usuários**, em todas as bases, têm esse perfil |
||||
|
e não têm nem "Operador" nem "Operador Sessao Plenaria" |
||||
|
|
||||
|
* Operador Tabela Auxiliar |
||||
|
A edição das tabelas auxiliares deve ser feita por um administrador |
||||
|
|
||||
|
* Operador Lexml |
||||
|
Também podemos assumir que essa é uma tarefa de um administrador |
||||
|
""" |
||||
|
|
||||
|
ARQUIVO_USUARIOS = MEDIA_ROOT.child('USERS') |
||||
|
with open(ARQUIVO_USUARIOS, 'r') as f: |
||||
|
usuarios = eval(f.read()) |
||||
|
usuarios = [ |
||||
|
(nome, |
||||
|
# troca senha "inicial" por uma inutilizável |
||||
|
senha if senha != 'inicial' else None, |
||||
|
# filtra perfis ignorados |
||||
|
{p for p in perfis if p not in IGNORADOS}) |
||||
|
for nome, senha, perfis in usuarios] |
||||
|
|
||||
|
for nome, senha, perfis in usuarios: |
||||
|
usuario = User.objects.get_or_create(username=nome)[0] |
||||
|
for perfil in perfis: |
||||
|
if perfil in ADMINISTRADORES: |
||||
|
# Manager |
||||
|
usuario.is_staff = True |
||||
|
usuario.save() |
||||
|
else: |
||||
|
usuario.groups.add(PERFIL_LEGADO_PARA_NOVO[perfil]) |
||||
|
# apaga arquivo (importante pois contém senhas) |
||||
|
ARQUIVO_USUARIOS.remove() |
||||
@ -0,0 +1,3 @@ |
|||||
|
Data*.fs* |
||||
|
sapl_documentos |
||||
|
XSLT |
||||
@ -0,0 +1,261 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
# IMPORTANTE: |
||||
|
# Esse script precisa rodar em python 2 |
||||
|
# e depende apenas do descrito no arquivo requiments.txt |
||||
|
|
||||
|
import os.path |
||||
|
import sys |
||||
|
from collections import defaultdict |
||||
|
from functools import partial |
||||
|
from os.path import splitext |
||||
|
|
||||
|
import yaml |
||||
|
import ZODB.DB |
||||
|
import ZODB.FileStorage |
||||
|
from ZODB.broken import Broken |
||||
|
|
||||
|
EXTENSOES = { |
||||
|
'application/msword': '.doc', |
||||
|
'application/pdf': '.pdf', |
||||
|
'application/vnd.oasis.opendocument.text': '.odt', |
||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx', # noqa |
||||
|
'application/xml': '.xml', |
||||
|
'text/xml': '.xml', |
||||
|
'application/zip': '.zip', |
||||
|
'image/jpeg': '.jpeg', |
||||
|
'image/png': '.png', |
||||
|
'image/gif': '.gif', |
||||
|
'text/html': '.html', |
||||
|
'text/rtf': '.rtf', |
||||
|
'text/x-python': '.py', |
||||
|
'text/plain': '.txt', |
||||
|
'SDE-Document': 'xml', |
||||
|
|
||||
|
# TODO rever... |
||||
|
'text/richtext': '.rtf', |
||||
|
|
||||
|
# sem extensao |
||||
|
'application/octet-stream': '', # binario |
||||
|
'inode/x-empty': '', # vazio |
||||
|
'text/x-unknown-content-type': '', |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def br(obj): |
||||
|
if isinstance(obj, Broken): |
||||
|
return obj.__Broken_state__ |
||||
|
else: |
||||
|
return obj |
||||
|
|
||||
|
|
||||
|
extensoes_desconhecidas = defaultdict(list) |
||||
|
|
||||
|
|
||||
|
def dump_file(doc, path): |
||||
|
id = doc['__name__'] |
||||
|
name, extension = splitext(id) |
||||
|
content_type = doc['content_type'] |
||||
|
extension = extension or EXTENSOES.get(content_type, 'ZZZZ') |
||||
|
|
||||
|
fullname = os.path.join(path, name + extension) |
||||
|
print(fullname) |
||||
|
|
||||
|
if extension == 'ZZZZ': |
||||
|
extensoes_desconhecidas[content_type].append(fullname) |
||||
|
|
||||
|
# A partir daqui usamos dict.pop('...') nos __Broken_state__ |
||||
|
# para contornar um "vazamento" de memória que ocorre |
||||
|
# ao percorrer a árvore de objetos |
||||
|
# |
||||
|
# Imaginamos que, internamente, o ZODB está guardando referências |
||||
|
# para os objetos Broken criados e não conseguimos identificar como. |
||||
|
# |
||||
|
# Essa medida descarta quase todos os dados retornados |
||||
|
# e só funciona na primeira passagem |
||||
|
|
||||
|
pdata = br(doc.pop('data')) |
||||
|
if isinstance(pdata, str): |
||||
|
# Retrocedemos se pdata ja eh uma str (necessario em Images) |
||||
|
doc['data'] = pdata |
||||
|
pdata = doc |
||||
|
|
||||
|
with open(fullname, 'w') as arq: |
||||
|
while pdata: |
||||
|
arq.write(pdata.pop('data')) |
||||
|
pdata = br(pdata.pop('next', None)) |
||||
|
|
||||
|
return id |
||||
|
|
||||
|
|
||||
|
def enumerate_by_key_list(folder, key_list, type_key): |
||||
|
for entry in folder.get(key_list, []): |
||||
|
id, meta_type = entry['id'], entry[type_key] |
||||
|
obj = br(folder.get(id, None)) |
||||
|
yield id, obj, meta_type |
||||
|
|
||||
|
|
||||
|
enumerate_folder = partial(enumerate_by_key_list, |
||||
|
key_list='_objects', type_key='meta_type') |
||||
|
|
||||
|
enumerate_properties = partial(enumerate_by_key_list, |
||||
|
key_list='_properties', type_key='type') |
||||
|
|
||||
|
|
||||
|
def enumerate_btree(folder): |
||||
|
contagem_esperada = folder['_count'].value |
||||
|
tree = folder['_tree'] |
||||
|
for contagem_real, (id, obj) in enumerate(tree.iteritems(), start=1): |
||||
|
obj, meta_type = br(obj), type(obj).__name__ |
||||
|
yield id, obj, meta_type |
||||
|
# verificação de consistência |
||||
|
assert contagem_esperada == contagem_real |
||||
|
|
||||
|
|
||||
|
nao_identificados = defaultdict(list) |
||||
|
|
||||
|
|
||||
|
def dump_folder(folder, path='', enum=enumerate_folder): |
||||
|
name = folder['id'] |
||||
|
path = os.path.join(path, name) |
||||
|
if not os.path.exists(path): |
||||
|
os.makedirs(path) |
||||
|
for id, obj, meta_type in enum(folder): |
||||
|
dump = DUMP_FUNCTIONS.get(meta_type, '?') |
||||
|
if dump == '?': |
||||
|
nao_identificados[meta_type].append(path + '/' + id) |
||||
|
elif dump: |
||||
|
id_interno = dump(obj, path) |
||||
|
assert id == id_interno |
||||
|
return name |
||||
|
|
||||
|
|
||||
|
def decode_iso8859(obj): |
||||
|
return obj.decode('iso8859-1') if isinstance(obj, str) else obj |
||||
|
|
||||
|
|
||||
|
def read_sde(element): |
||||
|
|
||||
|
def read_properties(): |
||||
|
for id, obj, meta_type in enumerate_properties(element): |
||||
|
yield id, decode_iso8859(obj) |
||||
|
|
||||
|
def read_children(): |
||||
|
for id, obj, meta_type in enumerate_folder(element): |
||||
|
assert meta_type in ['SDE-Document-Element', |
||||
|
'SDE-Template-Element', |
||||
|
'SDE-Template-Link', |
||||
|
'SDE-Template-Attribute', |
||||
|
'Script (Python)', |
||||
|
] |
||||
|
if meta_type != 'Script (Python)': |
||||
|
# ignoramos os scrips python de eventos dos templates |
||||
|
yield id, read_sde(obj) |
||||
|
|
||||
|
data = dict(read_properties()) |
||||
|
children = list(read_children()) |
||||
|
if children: |
||||
|
data['children'] = children |
||||
|
return data |
||||
|
|
||||
|
|
||||
|
def save_as_yaml(path, name, obj): |
||||
|
fullname = os.path.join(path, name) |
||||
|
with open(fullname, 'w') as arquivo: |
||||
|
yaml.safe_dump(obj, arquivo) |
||||
|
print(fullname) |
||||
|
return fullname |
||||
|
|
||||
|
|
||||
|
def dump_sde(strdoc, path, tipo): |
||||
|
id = strdoc['id'] |
||||
|
sde = read_sde(strdoc) |
||||
|
save_as_yaml(path, '{}.{}.yaml'.format(id, tipo), sde) |
||||
|
return id |
||||
|
|
||||
|
|
||||
|
DUMP_FUNCTIONS = { |
||||
|
'File': dump_file, |
||||
|
'Image': dump_file, |
||||
|
'Folder': partial(dump_folder, enum=enumerate_folder), |
||||
|
'BTreeFolder2': partial(dump_folder, enum=enumerate_btree), |
||||
|
'SDE-Document': partial(dump_sde, tipo='sde.document'), |
||||
|
'SDE-Template': partial(dump_sde, tipo='sde.template'), |
||||
|
|
||||
|
# explicitamente ignorados |
||||
|
'ZCatalog': None, |
||||
|
'Dumper': None, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def get_app(data_fs_path): |
||||
|
storage = ZODB.FileStorage.FileStorage(data_fs_path) |
||||
|
db = ZODB.DB(storage) |
||||
|
connection = db.open() |
||||
|
root = connection.root() |
||||
|
app = br(root['Application']) |
||||
|
|
||||
|
def close_db(): |
||||
|
db.close() |
||||
|
|
||||
|
return app, close_db |
||||
|
|
||||
|
|
||||
|
def find_sapl(app): |
||||
|
for obj in app['_objects']: |
||||
|
id, meta_type = obj['id'], obj['meta_type'] |
||||
|
if id.startswith('cm_') and meta_type == 'Folder': |
||||
|
cm_zzz = br(app[id]) |
||||
|
sapl = br(cm_zzz.get('sapl', None)) |
||||
|
if sapl and 'sapl_documentos' in sapl and 'acl_users' in sapl: |
||||
|
return sapl |
||||
|
|
||||
|
|
||||
|
def dump_propriedades(docs, path): |
||||
|
props_sapl = br(docs['props_sapl']) |
||||
|
ids = [p['id'] for p in props_sapl['_properties']] |
||||
|
props = {id: props_sapl[id] for id in ids} |
||||
|
props = {id: p.decode('iso-8859-1') if isinstance(p, str) else p |
||||
|
for id, p in props.items()} |
||||
|
save_as_yaml(path, 'sapl_documentos/propriedades.yaml', props) |
||||
|
|
||||
|
|
||||
|
def dump_usuarios(sapl, path): |
||||
|
users = br(br(sapl['acl_users'])['data']) |
||||
|
users = {k: br(v) for k, v in users['data'].items()} |
||||
|
save_as_yaml(path, 'usuarios.yaml', users) |
||||
|
|
||||
|
|
||||
|
def dump_sapl(data_fs_path, destino='../../../../media'): |
||||
|
app, close_db = get_app(data_fs_path) |
||||
|
try: |
||||
|
sapl = find_sapl(app) |
||||
|
# extrai folhas XSLT |
||||
|
dump_folder(br(sapl['XSLT']), destino) |
||||
|
# extrai usuários com suas senhas e perfis |
||||
|
dump_usuarios(sapl, destino) |
||||
|
|
||||
|
# extrai documentos |
||||
|
docs = br(sapl['sapl_documentos']) |
||||
|
nao_identificados.clear() |
||||
|
dump_folder(docs, destino) |
||||
|
dump_propriedades(docs, destino) |
||||
|
if nao_identificados: |
||||
|
print('#' * 80) |
||||
|
print('#' * 80) |
||||
|
print(u'FORAM ENCONTRADOS ARQUIVOS DE FORMATO NÃO IDENTIFICADO!!!') |
||||
|
print(u'REFAÇA A EXPORTAÇÃO\n') |
||||
|
print(nao_identificados) |
||||
|
print('#' * 80) |
||||
|
print('#' * 80) |
||||
|
finally: |
||||
|
close_db() |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
if len(sys.argv) == 2: |
||||
|
data_fs_path = sys.argv[1] |
||||
|
dump_sapl(data_fs_path) |
||||
|
else: |
||||
|
print('Uso: python exporta_zope <caminho p Data.fs>') |
||||
@ -0,0 +1,3 @@ |
|||||
|
# ZODB version 3.7.4 |
||||
|
PyYAML==3.12 |
||||
|
ZODB==5.3.0 |
||||
@ -1,28 +0,0 @@ |
|||||
-- Apaga as restrições somente para essa sessão |
|
||||
SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES,','ALLOW_INVALID_DATES'); |
|
||||
-- Exclui procedures caso já existam |
|
||||
DROP PROCEDURE IF EXISTS verifica_campos_proposicao; |
|
||||
DROP PROCEDURE IF EXISTS verifica_campos_tipo_materia_legislativa; |
|
||||
DROP PROCEDURE IF EXISTS verifica_campos_sessao_plenaria_presenca; |
|
||||
DROP PROCEDURE IF EXISTS cria_lexml_registro_provedor_e_publicador; |
|
||||
DROP PROCEDURE IF EXISTS cria_tipo_situacao_militar; |
|
||||
DROP PROCEDURE IF EXISTS muda_vinculo_norma_juridica_ind_excluido; |
|
||||
-- Procedure para criar campo num_proposicao em proposicao |
|
||||
CREATE PROCEDURE verifica_campos_proposicao() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='proposicao' AND column_name='num_proposicao') THEN UPDATE proposicao SET dat_envio = '1800-01-01' WHERE CAST(dat_envio AS CHAR(20)) = '0000-00-00 00:00:00'; ALTER TABLE proposicao ADD COLUMN num_proposicao INT(11) NULL after txt_justif_devolucao; END IF; END; |
|
||||
-- Procedure para criar campo iind_num_automatica em tipo_materia_legislativa |
|
||||
CREATE PROCEDURE verifica_campos_tipo_materia_legislativa() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tipo_materia_legislativa' AND column_name='ind_num_automatica') THEN ALTER TABLE tipo_materia_legislativa ADD COLUMN ind_num_automatica BOOLEAN NULL DEFAULT FALSE after des_tipo_materia; END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tipo_materia_legislativa' AND column_name='quorum_minimo_votacao') THEN ALTER TABLE tipo_materia_legislativa ADD COLUMN quorum_minimo_votacao INT(11) NULL after ind_num_automatica; END IF; END; |
|
||||
-- Procedure para criar campos cod_presenca_sessao (sendo a nova PK da tabela) e dat_sessao em sessao_plenaria_presenca |
|
||||
CREATE PROCEDURE verifica_campos_sessao_plenaria_presenca() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='sessao_plenaria_presenca' AND column_name='cod_presenca_sessao') THEN ALTER TABLE sessao_plenaria_presenca DROP PRIMARY KEY, ADD cod_presenca_sessao INT AUTO_INCREMENT PRIMARY KEY FIRST; END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='sessao_plenaria_presenca' AND column_name='dat_sessao') THEN ALTER TABLE sessao_plenaria_presenca ADD COLUMN dat_sessao DATE NULL after cod_parlamentar; END IF; END; |
|
||||
-- Procedure para criar tabela lexml_registro_provedor e lexml_registro_publicador |
|
||||
CREATE PROCEDURE cria_lexml_registro_provedor_e_publicador() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='lexml_registro_publicador') THEN CREATE TABLE lexml_registro_publicador (cod_publicador INT AUTO_INCREMENT NOT NULL, id_publicador INT, nom_publicador VARCHAR(255), adm_email VARCHAR(50), sigla VARCHAR(255), nom_responsavel VARCHAR(255), tipo VARCHAR(50), id_responsavel INT, PRIMARY KEY (cod_publicador)); END IF; IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='lexml_registro_provedor') THEN CREATE TABLE lexml_registro_provedor (cod_provedor INT AUTO_INCREMENT NOT NULL, id_provedor INT, nom_provedor VARCHAR(255), sgl_provedor VARCHAR(15), adm_email VARCHAR(50), nom_responsavel VARCHAR(255), tipo VARCHAR(50), id_responsavel INT, xml_provedor LONGTEXT, PRIMARY KEY (cod_provedor)); END IF; END; |
|
||||
-- Procedure para criar tabela tipo_situacao_militar |
|
||||
CREATE PROCEDURE cria_tipo_situacao_militar() BEGIN IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tipo_situacao_militar') THEN CREATE TABLE tipo_situacao_militar (tip_situacao_militar INT AUTO_INCREMENT NOT NULL, des_tipo_situacao VARCHAR(50), ind_excluido INT, PRIMARY KEY (tip_situacao_militar)); END IF; END; |
|
||||
-- Procedure para mudar valor do campo ind_excluido da tabela vinculo_norma_juridica de 0 para string vazia '' |
|
||||
CREATE PROCEDURE muda_vinculo_norma_juridica_ind_excluido() BEGIN UPDATE vinculo_norma_juridica SET ind_excluido = '' WHERE trim(ind_excluido) = '0'; END; |
|
||||
-- Executa as procedures criadas acima |
|
||||
CALL verifica_campos_proposicao; |
|
||||
CALL verifica_campos_tipo_materia_legislativa; |
|
||||
CALL verifica_campos_sessao_plenaria_presenca; |
|
||||
CALL cria_lexml_registro_provedor_e_publicador; |
|
||||
CALL cria_tipo_situacao_militar; |
|
||||
CALL muda_vinculo_norma_juridica_ind_excluido; |
|
||||
@ -1,5 +1,11 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
# (Re)cria todos os bancos postgres para migração |
# (Re)cria todos os bancos postgres para migração |
||||
# cria um banco postgres (de mesmo nome) para cada banco mysql cujo nome começa com "sapl_" |
# cria um banco postgres (de mesmo nome) para cada banco mysql cujo nome começa com "sapl_" |
||||
|
|
||||
mysql -u root -padmin -e 'show databases;' | grep '^sapl_' | xargs -I{} ./recria_um_db_postgres.sh {} |
if [ $# -eq 2 ]; then |
||||
|
parallel --verbose -j+0 ./recria_um_db_postgres.sh :::: <(mysql -u $1 -p$2 -e 'show databases;' | grep '^sapl_' | grep -v '_copy$') |
||||
|
else |
||||
|
echo "USO:" |
||||
|
echo " $0 [usuário mysql] [senha mysql]" |
||||
|
fi; |
||||
@ -1,5 +1,6 @@ |
|||||
# (Re)cria um db postgres |
# (Re)cria um db postgres |
||||
# uso: recria_um_db_postgres <NOME DO BANCO> |
# uso: recria_um_db_postgres <NOME DO BANCO> |
||||
|
|
||||
|
echo "Database $1" |
||||
sudo -u postgres psql -c "drop DATABASE if exists $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;" |
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;" |
||||
|
|||||
@ -1,150 +0,0 @@ |
|||||
#!/usr/bin/python |
|
||||
|
|
||||
# requisito: pip install PyMySQL |
|
||||
|
|
||||
import pymysql.cursors |
|
||||
|
|
||||
HOST = 'localhost' |
|
||||
USER = 'root' |
|
||||
PASSWORD = '' |
|
||||
DB = '' |
|
||||
|
|
||||
|
|
||||
SELECT_EXCLUIDOS = "SELECT %s FROM %s WHERE ind_excluido = 1 ORDER BY %s" |
|
||||
|
|
||||
REGISTROS_INCONSISTENTES = "DELETE FROM %s WHERE %s " |
|
||||
"in (%s) AND ind_excluido = 0 " |
|
||||
|
|
||||
EXCLUI_REGISTRO = "DELETE FROM %s WHERE ind_excluido=1" |
|
||||
|
|
||||
NORMA_DEP = "DELETE FROM vinculo_norma_juridica WHERE cod_norma_referente in (%s) OR \ |
|
||||
cod_norma_referida in (%s) AND ind_excluido = 0 " |
|
||||
|
|
||||
mapa = {} # mapa com tabela principal -> tabelas dependentes |
|
||||
|
|
||||
mapa['tipo_autor'] = ['autor'] |
|
||||
mapa['materia_legislativa'] = ['acomp_materia', 'autoria', 'despacho_inicial', |
|
||||
'documento_acessorio', 'expediente_materia', |
|
||||
'legislacao_citada', 'materia_assunto', |
|
||||
'numeracao', 'ordem_dia', 'parecer', |
|
||||
'proposicao', 'registro_votacao', |
|
||||
'relatoria', 'tramitacao'] |
|
||||
mapa['norma_juridica'] = ['vinculo_norma_juridica'] |
|
||||
mapa['comissao'] = ['composicao_comissao'] |
|
||||
mapa['sessao_legislativa'] = ['composicao_mesa'] |
|
||||
mapa['tipo_expediente'] = ['expediente_sessao_plenaria'] |
|
||||
|
|
||||
""" |
|
||||
mapa['autor'] = ['tipo_autor', 'partido', 'comissao', 'parlamentar'] |
|
||||
mapa['parlamentar'] = ['autor', 'autoria', 'composicao_comissao', |
|
||||
'composicao_mesa', 'dependente', 'filiacao', |
|
||||
'mandato', 'mesa_sessao_plenaria', 'oradores', |
|
||||
'oradores_expediente', 'ordem_dia_presenca', |
|
||||
'registro_votacao_parlamentar', 'relatoria', |
|
||||
'sessao_plenaria_presenca', 'unidade_tramitacao'] |
|
||||
""" |
|
||||
|
|
||||
|
|
||||
def get_ids_excluidos(cursor, query): |
|
||||
""" |
|
||||
recupera as PKs de registros com ind_excluido = 1 da tabela principal |
|
||||
""" |
|
||||
cursor.execute(query) |
|
||||
excluidos = cursor.fetchall() |
|
||||
# flat tuple of tuples with map transformation into string |
|
||||
excluidos = [str(val) for sublist in excluidos for val in sublist] |
|
||||
return excluidos |
|
||||
|
|
||||
|
|
||||
def remove_tabelas(cursor, tabela_principal, pk, query_dependentes=None): |
|
||||
|
|
||||
QUERY = SELECT_EXCLUIDOS % (pk, tabela_principal, pk) |
|
||||
ids_excluidos = get_ids_excluidos(cursor, QUERY) |
|
||||
print("\nRegistros da tabela '%s' com ind_excluido = 1: %s" % |
|
||||
(tabela_principal.upper(), len(ids_excluidos))) |
|
||||
|
|
||||
""" |
|
||||
Remove registros de tabelas que dependem da tabela principal, |
|
||||
e que se encontram com ind_excluido = 0 (nao excluidas), se |
|
||||
tais registros existirem. |
|
||||
""" |
|
||||
if ids_excluidos: |
|
||||
print("Dependencias inconsistentes") |
|
||||
for tabela in mapa[tabela_principal]: |
|
||||
|
|
||||
QUERY_DEP = REGISTROS_INCONSISTENTES % ( |
|
||||
tabela, pk, ','.join(ids_excluidos)) |
|
||||
|
|
||||
# Trata caso especifico de norma_juridica |
|
||||
if query_dependentes: |
|
||||
QUERY_DEP = query_dependentes % (','.join(ids_excluidos), |
|
||||
','.join(ids_excluidos)) |
|
||||
|
|
||||
print(tabela.upper(), cursor.execute(QUERY_DEP)) |
|
||||
|
|
||||
""" |
|
||||
Remove todos os registros com ind_excluido = 1 das tabelas |
|
||||
dependentes e da tabela principal, nesta ordem. |
|
||||
""" |
|
||||
print("\n\nRegistros com ind_excluido = 1") |
|
||||
for tabela in mapa[tabela_principal] + [tabela_principal]: |
|
||||
QUERY = EXCLUI_REGISTRO % tabela |
|
||||
print(tabela.upper(), cursor.execute(QUERY)) |
|
||||
|
|
||||
|
|
||||
def remove_excluidas(cursor): |
|
||||
cursor.execute("SHOW_TABLES") |
|
||||
for row in cursor.fetchall(): |
|
||||
print(row) |
|
||||
|
|
||||
|
|
||||
def remove_proposicao_invalida(cursor): |
|
||||
return cursor.execute( |
|
||||
"DELETE FROM proposicao WHERE cod_mat_ou_doc is null") |
|
||||
|
|
||||
|
|
||||
def remove_materia_assunto_invalida(cursor): |
|
||||
return cursor.execute( |
|
||||
"DELETE FROM materia_assunto WHERE cod_assunto = 0") |
|
||||
|
|
||||
|
|
||||
def shotgun_remove(cursor): |
|
||||
for tabela in get_ids_excluidos(cursor, "SHOW TABLES"): |
|
||||
try: |
|
||||
cursor.execute("DELETE FROM %s WHERE ind_excluido = 1" % tabela) |
|
||||
except: |
|
||||
pass |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
connection = pymysql.connect(host=HOST, |
|
||||
user=USER, |
|
||||
password=PASSWORD, |
|
||||
db=DB) |
|
||||
cursor = connection.cursor() |
|
||||
# TIPO AUTOR |
|
||||
remove_tabelas(cursor, 'tipo_autor', 'tip_autor') |
|
||||
# MATERIA LEGISLATIVA |
|
||||
remove_tabelas(cursor, 'materia_legislativa', 'cod_materia') |
|
||||
# NORMA JURIDICA |
|
||||
remove_tabelas(cursor, 'norma_juridica', 'cod_norma', NORMA_DEP) |
|
||||
# COMISSAO |
|
||||
remove_tabelas(cursor, 'comissao', 'cod_comissao') |
|
||||
# SESSAO LEGISLATIVA |
|
||||
remove_tabelas(cursor, 'sessao_legislativa', 'cod_sessao_leg') |
|
||||
# EXPEDIENTE SESSAO |
|
||||
remove_tabelas(cursor, 'tipo_expediente', 'cod_expediente') |
|
||||
# AUTOR |
|
||||
remove_tabelas(cursor, 'autor', 'cod_autor') |
|
||||
# PARLAMENTAR |
|
||||
remove_tabelas(cursor, 'parlamentar', 'cod_parlamentar') |
|
||||
|
|
||||
# PROPOSICAO |
|
||||
remove_proposicao_invalida(cursor) |
|
||||
|
|
||||
# MATERIA_ASSUNTO |
|
||||
remove_materia_assunto_invalida(cursor) |
|
||||
|
|
||||
# shotgun_remove(cursor) |
|
||||
|
|
||||
cursor.close() |
|
||||
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.12 on 2017-08-15 12:38 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0011_auto_20170808_1034'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='proposicao', |
||||
|
name='tipo', |
||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.TipoProposicao', verbose_name='Tipo'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='tramitacao', |
||||
|
name='status', |
||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.StatusTramitacao', verbose_name='Status'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,21 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.12 on 2017-08-16 11:36 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0012_auto_20170815_1238'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='tramitacao', |
||||
|
name='unidade_tramitacao_destino', |
||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tramitacoes_destino', to='materia.UnidadeTramitacao', verbose_name='Unidade Destino'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,19 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.7 on 2017-09-05 08:18 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0013_adiciona_status_tramitacao'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='unidadetramitacao', |
||||
|
options={'ordering': ['orgao', 'comissao', 'parlamentar'], 'verbose_name': 'Unidade de Tramitação', 'verbose_name_plural': 'Unidades de Tramitação'}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-09-08 10:24 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
from sapl.materia.models import TipoProposicao |
||||
|
|
||||
|
|
||||
|
class AlterUniqueTogetherFixConstraintInexistente( |
||||
|
migrations.AlterUniqueTogether): |
||||
|
|
||||
|
def database_forwards(self, |
||||
|
app_label, schema_editor, from_state, to_state): |
||||
|
constraint_names = schema_editor._constraint_names( |
||||
|
TipoProposicao, ['content_type_id', 'object_id'], unique=True) |
||||
|
if constraint_names: |
||||
|
# por alguma razão a constraint não existe em alguns bancos |
||||
|
# se ela existir continua a exetução normal |
||||
|
super(AlterUniqueTogetherFixConstraintInexistente, |
||||
|
self).database_forwards( |
||||
|
app_label, schema_editor, from_state, to_state |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0014_auto_20170905_0818'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
AlterUniqueTogetherFixConstraintInexistente( |
||||
|
name='tipoproposicao', |
||||
|
unique_together=set([]), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,16 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-09-08 11:57 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0015_auto_20170908_1024'), |
||||
|
('materia', '0013_auto_20170816_1136'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
] |
||||
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-09-18 12:57 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0016_merge'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='proposicao', |
||||
|
name='data_envio', |
||||
|
field=models.DateTimeField(null=True, verbose_name='Data de Envio'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,101 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-11-13 15:39 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0017_auto_20170918_1257'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='anexada', |
||||
|
name='materia_anexada', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materia_anexada_set', to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='anexada', |
||||
|
name='materia_principal', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materia_principal_set', to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='autoria', |
||||
|
name='autor', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.Autor', verbose_name='Autor'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='autoria', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa', verbose_name='Matéria Legislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='despachoinicial', |
||||
|
name='comissao', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='comissoes.Comissao'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='despachoinicial', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='documentoacessorio', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='materiaassunto', |
||||
|
name='assunto', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.AssuntoMateria', verbose_name='Assunto'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='materiaassunto', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa', verbose_name='Matéria'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='numeracao', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='parecer', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='parecer', |
||||
|
name='relatoria', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.Relatoria'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='proposicao', |
||||
|
name='materia_de_vinculo', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='proposicao_set', to='materia.MateriaLegislativa', verbose_name='Matéria anexadora'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='relatoria', |
||||
|
name='comissao', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='comissoes.Comissao', verbose_name='Comissão'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='relatoria', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='relatoria', |
||||
|
name='parlamentar', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parlamentares.Parlamentar', verbose_name='Parlamentar'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='tramitacao', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-11-27 17:00 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0018_auto_20171113_1339'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='anexada', |
||||
|
name='materia_anexada', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materia_anexada_set', to='materia.MateriaLegislativa', verbose_name='Matéria Anexada'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='anexada', |
||||
|
name='materia_principal', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materia_principal_set', to='materia.MateriaLegislativa', verbose_name='Matéria Principal'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,27 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-12-04 18:58 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('materia', '0019_auto_20171127_1500'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='orgao', |
||||
|
options={'ordering': ['nome'], 'verbose_name': 'Órgão', 'verbose_name_plural': 'Órgãos'}, |
||||
|
), |
||||
|
migrations.AlterModelOptions( |
||||
|
name='tipodocumento', |
||||
|
options={'ordering': ['descricao'], 'verbose_name': 'Tipo de Documento', 'verbose_name_plural': 'Tipos de Documento'}, |
||||
|
), |
||||
|
migrations.AlterModelOptions( |
||||
|
name='unidadetramitacao', |
||||
|
options={'verbose_name': 'Unidade de Tramitação', 'verbose_name_plural': 'Unidades de Tramitação'}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,68 @@ |
|||||
|
import pytest |
||||
|
from django.utils.translation import ugettext as _ |
||||
|
from model_mommy import mommy |
||||
|
|
||||
|
from sapl.materia import forms |
||||
|
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_valida_campos_obrigatorios_ficha_pesquisa_form(): |
||||
|
form = forms.FichaPesquisaForm(data={}) |
||||
|
|
||||
|
assert not form.is_valid() |
||||
|
|
||||
|
errors = form.errors |
||||
|
|
||||
|
assert errors['tipo_materia'] == [_('Este campo é obrigatório.')] |
||||
|
assert errors['data_inicial'] == [_('Este campo é obrigatório.')] |
||||
|
assert errors['data_final'] == [_('Este campo é obrigatório.')] |
||||
|
|
||||
|
assert len(errors) == 3 |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_ficha_pesquisa_form_datas_invalidas(): |
||||
|
tipo = mommy.make(TipoMateriaLegislativa) |
||||
|
|
||||
|
form = forms.FichaPesquisaForm(data={'tipo_materia': str(tipo.pk), |
||||
|
'data_inicial': '10/11/2017', |
||||
|
'data_final': '09/11/2017' |
||||
|
}) |
||||
|
assert not form.is_valid() |
||||
|
assert form.errors['__all__'] == [_('A Data Final não pode ser menor que ' |
||||
|
'a Data Inicial')] |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_ficha_pesquisa_form_invalido(): |
||||
|
tipo = mommy.make(TipoMateriaLegislativa) |
||||
|
|
||||
|
form = forms.FichaPesquisaForm(data={'tipo_materia': str(tipo.pk), |
||||
|
'data_inicial': '10/11/2017', |
||||
|
'data_final': '09/11/2017' |
||||
|
}) |
||||
|
|
||||
|
assert not form.is_valid() |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_valida_campos_obrigatorios_ficha_seleciona_form(): |
||||
|
form = forms.FichaSelecionaForm(data={}) |
||||
|
|
||||
|
assert not form.is_valid() |
||||
|
|
||||
|
errors = form.errors |
||||
|
|
||||
|
assert errors['materia'] == [_('Este campo é obrigatório.')] |
||||
|
|
||||
|
assert len(errors) == 1 |
||||
|
|
||||
|
|
||||
|
@pytest.mark.django_db(transaction=False) |
||||
|
def test_ficha_seleciona_form_valido(): |
||||
|
materia = mommy.make(MateriaLegislativa) |
||||
|
|
||||
|
form = forms.FichaSelecionaForm(data={'materia': str(materia.pk)}) |
||||
|
|
||||
|
assert form.is_valid() |
||||
@ -0,0 +1,119 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Altera o(a)", |
||||
|
"descricao_passiva": "Alterado(a) pelo(a)", |
||||
|
"sigla": "A" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "1" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Revoga integralmente o(a)", |
||||
|
"descricao_passiva": "Revogado(a) integralmente pelo(a)", |
||||
|
"sigla": "R" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "2" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Revoga parcialmente o(a)", |
||||
|
"descricao_passiva": "Revogado(a) parcialmente pelo(a)", |
||||
|
"sigla": "P" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "3" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Revoga integralmente por consolida\u00e7\u00e3o", |
||||
|
"descricao_passiva": "Revogado(a) integralmente por consolida\u00e7\u00e3o", |
||||
|
"sigla": "T" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "4" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Norma correlata", |
||||
|
"descricao_passiva": "Norma correlata", |
||||
|
"sigla": "C" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "5" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Ressalva o(a)", |
||||
|
"descricao_passiva": "Ressalvada pelo(a)", |
||||
|
"sigla": "S" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "6" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Reedita o(a)", |
||||
|
"descricao_passiva": "Reeditada pelo(a)", |
||||
|
"sigla": "E" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "7" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Reedita com altera\u00e7\u00e3o o(a)", |
||||
|
"descricao_passiva": "Reeditada com altera\u00e7\u00e3o pelo(a)", |
||||
|
"sigla": "I" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "8" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Regulamenta o(a)", |
||||
|
"descricao_passiva": "Regulamentada pelo(a)", |
||||
|
"sigla": "G" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "9" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Suspende parcialmente o(a)", |
||||
|
"descricao_passiva": "Suspenso(a) parcialmente pelo(a)", |
||||
|
"sigla": "K" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "10" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Suspende integralmente o(a)", |
||||
|
"descricao_passiva": "Suspenso(a) integralmente pelo(a)", |
||||
|
"sigla": "L" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "11" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Julga integralmente inconstitucional", |
||||
|
"descricao_passiva": "Julgada integralmente inconstitucional", |
||||
|
"sigla": "N" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "12" |
||||
|
}, |
||||
|
{ |
||||
|
"fields": { |
||||
|
"descricao_ativa": "Julga parcialmente inconstitucional", |
||||
|
"descricao_passiva": "Julgada parcialmente inconstitucional", |
||||
|
"sigla": "O" |
||||
|
}, |
||||
|
"model": "norma.TipoVinculoNormaJuridica", |
||||
|
"pk": "13" |
||||
|
} |
||||
|
] |
||||
@ -0,0 +1,39 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
import os |
||||
|
|
||||
|
from django.core.management import call_command |
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
def gera_tipo_vinculo(apps, schema_editor): |
||||
|
TipoVinculoNormaJuridica = apps.get_model("norma", "TipoVinculoNormaJuridica") |
||||
|
|
||||
|
db_alias = schema_editor.connection.alias |
||||
|
tipo_vinculos = TipoVinculoNormaJuridica.objects.all().exists() |
||||
|
|
||||
|
if tipo_vinculos: |
||||
|
# Caso haja algum TipoVinculoNormaJuridica cadastrado na base de dados, |
||||
|
# a migração não deve ser carregada para evitar duplicações de dados. |
||||
|
print("Carga de {} não efetuada. Já Existem {} cadastrados...".format( |
||||
|
TipoVinculoNormaJuridica._meta.verbose_name, |
||||
|
TipoVinculoNormaJuridica._meta.verbose_name_plural |
||||
|
) |
||||
|
) |
||||
|
else: |
||||
|
fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures')) |
||||
|
# pega tipo_vinculo_norma_juridica listados em fixtures/pre_popula_tipo_vinculo_norma.json |
||||
|
fixture_filename = 'pre_popula_tipo_vinculo_norma.json' |
||||
|
fixture_file = os.path.join(fixture_dir, fixture_filename) |
||||
|
call_command('loaddata', fixture_file) |
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('norma', '0007_auto_20170904_1708'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RunPython(gera_tipo_vinculo), |
||||
|
] |
||||
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-11-13 15:39 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('norma', '0008_normajuridica_popula_tipo_vinculo_norma'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='legislacaocitada', |
||||
|
name='materia', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='materia.MateriaLegislativa'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='legislacaocitada', |
||||
|
name='norma', |
||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.NormaJuridica'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,27 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.13 on 2017-09-05 16:17 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('parlamentares', '0008_adiciona_cargos_mesa'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='situacaomilitar', |
||||
|
options={'ordering': ['descricao'], 'verbose_name': 'Tipo Situação Militar', 'verbose_name_plural': 'Tipos Situações Militares'}, |
||||
|
), |
||||
|
migrations.AlterModelOptions( |
||||
|
name='tipoafastamento', |
||||
|
options={'ordering': ['descricao'], 'verbose_name': 'Tipo de Afastamento', 'verbose_name_plural': 'Tipos de Afastamento'}, |
||||
|
), |
||||
|
migrations.AlterModelOptions( |
||||
|
name='tipodependente', |
||||
|
options={'ordering': ['descricao'], 'verbose_name': 'Tipo de Dependente', 'verbose_name_plural': 'Tipos de Dependente'}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,36 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
def altera_data_inicio_mandato(apps, schema_editor): |
||||
|
Mandato = apps.get_model("parlamentares", "Mandato") |
||||
|
mandatos = Mandato.objects.all() |
||||
|
|
||||
|
for mandato in mandatos: |
||||
|
data_inicio = mandato.data_inicio_mandato |
||||
|
data_inicio_legislatura = mandato.legislatura.data_inicio |
||||
|
|
||||
|
days = abs((data_inicio - data_inicio_legislatura |
||||
|
).days) if data_inicio else 60 |
||||
|
|
||||
|
if days >= 60: |
||||
|
mandato.data_inicio_mandato = data_inicio_legislatura |
||||
|
mandato.save() |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
# A dependencia real desse script é o arquivo 0001_initial.py, mas |
||||
|
# isso gera um erro (Conflicting migrations detected; multiple leaf |
||||
|
# nodes in the migration graph). para não ocasionar problemas de migração, |
||||
|
# vamos manter a ordem padrão do django. |
||||
|
('parlamentares', '0009_auto_20170905_1617'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RunPython(altera_data_inicio_mandato), |
||||
|
] |
||||
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.3 on 2017-10-10 17:33 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('parlamentares', '0010_corrige_data_inicio_mandato'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='mandato', |
||||
|
name='data_inicio_mandato', |
||||
|
field=models.DateField(null=True, verbose_name='Início do Mandato'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,25 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.11 on 2017-10-20 12:45 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('parlamentares', '0011_auto_20171010_1433'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='dependente', |
||||
|
name='nome', |
||||
|
field=models.CharField(max_length=150, verbose_name='Nome'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='tipodependente', |
||||
|
name='descricao', |
||||
|
field=models.CharField(max_length=150, verbose_name='Descrição'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,19 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9.3 on 2017-09-20 21:52 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('protocoloadm', '0001_initial'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RemoveField( |
||||
|
model_name='documentoadministrativo', |
||||
|
name='numero_protocolo', |
||||
|
), |
||||
|
] |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue