diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 5d2d578eb..841e48f9c 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -36,6 +36,7 @@ kazoo==2.8.0 django-prometheus==2.2.0 asn1crypto==1.5.1 +XlsxWriter==3.2.0 git+https://github.com/interlegis/trml2pdf git+https://github.com/interlegis/django-admin-bootstrapped diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 5492ddfb6..d6742c00a 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -24,6 +24,7 @@ from django.shortcuts import render from django.template import loader from django.urls import reverse from django.utils import formats, timezone +from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, ListView, TemplateView, UpdateView from django.views.generic.base import RedirectView @@ -53,7 +54,7 @@ from sapl.utils import (autor_label, autor_modal, gerar_hash_arquivo, get_base_u get_client_ip, get_mime_type_from_file_extension, lista_anexados, mail_service_configured, montar_row_autor, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, get_tempfile_dir, - google_recaptcha_configured) + google_recaptcha_configured, MultiFormatOutputMixin) from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, AnexadaEmLoteFilterSet, AdicionarVariasAutoriasFilterSet, @@ -104,10 +105,10 @@ def proposicao_texto(request, pk): if proposicao.texto_original: if (not proposicao.data_recebimento and - not proposicao.autor.operadores.filter( - id=request.user.id + not proposicao.autor.operadores.filter( + id=request.user.id ).exists() - ): + ): logger.error("user=" + username + ". Usuário ({}) não tem permissão para acessar o texto original." .format(request.user.id)) messages.error(request, _( @@ -1261,11 +1262,11 @@ class HistoricoProposicaoView(PermissionRequiredMixin, ListView): paginate_by = 10 model = HistoricoProposicao permission_required = ( - 'materia.list_historicoproposicao', - 'materia.add_historicoproposicao', - 'materia.change_historicoproposicao', - 'materia.delete_historicoproposicao', - 'materia.detail_historicoproposicao', + 'materia.list_historicoproposicao', + 'materia.add_historicoproposicao', + 'materia.change_historicoproposicao', + 'materia.delete_historicoproposicao', + 'materia.detail_historicoproposicao', ) def get_queryset(self): @@ -2039,11 +2040,27 @@ class AcompanhamentoExcluirView(TemplateView): return HttpResponseRedirect(self.get_success_url()) -class MateriaLegislativaPesquisaView(FilterView): +class MateriaLegislativaPesquisaView(MultiFormatOutputMixin, FilterView): model = MateriaLegislativa filterset_class = MateriaLegislativaFilterSet paginate_by = 50 + fields_base_report = [ + 'id', 'ano', 'numero', 'tipo__sigla', 'tipo__descricao', 'autoria__autor__nome', 'texto_original', 'ementa' + ] + fields_report = { + 'csv': fields_base_report, + 'xlsx': fields_base_report, + 'json': fields_base_report, + } + + def hook_texto_original(self, obj): + url = self.request.build_absolute_uri('/')[:-1] + texto_original = obj.texto_original if not isinstance( + obj, dict) else obj["texto_original"] + + return f'{url}/{texto_original}' + def get_filterset_kwargs(self, filterset_class): super().get_filterset_kwargs(filterset_class) @@ -2099,8 +2116,9 @@ class MateriaLegislativaPesquisaView(FilterView): qs = qs.filter(materiaassunto__isnull=True) if 'o' in self.request.GET and not self.request.GET['o']: - args = ['-ano', 'tipo__sequencia_regimental', '-numero'] if BaseAppConfig.attr('ordenacao_pesquisa_materia') == 'R' else ['-ano', 'tipo__sigla', '-numero'] - + args = ['-ano', 'tipo__sequencia_regimental', '-numero'] if BaseAppConfig.attr( + 'ordenacao_pesquisa_materia') == 'R' else ['-ano', 'tipo__sigla', '-numero'] + qs = qs.order_by(*args) kwargs.update({ diff --git a/sapl/norma/views.py b/sapl/norma/views.py index fd12ebaf6..ce5c1a365 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -28,7 +28,7 @@ from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, make_pagination) from sapl.materia.models import Orgao from sapl.utils import show_results_filter_set, get_client_ip,\ - sapn_is_enabled + sapn_is_enabled, MultiFormatOutputMixin from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm, @@ -104,7 +104,7 @@ class PesquisarAssuntoNormaView(FilterView): if 'assunto' in self.request.META['QUERY_STRING'] or\ 'page' in self.request.META['QUERY_STRING']: - resultados = self.object_list + resultados = self.object_list else: resultados = [] @@ -147,11 +147,27 @@ class NormaRelacionadaCrud(MasterDetailCrud): layout_key = 'NormaRelacionadaDetail' -class NormaPesquisaView(FilterView): +class NormaPesquisaView(MultiFormatOutputMixin, FilterView): model = NormaJuridica filterset_class = NormaFilterSet paginate_by = 50 + fields_base_report = [ + 'id', 'ano', 'numero', 'tipo__sigla', 'tipo__descricao', 'texto_integral', 'ementa' + ] + fields_report = { + 'csv': fields_base_report, + 'xlsx': fields_base_report, + 'json': fields_base_report, + } + + def hook_texto_integral(self, obj): + url = self.request.build_absolute_uri('/')[:-1] + texto_integral = obj.texto_integral if not isinstance( + obj, dict) else obj["texto_integral"] + + return f'{url}/{texto_integral}' + def get_queryset(self): qs = super().get_queryset() diff --git a/sapl/templates/crud/format_options.html b/sapl/templates/crud/format_options.html new file mode 100644 index 000000000..eb3bdd18d --- /dev/null +++ b/sapl/templates/crud/format_options.html @@ -0,0 +1,10 @@ +{% load i18n %} + + +
diff --git a/sapl/templates/materia/materialegislativa_filter.html b/sapl/templates/materia/materialegislativa_filter.html index 3a51dc973..bf4a731b8 100644 --- a/sapl/templates/materia/materialegislativa_filter.html +++ b/sapl/templates/materia/materialegislativa_filter.html @@ -7,7 +7,15 @@ {% block actions %} -