ADVPL + REACT – Parte 04 | API Consulta de Permissões

Introdução

Dando continuidade a série de artigos sobre ReactJS + Advpl, hoje irei iniciar a API de CRUD com a parte de listar as permissões salvas na tabela Z20. Caso você tenha perdido alguma parte ou tenha interesse em ler os primeiros artigos dessa série, abaixo você tem uma lista contendo o título e o link de cada um deles.

API de Consulta

Agora iremos entrar na parte mais interessante do backend da nossa aplicação, onde faremos endpoints para trabalhar com a inclusão, alteração, consulta e deleção dos dados na tabela Z20.

Vamos iniciar pela consulta (GET), onde o endpoint “/TPontinAccessControl” estará hapto a receber requisições do tipo GET e retornar via JSON todos os registros da tabela Z20.

Bora Codar!!!

Vamos começar criando uma classe responsável por gerar o objeto com o modelo de dados da Z20 conforme o dicionário de dados (SX3).
Faremos de forma que esse modelo seja o mais dinâmico possível, não necessitando de manutenção nos fontes em caso de criação de novos campos ou alterações no dicionário de dados da Z20.

Model

Vamos então criar uma pasta chamada “models” dentro da pasta “src” e em seguida criamos o nosso fonte “TPontinAccessControlModel.prw“, ficando no seguinte caminho: src/models/TPontinAccessControlModel.prw.

Agora basta incluir o código abaixo no nosso fonte:

#include 'totvs.ch'


//|Responsavel por montar o modelo de dados da Z20 |
Class TPontinAccessControlModel From LongClassName

  Data oObjZ20

  Method New() Constructor

EndClass


Method New() Class TPontinAccessControlModel

  Local aZ20Struct  := {}
  Local nI          := 0

  dbSelectArea("Z20")
  Z20->( dbSetOrder(1) )

  aZ20Struct  := Z20->( dbStruct() )

  ::oObjZ20 := JsonObject():New()

  ::oObjZ20['RECNO'] := 0

  For nI := 1 To Len(aZ20Struct)

    ::oObjZ20[ aZ20Struct[nI,1] ] := CriaVar( aZ20Struct[nI,1], .T. )

  Next nI

Return self

Explicando por partes…

Class TPontinAccessControlModel From LongClassName

  Data oObjZ20

  Method New() Constructor

EndClass

No trecho acima é criado a classe e informado que será utilizado a propriedade “oObjZ20”.
Logo em seguida informamos os métodos que serão criados na classe.

Method New() Class TPontinAccessControlModel

  Local aZ20Struct  := {}
  Local nI          := 0

  dbSelectArea("Z20")
  Z20->( dbSetOrder(1) )

  aZ20Struct  := Z20->( dbStruct() )

  ::oObjZ20 := JsonObject():New()

  ::oObjZ20['RECNO'] := 0

  For nI := 1 To Len(aZ20Struct)

    ::oObjZ20[ aZ20Struct[nI,1] ] := CriaVar( aZ20Struct[nI,1], .T. )

  Next nI

Return self

Linha 09: aZ20Struct := Z20->( dbStruct() )
Basicamente nesse ponto utilizamos a classe “dbStruct()” para buscar a estrutura de campos da Z20 direto no dicionário de dados, com isso caso um campo seja alterado ou incluído não será necessário realizar manutenção no nosso modelo.

Linha 13: ::oObjZ20[‘RECNO’] := 0
Foi criado também a propriedade “RECNO” no JsonObject do modelo para guardar o R_E_C_N_O_ do registro em questão para uso nos momentos de alteração e exclusão de registros.

Linha 15 a 19: For nI := 1 To Len(aZ20Struct)
Utilizamos o FOR para percorrer todos os campos da Z20 e incluí-los no JsonObject, com isso conseguiremos obter os campos através do método “GetNames” da classe JsonObject e inserir os valores buscando do banco de dados através do DAO (data access object).

Data Access Object

Vamos agora criar o nosso DAO que será a camada responsável por toda a comunicação com o banco de dados.

Começamos criando uma pasta chamada “DAO” dentro da pasta “src” e em seguida criamos o nosso fonte “TPontinAccessControlDAO.prw“, ficando no seguinte caminho: src/models/TPontinAccessControlDAO.prw.

Agora incluímos o código abaixo no nosso fonte:

#include 'totvs.ch'


//|Responsavel por acesso ao banco de dados |
Class TPontinAccessControlDAO From LongClassName

  Data oModel

  Method New() Constructor
  Method ListarZ20()

EndClass


Method New() Class TPontinAccessControlDAO

  ::oModel  := TPontinAccessControlModel():New()

Return self


