Browse Source

corrige excl em bloco de dispositivos na app comp

pull/1781/head
LeandroRoberto 7 years ago
parent
commit
42da8ff5b2
  1. 44
      sapl/compilacao/migrations/0005_auto_20180319_1041.py
  2. 35
      sapl/compilacao/migrations/0006_auto_20180321_1054.py
  3. 81
      sapl/compilacao/models.py
  4. 75
      sapl/compilacao/views.py

44
sapl/compilacao/migrations/0005_auto_20180319_1041.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-19 13:41
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
def adjust_dispositivo_raiz(apps, schema_editor):
Dispositivo = apps.get_model('compilacao', 'Dispositivo')
articulacoes = Dispositivo.objects.filter(
dispositivo_pai__isnull=True)
def adicionar_raiz_aos_filhos(raiz, dispositivo):
for d in dispositivo.dispositivos_filhos_set.all():
d.dispositivo_raiz = raiz
d.save()
adicionar_raiz_aos_filhos(raiz, d)
for artic in articulacoes:
adicionar_raiz_aos_filhos(artic, artic)
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0004_auto_20171031_1327'),
]
operations = [
migrations.AddField(
model_name='dispositivo',
name='dispositivo_raiz',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='nodes', to='compilacao.Dispositivo', verbose_name='Dispositivo Raiz'),
),
migrations.AlterUniqueTogether(
name='dispositivo',
unique_together=set([('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5',
'tipo_dispositivo', 'dispositivo_raiz', 'dispositivo_pai', 'dispositivo_atualizador', 'ta_publicado', 'publicacao'), ('ta', 'ordem')]),
),
migrations.RunPython(adjust_dispositivo_raiz),
]

35
sapl/compilacao/migrations/0006_auto_20180321_1054.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-03-21 13:54
from __future__ import unicode_literals
from django.db import migrations, models
def adjust_contagem_continua(apps, schema_editor):
Dispositivo = apps.get_model('compilacao', 'Dispositivo')
Dispositivo.objects.filter(
tipo_dispositivo__contagem_continua=True
).update(contagem_continua=True)
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0005_auto_20180319_1041'),
]
operations = [
migrations.AddField(
model_name='dispositivo',
name='contagem_continua',
field=models.BooleanField(choices=[(
True, 'Sim'), (False, 'Não')], default=False, verbose_name='Contagem contínua'),
),
migrations.AlterUniqueTogether(
name='dispositivo',
unique_together=set([('ta', 'ordem'), ('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5', 'tipo_dispositivo', 'contagem_continua', 'dispositivo_raiz', 'dispositivo_atualizador', 'ta_publicado',
'publicacao'), ('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5', 'tipo_dispositivo', 'dispositivo_raiz', 'dispositivo_pai', 'dispositivo_atualizador', 'ta_publicado', 'publicacao')]),
),
migrations.RunPython(adjust_contagem_continua),
]

81
sapl/compilacao/models.py

