From d65200797447d4e8681848842253d3e42cf7297b Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Mon, 31 Oct 2016 12:57:45 -0200 Subject: [PATCH 01/24] FIX #768 --- sapl/sessao/forms.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index f213e1b94..c99691656 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -21,7 +21,10 @@ from .models import (Bancada, ExpedienteMateria, Orador, OradorExpediente, def recupera_anos(): try: anos_list = SessaoPlenaria.objects.all().dates('data_inicio', 'year') - anos = [(k.year, k.year) for k in anos_list] + # a listagem deve ser em ordem descrescente, mas por algum motivo + # a adicao de .order_by acima depois do all() nao surte efeito + # apos a adicao do .dates(), por isso o reversed() abaixo + anos = [(k.year, k.year) for k in reversed(anos_list)] return anos except: return [] From 57c4fbc5b9dc3944650ee87e8a66eb1f8f606950 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Mon, 31 Oct 2016 14:08:31 -0200 Subject: [PATCH 02/24] Add teste q valida perms adicionadas em decorators --- sapl/rules/tests/test_rules.py | 28 ++++ scripts/lista_permissions_in_decorators.py | 142 +++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 scripts/lista_permissions_in_decorators.py diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index e03bf85d0..be145e3ea 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -9,6 +9,8 @@ import pytest from sapl.rules import SAPL_GROUPS from sapl.rules.map_rules import rules_patterns from sapl.test_urls import create_perms_post_migrate +from scripts.lista_permissions_in_decorators import \ + lista_permissions_in_decorators from scripts.lista_urls import lista_urls @@ -152,3 +154,29 @@ def test_permission_required_of_views_exists(url_item): assert p, _('Permissão (%s) na view (%s) não existe.') % ( codename, view) + + +_lista_permissions_in_decorators = lista_permissions_in_decorators() + + +@pytest.mark.django_db(transaction=False) +@pytest.mark.parametrize('permission', _lista_permissions_in_decorators) +def test_permission_required_of_decorators(permission): + """ + testa se, nos decorators permission_required com ou sem method_decorator + as permissões fixas escritas manualmente realmente exitem em Permission + """ + + for app in sapl_appconfs: + # readequa permissões dos models adicionando + # list e detail permissions + create_perms_post_migrate(app) + + codename = permission[0].split('.') + p = Permission.objects.filter( + content_type__app_label=codename[0], + codename=codename[1]).exists() + + assert p, _('Permissão (%s) na view (%s) não existe.') % ( + permission[0], + permission[1]) diff --git a/scripts/lista_permissions_in_decorators.py b/scripts/lista_permissions_in_decorators.py new file mode 100644 index 000000000..8138cd0f7 --- /dev/null +++ b/scripts/lista_permissions_in_decorators.py @@ -0,0 +1,142 @@ +import ast +import inspect +import os + + +if __name__ == '__main__': + + import django + + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sapl.settings") + django.setup() + +if True: + from scripts.lista_urls import lista_urls + + +def get_decorators(cls): + target = cls + decorators = {} + + def visit_FunctionDef(node): + decorators[node.name] = [] + for n in node.decorator_list: + name = '' + if isinstance(n, ast.Call): + name = n.func.attr if isinstance( + n.func, ast.Attribute) else n.func.id + else: + name = n.attr if isinstance(n, ast.Attribute) else n.id + + decorators[node.name].append(name) + + node_iter = ast.NodeVisitor() + node_iter.visit_FunctionDef = visit_FunctionDef + node_iter.visit(ast.parse(inspect.getsource(target))) + return decorators + + +def get_permission_requireds(cls): + target = cls + decorators = [] + + def get_permission_required(arg): + + for perm in arg.args: + + if isinstance(perm, ast.Str): + decorators.append(getattr(perm, perm._fields[0])) + continue + + if isinstance(perm, (ast.Tuple, ast.List)): + if 'elts' not in perm._fields: + continue + + for elt in perm.elts: + + if isinstance(elt, ast.Str): + decorators.append(getattr(elt, elt._fields[0])) + + def get_method_decorator(n): + for arg in n.args: + + if not isinstance(arg, ast.Call): + continue + + """ + Espera-se que: + - o decorator seja uma função + - esta função tenha o meta atributo 'id' + - id = 'permission_required' + - esta função tenha argumento args + """ + if ('func' not in arg._fields or + 'id' not in arg.func._fields or + arg.func.id != 'permission_required' or + 'args' not in arg._fields): + continue + + get_permission_required(arg) + + def visit_FunctionDef(node): + for n in node.decorator_list: + if not isinstance(n, ast.Call): + continue + + """ + Espera-se que: + - o decorator seja uma função + - esta função tenha o meta atributo 'id' + - id = 'method_decorator' + - esta função tenha argumento args + """ + if ('func' not in n._fields or + 'id' not in n.func._fields or + n.func.id != 'method_decorator' or + 'args' not in n._fields): + get_permission_required(n) + else: + get_method_decorator(n) + + node_iter = ast.NodeVisitor() + node_iter.visit_FunctionDef = visit_FunctionDef + node_iter.visit(ast.parse(inspect.getsource(target))) + return decorators + + +class ListaPermissionInDecorators(): + decorators = [] + + def lista_permissions_in_decorators(self): + urls = lista_urls() + + for url_item in urls: + key, url, var, app_name = url_item + if hasattr(key, 'view_class'): + view = key.view_class + elif hasattr(key, 'cls'): + view = key.cls + else: + view = key + + if not view.__module__.startswith('sapl.'): + continue + + try: + decorators = list(map(lambda x: (x, view), + get_permission_requireds(view) + )) + self.decorators += decorators + except: + pass + return self.decorators + + def __call__(self): + return self.lista_permissions_in_decorators() + + +lista_permissions_in_decorators = ListaPermissionInDecorators() + +if __name__ == '__main__': + _lista_permissions_in_decorators = lista_permissions_in_decorators() + print(_lista_permissions_in_decorators) From fc0fbda3da7b71577e20db340529e12fdfca8f01 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Mon, 31 Oct 2016 14:30:35 -0200 Subject: [PATCH 03/24] =?UTF-8?q?Ajusta=20seq=20de=20heran=C3=A7a=20de=20M?= =?UTF-8?q?ixin=20de=20perm=20em=20doc=20adm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/protocoloadm/views.py | 71 +++++--------------------------------- 1 file changed, 9 insertions(+), 62 deletions(-) diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 36c15718f..0e78cce97 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -47,8 +47,7 @@ class DocumentoAdministrativoMixin: if app_config and app_config.documentos_administrativos == 'O': return True - return self.request.user.has_module_perms( - sapl.base.models.AppConfig.label) + return super().has_permission() class DocumentoAdministrativoCrud(Crud): @@ -60,10 +59,10 @@ class DocumentoAdministrativoCrud(Crud): 'numero_protocolo', 'assunto', 'interessado', 'tramitacao', 'texto_integral'] - class ListView(Crud.ListView, DocumentoAdministrativoMixin): + class ListView(DocumentoAdministrativoMixin, Crud.ListView): pass - class DetailView(Crud.DetailView, DocumentoAdministrativoMixin): + class DetailView(DocumentoAdministrativoMixin, Crud.DetailView): pass @@ -356,9 +355,9 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView): return redirect(self.get_success_url()) -class PesquisarDocumentoAdministrativoView(PermissionRequiredMixin, - FilterView, - DocumentoAdministrativoMixin): +class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin, + PermissionRequiredMixin, + FilterView): model = DocumentoAdministrativo filterset_class = DocumentoAdministrativoFilterSet paginate_by = 10 @@ -565,65 +564,13 @@ class TramitacaoAdmCrud(MasterDetailCrud): class UpdateView(MasterDetailCrud.UpdateView): form_class = TramitacaoAdmEditForm - class ListView(MasterDetailCrud.ListView, DocumentoAdministrativoMixin): + class ListView(DocumentoAdministrativoMixin, MasterDetailCrud.ListView): def get_queryset(self): qs = super(MasterDetailCrud.ListView, self).get_queryset() kwargs = {self.crud.parent_field: self.kwargs['pk']} return qs.filter(**kwargs).order_by('-data_tramitacao', '-id') - class DetailView(MasterDetailCrud.DetailView, - DocumentoAdministrativoMixin): + class DetailView(DocumentoAdministrativoMixin, + MasterDetailCrud.DetailView): pass - - -""" -def get_nome_autor(request): - nome_autor = '' - if request.method == 'GET': - id = request.GET.get('id', '') - try: - autor = Autor.objects.get(pk=id) - if autor.parlamentar: - nome_autor = autor.parlamentar.nome_parlamentar - elif autor.comissao: - nome_autor = autor.comissao.nome - except ObjectDoesNotExist: - pass - return HttpResponse("{\"nome\":\"" + nome_autor + "\"}", - content_type="application/json; charset=utf-8")""" - -""" -def pesquisa_autores(request): - q = '' - if request.method == 'GET': - q = request.GET.get('q', '') - - autor = Autor.objects.filter( - Q(nome__icontains=q) | - Q(parlamentar__nome_parlamentar__icontains=q) | - Q(comissao__nome__icontains=q) - ) - - autor = Autor.objects.filter(nome__icontains=q) - - autores = [] - - for a in autor: - nome = '' - if a.nome: - nome = a.nome - elif a.parlamentar: - nome = a.parlamentar.nome_parlamentar - elif a.comissao: - nome = a.comissao.nome - - autores.append((a.id, nome)) - - autores = sorted(autores, key=lambda x: x[1]) - - return HttpResponse(json.dumps(autores, - sort_keys=True, - ensure_ascii=False), - content_type="application/json; charset=utf-8") -""" From 5898519bb4a919676d95763195e70ae53f428762 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Mon, 31 Oct 2016 15:14:06 -0200 Subject: [PATCH 04/24] =?UTF-8?q?Add=20coment=C3=A1rio=20sobre=20def=20do?= =?UTF-8?q?=20sapl.rules.map=5Frules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/crud/base.py | 9 ++++--- sapl/rules/map_rules.py | 53 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/sapl/crud/base.py b/sapl/crud/base.py index 945ddf5ae..074c1719b 100644 --- a/sapl/crud/base.py +++ b/sapl/crud/base.py @@ -16,26 +16,25 @@ from django.http.response import Http404 from django.shortcuts import redirect from django.utils.decorators import classonlymethod from django.utils.encoding import force_text -from django.utils.translation import ugettext_lazy as _ from django.utils.translation import string_concat +from django.utils.translation import ugettext_lazy as _ from django.views.generic import (CreateView, DeleteView, DetailView, ListView, UpdateView) from django.views.generic.base import ContextMixin from django.views.generic.list import MultipleObjectMixin from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display +from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, + RP_DETAIL, RP_LIST) from sapl.settings import BASE_DIR from sapl.utils import normalize + logger = logging.getLogger(BASE_DIR.name) ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \ 'list', 'create', 'detail', 'update', 'delete' -# RP - Radical das permissões para "..." -RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ - '.list_', '.detail_', '.add_', '.change_', '.delete_', - def _form_invalid_message(msg): return '%s %s' % (_('Formulário inválido.'), msg) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 8f9441e62..75fe55ac3 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -1,7 +1,6 @@ from sapl.base import models as base from sapl.comissoes import models as comissoes from sapl.compilacao import models as compilacao -from sapl.crud.base import RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST from sapl.lexml import models as lexml from sapl.materia import models as materia from sapl.norma import models as norma @@ -16,7 +15,47 @@ from sapl.rules import (SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO) from sapl.sessao import models as sessao -# RP = Radicao de Permissão +""" +Todas as permissões do django framework seguem o padrão + + [app_label].[radical_de_permissao]_[model] + +ou seja, em sapl.norma.NormaJuridica, por exemplo, o django framework cria +três permissões registadas na classe Permission: + + definição uso + + - add_normajuridica norma.add_normajuridica + - change_normajuridica norma.change_normajuridica + - delete_normajuridica norma.delete_normajuridica + +No SAPL foram acrescidas em todos os models as duas regras abaixo, adicionadas +com o Signal post_migrate `create_proxy_permissions` +localizado em sapl.rules.apps.py. + + - list_normajuridica norma.list_normajuridica + - detail_normajuridica norma.detail_normajuridica + +Tanto o Crud implementado em sapl.crud.base.py quanto o Signal post_migrate +`update_groups` que é responsável por ler o mapa deste +arquivo (sapl.rules.map_rules.py) e criar os grupos definidos na regra de +negócio trabalham com os cinco radiais de permissão +e com qualquer outro tipo de permissão customizada, nesta ordem de precedência. + +Os cinco radicais de permissão completa são: + + RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ + '.list_', '.detail_', '.add_', '.change_', '.delete_', + +Tanto a app crud quanto a app rules estão sempre ligadas a um model. Ao lidar +com permissões, sempre é analisado se é apenas um radical ou permissão +completa, sendo apenas um radical, a permissão completa é montada com base +no model associado. +""" + +RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ + '.list_', '.detail_', '.add_', '.change_', '.delete_', + __base__ = [RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE] __listdetailchange__ = [RP_LIST, RP_DETAIL, RP_CHANGE] @@ -74,10 +113,12 @@ rules_group_materia = { (compilacao.Dispositivo, __base__ + [ 'change_dispositivo_edicao_dinamica', - # sobre a regra abaixo deve ser pensada sobre isso - # abre possibilidade pra haver compilacao de emenda com projeto - # mas testes devem ser feitos especificamente para materia - # 'change_dispositivo_registros_compilacao' + # TODO: adicionar 'change_dispositivo_registros_compilacao' + # quando testes forem feitos para permtir que matérias possam + # ser vinculadas a outras matérias via registro de compilação. + # Normalmente emendas e/ou projetos substitutivos podem alterar + # uma matéria original. Fazer esse registro de compilação + # oferecia um autografo eletrônico pronto ser convertido em Norma. ]) ] } From e70c72dcfc7bce4794e0e9747eaa0f97b032ab53 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Mon, 31 Oct 2016 16:01:43 -0200 Subject: [PATCH 05/24] =?UTF-8?q?add=20test=20que=20valida=20aus=C3=AAncia?= =?UTF-8?q?=20de=20perm=20em=20map=5Frules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/rules/map_rules.py | 4 +- sapl/rules/tests/test_rules.py | 77 +++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 75fe55ac3..00438b8e8 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -205,8 +205,8 @@ rules_group_geral = { (comissoes.TipoComissao, __base__), (comissoes.Periodo, __base__), - (materia.AssuntoMateria, []), # não há implementação - (materia.MateriaAssunto, []), # não há implementação + (materia.AssuntoMateria, __base__), # não há implementação + (materia.MateriaAssunto, __base__), # não há implementação (materia.TipoProposicao, __base__), (materia.TipoMateriaLegislativa, __base__), (materia.RegimeTramitacao, __base__), diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index be145e3ea..816c030af 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -6,8 +6,12 @@ from django.utils import six from django.utils.translation import ugettext_lazy as _ import pytest +from sapl.base.models import CasaLegislativa, ProblemaMigracao +from sapl.compilacao.models import TipoDispositivo,\ + PerfilEstruturalTextoArticulado, TipoDispositivoRelationship +from sapl.materia.models import AcompanhamentoMateria from sapl.rules import SAPL_GROUPS -from sapl.rules.map_rules import rules_patterns +from sapl.rules import map_rules from sapl.test_urls import create_perms_post_migrate from scripts.lista_permissions_in_decorators import \ lista_permissions_in_decorators @@ -26,7 +30,7 @@ sapl_models.reverse() def test_groups_in_rules_patterns(group_item): test = False - for rules_group in rules_patterns: + for rules_group in map_rules.rules_patterns: if rules_group['group'] == group_item: test = True @@ -37,7 +41,7 @@ def test_groups_in_rules_patterns(group_item): def test_models_in_rules_patterns(model_item): test = False - for rules_group in rules_patterns: + for rules_group in map_rules.rules_patterns: rules_model = rules_group['rules'] for rm in rules_model: if rm[0] == model_item: @@ -49,6 +53,68 @@ def test_models_in_rules_patterns(model_item): str(model_item), model_item._meta.verbose_name) +# __falsos_positivos__ +__fp__in__test_permission_of_models_in_rules_patterns = { + map_rules.RP_ADD: [CasaLegislativa, + ProblemaMigracao, + TipoDispositivo, + TipoDispositivoRelationship, + PerfilEstruturalTextoArticulado], + + map_rules.RP_CHANGE: [ProblemaMigracao, + AcompanhamentoMateria, + TipoDispositivo, + TipoDispositivoRelationship, + PerfilEstruturalTextoArticulado], + + map_rules.RP_DELETE: [CasaLegislativa, + ProblemaMigracao, + TipoDispositivo, + TipoDispositivoRelationship, + PerfilEstruturalTextoArticulado], + + map_rules.RP_LIST: [ProblemaMigracao, + AcompanhamentoMateria, + TipoDispositivo, + TipoDispositivoRelationship, + PerfilEstruturalTextoArticulado], + + map_rules.RP_DETAIL: [ProblemaMigracao, + AcompanhamentoMateria, + TipoDispositivo, + TipoDispositivoRelationship, + PerfilEstruturalTextoArticulado] + +} + + +@pytest.mark.parametrize('model_item', sapl_models) +def test_permission_of_models_in_rules_patterns(model_item): + + permissions = map_rules.__base__ + list(map(lambda x: x[0], + model_item._meta.permissions)) + + __fp__ = __fp__in__test_permission_of_models_in_rules_patterns + for perm in permissions: + if perm in __fp__ and model_item in __fp__[perm]: + continue + + test = False + for rules_group in map_rules.rules_patterns: + rules_model = rules_group['rules'] + for rm in rules_model: + model = rm[0] + rules = rm[1] + if model == model_item: + if perm in rules: + test = True + break + + assert test, _('A permissão (%s) do model (%s) não foi adicionado em ' + 'nenhum grupo padrão para regras de acesso.') % ( + perm, + str(model_item)) + @pytest.mark.django_db(transaction=False) @pytest.mark.parametrize('model_item', sapl_models) @@ -57,7 +123,7 @@ def test_permission_of_rules_exists(model_item): print(model_item) create_perms_post_migrate(model_item._meta.app_config) - for rules_group in rules_patterns: + for rules_group in map_rules.rules_patterns: rules_model = rules_group['rules'] for rm in rules_model: model = rm[0] @@ -77,7 +143,8 @@ def test_permission_of_rules_exists(model_item): content_type=content_type, codename=codename).exists() - assert p, _('Permissão (%s) no model (%s) não existe.') % ( + assert p, _('Permissão (%s) associada ao model (%s) ' + 'não está em _meta.permissions.') % ( codename, model_item) From c4cdfbe87d348564b5e8d701f38cb53a83a71710 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Mon, 31 Oct 2016 16:59:38 -0200 Subject: [PATCH 06/24] Corrige falha em teste add no commit anterior --- sapl/rules/tests/test_rules.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index 816c030af..bdc885558 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -88,11 +88,18 @@ __fp__in__test_permission_of_models_in_rules_patterns = { } +@pytest.mark.django_db(transaction=False) @pytest.mark.parametrize('model_item', sapl_models) def test_permission_of_models_in_rules_patterns(model_item): - permissions = map_rules.__base__ + list(map(lambda x: x[0], - model_item._meta.permissions)) + create_perms_post_migrate(model_item._meta.app_config) + permissions = map_rules.__base__ + list( + filter( + lambda perm: not perm.startswith( + 'detail_') and not perm.startswith('list_'), + map(lambda x: x[0], + model_item._meta.permissions)) + ) __fp__ = __fp__in__test_permission_of_models_in_rules_patterns for perm in permissions: From 698e53a8c55bdb16752ed60099f739d3d2e8863d Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 09:10:56 -0200 Subject: [PATCH 07/24] Ajusta QA check --- sapl/base/templatetags/common_tags.py | 1 + sapl/materia/forms.py | 6 +++--- sapl/materia/tests/test_materia.py | 2 +- sapl/materia/views.py | 4 +--- sapl/painel/views.py | 1 - sapl/protocoloadm/forms.py | 3 +-- sapl/protocoloadm/urls.py | 2 +- sapl/protocoloadm/views.py | 9 ++++----- sapl/rules/tests/test_rules.py | 3 +-- sapl/sessao/views.py | 2 -- sapl/utils.py | 18 +++++++----------- 11 files changed, 20 insertions(+), 31 deletions(-) diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index d023104d5..b4f4bb23d 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -3,6 +3,7 @@ from django import template from sapl.base.models import AppConfig from sapl.parlamentares.models import Filiacao + register = template.Library() diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index 8ba0e5477..b9a3db1ed 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, @@ -32,7 +33,6 @@ 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) -import sapl from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, Numeracao, diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index 5455792f4..a8aaaf2ec 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -1,9 +1,9 @@ +import pytest from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.files.uploadedfile import SimpleUploadedFile from django.core.urlresolvers import reverse from model_mommy import mommy -import pytest from sapl.base.models import Autor, TipoAutor from sapl.comissoes.models import Comissao, TipoComissao diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 30d038f23..e1a686f1f 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -21,6 +21,7 @@ from django.views.generic.base import RedirectView from django.views.generic.edit import FormView from django_filters.views import FilterView +import sapl from sapl.base.models import Autor, CasaLegislativa from sapl.compilacao.views import IntegracaoTaView from sapl.crispy_layout_mixin import SaplFormLayout, form_actions @@ -28,7 +29,6 @@ from sapl.crud.base import (ACTION_CREATE, ACTION_DELETE, ACTION_DETAIL, ACTION_LIST, ACTION_UPDATE, RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, PermissionRequiredForAppCrudMixin, make_pagination) -from sapl.materia import apps from sapl.materia.forms import (AnexadaForm, ConfirmarProposicaoForm, LegislacaoCitadaForm, ProposicaoForm, TipoProposicaoForm) @@ -36,7 +36,6 @@ from sapl.norma.models import LegislacaoCitada from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label, autor_modal, gerar_hash_arquivo, get_base_url, montar_row_autor) -import sapl from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, DocumentoAcessorioForm, MateriaLegislativaFilterSet, @@ -51,7 +50,6 @@ from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, TipoMateriaLegislativa, TipoProposicao, Tramitacao, UnidadeTramitacao) - OrigemCrud = Crud.build(Origem, '') TipoMateriaCrud = CrudAux.build( diff --git a/sapl/painel/views.py b/sapl/painel/views.py index d43555f51..6c43708a4 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -16,7 +16,6 @@ from sapl.sessao.models import (ExpedienteMateria, OrdemDia, PresencaOrdemDia, from .models import Cronometro - CronometroPainelCrud = Crud.build(Cronometro, '') # FIXME mudar lógica diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index de17af830..0315d6f1c 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,7 +9,6 @@ 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 @@ -20,7 +20,6 @@ from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) - TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido'), ('', 'Ambos')] NATUREZA_PROCESSO = [('', 'Ambos'), diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index 07c89029e..1de09a01a 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -9,7 +9,7 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView, DocumentoAcessorioAdministrativoView, DocumentoAdministrativoCrud, PesquisarDocumentoAdministrativoView, - ProtocoloDocumentoView, ProtocoloListView, + ProtocoloDocumentoView, ProtocoloMateriaView, ProtocoloMostrarView, ProtocoloPesquisaView, diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 0e78cce97..5019d47bf 100644 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -12,10 +12,10 @@ from django.views.generic import CreateView, DetailView, FormView, ListView from django.views.generic.base import TemplateView from django_filters.views import FilterView +import sapl from sapl.crud.base import Crud, CrudAux, MasterDetailCrud, make_pagination from sapl.materia.models import TipoMateriaLegislativa -from sapl.utils import (create_barcode, get_client_ip) -import sapl +from sapl.utils import create_barcode, get_client_ip from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm, DocumentoAdministrativoFilterSet, @@ -26,14 +26,13 @@ from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, StatusTramitacaoAdministrativo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) - TipoDocumentoAdministrativoCrud = CrudAux.build( TipoDocumentoAdministrativo, '') -#ProtocoloDocumentoCrud = Crud.build(Protocolo, '') +# ProtocoloDocumentoCrud = Crud.build(Protocolo, '') # FIXME precisa de uma chave diferente para o layout -#ProtocoloMateriaCrud = Crud.build(Protocolo, '') +# ProtocoloMateriaCrud = Crud.build(Protocolo, '') DocumentoAcessorioAdministrativoCrud = Crud.build( diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index bdc885558..0dcd808b0 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -1,10 +1,10 @@ +import pytest from django.apps import apps from django.conf import settings from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.utils import six from django.utils.translation import ugettext_lazy as _ -import pytest from sapl.base.models import CasaLegislativa, ProblemaMigracao from sapl.compilacao.models import TipoDispositivo,\ @@ -17,7 +17,6 @@ from scripts.lista_permissions_in_decorators import \ lista_permissions_in_decorators from scripts.lista_urls import lista_urls - sapl_appconfs = [apps.get_app_config(n[5:]) for n in settings.SAPL_APPS] sapl_models = [] diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index f36381233..3fc239e02 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -29,7 +29,6 @@ from sapl.materia.views import MateriaLegislativaPesquisaView from sapl.norma.models import NormaJuridica from sapl.parlamentares.models import (Legislatura, Parlamentar, SessaoLegislativa) - from sapl.sessao.apps import AppConfig from sapl.sessao.forms import ExpedienteMateriaForm, OrdemDiaForm @@ -45,7 +44,6 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa, SessaoPlenariaPresenca, TipoExpediente, TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar) - TipoSessaoCrud = CrudAux.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria') TipoExpedienteCrud = CrudAux.build(TipoExpediente, 'tipo_expediente') CargoBancadaCrud = CrudAux.build(CargoBancada, '') diff --git a/sapl/utils.py b/sapl/utils.py index 792099eaf..3969cfb74 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,30 +1,26 @@ -from datetime import date -from functools import wraps -from unicodedata import normalize as unicodedata_normalize import hashlib import logging import re +from datetime import date +from functools import wraps +from unicodedata import normalize as unicodedata_normalize +import magic from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button from django import forms from django.apps import apps from django.conf import settings from django.contrib import admin -from django.contrib.auth.decorators import user_passes_test -from django.contrib.auth.models import Permission from django.contrib.contenttypes.fields import (GenericForeignKey, GenericRel, GenericRelation) -from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import PermissionDenied, ValidationError +from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from floppyforms import ClearableFileInput -import magic from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row from sapl.settings import BASE_DIR - sapl_logger = logging.getLogger(BASE_DIR.name) @@ -399,12 +395,12 @@ def permissoes(nome_grupo, app_label): def permission_required_for_app(app_label, login_url=None, raise_exception=False): - + Decorator for views that checks whether a user has a particular permission enabled, redirecting to the log-in page if necessary. If the raise_exception parameter is given the PermissionDenied exception is raised. - + def check_perms(user): if user.has_module_perms(app_label): return True From aa05edcdc9f851feeae441e01642d19ff7a637e6 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 09:24:06 -0200 Subject: [PATCH 08/24] =?UTF-8?q?Torna=20enumera=C3=A7=C3=A3o=20pythonica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/sessao/views.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 3fc239e02..1a7110e11 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -59,11 +59,9 @@ TipoResultadoVotacaoCrud = CrudAux.build( def reordernar_materias_expediente(request, pk): expedientes = ExpedienteMateria.objects.filter( sessao_plenaria_id=pk) - exp_num = 1 - for e in expedientes: + for exp_num, e in enumerate(expedientes, 1): e.numero_ordem = exp_num e.save() - exp_num += 1 return HttpResponseRedirect( reverse('sapl.sessao:expedientemateria_list', kwargs={'pk': pk})) @@ -72,11 +70,9 @@ def reordernar_materias_expediente(request, pk): def reordernar_materias_ordem(request, pk): ordens = OrdemDia.objects.filter( sessao_plenaria_id=pk) - ordem_num = 1 - for o in ordens: + for ordem_num, o in enumerate(ordens,1): o.numero_ordem = ordem_num o.save() - ordem_num += 1 return HttpResponseRedirect( reverse('sapl.sessao:ordemdia_list', kwargs={'pk': pk})) From 1d52849fe9e02d0d983f6359b51bcfafff9fea58 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 10:37:54 -0200 Subject: [PATCH 09/24] Pequenos ajustes --- sapl/compilacao/views.py | 3 +-- sapl/crud/base.py | 7 +++---- sapl/materia/views.py | 2 +- sapl/parlamentares/views.py | 3 +-- sapl/rules/tests/test_rules.py | 8 ++++---- sapl/sessao/views.py | 2 +- scripts/lista_permissions_in_decorators.py | 1 - 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index 9b7f79d95..0b6a476a9 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -53,8 +53,7 @@ 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') +TipoDispositivoCrud = Crud.build(TipoDispositivo, 'tipo_dispositivo') logger = logging.getLogger(BASE_DIR.name) diff --git a/sapl/crud/base.py b/sapl/crud/base.py index 074c1719b..a5c029655 100644 --- a/sapl/crud/base.py +++ b/sapl/crud/base.py @@ -16,20 +16,19 @@ from django.http.response import Http404 from django.shortcuts import redirect from django.utils.decorators import classonlymethod from django.utils.encoding import force_text -from django.utils.translation import string_concat from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import string_concat from django.views.generic import (CreateView, DeleteView, DetailView, ListView, UpdateView) from django.views.generic.base import ContextMixin from django.views.generic.list import MultipleObjectMixin from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display -from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, - RP_DETAIL, RP_LIST) +from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, + RP_LIST) from sapl.settings import BASE_DIR from sapl.utils import normalize - logger = logging.getLogger(BASE_DIR.name) ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \ diff --git a/sapl/materia/views.py b/sapl/materia/views.py index e1a686f1f..7be1e8560 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -84,7 +84,7 @@ class MateriaTaView(IntegracaoTaView): class ProposicaoTaView(IntegracaoTaView): model = Proposicao model_type_foreignkey = TipoProposicao - # TODO implmentar o mapa de fields e utiliza-lo em IntegracaoTaView + # TODO implementar o mapa de fields e utiliza-lo em IntegracaoTaView fields = { } diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py index 4e937bd54..38228d920 100644 --- a/sapl/parlamentares/views.py +++ b/sapl/parlamentares/views.py @@ -64,8 +64,7 @@ class ProposicaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView): class ListView(CrudBaseForListAndDetailExternalAppView.ListView): def get_queryset(self): - return super().get_queryset().filter( - data_envio__isnull=False) + return super().get_queryset().filter(data_envio__isnull=False) class ParticipacaoParlamentarCrud(CrudBaseForListAndDetailExternalAppView): diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index 0dcd808b0..3662477b9 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -7,11 +7,11 @@ from django.utils import six from django.utils.translation import ugettext_lazy as _ from sapl.base.models import CasaLegislativa, ProblemaMigracao -from sapl.compilacao.models import TipoDispositivo,\ - PerfilEstruturalTextoArticulado, TipoDispositivoRelationship +from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, + TipoDispositivo, + TipoDispositivoRelationship) from sapl.materia.models import AcompanhamentoMateria -from sapl.rules import SAPL_GROUPS -from sapl.rules import map_rules +from sapl.rules import SAPL_GROUPS, map_rules from sapl.test_urls import create_perms_post_migrate from scripts.lista_permissions_in_decorators import \ lista_permissions_in_decorators diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 1a7110e11..d5ce1bdad 100644 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -70,7 +70,7 @@ def reordernar_materias_expediente(request, pk): def reordernar_materias_ordem(request, pk): ordens = OrdemDia.objects.filter( sessao_plenaria_id=pk) - for ordem_num, o in enumerate(ordens,1): + for ordem_num, o in enumerate(ordens, 1): o.numero_ordem = ordem_num o.save() diff --git a/scripts/lista_permissions_in_decorators.py b/scripts/lista_permissions_in_decorators.py index 8138cd0f7..4d504e6c0 100644 --- a/scripts/lista_permissions_in_decorators.py +++ b/scripts/lista_permissions_in_decorators.py @@ -2,7 +2,6 @@ import ast import inspect import os - if __name__ == '__main__': import django From a50d1a1878375f56f537bfc1fef8676b29d90425 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 11:31:07 -0200 Subject: [PATCH 10/24] Lista ano em ordem decrescente em pesquisa norma --- sapl/norma/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index a767c37fa..0246ec320 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -84,7 +84,7 @@ class NormaJuridicaPesquisaForm(ModelForm): ano = forms.ModelChoiceField( label='Ano', required=False, - queryset=NormaJuridica.objects.order_by('ano').values_list( + queryset=NormaJuridica.objects.order_by('-ano').values_list( 'ano', flat=True).distinct(), empty_label='Selecione' ) From 6275384ab8bcf50c801a224256ce288dd5ba1136 Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 13:35:44 -0200 Subject: [PATCH 11/24] Abre controlador painel na mesma tela --- sapl/templates/sessao/painel.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/templates/sessao/painel.html b/sapl/templates/sessao/painel.html index 6ff1dbc8b..f4e95163a 100644 --- a/sapl/templates/sessao/painel.html +++ b/sapl/templates/sessao/painel.html @@ -19,7 +19,7 @@ - +