Method ListarZ20() Class TPontinAccessControlDAO

  Local oObjRet     := Nil
  Local oDados      := Nil
  Local aArea       := GetArea()
  Local aAreaZ20    := Z20->( GetArea() )
  Local aCampos     := {}
  Local aPermissao  := {}
  Local nPos        := 0
  Local nZ          := 0
  Local nCont       := 0

  dbSelectArea("Z20")
  Z20->( dbSetOrder(1) )
  Z20->( dbGoTop() )

  oObjRet   := JsonObject():New()

  //|Busca todos os campos do model |
  aCampos   := ::oModel:oObjZ20:GetNames()

  While !Z20->( EoF() )

    oDados  := TPontinAccessControlModel():New()

    aAdd( aPermissao, oDados:oObjZ20 )
    nPos  := Len(aPermissao)

    For nZ := 1 To Len(aCampos)

      If aCampos[nZ] == 'RECNO'
        aPermissao[ nPos, 'RECNO' ] := Z20->( Recno() )
      Else
        aPermissao[ nPos, aCampos[nZ] ]  := AlLTrim( &( 'Z20->' + aCampos[nZ] ) )
      EndIf

    Next nZ

    nCont++

    Z20->( dbSkip() )

  EndDO

  oObjRet['registros']  := nCont
  oOBjRet['result']     := JSonObject():New()
  oObjRet['result']     := aPermissao

  RestArea(aAreaZ20)
  RestArea(aArea)

Return oObjRet

No código acima criamos a classe “TPontinAccessControlDAO” com a propriedade “oModel” e os métodos “New()” que é o construtor da classe e o método “ListarZ20()” que é responsável por buscar os dados na tabela Z20 e retorna-los em um JsonObject.

Explicando o método ListarZ20:

Linha 41: aCampos   := ::oModel:oObjZ20:GetNames()
O array “aCampos” recebe os campos que estão no modelo da Z20 através do método GetNames() da classe JsonObject, inclusive com o campo RECNO que criamos.

Linha 43 a 64: While !Z20->( EoF() )
Percorre todos os itens gravados na Z20 e alimenta no array “aPermissao” com todos os campos da Z20 de forma dinâmica através da macro substituição do nome do campo: “&('Z20->'+aCampos[nZ])“.

No final é alimentado o objeto “oObjRet” com a quantidade de registros encontrados e com o array “aPermissao” com os dados.

Com isso o nosso DAO já está preparado para buscar os dados da Z20 no banco de dados e retornar no objeto Json.

Controller

Agora podemos criar o controller que será responsável por receber as requisições REST. De início vamos criar dentro da pasta src/controllers o fonte: “TPontinAccessControl.prw” e vamos incluir o código abaixo para receber a requisição GET.

#include 'totvs.ch'
#include 'restful.ch'


WSRESTFUL TPontinAccessControl DESCRIPTION "Serviço REST para controle de acesso dos usuarios"

  WSMETHOD GET DESCRIPTION "Retorna o cadastro de controle de acessos" ;
    WSSYNTAX "/TPontinAccessControl"

END WSRESTFUL


WSMETHOD GET WSRECEIVE WSSERVICE TPontinAccessControl

  Local oDAO      := NIL
  Local oDados    := NIL

  ::SetContentType("application/json")

  oDados  := JsonObject():New()

  oDAO    := TPontinAccessControlDAO():New()
  oDados  := oDAO:ListarZ20()

  ::SetStatus(200)
  ::SetResponse( oDados:ToJson() )


Return .T.

A parte de WSRESTFUL e demais detalhes da API REST já foram explicadas anteriormente, então vamos forcar no método GET a partir da linha 20.

Linha 20: oDados := JsonObject():New()
Informo que a variável oDados será um objeto Json

Linha 22: oDAO := TPontinAccessControlDAO():New()
A variável oDAO recebe o resultado do método construtor do nosso DAO (Data Access Object)

Linha 23: oDados := oDAO:ListarZ20()
Executa o método “ListarZ20()” e insere o resultado na variável oDados

Linha 25: ::SetStatus(200)
Informo que irei retornar o status 200 (OK) para o solicitante dos dados. É interessante realizar o tratamento desse código de retorno seguindo as boas práticas, porém para esse exemplo vamos manter o 200.

Linha 26: ::SetResponse( oDados:ToJson() )
O método “ToJson()” fará a conversão do objeto criado pela classe JsonObject e alimentado pelo método “ListarZ20()” para um string no formato JSON e responderá o solicitante com o resultado.

Finalizando vamos compilar os três novos fontes (Model, DAO e Controller) e podemos testar.

Com os fontes compilados, iremos criar dois registros na Z20 via APSDU apenas para conseguir ver o resultado no Json, depois podemos excluí-los devido objetivo é serem inseridos via requisição POST.

Hora da verdade, vamos realizar a requisição desse endpoint no insomnia conforme imagem abaixo (lembre-se de realizar o login e pegar o token).

Resultado:

Show de bola, agora já temos o método GET buscando dados reais da nossa tabela de permissões via requisição REST.

Lembrando que os fontes estão disponíveis para todos no GitHub.

No próximo tópico iremos fazer o método POST com algumas validações básicas do body.

Se inscrevam no blog para receber em primeira mão as novidades dessa série e não perder nada do que rola por aqui.

O nosso objetivo é criar uma cultura de uso da tecnologia para tornar as empresas brasileiras mais competitivas, por isso compartilhem esses posts com seus amigos para que possamos atingir um número maior ainda de pessoas.

Até mais…

Referências

gostou? siga e compartilhe

Deixe seu comentário

error

Siga para receber novidades

Registrar
LinkedIn
LinkedIn
Share
Instagram