Atualização Automática de Moedas no Protheus

Atualização Automática de Moedas no Protheus

Sabe aquelas automações que facilitam a vida dos colaboradores da empresa, e ainda agregam valor ao nosso trabalho?

O nosso post de hoje, é exatamente sobre um desses tipos de automação. Iremos demonstrar como fazer uma customização para atualização automática de moedas no Protheus.

Algumas rotinas dos módulos de Comércio Exterior (SIGAEIC – SIGAEEC – SIGAECO – SIGAEDC – SIGAEFF) do Protheus, e até mesmo do Faturamento e do Financeiro, necessitam ter a moeda do sistema atualizada, para a correta execução de algumas rotinas.

Essa customização poderá ser colocada em um JOB, pode-se criar um botão na tela de Cadastro de Moedas (se tiver PE disponível para tanto), ou em qualquer rotina que desejar.

O WebService (WS) de cotações de moedas do Banco Central, disponibiliza vários métodos, nos quais é possível recuperar os valores da moeda na data atual, recuperar valores em um determinado período de datas, recuperar cotações de várias moedas ao mesmo tempo em um período determinado, etc.

Na nossa customização, iremos utilizar o método “getUltimoValorXML”, o qual iremos passar o código da moeda que desejamos, e o mesmo irá nos retornar a cotação mais atual, no formato XML.

A primeira coisa que precisamos fazer, é construir o WsClient. Essa tarefa é muito fácil de fazer, já que, pelo próprio ToTvs Developer Studio (TDS), informamos a URL do WSDL, e o TDS faz o “trabalho pesado”, criando todo o fonte necessário para uso do WS.

Caso não saiba como consumir um WSDL para criação de um WsClient no TDS, basta conferir o nosso post, ensinando passo a passo, tal procedimento. Para tanto, clique aqui.

Após o TDS criar o WsClient para atualização automática de moedas no Protheus, teremos um fonte com a seguinte estrutura:

#INCLUDE "PROTHEUS.CH"
#INCLUDE "APWEBSRV.CH"

/* ===============================================================================
WSDL Location    https://www3.bcb.gov.br/sgspub/JSP/sgsgeral/FachadaWSSGS.wsdl
Gerado em        12/27/17 14:28:34
Observações      Código-Fonte gerado por ADVPL WSDL Client 1.120703
                 Alterações neste arquivo podem causar funcionamento incorreto
                 e serão perdidas caso o código-fonte seja gerado novamente.
=============================================================================== */

User Function _EWGQNCN ; Return  // "dummy" function - Internal Use 

/* -------------------------------------------------------------------------------
WSDL Service WSFachadaWSSGSService
------------------------------------------------------------------------------- */

WSCLIENT WSFachadaWSSGSService

  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD RESET
  WSMETHOD CLONE
  WSMETHOD getValoresSeriesVO
  WSMETHOD getUltimosValoresSerieVO
  WSMETHOD getValoresSeriesXML
  WSMETHOD getUltimoValorVO
  WSMETHOD getUltimoValorXML
  WSMETHOD getValor
  WSMETHOD getValorEspecial

  WSDATA   _URL                      AS String
  WSDATA   _CERT                     AS String
  WSDATA   _PRIVKEY                  AS String
  WSDATA   _PASSPHRASE               AS String
  WSDATA   _HEADOUT                  AS Array of String
  WSDATA   _COOKIES                  AS Array of String
  WSDATA   oWSgetValoresSeriesVOin0  AS FachadaWSSGSService_ArrayOfflong
  WSDATA   cin1                      AS string
  WSDATA   cin2                      AS string
  WSDATA   oWSgetValoresSeriesVOReturn AS FachadaWSSGSService_ArrayOffWSSerieVO
  WSDATA   nin0                      AS long
  WSDATA   oWSgetUltimosValoresSerieVOReturn AS FachadaWSSGSService_WSSerieVO
  WSDATA   oWSgetValoresSeriesXMLin0 AS FachadaWSSGSService_ArrayOfflong
  WSDATA   cgetValoresSeriesXMLReturn AS string
  WSDATA   oWSgetUltimoValorVOReturn AS FachadaWSSGSService_WSSerieVO
  WSDATA   cgetUltimoValorXMLReturn  AS string
  WSDATA   ngetValorReturn           AS decimal
  WSDATA   ngetValorEspecialReturn   AS decimal

ENDWSCLIENT

WSMETHOD NEW WSCLIENT WSFachadaWSSGSService
::Init()
If !FindFunction("XMLCHILDEX")
  UserException("O Código-Fonte Client atual requer os executáveis do Protheus Build [7.00.131227A-20171123 NG] ou superior. Atualize o Protheus ou gere o Código-Fonte novamente utilizando o Build atual.")
EndIf
Return Self

