API Get em WebSpeed progress

Olá, passei um tempo tentando aprender a desenvolver APIs customizadas no padrão da TOTVS para executar telas em HTML no ERP Datasul, más tive muita dificuldade em encontrar conteúdo claro e prático sobre o assunto na internet.

Por fim o pessoal da comunidade 4each.com.br me convenceu a usar os recursos que já tenho algum conhecimento.

Então vou tentar escrever um artigo onde teremos uma API com método GET bem simples só para listar as cidades cadastradas.
E depois vou tentar complementar fazendo uma tela de consulta com Angular e PO-UI.

Sobre APIs e telas em HTML customizadas Datasul caso esteja interessado em desenvolver as APIs e telas em HTML customizadas para o ERP Datasul segue abaixo um compilado de links que encontrei e considerei útil:

Configurar WebSpeed

Antes de iniciar, eu trabalho com o WebSpeed rodando no IIS, sempre que preciso configurar algo recorro a esse guia da Progress e da TOTVS:
https://knowledgebase.progress.com/articles/Article/P125146
https://tdn.totvs.com/pages/releaseview.action?pageId=189317595

O código

O fonte gerado para este exemplo está disponível no GitHub:
https://github.com/fabianofss/OpenEdge_Progress/blob/main/API/api_cidades.p

Agora vou explicar alguns pontos em detalhes.

Iniciamos o código importando uma classe da Progress para manipular Json

USING Progress.Json.ObjectModel.*.

Definimos algumas variáveis que vamos usar para pegar os parâmetros passado pela URL:

define variable p_filtro as logical no-undo.
define variable p_cidade as character no-undo.
…

vamos definir uma tabela temporária para manipular os dados que serão retornados pela API observe que para as colunas que possuem nome muito longo ou palavras separadas por traço usei o serialize-name para ajustar o nome do campo no Json que será gerado.
Também criei os campos CallBack e mgsRetorno para retornar uma mensagem caso aconteça algum erro previsto.

define temp-table ttCidade
    field cidade          like mgcad.cidade.cidade
    field sigla           like mgcad.cidade.sigla
    field estado          like mgcad.cidade.estado
    field pais            like mgcad.cidade.pais
    field cdn-munpio-ibge like mgcad.cidade.cdn-munpio-ibge serialize-name "cdnMunpioIbge"
    field CallBack        as character
    field mgsRetorno      as character.

Aqui estamos lendo os parâmetros e populando as variáveis:

PROCEDURE LerParametros :
    assign
        p_cidade = get-value(trim("cidade"))
        p_sigla  = get-value(trim("sigla"))
        p_estado = get-value(trim("estado"))
        p_pais   = get-value(trim("pais"))
        p_filtro = logical(get-value(trim("filtro"))).

Vamos usar o parâmetro p_filtro para controle, se ele for false então buscamos todas as cidades,se for true vamos fazer o filtro das cidades.

A procedure outputHeader usamos para configurar o header da resposta da API, se o Access-Control-Allow-Origin não for configurado pode gerar erro no Angular:

PROCEDURE outputHeader :
  output-http-header("Access-Control-Allow-Origin", "*").
  output-content-type ("application/json":U).
END PROCEDURE.

E process fazemos uso dos parâmetros capturados pela URL realizamos as operações

PROCEDURE process :
    if p_filtro = false then do:
        for each mgcad.cidade
            no-lock:
            create ttCidade.
            buffer-copy mgcad.cidade to ttCidade.
        end.
    end.
    else do:
        /* Buscar cidade pelo nome */
        if p_cidade <> "" then do:
            find first mgcad.cidade no-lock
                where mgcad.cidade.cidade = p_cidade
                no-error.
            if available mgcad.cidade then do:
                create ttCidade.
                buffer-copy mgcad.cidade to ttCidade.
            end.
        end.

Usamos o CallBack e o mgsRetorno para retornar um erro caso nenhuma cidade seja localizada.

    if not available ttCidade then do:
        create ttCidade.
        assign
            ttCidade.CallBack = "erro"
            ttCidade.mgsRetorno = "Nenhuma cidade localizada!".
        next.
    end.

Criamos a função LongcharToObject para converter um Lonhchar em Objeto Json, vamos usar este objeto para concatenar em outro objeto antes de dar o retorno da API:

FUNCTION LongcharToObject RETURNS JsonObject ( input jsonChar as longchar ) :
    /*  função que transforma um longchar em objeto json */
    define variable jsonInput as JsonObject no-undo.
    define variable objParse as ObjectModelParser no-undo.
    define variable jsonOutput as JsonObject no-undo.  

    assign
        jsonOutput = new JsonObject()
        objParse = new ObjectModelParser()                    
        jsonOutput = cast(objParse:Parse(jsonChar), JsonObject).

    delete object objParse.

    return jsonOutput.
END FUNCTION.

E por fim, na procedure process-web-request transformamos o conteúdo da tabela temporária ttCidade em um Json longchar para que a API retorne o conteúdo.

PROCEDURE process-web-request :
  define variable jsonObjeto as JsonArray no-undo.
  define variable jsonTemp AS JsonObject NO-UNDO.
  DEFINE VARIABLE cJSON       AS LONGCHAR NO-UNDO.
  DEFINE VARIABLE lOK         AS LOGICAL   NO-UNDO.                   
                   
  /* 
   * Output the MIME header and set up the object as state-less or state-aware. 
   * This is required if any HTML is to be returned to the browser.
   */
  RUN outputHeader.
  
  find first ttCidade no-lock no-error.

  ASSIGN lOK = TEMP-TABLE ttCidade:WRITE-JSON("LONGCHAR", cJSON).

  assign jsonObjeto = LongcharToObject(cJSON):GetJsonArray("ttCidade").
  
  jsonObjeto:Write(cJSON).

  jsonTemp = NEW JSONObject().
  jsonTemp:ADD("hasNext", false).
  jsonTemp:ADD("items", jsonObjeto).

  jsonTemp:Write(cJSON).

  /* o prefixo cb significa CallBack */
  {&OUT} STRING(cJSON).
  
END PROCEDURE.

Observe que neste momento em que converto o conteúdo da ttCidade em Json já poderia ter feito o retorno deste conteúdo. Porém para ficar um pouco mais próximo do padrão adotado pela TOTVS criei um segundo Json e inseri o conteúdo convertido dentro do campo items.


O resultado será esse:
Testando filtro de cidades no navegador:

Testando no Postman, agora filtrando por estado:

One thought on “API Get em WebSpeed progress

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.