Automatizar a gestão documental com o Power Automate e o SharePoint. Como criar um arquivo de documentos por ano e entidade
O cenário é comum a muitas empresas: receber centenas ou milhares de documentos por ano dos seus fornecedores e pretendem automatizar o arquivo de acordo com as suas regras de negócio. Tal facilita a organização, a auditoria, a pesquisa e o controlo interno. Neste artigo, vamos ver como criar uma solução de arquivo automatizado com o Power Automate e o SharePoint.
O primeiro passo consiste em criar um repositório, seja um document folder do SharePoint, onde serão armazenadas as faturas dos fornecedores. Esta etapa do processo poderá ser automatizada de diversas formas:
- através da criação de um email onde todos os anexos serão recolhidos e arquivados numa pasta de entrada,
- através de uma app, em que alguém faz upload desses documentos à medida que eles chegam,
- através de um outro fluxo de automação que procede ao armazenamento dos documentos, no momento em que são classificados como aprovados,
- há muitas oportunidades de automatizar o inbound documental.
Na verdade, este processo pode ser bastante mais longo do que estamos a descrever neste post, mas vamos começar por criar uma lista no SharePoint e considerá-la como o nosso ponto de partida:
Vamos assumir que os documentos chegam a esta lista, provenientes de todos os fornecedores da empresa e que o nosso objetivo é organizá-los primeiro por ano (assumindo o ano como a data de chegada dos documentos) e, dentro de cada ano, por fornecedor.
Pretende-se também renomear cada um dos documentos para a seguinte nomenclatura:
- número do documento
- underscore
- nome do fornecedor
Os documentos ficarão guardados na lista e nela vamos acrescentar colunas com a meta data necessária para a automação do processo. Teríamos, por exemplo:
Num cenário real, teríamos muitas outras colunas com mais informação relevante para a classificação dos documentos. Os anexos ficam guardados na própria lista e podem ser vistos se abrirmos um dos items. Por exemplo, o documento número 1235, poderia ser acedido a partir do painel do lado direito:
O fluxo de automação será ativado no momento em que for acrescentado um item a esta lista. Portanto, no Power Automate, o trigger será: “When an item is created”:
Segue-se a primeira ação que poderá ser identificar o país a que a fatura diz respeito. Para isso, vamos começar por acrescentar uma ação com a inicialização de uma variável, seja a variável “Country”, com o tipo “String”, isto é, uma variável de texto:
A nossa lista contém apenas dois países: Portugal e Espanha, mas vamos desenhar o fluxo de automação de modo a permitir a contemplação de mais países. Para isso, vamos acrescentar uma ação do tipo Switch, que vai analisar o campo País da lista e definir a variável Country para a respetiva sigla. Se o país não for considerado na ação Switch, a variável poderá ficar vazia e o flow pode terminar, ou então, ser definida para “Outros”, ficando as faturas guardadas num diretório com o mesmo nome.
Esta ação poderá ser útil para lidar com situações em que o nome do país está incorreto ou quando a empresa tem um fornecedor proveniente de um país novo que ainda não foi classificado. Posteriormente, poderia ser criado um novo fluxo de automação com uma notificação via email para a pessoa responsável tomar conhecimento e agir perante este tipo de casos.
Primeiro passo – recolher os dados do documento
Como podemos ver na imagem seguinte, a ação Switch ficará “embrulhada” num loop do tipo “Apply to each” porque vai ser executada de cada vez que um (ou mais) items são criados na lista do SharePoint:
A próxima variável a inicializar será o ano e aqui podemos optar por considerar o ano referente à data do documento ou ao ano em que o documento foi carregado na lista, em função da regra de negócio determinada pela empresa.
Vamos assumir a segunda opção e acrescentar uma nova ação: “Initialize variable”:
A expressão que utilizamos para inicializar esta variável é:
formatDateTime(utcNow(), 'yyyy')
Basicamente, esta função cria um “timestamp” do momento atual (em que o flow é executado) e converte-o no formato ano. Por exemplo, hoje são 20 de novembro de 2023 e a variável será definida para 2023, sob a forma de texto.
É este texto que nos interessa para criar a estrutura do arquivo de faturas mais à frente na definição deste fluxo de automação.
Segue-se a variável com o nome do fornecedor, mas neste passo vamos ter algum cuidado. Vamos assumir que poderá existir alguma ambiguidade nos nomes dos fornecedores e que o nome do mesmo fornecedor poderá surgir várias vezes de formas diferentes. Por exemplo, em maiúsculas e minúsculas, com acentuação, e sem acentuação, etc.
Por isso, vamos começar por inicializar uma nova variável “NomeFornecedor” e defini-la com o valor que vem da lista SharePoint, mas convertido em minúsculas e sem pontos:
A expressão contida na última ação “Set variable” é a seguinte:
replace(toLower(items('Apply_to_each_2')?['Fornecedor']), '.', '')
Vamos testar o fluxo com a entrada de uma nova fatura:
Analisando a execução do fluxo, verificamos que as variáveis País, Ano e NomeFornecedor foram corretamente definidas:
Como podemos verificar na imagem acima, o nome do fornecedor está agora limpo de pontuação e todo em minúsculas. Poderíamos ir um pouco mais longe e converter este texto em “camel case”, isto é, converter cada palavra em maiúscula e unir todas as palavras numa só.
Para tal, vamos inicializar a variável “FornecedorCamelCase” como string vazia:
Na ação seguinte, vamos converter o nome do fornecedor num array, usando a função split para separar o nome do fornecedor como está em espaços. A expressão é a seguinte:
split(variables('NomeFornecedor'), ' ')
O nome do fornecedor agora está dividido em quatro palavras. Por isso, vamos mais uma vez embrulhar o resultado da expressão acima num loop “Apply to each” para tratar cada palavra separadamente.
A cada palavra, vamos aplicar uma ação “Compose” que vai realizar um teste lógico. Se a dimensão da palavra for de apenas um caracter, a mesma será convertida em maiúscula. Senão, apenas o primeiro caracter da palavra será convertido em maiúscula. A expressão será:
if
(
equals(length(item()),1),
toupper(item()),
concat(first(toupper(item())),toLower(substring(item(),1,sub(length(item()),1))))
)
Finalmente, cada palavra convertida em maiúscula é anexada à variável “FornecedorCamelCase” de modo a gerar-se uma palavra só.
Podemos visualizar o resultado até ao momento no designer:
E testando o fluxo até ao momento com os mesmos dados, veríamos o resultado:
Como podemos visualizar acima, o loop Apply to each contém quatro voltas, uma para cada palavra, e cada uma delas capitalizou a primeira letra.
Segundo passo – enviar o documento para o document folder do SharePoint
Chegados a este ponto, resta-nos enviar o documento da lista para a biblioteca de documentos (document folder) do SharePoint. No entanto, queremos fazê-lo com a estrutura e a nomenclatura corretas.
A primeira coisa que nos interessa é saber se a pasta na qual pretendemos arquivar o documento já existe. Se não existir, teremos de a criar. Para isso, vamos acrescentar uma ação “Send HTTP request to SharePoint”. A API do SharePoint vai devolver-nos True ou False conforme os casos.
Assim, a próxima ação seria:
No campo “Site Address” colocamos o site SharePoint que criámos para este projeto.
O método selecionado é o GET, pois estamos apenas a obter uma resposta do servidor.
E o campo “Uri” é o mais complexo e nele vamos usar uma parte fixa de texto e uma parte variável com a lógica da estrutura de pastas que pretendemos criar. Dentro da biblioteca de documentos “Automação Arquivo Faturas” vamos testar se existe um diretório com a estrutura “/Country/Ano/FornecedorCamelCase.
Testando mais uma vez este fluxo com os mesmos dados de entrada temos:
Como seria de esperar, o resultado é falso, pois ainda não criámos a pasta que nos interessa. É o que faremos de seguida: acrescentar uma condição para avaliar a existência do diretório e as ações para a criação da pasta, caso não exista ainda:
Correndo o fluxo, verificamos que o diretório é criado de acordo com a estrutura pretendida. Na nossa biblioteca de documentos “Automação Arquivo Faturas”, foram criados os diretórios “PT”, “2023” e “TwisterGymnasticsAcademyInc”:
Como seria de esperar, se executarmos o fluxo novamente com os mesmos dados de entrada, nada irá acontecer, pois o diretório já existe. É no entanto importante referir que, mesmo que o resultado da condição lógica acima não resultar numa ação direta, o fluxo continua, pois o resto do processo ainda não ocorreu: ainda temos de arquivar o documento nesta pasta. Assim, vamos acrescentar uma nova ação ao fluxo, para obter o anexo da lista do SharePoint.
Para tal, precisamos de duas ações:
- uma primeira, para obter os anexos do item da lista que dispara o fluxo (cada item de uma lista SharePoint pode conter mais do que um anexo)
- e a segunda, que obtém o conteúdo de cada anexo, que poderá ser copiado para outro local qualquer, enviado por email, etc.
Note-se que como cada item pode conter mais do que um anexo, ambas as ações ficaram dentro de loops “Apply to each”, embora, no caso que estamos a analisar apenas exista um documento em causa.
No próximo passo, vamos criar o ficheiro na biblioteca de documentos, no diretório pretendido mas ainda com o nome original:
Podemos visualizar na biblioteca de documentos que o ficheiro foi criado:
Podemos considerar este ficheiro como temporário e criar um definitivo com o nome correto com base neste. Para isso, precisamos de algumas ações:
- obter a extensão do ficheiro
- criar o ficheiro definitivo com o nome e a extensão pretendidos
- eliminar o ficheiro temporário
No designer podemos visualizar estas ações:
Na primeira ação, estamos a recolher as propriedades do ficheiro criado anteriormente. A expressão que obtém a extensão do ficheiro está na segunda ação “Compose” e é a seguinte:
last(split(outputs('Get_file_properties')?['body/{FilenameWithExtension}'],'.'))
Finalmente, as duas últimas ações são as seguintes:
A criação do ficheiro definitivo no mesmo diretório mas com a nomenclatura desejada, que é dada pela expressão:
concat(items('Apply_to_each_4')?['NumeroFatura'], '_', variables('FornecedorCamelCase'),'.',outputs('Compose_2'))
E a última ação deste fluxo de automação elimina o ficheiro temporário.
Como vemos na imagem seguinte, o documento foi acrescentado à biblioteca de documentos do SharePoint: