Vamos criar uma tela de consulta totalmente customizada que possamos usar no ERP Datasul da TOTVs. Vamos criar uma consulta de cidades neste guia.
Primeiramente vamos criar a API que fará a coleta dos dados no sistema usando os recursos apresentados n
este link: https://tdn.totvs.com/display/public/FRAMJOI/Desenvolvimento+de+APIs+para+o+produto+Datasul
Também vamos usar o programa criado pelo Rubinhos e disponibilizado no GIT da TOTVs neste endereço: https://github.com/totvs/CoffeeAndCodeJOI/blob/master/dts-thf/back-end/fnd/api/v1/idiomas.p
Em seguida vamos criar uma tela de consulta com Angular e POUI e tentar inserir no ERP Datasul baseados no guia deste endereço: https://po-ui.io/guides/getting-started
Criando a API para consulta
Vamos criar uma procedure chamada api_cidade.p, segue o código:
USING Progress.Json.ObjectModel.*.
USING Progress.Json.ObjectModel.ObjectModelParser.
USING Progress.Json.ObjectModel.JsonArray.
USING Progress.Json.ObjectModel.JsonObject.
{utp/ut-api.i}
{utp/ut-api-utils.i}
{utp/ut-api-action.i piGet GET /cidade/~*}
{utp/ut-api-action.i piGetAll GET /~*}
{utp/ut-api-notfound.i}
define temp-table ttCidade no-undo
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".
/*------------------------------------------------------------------------------
Retorna a lista de cidades.
------------------------------------------------------------------------------*/
PROCEDURE piGetAll:
DEFINE INPUT PARAMETER jsonInput AS JsonObject NO-UNDO.
DEFINE OUTPUT PARAMETER jsonOutput AS JsonObject NO-UNDO.
DEFINE VARIABLE jsonRetorno AS JsonArray NO-UNDO.
EMPTY TEMP-TABLE ttCidade.
EMPTY TEMP-TABLE RowErrors.
for each mgcad.cidade no-lock
by cidade:
create ttCidade.
buffer-copy mgcad.cidade to ttCidade.
end.
ASSIGN jsonRetorno = NEW JsonArray().
jsonRetorno:Read(TEMP-TABLE ttCidade:HANDLE).
RUN createJsonResponse(
INPUT jsonRetorno,
INPUT TABLE RowErrors,
INPUT FALSE,
OUTPUT jsonOutput).
END PROCEDURE.
/*------------------------------------------------------------------------------
Retorna os dados da cidade informada por parametro (Parametro de URL)
------------------------------------------------------------------------------*/
PROCEDURE piGet:
DEFINE INPUT PARAMETER jsonInput AS JsonObject NO-UNDO.
DEFINE OUTPUT PARAMETER jsonOutput AS JsonObject NO-UNDO.
DEFINE VARIABLE jsonRetorno AS JsonArray NO-UNDO.
define variable oRequestParser as JsonAPIRequestParser no-undo.
define variable oQueryParams as JsonObject no-undo.
DEFINE VARIABLE vAux AS CHARACTER NO-UNDO.
EMPTY TEMP-TABLE ttCidade.
EMPTY TEMP-TABLE RowErrors.
ASSIGN
oQueryParams = NEW JsonObject()
jsonRetorno = NEW JsonArray().
oRequestParser = NEW JsonAPIRequestParser(jsonInput).
assign oQueryParams = oRequestParser:getQueryParams().
/* se vazio o GetJsonText() retorna 2 */
if length(oQueryParams:GetJsonText()) <= 2 then do:
CREATE RowErrors.
ASSIGN
RowErrors.ErrorNumber = 42424
RowErrors.ErrorType = "error"
RowErrors.ErrorDescription = "Nenhum parâmetro de busca informado"
RowErrors.ErrorSubType = "ERROR".
end.
else do:
if oQueryParams:has("cidade") then do:
/* getQueryParams retorna JsonArray, vamos estrair a informação na primeira posição */
assign jsonRetorno = oQueryParams:GetJsonArray("cidade").
assign vAux = string(jsonRetorno:GetJsonText(1)).
for each mgcad.cidade no-lock
where mgcad.cidade.cidade = vAux
by cidade:
create ttCidade.
buffer-copy mgcad.cidade to ttCidade.
end.
/* Se for filtrar estado */
/* :has é case sensitive */
if oQueryParams:has("estado") then do:
assign jsonRetorno = oQueryParams:GetJsonArray("estado").
assign vAux = string(jsonRetorno:GetJsonText(1)).
for each ttCidade
where ttCidade.estado <> vAux
:
delete ttCidade.
end.
end.
/* Se for filtrar estado */
if oQueryParams:has("pais") then do:
assign jsonRetorno = oQueryParams:GetJsonArray("pais").
assign vAux = string(jsonRetorno:GetJsonText(1)).
for each ttCidade
where ttCidade.pais <> vAux
:
delete ttCidade.
end.
end.
end.
end.
if not can-find(first ttCidade) then do:
CREATE RowErrors.
ASSIGN
RowErrors.ErrorNumber = 42424
RowErrors.ErrorType = "error"
RowErrors.ErrorDescription = "Nenhum registro localizado"
RowErrors.ErrorSubType = "ERROR".
end.
else
jsonRetorno:Read(TEMP-TABLE ttCidade:HANDLE).
if not can-find(first RowErrors) then do:
RUN createJsonResponse(
INPUT jsonRetorno,
INPUT TABLE RowErrors,
INPUT FALSE,
OUTPUT jsonOutput).
end.
else do:
RUN createJsonResponse(NEW JsonObject(), INPUT TABLE RowErrors, INPUT FALSE, OUTPUT jsonOutput).
end.
END PROCEDURE.
Resultado da consulta realizado pelo Postman:
O próximo passo é criar a tela de consulta de dados .
Porem antes vem um detalhe importante. Ao tentar fazer uma consulta pode estar tendo um retorno de falha de login.
Acontece pois a API vai tentar logar o usuário antes da consulta, para conseguir acessar deve ser informado um usuário e senha cadastrados no sistema Datasul, e a senha deve estar convertida para SHA1
DEFINE VARIABLE testPass AS CHARACTER NO-UNDO.
testPass = BASE64-ENCODE(SHA1-DIGEST(LC("testPassword"))).
O resultado desta conversão será “i7YRj4/Wk1rQh2o740pxfTJwj/0=”
Para realizar o teste no Postman por exemplo devemos configurar Basic Auth em Autorization:
Boa tarde Fabiano, tudo bem?
Assunto muito interessante, porém o primeiro link é apenas para pessoal da TOTVS, franqueados ou parceiros, não sei como conseguir acesso a ele.
Olá,
Tem razão, também não tenho mais acesso, desculpe.
Olhe esses links se podem te ajuda:
API Get em WebSpeed progress
YouTube – How To | Desenvolvimento de API para o produto Datasul
Desenvolvimento de APIs para o produto Datasul
Opa, já me deu uma luz, estou tendo alguns problemas, mas acredito que seja configuração de produto, abri um chamado na TOTVS pra ver se eles me auxiliam, por enquanto, muito obrigado =)
Muito bom seu tutorial, como estou iniciando nesta jornada (PO-UI x Progress) não entendi bem onde ficarão os programas da sua API.
Por exemplo, se eu quiser construir algo para o módulo de cadastros, devo colocar meu .R na pasta : ..\totvs\datasul\dts-12\ERP\ems2\cdp\api\v2 ?
E no caso acima o seu API_CIDADE.P está onde ?
Bom dia,
desculpe a demora em responder, estranhamente não fui notificado do comentário.
Por padrão adotamos que os customizados recebem a nomeclatura dms, então temos um banco de dados mgdms, as tabelas recebem dm_ no inicio e no propatch os compilados ficam na pasta dms/ pra baixo.
Estou colocando todas as APIs feitas por mim no seguinte diretório: …\erp\fnd\dms\api\v1
Bom dia Fabiano, tudo certo?
Para consumir essas APIs eu vou sempre precisar criar uma pasta customizada dentro da pasta fnd ou pastas padrões datasul? Porque aqui na empresa utilizamos uma pasta _custom que fica depois da ERP, no caso ERP\_custom e aqui salvamos nossos customizados, gostaria de saber se consigo criar uma pasta api\v1 dentro dessa custom e utilizar as APIs, estou tentando de todas as formas e só consegui com a pasta customizada dentro da fnd mesmo.
Olá Fabiano! Obrigada pelo tutorial. Consegui dar meus primeiros passos e compartilho aqui 🙂
1) Caminho dos programas: temos a pasta “esp” de específico que também está no Propath do AppServer. Ficou assim: esp\fnd\api\v1\api_cidade.r. Na chamada via Postman ficou assim: http://servidor:porta/api/fnd/v1/api_cidade?cidade=CURITIBA&estado=PR&pais=Brasil
2) Postman: não tive falha no login, em “Authorization” informei o tipo “Basic Auth” e usuário e senha do Datasul sem a necessidade de converter para SHA1
Abraços!
Não consigo fazer funcionar…
quando chamo http://cairo:8180/api/sec/api/v1/api_cidade ele devolve o erro abaixo
{“detailedMessage”:”Method not found”,”code”:”1″,”message”:”BAD_REQUEST”,”type”:”error”}
porem acredito que não seja problema de propath, por se eu colocar o caminho errado… ele da erro..
http://cairo:8180/api/sec/api/v1/api_cidadeXXX
{“detailedMessage”:”ERROR condition: ** \”sec\/api\/v1\/api_cidadeXXX\” nao foi encontrado. (293) (7211)”,”code”:500,”message”:”Internal server error”}
alguem consegue me dar uma luz ? k
Olá,
eu não tenho mais acesso ao ambiente pra te responder com certeza mas pode ser configuração no servidor se é TomCat ou JBoss
tem que fazer umas configurações para habilitar o acesso e reconhecimento da rota.
dá uma olhada nesse link: https://tdn.engpro.totvs.com.br/pages/viewpage.action?pageId=571250227
e para ter um resultado melhor, tente usar o Postman.
Espero pelo menos ter dado um norte para sua pesquisa.
Boa tarde, alguém pode me dizer o motivo deste erro abaixo:
{
“detailedMessage”: “Method not found”,
“code”: “1”,
“message”: “BAD_REQUEST”,
“type”: “error”
}
Olá,
pode ser um destes motivos:
O método utilizado como GET, POST PUT não foi definido no definitions
O nome do método na URL está diferente do método criado no definitions:
{utp/ut-api-action.i piGet GET /cidade/~*}
URL: servidor:porta/dts/datasul-rest/xxx/pi_Get/?cidade=XXXX
Ou a URL pode estar errada.
Boa sorte..