diff --git a/sapl/compilacao/migrations/0060_auto_20161101_0913.py b/sapl/compilacao/migrations/0060_auto_20161101_0913.py new file mode 100644 index 000000000..851746ec0 --- /dev/null +++ b/sapl/compilacao/migrations/0060_auto_20161101_0913.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-01 09:13 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0059_auto_20161027_1323'), + ] + + operations = [ + migrations.AlterModelOptions( + name='dispositivo', + options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('view_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, + ), + ] diff --git a/sapl/compilacao/migrations/0061_auto_20161101_1025.py b/sapl/compilacao/migrations/0061_auto_20161101_1025.py new file mode 100644 index 000000000..d74bdc8da --- /dev/null +++ b/sapl/compilacao/migrations/0061_auto_20161101_1025.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-01 10:25 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0060_auto_20161101_0913'), + ] + + operations = [ + migrations.AlterField( + model_name='dispositivo', + name='ta', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dispositivos_set', to='compilacao.TextoArticulado', verbose_name='Texto Articulado'), + ), + ] diff --git a/sapl/compilacao/migrations/0062_auto_20161101_1221.py b/sapl/compilacao/migrations/0062_auto_20161101_1221.py new file mode 100644 index 000000000..63e703843 --- /dev/null +++ b/sapl/compilacao/migrations/0062_auto_20161101_1221.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-01 12:21 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0061_auto_20161101_1025'), + ] + + operations = [ + migrations.AlterModelOptions( + name='dispositivo', + options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('view_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.'), ('change_dispositivo_de_vigencia_global', 'Permissão alteração global do dispositivo de vigência')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index f026222c3..117a79289 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -635,7 +635,7 @@ class Dispositivo(BaseModel, TimestampedMixin): ta = models.ForeignKey( TextoArticulado, - on_delete=models.PROTECT, + on_delete=models.CASCADE, related_name='dispositivos_set', verbose_name=_('Texto Articulado')) ta_publicado = models.ForeignKey( @@ -702,8 +702,10 @@ class Dispositivo(BaseModel, TimestampedMixin): 'via formulários de edição avançada.')), ('change_dispositivo_registros_compilacao', _( 'Permissão de registro de compilação via editor dinâmico.')), - ('change_dispositivo_notificacoes', _( + ('view_dispositivo_notificacoes', _( 'Permissão de acesso às notificações de pendências.')), + ('change_dispositivo_de_vigencia_global', _( + 'Permissão alteração global do dispositivo de vigência')), ) def __str__(self): @@ -1260,7 +1262,7 @@ class Dispositivo(BaseModel, TimestampedMixin): disps[0].get_numero_completo()) # dispositivo.transform_in_next() else: - dispositivo.set_numero_completo([1, 0, 0, 0, 0, 0, ]) + dispositivo.set_numero_completo([0, 0, 0, 0, 0, 0, ]) else: if ';' in tipo_base.rotulo_prefixo_texto: diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index 0b6a476a9..d3b4739a0 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -46,14 +46,15 @@ from sapl.compilacao.models import (Dispositivo, Nota, VeiculoPublicacao, Vide) from sapl.compilacao.utils import (DISPOSITIVO_SELECT_RELATED, DISPOSITIVO_SELECT_RELATED_EDIT) -from sapl.crud.base import Crud, CrudListView, make_pagination +from sapl.crud.base import CrudAux, CrudListView, make_pagination from sapl.settings import BASE_DIR -TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') -TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') -TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') -VeiculoPublicacaoCrud = Crud.build(VeiculoPublicacao, 'veiculo_publicacao') -TipoDispositivoCrud = Crud.build(TipoDispositivo, 'tipo_dispositivo') +TipoNotaCrud = CrudAux.build(TipoNota, 'tipo_nota') +TipoVideCrud = CrudAux.build(TipoVide, 'tipo_vide') +TipoPublicacaoCrud = CrudAux.build(TipoPublicacao, 'tipo_publicacao') +VeiculoPublicacaoCrud = CrudAux.build(VeiculoPublicacao, 'veiculo_publicacao') +TipoDispositivoCrud = CrudAux.build( + TipoDispositivo, 'tipo_dispositivo') logger = logging.getLogger(BASE_DIR.name) @@ -86,12 +87,31 @@ def choice_models_in_extenal_views(): return result +def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): + yield None, '-------------' + + if not id_tipo_ta: + return + + tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) + + integrations_view_names = get_integrations_view_names() + for item in integrations_view_names: + if hasattr(item, 'model_type_foreignkey'): + if (tipo_ta.content_type.model == item.model.__name__.lower() and + tipo_ta.content_type.app_label == + item.model._meta.app_label): + for i in item.model_type_foreignkey.objects.all(): + yield i.pk, i + + class IntegracaoTaView(TemplateView): def get_redirect_deactivated(self): messages.error( self.request, - _('O modulo de Textos Articulados está desativado.')) + _('O modulo de Textos Articulados para %s está desativado.' + ) % self.model._meta.verbose_name_plural) return redirect('/') def get(self, request, *args, **kwargs): @@ -107,6 +127,25 @@ class IntegracaoTaView(TemplateView): str(e))) return self.get_redirect_deactivated() + assert hasattr(self, 'map_fields'), _( + """ + O mapa dos campos não foi definido. Ele deve seguir a estrutura + de chaves abaixo: + + map_fields = { + 'data': 'data', + 'ementa': 'ementa', + 'observacao': 'observacao', + 'numero': 'numero', + 'ano': 'ano', + } + + Caso o model de integração não possua um dos campos, + implemente, ou passe `None` para as chaves que são fixas. + """) + + mf = self.map_fields + item = get_object_or_404(self.model, pk=kwargs['pk']) related_object_type = ContentType.objects.get_for_model(item) @@ -127,64 +166,24 @@ class IntegracaoTaView(TemplateView): else: ta = ta[0] - if hasattr(item, 'ementa') and item.ementa: - ta.ementa = item.ementa - else: - ta.ementa = _('Integração com %s sem ementa.') % item - - if hasattr(item, 'observacao') and item.observacao: - ta.observacao = item.observacao - else: - ta.observacao = _('Integração com %s sem observacao.') % item - - if hasattr(item, 'numero') and item.numero: - ta.numero = item.numero - else: - ta.numero = int('%s%s%s' % ( - int(datetime.now().year), - int(datetime.now().month), - int(datetime.now().day))) - - if hasattr(item, 'ano') and item.ano: - ta.ano = item.ano - else: - ta.ano = datetime.now().year - - if hasattr(item, 'data_apresentacao'): - ta.data = item.data_apresentacao - elif hasattr(item, 'data'): - ta.data = item.data - else: - ta.data = datetime.now() + ta.data = getattr(item, mf['data'], datetime.now()) + ta.ementa = getattr( + item, mf['ementa'], _('Integração com %s sem ementa.') % item) + ta.observacao = getattr(item, mf['observacao'], '') + ta.numero = getattr(item, mf['numero'], int('%s%s%s' % ( + int(datetime.now().year), + int(datetime.now().month), + int(datetime.now().day)))) + ta.ano = getattr(item, mf['ano'], datetime.now().year) ta.save() - return redirect(to=reverse_lazy('sapl.compilacao:ta_text', - kwargs={'ta_id': ta.pk})) - - """msg = messages.error if not request.user.is_anonymous( - ) else messages.info - - msg(request, - _('A funcionalidade de Textos Articulados está desativada.')) - - if not request.user.is_anonymous(): - msg( - request, - _('Para ativá-la, os Tipos de Textos devem ser criados.')) - - msg(request, - _('Sua tela foi redirecionada para a tela de ' - 'cadastro de Textos Articulados.')) - - return redirect(to=reverse_lazy('sapl.compilacao:tipo_ta_list', - kwargs={})) + if Dispositivo.objects.filter(ta_id=ta.pk).exists(): + return redirect(to=reverse_lazy('sapl.compilacao:ta_text', + kwargs={'ta_id': ta.pk})) else: - - return redirect(to=reverse_lazy( - '%s:%s_detail' % ( - item._meta.app_config.name, item._meta.model_name), - kwargs={'pk': item.pk}))""" + return redirect(to=reverse_lazy('sapl.compilacao:ta_text_edit', + kwargs={'ta_id': ta.pk})) def import_pattern(self): @@ -539,24 +538,6 @@ class VideMixin(DispositivoSuccessUrlMixin): return super(VideMixin, self).dispatch(*args, **kwargs) -def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): - yield None, '-------------' - - if not id_tipo_ta: - return - - tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) - - integrations_view_names = get_integrations_view_names() - for item in integrations_view_names: - if hasattr(item, 'model_type_foreignkey'): - if (tipo_ta.content_type.model == item.model.__name__.lower() and - tipo_ta.content_type.app_label == - item.model._meta.app_label): - for i in item.model_type_foreignkey.objects.all(): - yield i.pk, i - - class VideCreateView(VideMixin, CreateView): model = Vide template_name = 'compilacao/ajax_form.html' @@ -710,39 +691,6 @@ class TextView(CompMixin, ListView): def get(self, request, *args, **kwargs): ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) self.object = ta - if ta.content_object: - item = ta.content_object - self.object = item - if hasattr(item, 'ementa') and item.ementa: - ta.ementa = item.ementa - else: - ta.ementa = _('Integração com %s sem ementa.') % item - - if hasattr(item, 'observacao') and item.observacao: - ta.observacao = item.observacao - else: - ta.observacao = _('Integração com %s sem observacao.') % item - - if hasattr(item, 'numero') and item.numero: - ta.numero = item.numero - else: - ta.numero = int('%s%s%s' % ( - int(datetime.now().year), - int(datetime.now().month), - int(datetime.now().day))) - - if hasattr(item, 'ano') and item.ano: - ta.ano = item.ano - else: - ta.ano = datetime.now().year - - if hasattr(item, 'data_apresentacao'): - ta.data = item.data_apresentacao - elif hasattr(item, 'data'): - ta.data = item.data - else: - ta.data = datetime.now() - ta.save() return super(TextView, self).get(request, *args, **kwargs) @@ -1720,6 +1668,12 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): for td in otds: + if td.dispositivo_de_alteracao: + if not self.request.user.has_perm( + 'compilacao.' + 'change_dispositivo_registros_compilacao'): + continue + if paradentro and not td.permitido_inserir_in( tipb, include_relative_autos=True, diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index b887569f4..e95d38f8a 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1,7 +1,8 @@ -from datetime import date, datetime import os +from datetime import date, datetime +import django_filters from crispy_forms.bootstrap import (Alert, FormActions, InlineCheckboxes, InlineRadios) from crispy_forms.helper import FormHelper @@ -17,8 +18,8 @@ from django.db.models import Max from django.forms import ModelForm, widgets from django.forms.forms import Form from django.utils.translation import ugettext_lazy as _ -import django_filters +import sapl from sapl.base.models import Autor from sapl.comissoes.models import Comissao from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, @@ -30,10 +31,9 @@ from sapl.parlamentares.models import Parlamentar from sapl.protocoloadm.models import Protocolo from sapl.settings import MAX_DOC_UPLOAD_SIZE from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, - ChoiceWithoutValidationField, RangeWidgetOverride, - autor_label, autor_modal, models_with_gr_for_model, - MateriaPesquisaOrderingFilter) -import sapl + ChoiceWithoutValidationField, + MateriaPesquisaOrderingFilter, RangeWidgetOverride, + autor_label, autor_modal, models_with_gr_for_model) from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, Numeracao, diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 7be1e8560..0e42c8a6e 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -68,6 +68,13 @@ TipoFimRelatoriaCrud = CrudAux.build( class MateriaTaView(IntegracaoTaView): model = MateriaLegislativa model_type_foreignkey = TipoMateriaLegislativa + map_fields = { + 'data': 'data_apresentacao', + 'ementa': 'ementa', + 'observacao': 'observacao', + 'numero': 'numero', + 'ano': 'ano', + } def get(self, request, *args, **kwargs): """ @@ -84,8 +91,12 @@ class MateriaTaView(IntegracaoTaView): class ProposicaoTaView(IntegracaoTaView): model = Proposicao model_type_foreignkey = TipoProposicao - # TODO implementar o mapa de fields e utiliza-lo em IntegracaoTaView - fields = { + map_fields = { + 'data': 'data_recebimento', + 'ementa': 'descricao', + 'observacao': None, + 'numero': 'numero_proposicao', + 'ano': 'ano', } def get(self, request, *args, **kwargs): diff --git a/sapl/norma/views.py b/sapl/norma/views.py index 283c43bb8..27b7d7b4c 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -28,6 +28,13 @@ TipoNormaCrud = CrudAux.build( class NormaTaView(IntegracaoTaView): model = NormaJuridica model_type_foreignkey = TipoNormaJuridica + map_fields = { + 'data': 'data', + 'ementa': 'ementa', + 'observacao': 'observacao', + 'numero': 'numero', + 'ano': 'ano', + } def get(self, request, *args, **kwargs): """ diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index c3bab49e7..b439ffb88 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -1,5 +1,6 @@ from datetime import datetime +import django_filters from crispy_forms.bootstrap import InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout, Submit @@ -8,19 +9,17 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ -import django_filters from sapl.base.models import Autor from sapl.crispy_layout_mixin import form_actions, to_row from sapl.materia.models import UnidadeTramitacao -from sapl.utils import (RANGE_ANOS, RangeWidgetOverride, autor_label, - autor_modal, AnoNumeroOrderingFilter) +from sapl.utils import (RANGE_ANOS, AnoNumeroOrderingFilter, + RangeWidgetOverride, autor_label, autor_modal) from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) - TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido'), ('', 'Ambos')] NATUREZA_PROCESSO = [('', 'Ambos'), diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 00438b8e8..570af1aa2 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -137,10 +137,11 @@ rules_group_norma = { (compilacao.Vide, __base__), (compilacao.Nota, __base__), (compilacao.Dispositivo, __base__ + [ - 'change_dispositivo_notificacoes', + 'view_dispositivo_notificacoes', 'change_dispositivo_edicao_dinamica', 'change_dispositivo_edicao_avancada', - 'change_dispositivo_registros_compilacao' + 'change_dispositivo_registros_compilacao', + 'change_dispositivo_de_vigencia_global' ]) ] } diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index 988a0920b..1ade99710 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -1,19 +1,20 @@ from datetime import datetime +import django_filters from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Fieldset, Layout from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ -import django_filters from sapl.crispy_layout_mixin import form_actions, to_row from sapl.materia.forms import MateriaLegislativaFilterSet from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.parlamentares.models import Parlamentar -from sapl.utils import RANGE_DIAS_MES, RANGE_MESES, autor_label, autor_modal,\ - MateriaPesquisaOrderingFilter +from sapl.utils import (RANGE_DIAS_MES, RANGE_MESES, + MateriaPesquisaOrderingFilter, autor_label, + autor_modal) from .models import (Bancada, ExpedienteMateria, Orador, OradorExpediente, OrdemDia, SessaoPlenaria, SessaoPlenariaPresenca) diff --git a/sapl/templates/compilacao/ajax_actions_dinamic_edit.html b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html index c819723b7..55e0ba431 100644 --- a/sapl/templates/compilacao/ajax_actions_dinamic_edit.html +++ b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html @@ -1,21 +1,23 @@ {% load i18n %}
@@ -61,11 +65,13 @@ {% endfor %} {%endif%} - {% if not object.ta_publicado and not object.dispositivo_subsequente and not object.tipo_dispositivo.dispositivo_de_alteracao%} -