Criando uma API Genérica para Consumirem no Protheus

Envio abaixo um código para Serviço Rest no Protheus, para ser consumido por outras aplicações:

Exemplo de consumo GET:

http://dc01-hom117.dominio.com:8080/rest/01/WSCONSULTA?FIL=01&TABELA=SA1&LIKE=A1_NOME$ALMAVIVA

#Include 'Protheus.ch'
#Include 'FWMVCDEF.ch'
#Include 'RestFul.CH'
#Include 'TbiConn.CH'
#Include 'TopConn.CH'

*****************************************************************************
*+-------------------------------------------------------------------------+*
*|Funcao      | WSCONSULTA  | Autor | Jader Berto                          |*
*+------------+------------------------------------------------------------+*
*|Data        | 21.12.2017                                                 |*
*+------------+------------------------------------------------------------+*
*|Descricao   | Consulta Dinâmica para Tabelas do Protheus                 |*
*+------------+------------------------------------------------------------+*
*|Solicitante |                                                            |*
*+------------+------------------------------------------------------------+*
*|Partida     | WebService                                                 |*
*+------------+------------------------------------------------------------+*
*|Arquivos    |                                                            |*
*+------------+------------------------------------------------------------+*
*|             ATUALIZACOES SOFRIDAS DESDE A CONSTRUCAO INICIAL            |*
*+-------------------------------------------------------------------------+*
*| Programador       |   Data   | Motivo da alteracao                      |*
*+-------------------+----------+------------------------------------------+*
*|                   |          |                                          |*
*+-------------------+----------+------------------------------------------+*
*****************************************************************************

User Function WSCONSULTA()
Return

WSRESTFUL WSCONSULTA DESCRIPTION "Serviço REST para manipulação de WSCONSULTA"

WSDATA FIL As String
WSDATA FILTRO  As String
WSDATA TABELA  As String

WSMETHOD GET DESCRIPTION "Retorna a Consulta no Protheus informada na URL" WSSYNTAX "/WSCONSULTA || /WSCONSULTA/{}"

END WSRESTFUL