@ -1,5 +1,4 @@
import reversion
from django.contrib import messages from django.contrib import messages
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -13,6 +12,7 @@ from django.utils import timezone
from django.utils.decorators import classonlymethod from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import reversion
from sapl.compilacao.utils import (get_integrations_view_names, int_to_letter, from sapl.compilacao.utils import (get_integrations_view_names, int_to_letter,
int_to_roman) int_to_roman)
@ -978,6 +978,11 @@ class Dispositivo(BaseModel, TimestampedMixin):
blank=True, null=True, default=None, blank=True, null=True, default=None,
related_name='dispositivos_filhos_set', related_name='dispositivos_filhos_set',
verbose_name=_('Dispositivo Pai')) verbose_name=_('Dispositivo Pai'))
dispositivo_raiz = models.ForeignKey(
'self',
blank=True, null=True, default=None,
related_name='nodes',
verbose_name=_('Dispositivo Raiz'))
dispositivo_vigencia = models.ForeignKey( dispositivo_vigencia = models.ForeignKey(
'self', 'self',
blank=True, null=True, default=None, blank=True, null=True, default=None,
@ -990,6 +995,10 @@ class Dispositivo(BaseModel, TimestampedMixin):
related_name='dispositivos_alterados_set', related_name='dispositivos_alterados_set',
verbose_name=_('Dispositivo Atualizador')) verbose_name=_('Dispositivo Atualizador'))
contagem_continua = models.BooleanField(
default=False,
choices=YES_NO_CHOICES, verbose_name=_('Contagem contínua'))
class Meta: class Meta:
verbose_name = _('Dispositivo') verbose_name = _('Dispositivo')
verbose_name_plural = _('Dispositivos') verbose_name_plural = _('Dispositivos')
@ -1004,10 +1013,24 @@ class Dispositivo(BaseModel, TimestampedMixin):
'dispositivo4', 'dispositivo4',
'dispositivo5', 'dispositivo5',
'tipo_dispositivo', 'tipo_dispositivo',
'dispositivo_raiz',
'dispositivo_pai', 'dispositivo_pai',
'dispositivo_atualizador', 'dispositivo_atualizador',
'ta_publicado', 'ta_publicado',
'publicacao',), 'publicacao',),
('ta',
'dispositivo0',
'dispositivo1',
'dispositivo2',
'dispositivo3',
'dispositivo4',
'dispositivo5',
'tipo_dispositivo',
'contagem_continua',
'dispositivo_raiz',
'dispositivo_atualizador',
'ta_publicado',
'publicacao',),
) )
permissions = ( permissions = (
('change_dispositivo_edicao_dinamica', _( ('change_dispositivo_edicao_dinamica', _(
@ -1027,10 +1050,58 @@ class Dispositivo(BaseModel, TimestampedMixin):
'Permissão alteração global do dispositivo de vigência')), 'Permissão alteração global do dispositivo de vigência')),
) )
def clean(self):
"""
Check for instances with null values in unique_together fields.
"""
from django.core.exceptions import ValidationError
for field_tuple in self._meta.unique_together[:]:
unique_filter = {}
unique_fields = []
null_found = False
for field_name in field_tuple:
field_value = getattr(self, field_name)
if getattr(self, field_name) is None:
unique_filter['%s__isnull' % field_name] = True
null_found = True
else:
unique_filter['%s' % field_name] = field_value
unique_fields.append(field_name)
if null_found:
unique_queryset = self.__class__.objects.filter(
**unique_filter)
if self.pk:
unique_queryset = unique_queryset.exclude(pk=self.pk)
if not self.contagem_continua and \
'contagem_continua' in field_tuple:
continue
if unique_queryset.exists():
msg = self.unique_error_message(
self.__class__, tuple(unique_fields))
raise ValidationError(msg)
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None, clean=True):
self.dispositivo_raiz = self.get_raiz()
self.contagem_continua = self.tipo_dispositivo.contagem_continua
return super().save(
force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields, clean=clean)
def __str__(self): def __str__(self):
return '%(rotulo)s' % { return '%(rotulo)s' % {
'rotulo': (self.rotulo if self.rotulo else self.tipo_dispositivo)} 'rotulo': (self.rotulo if self.rotulo else self.tipo_dispositivo)}
def get_raiz(self):
dp = self
while dp.dispositivo_pai is not None:
dp = dp.dispositivo_pai
return dp
def rotulo_padrao(self, local_insert=0, for_insert_in=0): def rotulo_padrao(self, local_insert=0, for_insert_in=0):
""" """
0 = Sem inserção - com nomeclatura padrao 0 = Sem inserção - com nomeclatura padrao
@ -1210,7 +1281,7 @@ class Dispositivo(BaseModel, TimestampedMixin):
if not numero[i]: if not numero[i]:
continue continue
if i > profundidade: if i < profundidade:
continue continue
numero[i] -= 1 numero[i] -= 1
@ -1516,12 +1587,6 @@ class Dispositivo(BaseModel, TimestampedMixin):
return True return True
return False return False
def get_raiz(self):
dp = self
while dp.dispositivo_pai is not None:
dp = dp.dispositivo_pai
return dp
def history(self): def history(self):
ultimo = self ultimo = self
while ultimo.dispositivo_subsequente: while ultimo.dispositivo_subsequente:

75
sapl/compilacao/views.py