WSMETHOD INIT WSCLIENT WSFachadaWSSGSService
  ::oWSgetValoresSeriesVOin0 := FachadaWSSGSService_ARRAYOFFLONG():New()
  ::oWSgetValoresSeriesVOReturn := FachadaWSSGSService_ARRAYOFFWSSERIEVO():New()
  ::oWSgetUltimosValoresSerieVOReturn := FachadaWSSGSService_WSSERIEVO():New()
  ::oWSgetValoresSeriesXMLin0 := FachadaWSSGSService_ARRAYOFFLONG():New()
  ::oWSgetUltimoValorVOReturn := FachadaWSSGSService_WSSERIEVO():New()
Return

WSMETHOD RESET WSCLIENT WSFachadaWSSGSService
  ::oWSgetValoresSeriesVOin0 := NIL 
  ::cin1               := NIL 
  ::cin2               := NIL 
  ::oWSgetValoresSeriesVOReturn := NIL 
  ::nin0               := NIL 
  ::oWSgetUltimosValoresSerieVOReturn := NIL 
  ::oWSgetValoresSeriesXMLin0 := NIL 
  ::cgetValoresSeriesXMLReturn := NIL 
  ::oWSgetUltimoValorVOReturn := NIL 
  ::cgetUltimoValorXMLReturn := NIL 
  ::ngetValorReturn    := NIL 
  ::ngetValorEspecialReturn := NIL 
  ::Init()
Return

WSMETHOD CLONE WSCLIENT WSFachadaWSSGSService
Local oClone := WSFachadaWSSGSService():New()
  oClone:_URL          := ::_URL 
  oClone:_CERT         := ::_CERT 
  oClone:_PRIVKEY      := ::_PRIVKEY 
  oClone:_PASSPHRASE   := ::_PASSPHRASE 
  oClone:oWSgetValoresSeriesVOin0 :=  IIF(::oWSgetValoresSeriesVOin0 = NIL , NIL ,::oWSgetValoresSeriesVOin0:Clone() )
  oClone:cin1          := ::cin1
  oClone:cin2          := ::cin2
  oClone:oWSgetValoresSeriesVOReturn :=  IIF(::oWSgetValoresSeriesVOReturn = NIL , NIL ,::oWSgetValoresSeriesVOReturn:Clone() )
  oClone:nin0          := ::nin0
  oClone:oWSgetUltimosValoresSerieVOReturn :=  IIF(::oWSgetUltimosValoresSerieVOReturn = NIL , NIL ,::oWSgetUltimosValoresSerieVOReturn:Clone() )
  oClone:oWSgetValoresSeriesXMLin0 :=  IIF(::oWSgetValoresSeriesXMLin0 = NIL , NIL ,::oWSgetValoresSeriesXMLin0:Clone() )
  oClone:cgetValoresSeriesXMLReturn := ::cgetValoresSeriesXMLReturn
  oClone:oWSgetUltimoValorVOReturn :=  IIF(::oWSgetUltimoValorVOReturn = NIL , NIL ,::oWSgetUltimoValorVOReturn:Clone() )
  oClone:cgetUltimoValorXMLReturn := ::cgetUltimoValorXMLReturn
  oClone:ngetValorReturn := ::ngetValorReturn
  oClone:ngetValorEspecialReturn := ::ngetValorEspecialReturn
Return oClone

// WSDL Method getValoresSeriesVO of Service WSFachadaWSSGSService

