diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 7ae6b85ba..071d959b3 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -14,7 +14,8 @@ from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.settings import MAX_DOC_UPLOAD_SIZE from sapl.utils import RANGE_ANOS, RangeWidgetOverride -from .models import AssuntoNorma, NormaJuridica +from .models import (AssuntoNorma, NormaJuridica, NormaRelacionada, + TipoNormaJuridica) def get_esferas(): @@ -146,3 +147,49 @@ class NormaJuridicaForm(ModelForm): norma.materia = self.cleaned_data['materia'] norma = super(NormaJuridicaForm, self).save(commit=True) return norma + + +class NormaRelacionadaForm(ModelForm): + + tipo = forms.ModelChoiceField( + label='Tipo', + required=True, + queryset=TipoNormaJuridica.objects.all(), + empty_label='----------', + ) + numero = forms.CharField(label='Número', required=True) + ano = forms.CharField(label='Ano', required=True) + ementa = forms.CharField( + required=False, + widget=forms.Textarea(attrs={'disabled': 'disabled'})) + + class Meta: + model = NormaRelacionada + fields = ['tipo', 'numero', 'ano', 'ementa', 'tipo_vinculo'] + + def __init__(self, *args, **kwargs): + super(NormaRelacionadaForm, self).__init__(*args, **kwargs) + + def clean(self): + if self.errors: + return self.errors + cleaned_data = self.cleaned_data + + try: + norma_relacionada = NormaJuridica.objects.get( + numero=cleaned_data['numero'], + ano=cleaned_data['ano'], + tipo=cleaned_data['tipo']) + except ObjectDoesNotExist: + msg = _('A norma a ser relacionada não existe.') + raise ValidationError(msg) + else: + cleaned_data['norma_relacionada'] = norma_relacionada + + return cleaned_data + + def save(self, commit=False): + relacionada = super(NormaRelacionadaForm, self).save(commit) + relacionada.norma_relacionada = self.cleaned_data['norma_relacionada'] + relacionada.save() + return relacionada diff --git a/sapl/norma/migrations/0023_auto_20161123_1359.py b/sapl/norma/migrations/0023_auto_20161123_1359.py new file mode 100644 index 000000000..450071cc8 --- /dev/null +++ b/sapl/norma/migrations/0023_auto_20161123_1359.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-23 13:59 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0022_auto_20161110_0910'), + ] + + operations = [ + migrations.AlterModelOptions( + name='vinculonormajuridica', + options={'verbose_name': 'Tipo de Vínculo entre Normas Jurídicas', 'verbose_name_plural': 'Tipos de Vínculos entre Normas Jurídicas'}, + ), + migrations.RemoveField( + model_name='vinculonormajuridica', + name='norma_referente', + ), + migrations.RemoveField( + model_name='vinculonormajuridica', + name='norma_referida', + ), + migrations.RemoveField( + model_name='vinculonormajuridica', + name='tipo_vinculo', + ), + migrations.AddField( + model_name='vinculonormajuridica', + name='descricao', + field=models.CharField(blank=True, max_length=20, verbose_name='Descrição'), + ), + migrations.AddField( + model_name='vinculonormajuridica', + name='sigla', + field=models.CharField(blank=True, max_length=1, verbose_name='Nome'), + ), + ] diff --git a/sapl/norma/migrations/0024_auto_20161123_1430.py b/sapl/norma/migrations/0024_auto_20161123_1430.py new file mode 100644 index 000000000..e531c2a38 --- /dev/null +++ b/sapl/norma/migrations/0024_auto_20161123_1430.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-23 14:30 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0023_auto_20161123_1359'), + ] + + operations = [ + migrations.AlterField( + model_name='vinculonormajuridica', + name='descricao', + field=models.CharField(blank=True, max_length=50, verbose_name='Descrição'), + ), + migrations.AlterField( + model_name='vinculonormajuridica', + name='sigla', + field=models.CharField(blank=True, max_length=1, verbose_name='Sigla'), + ), + ] diff --git a/sapl/norma/migrations/0025_normarelacionada.py b/sapl/norma/migrations/0025_normarelacionada.py new file mode 100644 index 000000000..1cfafedb2 --- /dev/null +++ b/sapl/norma/migrations/0025_normarelacionada.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-23 14:44 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0024_auto_20161123_1430'), + ] + + operations = [ + migrations.CreateModel( + name='NormaRelacionada', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('norma_principal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='norma_principal', to='norma.NormaJuridica')), + ('norma_relacionada', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='norma_relacionada', to='norma.NormaJuridica')), + ('tipo_vinculo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.VinculoNormaJuridica')), + ], + options={ + 'verbose_name': 'Norma Relacionada', + 'verbose_name_plural': 'Normas Relacionadas', + }, + ), + ] diff --git a/sapl/norma/migrations/0026_auto_20161123_1450.py b/sapl/norma/migrations/0026_auto_20161123_1450.py new file mode 100644 index 000000000..6fda19247 --- /dev/null +++ b/sapl/norma/migrations/0026_auto_20161123_1450.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-23 14:50 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0025_normarelacionada'), + ] + + operations = [ + migrations.AlterField( + model_name='normarelacionada', + name='tipo_vinculo', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.VinculoNormaJuridica', verbose_name='Tipo de Vínculo'), + ), + ] diff --git a/sapl/norma/migrations/0027_auto_20161123_1538.py b/sapl/norma/migrations/0027_auto_20161123_1538.py new file mode 100644 index 000000000..f44348b0e --- /dev/null +++ b/sapl/norma/migrations/0027_auto_20161123_1538.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-23 15:38 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0026_auto_20161123_1450'), + ] + + operations = [ + migrations.AlterField( + model_name='normarelacionada', + name='norma_principal', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='norma_principal', to='norma.NormaJuridica', verbose_name='Norma Principal'), + ), + migrations.AlterField( + model_name='normarelacionada', + name='norma_relacionada', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='norma_relacionada', to='norma.NormaJuridica', verbose_name='Norma Relacionada'), + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index debbdadc9..49e85182c 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -171,37 +171,37 @@ class LegislacaoCitada(models.Model): class VinculoNormaJuridica(models.Model): - TIPO_VINCULO_CHOICES = ( - ('A', _('Altera a norma')), - ('R', _('Revoga integralmente a norma')), - ('P', _('Revoga parcialmente a norma')), - ('T', _('Revoga integralmente por consolidação')), - ('C', _('Norma correlata')), - ('S', _('Ressalva a norma')), - ('E', _('Reedita a norma')), - ('I', _('Reedita a norma com alteração')), - ('G', _('Regulamenta a norma')), - ('K', _('Suspende parcialmente a norma')), - ('L', _('Suspende integralmente a norma')), - ('N', _('Julgada integralmente inconstitucional')), - ('O', _('Julgada parcialmente inconstitucional')), - ) + sigla = models.CharField( + max_length=1, blank=True, verbose_name=_('Sigla')) + descricao = models.CharField( + max_length=50, blank=True, verbose_name=_('Descrição')) + + class Meta: + verbose_name = _('Tipo de Vínculo entre Normas Jurídicas') + verbose_name_plural = _('Tipos de Vínculos entre Normas Jurídicas') + + def __str__(self): + return self.descricao + - # TODO M2M ??? - norma_referente = models.ForeignKey( - NormaJuridica, related_name='norma_referente_set') - norma_referida = models.ForeignKey( - NormaJuridica, related_name='norma_referida_set') - tipo_vinculo = models.CharField( - max_length=1, blank=True, choices=TIPO_VINCULO_CHOICES) +class NormaRelacionada(models.Model): + norma_principal = models.ForeignKey( + NormaJuridica, + related_name='norma_principal', + verbose_name=_('Norma Principal')) + norma_relacionada = models.ForeignKey( + NormaJuridica, + related_name='norma_relacionada', + verbose_name=_('Norma Relacionada')) + tipo_vinculo = models.ForeignKey( + VinculoNormaJuridica, verbose_name=_('Tipo de Vínculo')) class Meta: - verbose_name = _('Vínculo entre Normas Jurídicas') - verbose_name_plural = _('Vínculos entre Normas Jurídicas') + verbose_name = _('Norma Relacionada') + verbose_name_plural = _('Normas Relacionadas') def __str__(self): - return _('Referente: %(referente)s \n' - 'Referida: %(referida)s \nVínculo: %(vinculo)s') % { - 'referente': self.norma_referente, - 'referida': self.norma_referida, - 'vinculo': self.tipo_vinculo} + return _('Principal: %(norma_principal)s' + ' - Relacionada: %(norma_relacionada)s') % { + 'norma_principal': self.norma_principal, + 'norma_relacionada': self.norma_relacionada} diff --git a/sapl/norma/urls.py b/sapl/norma/urls.py index 8c261e23e..59d8f3473 100644 --- a/sapl/norma/urls.py +++ b/sapl/norma/urls.py @@ -1,7 +1,8 @@ from django.conf.urls import include, url from sapl.norma.views import (AssuntoNormaCrud, NormaCrud, NormaPesquisaView, - TipoNormaCrud, NormaTaView) + NormaRelacionadaCrud, NormaTaView, TipoNormaCrud, + VinculoNormaJuridicaCrud, recuperar_norma) from .apps import AppConfig @@ -9,14 +10,20 @@ app_name = AppConfig.name urlpatterns = [ - url(r'^norma/', include(NormaCrud.get_urls())), + url(r'^norma/', include(NormaCrud.get_urls() + + NormaRelacionadaCrud.get_urls())), # Integração com Compilação url(r'^norma/(?P[0-9]+)/ta$', NormaTaView.as_view(), name='norma_ta'), url(r'^sistema/norma/tipo/', include(TipoNormaCrud.get_urls())), url(r'^sistema/norma/assunto/', include(AssuntoNormaCrud.get_urls())), + url(r'^sistema/norma/vinculo/', include( + VinculoNormaJuridicaCrud.get_urls())), url(r'^norma/pesquisar$', NormaPesquisaView.as_view(), name='norma_pesquisa'), + + url(r'^norma/recuperar-norma/', recuperar_norma), + ] diff --git a/sapl/norma/views.py b/sapl/norma/views.py index 5a0dc283a..8f90190e4 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -1,6 +1,7 @@ from datetime import datetime from django.core.urlresolvers import reverse +from django.http import JsonResponse from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ from django.views.generic import FormView, ListView @@ -12,8 +13,9 @@ from sapl.compilacao.views import IntegracaoTaView from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, make_pagination) -from .forms import NormaFilterSet, NormaJuridicaForm -from .models import AssuntoNorma, NormaJuridica, TipoNormaJuridica +from .forms import NormaFilterSet, NormaJuridicaForm, NormaRelacionadaForm +from .models import (AssuntoNorma, NormaJuridica, NormaRelacionada, + TipoNormaJuridica, VinculoNormaJuridica) # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') AssuntoNormaCrud = CrudAux.build(AssuntoNorma, 'assunto_norma_juridica', @@ -23,6 +25,37 @@ AssuntoNormaCrud = CrudAux.build(AssuntoNorma, 'assunto_norma_juridica', TipoNormaCrud = CrudAux.build( TipoNormaJuridica, 'tipo_norma_juridica', list_field_names=['sigla', 'descricao', 'equivalente_lexml']) +VinculoNormaJuridicaCrud = CrudAux.build( + VinculoNormaJuridica, '', list_field_names=['sigla', 'descricao']) + + +class NormaRelacionadaCrud(MasterDetailCrud): + model = NormaRelacionada + parent_field = 'norma_principal' + help_path = '' + public = [RP_LIST, RP_DETAIL] + + class BaseMixin(MasterDetailCrud.BaseMixin): + list_field_names = ['norma_relacionada'] + + class CreateView(MasterDetailCrud.CreateView): + form_class = NormaRelacionadaForm + + class UpdateView(MasterDetailCrud.UpdateView): + form_class = NormaRelacionadaForm + + def get_initial(self): + self.initial['tipo'] = self.object.norma_relacionada.tipo.id + self.initial['numero'] = self.object.norma_relacionada.numero + self.initial['ano'] = self.object.norma_relacionada.ano + self.initial['ementa'] = self.object.norma_relacionada.ementa + return self.initial + + class DetailView(MasterDetailCrud.DetailView): + + @property + def layout_key(self): + return 'NormaRelacionadaDetail' class NormaPesquisaView(FilterView): @@ -129,3 +162,20 @@ class NormaCrud(Crud): self.initial['ano_materia'] = norma.materia.ano self.initial['numero_materia'] = norma.materia.numero return self.initial.copy() + + +def recuperar_norma(request): + tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo']) + numero = request.GET['numero'] + ano = request.GET['ano'] + + try: + norma = NormaJuridica.objects.get(tipo=tipo, + ano=ano, + numero=numero) + response = JsonResponse({'ementa': norma.ementa, + 'id': norma.id}) + except ObjectDoesNotExist: + response = JsonResponse({'ementa': '', 'id': 0}) + + return response diff --git a/sapl/templates/norma/layouts.yaml b/sapl/templates/norma/layouts.yaml index 99e14640c..52d16d587 100644 --- a/sapl/templates/norma/layouts.yaml +++ b/sapl/templates/norma/layouts.yaml @@ -49,3 +49,18 @@ LegislacaoCitadaDetail: - disposicoes parte livro titulo - capitulo secao subsecao artigo - paragrafo inciso alinea item + +VinculoNormaJuridica: + {% trans 'Tipo de Vínculo entre Normas Jurídicas' %}: + - sigla:2 descricao + +NormaRelacionada: + {% trans 'Norma Relacionada' %}: + - tipo numero ano + - tipo_vinculo + - ementa + +NormaRelacionadaDetail: + {% trans 'Norma Relacionada' %}: + - norma_relacionada + - tipo_vinculo diff --git a/sapl/templates/norma/normarelacionada_form.html b/sapl/templates/norma/normarelacionada_form.html new file mode 100644 index 000000000..300f7e3b3 --- /dev/null +++ b/sapl/templates/norma/normarelacionada_form.html @@ -0,0 +1,27 @@ +{% extends "crud/form.html" %} +{% load i18n %} +{% load crispy_forms_tags %} +{% load common_tags %} + +{% block extra_js %} + +{% endblock %} diff --git a/sapl/templates/norma/subnav.yaml b/sapl/templates/norma/subnav.yaml index be3cf3c0a..0599efdfb 100644 --- a/sapl/templates/norma/subnav.yaml +++ b/sapl/templates/norma/subnav.yaml @@ -2,6 +2,8 @@ - title: {% trans 'Início' %} url: normajuridica_detail +- title: {% trans 'Normas Relacionadas' %} + url: normarelacionada_list # Opção adicionada para chamar o TextoArticulado da norma. # para integração foram necessárias apenas criar a url norma_ta em urls.py diff --git a/sapl/templates/sistema.html b/sapl/templates/sistema.html index 9db02b417..6b9d1f5d4 100644 --- a/sapl/templates/sistema.html +++ b/sapl/templates/sistema.html @@ -70,7 +70,8 @@

Módulo Normas Jurídicas

- + +