diff --git a/sapl/base/forms.py b/sapl/base/forms.py index ccd2c132b..ec69c50d9 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -23,6 +23,7 @@ from sapl.crispy_layout_mixin import (SaplFormLayout, form_actions, to_column, from sapl.audiencia.models import AudienciaPublica,TipoAudienciaPublica from sapl.comissoes.models import Reuniao, Comissao from sapl.materia.models import (MateriaLegislativa, UnidadeTramitacao, StatusTramitacao) +from sapl.norma.models import (NormaJuridica) from sapl.parlamentares.models import SessaoLegislativa from sapl.sessao.models import SessaoPlenaria from sapl.settings import MAX_IMAGE_UPLOAD_SIZE @@ -688,6 +689,83 @@ class RelatorioAtasFilterSet(django_filters.FilterSet): ) +class RelatorioNormasMesFilterSet(django_filters.FilterSet): + + ano = django_filters.ChoiceFilter(required=True, + label='Ano da Norma', + choices=RANGE_ANOS) + + filter_overrides = {models.DateField: { + 'filter_class': django_filters.DateFromToRangeFilter, + 'extra': lambda f: { + 'label': '%s (%s)' % (f.verbose_name, _('Ano')), + 'widget': RangeWidgetOverride} + }} + + + class Meta: + model = NormaJuridica + fields = ['ano'] + + def __init__(self, *args, **kwargs): + super(RelatorioNormasMesFilterSet, self).__init__( + *args, **kwargs) + + self.filters['ano'].label = 'Ano' + self.form.fields['ano'].required = True + + row1 = to_row([('ano', 12)]) + + self.form.helper = FormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Normas por mês do ano.'), + row1, form_actions(label='Pesquisar')) + ) + + @property + def qs(self): + parent = super(RelatorioNormasMesFilterSet, self).qs + return parent.distinct().order_by('data') + + +class RelatorioNormasVigenciaFilterSet(django_filters.FilterSet): + + ano = django_filters.ChoiceFilter(required=True, + label='Ano da Norma', + choices=RANGE_ANOS) + + vigencia = forms.ChoiceField( + label=_('Vigência'), + choices=[(True, "Vigente"), (False, "Não vigente")], + widget=forms.RadioSelect(), + required=True) + + + def __init__(self, *args, **kwargs): + super(RelatorioNormasVigenciaFilterSet, self).__init__( + *args, **kwargs) + + self.filters['ano'].label = 'Ano' + self.form.fields['ano'].required = True + self.form.fields['vigencia'] = self.vigencia + + row1 = to_row([('ano', 12)]) + row2 = to_row([('vigencia', 12)]) + + self.form.helper = FormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + Fieldset(_('Normas por vigência.'), + row1, row2, + form_actions(label='Pesquisar')) + ) + + @property + def qs(self): + return qs_override_django_filter(self) + + class RelatorioPresencaSessaoFilterSet(django_filters.FilterSet): filter_overrides = {models.DateField: { @@ -1061,7 +1139,8 @@ class ConfiguracoesAppForm(ModelForm): 'cronometro_consideracoes', 'mostrar_brasao_painel', 'receber_recibo_proposicao', - 'assinatura_ata'] + 'assinatura_ata', + 'estatisticas_acesso_normas'] def __init__(self, *args, **kwargs): super(ConfiguracoesAppForm, self).__init__(*args, **kwargs) diff --git a/sapl/base/migrations/0027_appconfig_relatorios_atos.py b/sapl/base/migrations/0027_appconfig_relatorios_atos.py new file mode 100644 index 000000000..afd3382e1 --- /dev/null +++ b/sapl/base/migrations/0027_appconfig_relatorios_atos.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2018-12-11 20:25 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0026_auto_20181126_1727'), + ] + + operations = [ + migrations.AddField( + model_name='appconfig', + name='relatorios_atos', + field=models.CharField(choices=[('S', 'Sim'), ('N', 'Não')], default='N', max_length=1, verbose_name='Relatórios de atos acessados'), + ), + ] diff --git a/sapl/base/migrations/0028_appconfig_estatisticas_acesso_normas.py b/sapl/base/migrations/0028_appconfig_estatisticas_acesso_normas.py new file mode 100644 index 000000000..7a4af06de --- /dev/null +++ b/sapl/base/migrations/0028_appconfig_estatisticas_acesso_normas.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2018-12-18 17:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0027_appconfig_relatorios_atos'), + ] + + operations = [ + migrations.AddField( + model_name='appconfig', + name='estatisticas_acesso_normas', + field=models.CharField(choices=[('S', 'Sim'), ('N', 'Não')], default='N', max_length=1, verbose_name='Estatísticas de acesso a normas'), + ), + ] diff --git a/sapl/base/migrations/0029_remove_appconfig_relatorios_atos.py b/sapl/base/migrations/0029_remove_appconfig_relatorios_atos.py new file mode 100644 index 000000000..fa06b23ac --- /dev/null +++ b/sapl/base/migrations/0029_remove_appconfig_relatorios_atos.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2018-12-18 18:40 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0028_appconfig_estatisticas_acesso_normas'), + ] + + operations = [ + migrations.RemoveField( + model_name='appconfig', + name='relatorios_atos', + ), + ] diff --git a/sapl/base/models.py b/sapl/base/models.py index 5caf8b2c0..343a8db9b 100644 --- a/sapl/base/models.py +++ b/sapl/base/models.py @@ -12,6 +12,9 @@ from sapl.utils import (LISTA_DE_UFS, YES_NO_CHOICES, TIPO_DOCUMENTO_ADMINISTRATIVO = (('O', _('Ostensiva')), ('R', _('Restritiva'))) +RELATORIO_ATOS_ACESSADOS = (('S', _('Sim')), + ('N', _('Não'))) + SEQUENCIA_NUMERACAO = (('A', _('Sequencial por ano')), ('L', _('Sequencial por legislatura')), ('U', _('Sequencial único'))) @@ -84,6 +87,11 @@ class AppConfig(models.Model): verbose_name=_('Visibilidade dos Documentos Administrativos'), choices=TIPO_DOCUMENTO_ADMINISTRATIVO, default='O') + estatisticas_acesso_normas = models.CharField( + max_length=1, + verbose_name=_('Estatísticas de acesso a normas'), + choices=RELATORIO_ATOS_ACESSADOS, default='N') + sequencia_numeracao = models.CharField( max_length=1, verbose_name=_('Sequência de numeração'), diff --git a/sapl/base/urls.py b/sapl/base/urls.py index 93a5b1cd3..ae4add258 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -23,7 +23,11 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, RelatorioMateriasPorAutorView, RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, - RelatorioReuniaoView, SaplSearchView) + RelatorioReuniaoView, SaplSearchView, + RelatorioNormasPublicadasMesView, + RelatorioNormasVigenciaView, + EstatisticasAcessoNormas, + RelatoriosListView) app_name = AppConfig.name @@ -84,10 +88,16 @@ urlpatterns = [ url(r'^sistema/app-config/', include(AppConfigCrud.get_urls())), # TODO mover estas telas para a app 'relatorios' - url(r'^sistema/relatorios/$', TemplateView.as_view( - template_name='base/relatorios_list.html'), name='relatorios_list'), + url(r'^sistema/relatorios/$', + RelatoriosListView.as_view(), name='relatorios_list'), url(r'^sistema/relatorios/materia-por-autor$', RelatorioMateriasPorAutorView.as_view(), name='materia_por_autor'), + url(r'^sistema/relatorios/relatorio-por-mes$', + RelatorioNormasPublicadasMesView.as_view(), name='normas_por_mes'), + url(r'^sistema/relatorios/relatorio-por-vigencia$', + RelatorioNormasVigenciaView.as_view(), name='normas_por_vigencia'), + url(r'^sistema/relatorios/estatisticas-acesso$', + EstatisticasAcessoNormas.as_view(), name='estatisticas_acesso'), url(r'^sistema/relatorios/materia-por-ano-autor-tipo$', RelatorioMateriasPorAnoAutorTipoView.as_view(), name='materia_por_ano_autor_tipo'), diff --git a/sapl/base/views.py b/sapl/base/views.py index ca122ce9f..599d6b05f 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -1,3 +1,5 @@ +import collections +import datetime import logging import os @@ -30,6 +32,7 @@ from sapl.comissoes.models import Reuniao, Comissao from sapl.crud.base import CrudAux, make_pagination from sapl.materia.models import (Autoria, MateriaLegislativa, TipoMateriaLegislativa, StatusTramitacao, UnidadeTramitacao) +from sapl.norma.models import (NormaJuridica, NormaEstatisticas) from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria, SessaoPlenariaPresenca) from sapl.utils import (parlamentares_ativos, @@ -45,7 +48,8 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, RelatorioMateriasTramitacaoilterSet, RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, - UsuarioEditForm) + UsuarioEditForm, RelatorioNormasMesFilterSet, + RelatorioNormasVigenciaFilterSet) from .models import AppConfig, CasaLegislativa @@ -276,6 +280,20 @@ class AutorCrud(CrudAux): return url_reverse +class RelatoriosListView(TemplateView): + template_name='base/relatorios_list.html' + + def get_context_data(self, **kwargs): + context = super(TemplateView, self).get_context_data(**kwargs) + estatisticas_acesso_normas = AppConfig.objects.first().estatisticas_acesso_normas + if estatisticas_acesso_normas == 'S': + context['estatisticas_acesso_normas'] = True + else: + context['estatisticas_acesso_normas'] = False + + return context + + class RelatorioAtasView(FilterView): model = SessaoPlenaria filterset_class = RelatorioAtasFilterSet @@ -744,6 +762,145 @@ class RelatorioMateriasPorAutorView(FilterView): return context +class RelatorioNormasPublicadasMesView(FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasMesFilterSet + template_name = 'base/RelatorioNormaMes_filter.html' + + def get_context_data(self, **kwargs): + context = super(RelatorioNormasPublicadasMesView, + self).get_context_data(**kwargs) + context['title'] = _('Normas') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + normas_mes = collections.OrderedDict() + meses = {1: 'Janeiro', 2: 'Fevereiro', 3:'Março', 4: 'Abril', 5: 'Maio', 6:'Junho', + 7: 'Julho', 8: 'Agosto', 9:'Setembro', 10:'Outubro', 11:'Novembro', 12:'Dezembro'} + for norma in context['object_list']: + if not meses[norma.data.month] in normas_mes: + normas_mes[meses[norma.data.month]] = [] + normas_mes[meses[norma.data.month]].append(norma) + + context['normas_mes'] = normas_mes + + quant_normas_mes = {} + for key in normas_mes.keys(): + quant_normas_mes[key] = len(normas_mes[key]) + + context['quant_normas_mes'] = quant_normas_mes + + return context + + +class RelatorioNormasVigenciaView(FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasVigenciaFilterSet + template_name = 'base/RelatorioNormasVigencia_filter.html' + + def get_filterset_kwargs(self, filterset_class): + super(RelatorioNormasVigenciaView, + self).get_filterset_kwargs(filterset_class) + + kwargs = {'data': self.request.GET or None} + qs = self.get_queryset().order_by('data').distinct() + if kwargs['data']: + ano = kwargs['data']['ano'] + vigencia = kwargs['data']['vigencia'] + qs = qs.filter(ano=ano) + if vigencia == 'True': + qs_dt_not_null = qs.filter(data_vigencia__isnull=True) + qs = (qs_dt_not_null | qs.filter(data_vigencia__gte=datetime.datetime.now().date())).distinct() + else: + qs = qs.filter(data_vigencia__lt=datetime.datetime.now().date()) + + kwargs.update({ + 'queryset': qs + }) + return kwargs + + + def get_context_data(self, **kwargs): + context = super(RelatorioNormasVigenciaView, + self).get_context_data(**kwargs) + context['title'] = _('Normas por vigência') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + normas_totais = NormaJuridica.objects.filter(ano=self.request.GET['ano']) + + context['quant_total'] = len(normas_totais) + if self.request.GET['vigencia'] == 'True': + context['vigencia'] = 'Vigente' + context['quant_vigente'] = len(context['object_list']) + context['quant_nao_vigente'] = context['quant_total'] - context['quant_vigente'] + else: + context['vigencia'] = 'Não vigente' + context['quant_nao_vigente'] = len(context['object_list']) + context['quant_vigente'] = context['quant_total'] - context['quant_nao_vigente'] + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + return context + + +class EstatisticasAcessoNormas(FilterView): + model = NormaJuridica + filterset_class = RelatorioNormasMesFilterSet + template_name = 'base/EstatisticasAcessoNormas_filter.html' + + def get_context_data(self, **kwargs): + context = super(EstatisticasAcessoNormas, + self).get_context_data(**kwargs) + context['title'] = _('Normas') + + # Verifica se os campos foram preenchidos + if not self.filterset.form.is_valid(): + return context + + qr = self.request.GET.copy() + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + context['show_results'] = show_results_filter_set(qr) + context['ano'] = self.request.GET['ano'] + + normas_mes = collections.OrderedDict() + meses = {1: 'Janeiro', 2: 'Fevereiro', 3:'Março', 4: 'Abril', 5: 'Maio', 6:'Junho', + 7: 'Julho', 8: 'Agosto', 9:'Setembro', 10:'Outubro', 11:'Novembro', 12:'Dezembro'} + for norma in context['object_list']: + if not meses[norma.data.month] in normas_mes: + normas_mes[meses[norma.data.month]] = [] + norma_est = [norma, len(NormaEstatisticas.objects.filter(norma=norma))] + normas_mes[meses[norma.data.month]].append(norma_est) + + meses_sem_acesso = [] + # Ordena por acesso e limita em 5 + for n in normas_mes: + sorted_by_value = sorted(normas_mes[n], key=lambda kv: kv[1], reverse=True) + normas_mes[n] = sorted_by_value[0:5] + if all(v[1]==0 for v in normas_mes[n]): + meses_sem_acesso.append(n) + + context['normas_mes'] = normas_mes + context['meses_sem_acesso'] = meses_sem_acesso + + return context + + class ListarUsuarioView(PermissionRequiredMixin, ListView): model = get_user_model() template_name = 'auth/user_list.html' diff --git a/sapl/norma/migrations/0017_normaestatisticas.py b/sapl/norma/migrations/0017_normaestatisticas.py new file mode 100644 index 000000000..03009eeec --- /dev/null +++ b/sapl/norma/migrations/0017_normaestatisticas.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.8 on 2018-12-17 18:44 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('norma', '0016_tipovinculonormajuridica_revoga_integramente'), + ] + + operations = [ + migrations.CreateModel( + name='NormaEstatisticas', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('usuario', models.CharField(max_length=50)), + ('horario_acesso', models.DateTimeField(auto_now=True, null=True)), + ('norma', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.NormaJuridica')), + ], + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index 6565304ee..80075f113 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -191,6 +191,18 @@ class NormaJuridica(models.Model): update_fields=update_fields) +class NormaEstatisticas(models.Model): + usuario = models.CharField(max_length=50) + horario_acesso = models.DateTimeField( + blank=True, null=True, + auto_now=True) + norma = models.ForeignKey(NormaJuridica, + on_delete=models.CASCADE) + def __str__(self): + return _('Usuário: %(usuario)s, Norma: %(norma)s') % { + 'usuario': self.usuario, 'norma': self.norma} + + @reversion.register() class AutoriaNorma(models.Model): autor = models.ForeignKey(Autor, diff --git a/sapl/norma/tests/test_norma.py b/sapl/norma/tests/test_norma.py index 6603d7167..5c2a76a6a 100644 --- a/sapl/norma/tests/test_norma.py +++ b/sapl/norma/tests/test_norma.py @@ -7,6 +7,7 @@ from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa from sapl.norma.forms import (NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm) from sapl.norma.models import NormaJuridica, TipoNormaJuridica +from sapl.base.models import AppConfig @pytest.mark.django_db(transaction=False) @@ -15,6 +16,7 @@ def test_incluir_norma_submit(admin_client): tipo = mommy.make(TipoNormaJuridica, sigla='T', descricao='Teste') + config = mommy.make(AppConfig) # Testa POST response = admin_client.post(reverse('sapl.norma:normajuridica_create'), diff --git a/sapl/norma/views.py b/sapl/norma/views.py index f2dfb6f2e..f7800c42f 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -1,6 +1,8 @@ -import re import logging +import re +import sapl +import weasyprint from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import ObjectDoesNotExist @@ -13,8 +15,6 @@ from django.views.generic import TemplateView, UpdateView from django.views.generic.base import RedirectView from django.views.generic.edit import FormView from django_filters.views import FilterView -import weasyprint -import sapl from sapl.base.models import AppConfig from sapl.compilacao.views import IntegracaoTaView from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, @@ -24,7 +24,7 @@ from sapl.utils import show_results_filter_set from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm, AutoriaNormaForm) from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelacionada, - TipoNormaJuridica, TipoVinculoNormaJuridica, AutoriaNorma) + TipoNormaJuridica, TipoVinculoNormaJuridica, AutoriaNorma, NormaEstatisticas) # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') @@ -190,7 +190,13 @@ class NormaCrud(Crud): return reverse('%s:%s' % (namespace, 'norma_pesquisa')) class DetailView(Crud.DetailView): - pass + def get(self, request, *args, **kwargs): + estatisticas_acesso_normas = AppConfig.objects.first().estatisticas_acesso_normas + if estatisticas_acesso_normas == 'S': + NormaEstatisticas.objects.create(usuario=str(self.request.user), + norma_id=kwargs['pk']) + return super().get(request, *args, **kwargs) + class DeleteView(Crud.DeleteView): @@ -225,7 +231,7 @@ class NormaCrud(Crud): class ListView(Crud.ListView, RedirectView): def get_redirect_url(self, *args, **kwargs): - namespace = self.model._meta.app_config.name + namespace = self.model._meta.app_config.name return reverse('%s:%s' % (namespace, 'norma_pesquisa')) def get(self, request, *args, **kwargs): diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index aa691da5e..f9b63fd4b 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -139,6 +139,7 @@ rules_group_norma = { (norma.NormaRelacionada, __base__), (norma.AnexoNormaJuridica, __base__), (norma.AutoriaNorma, __base__), + (norma.NormaEstatisticas, __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 @@ -242,6 +243,7 @@ rules_group_geral = { (norma.AssuntoNorma, __base__), (norma.TipoNormaJuridica, __base__), (norma.TipoVinculoNormaJuridica, __base__), + (norma.NormaEstatisticas, __base__), (parlamentares.Legislatura, __base__), (parlamentares.SessaoLegislativa, __base__), diff --git a/sapl/templates/base/EstatisticasAcessoNormas_filter.html b/sapl/templates/base/EstatisticasAcessoNormas_filter.html new file mode 100644 index 000000000..a8246e22d --- /dev/null +++ b/sapl/templates/base/EstatisticasAcessoNormas_filter.html @@ -0,0 +1,64 @@ +{% extends "crud/list.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block base_content %} + {% if not show_results %} + {% crispy filter.form %} + {% endif %} + {% if show_results %} +
+ {% trans 'Fazer nova pesquisa' %} +
+



+ PARÂMETROS DE PESQUISA:
+  Ano: {{ ano }}
+
+ {% if normas_mes|length == 0 %} +
+

{% trans 'Não foi encontrada nenhuma norma com os parâmetros buscados.'%}

+ {% elif normas_mes|length == meses_sem_acesso|length %} +
+

{% trans 'Nenhuma norma teve acesso neste ano.'%}

+ {% else %} + {% for mes, normas in normas_mes.items %} +
+ + + + + + +

Mês: {{ mes }}

+ {% if not mes in meses_sem_acesso %} + + + + + + + + + + {% for n in normas %} + {% if n.1 > 0 %} + + + + + + {% endif %} + {% endfor %} + +
NormaEmentaAcessos
+ {{n.0.tipo.descricao}} - {{n.0.tipo.sigla}} {{n.0.numero}}/{{n.0.ano}} + {{n.0.ementa}}
{{n.0.observacao}}
{{n.1}}
+ {% else %} +

{% trans 'Nenhuma norma deste mês teve acessos.'%}

+

+ {% endif %} +
+ {% endfor %} + {% endif %} + {% endif %} +{% endblock base_content %} diff --git a/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html b/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html index cca46d3ad..1151cd094 100644 --- a/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html +++ b/sapl/templates/base/RelatorioHistoricoTramitacao_filter.html @@ -30,7 +30,7 @@ {{materia.tipo.descricao}} - {{materia.tipo.sigla}} {{materia.numero}}/{{materia.ano}} - {{materia.ementa}} + {{materia.ementa}}
{{materia.observacao}} {% endfor %} diff --git a/sapl/templates/base/RelatorioMateriasPorAutor_filter.html b/sapl/templates/base/RelatorioMateriasPorAutor_filter.html index 6a8ed41a8..35e9aa50c 100644 --- a/sapl/templates/base/RelatorioMateriasPorAutor_filter.html +++ b/sapl/templates/base/RelatorioMateriasPorAutor_filter.html @@ -51,7 +51,7 @@ {{materia.tipo.sigla}} {{materia.numero}}/{{materia.ano}} - {% autoescape off %}{{materia.ementa}}{% endautoescape %} + {% autoescape off %}{{materia.ementa}}
{{materia.observacao}}{% endautoescape %} {% if materia.autoria_set.first != materia.autoria_set.last %} {% for autor in materia.autoria_set.all %} diff --git a/sapl/templates/base/RelatorioNormaMes_filter.html b/sapl/templates/base/RelatorioNormaMes_filter.html new file mode 100644 index 000000000..d4f8d5b30 --- /dev/null +++ b/sapl/templates/base/RelatorioNormaMes_filter.html @@ -0,0 +1,67 @@ +{% extends "crud/list.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block base_content %} + {% if not show_results %} + {% crispy filter.form %} + {% endif %} + + {% if show_results %} +
+ {% trans 'Fazer nova pesquisa' %} +
+



+ PARÂMETROS DE PESQUISA:
+  Ano: {{ ano }}
+
+ {% if normas_mes|length == 0 %} +
+

{% trans 'Não foi encontrada nenhuma norma com os parâmetros buscados.'%}

+ {% endif %} + {% for mes, normas in normas_mes.items %} +
+ + + + + + +

Mês: {{ mes }}

+ + + + {% for k, v in quant_normas_mes.items %} + {% if k == mes %} + {% if v > 1 %} + + {% else %} + + {% endif %} + {% endif %} + {% endfor %} + + +
Quantidade encontrada no mês: {{ v }} normas.Quantidade encontrada no mês: 1 norma.
+ + + + + + + + + {% for n in normas %} + + + + + {% endfor %} + +
NormaEmenta
+ {{n.tipo.descricao}} - {{n.tipo.sigla}} {{n.numero}}/{{n.ano}} + {{n.ementa}}
{{n.observacao}}
+
+ {% endfor %} + {% endif %} +{% endblock base_content %} diff --git a/sapl/templates/base/RelatorioNormasVigencia_filter.html b/sapl/templates/base/RelatorioNormasVigencia_filter.html new file mode 100644 index 000000000..6412b5b20 --- /dev/null +++ b/sapl/templates/base/RelatorioNormasVigencia_filter.html @@ -0,0 +1,57 @@ +{% extends "crud/list.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block base_content %} + {% if not show_results %} + {% crispy filter.form %} + {% endif %} + + {% if show_results %} +
+ {% trans 'Fazer nova pesquisa' %} +
+



+ PARÂMETROS DE PESQUISA:
+  Ano: {{ ano }}
+  Vigência: {{ vigencia }}
+ {% if object_list %} +
+ {% if object_list|length > 1 %} +

Foram encontradas {{object_list|length}} normas.

+ {% else %} +

Foi encontrada 1 norma.

+ {% endif %} +
+ + + + + + + + + {% for norma in object_list %} + + + + + {% endfor %} + +
NormaEmenta
+ {{norma.tipo.descricao}} - {{norma.tipo.sigla}} {{norma.numero}}/{{norma.ano}} + {{norma.ementa}}
{{norma.observacao}}
+ {% else %} + + + + + + +
Não foi encontrada nenhuma norma com os parâmetros buscados.
+ {% endif %} +
+

Estatísticas das normas do ano:


+

{{quant_vigente}} vigente(s) / {{quant_nao_vigente}} não vigente(s)

+ {% endif %} +{% endblock base_content %} diff --git a/sapl/templates/base/layouts.yaml b/sapl/templates/base/layouts.yaml index ef1e53d2a..4f6bbd45d 100644 --- a/sapl/templates/base/layouts.yaml +++ b/sapl/templates/base/layouts.yaml @@ -23,6 +23,9 @@ AppConfig: {% trans 'Textos Articulados' %}: - texto_articulado_proposicao texto_articulado_materia texto_articulado_norma + {% trans 'Estatísticas de acesso' %}: + - estatisticas_acesso_normas + {% trans 'Assinaturas' %}: - assinatura_ata diff --git a/sapl/templates/base/relatorios_list.html b/sapl/templates/base/relatorios_list.html index 78192855a..87f8933be 100644 --- a/sapl/templates/base/relatorios_list.html +++ b/sapl/templates/base/relatorios_list.html @@ -48,6 +48,20 @@ Audiência Pública Audiência Pública com o tipo. + + Normas por mês + Normas publicadas por mês. + + + Normas por vigência + Normas vigentes ou não vigentes. + + {% if estatisticas_acesso_normas %} + + Estatísticas de acesso de Normas. + Normas por acesso. + + {% endif %}