Browse Source

Merge branch 'master' into 758-refatora-painel

pull/792/head
Eduardo Calil 9 years ago
parent
commit
d87e0fed85
  1. 15
      README.rst
  2. 129
      sapl/compilacao/models.py
  3. 14
      sapl/compilacao/utils.py
  4. 85
      sapl/compilacao/views.py
  5. 21
      sapl/legacy_migration_settings.py
  6. 16
      sapl/materia/forms.py
  7. 2
      sapl/templates/sessao/adicionar_varias_materias_expediente.html
  8. 1
      sapl/urls.py

15
README.rst

@ -190,24 +190,20 @@ Instalação e configuração das dependências do projeto
http://localhost:8000/
Instruções para criação dos grupos de perfis de usuários e os usuários de testes
Instruções para criação do super usuário e de usuários de testes
===========================================================================
* Criar super usuário do django-contrib-admin (Será solicitado alguns dados para criação)::
./manage.py createsuperuser
Os perfis semânticos do SAPL devem ser criados manualmente através da execução de um script que gera esses perfis e adiciona um usuário padrão em cada perfil. Para testar o comportamento de cada perfil é necessário executar este script:
* `Os perfis semânticos do SAPL <https://github.com/interlegis/sapl/blob/master/sapl/rules/__init__.py>`_ são fixos e atualizados a cada execução do comando:
* Execute::
./manage.py shell_plus
* Será aberto um prompt do python customizado com diversas funcionalidades do django e do sapl. Execute dentro do prompt::
./manage.py migrate
%run scripts/inicializa_grupos_autorizacoes.py
* Os perfis fixos não aceitam customização via admin, porém outros grupos podem ser criados. O SAPL não interferirá no conjunto de permissões definidas em grupos customizados e se comportará diante de usuários segundo seus grupos e suas permissões.
* Os usuários criados, todos com senha "interlegis", serão::
* Os usuários de testes de perfil são criados apenas se o SAPL estiver rodando em modo DEBUG=True. Todos com senha "interlegis", serão::
operador_administrativo
operador_protocoloadm
@ -217,7 +213,6 @@ Os perfis semânticos do SAPL devem ser criados manualmente através da execuç
operador_sessao
operador_painel
operador_geral
operador_autor
Instruções para Tradução
========================

129
sapl/compilacao/models.py

@ -1,3 +1,5 @@
from datetime import datetime
from django.contrib import messages
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
@ -6,9 +8,11 @@ from django.db.models import F, Q
from django.db.models.aggregates import Max
from django.http.response import Http404
from django.template import defaultfilters
from django.utils.decorators import classonlymethod
from django.utils.translation import ugettext_lazy as _
from sapl.compilacao.utils import int_to_letter, int_to_roman
from sapl.compilacao.utils import int_to_letter, int_to_roman,\
get_integrations_view_names
from sapl.utils import YES_NO_CHOICES, get_settings_auth_user_model
@ -280,6 +284,129 @@ class TextoArticulado(TimestampedMixin):
return True
@classonlymethod
def update_or_create(cls, view_integracao, obj):
map_fields = view_integracao.map_fields
ta_values = getattr(view_integracao, 'ta_values', {})
related_object_type = ContentType.objects.get_for_model(obj)
ta = TextoArticulado.objects.filter(
object_id=obj.pk,
content_type=related_object_type)
ta_exists = bool(ta.exists())
if not ta_exists:
tipo_ta = TipoTextoArticulado.objects.filter(
content_type=related_object_type).first()
ta = TextoArticulado()
ta.tipo_ta = tipo_ta
ta.content_object = obj
ta.privacidade = ta_values.get('privacidade', STATUS_TA_EDITION)
ta.editing_locked = ta_values.get('editing_locked', False)
ta.editable_only_by_owners = ta_values.get(
'editable_only_by_owners', False)
else:
ta = ta[0]
if not ta.data:
ta.data = getattr(obj, map_fields['data']
if map_fields['data'] else 'xxx',
datetime.now())
if not ta.data:
ta.data = datetime.now()
ta.ementa = getattr(
obj, map_fields['ementa']
if map_fields['ementa'] else 'xxx', _(
'Integração com %s sem ementa.') % obj)
ta.observacao = getattr(
obj, map_fields['observacao']
if map_fields['observacao'] else 'xxx', '')
ta.numero = getattr(
obj, map_fields['numero']
if map_fields['numero'] else 'xxx', int('%s%s%s' % (
int(datetime.now().year),
int(datetime.now().month),
int(datetime.now().day))))
ta.ano = getattr(obj, map_fields['ano']
if map_fields['ano'] else 'xxx', datetime.now().year)
ta.save()
return ta
def clone_for(self, obj):
# O clone gera um texto válido original dada a base self,
# mesmo sendo esta base um texto compilado.
# Os dispositivos a clonar será com base no texto compilado
assert self.tipo_ta and self.tipo_ta.content_type, _(
'Não é permitido chamar o método clone_for '
'para Textos Articulados independentes.')
view_integracao = list(filter(lambda x:
x.model == obj._meta.model,
get_integrations_view_names()))
assert len(view_integracao) > 0, _(
'Não é permitido chamar o método clone_for '
'se não existe integração.')
assert len(view_integracao) == 1, _(
'Não é permitido haver mais de uma integração para um Model.')
view_integracao = view_integracao[0]
ta = TextoArticulado.update_or_create(view_integracao, obj)
dispositivos = Dispositivo.objects.filter(ta=self).order_by('ordem')
map_ids = {}
for d in dispositivos:
id_old = d.id
# TODO
# validar isso: é o suficiente para pegar apenas o texto válido?
# exemplo:
# quando uma matéria for alterada por uma emenda
# ao usar esta função para gerar uma norma deve vir apenas
# o texto válido, compilado...
if d.dispositivo_subsequente:
continue
d.id = None
d.inicio_vigencia = ta.data
d.fim_vigencia = None
d.inicio_eficacia = ta.data
d.fim_eficacia = None
d.publicacao = None
d.ta = ta
d.ta_publicado = None
d.dispositivo_subsequente = None
d.dispositivo_substituido = None
d.dispositivo_vigencia = None
d.dispositivo_atualizador = None
d.save()
map_ids[id_old] = d.id
dispositivos = Dispositivo.objects.filter(ta=ta).order_by('ordem')
for d in dispositivos:
if not d.dispositivo_pai:
continue
d.dispositivo_pai_id = map_ids[d.dispositivo_pai_id]
d.save()
return ta
def reagrupar_ordem_de_dispositivos(self):
dpts = Dispositivo.objects.filter(ta=self)

