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.contenttypes.fields import GenericForeignKey
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.encoding import force_text
from django.utils.translation import ugettext_lazy as _
import reversion
from sapl.compilacao.utils import (get_integrations_view_names, int_to_letter,
int_to_roman)
@ -978,6 +978,11 @@ class Dispositivo(BaseModel, TimestampedMixin):
blank=True, null=True, default=None,
related_name='dispositivos_filhos_set',
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(
'self',
blank=True, null=True, default=None,
@ -990,6 +995,10 @@ class Dispositivo(BaseModel, TimestampedMixin):
related_name='dispositivos_alterados_set',
verbose_name=_('Dispositivo Atualizador'))
contagem_continua = models.BooleanField(
default=False,
choices=YES_NO_CHOICES, verbose_name=_('Contagem contínua'))
class Meta:
verbose_name = _('Dispositivo')
verbose_name_plural = _('Dispositivos')
@ -1004,10 +1013,24 @@ class Dispositivo(BaseModel, TimestampedMixin):
'dispositivo4',
'dispositivo5',
'tipo_dispositivo',
'dispositivo_raiz',
'dispositivo_pai',
'dispositivo_atualizador',
'ta_publicado',
'publicacao',),
('ta',
'dispositivo0',
'dispositivo1',
'dispositivo2',
'dispositivo3',
'dispositivo4',
'dispositivo5',
'tipo_dispositivo',
'contagem_continua',
'dispositivo_raiz',
'dispositivo_atualizador',
'ta_publicado',
'publicacao',),
)
permissions = (
('change_dispositivo_edicao_dinamica', _(
@ -1027,10 +1050,58 @@ class Dispositivo(BaseModel, TimestampedMixin):
'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):
return '%(rotulo)s' % {
'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):
"""
0 = Sem inserção - com nomeclatura padrao
@ -1210,7 +1281,7 @@ class Dispositivo(BaseModel, TimestampedMixin):
if not numero[i]:
continue
if i > profundidade:
if i < profundidade:
continue
numero[i] -= 1
@ -1516,12 +1587,6 @@ class Dispositivo(BaseModel, TimestampedMixin):
return True
return False
def get_raiz(self):
dp = self
while dp.dispositivo_pai is not None:
dp = dp.dispositivo_pai
return dp
def history(self):
ultimo = self
while ultimo.dispositivo_subsequente:

75
sapl/compilacao/views.py

@ -1,7 +1,7 @@
import logging
import sys
from collections import OrderedDict
from datetime import timedelta
import logging
import sys
from braces.views import FormMessagesMixin
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.utils.dateparse import parse_date
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.base import TemplateView
from django.views.generic.detail import DetailView
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.settings import BASE_DIR
TipoNotaCrud = CrudAux.build(TipoNota, 'tipo_nota')
TipoVideCrud = CrudAux.build(TipoVide, 'tipo_vide')
TipoPublicacaoCrud = CrudAux.build(TipoPublicacao, 'tipo_publicacao')
@ -1661,10 +1662,13 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
base.delete()
for irmao in irmaos_posteriores:
irmao.transform_in_prior(
profundidade=profundidade_base)
irmao.rotulo = irmao.rotulo_padrao()
irmao.save()
try:
irmao.transform_in_prior(
profundidade=profundidade_base)
irmao.rotulo = irmao.rotulo_padrao()
irmao.save()
except:
break
irmaos = pai_base.dispositivos_filhos_set.\
filter(tipo_dispositivo=base.tipo_dispositivo)
@ -1766,17 +1770,37 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
dcc_a_religar = dcc_a_religar.exclude(
ordem__gte=proxima_articulacao.ordem)
primeiro_a_religar = 0
primeiro_a_religar = True
profundidade = d.get_profundidade()
for dr in dcc_a_religar:
if not primeiro_a_religar:
primeiro_a_religar = dr.dispositivo0
base.delete()
dr.dispositivo0 = (
dr.dispositivo0 -
primeiro_a_religar + d.dispositivo0)
if primeiro_a_religar:
primeiro_a_religar = False
d_pk = d.pk
d.delete()
if base.pk == d_pk:
base = d
dr.transform_in_prior(profundidade=profundidade)
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:
dpts = base.dispositivos_alterados_set.all().order_by(
@ -1785,7 +1809,19 @@ class ActionDeleteDispositivoMixin(ActionsCommonsMixin):
self.remover_dispositivo(dpt, False)
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 ''
@ -2198,6 +2234,11 @@ class ActionDispositivoCreateMixin(ActionsCommonsMixin):
'foi excedido.'), time=6000)
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(
espaco_a_criar=1, local=local_add)

Loading…
Cancel
Save