Objetivo
Possibilitar acesso aos modelos de dados de usuário do Protheus através de API RESTFul.
Pré-requisitos
Requisitos Mínimos
Para utilizar certifique-se que:
* Para atualização do ambiente, consulte nossa Central de Download no endereço: http://www.totvs.com.br/suporte
Como utilizar
Os modelos de dados devem ser publicados para serem acessíveis através da API, para isso deve-se utilizar o seguinte comando:
Obs: Cada modelo deverá ser publicado utilizando esse comando. Não é necessário estar no mesmo fonte do modelo de dados.
NAME = Nome da API que representará o modelo de dados.
SOURCE = Fonte aonde está o modelo de dados (função modeldef), caso esse comando não for informado, será acatado o fonte atual. (Não é obrigatório)
RESOURCE OBJECT = Classe que deverá herdar da FwRestModel. (Não é obrigatório)
Com este comando os modelos de dados serão acessíveis através do seguinte endereço: <protocol>://<server>:<port>/fwmodel/<name of published model>/<PK>
Exemplo: http://localhost:8084/fwmodel/products
Parametros
<Name of published model> = Nome o modelo informado no comando
<PK> = Valor da chave primaria do alias do modelo em encodado em base64 (Opcional)
Classe FWRestModel (link: FWRestModelObject.prx)
Utilização
Esta API segue o padrão de REST.
Por exemplo:
Para retornar a lista de registros referente ao modelo de dados deve-se efetuar um GET sem informar a <PK>. Os registros listados terão filtrados pelas filiais que o usuário tem acesso (isso se o campo filial existir.)
Para inserir um registro deve-se efetuar um POST sem informar a <PK> e enviar no body o conteúdo a ser inserido.
Ao informar o parâmetro <PK> será acessado um registro em específico e assim podendo ser utilizado os métodos GET, PUT, DELETE.
QueryStrings
COUNT = Quantidade de registro que devem ser retornados (padrão: 10)
STARTINDEX = Indica a partir que qual index deverá ser retornado (padrão: 1)
FILTER = Filtro que será aplicado no método SetFilter()
FIELDDETAIL = Habilita mostrar mais informações nos campos do modelo (padrão: 10)
FIELDVIRTUAL = Habilita o retorno de campos virtuais (padrão: false)
FIELDEMPTY = Habilita o retorno de campos sem valores (padrão: false)
FIRSTLEVEL = Habilita o retorno dos sub modelos (padrão: true)
FIELDS = Indica os campos a serem filtrados no retorno do modelo, incluindo os sub modelos, caso não informado todos os campos serão retornados
DEBUG = Valor booleano para habilitar o modo debug (padrão: false)
CACHE = Indica se sera feito cache do total de registros por alias, refere-se ao valor do total no retorno (padrão: true)
INTERNALID = Indica se deve retornar o ID(Recno) como informação complementar das linhas do GRID (padrão: false)
Exemplo de utilização
Ao publicar um modelo de dados, se o mesmo utilizar alias, basta publicá-lo.
Caso o modelo tenha sido desenvolvido utilizando array ou carga manual, deve-se criar uma classe e herda-la da FwRestModel e sobrescrever os métodos necessários para atender a sua necessidade.
Exemplo de modelo de dados de usuário com customização da classe REST:
#INCLUDE "TOTVS.CH" #INCLUDE "FWMVCDEF.CH" PUBLISH USER MODEL REST NAME Branch RESOURCE OBJECT oRestBranch Class oRestBranch From FwRestModel Data lSm0Closed Method Activate() Method DeActivate() Method Total() Method SetAlias() Method Skip() Method Seek() EndClass Method Activate() Class oRestBranch self:lSm0Closed := .F. If Select("SM0") == 0 self:lSm0Closed := .T. OpenSm0(, .F.) EndIf Return _Super:Activate() Method DeActivate() Class oRestBranch If self:lSm0Closed SM0->(dbCloseArea()) EndIf Return _Super:DeActivate() Method Total() Class oRestBranch Local nRecno := SM0->(Recno()) Local nTotal := 0 If self:Seek() While !SM0->(Eof()) nTotal++ self:Skip() End EndIf SM0->(dbGoTo(nRecno)) Return nTotal Method SetAlias() Class oRestBranch self:cAlias := "SM0" Return .T. Method Skip(nSkip) Class oRestBranch Local lRet := .F. SM0->(DbSkip(nSkip)) lRet := !SM0->(Eof()) Return lRet Method Seek(cPk) Class oRestBranch Local lRet := .F. If Empty(cPK) SM0->(DbGotop()) lRet := !SM0->(Eof()) Else cPK := SubStr(cPK, Len(xFilial("SM0")) + 1) // Removo o valor da filial que e inserido automaticamente pelo model no valor da PK. SM0->(dbSetOrder(1)) lRet := SM0->(DbSeek(cPK)) Endif Return lRet // MODELO DE DADOS Static Function Modeldef() Local oStruSM0 := DefStrModel() oModel := FWFormModel():New( 'MYFILIAL', {|| }, {|| }, {|| }, {|| } ) oModel:AddFields( 'SM0MASTER', , oStruSM0, {|| }, {|| },{|oM| MyLoad() }) oModel:SetDescription( "Empresas Protheus" ) oModel:GetModel( 'SM0MASTER' ):SetDescription( "Empresas Protheus" ) oModel:SetPrimaryKey( {"M0_CODIGO", "M0_CODFIL"} ) Return oModel Static Function DefStrModel() Local oStruct := FWFormModelStruct():New() Local bValid := { || .T.} Local bWhen := { || } Local bRelac := { || } // TABELA oStruct:AddTable( "SM0", {}, "Filiais", {|| }) // INDICES oStruct:AddIndex(1, "1", "M0_CODIGO", "Cód Empresa", "", "", .T.) // CAMPOS oStruct:AddField( "Cód Empresa" , "Cód Empresa" , "M0_CODIGO" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Cód Filial" , "Cód Filial" , "M0_CODFIL" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Nome Empresa" , "Nome Empresa" , "M0_NOMECOM", "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "CNPJ" , "CNPJ" , "M0_CGC" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "UF" , "UF" , "M0_ESTENT" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Insc Estadual" , "Insc Estadual" , "M0_INSC" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Insc Municipal", "Insc Municipal" , "M0_INSCM" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Cód Munic" , "Cód Munic" , "M0_CODMUN" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Nome Filial" , "Nome Filial" , "M0_FILIAL" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Município" , "Município" , "M0_CIDENT" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Inscrição" , "Inscrição" , "M0_INSCANT", "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "NIRE" , "NIRE" , "M0_NIRE" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "Data do Nire" , "Data do Nire" , "M0_DTRE" , "D", 08, 0, bValid, bWhen, , , bRelac, .F., , , ) oStruct:AddField( "End Cob" , "End Cob" , "M0_ENDCOB" , "C", 50, 0, bValid, bWhen, , , bRelac, .F., , , ) Return oStruct Static Function MyLoad() Local aRet := {} aRet := {{SM0->M0_CODIGO, SM0->M0_CODFIL, SM0->M0_NOMECOM, SM0->M0_CGC, SM0->M0_ESTENT, SM0->M0_INSC, SM0->M0_INSCM, SM0->M0_CODMUN,; SM0->M0_FILIAL, SM0->M0_CIDENT, SM0->M0_INSCANT, SM0->M0_NIRE, SM0->M0_DTRE, SM0->M0_ENDCOB}, ; SM0->(Recno())} Return aRet
Exemplo de alteração de registro utilizando API:
* A documentação da utilização da API RESTFul FWMODEL pode ser visualizada acessando a URL da mesma no seu servidor REST. Exemplo: http://localhost:9090/rest/index/FWMODEL
- Para alteração de registro, é recomendável (não obrigatório, dependendo da lógica do serviço do cliente) a utilização do PK Id. Para obter o PK de determinado registro, iremos efetuar um GET no endereço do servidor REST, utilizando o modelo de uma rotina do módulo jurídico (JURA068), para efeito de exemplo:
- Com o resultado, obtemos a listagem dos registros desse modelo/rotina (que no exemplo, é apenas 1 registro), e podemos observar qual é o PK deste registro ("pk": "ICAwMDEgIA=="). Vamos trazer agora para a tela apenas o JSON daquele registro, enviando o PK na URL:
- Em posse desta informação, a alteração do registro pode ser feita através do método PUT, enviando junto o PK na URL. Foi copiado todo o conteúdo do JSON de retorno anterior, e foi colado na opção "Body" da API, para que seja feita a alteração que será enviada (no caso, foi alterado o texto "Escritorio 001" para "Escritorio 002").
- Após essa alteração, ao efetuar novamente um GET para obter informações do servidor REST, notamos que o valor foi alterado corretamente.
Caracteres XML Reservados
Importante se atentar a utilização dos caracteres XML reservados, devendo estes serem tratados na origem conforme tabela abaixo para evitar erros de parser do XML.
Caractere reservado | Entidade nomeada |
---|---|
< | < |
> | > |
& | & |
" | " |
' | ' |