14
sapl/compilacao/utils.py

@ -1,3 +1,4 @@
import sys
DISPOSITIVO_SELECT_RELATED = (
'tipo_dispositivo',
@ -52,3 +53,16 @@ def int_to_letter(int_value):
result = chr(rest + 65) + result
result = chr(int_value + 65) + result
return result
def get_integrations_view_names():
result = []
modules = sys.modules
for key, value in modules.items():
if key.endswith('.views'):
for v in value.__dict__.values():
if hasattr(v, '__bases__'):
for base in v.__bases__:
if 'IntegracaoTaView' in str(base):
result.append(v)
return result

85
sapl/compilacao/views.py

@ -45,7 +45,8 @@ from sapl.compilacao.models import (Dispositivo, Nota,
VeiculoPublicacao, Vide, STATUS_TA_EDITION,
STATUS_TA_PRIVATE, STATUS_TA_PUBLIC)
from sapl.compilacao.utils import (DISPOSITIVO_SELECT_RELATED,
DISPOSITIVO_SELECT_RELATED_EDIT)
DISPOSITIVO_SELECT_RELATED_EDIT,
get_integrations_view_names)
from sapl.crud.base import Crud, CrudListView, make_pagination
from sapl.settings import BASE_DIR
@ -60,19 +61,6 @@ TipoDispositivoCrud = Crud.build(
logger = logging.getLogger(BASE_DIR.name)
def get_integrations_view_names():
result = []
modules = sys.modules
for key, value in modules.items():
if key.endswith('.views'):
for v in value.__dict__.values():
if hasattr(v, '__bases__'):
for base in v.__bases__:
if base == IntegracaoTaView:
result.append(v)
return result
def choice_models_in_extenal_views():
integrations_view_names = get_integrations_view_names()
result = [(None, '-------------'), ]
@ -165,54 +153,35 @@ class IntegracaoTaView(TemplateView):
object_id=item.pk,
content_type=related_object_type)
tipo_ta = TipoTextoArticulado.objects.filter(
content_type=related_object_type)
ta_exists = bool(ta.exists())
if not ta_exists:
ta = TextoArticulado()
tipo_ta = TipoTextoArticulado.objects.filter(
content_type=related_object_type)[:1]
if tipo_ta.exists():
ta.tipo_ta = tipo_ta[0]
ta.content_object = item
ta.privacidade = ta_values.get('privacidade', STATUS_TA_EDITION)
if (ta_exists or
(request.user.has_perm(
'compilacao.change_dispositivo_edicao_dinamica') and
ta_values.get('privacidade', STATUS_TA_EDITION
) != STATUS_TA_PRIVATE) or
(request.user.has_perm(
'compilacao.change_your_dispositivo_edicao_dinamica') and
ta_values.get('privacidade', STATUS_TA_EDITION
) == STATUS_TA_PUBLIC)):
"""
o texto articulado será criado/atualizado se:
- texto articulado foi criado.
ta.editing_locked = ta_values.get('editing_locked', False)
ta.editable_only_by_owners = ta_values.get(
'editable_only_by_owners', False)
- não foi criado e o usuário possui permissão para criar
desde que o texto não seja um texto privado pois a permissão
para criar textos privados é diferente.
- não foi criado e o usuário possui permissão para criar desde
que o texto seja privado e a permissão seja específica para
textos privados.
"""
pass
else:
ta = ta[0]
if not ta.data:
ta.data = getattr(item, map_fields['data']
if map_fields['data'] else 'xxx',
datetime.now())
if not ta.data:
ta.data = datetime.now()
ta.ementa = getattr(
item, map_fields['ementa']
if map_fields['ementa'] else 'xxx', _(
'Integração com %s sem ementa.') % item)
ta.observacao = getattr(
item, map_fields['observacao']
if map_fields['observacao'] else 'xxx', '')
ta.numero = getattr(
item, map_fields['numero']
if map_fields['numero'] else 'xxx', int('%s%s%s' % (
int(datetime.now().year),
int(datetime.now().month),
int(datetime.now().day))))
ta.ano = getattr(item, map_fields['ano']
if map_fields['ano'] else 'xxx', datetime.now().year)
ta.save()
messages.info(request, _('%s não possui %s.') % (
item, TextoArticulado._meta.verbose_name))
return redirect('/message')
ta = TextoArticulado.update_or_create(self, item)
if not ta_exists:
if ta.editable_only_by_owners and\

