From 059f5f16aada2305da3f2fc9b0ae3e69be6236c4 Mon Sep 17 00:00:00 2001 From: joaohortsenado <100957576+joaohortsenado@users.noreply.github.com> Date: Fri, 30 Jun 2023 20:29:32 -0300 Subject: [PATCH] feat: Adiciona funcionalidade de baixar lista de documentos acessorios de um documento administrativo (#3650) Co-authored-by: joao --- sapl/protocoloadm/urls.py | 5 +- sapl/protocoloadm/views.py | 75 ++++++++++++++++++- ...documentoacessorioadministrativo_list.html | 12 +++ 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 sapl/templates/protocoloadm/documentoacessorioadministrativo_list.html diff --git a/sapl/protocoloadm/urls.py b/sapl/protocoloadm/urls.py index ab3dcefeb..05c787897 100644 --- a/sapl/protocoloadm/urls.py +++ b/sapl/protocoloadm/urls.py @@ -27,7 +27,8 @@ from sapl.protocoloadm.views import (AcompanhamentoDocumentoView, TramitacaoEmLoteAdmView, apaga_protocolos_view, VinculoDocAdminMateriaCrud, - VinculoDocAdminMateriaEmLoteView) + VinculoDocAdminMateriaEmLoteView, + get_pdf_docacessorios) from .apps import AppConfig @@ -51,6 +52,8 @@ urlpatterns_documento_administrativo = [ name='anexado_em_lote'), url(r'^docadm/(?P\d+)/vinculo-em-lote', VinculoDocAdminMateriaEmLoteView.as_view(), name='vinculodocadminmateria_em_lote'), + url(r'^docadm/documentoacessorioadministrativo/pdf/(?P\d+)$', get_pdf_docacessorios, + name='merge_docacessorios') ] urlpatterns_protocolo = [ diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 2b1346f7b..38ffcf42a 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -1,9 +1,13 @@ +import os +import time from datetime import datetime import logging +from io import BytesIO from random import choice import re from string import ascii_letters, digits +from PyPDF4 import PdfFileMerger from braces.views import FormValidMessageMixin from django.conf import settings from django.contrib import messages @@ -16,7 +20,7 @@ from django.db import transaction from django.db.models import Max, Q from django.http import Http404, HttpResponse, JsonResponse from django.http.response import HttpResponseRedirect -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import render from django.urls import reverse from django.utils import timezone @@ -43,7 +47,7 @@ from sapl.relatorios.views import relatorio_doc_administrativos from sapl.utils import (create_barcode, get_base_url, get_client_ip, get_mime_type_from_file_extension, lista_anexados, show_results_filter_set, mail_service_configured, from_date_to_datetime_utc, - google_recaptcha_configured) + google_recaptcha_configured, get_tempfile_dir) from .forms import (AcompanhamentoDocumentoForm, AnexadoEmLoteFilterSet, AnexadoForm, AnularProtocoloAdmForm, compara_tramitacoes_doc, @@ -58,7 +62,7 @@ from .forms import (AcompanhamentoDocumentoForm, AnexadoEmLoteFilterSet, Anexado from .models import (Anexado, AcompanhamentoDocumento, DocumentoAcessorioAdministrativo, DocumentoAdministrativo, StatusTramitacaoAdministrativo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) - +from ..settings import MEDIA_ROOT TipoDocumentoAdministrativoCrud = CrudAux.build( TipoDocumentoAdministrativo, '') @@ -118,6 +122,71 @@ def doc_texto_integral(request, pk): raise Http404 +def get_pdf_docacessorios(request, pk): + documento_administrativo = get_object_or_404(DocumentoAdministrativo, pk=pk) + logger = logging.getLogger(__name__) + username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username + try: + external_name, data = create_pdf_docacessorios(documento_administrativo) + logger.info( + "user= {}. Gerou o pdf compilado de documento acessorios".format(username)) + except FileNotFoundError: + logger.error("user= {}.Não há arquivos cadastrados".format(username)) + msg = _('Não há arquivos cadastrados nesses documentos acessórios.') + messages.add_message(request, messages.ERROR, msg) + return redirect(reverse('sapl.materia:documentoacessorio_list', + kwargs={'pk': pk})) + except Exception as e: + logger.error("user= {}.Um erro inesperado ocorreu na criação do pdf de documentos acessorios: {}" + .format(username, str(e))) + msg = _('Um erro inesperado ocorreu. Entre em contato com o suporte do SAPL.') + messages.add_message(request, messages.ERROR, msg) + return redirect(reverse('sapl.materia:documentoacessorio_list', + kwargs={'pk': pk})) + + if not data: + msg = _('Não há nenhum documento acessório PDF cadastrado.') + messages.add_message(request, messages.ERROR, msg) + return redirect(reverse('sapl.materia:documentoacessorio_list', + kwargs={'pk': pk})) + + response = HttpResponse(data, content_type='application/pdf') + response['Content-Disposition'] = ('attachment; filename="%s"' + % external_name) + return response + + +def create_pdf_docacessorios(docadministrativo): + """ + Creates a unified in memory PDF file + """ + logger = logging.getLogger(__name__) + docs = docadministrativo.documentoacessorioadministrativo_set. \ + all().values_list('arquivo', flat=True) + if not docs: + return None, None + + docs_path = [os.path.join(MEDIA_ROOT, i) + for i in docs if i.lower().endswith('pdf')] + if not docs_path: + raise FileNotFoundError( + "Não há arquivos PDF cadastrados em documentos acessorios.") + logger.info("Gerando compilado PDF de documentos acessorios com {} documentos" + .format(docs_path)) + + merger = PdfFileMerger() + for f in docs_path: + merger.append(fileobj=f) + + data = BytesIO() + merger.write(data) + merger.close() + + external_name = "docadm_{}_{}_docacessorios.pdf".format( + docadministrativo.numero, docadministrativo.ano) + return external_name, data.getvalue() + + class AcompanhamentoConfirmarView(TemplateView): logger = logging.getLogger(__name__) diff --git a/sapl/templates/protocoloadm/documentoacessorioadministrativo_list.html b/sapl/templates/protocoloadm/documentoacessorioadministrativo_list.html new file mode 100644 index 000000000..6c68a934e --- /dev/null +++ b/sapl/templates/protocoloadm/documentoacessorioadministrativo_list.html @@ -0,0 +1,12 @@ +{% extends "crud/list.html" %} +{% load i18n %} +{% load common_tags %} + +{% block base_content %} + {{ block.super }} +
+ +
+{% endblock base_content%} \ No newline at end of file