Operação do Painel Eletrônico

From 0568bc8b88527337c706807faedb1b6a1b3da09d Mon Sep 17 00:00:00 2001 From: Edward Ribeiro Date: Tue, 1 Nov 2016 13:51:21 -0200 Subject: [PATCH 12/24] =?UTF-8?q?Adiciona=20bot=C3=A3o=20de=20voltar=20a?= =?UTF-8?q?=20controlador=20painel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/templates/painel/controlador.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sapl/templates/painel/controlador.html b/sapl/templates/painel/controlador.html index f4aaabc00..32ed27913 100644 --- a/sapl/templates/painel/controlador.html +++ b/sapl/templates/painel/controlador.html @@ -21,4 +21,8 @@ FECHADO +
+
+Voltar + {% endblock %} From dee81594ebc87d3148dd5c8d01d13f32afab50cb Mon Sep 17 00:00:00 2001 From: Leandro Roberto da Silva Date: Tue, 1 Nov 2016 15:15:47 -0200 Subject: [PATCH 13/24] =?UTF-8?q?Atualiza=20vers=C3=A3o=20do=20django-filt?= =?UTF-8?q?er=20(#776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * altera travis para testar com 3.5.2 * retorna python para 3.4.3 * downgrading django-filter to 0.11 * altera versão do django-filter para ult do pypi * ref pesquisas para atualização do django-filter --- requirements/requirements.txt | 2 +- sapl/materia/forms.py | 36 ++++++----------------- sapl/protocoloadm/forms.py | 47 +++++------------------------- sapl/sessao/forms.py | 17 ++++------- sapl/utils.py | 54 ++++++++++++++++++++++++++++++++--- 5 files changed, 72 insertions(+), 84 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 9ddd7a255..4387cb37d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -8,7 +8,7 @@ django-compressor==2.0 django-crispy-forms==1.6.0 django-extensions==1.6.7 django-extra-views==0.8.0 -django-filter==0.13.0 +django-filter==0.15.3 django-floppyforms==1.6.2 django-model-utils==2.5 django-sass-processor==0.4.6 diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index b9a3db1ed..b887569f4 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -1,8 +1,7 @@ -import os from datetime import date, datetime +import os -import django_filters from crispy_forms.bootstrap import (Alert, FormActions, InlineCheckboxes, InlineRadios) from crispy_forms.helper import FormHelper @@ -18,8 +17,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, @@ -32,7 +31,9 @@ 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) + autor_label, autor_modal, models_with_gr_for_model, + MateriaPesquisaOrderingFilter) +import sapl from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial, DocumentoAcessorio, MateriaLegislativa, Numeracao, @@ -444,6 +445,8 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): label=u'Ano da Matéria', choices=em_tramitacao) + o = MateriaPesquisaOrderingFilter() + class Meta: model = MateriaLegislativa fields = ['numero', @@ -453,7 +456,7 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): 'data_apresentacao', 'data_publicacao', 'autoria__autor__tipo', - # 'autoria__autor__partido', + # FIXME 'autoria__autor__partido', 'relatoria__parlamentar_id', 'local_origem_externa', 'tramitacao__unidade_tramitacao_destino', @@ -461,29 +464,6 @@ class MateriaLegislativaFilterSet(django_filters.FilterSet): 'em_tramitacao', ] - order_by = ( - ('', 'Selecione'), - ('dataC', 'Data, Tipo, Ano, Numero - Ordem Crescente'), - ('dataD', 'Data, Tipo, Ano, Numero - Ordem Decrescente'), - ('tipoC', 'Tipo, Ano, Numero, Data - Ordem Crescente'), - ('tipoD', 'Tipo, Ano, Numero, Data - Ordem Decrescente') - ) - - order_by_mapping = { - '': [], - 'dataC': ['data_apresentacao', 'tipo__sigla', 'ano', 'numero'], - 'dataD': ['-data_apresentacao', '-tipo__sigla', '-ano', '-numero'], - 'tipoC': ['tipo__sigla', 'ano', 'numero', 'data_apresentacao'], - 'tipoD': ['-tipo__sigla', '-ano', '-numero', '-data_apresentacao'], - } - - def get_order_by(self, order_value): - if order_value in self.order_by_mapping: - return self.order_by_mapping[order_value] - else: - return super(MateriaLegislativaFilterSet, - self).get_order_by(order_value) - def __init__(self, *args, **kwargs): super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs) diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 0315d6f1c..c3bab49e7 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -1,6 +1,5 @@ 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 @@ -9,17 +8,19 @@ 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) + autor_modal, AnoNumeroOrderingFilter) from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, Protocolo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) + TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido'), ('', 'Ambos')] NATUREZA_PROCESSO = [('', 'Ambos'), @@ -68,6 +69,8 @@ class ProtocoloFilterSet(django_filters.FilterSet): widget=forms.Select( attrs={'class': 'selector'})) + o = AnoNumeroOrderingFilter() + class Meta: model = Protocolo fields = ['numero', @@ -76,25 +79,6 @@ class ProtocoloFilterSet(django_filters.FilterSet): 'tipo_materia', ] - order_by = ( - ('', 'Selecione'), - ('CRE', 'Ordem Crescente'), - ('DEC', 'Ordem Decrescente'), - ) - - order_by_mapping = { - '': [], - 'CRE': ['ano', 'numero'], - 'DEC': ['-ano', '-numero'], - } - - def get_order_by(self, order_value): - if order_value in self.order_by_mapping: - return self.order_by_mapping[order_value] - else: - return super(ProtocoloFilterSet, - self).get_order_by(order_value) - def __init__(self, *args, **kwargs): super(ProtocoloFilterSet, self).__init__(*args, **kwargs) @@ -162,6 +146,8 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): interessado = django_filters.CharFilter(lookup_expr='icontains') + o = AnoNumeroOrderingFilter() + class Meta: model = DocumentoAdministrativo fields = ['tipo', @@ -171,25 +157,6 @@ class DocumentoAdministrativoFilterSet(django_filters.FilterSet): 'tramitacaoadministrativo__unidade_tramitacao_destino', 'tramitacaoadministrativo__status'] - order_by = ( - ('', 'Selecione'), - ('CRE', 'Ordem Crescente'), - ('DEC', 'Ordem Decrescente'), - ) - - order_by_mapping = { - '': [], - 'CRE': ['ano', 'numero'], - 'DEC': ['-ano', '-numero'], - } - - def get_order_by(self, order_value): - if order_value in self.order_by_mapping: - return self.order_by_mapping[order_value] - else: - return super(DocumentoAdministrativoFilterSet, - self).get_order_by(order_value) - def __init__(self, *args, **kwargs): super(DocumentoAdministrativoFilterSet, self).__init__(*args, **kwargs) diff --git a/sapl/sessao/forms.py b/sapl/sessao/forms.py index c99691656..988a0920b 100644 --- a/sapl/sessao/forms.py +++ b/sapl/sessao/forms.py @@ -1,18 +1,19 @@ 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 +from sapl.utils import RANGE_DIAS_MES, RANGE_MESES, autor_label, autor_modal,\ + MateriaPesquisaOrderingFilter from .models import (Bancada, ExpedienteMateria, Orador, OradorExpediente, OrdemDia, SessaoPlenaria, SessaoPlenariaPresenca) @@ -206,6 +207,8 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet): class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet): + o = MateriaPesquisaOrderingFilter() + class Meta: model = MateriaLegislativa fields = ['numero', @@ -215,20 +218,12 @@ class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet): 'data_apresentacao', 'data_publicacao', 'autoria__autor__tipo', - # 'autoria__autor__partido', + # FIXME 'autoria__autor__partido', 'relatoria__parlamentar_id', 'local_origem_externa', 'em_tramitacao', ] - order_by = ( - ('', 'Selecione'), - ('dataC', 'Data, Tipo, Ano, Numero - Ordem Crescente'), - ('dataD', 'Data, Tipo, Ano, Numero - Ordem Decrescente'), - ('tipoC', 'Tipo, Ano, Numero, Data - Ordem Crescente'), - ('tipoD', 'Tipo, Ano, Numero, Data - Ordem Decrescente') - ) - def __init__(self, *args, **kwargs): super(MateriaLegislativaFilterSet, self).__init__(*args, **kwargs) diff --git a/sapl/utils.py b/sapl/utils.py index 3969cfb74..ecf91e613 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,11 +1,10 @@ -import hashlib -import logging -import re from datetime import date from functools import wraps from unicodedata import normalize as unicodedata_normalize +import hashlib +import logging +import re -import magic from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button from django import forms @@ -17,10 +16,13 @@ from django.contrib.contenttypes.fields import (GenericForeignKey, GenericRel, from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from floppyforms import ClearableFileInput +import django_filters +import magic from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row from sapl.settings import BASE_DIR + sapl_logger = logging.getLogger(BASE_DIR.name) @@ -466,6 +468,50 @@ def permissao_tb_aux(self): """ +class MateriaPesquisaOrderingFilter(django_filters.OrderingFilter): + + choices = ( + ('', 'Selecione'), + ('dataC', 'Data, Tipo, Ano, Numero - Ordem Crescente'), + ('dataD', 'Data, Tipo, Ano, Numero - Ordem Decrescente'), + ('tipoC', 'Tipo, Ano, Numero, Data - Ordem Crescente'), + ('tipoD', 'Tipo, Ano, Numero, Data - Ordem Decrescente') + ) + order_by_mapping = { + '': [], + 'dataC': ['data_apresentacao', 'tipo__sigla', 'ano', 'numero'], + 'dataD': ['-data_apresentacao', '-tipo__sigla', '-ano', '-numero'], + 'tipoC': ['tipo__sigla', 'ano', 'numero', 'data_apresentacao'], + 'tipoD': ['-tipo__sigla', '-ano', '-numero', '-data_apresentacao'], + } + + def __init__(self, *args, **kwargs): + kwargs['choices'] = self.choices + super(MateriaPesquisaOrderingFilter, self).__init__(*args, **kwargs) + + def filter(self, qs, value): + return super().filter(qs, self.order_by_mapping[value[0]]) + + +class AnoNumeroOrderingFilter(django_filters.OrderingFilter): + + choices = (('', 'Selecione...'), + ('CRE', 'Ordem Crescente'), + ('DEC', 'Ordem Decrescente'),) + order_by_mapping = { + '': [], + 'CRE': ['ano', 'numero'], + 'DEC': ['-ano', '-numero'], + } + + def __init__(self, *args, **kwargs): + kwargs['choices'] = self.choices + super(AnoNumeroOrderingFilter, self).__init__(*args, **kwargs) + + def filter(self, qs, value): + return super().filter(qs, self.order_by_mapping[value[0]]) + + def gerar_hash_arquivo(arquivo, pk, block_size=2**20): md5 = hashlib.md5() arq = open(arquivo, 'rb') From 008a75ef9fd65ffac928c508219424187df510d9 Mon Sep 17 00:00:00 2001 From: Leandro Roberto da Silva Date: Thu, 3 Nov 2016 09:52:48 -0200 Subject: [PATCH 14/24] HOT-FIX warning deprecated --- sapl/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapl/settings.py b/sapl/settings.py index 4bb3a985b..cfeefdd0f 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -132,8 +132,8 @@ TEMPLATES = [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', - "django.core.context_processors.media", - "django.core.context_processors.static", + "django.template.context_processors.media", + "django.template.context_processors.static", 'django.contrib.messages.context_processors.messages', 'sapl.context_processors.parliament_info', ], From 6b92694267ca9d4a9908ab1ce36be8f2d4035340 Mon Sep 17 00:00:00 2001 From: Leandro Roberto da Silva Date: Thu, 3 Nov 2016 10:27:28 -0200 Subject: [PATCH 15/24] =?UTF-8?q?HOT-FIX=20erro=20na=20pesquisa=20sem=20se?= =?UTF-8?q?le=C3=A7=C3=A3o=20de=20ordem.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sapl/utils.py b/sapl/utils.py index ecf91e613..e4786085c 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -490,7 +490,8 @@ class MateriaPesquisaOrderingFilter(django_filters.OrderingFilter): super(MateriaPesquisaOrderingFilter, self).__init__(*args, **kwargs) def filter(self, qs, value): - return super().filter(qs, self.order_by_mapping[value[0]]) + _value = self.order_by_mapping[value[0]] if value else value + return super().filter(qs, _value) class AnoNumeroOrderingFilter(django_filters.OrderingFilter): @@ -509,7 +510,8 @@ class AnoNumeroOrderingFilter(django_filters.OrderingFilter): super(AnoNumeroOrderingFilter, self).__init__(*args, **kwargs) def filter(self, qs, value): - return super().filter(qs, self.order_by_mapping[value[0]]) + _value = self.order_by_mapping[value[0]] if value else value + return super().filter(qs, _value) def gerar_hash_arquivo(arquivo, pk, block_size=2**20): From 481752cc56b4e1f55cc9dd2f684a6d557259c321 Mon Sep 17 00:00:00 2001 From: Leandro Roberto da Silva Date: Thu, 3 Nov 2016 10:37:48 -0200 Subject: [PATCH 16/24] Fix #773 (#777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add ctrl de perms para compilação nos templates * Fix #773 --- .../migrations/0060_auto_20161101_0913.py | 19 ++ .../migrations/0061_auto_20161101_1025.py | 21 +++ .../migrations/0062_auto_20161101_1221.py | 19 ++ sapl/compilacao/models.py | 8 +- sapl/compilacao/views.py | 178 +++++++----------- sapl/materia/forms.py | 12 +- sapl/materia/views.py | 15 +- sapl/norma/views.py | 7 + sapl/protocoloadm/forms.py | 7 +- sapl/rules/map_rules.py | 5 +- sapl/sessao/forms.py | 7 +- .../compilacao/ajax_actions_dinamic_edit.html | 48 ++--- sapl/templates/compilacao/text_edit.html | 14 +- sapl/templates/compilacao/text_list.html | 18 +- .../compilacao/textoarticulado_detail.html | 18 +- .../textoarticulado_menu_config.html | 18 +- .../materia/tipoproposicao_form.html | 5 +- sapl/utils.py | 11 +- 18 files changed, 240 insertions(+), 190 deletions(-) create mode 100644 sapl/compilacao/migrations/0060_auto_20161101_0913.py create mode 100644 sapl/compilacao/migrations/0061_auto_20161101_1025.py create mode 100644 sapl/compilacao/migrations/0062_auto_20161101_1221.py 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 %} + {%endif%} + {% endif %}
@@ -61,11 +65,13 @@ {% endfor %} {%endif%} - {% if not object.ta_publicado and not object.dispositivo_subsequente and not object.tipo_dispositivo.dispositivo_de_alteracao%} -
- -
- {%endif%} + {% if perms.compilacao.change_dispositivo_de_vigencia_global %} + {% if not object.ta_publicado and not object.dispositivo_subsequente and not object.tipo_dispositivo.dispositivo_de_alteracao%} +
+ +
+ {% endif %} + {% endif %} diff --git a/sapl/templates/compilacao/text_edit.html b/sapl/templates/compilacao/text_edit.html index 013a7429d..c93042c7f 100644 --- a/sapl/templates/compilacao/text_edit.html +++ b/sapl/templates/compilacao/text_edit.html @@ -15,14 +15,16 @@ {% endblock %} {% block actions %} -
-