WSMETHOD getValoresSeriesVO WSSEND oWSgetValoresSeriesVOin0,cin1,cin2 WSRECEIVE oWSgetValoresSeriesVOReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getValoresSeriesVO xmlns:q1="http://publico.ws.casosdeuso.sgs.pec.bcb.gov.br">'
cSoap += WSSoapValue("in0", ::oWSgetValoresSeriesVOin0, oWSgetValoresSeriesVOin0 , "ArrayOfflong", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in1", ::cin1, cin1 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in2", ::cin2, cin2 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getValoresSeriesVO>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::oWSgetValoresSeriesVOReturn:SoapRecv( WSAdvValue( oXmlRet,"_GETVALORESSERIESVORETURN","ArrayOffWSSerieVO",NIL,NIL,NIL,"O",NIL,NIL) )

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getUltimosValoresSerieVO of Service WSFachadaWSSGSService

WSMETHOD getUltimosValoresSerieVO WSSEND nin0,nin1 WSRECEIVE oWSgetUltimosValoresSerieVOReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getUltimosValoresSerieVO xmlns:q1="http://publico.ws.casosdeuso.sgs.pec.bcb.gov.br">'
cSoap += WSSoapValue("in0", ::nin0, nin0 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in1", ::nin1, nin1 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getUltimosValoresSerieVO>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::oWSgetUltimosValoresSerieVOReturn:SoapRecv( WSAdvValue( oXmlRet,"_GETULTIMOSVALORESSERIEVORETURN","WSSerieVO",NIL,NIL,NIL,"O",NIL,NIL) )

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getValoresSeriesXML of Service WSFachadaWSSGSService

WSMETHOD getValoresSeriesXML WSSEND oWSgetValoresSeriesXMLin0,cin1,cin2 WSRECEIVE cgetValoresSeriesXMLReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getValoresSeriesXML xmlns:q1="http://publico.ws.casosdeuso.sgs.pec.bcb.gov.br">'
cSoap += WSSoapValue("in0", ::oWSgetValoresSeriesXMLin0, oWSgetValoresSeriesXMLin0 , "ArrayOfflong", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in1", ::cin1, cin1 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in2", ::cin2, cin2 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getValoresSeriesXML>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::cgetValoresSeriesXMLReturn :=  WSAdvValue( oXmlRet,"_GETVALORESSERIESXMLRETURN","string",NIL,NIL,NIL,"S",NIL,NIL) 

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getUltimoValorVO of Service WSFachadaWSSGSService

WSMETHOD getUltimoValorVO WSSEND nin0 WSRECEIVE oWSgetUltimoValorVOReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getUltimoValorVO xmlns:q1="http://www.w3.org/2001/XMLSchema">'
cSoap += WSSoapValue("in0", ::nin0, nin0 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getUltimoValorVO>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::oWSgetUltimoValorVOReturn:SoapRecv( WSAdvValue( oXmlRet,"_GETULTIMOVALORVORETURN","WSSerieVO",NIL,NIL,NIL,"O",NIL,NIL) )

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getUltimoValorXML of Service WSFachadaWSSGSService

WSMETHOD getUltimoValorXML WSSEND nin0 WSRECEIVE cgetUltimoValorXMLReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getUltimoValorXML xmlns:q1="http://www.w3.org/2001/XMLSchema">'
cSoap += WSSoapValue("in0", ::nin0, nin0 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getUltimoValorXML>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::cgetUltimoValorXMLReturn :=  WSAdvValue( oXmlRet,"_GETULTIMOVALORXMLRETURN","string",NIL,NIL,NIL,"S",NIL,NIL) 

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getValor of Service WSFachadaWSSGSService

WSMETHOD getValor WSSEND nin0,cin1 WSRECEIVE ngetValorReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getValor xmlns:q1="http://publico.ws.casosdeuso.sgs.pec.bcb.gov.br">'
cSoap += WSSoapValue("in0", ::nin0, nin0 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in1", ::cin1, cin1 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getValor>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::ngetValorReturn    :=  WSAdvValue( oXmlRet,"_GETVALORRETURN","decimal",NIL,NIL,NIL,"N",NIL,NIL) 

END WSMETHOD

oXmlRet := NIL
Return .T.

// WSDL Method getValorEspecial of Service WSFachadaWSSGSService

WSMETHOD getValorEspecial WSSEND nin0,cin1,cin2 WSRECEIVE ngetValorEspecialReturn WSCLIENT WSFachadaWSSGSService
Local cSoap := "" , oXmlRet

BEGIN WSMETHOD

cSoap += '<q1:getValorEspecial xmlns:q1="http://publico.ws.casosdeuso.sgs.pec.bcb.gov.br">'
cSoap += WSSoapValue("in0", ::nin0, nin0 , "long", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in1", ::cin1, cin1 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += WSSoapValue("in2", ::cin2, cin2 , "string", .T. , .T. , 0 , NIL, .F.,.F.) 
cSoap += "</q1:getValorEspecial>"

oXmlRet := SvcSoapCall(	Self,cSoap,; 
  "",; 
  "RPCX","https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS",,,; 
  "https://www3.bcb.gov.br/wssgs/services/FachadaWSSGS")

::Init()
::ngetValorEspecialReturn :=  WSAdvValue( oXmlRet,"_GETVALORESPECIALRETURN","decimal",NIL,NIL,NIL,"N",NIL,NIL) 

END WSMETHOD

oXmlRet := NIL
Return .T.


// WSDL Data Structure ArrayOfflong

WSSTRUCT FachadaWSSGSService_ArrayOfflong
  WSDATA   nlong                     AS long OPTIONAL
  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD CLONE
  WSMETHOD SOAPSEND
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT FachadaWSSGSService_ArrayOfflong
  ::Init()
Return Self

WSMETHOD INIT WSCLIENT FachadaWSSGSService_ArrayOfflong
  ::nlong                := {} // Array Of  0
Return

WSMETHOD CLONE WSCLIENT FachadaWSSGSService_ArrayOfflong
  Local oClone := FachadaWSSGSService_ArrayOfflong():NEW()
  oClone:nlong                := IIf(::nlong <> NIL , aClone(::nlong) , NIL )
Return oClone

WSMETHOD SOAPSEND WSCLIENT FachadaWSSGSService_ArrayOfflong
  Local cSoap := ""
  aEval( ::nlong , {|x| cSoap := cSoap  +  WSSoapValue("long", x , x , "long", .F. , .T., 0 , NIL, .F.,.F.)  } ) 
Return cSoap

// WSDL Data Structure ArrayOffWSSerieVO

WSSTRUCT FachadaWSSGSService_ArrayOffWSSerieVO
  WSDATA   oWSWSSerieVO              AS FachadaWSSGSService_WSSerieVO OPTIONAL
  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD CLONE
  WSMETHOD SOAPRECV
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT FachadaWSSGSService_ArrayOffWSSerieVO
  ::Init()
Return Self

WSMETHOD INIT WSCLIENT FachadaWSSGSService_ArrayOffWSSerieVO
  ::oWSWSSerieVO         := {} // Array Of  FachadaWSSGSService_WSSERIEVO():New()
Return

WSMETHOD CLONE WSCLIENT FachadaWSSGSService_ArrayOffWSSerieVO
  Local oClone := FachadaWSSGSService_ArrayOffWSSerieVO():NEW()
  oClone:oWSWSSerieVO := NIL
  If ::oWSWSSerieVO <> NIL 
    oClone:oWSWSSerieVO := {}
    aEval( ::oWSWSSerieVO , { |x| aadd( oClone:oWSWSSerieVO , x:Clone() ) } )
  Endif 
Return oClone

WSMETHOD SOAPRECV WSSEND oResponse WSCLIENT FachadaWSSGSService_ArrayOffWSSerieVO
  Local nRElem1 , nTElem1
  Local aNodes1 := WSRPCGetNode(oResponse,.T.)
  ::Init()
  If oResponse = NIL ; Return ; Endif 
  nTElem1 := len(aNodes1)
  For nRElem1 := 1 to nTElem1 
    If !WSIsNilNode( aNodes1[nRElem1] )
      aadd(::oWSWSSerieVO , FachadaWSSGSService_WSSerieVO():New() )
  			::oWSWSSerieVO[len(::oWSWSSerieVO)]:SoapRecv(aNodes1[nRElem1])
    Endif
  Next
Return

// WSDL Data Structure WSSerieVO

WSSTRUCT FachadaWSSGSService_WSSerieVO
  WSDATA   nanoFim                   AS int OPTIONAL
  WSDATA   nanoInicio                AS int OPTIONAL
  WSDATA   caviso                    AS string OPTIONAL
  WSDATA   ndiaFim                   AS int OPTIONAL
  WSDATA   ndiaInicio                AS int OPTIONAL
  WSDATA   lespecial                 AS boolean OPTIONAL
  WSDATA   cfonte                    AS string OPTIONAL
  WSDATA   cfullName                 AS string OPTIONAL
  WSDATA   cgestorProprietario       AS string OPTIONAL
  WSDATA   nmesFim                   AS int OPTIONAL
  WSDATA   nmesInicio                AS int OPTIONAL
  WSDATA   cnomeAbreviado            AS string OPTIONAL
  WSDATA   cnomeCompleto             AS string OPTIONAL
  WSDATA   noid                      AS long OPTIONAL
  WSDATA   cperiodicidade            AS string OPTIONAL
  WSDATA   cperiodicidadeSigla       AS string OPTIONAL
  WSDATA   lpossuiBloqueios          AS boolean OPTIONAL
  WSDATA   lpublica                  AS boolean OPTIONAL
  WSDATA   cshortName                AS string OPTIONAL
  WSDATA   oWSultimoValor            AS FachadaWSSGSService_WSValorSerieVO OPTIONAL
  WSDATA   cunidadePadrao            AS string OPTIONAL
  WSDATA   cunidadePadraoIngles      AS string OPTIONAL
  WSDATA   lvalorDiaNaoUtil          AS boolean OPTIONAL
  WSDATA   oWSvalores                AS FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO OPTIONAL
  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD CLONE
  WSMETHOD SOAPRECV
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT FachadaWSSGSService_WSSerieVO
  ::Init()
Return Self

WSMETHOD INIT WSCLIENT FachadaWSSGSService_WSSerieVO
Return

WSMETHOD CLONE WSCLIENT FachadaWSSGSService_WSSerieVO
  Local oClone := FachadaWSSGSService_WSSerieVO():NEW()
  oClone:nanoFim              := ::nanoFim
  oClone:nanoInicio           := ::nanoInicio
  oClone:caviso               := ::caviso
  oClone:ndiaFim              := ::ndiaFim
  oClone:ndiaInicio           := ::ndiaInicio
  oClone:lespecial            := ::lespecial
  oClone:cfonte               := ::cfonte
  oClone:cfullName            := ::cfullName
  oClone:cgestorProprietario  := ::cgestorProprietario
  oClone:nmesFim              := ::nmesFim
  oClone:nmesInicio           := ::nmesInicio
  oClone:cnomeAbreviado       := ::cnomeAbreviado
  oClone:cnomeCompleto        := ::cnomeCompleto
  oClone:noid                 := ::noid
  oClone:cperiodicidade       := ::cperiodicidade
  oClone:cperiodicidadeSigla  := ::cperiodicidadeSigla
  oClone:lpossuiBloqueios     := ::lpossuiBloqueios
  oClone:lpublica             := ::lpublica
  oClone:cshortName           := ::cshortName
  oClone:oWSultimoValor       := IIF(::oWSultimoValor = NIL , NIL , ::oWSultimoValor:Clone() )
  oClone:cunidadePadrao       := ::cunidadePadrao
  oClone:cunidadePadraoIngles := ::cunidadePadraoIngles
  oClone:lvalorDiaNaoUtil     := ::lvalorDiaNaoUtil
  oClone:oWSvalores           := IIF(::oWSvalores = NIL , NIL , ::oWSvalores:Clone() )
Return oClone

WSMETHOD SOAPRECV WSSEND oResponse WSCLIENT FachadaWSSGSService_WSSerieVO
  Local oNode20
  Local oNode24
  ::Init()
  If oResponse = NIL ; Return ; Endif 
  ::nanoFim            :=  WSAdvValue( oResponse,"_ANOFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::nanoInicio         :=  WSAdvValue( oResponse,"_ANOINICIO","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::caviso             :=  WSAdvValue( oResponse,"_AVISO","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::ndiaFim            :=  WSAdvValue( oResponse,"_DIAFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::ndiaInicio         :=  WSAdvValue( oResponse,"_DIAINICIO","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::lespecial          :=  WSAdvValue( oResponse,"_ESPECIAL","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  ::cfonte             :=  WSAdvValue( oResponse,"_FONTE","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::cfullName          :=  WSAdvValue( oResponse,"_FULLNAME","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::cgestorProprietario :=  WSAdvValue( oResponse,"_GESTORPROPRIETARIO","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::nmesFim            :=  WSAdvValue( oResponse,"_MESFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::nmesInicio         :=  WSAdvValue( oResponse,"_MESINICIO","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::cnomeAbreviado     :=  WSAdvValue( oResponse,"_NOMEABREVIADO","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::cnomeCompleto      :=  WSAdvValue( oResponse,"_NOMECOMPLETO","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::noid               :=  WSAdvValue( oResponse,"_OID","long",NIL,NIL,NIL,"N",NIL,NIL) 
  ::cperiodicidade     :=  WSAdvValue( oResponse,"_PERIODICIDADE","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::cperiodicidadeSigla :=  WSAdvValue( oResponse,"_PERIODICIDADESIGLA","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::lpossuiBloqueios   :=  WSAdvValue( oResponse,"_POSSUIBLOQUEIOS","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  ::lpublica           :=  WSAdvValue( oResponse,"_PUBLICA","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  ::cshortName         :=  WSAdvValue( oResponse,"_SHORTNAME","string",NIL,NIL,NIL,"S",NIL,NIL) 
  oNode20 :=  WSAdvValue( oResponse,"_ULTIMOVALOR","WSValorSerieVO",NIL,NIL,NIL,"O",NIL,NIL) 
  If oNode20 != NIL
    ::oWSultimoValor := FachadaWSSGSService_WSValorSerieVO():New()
    ::oWSultimoValor:SoapRecv(oNode20)
  EndIf
  ::cunidadePadrao     :=  WSAdvValue( oResponse,"_UNIDADEPADRAO","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::cunidadePadraoIngles :=  WSAdvValue( oResponse,"_UNIDADEPADRAOINGLES","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::lvalorDiaNaoUtil   :=  WSAdvValue( oResponse,"_VALORDIANAOUTIL","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  oNode24 :=  WSAdvValue( oResponse,"_VALORES","ArrayOf_tns2_WSValorSerieVO",NIL,NIL,NIL,"O",NIL,NIL) 
  If oNode24 != NIL
    ::oWSvalores := FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO():New()
    ::oWSvalores:SoapRecv(oNode24)
  EndIf
Return

// WSDL Data Structure WSValorSerieVO

WSSTRUCT FachadaWSSGSService_WSValorSerieVO
  WSDATA   nano                      AS int OPTIONAL
  WSDATA   nanoFim                   AS int OPTIONAL
  WSDATA   lbloqueado                AS boolean OPTIONAL
  WSDATA   lbloqueioLiberado         AS boolean OPTIONAL
  WSDATA   ndia                      AS int OPTIONAL
  WSDATA   ndiaFim                   AS int OPTIONAL
  WSDATA   nmes                      AS int OPTIONAL
  WSDATA   nmesFim                   AS int OPTIONAL
  WSDATA   noid                      AS long OPTIONAL
  WSDATA   noidSerie                 AS long OPTIONAL
  WSDATA   csvalor                   AS string OPTIONAL
  WSDATA   nvalor                    AS decimal OPTIONAL
  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD CLONE
  WSMETHOD SOAPRECV
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT FachadaWSSGSService_WSValorSerieVO
  ::Init()
Return Self

WSMETHOD INIT WSCLIENT FachadaWSSGSService_WSValorSerieVO
Return

WSMETHOD CLONE WSCLIENT FachadaWSSGSService_WSValorSerieVO
  Local oClone := FachadaWSSGSService_WSValorSerieVO():NEW()
  oClone:nano                 := ::nano
  oClone:nanoFim              := ::nanoFim
  oClone:lbloqueado           := ::lbloqueado
  oClone:lbloqueioLiberado    := ::lbloqueioLiberado
  oClone:ndia                 := ::ndia
  oClone:ndiaFim              := ::ndiaFim
  oClone:nmes                 := ::nmes
  oClone:nmesFim              := ::nmesFim
  oClone:noid                 := ::noid
  oClone:noidSerie            := ::noidSerie
  oClone:csvalor              := ::csvalor
  oClone:nvalor               := ::nvalor
Return oClone

WSMETHOD SOAPRECV WSSEND oResponse WSCLIENT FachadaWSSGSService_WSValorSerieVO
  ::Init()
  If oResponse = NIL ; Return ; Endif 
  ::nano               :=  WSAdvValue( oResponse,"_ANO","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::nanoFim            :=  WSAdvValue( oResponse,"_ANOFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::lbloqueado         :=  WSAdvValue( oResponse,"_BLOQUEADO","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  ::lbloqueioLiberado  :=  WSAdvValue( oResponse,"_BLOQUEIOLIBERADO","boolean",NIL,NIL,NIL,"L",NIL,NIL) 
  ::ndia               :=  WSAdvValue( oResponse,"_DIA","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::ndiaFim            :=  WSAdvValue( oResponse,"_DIAFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::nmes               :=  WSAdvValue( oResponse,"_MES","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::nmesFim            :=  WSAdvValue( oResponse,"_MESFIM","int",NIL,NIL,NIL,"N",NIL,NIL) 
  ::noid               :=  WSAdvValue( oResponse,"_OID","long",NIL,NIL,NIL,"N",NIL,NIL) 
  ::noidSerie          :=  WSAdvValue( oResponse,"_OIDSERIE","long",NIL,NIL,NIL,"N",NIL,NIL) 
  ::csvalor            :=  WSAdvValue( oResponse,"_SVALOR","string",NIL,NIL,NIL,"S",NIL,NIL) 
  ::nvalor             :=  WSAdvValue( oResponse,"_VALOR","decimal",NIL,NIL,NIL,"N",NIL,NIL) 
Return

// WSDL Data Structure ArrayOf_tns2_WSValorSerieVO

WSSTRUCT FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO
  WSDATA   oWSWSValorSerieVO         AS FachadaWSSGSService_WSValorSerieVO OPTIONAL
  WSMETHOD NEW
  WSMETHOD INIT
  WSMETHOD CLONE
  WSMETHOD SOAPRECV
ENDWSSTRUCT

WSMETHOD NEW WSCLIENT FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO
  ::Init()
Return Self

WSMETHOD INIT WSCLIENT FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO
  ::oWSWSValorSerieVO    := {} // Array Of  FachadaWSSGSService_WSVALORSERIEVO():New()
Return

WSMETHOD CLONE WSCLIENT FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO
  Local oClone := FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO():NEW()
  oClone:oWSWSValorSerieVO := NIL
  If ::oWSWSValorSerieVO <> NIL 
    oClone:oWSWSValorSerieVO := {}
    aEval( ::oWSWSValorSerieVO , { |x| aadd( oClone:oWSWSValorSerieVO , x:Clone() ) } )
  Endif 
Return oClone

WSMETHOD SOAPRECV WSSEND oResponse WSCLIENT FachadaWSSGSService_ArrayOf_tns2_WSValorSerieVO
  Local nRElem1 , nTElem1
  Local aNodes1 := WSRPCGetNode(oResponse,.T.)
  ::Init()
  If oResponse = NIL ; Return ; Endif 
  nTElem1 := len(aNodes1)
  For nRElem1 := 1 to nTElem1 
    If !WSIsNilNode( aNodes1[nRElem1] )
      aadd(::oWSWSValorSerieVO , FachadaWSSGSService_WSValorSerieVO():New() )
  			::oWSWSValorSerieVO[len(::oWSWSValorSerieVO)]:SoapRecv(aNodes1[nRElem1])
    Endif
  Next
Return

Antes de construirmos o fonte que irá consumir o WsClient gerado pelo TDS, e atualizar a tabela de Cadastro de Moedas do Protheus, abaixo vamos listar os códigos da moedas suas respectivas descrições e o tipo de operação (venda e/ou compra).

Código da MoedaMoeda (Operação)
1Dólar (venda)
10813Dólar (compra)
21619Euro (venda)
21620Euro (compra)
21621Iene (venda)
21622Iene (compra)
21623Libra esterlina (venda)
21624Libra esterlina (compra)
21625Franco Suiço (venda)
21626Franco Suiço (compra)
21627Coroa Dinamarquesa (venda)
21628Coroa Dinamarquesa (compra)
21629Coroa Norueguesa (venda)
21630Coroa Norueguesa (compra)
21631Coroa Sueca (venda)
21632Coroa Sueca (compra)
21633Dólar Australiano (venda)
21634Dólar Australiano (compra)
21635Dólar Canadense (venda)
21636Dólar Canadense (compra)

Agora que já temos os códigos das moedas com suas respectivas operações, podemos construir nosso fonte.

No nosso exemplo, iremos utilizar o código 10813, que é relativo a moeda Dólar, para operação de compra.

Abaixo segue o código fonte, o qual instanciámos o objeto referente ao WsClient, que irá consumir o WS do Banco Central e efetuar atualização automática de moedas no Protheus:

#Include 'Protheus.ch'

User Function CotacaoMoedas()

  //Variaveis Locais
  Local oCotacaoMoedas 	:= Nil
  Local cRetCotMoeda 		:= ""
  Local cAvisos			:= ""
  Local cErros			:= ""
  Local cReplace			:= ""
  Local oXMLCotMoeda		:= Nil
  Local dDataCotacao		:= StoD("")	
  Local nCotacaoMoeda		:= 0
  Local lAtzDolar			:= .F.

  //Instanciacao do WsClient de Moeda do Fonte WCCotacaoMoedas.prw
  oCotacaoMoedas 	:= WSFachadaWSSGSService():New()

  //Setado o Codigo 10813 respectivo ao Dolar (Compra)
  oCotacaoMoedas:nin0 := 10813

  //Verificamos se o metodo getUltimoValorXML do WsClient WSFachadaWSSGSService foi consumido com sucesso
  If (oCotacaoMoedas:getUltimoValorXML())

    //Obtem o retorno de cotacao da Moeda no formato XML
    cRetCotMoeda := oCotacaoMoedas:cgetUltimoValorXMLReturn 

    //Utiliza a funcao XmlParser para converter o retorno XML do WS para uma variavel do Tipo Objeto
    oXMLCotMoeda :=  XmlParser(cRetCotMoeda, cReplace, @cErros, @cAvisos)	

    //Verifica se houve erro ao consumir o WS
    If AllTrim(cErros) == ""
      //Obtem a Data da Ultima Cotacao
      dDataCotacao := StoD(oXMLCotMoeda:_RESPOSTA:_SERIE:_DATA:_ANO:TEXT + oXMLCotMoeda:_RESPOSTA:_SERIE:_DATA:_MES:TEXT + oXMLCotMoeda:_RESPOSTA:_SERIE:_DATA:_DIA:TEXT)

      //Obtem o Valor da Ultima Cotacao
      nCotacaoMoeda := Val(StrTran(oXMLCotMoeda:_RESPOSTA:_SERIE:_VALOR:TEXT, ",", "."))

      //Abre o Ordena a Tabela de Moedas - SM2
      DBSelectArea("SM2")
      SM2->(DBSetOrder(1))

      //Verifaca se ja existe ou nao, a Cotacao na Data obtida no consumo do WS
      IIF(DBSeek(FWFilial("SM2") + DtoS(dDataCotacao)),  RecLock("SM2", .F.), RecLock("SM2", .T.)) 

      //Atualiza a Data, Valor (no caso o Dolar e a Moeda 2, mas isso depende da configuracao), e a nao abertura da Tela de Cotacao na entrada do sistema
      SM2->M2_DATA	:= dDataCotacao
      SM2->M2_MOEDA2	:= nCotacaoMoeda
      SM2->M2_INFORM	:= "S"

      //Libera o registro alterado
      SM2->(MsUnLock())

      //Operacao realizada com sucesso
      lAtzDolar := .T.

    EndIf

  EndIf

Return (lAtzDolar)

No nosso código em questão, estamos utilizando a atualização da Tabela SM2 (Moedas do Sistema). Dependendo do módulo utilizado, faz-se necessário a atualização de outras tabelas. O conceito para atualizar as outras tabelas, é o mesmo do fonte acima.

Para realizar o download dos fontes utilizados para realizar a atualização automática de moedas no Protheus, e verificar o endereço do WS de cotações de moedas do Banco Central, basta acessar abaixo, a nossa seção “Anexos”.

Como podemos verificar nesse post, a atualização automática de moedas no Protheus, é muito simples de fazer, porém agrega muito valor ao trabalho do analista.

Caso ainda não tenham se inscrito no Canal Smart Siga, ou em nossas mídias sociais, aproveitem para se cadastrar agora, pois assim, vocês recebem em primeira mão, todas as novidades do nosso site.

Aproveitem também, para ingressar em nosso Canal do Smart Siga no Telegram. Para tanto acessem: https://t.me/smartsiga.

Espero que vocês tenham gostado do nosso post, e que o nosso site esteja ajudando os nossos amigos analista.

E por hoje é só pessoal!!!

Abraços e até a próxima.

Anexos


Anexo 01: Para realizar o download do fonte WsClient, que consome o WS do Banco Central, diretamente do GitHub do Smart Siga, clique aqui;

Anexo 02: Para realizar o download do fonte de atualização automática de moedas no Protheus, diretamente do GitHub do Smart Siga, clique aqui;

Anexo 03: O endereço do WebService de cotações de moedas do Banco Central do Brasil é o seguinte: https://www3.bcb.gov.br/sgspub/JSP/sgsgeral/FachadaWSSGS.wsdl.


Smart Siga - TI Inteligente

 


Referências:

Banco Central do Brasil
Blog do Tiago Crizanto
Compartilhe:
  •  
  •  
  •  

8 thoughts on “Atualização Automática de Moedas no Protheus

  1. Olá Christian,

    Muito o legal este post, que, com certeza irá facilitar a vida de muitos usuários.

    Senti falta apenas da informação da URL no formato WSDL para criar o Client pelo TDS, pois se informarmos a URL descrita no fonte no formado https://www3.bcb.gov.br/sgspub/JSP/sgsgeral/FachadaWSSGS.wsdl o TDS acusa o seguinte erro: “Verifique a URL contendo o serviço. Este serviço parece ser inválido”.

    Grande Abraço… Valeu!!!

    1. Boa Tarde Marcos,

      Primeiramente obrigado por acompanhar o nosso site.

      Realmente, faltou citar o endereço da WSDL do post.

      Já fizemos a correção, obrigado por nos avisar.

      A WSDL citada por você no comentário, está correta.

      Verificou, se de repente seu Firewall não está bloqueando o acesso a mesma?

      Se você digitar a WSDL no navegador, consegue fazer o download da mesma? Se sim, pode usar o arquivo para importar a estrutura através da opção “Remoto”, ao criar o WsClient.

      Obrigado e qualquer dúvida estamos a disposição.

      Att,

      Smart Siga
      TI Inteligente

      1. Ok Cristian,

        Está tudo certo… Sim, eu consego fazer o download normalmente pelo browser e testando a criação do WsClient pelo DevStudio (IDE) não ocorreu nenhum erro.

        Me chamou a atenção sua observação para informar o Tipo “Remoto”, pois eu não encontrei esta opção em meu TDS.

        Só então me dei conta de que estava utilizando a versão 11.2 do TDS que não tem essa opção, mas ao utilizar a versão 11.3 com o Tipo “Remoto” a URL foi carregada sem nenhum problema.

        Muito obrigado pelo retorno e mais uma vez parabéns pelo post.

        Até mais.

        1. Boa Tarde Marcos,

          Que bom que deu tudo certo, e que o nosso site esteja te ajudando.

          Continue nos acompanhando.

          Abraços.

          Smart Siga
          TI Inteligente

    1. Bom dia Fernando.

      Obrigado por acompanhar o Smart Siga.

      Em caso de feriados ou finais de semana, o WebService (WS) sempre retornará o valor do último dia útil.

      Por exemplo; No caso de sábado e/ou domingo retornará o valor da sexta-feria. Se um feriado, cair em uma quarta-feria, e você consultar o WS, o mesmo retornará o valor de terça-feira.

      Abs,

      Smart Siga
      TI Inteligente

  2. Eu acabei tendo um problema com o código como está.
    O retorno da data do xml vinha sem o zero no dia e no mês, resultando em uma string tipo: 201835 ao invés de 20180305.
    Não sei se isso é alguma configuração do meu servidor aqui, mas caso alguém esteja com problemas, vale a pena conferir.

Deixe uma resposta

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

Seja um Analista VIP!!!

Recebe em primeira mão as novidades do Canal Smart Siga, além de conteúdos exclusivos.