From e2cb37c8586ab756d7f4b3dc337b193e5f7add28 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Tue, 20 Sep 2016 16:48:57 -0300 Subject: [PATCH 1/6] =?UTF-8?q?Add=20registro=20de=20revoga=C3=A7=C3=A3o?= =?UTF-8?q?=20unit=C3=A1ria=20de=20dispositivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/compilacao/forms.py | 48 ++++++++++++++++ ...55_dispositivo_dispositivo_de_revogacao.py | 20 +++++++ sapl/compilacao/models.py | 38 ++++++++++++- .../templatetags/compilacao_filters.py | 2 +- sapl/compilacao/views.py | 57 ++++++++++++++----- sapl/static/js/compilacao_edit.js | 53 +++++++++++++++++ .../compilacao/ajax_actions_dinamic_edit.html | 4 +- .../templates/compilacao/text_list_bloco.html | 12 +++- 8 files changed, 214 insertions(+), 20 deletions(-) create mode 100644 sapl/compilacao/migrations/0055_dispositivo_dispositivo_de_revogacao.py diff --git a/sapl/compilacao/forms.py b/sapl/compilacao/forms.py index f93f71855..c3405eb7f 100644 --- a/sapl/compilacao/forms.py +++ b/sapl/compilacao/forms.py @@ -1280,3 +1280,51 @@ class DispositivoRegistroAlteracaoForm(Form): super(DispositivoRegistroAlteracaoForm, self).__init__(*args, **kwargs) self.fields['dispositivo_alterado'].choices = [] + + +class DispositivoRegistroRevogacaoForm(Form): + + dispositivo_revogado = forms.ModelChoiceField( + label=_('Dispositivo a ser revogado'), + required=False, + queryset=Dispositivo.objects.all()) + + dispositivo_search_form = forms.CharField(widget=forms.HiddenInput(), + required=False) + + def __init__(self, *args, **kwargs): + + layout = [] + kwargs.pop('instance') + kwargs['initial'].pop('editor_type') + + row_dispositivo = Field( + 'dispositivo_revogado', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_revogado', + data_type_selection='radio', + template="compilacao/layout/dispositivo_radio.html") + + layout.append(Fieldset(_('Registro de Revogação - ' + 'Seleção do Dispositivo a ser Revogado'), + row_dispositivo, + css_class="col-md-12")) + layout.append(Field('dispositivo_search_form')) + + more = [ + HTML('%s' % + _('Cancelar')), + ] + more.append(Submit('salvar', _('Salvar'), css_class='pull-right')) + + buttons = FormActions(*more, css_class='form-group') + + _fields = [Div(*layout, css_class="row-fluid")] + \ + [to_row([(buttons, 12)])] + + self.helper = FormHelper() + self.helper.layout = Layout(*_fields) + + super(DispositivoRegistroRevogacaoForm, self).__init__(*args, **kwargs) + + self.fields['dispositivo_revogado'].choices = [] diff --git a/sapl/compilacao/migrations/0055_dispositivo_dispositivo_de_revogacao.py b/sapl/compilacao/migrations/0055_dispositivo_dispositivo_de_revogacao.py new file mode 100644 index 000000000..daf297852 --- /dev/null +++ b/sapl/compilacao/migrations/0055_dispositivo_dispositivo_de_revogacao.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-20 11:57 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0054_auto_20160916_1424'), + ] + + operations = [ + migrations.AddField( + model_name='dispositivo', + name='dispositivo_de_revogacao', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Dispositivo de Revogação'), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index 7bcc3ae39..e2425bfcf 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -132,7 +132,7 @@ class TextoArticulado(TimestampedMixin): 'numero': self.numero, 'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")} - def ordenar_dispositivos(self): + def reagrupar_ordem_de_dispositivos(self): dpts = Dispositivo.objects.filter(ta=self) @@ -150,6 +150,37 @@ class TextoArticulado(TimestampedMixin): count += Dispositivo.INTERVALO_ORDEM Dispositivo.objects.filter(pk=d).update(ordem=count) + def reordenar_dispositivos(self): + + dpts = Dispositivo.objects.filter(ta=self) + + if not dpts.exists(): + return + + ordem_max = dpts.last().ordem + dpts.update(ordem=F('ordem') + ordem_max) + + raizes = Dispositivo.objects.filter( + ta=self, + dispositivo_pai__isnull=True).values_list( + 'pk', flat=True).order_by('ordem') + + count = [] + count.append(Dispositivo.INTERVALO_ORDEM) + + def update(dpk): + Dispositivo.objects.filter(pk=dpk).update(ordem=count[0]) + count[0] = count[0] + Dispositivo.INTERVALO_ORDEM + filhos = Dispositivo.objects.filter( + dispositivo_pai_id=dpk).values_list( + 'pk', flat=True).order_by('ordem') + + for dpk in filhos: + update(dpk) + + for dpk in raizes: + update(dpk) + class TipoNota(models.Model): sigla = models.CharField( @@ -587,6 +618,11 @@ class Dispositivo(BaseModel, TimestampedMixin): choices=YES_NO_CHOICES, verbose_name=_('Visibilidade no Texto Articulado Publicado')) + dispositivo_de_revogacao = models.BooleanField( + default=False, + choices=YES_NO_CHOICES, + verbose_name=_('Dispositivo de Revogação')) + tipo_dispositivo = models.ForeignKey( TipoDispositivo, related_name='dispositivos_do_tipo_set', diff --git a/sapl/compilacao/templatetags/compilacao_filters.py b/sapl/compilacao/templatetags/compilacao_filters.py index d7929c559..de8b70530 100644 --- a/sapl/compilacao/templatetags/compilacao_filters.py +++ b/sapl/compilacao/templatetags/compilacao_filters.py @@ -86,7 +86,7 @@ def nota_automatica(dispositivo, ta_pub_list): ta_publicado = ta_pub_list[dispositivo.ta_publicado_id] if\ ta_pub_list else dispositivo.ta_publicado - if dispositivo.texto == Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO: + if dispositivo.dispositivo_de_revogacao: return _('Revogado pelo %s - %s.') % ( d, ta_publicado) elif not dispositivo.dispositivo_substituido_id: diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index ec26d5996..23d698465 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -1,6 +1,6 @@ -import sys from collections import OrderedDict from datetime import datetime, timedelta +import sys from braces.views import FormMessagesMixin from django import forms @@ -30,7 +30,8 @@ from sapl.compilacao.forms import (DispositivoDefinidorVigenciaForm, DispositivoRegistroAlteracaoForm, DispositivoSearchModalForm, NotaForm, PublicacaoForm, TaForm, - TextNotificacoesForm, TipoTaForm, VideForm) + TextNotificacoesForm, TipoTaForm, VideForm, + DispositivoRegistroRevogacaoForm) from sapl.compilacao.models import (Dispositivo, Nota, PerfilEstruturalTextoArticulado, Publicacao, TextoArticulado, @@ -41,6 +42,7 @@ from sapl.compilacao.utils import (DISPOSITIVO_SELECT_RELATED, DISPOSITIVO_SELECT_RELATED_EDIT) from sapl.crud.base import Crud, CrudListView, make_pagination + TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') @@ -983,8 +985,7 @@ class TextEditView(TemplateView): ta_publicado = lista_ta_publicado[dispositivo.ta_publicado_id] if\ lista_ta_publicado else dispositivo.ta_publicado - if dispositivo.texto == \ - Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO: + if dispositivo.dispositivo_de_revogacao: return _('Revogado pelo %s - %s.') % ( d, ta_publicado) elif not dispositivo.dispositivo_substituido_id: @@ -1170,7 +1171,7 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin): else: self.set_message(data, 'success', _( 'Exclusão efetuada com sucesso!'), modal=True) - ta_base.ordenar_dispositivos() + ta_base.reagrupar_ordem_de_dispositivos() except Exception as e: data['pk'] = self.kwargs['dispositivo_id'] self.set_message(data, 'danger', str(e), modal=True) @@ -2066,7 +2067,17 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, return perfis[0].pk return None - def registra_alteracao(self, bloco_alteracao, dispositivo_a_alterar): + def registra_revogacao(self, bloco_alteracao, dispositivo_a_revogar): + return self.registra_alteracao( + bloco_alteracao, + dispositivo_a_revogar, + revogacao=True + ) + + def registra_alteracao(self, + bloco_alteracao, + dispositivo_a_alterar, + revogacao=False): """ Caracteristicas: 1 - Se é um dispositivo simples e sem subsequente @@ -2096,10 +2107,10 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, for d in history: """FIXME: A comparação "<" deverá ser mudada para - "<=" caso um seja necessário permitir duas alterações + "<=" caso seja necessário permitir duas alterações com mesmo inicio_vigencia no mesmo dispositivo. Neste Caso, - a sequencia correta ficará a cargo dos reposicionamentos entre - dispositivos de mesmo nível, + a sequencia correta ficará a cargo dos reposicionamentos e + (a ser implementado) entre dispositivos de mesmo nível, """ if d.inicio_vigencia < bloco_alteracao.inicio_vigencia: dispositivo_a_alterar = d @@ -2118,8 +2129,12 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, dispositivo_a_alterar, dispositivo_a_alterar.tipo_dispositivo) ndp.rotulo = dispositivo_a_alterar.rotulo - ndp.texto = dispositivo_a_alterar.texto ndp.publicacao = bloco_alteracao.publicacao + if not revogacao: + ndp.texto = dispositivo_a_alterar.texto + else: + ndp.texto = Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO + ndp.dispositivo_de_revogacao = True ndp.dispositivo_vigencia = bloco_alteracao.dispositivo_vigencia if ndp.dispositivo_vigencia: @@ -2167,9 +2182,16 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, d.dispositivo_pai = ndp d.save() - self.set_message( - data, 'success', - _('Dispositivo de Alteração adicionado com sucesso.')) + ndp.ta.reordenar_dispositivos() + + if not revogacao: + self.set_message( + data, 'success', + _('Dispositivo de Alteração adicionado com sucesso.')) + else: + self.set_message( + data, 'success', + _('Dispositivo de Revogação adicionado com sucesso.')) except Exception as e: print(e) @@ -2221,6 +2243,8 @@ class DispositivoDinamicEditView( self.form_class = DispositivoEdicaoBasicaForm elif self.action.endswith('_alteracao'): self.form_class = DispositivoRegistroAlteracaoForm + elif self.action.endswith('_revogacao'): + self.form_class = DispositivoRegistroRevogacaoForm context = self.get_context_data() return self.render_to_response(context) elif self.action.startswith('get_actions'): @@ -2267,6 +2291,13 @@ class DispositivoDinamicEditView( data = self.registra_alteracao(d, dispositivo_a_alterar) + if formtype == 'get_form_revogacao': + + dispositivo_a_revogar = Dispositivo.objects.get( + pk=request.POST['dispositivo_revogado']) + + data = self.registra_revogacao(d, dispositivo_a_revogar) + elif formtype == 'get_form_base': texto = request.POST['texto'].strip() texto_atualizador = request.POST['texto_atualizador'].strip() diff --git a/sapl/static/js/compilacao_edit.js b/sapl/static/js/compilacao_edit.js index 94c279067..b78ad897a 100644 --- a/sapl/static/js/compilacao_edit.js +++ b/sapl/static/js/compilacao_edit.js @@ -138,6 +138,28 @@ function DispositivoEdit() { }); } + instance.get_form_revogacao = function () { + var _this = $(this); + _this.off('get_form_revogacao'); + $('.dpt-actions, .dpt-actions-bottom').html(''); + + var dpt_form = _this.children().filter('.dpt-form').children().first(); + var url_search = dpt_form[0]['id_dispositivo_search_form'].value; + DispostivoSearch({ + 'url_form': url_search, + 'text_button': 'Selecionar' + }); + + instance.scrollTo(_this); + dpt_form.submit(instance.onSubmitFormRegistraRevogacao); + + var btn_fechar = _this.find('.btn-fechar'); + btn_fechar.on('click', function() { + instance.clearEditSelected(); + instance.triggerBtnDptEdit(_this.attr('pk')); + }); + } + instance.loadActionsEdit = function(dpt) { var pk = dpt.attr('pk'); var url = pk+'/refresh?action=get_actions'; @@ -258,8 +280,39 @@ function DispositivoEdit() { }); if (event != null) event.preventDefault(); + } + + instance.onSubmitFormRegistraRevogacao = function(event) { + var _this = this; + var form_data = { + 'csrfmiddlewaretoken' : this['csrfmiddlewaretoken'].value, + 'dispositivo_revogado' : this['dispositivo_revogado'].value, + 'formtype': 'get_form_revogacao', + }; + var url = $(this).closest('.dpt').attr( "pk" )+'/refresh'; + + instance.waitShow(); + + $.post(url, form_data) + .done(function(data) { + instance.clearEditSelected(); + + if (data.pk != null) { + instance.refreshScreenFocusPk(data); + instance.message(data); + } + else { + alert('Erro na resposta!'); + } + + }).always(function() { + instance.waitHide(); + }); + if (event != null) + event.preventDefault(); } + instance.onSubmitEditFormBase = function(event) { var _this = this; diff --git a/sapl/templates/compilacao/ajax_actions_dinamic_edit.html b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html index 3231fdd1d..2d746740e 100644 --- a/sapl/templates/compilacao/ajax_actions_dinamic_edit.html +++ b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html @@ -53,7 +53,7 @@ {% endif %}
- {% if object.dispositivo_subsequente == None %} + {% if not object.dispositivo_subsequente %} {% for perfil in perfil_estrutural_list%}
- {% if not object.ta_publicado%} + {% if not object.ta_publicado and not object.dispositivo_subsequente %}