Carga de api paginada para powerbi com logic app e storage account - exemplo omie
Tags: powerbi, logicapps, storageaccount, api
Published: 2021-02-05 12:44:04

Oi Pessoal!

Ao pesquisar sobre como consumir api's páginadas no powerbi encontrei alguns exemplos que utilizam a linguagem M, como no [vídeo](https://www.youtube.com/watch?v=yc78DZnGhbQ) do colega [Raphael Pacheco](https://www.linkedin.com/in/raphael-pacheco-702a3b49/).

Esse post é uma alternativa a solução direta no powerbi utilizando M. 

Minha motivação é diminuir a carga cognitiva do processo, visto que não sou um especialista em powerbi e não conheço muito M. Vamos isolar o powerbi apenas como a camada de montagem de painéis. Toda a lógica de integração fica em uma outra camada (logic app), os dados prontos para consumo ficam no storage account e disponibilizado através de uma url.

É provável que seja possível fazer o mesmo processo com o [Power Automate](https://flow.microsoft.com/pt-br/).

##Arquitetura

![post-integracao-logic-app-omie](https://dev-to-uploads.s3.amazonaws.com/i/1a2snxyxsapmrgp1mccd.png)
 
Vou focar na camada central que é a extração e preparação de dados, e partir do pressuposto que você já tenha algum conhecimento prévio em API's e Powerbi.

##Recursos

* [Postman](https://www.postman.com/downloads/)
* [Assinatura Azure](https://azure.microsoft.com/pt-br/)
* [Assinatura Omie (teste)](https://developer.omie.com.br/)
* [PowerBi](https://powerbi.microsoft.com/pt-br/desktop/)

##Fonte Bruta - Api da Omie

Faça o download do [postman](https://www.postman.com/downloads/).
Entre no site da [omie](https://developer.omie.com.br/) e faça o cadastro. 
Vamos usar a api de [lista de produtos](https://app.omie.com.br/api/v1/geral/produtos/#ListarProdutos) para esse exemplo.

Por algum motivo não conseguimos fazer a requisição conforme é apresentado na tela. 
Ao inspecionar a requisição (aperte F12 no navegador), é possível ver que a requisição tem um parâmetro a mais, _**url**_, e temos que incluir esse para parâmetro para reproduzir em nossa aplicação.

![omie-request](https://dev-to-uploads.s3.amazonaws.com/i/wor8ejxc2sgn9oe7ghdr.PNG)

Preencha a requisição no postman conforme as imagens abaixo:

![postman-request](https://dev-to-uploads.s3.amazonaws.com/i/xe6i5ke8ox67va0fs4f4.PNG)

![params-request](https://dev-to-uploads.s3.amazonaws.com/i/0p77k0opr18n9ohkwprf.PNG)
 
A parte da resposta que contém a lista de produtos está em "response"
 ![postman-response](https://dev-to-uploads.s3.amazonaws.com/i/qssfjeyi7v7261ds6w2f.PNG)
 
Por hora é isso, depois voltamos aqui.

##Storage Account | Container - Azure

Vá até o portal do azure e crie um novo grupo de recursos. 
Recomendo que você siga os nomes que vou atribuir aos recursos, ao menos pra esse tutorial.
Crie todos recursos desse tutorial dentro desse grupo de recursos.

![new-gr](https://dev-to-uploads.s3.amazonaws.com/i/6nh63vyizivtdurrbvb9.PNG) 
![gr-name](https://dev-to-uploads.s3.amazonaws.com/i/xha1fdpiz2w8evddk4gv.PNG)

Agora vamos criar um storage account.

![add-rsrc](https://dev-to-uploads.s3.amazonaws.com/i/rengmm36vj5b9f8ru1x2.PNG)

![select-st-acc](https://dev-to-uploads.s3.amazonaws.com/i/hgs19ex6bq4p0fb0kbk4.PNG)

Nessa estapa substitua o conteúdo de Storage account name
 de nomeomie por {seunome}omie, pra evitar conflitos com a url.
![config-st](https://dev-to-uploads.s3.amazonaws.com/i/d92ahbx26jtbjmy279eb.PNG)

![created-rsrc](https://dev-to-uploads.s3.amazonaws.com/i/uec9580botnahy55wzqg.PNG)

![create-container](https://dev-to-uploads.s3.amazonaws.com/i/65l3z4kn1xuy8xfyykyn.PNG)

Nessa etapa eu dei o nome de container de 'fonte-preparada' e configurei a camada de acesso como pública, para focarmos no processo de integração, mas em produção fique atento nas questões de segurança.
![create-container](https://dev-to-uploads.s3.amazonaws.com/i/d1zbrte7l0hgmfg8x205.PNG)

Nosso container para receber os dados está pronto.

##Logic App

Volte até o grupo de recursos OMIE e clique novamente para adicionar um novo recurso.
Repare que o nosso storage já se encontra listado.

![create-logic-app](https://dev-to-uploads.s3.amazonaws.com/i/delb1w6jq2k9a11rteja.PNG)

![create-logic-app2](https://dev-to-uploads.s3.amazonaws.com/i/448fnb5zfxyav9p844ao.PNG)

![extracao-produtos](https://dev-to-uploads.s3.amazonaws.com/i/fd97s3vo47injpnnegz0.PNG)

![go-to-rsrc](https://dev-to-uploads.s3.amazonaws.com/i/fmux55lkq3d9cqb48zaz.PNG)

![BlankLogicApp](https://dev-to-uploads.s3.amazonaws.com/i/mdbk1z27h2zrys2gh70a.PNG)

#####Recorrência

Na tela de designer, vamos definir a primeira etapa que é como esse procedimento será iniciado. Vamos escolher o método de recorrência e definir que ele seja repetido de 5 em 5 minutos. Estou definindo esse intervalo curto, pra podermos analisar os resultados em uma janela menor de tempo, mas faça como fizer sentido para você.

![schedule-search](https://dev-to-uploads.s3.amazonaws.com/i/3nqgwjw5t0xdh35upnoh.PNG)

![schedule-recurrency](https://dev-to-uploads.s3.amazonaws.com/i/vdsr01kpyzb77fi3e4zx.PNG)

![schedule-frequency](https://dev-to-uploads.s3.amazonaws.com/i/98a7viumf594w4ccrqnz.PNG)
 

#####Dados da paginação

A próxima etapa é obter os dados da paginação de forma dinâmica. Para isso vamos fazer uma requisição a api, reservar os dados da página atual e total de páginas e desprezar o restante das respostas.

Esses são os dados que vamos reservar.

![data-page](https://dev-to-uploads.s3.amazonaws.com/i/trcfd4ueg93bfajc4n1b.PNG)

No nosso designer acrescente na sequencia uma etapa do tipo HTTP.

![step-http-page](https://dev-to-uploads.s3.amazonaws.com/i/51z6tkpg1wlzlumld45v.PNG)
 

![action-http-page](https://dev-to-uploads.s3.amazonaws.com/i/lspzynv1n5vbyoknw6jd.PNG)

Configure essa etapa conforme fizemos no postman e a renomeie para "ObterDadosDaPagina", importante dizer o que estamos fazendo.

![obter-dados-da-pagina-http](https://dev-to-uploads.s3.amazonaws.com/i/cvd57uji7babg9o92838.PNG)

#####Propriedades da paginação
A próxima etapa é mapear a resposta da api, para que possamos usar suas propriedades como variáveis nas etapas a seguir.

Para isso vamos utilizar o método Parse Json.

![data-operations](https://dev-to-uploads.s3.amazonaws.com/i/qwfhspjbxnbfd2u0qzd4.PNG)

![parse-json](https://dev-to-uploads.s3.amazonaws.com/i/8jxb1lo5tgajnct0pplk.PNG)

Em content vamos utilizar o output Body da etapa anterior, que é o corpo da resposta da api.

![content-parse-json](https://dev-to-uploads.s3.amazonaws.com/i/4knt8y47huoofncppyhe.PNG)

Em Schema, clique em "Use sample payload to generate schema".

![use-sample-payload](https://dev-to-uploads.s3.amazonaws.com/i/a6br6hhusb3lfhhwjgqz.PNG)

Agora copie e cole a reposta do postman na janela que vai abrir.
![copy-response](https://dev-to-uploads.s3.amazonaws.com/i/fdzeu65gtbn9lte30qem.PNG)

![past-payload](https://dev-to-uploads.s3.amazonaws.com/i/54e125ca404sickieziy.PNG)

Esse procedimento vai auto mapear os nomes e tipos das propriedades da resposta.


Renomeie essa etapa como PropriedadesDaPagina

![propriedades-da-pagina-rename](https://dev-to-uploads.s3.amazonaws.com/i/e7bo0za9xbuq9pjppbtm.PNG)
 

#####Variáveis

Na próxima etapa vamos definir as variáveis que vamos utilizar para as próximos métodos.

######Produtos

Essa variável é do tipos lista e será iniciada como vazia, ela será responsável por armazenar as respostas das requisições.

Para isso vamos utilizar o método Variables.

![variables](https://dev-to-uploads.s3.amazonaws.com/i/ip8rs6wzfjkyg54p0t7i.PNG)
 
![produtos](https://dev-to-uploads.s3.amazonaws.com/i/ryvl8tbd1kf1mm13yaxz.PNG)

######Página
Agora vamos declarar a variável Pagina que será responsável por armazenar o número da página a ser requisitada.

Dessa vez vamos iniciar essa variável com o valor da propriedade pagina, obtida no output do método PropriedadesDaPagina.
![pagina-dynamic](https://dev-to-uploads.s3.amazonaws.com/i/vio96s6vx36o79akm882.PNG)

######Total de páginas
Vamos declarar a variável TotalDePaginas que será responsável por armazenar o número total de páginas a serem requisitadas.

Vamos iniciar essa variável com o valor da propriedade total_de_paginas, obtida no output do método PropriedadesDaPagina.
![total-de-paginas](https://dev-to-uploads.s3.amazonaws.com/i/ly9wosf4jo1o57gs6i3d.PNG)

#####Recursão
Nessa etapa vamos declarar um método de recursão. A lógica aqui é fazer a requisição da página X, armazenar a resposta na variável produto, e repetir esse processo na página X + 1 até que o número total de páginas tenha sido requisitado.

Para isso vamos utilizar o método Until.

![control](https://dev-to-uploads.s3.amazonaws.com/i/cs3a0tgfxlh3ws0srob7.PNG)

![until](https://dev-to-uploads.s3.amazonaws.com/i/hnpfuvwyds5wuiqt6x1m.PNG)

A lógica utilizada nesse laço de repetição é executar as tarefas a seguir até que o Total de páginas for menor que o valor da página.

![logic-until](https://dev-to-uploads.s3.amazonaws.com/i/q92r3ud6fyzzynwadvmo.PNG)

######Obter Produtos

Agora sim vamos fazer a requisição onde vamos o obter os valores para alimentar nossa resposta.

Dentro do laço vamos adicionar novamente o método HTTP, e configurá-lo quase igual a primeira vez que o fizemos. Porém dessa vez no body da requisição vamos substituir o valor da página que até então era 1 para o valor da variável página.

![ObterProdutos](https://dev-to-uploads.s3.amazonaws.com/i/sfuhzxhe5zohca78uda5.PNG)
 
######Propriedades Do Produto

Na sequência vamos executar novamente o método Parse Json para analisar a resposta da requisição feita na etapa anterior.

![propriedades-do-produto](https://dev-to-uploads.s3.amazonaws.com/i/5uh1cs1do4gsken9jsu0.PNG)

Em Schema, clique em "Use sample payload to generate schema" e vamos copiar e colar a reposta do postman na janela que vai abrir.
Esse procedimento vai auto mapear os nomes e tipos das propriedades da resposta. Porém dessa vez teremos que fazer uma alteração no mapeamento.

As propriedades peso_bruto e peso_liq tem que ter seu type substituído de integer para um array de tipos:

![peso_bruto](https://dev-to-uploads.s3.amazonaws.com/i/w8zygjvyamkztrxlhdl1.PNG)

![peso_liq](https://dev-to-uploads.s3.amazonaws.com/i/rpryqp6lgf7xgcr9pmdu.PNG)

Isso deve ser feito sempre que um campo pode obter valores inteiros ou decimais.

######Preencher Produtos

A próxima etapa é preencher a variável produtos com o valor da propriedade response anteriormente mapeada pelo método Propriedades do produto.

Para isso vamos utilizar o método Append to array variable.

![append-to-array-variable](https://dev-to-uploads.s3.amazonaws.com/i/k4kt7v5oosubhba9xzkl.PNG)
 
![pre-append-to-array-variable](https://dev-to-uploads.s3.amazonaws.com/i/mbi5vnhcyfgtxu83yvsv.PNG)

![preencher-produtos](https://dev-to-uploads.s3.amazonaws.com/i/wcpf9u5gz8f38zuj6d1s.PNG)
 
######Incrementar Página
Agora pra finalizar o laço vamos incrementar a variável página, fazendo com o que o seu valor seja X + 1.

Para isso vamos utilizar o método Increment Variable.

![pre-increment-variable](https://dev-to-uploads.s3.amazonaws.com/i/wwn6asuoy5qdezttw7e8.PNG)

![increment-pagina](https://dev-to-uploads.s3.amazonaws.com/i/kf98hsjpxpbp6tro8z9u.PNG)


######Criar arquivo

Agora vamos criar a última etapa dentro do logic app que é enviar a resposta como um arquivo no formato json para dentro do container no storage account.

Para isso vamos utilizar o método Create blob.

![blob](https://dev-to-uploads.s3.amazonaws.com/i/qxqwajoeo0qy6vduawr7.PNG)
 
![create-blob](https://dev-to-uploads.s3.amazonaws.com/i/eeb5wz5lnanbvx22r10j.PNG)
 

A primeira parte é criar uma conexão com o storage.

![create-connection](https://dev-to-uploads.s3.amazonaws.com/i/kjbmu3dq66vhrlpt174m.PNG)
 

A segunda parte é configurar o blob, informar em qual container ele será salvo, seu nome seguido da extensão e o seu conteúdo. Infelizmente o Dynamic content não reconhece a variável Produtos como um valor elegível para o campo content, de forma que temos que incluí-la com uma expressão:

![create-product](https://dev-to-uploads.s3.amazonaws.com/i/0vk0qihcbhaorw4w8af3.PNG)

Ao final o processo terá o visual abaixo, após salvar vamos executar e ver o resultado.
![final](https://dev-to-uploads.s3.amazonaws.com/i/wvqmomecjoj0gzmuxaqa.PNG)
 

Depois de executar, se tudo der certo o resultado será esse:
![success](https://dev-to-uploads.s3.amazonaws.com/i/45ozlj621taxnqcqsog7.PNG)
 

Confira indo até o storage account.
 
 ![product-storage](https://dev-to-uploads.s3.amazonaws.com/i/dwdtevgje9m8xuk82658.PNG)

Agora você pode obter o link e abrir no powerbi.

![copy-link](https://dev-to-uploads.s3.amazonaws.com/i/01ffdq2sml9meek9belo.PNG)
![power-json](https://dev-to-uploads.s3.amazonaws.com/i/d6ldonpj6hsuc9vzdv0z.PNG)
![open-json](https://dev-to-uploads.s3.amazonaws.com/i/kxcie956pnd695fm9blt.PNG)
![para-a-tabela](https://dev-to-uploads.s3.amazonaws.com/i/g6683vwfp2py543mz0ky.PNG)
![produtos-power](https://dev-to-uploads.s3.amazonaws.com/i/mih4kxgqk3ulend5ru5y.PNG)
![fim](https://dev-to-uploads.s3.amazonaws.com/i/qwjb1teb9x2v8rhqdd1f.PNG)

Algumas considerações.
> Esse post segue o caminho feliz.
> Não foi analisado escala.
> Não foi considerado segurança.
> Não foi utilizado tratamento de erros.
> Não foi considerado cargas incrementais, de forma que o arquivo é sempre substituído como o todo.

Espero que isso te ajude!