Gerando arquivo em PDF e salvando no GED

Galera, tenho uma necessidade que é antes de entrar em uma atividade do processo, gerar um PDF(um certificado) e após gerar esse PDF anexar o mesmo a uma pasta do ECM.

A visão que tenho hoje é que tenho que executar as ações antes de chegar na atividade, através de um evento de processo.

Esses eventos do fluig, são interpretados em java? acho que isso dificultaria um pouco essa implementação.

Qual outra alternativa tenho? Usar widget(tenho pouca experiência com sua utilização).

Bom dia use o jspdf para gerar seu certificado.
Salve ele numa pasta depois via api fluig carregue ele para o ged.
você pode usar uma atividade de serviço ou os eventos de formulario.

1 curtida

Essa ação de salvar em uma pasta e carregar via para api para o GED é manual? Ou consigo passar o PDF gerado para essa API log após ele ser gerado? Se for manual, acho que inviabilizaria aqui.

Todas as vezes que perguntei sobre criar PDF sempre me recomendaram fazer no Front com uma biblioteca JS ou delegar pra um serviço externo (o que é bem triste). Vai um exemplo do que fiz utilizando um serviço externo (faço isso numa atividade Serviço):


/**
 * Cria o PDF do formulário
 *
 * @param {number} attempt Número da tentativa
 * @param {string} message Última mensagem de erro da atividade
 * @returns {boolean} True se executou
 * @throws {string} Exceção com a mensagem de erro
 */
function servicetask112(attempt, message) {
    var FOLDER_FORM_PDF = 5; // ID da pasta onde salvará o PDF
    var serviceHelper = ServiceManager.getService("ECMDocumentService").getBean();
    var service = serviceHelper
        .instantiate("com.totvs.technology.ecm.dm.ws.ECMDocumentServiceService")
        .getDocumentServicePort();

    if (service == null) {
        log.error("Erro ao carregar ECMDocumentService");
        throw "Erro ao gerar PDF do formulário";
    }

    try {
        var fileName = "nome-do-pdf-" + getValue("WKNumProces") + ".pdf";
        var attachment = serviceHelper.instantiate("com.totvs.technology.ecm.dm.ws.Attachment");
        attachment.setFileName(fileName);
        attachment.setFileSize(1);
        attachment.setAttach(true);
        attachment.setEditing(false);
        attachment.setPrincipal(true);

        // Faz o download do conteúdo do PDF usando o serviço externo
        attachment.setFilecontent(downloadProcessFormAsPdf());

        var attachmentArray = serviceHelper.instantiate("com.totvs.technology.ecm.dm.ws.AttachmentArray");
        attachmentArray.getItem().add(attachment);

        var fluigCredentials = getFluigWebServiceUser();

        var result = service.createSimpleDocument(
            fluigCredentials.username,
            fluigCredentials.password,
            1,
            FOLDER_FORM_PDF,
            "admin",
            fileName,
            attachmentArray
        );

        hAPI.attachDocument(result.getItem().get(0).getDocumentId());
    } catch (err) {
        log.error(err);
        throw "Erro ao gerar PDF do formulário";
    }

    return true;
}

/**
 * Efetua o download do formulário do processo em formato PDF
 *
 * O PDF é gerado por um serviço externo que lê os dados do formulário
 * através do WS do Fluig e então cria o PDF.
 *
 * @returns {byte[]} Array de Bytes (Java) para enviar ao WS do Fluig
 */
function downloadProcessFormAsPdf() {
    var urlDownload = new java.net.URL(FluigPdfURL + "/endpoint.php?"
        + "user=usuario"
        + "&password=senha"
        + "&processId=" + getValue("WKNumProces")
    );

    var is 			= urlDownload.openStream();
    var bytesBuffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 8192);
    var baos 		= new java.io.ByteArrayOutputStream();
    var len 		= 0;

    while ((len = is.read(bytesBuffer, 0, bytesBuffer.length)) != -1) {
        baos.write(bytesBuffer, 0, len);
    }

    var fileContents = baos.toByteArray();
    baos.close();
    return fileContents;
}

Se você fizer no front pode usar salvar numa pasta do GED também. Inclusive acho que já vi alguns códigos aqui no fórum ensinando a fazer o upload pelo front.

Essa atividade de serviço é executada internamente pelo fluig(Java), não sendo possível usar JS né!?
Minha necessidade é, após a movimentação(aprovação ou reprovação), gerar um certificado. Se eu conseguisse fazer isso com JS seria mais fácil, com essa abordagem ainda tem muitas coisas obscuras pra mim.

Se eu criasse uma forma de gerar um PDF custmizado no front , eu poderia chamá-la nessa atividade de serviço?

Aí você terá que fazer no JS do formulário né? Em algum momento quando submeter o formulário vai ter que executar fazer a leitura dos campos, verificar se foi aprovado ou não e só depois de enviar o arquivo vai permitir continuar o processo.

Sinceramente não sei como faria isso.

Mas fica um exemplo de como, em uma widget, eu crio um PDF no JS e envio para o GED do Fluig.

Basicamente faz o upload para /api/public/2.0/contentfiles/upload/ e então cria o documento com a /api/public/ecm/document/createDocument

@Bruno_Gasparetto Entendi. Sabe se tem como fazer isso sem ser necessariamente com widgets?

Desisti da ideia de tentar fazer isso como uma atividade de serviço ou algo relacionado a BPM. Vou tentar fazer essa ação no form mesmo. Não consigo vizualizar uma widget integrada a um form.

Fazer numa widget ou no form, sendo pelo front, não tem diferença. Você vai chamar os mesmos WS para enviar o arquivo e então criar o documento no GED.

Talvez você possa usar o evento beforeSendValidate do front do formulário pra verificar se houve a aprovação e então gerar o PDF no front.

1 curtida

@Bruno_Gasparetto como você referencia as bibliotecas blob-stream e pdfkit no HTML? Não estou conseguindo aqui.

@daniel_fmartins , são bibliotecas externas.

No meu caso eu criei uma widget só pra servir de repositório dentro do próprio Fluig e no HTML eu coloco a tag script apontando pro JS delas. Mas você pode pegar outras bibliotecas. Tem várias opções de bibliotecas JS para gerar PDF. Eu só dei o exemplo delas porque foi a que usaram aqui, hehe.

1 curtida

@Bruno_Gasparetto entendi.

No meu caso, eu tentei usar jsPDF para gerar o PDF, até aí ok.

Minhas dúvidas:
*1: Como linkar meu jsPDF com o body, você usa essa blob-stream. Eu consigo usar isso com jsPDF?
*2: Por que são utilizados dois posts para o upload? Um para /api/public/2.0/contentfiles/upload/?fileName=${fileName} e outro para
“/api/public/ecm/document/createDocument”

function generatePDF() {
    var doc = new jsPDF();
    var input = 'String qualquer';
    var fileName = 'documento.pdf';

    // Montagem do PDF
    doc.text(`a string ${input}`, 10, 10);

    fetch(
        `/api/public/2.0/contentfiles/upload/?fileName=${fileName}`,
        {
            method: "POST",
            headers: {
                "Content-Type": "application/octet-stream",
            },
            cache: "no-cache",
            *1:
            body: stream.toBlob("application/pdf")
        }
    ).then(function (response) {
        if (!response.ok) {
            throw "Erro ao enviar o arquivo.";
        }
    }).then(function () {

        // Cria o Documento no GED

        let document = {
            companyId: WCMAPI.organizationId,
            description: fileName,
            immutable: true,
            parentId: 1460, // ID da pasta onde salvar o PDF
            isPrivate: false,
            downloadEnabled: true,
            attachments: [{
                fileName: fileName,
            }],
        };

        return fetch(
            "/api/public/ecm/document/createDocument",
            {
                method: "POST",
                headers: {
                    "Content-Type": "application/json;charset=utf-8",
                },
                cache: "no-cache",
                body: JSON.stringify(document)
            }
        )
        .then(function (response) {
            if (!response.ok) {
                throw "Erro ao Salvar documento na Pasta Indicada";
            }
            return response.json();
        })
        .then(response => response.content);
    });
}

Se não me engano, pois mexi pouco com a jsPDF, seria algo assim:

body: doc.output('blob')

A biblioteca JS de PDF que utilizaram aqui é um pouco mais rústica/antiga, então precisa usar a blob-stream pra converter o stream num blob pra enviar no body do fetch.

É como o Fluig trabalha. Você primeiro deve enviar o arquivo para ele e então criar o documento no GED.

1 curtida

@Bruno_Gasparetto tem alguma forma de eu recuperar a WCMAPI.organizationId no form?

@daniel_fmartins , tem sim.

A WCMAPI é do contexto global do Fluig, porém o formulário é executado dentro de um iframe, então basta pegar a WCMAPI do parent: parent.WCMAPI

1 curtida

@Bruno_Gasparetto , sei nem como te agradecer rsrs.

Consegui aqui. Muito agradecido pela ajuda, valeu mesmo.

1 curtida

Este tópico foi fechado automaticamente 16 horas depois da úlima resposta. Novas respostas não são mais permitidas.