@ -1,7 +1,7 @@
import logging
import sys
from collections import OrderedDict from collections import OrderedDict
from datetime import timedelta from datetime import timedelta
import logging
import sys
from braces.views import FormMessagesMixin from braces.views import FormMessagesMixin
from django import forms from django import forms
@ -19,8 +19,8 @@ from django.http.response import (HttpResponse, HttpResponseRedirect,
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.utils.dateparse import parse_date from django.utils.dateparse import parse_date
from django.utils.encoding import force_text 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 string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import (CreateView, DeleteView, FormView, from django.views.generic.edit import (CreateView, DeleteView, FormView,
@ -51,6 +51,7 @@ from sapl.compilacao.utils import (DISPOSITIVO_SELECT_RELATED,
from sapl.crud.base import Crud, CrudAux, CrudListView, make_pagination from sapl.crud.base import Crud, CrudAux, CrudListView, make_pagination
from sapl.settings import BASE_DIR from sapl.settings import BASE_DIR
TipoNotaCrud = CrudAux.build(TipoNota, 'tipo_nota') TipoNotaCrud = CrudAux.build(TipoNota, 'tipo_nota')
TipoVideCrud = CrudAux.build(TipoVide, 'tipo_vide') TipoVideCrud = CrudAux.build(TipoVide, 'tipo_vide')
TipoPublicacaoCrud = CrudAux.build(TipoPublicacao, 'tipo_publicacao') TipoPublicacaoCrud = CrudAux.build(TipoPublicacao, 'tipo_publicacao')
@ -1661,10 +1662,13 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
base.delete() base.delete()
for irmao in irmaos_posteriores: for irmao in irmaos_posteriores:
irmao.transform_in_prior( try:
profundidade=profundidade_base) irmao.transform_in_prior(
irmao.rotulo = irmao.rotulo_padrao() profundidade=profundidade_base)
irmao.save() irmao.rotulo = irmao.rotulo_padrao()
irmao.save()
except:
break
irmaos = pai_base.dispositivos_filhos_set.\ irmaos = pai_base.dispositivos_filhos_set.\
filter(tipo_dispositivo=base.tipo_dispositivo) filter(tipo_dispositivo=base.tipo_dispositivo)
@ -1766,17 +1770,37 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
dcc_a_religar = dcc_a_religar.exclude( dcc_a_religar = dcc_a_religar.exclude(
ordem__gte=proxima_articulacao.ordem) ordem__gte=proxima_articulacao.ordem)
primeiro_a_religar = 0 primeiro_a_religar = True
profundidade = d.get_profundidade()
for dr in dcc_a_religar: for dr in dcc_a_religar:
if not primeiro_a_religar: if primeiro_a_religar:
primeiro_a_religar = dr.dispositivo0 primeiro_a_religar = False
base.delete() d_pk = d.pk
d.delete()
dr.dispositivo0 = ( if base.pk == d_pk:
dr.dispositivo0 - base = d
primeiro_a_religar + d.dispositivo0)
dr.transform_in_prior(profundidade=profundidade)
dr.rotulo = dr.rotulo_padrao() dr.rotulo = dr.rotulo_padrao()
dr.save(clean=base != dr) try:
dr.save(clean=base != dr)
except:
break
# Pode não ser religavável
# Exemplo, numa sequencia com variáção:
# Art. 1º
# ...
# Art. 1º-A
# ...
# Art. 2º
# ...
# Ao tentar excluir o Art. 1º-A, o algoritmo
# de religação tentará reduzir Art. 2º para 1º
# e o método clean lançará um erro visto que
# já existe um, por outro lado, não é lógico
# reduzir Art 2º para Art. 1º-A, ou seja,
# em caso de variação não há o que reduzir
if base.tipo_dispositivo.dispositivo_de_alteracao: if base.tipo_dispositivo.dispositivo_de_alteracao:
dpts = base.dispositivos_alterados_set.all().order_by( dpts = base.dispositivos_alterados_set.all().order_by(
@ -1785,7 +1809,19 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
self.remover_dispositivo(dpt, False) self.remover_dispositivo(dpt, False)
if base.pk: if base.pk:
base.delete() """
Um registro a ser excluido em bloco que não é um
dispositivo de contagem contínua, neste ponto, teve todos
os seus filhos excluídos mas ainda não foi e, tão pouco,
foi seus imãos (anterior e posterior) religados
numericamente.
A exclusão em bloco religa apenas dispositivos de contagem
continua internos extra bloco.
Depois do bloco limpo, a função é chamada novamente para
excluir realmente a escolha do usuário
e religar seus irmaos
"""
self.remover_dispositivo(base, False)
return '' return ''
@ -2198,6 +2234,11 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin):
'foi excedido.'), time=6000) 'foi excedido.'), time=6000)
return data return data
# FIXME - a criação de espaço não está considerando o local correto
# quando não existem irmãos ou pais possíveis e jogando o
# dispositivo a ser inserido para o final da articulação
# e não para onde o usuário decidiu, bem como para logo abaixo
# seus filhos serem associados a ele.
ordem = base.criar_espaco( ordem = base.criar_espaco(
espaco_a_criar=1, local=local_add) espaco_a_criar=1, local=local_add)

Loading…
Cancel
Save