21
sapl/legacy_migration_settings.py

@ -1,19 +1,30 @@
# Settings for data migration from mysql legacy to new postgres database
import os
from decouple import Config, RepositoryEnv, AutoConfig
from dj_database_url import parse as db_url
from .settings import * # flake8: noqa
config = AutoConfig()
config.config = Config(RepositoryEnv(os.path.abspath('sapl/legacy/.env')))
INSTALLED_APPS += (
'sapl.legacy', # legacy reversed model definitions
)
DATABASES['legacy'] = {
DATABASES['legacy'] = config('DATABASE_URL', cast=db_url,)
"""DATABASES['legacy'] = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'sapl25',
'NAME': 'legacy_interlegis',
'USER': 'root',
'PASSWORD': 'admin',
'HOST': 'localhost', # Or an IP Address that your DB is hosted on
'PASSWORD': '',
'HOST': '', # Or an IP Address that your DB is hosted on
'PORT': '3306',
}
"""
DATABASE_ROUTERS = ['sapl.legacy.router.LegacyRouter', ]

16
sapl/materia/forms.py

@ -22,7 +22,7 @@ import django_filters
from sapl.base.models import Autor
from sapl.comissoes.models import Comissao
from sapl.compilacao.models import STATUS_TA_PRIVATE,\
STATUS_TA_IMMUTABLE_PUBLIC, TextoArticulado
STATUS_TA_IMMUTABLE_PUBLIC, TextoArticulado, STATUS_TA_PUBLIC
from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column,
to_row)
from sapl.materia.models import TipoProposicao, MateriaLegislativa,\
@ -472,7 +472,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet):
ementa = django_filters.CharFilter(lookup_expr='icontains')
em_tramitacao = django_filters.ChoiceFilter(required=False,
label=u'Ano da Matéria',
label=u'Em tramitação',
choices=em_tramitacao)
o = MateriaPesquisaOrderingFilter()
@ -1212,14 +1212,10 @@ class ConfirmarProposicaoForm(ProposicaoForm):
if proposicao.texto_articulado.exists():
ta = proposicao.texto_articulado.first()
ta.id = None
ta.content_object = materia
ta.save()
pass
# FIXME - gerar texto_articulado da materia com base na prop.
# materia.texto_articulo = proposicao.texto_articulado
ta_materia = ta.clone_for(materia)
ta_materia.editing_locked = True
ta_materia.privacidade = STATUS_TA_IMMUTABLE_PUBLIC
ta_materia.save()
self.instance.results['messages']['success'].append(_(
'Matéria Legislativa registrada com sucesso (%s)'

2
sapl/templates/sessao/adicionar_varias_materias_expediente.html

@ -52,7 +52,7 @@
{% for m in page_obj %}
<tr>
<td>
<input type="checkbox" name="materia_id" value="{{m.id}}" {% if check %} checked {% endif %}/>
<input type="checkbox" name="materia_id" id="{{m.id}}" value="{{m.id}}" {% if check %} checked {% endif %}>
<strong><a href="{% url 'sapl.materia:materialegislativa_detail' m.id %}">{{m.tipo.sigla}} {{m.numero}}/{{m.ano}} - {{m.tipo}}</strong></a></br>
<strong>Autores:</strong>
{% for a in m.autoria_set.all %}

1
sapl/urls.py

@ -36,6 +36,7 @@ import sapl.sessao.urls
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='index.html')),
url(r'^message$', TemplateView.as_view(template_name='base.html')),
url(r'^admin/', include(admin.site.urls)),
url(r'', include(sapl.comissoes.urls)),

Loading…
Cancel
Save