WSMETHOD GET WSRECEIVE FILTRO  WSSERVICE WSCONSULTA
Local oObjProd := Nil
Local cStatus  := ""
Local cJson    := "{"
Local aCabNom  := {}
Local aDados   := {}
Local xAlias
Local TotCol   := 0
Local aLinha   := {}
Local aParam   := {}
Local cQuery   := ""
Local xRecno   := 0
Local cFilCmp  := ""
Local nExts    := 1
Private aFilt  := {}
Private aFilInt  := {}


        xAlias  := Self:TABELA


        aFilt := StrTokArr( Self:FILTRO, "@" )

        cFilAnt := UPPER(Self:FIL)

        ::SetContentType("application/json;  charset=iso-8859-1")

        SX2->( dbGoTop())
        dbSelectArea('SX2')
        If !SX2->( dbSeek( xAlias ) )
            ::SetResponse('{"erro":"Tabela:' +xAlias+'  não foi encontrada na Empresa '+cEmpAnt+' do Protheus."}')
            Return .T.
        EndIf    
        SX2->( dbCloseArea())




        DbSelectArea("SX3")
        DbSetOrder(1)

        SX3->(DbSeek(xAlias))          
        While SX3->(!Eof()) .And. SX3->X3_ARQUIVO == xAlias
            If ( SX3->X3_CONTEXT <> "V" )
                TotCol++
            Endif
        SX3->(DbSkip())
        End

        SX3->(DbGoTop())


        aCabNom := ARRAY(TotCol)

        TotCol := 0
        SX3->(DbSeek(xAlias))          
        While SX3->(!Eof()) .And. SX3->X3_ARQUIVO == xAlias
            If "FILIAL" $ SX3->X3_CAMPO
                cFilCmp := SX3->X3_CAMPO
            EndIF
            If ( SX3->X3_CONTEXT <> "V" )
                TotCol++
                aCabNom[TotCol]    := Alltrim(SX3->X3_CAMPO)
            Endif
        SX3->(DbSkip())
        End        



        /*
        //Título dos campos
        aCab   :=  {"Codigo", "Descricao" , "UM" }
        */


        cQuery := "SELECT * FROM "+RetSqlName(xAlias)
        cQuery += "  WHERE 1=1 "

        For n1 := 1 to Len(aFilt)

            If "$$" $ aFilt[n1]
                aFilInt := ACLONE(StrTokArr(aFilt[n1], "$$" ))
                cQuery += " AND "+aFilInt[1]+" LIKE '%"+aFilInt[2]+"%'"
            Else
                aFilInt := ACLONE(StrTokArr(aFilt[n1], "$" ))
                cQuery += " AND "+aFilInt[1]+"='"+aFilInt[2]+"'"
            EndIf
        Next n1

        If !Empty(xFilial(xAlias))
            cQuery += "  AND "+cFilCmp+" = '"+xFilial(xAlias)+"' "
        EndIf
        cQuery += "  AND D_E_L_E_T_ <> '*' "        


        cQuery := ChangeQuery(cQuery)

        //Antes de criar a tabela, verificar se a mesma já foi aberta
        If (Select("TMP") <> 0)
            dbSelectArea("TMP")
            TMP->(dbCloseArea ())
        Endif

        TCQUERY cQuery Alias TMP NEW

        //Item, Produto, Executado nao medido, executado, valor unitário

        If TMP->(EOF())

            ::SetResponse('{"erro":"Registro nao encontrado na Tabela:' +xAlias+' da Empresa/Filial '+cEmpAnt+cFilAnt+'."}') 
            Return .T.
        EndIF

        While TMP->(!EOF())    

            aLinha := ARRAY(TotCol)

            For n := 1 to TotCol
                If Type("TMP->"+aCabNom[n]) # "U"
                    aLinha[n] := Alltrim(&("TMP->"+aCabNom[n]))
                Else 
                    aLinha[n] := ""
                EndIf
            Next n

            AADD(aDados, aLinha)
        TMP->(DBSkip())
        End
        TMP->(DBCloseArea())





        cJson    += U_JSON( { xAlias , aCabNom, aDados} )

        cJson += "}"

        ::SetResponse(cJson)



Return(.T.)



//Função para Gerar Formato Json
User function JSON(aGeraXML)
Local cJSON  := ""                   
Local cTable := aGeraXML[1]                    
Local aCab   := aGeraXML[2]  
Local aLin   := aGeraXML[3]  

cJSON += '"'+cTable+'": [' 

FOR L:= 1 TO LEN( aLin )

    cJSON += '{'

    for C:= 1 to Len( aCab ) 

        IF VALTYPE(aLin[L][C]) = "C"  
           cConteudo := '"'+U_TIRACENTO(aLin[L][C])+'" '
        ELSEIF VALTYPE(aLin[L][C]) = "N"
            cConteudo := ALLTRIM(STR(aLin[L][C]))
        ELSEIF VALTYPE(aLin[L][C]) = "D"
            cConteudo := '"'+DTOC(aLin[L][C])+'"'
        ELSEIF VALTYPE(aLin[L][C]) = "L"
            cConteudo := IF(aLin[L][C], '"true"' , '"false"') 
        ELSE
            cConteudo := '"'+U_TIRACENTO(aLin[L][C])+'"'
        ENDIF               

        cJSON += '"'+aCab[C]+'":' + cConteudo

        IF C < LEN(aCab)
           cJSON += ','
        ENDIF

    Next C
    cJSON += '}'
    IF L < LEN(aLin)
       cJSON += ','
    ENDIF

Next

cJSON += ']'

Return cJSON
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do SigaOAdvpl!

1 resposta

Não é a resposta que estava procurando? Procure outras perguntas com as tags ou faça a sua própria pergunta.