diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 3d906e446..71f63e130 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -44,6 +44,15 @@ def split(value, arg): return value.split(arg) +@register.filter +def to_str(arg): + return str(arg) + +@register.filter +def get_last_item_from_list(list,arg): + return list[arg] + + @register.filter def sort_by_keys(value, key): transformed = [] diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 610895e09..92fadde55 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -14,7 +14,7 @@ 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, NormaRelacionada, +from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, TipoNormaJuridica) @@ -120,6 +120,7 @@ class NormaJuridicaForm(ModelForm): 'assuntos'] widgets = {'assuntos': widgets.CheckboxSelectMultiple} + def clean(self): cleaned_data = super(NormaJuridicaForm, self).clean() @@ -175,9 +176,41 @@ class NormaJuridicaForm(ModelForm): norma.timestamp = timezone.now() norma.materia = self.cleaned_data['materia'] norma = super(NormaJuridicaForm, self).save(commit=True) + return norma +class AnexoNormaJuridicaForm(ModelForm): + class Meta: + model = AnexoNormaJuridica + fields = ['norma', 'anexo_arquivo'] + widgets = { + 'norma': forms.HiddenInput(), + } + + def clean(self): + cleaned_data = super(AnexoNormaJuridicaForm, self).clean() + if not self.is_valid(): + return cleaned_data + anexo_arquivo = self.cleaned_data.get('anexo_arquivo', False) + if anexo_arquivo: + if anexo_arquivo.size > MAX_DOC_UPLOAD_SIZE: + max_size = str(MAX_DOC_UPLOAD_SIZE / (1024 * 1024)) + raise ValidationError( + "Arquivo muito grande. ( > {0}MB )".format(max_size)) + return cleaned_data + + def save(self, commit=False): + anexo = self.instance + anexo.ano = self.cleaned_data['norma'].ano + anexo = super(AnexoNormaJuridicaForm, self).save(commit=True) + anexo.norma = self.cleaned_data['norma'] + anexo.anexo_arquivo = self.cleaned_data['anexo_arquivo'] + anexo.save() + return anexo + + + class NormaRelacionadaForm(ModelForm): tipo = forms.ModelChoiceField( diff --git a/sapl/norma/migrations/0012_anexonormajuridica.py b/sapl/norma/migrations/0012_anexonormajuridica.py new file mode 100644 index 000000000..2ba9ebdca --- /dev/null +++ b/sapl/norma/migrations/0012_anexonormajuridica.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-08-06 19:48 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import sapl.norma.models +import sapl.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0011_auto_20180220_1859'), + ] + + operations = [ + migrations.CreateModel( + name='AnexoNormaJuridica', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('anexo_arquivo', models.FileField(blank=True, null=True, upload_to=sapl.norma.models.norma_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Arquivo Anexo')), + ('ano', models.PositiveSmallIntegerField(choices=[(2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano')), + ('norma', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='norma', to='norma.NormaJuridica', verbose_name='Norma Juridica')), + ], + options={ + 'verbose_name_plural': 'Anexos da Norma Juridica', + 'verbose_name': 'Anexo da Norma Juridica', + }, + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index b045ea1f9..54f47e865 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -141,6 +141,12 @@ class NormaJuridica(models.Model): norma_relacionada=self.id) return (principais, relacionadas) + def get_anexos_norma_juridica(self): + anexos = AnexoNormaJuridica.objects.filter( + norma=self.id) + return anexos + + def __str__(self): return _('%(tipo)s nº %(numero)s de %(data)s') % { 'tipo': self.tipo, @@ -252,3 +258,28 @@ class NormaRelacionada(models.Model): ' - Relacionada: %(norma_relacionada)s') % { 'norma_principal': self.norma_principal, 'norma_relacionada': self.norma_relacionada} + + +@reversion.register() +class AnexoNormaJuridica(models.Model): + norma = models.ForeignKey( + NormaJuridica, + related_name='norma', + on_delete=models.PROTECT, + verbose_name=_('Norma Juridica')) + anexo_arquivo = models.FileField( + blank=True, + null=True, + upload_to=norma_upload_path, + verbose_name=_('Arquivo Anexo'), + validators=[restringe_tipos_de_arquivo_txt]) + ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'), + choices=RANGE_ANOS) + + class Meta: + verbose_name = _('Anexo da Norma Juridica') + verbose_name_plural = _('Anexos da Norma Juridica') + + def __str__(self): + return _('Anexo: %(anexo)s da norma %(norma)s') % { + 'anexo': self.anexo_arquivo, 'norma': self.norma} diff --git a/sapl/norma/urls.py b/sapl/norma/urls.py index 93081c4fc..d943f71e8 100644 --- a/sapl/norma/urls.py +++ b/sapl/norma/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import include, url -from sapl.norma.views import (AssuntoNormaCrud, NormaCrud, NormaPesquisaView, +from sapl.norma.views import (AnexoNormaJuridicaCrud,AssuntoNormaCrud, NormaCrud, NormaPesquisaView, NormaRelacionadaCrud, NormaTaView, TipoNormaCrud, TipoVinculoNormaJuridicaCrud, recuperar_norma, recuperar_numero_norma) @@ -12,11 +12,11 @@ app_name = AppConfig.name urlpatterns = [ url(r'^norma/', include(NormaCrud.get_urls() + - NormaRelacionadaCrud.get_urls())), + NormaRelacionadaCrud.get_urls() + + AnexoNormaJuridicaCrud.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( diff --git a/sapl/norma/views.py b/sapl/norma/views.py index f5fecdefc..de3efa8ef 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -19,9 +19,9 @@ from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, make_pagination) from sapl.utils import show_results_filter_set -from .forms import (NormaFilterSet, NormaJuridicaForm, +from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm) -from .models import (AssuntoNorma, NormaJuridica, NormaRelacionada, +from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, TipoNormaJuridica, TipoVinculoNormaJuridica) # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') @@ -98,6 +98,38 @@ class NormaPesquisaView(FilterView): return context +class AnexoNormaJuridicaCrud(MasterDetailCrud): + model = AnexoNormaJuridica + parent_field = 'norma' + help_topic = 'anexonormajuridica' + public = [RP_LIST, RP_DETAIL] + + class BaseMixin(MasterDetailCrud.BaseMixin): + list_field_names = ['id','anexo_arquivo'] + + class CreateView(MasterDetailCrud.CreateView): + form_class = AnexoNormaJuridicaForm + layout_key = 'AnexoNormaJuridica' + def get_initial(self): + norma_id = str(self.request).split("/")[-3] + self.initial = super(MasterDetailCrud.CreateView, self).get_initial() + self.initial['norma'] = NormaJuridica.objects.get(id=norma_id) + return self.initial + + class UpdateView(MasterDetailCrud.UpdateView): + form_class = AnexoNormaJuridicaForm + layout_key = 'AnexoNormaJuridica' + def get_initial(self): + initial = super(UpdateView, self).get_initial() + initial['norma'] = self.object.norma + initial['anexo_arquivo'] = self.object.anexo_arquivo + initial['ano'] = self.object.ano + return initial + + class DetailView(MasterDetailCrud.DetailView): + form_class = AnexoNormaJuridicaForm + layout_key = 'AnexoNormaJuridica' + class NormaTaView(IntegracaoTaView): model = NormaJuridica diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index f98da8c0e..bba114149 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -135,6 +135,7 @@ rules_group_norma = { 'rules': [ (norma.NormaJuridica, __base__), (norma.NormaRelacionada, __base__), + (norma.AnexoNormaJuridica, __base__), # Publicacao está com permissão apenas para norma e não para matéria # e proposições apenas por análise do contexto, não é uma limitação diff --git a/sapl/templates/norma/layouts.yaml b/sapl/templates/norma/layouts.yaml index a06b80b2b..591faed38 100644 --- a/sapl/templates/norma/layouts.yaml +++ b/sapl/templates/norma/layouts.yaml @@ -24,6 +24,11 @@ NormaJuridica: - observacao - assuntos +AnexoNormaJuridica: + {% trans 'Adicionar Anexos à Norma Jurídica' %}: + - anexo_arquivo + - norma + NormaJuridicaCreate: {% trans 'Identificação Básica' %}: - tipo ano numero diff --git a/sapl/templates/norma/normajuridica_detail.html b/sapl/templates/norma/normajuridica_detail.html index 6dcd3d592..24df5476a 100644 --- a/sapl/templates/norma/normajuridica_detail.html +++ b/sapl/templates/norma/normajuridica_detail.html @@ -58,6 +58,22 @@ {% endfor %} {% endif %} + +
+
+
+  

Anexos Norma Jurídica

+ {% if object.get_anexos_norma_juridica|length > 0 %} + {% for p in object.get_anexos_norma_juridica %} + + {% endfor %} + {% endif %} +
+
{% endblock detail_content %} diff --git a/sapl/templates/norma/subnav.yaml b/sapl/templates/norma/subnav.yaml index a89326fd7..9358787ff 100644 --- a/sapl/templates/norma/subnav.yaml +++ b/sapl/templates/norma/subnav.yaml @@ -5,6 +5,8 @@ - title: {% trans 'Alterações em Outras Normas' %} url: normarelacionada_list check_permission: norma.list_normarelacionada +- title: {% trans 'Anexos da Norma' %} + url: anexonormajuridica_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