From a68d7117f7bfe5103985865a32b0c71f70e8911b Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Fri, 18 Oct 2019 17:39:25 -0300 Subject: [PATCH] =?UTF-8?q?refatora=20backend=20de=20compila=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/compilacao/forms.py | 58 ++- .../migrations/0013_auto_20190924_0830.py | 27 ++ sapl/compilacao/models.py | 29 +- .../templatetags/compilacao_filters.py | 3 +- sapl/compilacao/views.py | 422 ++++++++++-------- .../dispositivo_form_search_fragment.html | 123 +---- ...ispositivo_form_search_fragment_child.html | 45 ++ sapl/templates/compilacao/subnav.html | 4 +- sapl/templates/compilacao/text_edit.html | 23 +- .../templates/compilacao/text_edit_bloco.html | 16 +- sapl/templates/compilacao/text_list.html | 5 +- .../compilacao/text_list__embedded.html | 12 +- .../compilacao/text_list_blocoalteracao.html | 4 +- .../compilacao/textoarticulado_detail.html | 15 +- .../compilacao/textoarticulado_list.html | 51 ++- 15 files changed, 457 insertions(+), 380 deletions(-) create mode 100644 sapl/compilacao/migrations/0013_auto_20190924_0830.py create mode 100644 sapl/templates/compilacao/dispositivo_form_search_fragment_child.html diff --git a/sapl/compilacao/forms.py b/sapl/compilacao/forms.py index e82d58f63..0a7542a46 100644 --- a/sapl/compilacao/forms.py +++ b/sapl/compilacao/forms.py @@ -13,6 +13,7 @@ from django.forms.forms import Form from django.forms.models import ModelForm from django.template import defaultfilters from django.utils.translation import ugettext_lazy as _ +from model_utils.choices import Choices from sapl import utils from sapl.compilacao.models import (NOTAS_PUBLICIDADE_CHOICES, @@ -115,7 +116,7 @@ class TaForm(ModelForm): queryset=TipoTextoArticulado.objects.all(), required=True, empty_label=None) - numero = forms.IntegerField( + numero = forms.CharField( label=TextoArticulado._meta.get_field( 'numero').verbose_name, required=True) @@ -744,6 +745,12 @@ class DispositivoEdicaoBasicaForm(ModelForm): class DispositivoSearchModalForm(Form): + TIPO_RESULTADO_CHOICES = Choices( + ('C', 'coincidentes', _('Apenas Coincidentes')), + ('I', 'internos', _('Incluir Internos')), + ('S', 'coin_sequentes', _('Coincidentes e seus sequentes')), + ) + tipo_ta = forms.ModelChoiceField( label=_('Tipo do Texto Articulado'), queryset=TipoTextoArticulado.objects.all(), @@ -758,9 +765,9 @@ class DispositivoSearchModalForm(Form): ano_ta = forms.IntegerField( label=_('Ano do Documento'), required=False) - dispositivos_internos = forms.ChoiceField( - label=_('Dispositivos Internos?'), - choices=utils.YES_NO_CHOICES, + tipo_resultado = forms.ChoiceField( + label=_('Tipo do Resultado?'), + choices=TIPO_RESULTADO_CHOICES, widget=forms.RadioSelect(), required=False) @@ -769,7 +776,7 @@ class DispositivoSearchModalForm(Form): choices=[(10, _('Dez Dispositivos')), (30, _('Trinta Dispositivos')), (50, _('Cinquenta Dispositivos')), - (0, _('Tudo que atender aos Critérios da Busca'))], + (100, _('Cem Dispositivos'))], widget=forms.Select(), required=False) @@ -789,22 +796,33 @@ class DispositivoSearchModalForm(Form): to_column(('num_ta', 4)), to_column(('ano_ta', 4)), to_column(('max_results', 4))), + Row( - to_column(('tipo_ta', 6)), - to_column(('tipo_model', 6))), - Row(to_column((InlineRadios('dispositivos_internos'), 3)), - to_column(('rotulo_dispositivo', 2)), - to_column((FieldWithButtons( - Field( - 'texto_dispositivo', - placeholder=_('Digite palavras, letras, ' - 'números ou algo' - ' que estejam no texto.')), - StrictButton( - _('Buscar'), - css_class='btn-busca btn-primary')), 7)) + to_column(('tipo_resultado', 3)), + to_column( + ( + Div( + Row( + to_column(('tipo_ta', 6)), + to_column(('tipo_model', 6))), + Row( + to_column(('rotulo_dispositivo', 4)), + to_column( + ( + FieldWithButtons( + Field( + 'texto_dispositivo', + placeholder=_('Digite palavras, letras, ' + 'números ou algo' + ' que estejam no texto.')), + StrictButton( + _('Buscar'), + css_class='btn-busca btn-primary')), 8)) + ) + ), 9 + ) ) - ) + )) self.helper = SaplFormHelper() self.helper.layout = Layout( @@ -821,7 +839,7 @@ class DispositivoSearchModalForm(Form): choice = ch(kwargs['instance'].ta.tipo_ta_id) self.base_fields['tipo_model'].choices = choice - kwargs['initial'].update({'dispositivos_internos': False}) + kwargs['initial'].update({'tipo_resultado': 'C'}) super(DispositivoSearchModalForm, self).__init__(*args, **kwargs) diff --git a/sapl/compilacao/migrations/0013_auto_20190924_0830.py b/sapl/compilacao/migrations/0013_auto_20190924_0830.py new file mode 100644 index 000000000..c984718ef --- /dev/null +++ b/sapl/compilacao/migrations/0013_auto_20190924_0830.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.24 on 2019-09-24 11:30 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0012_bug_auto_inserido'), + ] + + operations = [ + migrations.AlterField( + model_name='textoarticulado', + name='editable_only_by_owners', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, + verbose_name='Editável apenas pelos donos do Texto Articulado?'), + ), + migrations.AlterField( + model_name='textoarticulado', + name='editing_locked', + field=models.BooleanField(choices=[( + True, 'Sim'), (False, 'Não')], default=True, verbose_name='Texto Articulado em Edição?'), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index f64285aee..bac67b535 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -221,12 +221,12 @@ class TextoArticulado(TimestampedMixin): editable_only_by_owners = models.BooleanField( choices=YES_NO_CHOICES, default=True, - verbose_name=_('Editável apenas pelos donos do Texto Articulado')) + verbose_name=_('Editável apenas pelos donos do Texto Articulado?')) editing_locked = models.BooleanField( choices=YES_NO_CHOICES, default=True, - verbose_name=_('Texto Articulado em Edição')) + verbose_name=_('Texto Articulado em Edição?')) privacidade = models.IntegerField( _('Privacidade'), @@ -416,8 +416,8 @@ class TextoArticulado(TimestampedMixin): def clone_for(self, obj): # O clone gera um texto válido original dada a base self, - # mesmo sendo esta base um texto compilado. - # Os dispositivos a clonar será com base no texto compilado + # mesmo sendo esta base um Texto Articulado. + # Os dispositivos a clonar será com base no Texto Articulado assert self.tipo_ta and self.tipo_ta.content_type, _( 'Não é permitido chamar o método clone_for ' @@ -1072,6 +1072,10 @@ class Dispositivo(BaseModel, TimestampedMixin): 'Permissão alteração global do dispositivo de vigência')), ) + def ws_sync(self): + return self.ta and self.ta.privacidade in ( + STATUS_TA_IMMUTABLE_PUBLIC, STATUS_TA_PUBLIC) + def clean(self): """ Check for instances with null values in unique_together fields. @@ -1113,14 +1117,15 @@ class Dispositivo(BaseModel, TimestampedMixin): self.contagem_continua = self.tipo_dispositivo.contagem_continua - try: + """try: if self.texto: + self.texto = self.texto.replace('\xa0', '') self.texto = str(BeautifulSoup(self.texto, "html.parser")) if self.texto_atualizador: self.texto_atualizador = str(BeautifulSoup( self.texto_atualizador, "html.parser")) except: - pass + pass""" return super().save( force_insert=force_insert, force_update=force_update, using=using, @@ -1624,7 +1629,7 @@ class Dispositivo(BaseModel, TimestampedMixin): yield ultimo @staticmethod - def new_instance_based_on(dispositivo_base, tipo_base): + def new_instance_based_on(dispositivo_base, tipo_base, base_alteracao=None): dp = Dispositivo() dp.tipo_dispositivo = tipo_base @@ -1639,6 +1644,16 @@ class Dispositivo(BaseModel, TimestampedMixin): dp.dispositivo_pai = dispositivo_base.dispositivo_pai dp.publicacao = dispositivo_base.publicacao + b = base_alteracao if base_alteracao else dispositivo_base + + # teste de criação inversa de itens alterados por mesmo bloco + dp.ta_publicado = b.ta_publicado + dp.dispositivo_atualizador = b.dispositivo_atualizador + + if dp.ta_publicado: + dp.ordem_bloco_atualizador = b.ordem_bloco_atualizador + \ + Dispositivo.INTERVALO_ORDEM + dp.dispositivo_vigencia = dispositivo_base.dispositivo_vigencia if dp.dispositivo_vigencia: dp.inicio_eficacia = dp.dispositivo_vigencia.inicio_eficacia diff --git a/sapl/compilacao/templatetags/compilacao_filters.py b/sapl/compilacao/templatetags/compilacao_filters.py index a7fb2eada..201e0d62c 100644 --- a/sapl/compilacao/templatetags/compilacao_filters.py +++ b/sapl/compilacao/templatetags/compilacao_filters.py @@ -65,6 +65,8 @@ def get_bloco_atualizador(pk_atualizador): @register.simple_tag def dispositivo_desativado(dispositivo, inicio_vigencia, fim_vigencia): + if dispositivo.dispositivo_de_revogacao: + return 'revogado' if inicio_vigencia and fim_vigencia: if dispositivo.fim_vigencia is None: return '' @@ -292,7 +294,6 @@ def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0): return result - @register.filter def list(obj): return [obj, ] diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index d27d85f1a..0f165403a 100644 --- a/sapl/compilacao/views.py +++ b/sapl/compilacao/views.py @@ -10,7 +10,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ValidationError +from django.core.exceptions import ValidationError, PermissionDenied from django.core.signing import Signer from django.core.urlresolvers import reverse, reverse_lazy from django.db import transaction @@ -494,6 +494,18 @@ class TaListView(CompMixin, ListView): ~Q(owners=self.request.user.id), privacidade=STATUS_TA_PRIVATE) + if 'check' in self.request.GET: + qs = qs.filter( + temp_check_migrations=False, + privacidade=0, + ).exclude(dispositivos_set__tipo_dispositivo_id=3) + + if 'check_dvt' in self.request.GET: + qs = qs.filter( + ).filter( + dispositivos_set__isnull=False, + dispositivos_set__dispositivo_vigencia__isnull=True).distinct() + return qs @@ -565,13 +577,29 @@ class TaDeleteView(CompMixin, DeleteView): template_name = "crud/confirm_delete.html" permission_required = 'compilacao.delete_textoarticulado' + def post(self, request, *args, **kwargs): + if not request.user.is_superuser: + raise PermissionDenied + return DeleteView.post(self, request, *args, **kwargs) + @property def detail_url(self): return reverse_lazy('sapl.compilacao:ta_detail', kwargs={'pk': self.kwargs['pk']}) def get_success_url(self): - return reverse_lazy('sapl.compilacao:ta_list') + messages.info(self.request, 'Texto Articulado excluido com sucesso!') + + reverse_url = '%s:%s_detail' % ( + self.object.content_object._meta.app_config.name, + self.object.content_object._meta.model_name) + + return reverse_lazy(reverse_url, + kwargs={'pk': self.object.content_object.pk}) + + @property + def title(self): + return 'Texto Articulado: %s' % self.object class DispositivoSuccessUrlMixin(CompMixin): @@ -849,6 +877,10 @@ class TextView(CompMixin, ListView): fim_vigencia = None ta_vigencia = None + @property + def title(self): + return 'Texto Articulado: %s' % self.object + def has_permission(self): self.object = self.ta return self.object.has_view_permission(self.request) @@ -1078,7 +1110,7 @@ class TextEditView(CompMixin, TemplateView): self.object.content_object.save() else: - if 'lock' in request.GET: + if 'lock' in request.GET or 'check' in request.GET: # TODO - implementar logging de ação de usuário notificacoes = self.get_notificacoes( @@ -1097,11 +1129,17 @@ class TextEditView(CompMixin, TemplateView): 'sapl.compilacao:ta_text_notificacoes', kwargs={ 'ta_id': self.object.id})) - self.object.editing_locked = True - self.object.privacidade = STATUS_TA_PUBLIC - self.object.save() - messages.success(request, _( - 'Texto Articulado bloqueado com sucesso.')) + if 'lock' in request.GET: + self.object.editing_locked = True + self.object.privacidade = STATUS_TA_PUBLIC + self.object.save() + messages.success(request, _( + 'Texto Articulado publicado com sucesso.')) + else: + self.object.temp_check_migrations = True + self.object.save() + messages.success(request, _( + 'Texto Articulado Checado...')) if self.object.content_object: self.object.content_object.save() @@ -2083,6 +2121,10 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): if len(result) > 2: result.pop() + result[0]['itens'] = result[1]['itens'] + result[0]['itens'] + result[0]['tipo_insert'] = 'Inserção' + result[1]['itens'] = [] + return result except Exception as e: @@ -2097,7 +2139,6 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): dvt = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) if dvt.auto_inserido: dvt = dvt.dispositivo_pai - try: Dispositivo.objects.filter( ta=dvt.ta, ta_publicado__isnull=True @@ -2109,7 +2150,7 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): Dispositivo.objects.filter(ta_publicado=dvt.ta ).update( dispositivo_vigencia=dvt, - inicio_vigencia=dvt.inicio_eficacia, + inicio_vigencia=dvt.inicio_vigencia, inicio_eficacia=dvt.inicio_eficacia) dps = Dispositivo.objects.filter(dispositivo_vigencia=dvt) @@ -2162,6 +2203,10 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): dp_auto_insert = None base = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) + + if base.dispositivo_atualizador: + registro_inclusao = True + tipo = TipoDispositivo.objects.get(pk=context['tipo_pk']) pub_last = Publicacao.objects.order_by( 'data', 'hora').filter(ta=base.ta).last() @@ -2197,11 +2242,13 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): dp_pai = dp if dp_irmao is not None: - dp = Dispositivo.new_instance_based_on(dp_irmao, tipo) + dp = Dispositivo.new_instance_based_on( + dp_irmao, tipo, base_alteracao=base) dp.transform_in_next(variacao) else: # Inserção sem precedente - dp = Dispositivo.new_instance_based_on(dp_pai, tipo) + dp = Dispositivo.new_instance_based_on( + dp_pai, tipo, base_alteracao=base) dp.dispositivo_pai = dp_pai dp.nivel += 1 @@ -2224,6 +2271,9 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): else: dp.set_numero_completo([1, 0, 0, 0, 0, 0, ]) + if dp.dispositivo_atualizador: + registro_inclusao = True + # verificar se existe restrição de quantidade de itens if dp.dispositivo_pai: for perfil in perfil_parents: @@ -2262,7 +2312,8 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): dp.incrementar_irmaos(variacao, [local_add, ], force=False) dp.publicacao = pub_last - dp.save() + + dp.save(clean=not registro_inclusao) count_auto_insert = 0 if create_auto_inserts: @@ -2314,6 +2365,10 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin): ordem += Dispositivo.INTERVALO_ORDEM dp = Dispositivo.objects.get(pk=dp_pk) + dp.ta_publicado = None + dp.dispositivo_atualizador = None + dp.ordem_bloco_atualizador = 0 + dp.save(clean=False) ''' Reenquadrar todos os dispositivos que possuem pai antes da inserção atual e que são inferiores a dp, @@ -2624,8 +2679,12 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, ds = d while ds.dispositivo_subsequente: ds = ds.dispositivo_subsequente + dsps_ids.add(ds.pk) + if revogacao and ds.dispositivo_de_revogacao: + dsps_ids.remove(ds.pk) + if em_bloco: proximo_bloco = Dispositivo.objects.filter( ordem__gt=ds.ordem, @@ -2636,9 +2695,18 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, 'ta_id': ds.ta_id, 'nivel__gte': ds.nivel, 'ordem__gte': ds.ordem, - 'dispositivo_subsequente__isnull': True + 'dispositivo_subsequente__isnull': True, } + if revogacao: + params.update( + { + 'dispositivo_de_revogacao': False, + 'tipo_dispositivo__dispositivo_de_articulacao': False + } + + ) + if proximo_bloco: params['ordem__lt'] = proximo_bloco.ordem @@ -2655,9 +2723,9 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, dsps_ids = Dispositivo.objects.filter( id__in=dsps_ids - ).values_list('id', flat="True") - for dsp in dsps_ids: - with transaction.atomic(): + ).values_list('id', flat="True").order_by('ordem') + with transaction.atomic(): + for dsp in dsps_ids: data.update( self.registra_alteracao( bloco_alteracao, @@ -2713,10 +2781,10 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, if ndp.dispositivo_vigencia: ndp.inicio_eficacia = ndp.dispositivo_vigencia.inicio_eficacia - ndp.inicio_vigencia = ndp.dispositivo_vigencia.inicio_eficacia + ndp.inicio_vigencia = ndp.dispositivo_vigencia.inicio_vigencia else: ndp.inicio_eficacia = bloco_alteracao.inicio_eficacia - ndp.inicio_vigencia = bloco_alteracao.inicio_eficacia + ndp.inicio_vigencia = bloco_alteracao.inicio_vigencia try: ordem = dsp_a_alterar.criar_espaco( @@ -2748,6 +2816,7 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, ).ordem_bloco_atualizador + Dispositivo.INTERVALO_ORDEM else: ndp.ordem_bloco_atualizador = Dispositivo.INTERVALO_ORDEM + ndp.save() p.dispositivo_subsequente = ndp @@ -2765,10 +2834,10 @@ class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, filhos_diretos = dsp_a_alterar.dispositivos_filhos_set for d in filhos_diretos.all(): d.dispositivo_pai = ndp - d.save() + d.save(clean=False) - ndp.ta.reordenar_dispositivos() - bloco_alteracao.ordenar_bloco_alteracao() + # ndp.ta.reordenar_dispositivos() + # bloco_alteracao.ordenar_bloco_alteracao() if not revogacao: if 'message' not in data: @@ -2980,201 +3049,172 @@ class DispositivoSearchFragmentFormView(ListView): itens.append(item) return JsonResponse(itens, safe=False) - response = ListView.get(self, request, *args, **kwargs) - - if not self.object_list or \ - not isinstance(self.object_list, list) and \ - not self.object_list.exists(): - messages.info( - request, _('Não foram encontrados resultados ' - 'com seus critérios de busca!')) - username = self.request.user.username - self.logger.error("user=" + username + ". Não foram encontrados " - "resultados com esses critérios de busca. " - "id_tipo_ta=".format(request.GET['tipo_ta'])) - - try: - r = response.render() - return response - except Exception as e: - messages.error(request, "Erro - %s" % str(e)) - context = {} - self.template_name = 'compilacao/messages.html' - username = self.request.user.username - self.logger.error("user=" + username + ". " + str(e)) - return self.render_to_response(context) + return ListView.get(self, request, *args, **kwargs) def get_queryset(self): - try: - n = 10 - if 'max_results' in self.request.GET: - n = int(self.request.GET['max_results']) - - q = Q() - if 'initial_ref' in self.request.GET: - initial_ref = self.request.GET['initial_ref'] - if initial_ref: - q = q & Q(pk=initial_ref) - - result = Dispositivo.objects.filter(q).select_related( - 'ta').exclude( - tipo_dispositivo__dispositivo_de_alteracao=True) - - return result[:n] - - str_texto = '' - texto = '' - rotulo = '' - num_ta = '' - ano_ta = '' - - if 'texto' in self.request.GET: - str_texto = self.request.GET['texto'] + result = [] + try: + tipo_model = self.request.GET.get('tipo_model', '') + limit = int(self.request.GET.get('max_results', 100)) + tipo_ta = self.request.GET.get('tipo_ta', '') + num_ta = self.request.GET.get('num_ta', '') + ano_ta = self.request.GET.get('ano_ta', '') + rotulo = self.request.GET.get('rotulo', '') + str_texto = self.request.GET.get('texto', '') texto = str_texto.split(' ') - if 'rotulo' in self.request.GET: - rotulo = self.request.GET['rotulo'] - if rotulo: - q = q & Q(rotulo__icontains=rotulo) - - for item in texto: - if not item: - continue - if q: - q = q & (Q(texto__icontains=item) | - Q(texto_atualizador__icontains=item)) - else: - q = (Q(texto__icontains=item) | - Q(texto_atualizador__icontains=item)) - - if 'tipo_ta' in self.request.GET: - tipo_ta = self.request.GET['tipo_ta'] - if tipo_ta: - q = q & Q(ta__tipo_ta_id=tipo_ta) - - if 'num_ta' in self.request.GET: - num_ta = self.request.GET['num_ta'] - if num_ta: - q = q & Q(ta__numero=num_ta) - - if 'ano_ta' in self.request.GET: - ano_ta = self.request.GET['ano_ta'] - if ano_ta: - q = q & Q(ta__ano=ano_ta) - - if not q.children and not n: - n = 10 - q = q & Q(nivel__gt=0) - - result = Dispositivo.objects.order_by( - '-ta__data', - '-ta__ano', - '-ta__numero', - 'ta', - 'ordem').filter(q).select_related('ta') - - if 'data_type_selection' in self.request.GET and\ - self.request.GET['data_type_selection'] == 'checkbox': - result = result.exclude( - tipo_dispositivo__dispositivo_de_alteracao=True) - else: - if 'data_function' in self.request.GET and\ - self.request.GET['data_function'] == 'alterador': - result = result.exclude( - tipo_dispositivo__dispositivo_de_alteracao=False, - ) - result = result.exclude( - tipo_dispositivo__dispositivo_de_articulacao=False, - ) - print(str(result.query)) - - def resultados(r): - if n: - return r[:n] - else: - return r + tipo_resultado = self.request.GET.get('tipo_resultado', '') + tipo_resultado = '' if tipo_resultado == 'False' else tipo_resultado - """if num_ta and ano_ta and not rotulo and not str_texto and\ - 'data_type_selection' in self.request.GET and\ - self.request.GET['data_type_selection'] == 'checkbox': - return r - else: - return r[:n]""" + model_class = None - if 'tipo_model' not in self.request.GET: - return resultados(result) + if tipo_ta: + tipo_ta = TipoTextoArticulado.objects.get(pk=tipo_ta) + + if tipo_ta and tipo_model: + integrations_view_names = get_integrations_view_names() + for item in integrations_view_names: + if hasattr(item, 'model_type_foreignkey') and\ + hasattr(item, 'model'): + if (tipo_ta.content_type.model == + item.model.__name__.lower() and + tipo_ta.content_type.app_label == + item.model._meta.app_label): + + model_class = item.model + model_type_class = item.model_type_foreignkey + tipo_model = item.model_type_foreignkey.objects.get( + pk=tipo_model) + break - tipo_model = self.request.GET['tipo_model'] - if not tipo_model: - return resultados(result) + column_field = '' + if model_class: + for field in model_class._meta.fields: + if field.related_model == model_type_class: + column_field = field.column + break - integrations_view_names = get_integrations_view_names() + dts = self.request.GET.get('data_type_selection', '') + df = self.request.GET.get('data_function', '') - tipo_ta = TipoTextoArticulado.objects.get(pk=tipo_ta) + AND_CONTROLS = '' + if dts == 'checkbox': + AND_CONTROLS = 'AND td.dispositivo_de_alteracao = false' + else: + if df == 'alterador': + AND_CONTROLS = '''AND td.dispositivo_de_alteracao = true + AND td.dispositivo_de_articulacao = true''' + + texto = list(map("d.texto ~* '{}'".format, texto)) + AND_TEXTO_ROTULO = '' + if str_texto and rotulo: + AND_TEXTO_ROTULO = '''AND ( ({BUSCA_TEXTO} AND d.rotulo ~* '{BUSCA_ROTULO}') OR + ({BUSCA_TEXTO} AND d.rotulo = '' AND dp.rotulo ~* '{BUSCA_ROTULO}') + )'''.format( + BUSCA_TEXTO=' AND '.join(texto), + BUSCA_ROTULO=rotulo + ) + elif str_texto: + AND_TEXTO_ROTULO = ' AND '.join(texto) + elif rotulo: + AND_TEXTO_ROTULO = "AND d.rotulo ~* '{BUSCA_ROTULO}'".format( + BUSCA_ROTULO=rotulo) + + jtms = '' # JOIN_TYPE_MODEL_SELECTED + atms = '' # AND_TYPE_MODEL_SELECTED + if tipo_model: + jtms = 'JOIN {gfk_table} gfkt on (gfkt.id = ta.object_id)'.format( + gfk_table=model_class._meta.db_table) + atms = 'AND gfkt.{gfk_field_type} = {gfk_field_type_id}'.format( + gfk_field_type=column_field, + gfk_field_type_id=tipo_model.id, + ) - model_class = None - for item in integrations_view_names: - if hasattr(item, 'model_type_foreignkey') and\ - hasattr(item, 'model'): - if (tipo_ta.content_type.model == - item.model.__name__.lower() and - tipo_ta.content_type.app_label == - item.model._meta.app_label): - - model_class = item.model - model_type_class = item.model_type_foreignkey - tipo_model = item.model_type_foreignkey.objects.get( - pk=tipo_model) - break + sql = ''' + SELECT d.* FROM compilacao_dispositivo d + JOIN compilacao_dispositivo dp on (d.dispositivo_pai_id = dp.id) + JOIN compilacao_tipodispositivo td on (d.tipo_dispositivo_id = td.id) + JOIN compilacao_textoarticulado ta on (d.ta_id = ta.id) + + {JOIN_TYPE_MODEL_SELECTED} + + where d.nivel > 0 + + {AND_TYPE_MODEL_SELECTED} + + {AND_TEXTO_ROTULO} + {AND1_NUMERO} + {AND2_ANO} + {AND3_TIPO_TA} + {AND_CONTROLS} + + order by ta.data desc, + ta.numero desc, + ta.id desc, + d.ordem + {limit}; + '''.format( + + limit='limit {}'.format(limit) if limit else '', + + JOIN_TYPE_MODEL_SELECTED=jtms, + AND_TYPE_MODEL_SELECTED=atms, + + AND3_TIPO_TA="AND ta.tipo_ta_id = {}".format( + tipo_ta.id) if tipo_ta else '', + + AND2_ANO="AND ta.ano = {}".format( + ano_ta) if ano_ta else '', + + AND1_NUMERO="AND ta.numero ~* '{}'".format( + num_ta) if num_ta else '', + + AND_TEXTO_ROTULO=AND_TEXTO_ROTULO if AND_TEXTO_ROTULO else '', + AND_CONTROLS=AND_CONTROLS if AND_CONTROLS else '' + ) - if not model_class: - return resultados(result) + result = Dispositivo.objects.raw(sql) - column_field = '' - for field in model_class._meta.fields: - if field.related_model == model_type_class: - column_field = field.column - break + r = [] + ids = set() - if not column_field: - return resultados(result) + def proc_dispositivos(ds): - r = [] + for d in ds: - """ - ao integrar um model ao app de compilação, se este model possuir + if d.id not in ids: + r.append(d) + ids.add(d.id) - texto_articulado = GenericRelation( - TextoArticulado, related_query_name='texto_articulado') + if tipo_resultado == 'I': + if ds != result: + d.I = True + proc_dispositivos(d.dispositivos_filhos_set.filter( + tipo_dispositivo__dispositivo_de_alteracao=False + )) + elif tipo_resultado == 'S' and ds == result: - será uma integração mais eficiente para as buscas de Dispositivos - """ - if hasattr(model_class, 'texto_articulado'): - q = q & Q(**{ - 'ta__texto_articulado__' + column_field: tipo_model.pk - }) - if n: - result = result.filter(q)[:n] - else: - result = result.filter(q) + seq = Dispositivo.objects.filter( + ta=d.ta, + ordem__gt=d.ordem, + nivel__gt=0, + tipo_dispositivo__dispositivo_de_alteracao=False + ) + proc_dispositivos(seq[:limit]) - for d in result: - if not d.ta.content_object or\ - not hasattr(d.ta.content_object, column_field): - continue + elif tipo_resultado == 'S': + d.S = True - if tipo_model.pk == getattr(d.ta.content_object, column_field): - r.append(d) + proc_dispositivos(result) - if (len(r) == n and (not num_ta or - not ano_ta or rotulo or str_texto)): - break return r except Exception as e: username = self.request.user.username self.logger.error("user=" + username + ". " + str(e)) + return [] + pass class DispositivoSearchModalView(FormView): diff --git a/sapl/templates/compilacao/dispositivo_form_search_fragment.html b/sapl/templates/compilacao/dispositivo_form_search_fragment.html index 5e18a1b08..df0ee7626 100644 --- a/sapl/templates/compilacao/dispositivo_form_search_fragment.html +++ b/sapl/templates/compilacao/dispositivo_form_search_fragment.html @@ -8,14 +8,19 @@ {{ message|safe }} {% endfor %} - -{% if object_list.count >= 100 %} -
- {% trans 'Use argumentos para simplificar listagem...' %} +{% if object_list|length > 1000 %} +
+ {% trans 'Mais de Mil itens no resultado... melhore os argumentos para simplificar listagem...' %}
{% endif %} - -{% for dpt in object_list %} +{% with object_list|length as length_results %} + {% if length_results %} + + {{ length_results }} ite{{ length_results|pluralize:"m,ns"}} corresponde{{length_results|pluralize:"m"}} a sua busca. + + {% endif %} +{% endwith %} +{% for dpt in object_list %} {% ifchanged dpt.ta%} {% if not forloop.first %}{% endif %} {% endif %} +{% empty %} +
Não foram encontrados itens com seus critérios de busca!
{% endfor %} diff --git a/sapl/templates/compilacao/dispositivo_form_search_fragment_child.html b/sapl/templates/compilacao/dispositivo_form_search_fragment_child.html new file mode 100644 index 000000000..d835a87bc --- /dev/null +++ b/sapl/templates/compilacao/dispositivo_form_search_fragment_child.html @@ -0,0 +1,45 @@ +{% load i18n compilacao_filters %} + +
  • +
    + {% if df.I %} +
    I
    + {% endif %} + {% if df.S %} +
    S
    + {% endif %} + + +
    + + +
  • + diff --git a/sapl/templates/compilacao/subnav.html b/sapl/templates/compilacao/subnav.html index 8710eaa63..107fda2d2 100644 --- a/sapl/templates/compilacao/subnav.html +++ b/sapl/templates/compilacao/subnav.html @@ -1,7 +1,7 @@ {% load i18n %} {% load compilacao_filters %} {% load common_tags %} -