diff --git a/compilacao/migrations/0044_auto_20160301_1816.py b/compilacao/migrations/0044_auto_20160301_1816.py new file mode 100644 index 000000000..fcca5b769 --- /dev/null +++ b/compilacao/migrations/0044_auto_20160301_1816.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-03-01 21:16 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0043_auto_20160110_1733'), + ] + + operations = [ + migrations.AlterField( + model_name='dispositivo', + name='dispositivo_subsequente', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='compilacao.Dispositivo', verbose_name='Dispositivo Subsequente'), + ), + migrations.AlterField( + model_name='dispositivo', + name='dispositivo_substituido', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='compilacao.Dispositivo', verbose_name='Dispositivo Substituido'), + ), + ] diff --git a/compilacao/models.py b/compilacao/models.py index 8ce953a98..b05f21629 100644 --- a/compilacao/models.py +++ b/compilacao/models.py @@ -59,6 +59,17 @@ class BaseModel(models.Model): self.__class__, tuple(unique_fields)) raise ValidationError(msg) + def save(self, force_insert=False, force_update=False, using=None, + update_fields=None, clean=True): + if clean: + self.clean() + return models.Model.save( + self, + force_insert=force_insert, + force_update=force_update, + using=using, + update_fields=update_fields) + class TipoTextoArticulado(models.Model): sigla = models.CharField(max_length=3, verbose_name=_('Sigla')) @@ -581,11 +592,13 @@ class Dispositivo(BaseModel, TimestampedMixin): 'self', blank=True, null=True, default=None, related_name='+', + on_delete=models.SET_NULL, verbose_name=_('Dispositivo Subsequente')) dispositivo_substituido = models.ForeignKey( 'self', blank=True, null=True, default=None, related_name='+', + on_delete=models.SET_NULL, verbose_name=_('Dispositivo Substituido')) dispositivo_pai = models.ForeignKey( 'self', @@ -925,7 +938,7 @@ class Dispositivo(BaseModel, TimestampedMixin): def get_parents_asc(self): return self.get_parents(ordem='asc') - def incrementar_irmaos(self, variacao=0, tipoadd=[]): + def incrementar_irmaos(self, variacao=0, tipoadd=[], force=True): if not self.tipo_dispositivo.contagem_continua: irmaos = list(Dispositivo.objects.filter( @@ -956,6 +969,10 @@ class Dispositivo(BaseModel, TimestampedMixin): dp_profundidade = self.get_profundidade() + if (not force and not variacao and len(irmaos) > 0 and + irmaos[0].get_numero_completo() > self.get_numero_completo()): + return + irmaos_a_salvar = [] ultimo_irmao = None for irmao in irmaos: @@ -1032,12 +1049,8 @@ class Dispositivo(BaseModel, TimestampedMixin): proxima_articulacao = Dispositivo.objects.filter( ordem__gt=self.ordem, nivel=0, - ta_id=self.ta_id)[:1] - - if not proxima_articulacao.exists(): - return None - - return proxima_articulacao[0] + ta_id=self.ta_id).first() + return proxima_articulacao def is_relative_auto_insert(self, perfil_pk=None): if self.dispositivo_pai is not None: diff --git a/compilacao/views.py b/compilacao/views.py index a331705f1..5835ea8ea 100644 --- a/compilacao/views.py +++ b/compilacao/views.py @@ -1007,26 +1007,180 @@ class ActionsEditMixin: return JsonResponse(action(context), safe=False) def delete_item_dispositivo(self, context): - return self.delete_bloco_dispositivo(context) + return self.delete_bloco_dispositivo(context, bloco=False) - def delete_bloco_dispositivo(self, context): + def delete_bloco_dispositivo(self, context, bloco=True): base = Dispositivo.objects.get(pk=context['dispositivo_id']) base_anterior = Dispositivo.objects.order_by('-ordem').filter( ta_id=base.ta_id, ordem__lt=base.ordem )[:1] - base.delete() + data = {} if base_anterior.exists(): - if base_anterior[0].dispositivo_pai_id: - data = {'pk': base_anterior[0].pk, 'pai': [ - base_anterior[0].dispositivo_pai_id, ]} + if base.dispositivo_pai_id: + data = {'pk': base_anterior[0].pk, + 'pai': [base.dispositivo_pai_id, ]} else: data = {'pk': base_anterior[0].pk, 'pai': [-1, ]} - return data - else: - return {} + + self.remover_dispositivo(base, bloco) + return data + + def remover_dispositivo(self, base, bloco): + if base.dispositivo_subsequente or base.dispositivo_substituido: + p = base.dispositivo_substituido + n = base.dispositivo_subsequente + + if n: + print(n.id, n) + n.dispositivo_substituido = p + n.save() + + if p: + print(p.id, p) + p.dispositivo_subsequente = n + if n: + p.fim_vigencia = n.ini_vigencia - timedelta(days=1) + p.fim_eficacia = n.ini_eficacia - timedelta(days=1) + else: + p.fim_vigencia = None + p.fim_eficacia = None + + for d in base.dispositivos_filhos_set.all(): + if d.tipo_dispositivo.possiveis_pais.filter( + pai=base.tipo_dispositivo, + perfil__padrao=True, + filho_de_insercao_automatica=True).exists(): + self.remover_dispositivo(d, bloco) + elif not bloco: + p.dispositivos_filhos_set.add(d) + p.save() + base.delete() + elif not bloco: + for d in base.dispositivos_filhos_set.all(): + # inserções automáticas são excluidas junto com sua base, + # independente da escolha do usuário + if d.tipo_dispositivo.possiveis_pais.filter( + pai=base.tipo_dispositivo, + perfil__padrao=True, + filho_de_insercao_automatica=True).exists(): + continue + + # encontrar possível pai que será o primeiro parent possível + # dos parents do dispostivo + # imediatamente anterior ao dispositivo base + anterior = Dispositivo.objects.order_by('-ordem').filter( + ta_id=base.ta_id, + ordem__lt=d.ordem + ).exclude(pk=base.pk).first() + + if anterior.tipo_dispositivo == d.tipo_dispositivo: + d.dispositivo_pai = anterior.dispositivo_pai + d.nivel = anterior.nivel + if not d.tipo_dispositivo.contagem_continua: + d.set_numero_completo(anterior.get_numero_completo()) + + if d.dispositivo_substituido != anterior: + d.transform_in_next() + d.rotulo = d.rotulo_padrao() + else: + parents = anterior.get_parents() + + for candidato in parents: + if candidato.tipo_dispositivo == d.tipo_dispositivo: + d.dispositivo_pai = candidato.dispositivo_pai + d.nivel = candidato.nivel + if not d.tipo_dispositivo.contagem_continua: + d.set_numero_completo( + candidato.get_numero_completo()) + if d.dispositivo_substituido != candidato: + d.transform_in_next() + d.rotulo = d.rotulo_padrao() + break + elif d.tipo_dispositivo.possiveis_pais.filter( + pai=candidato.tipo_dispositivo, + perfil__padrao=True).exists(): + d.dispositivo_pai = candidato + if ';' in d.tipo_dispositivo.rotulo_prefixo_texto: + d.set_numero_completo([0, 0, 0, 0, 0, 0, ]) + else: + d.set_numero_completo([1, 0, 0, 0, 0, 0, ]) + d.nivel = candidato.nivel + 1 + break + + d.save() + d.organizar_niveis() + + if base.nivel: + if not base.tipo_dispositivo.contagem_continua: + pai_base = base.dispositivo_pai + irmaos_posteriores = pai_base.dispositivos_filhos_set.\ + filter( + ordem__gt=base.ordem, + tipo_dispositivo=base.tipo_dispositivo) + + numero_completo_base = base.get_numero_completo() + base.delete() + + else: + proxima_articulacao = base.get_proximo_nivel_zero() + numero_completo_base = base.get_numero_completo() + + if proxima_articulacao: + irmaos_posteriores = Dispositivo.objects.filter( + ta_id=base.ta_id, + ordem__gt=base.ordem, + tipo_dispositivo=base.tipo_dispositivo, + ordem__lt=proxima_articulacao.ordem + ) + else: + irmaos_posteriores = Dispositivo.objects.filter( + ta_id=base.ta_id, + ordem__gt=base.ordem, + tipo_dispositivo=base.tipo_dispositivo) + + base.delete() + + numero_completo_irmao = None + for irmao in irmaos_posteriores: + numero_completo_irmao = irmao.get_numero_completo() + irmao.set_numero_completo(numero_completo_base) + numero_completo_base = numero_completo_irmao + irmao.rotulo = irmao.rotulo_padrao() + irmao.save() + else: + proxima_articulacao = base.get_proximo_nivel_zero() + + # Dispostivos de Contagem contínua de dentro da base + dcc = Dispositivo.objects.order_by('ordem').filter( + ta_id=base.ta_id, + ordem__gt=base.ordem, + tipo_dispositivo__contagem_continua=True) + + for d in dcc: + ultimo_dcc = Dispositivo.objects.order_by( + 'ordem').filter( + ta_id=base.ta_id, + ordem__lt=d.ordem, + tipo_dispositivo__contagem_continua=True, + tipo_dispositivo=d.tipo_dispositivo).last() + if not ultimo_dcc: + break + d.set_numero_completo(ultimo_dcc.get_numero_completo()) + + if d.dispositivo_substituido != ultimo_dcc: + d.transform_in_next() + + d.rotulo = d.rotulo_padrao() + d.save(clean=False) + + base.delete() + + elif bloco: + # TODO: reorganizar dispositivos de contagem continua + base.delete() def add_prior(self, context): return {} @@ -1124,7 +1278,7 @@ class ActionsEditMixin: dp.rotulo = dp.rotulo_padrao() dp.ordem = ordem - dp.incrementar_irmaos(variacao, [local_add, ]) + dp.incrementar_irmaos(variacao, [local_add, ], force=False) dp.clean() dp.save() diff --git a/static/js/compilacao_edit.js b/static/js/compilacao_edit.js index a5f720e33..feffe4450 100644 --- a/static/js/compilacao_edit.js +++ b/static/js/compilacao_edit.js @@ -250,7 +250,7 @@ $(document).ready(function() { $("#message_block").css("display", "none"); href = location.href.split('#') - if (href.length == 2) { + if (href.length == 2 && href[1] != '') { clickUpdateDispositivo(null, href[1], href[1], 'refresh', true); } diff --git a/static/styles/compilacao.scss b/static/styles/compilacao.scss index d4b79b424..d41499311 100644 --- a/static/styles/compilacao.scss +++ b/static/styles/compilacao.scss @@ -143,12 +143,15 @@ a:link:after, a:visited:after { .cp { - .desativado, .desativado * { - text-decoration: line-through; - color: #999 !important; + .desativado { - table, table td { - border: 1px dotted #ccc; + .dtxt, .dtxt * { + text-decoration: line-through; + color: #999 !important; + + table, table td { + border: 1px dotted #ccc; + } } } @@ -261,7 +264,6 @@ a:link:after, a:visited:after { } - .bloco_alteracao { padding-left: 10%; font-style: italic; @@ -399,6 +401,8 @@ a:link:after, a:visited:after { transform-origin: right; transition: all 0.3s ease; border-top: 1px solid $color_buttons; + + ul.btns-action { list-style: none; padding: 0; @@ -436,6 +440,7 @@ a:link:after, a:visited:after { text-align: left; font-size: 1.6rem; + .container-busca { ul{ list-style: none; @@ -708,7 +713,16 @@ a:link:after, a:visited:after { margin-bottom: 15em; - margin-left: 0.8em; + + .desativado, .desativado * { + + text-decoration: line-through; + color: #999 !important; + + table, table td { + border: 1px dotted #ccc; + } + } a { text-decoration: none; @@ -723,54 +737,36 @@ a:link:after, a:visited:after { font-weight: bold; color: #BFD1F6; } - .artigo { float: none; } + .caput { + margin-top: 0; + } & > .actions_left { color: #fff; + left: 0em; position: absolute; - left: -2.6em; opacity: 0; transition: all 0.4s ease-in-out; + z-index: 1; a { &.btn-edit { @include background-top-down(#3498DB, #2980C9); - @include border-radius(7px); color: #ffffff !important; font-weight: bold; - padding: 2px 7px 2px 7px; + padding: 5px 7px 3px; + display: inline-block; + line-height: 1; - &:hover { - @include background-top-down(#3cb0fd, #3498DB); - } } } } &:hover > .actions_left { - opacity: 0.5; - background-color: transparent !important; - &::before { - content: ""; - border: inset 0.375rem; - border-color: transparent transparent transparent #3cb0fd; - position: absolute; - display: block; - height: 0; - width: 0; - top: 0.4rem; - right: -0.73rem; - } - &:hover { - opacity: 1; - &::before { - border-color: transparent transparent transparent #3cf0ff; - } - } + opacity: 1; } - .bloco { display: block; clear: both; @@ -781,27 +777,36 @@ a:link:after, a:visited:after { cursor: pointer; } } - .articulacao{ - margin-left: -0.8em; + .articulacao { + border-top: 2 px solid #e5e5e5; + margin: 2em 0; + } + .bloco_alteracao { + border: 1px solid #ddd; + margin: -1px 0 0; + padding: 1em; + } + + .articulacao1 { margin-top: 2em; &::before { content: "Articulação"; background-color: #eee; - border-bottom: 1px solid #aaa; + border-bottom: 1px dotted #E88C8C; padding: 0.333em; padding-left: 1em; display:block; } } - .bloco_alteracao { - @extend .articulacao; - margin: 0; - padding-top: 3em; - padding-left: 0em; - background: #ddd; + .bloco_alteracao1 { + @extend .articulacao1; + margin: -1px 0 0; + padding: 1em; + border: 1px dotted #E88C8C; + overflow: hidden; &::before { content: "Bloco de Alteração"; - + margin: -1em -1em 0; display: block; } } @@ -837,16 +842,19 @@ a:link:after, a:visited:after { a:hover { background: transparent; } - } - & > .bloco { - padding: 1em 0; opacity: 1; - margin: 0 !important; + margin: 1em !important; + } + + .bloco_alteracao { + padding-top: 2em; } + + & > .dpt { padding: 0; &:last-child { diff --git a/templates/compilacao/text_edit.html b/templates/compilacao/text_edit.html index 41df0d905..7b9e3916a 100644 --- a/templates/compilacao/text_edit.html +++ b/templates/compilacao/text_edit.html @@ -14,7 +14,6 @@