CRUD em AdvPL – Parte 09

Introdução

Em cada post sobre o CRUD, vamos melhorando partes do código e acrescentando funcionalidade. Neste tópico, vamos acrescentar uma Busca de CEP na Internet, para fazer o preenchimento automático de alguns campos do endereço.

Botão de Consulta de CEP

Para disparar a busca, vamos aproveitar o valor preenchido no campo GET de CEP da Interface, adicionando um botão com o título “Buscar CEP”, porém vamos usar uma pré-validação do Botão — propriedade bWhen do Objeto, acessada pelo comando @…BUTTON através da instrução WHEN <condição>. Quando a expressão usada na condição do botão for verdadeira, o botão torna-se ativo. Caso contrário, ele é desativado. Vamos ao fonte:

(...)
@ 110,60 GET oGet8 VAR cCEP PICTURE "@R 99999-999" ;
   SIZE CALCSIZEGET(9),12 OF oPanelCrud PIXEL

// Habilita a busca de CEP com um botão do lado do GET
// O Botão somente está disponível caso o oGet8 ( campo CEP )
// estiver habilitado para edição
@ 110,110 BUTTON oBtnCEP PROMPT "Buscar CEP" SIZE 60,14 ;
   WHEN (oGet8:LACTIVE) ; 
   ACTION BuscaCEP(oDlg,aBtns,aGets) OF oPanelCrud PIXEL

// Novos campos inseridos em 07/10
(...)


Para que o botão de Busca de CEP somente esteja ativo quando o GET do CEP estiver ativo, usamos a propriedade lActive do objeto GET do CEP (oCep) como condição WHEN do botão.

Função BuscaCEP()

A função de busca de CEP vai verificar se o CEP digitado está completo, rodar uma segunda função para buscar os dados do endereço daquele CEP na Internet, e validar o retorno. Caso os dados sejam buscados com sucesso, o programa mostra os dados encontrados e pergunta se ele deve atualizar os campos de endereço do formulário com os dados obtidos. Vamos ao fonte:

/* ---------------------------------------------------
Botão para busca de CEP e preenchimento de campos 
de endereço automaticamente. 
--------------------------------------------------- */
Static Function BuscaCEP(oDlg,aBtns,aGets)
Local nPos , cCEP
Local cJsonCEP
Local oJsonObj
Local aJsonFields := {}
Local nRetParser := 0
Local oJHashMap
Local lOk
Local cCEPEnder := ''
Local cCEPBairro := ''
Local cCepCidade := ''
Local cCEPUF := ''
Local lCEPERRO := .F.

// Busca o campo CEP nos Gets e recupera o valor informado
nPos := ascan(aGets , {|x| x[1] == "CEP" } )
cCep := Eval(aGets[nPos][2]:bSetGet)
cCep := alltrim(cCep)

// Verifica se o valor informado está completo - 8 dígitos
IF len(cCEp) < 8
  MsgStop("Digite o número do CEP completo para a busca.","CEP Inválido ou incompleto")
  Return
Endif

// Busca o CEP usando uma API WEB
// Em caso de sucesso, a API retorna um JSON
// Em caso de falha, uam string vazia
cJsonCEP := WebGetCep(cCEP)

If !empty(cJsonCEP)
  // Caso o CEP tenha sido encontrado, chama o parser JSON
  oJsonObj := tJsonParser():New()
  // Faz o Parser da mensagem JSon e extrai para Array (aJsonfields)
  // e cria tambem um HashMap para os dados da mensagem (oJHM)
  lOk := oJsonObj:Json_Hash(cJsonCEP, len(cJsonCEP), @aJsonfields, @nRetParser, @oJHashMap)
  If ( !Lok )
    MsgStop(cJsonCEP,"Falha ao identificar CEP",cCEP)
  Else
    // Obtem o valor dos campos usando o Hashmap gerado
    HMGet(oJHashMap, "erro", @lCEPERRO)
    if lCEPERRO
      MsgStop("CEP Inexistente na Base de Dados","Falha ao buscar CEP "+cCEP)
    Else
      HMGet(oJHashMap, "logradouro", @cCEPEnder)
      HMGet(oJHashMap, "bairro", @cCEPBairro)
      HMGet(oJHashMap, "localidade", @cCepCidade)
      HMGet(oJHashMap, "uf", @cCEPUF)
      cCEPEnder := padr(upper(cCEPEnder) ,50)
      cCEPBairro := padr(upper(cCEPBairro),30)
      cCepCidade := padr(upper(cCepCidade),40)
      cCEPUF := padr(Upper(cCEPUF) ,2)

      IF MsgYesNo("Endereço ... "+cCEPEnder + chr(10) + ;
        "Bairro ..... "+cCEPBairro + chr(10) + ;
        "Cidade ..... "+cCEPCidade+ chr(10) + ;
        "Estado ..... "+cCepUF+ chr(10) + ;
        "Deseja atualizar o formulário com estes dados?","CEP encontrado")

        nPos := ascan(aGets , {|x| x[1] == "ENDER" } )
        Eval(aGets[nPos][2]:bSetGet , cCEPEnder )
        nPos := ascan(aGets , {|x| x[1] == "BAIRR" } )
        Eval(aGets[nPos][2]:bSetGet , cCEPBAirro )
        nPos := ascan(aGets , {|x| x[1] == "CIDADE" } )
        Eval(aGets[nPos][2]:bSetGet , cCepCidade )
        nPos := ascan(aGets , {|x| x[1] == "UF" } )
        Eval(aGets[nPos][2]:bSetGet , cCepUF )
      Endif
    Endif
  Endif
  // Limpa os objetos utilizados
  FreeObj(oJsonObj)
  FreeObj(oJHashMap)
Endif
Return

A função WebGetCep() recebe como parâmetro o CEP a ser pesquisado, em formato cartactere. Ela será a responsável bor buscar o CEP na Internet, usando a API oferecida pelo site viacep.com.br — vide deetalhes nas referências no final desse post.

Em caso de indisponibilidade do serviço, a função WebGetCep() deve retornar uma string vazia. Caso contrário, ela retorna uma string em formato JSON, que modemos parsear usando uma classe nativa do AdvPL, que retorna um objeto HashMap, para acelerar a busca pelas informações desejadas. Como a API já tem um formato pré-definido de retorno, basta procurarmos as condições que nos interessam.

Função WebGetCep()

Essa aqui é a responsável pela “mágica” — a chamada da API WEB disponível através de um método GET em HTTP, usando a função HttpGet() do AdvPL, e tratando um possível retorno de erro. Vamos ao código:

STATIC Function WebGetCep(cCEP)
Local cUrl , cJsonRet
Local nCode , cMsg := ''
// Montando a URL de pesquisa
cUrl := 'http://viacep.com.br/ws/'+cCEP+'/json/'
// Buscando o CEP
cJsonRet := httpget(cUrl)
// Verificando retorno 
If empty(cJsonRet)
  nCode := HTTPGETSTATUS(@cMsg)
  MsgStop(cMsg+" ( HTTP STATUS = "+cValToChar(nCode)+" )","Falha na Busca de CEP")
Endif
Return cJsonRet

A função é bem simples, a requisição também, e o tratamento de erro mais ainda. Caso a requisição volte um conteúdo vazio, pode ser uma indisponibilidade do serviço ou da conexão com a internet, seja o que for, o status de erro é recuperado pela função HttpGetStatus().

Busca de CEP funcionando

Primeiro entramos na agenda, acionamos a consulta, mostramos um registro desejado e clicamos em “Alterar” :

CRUD - Busca CEP 1.png

Feito isso, vamos digitar um CEP, por exemplo 18603-730, e clicamos no botão “Buscar CEP”. Caso a busca de CEP tenha sido executada com sucesso, devemos ver na tela a seguinte mensagem:

CRUD - Busca CEP 2

Vamos confirmar a operação, clicando em “Yes”, e vamos ver como ficou a tela com os dados do contato — os dados destacados em vermelho foram alterados.

CRUD - Busca CEP 3

Agora, basta clicar em “Salvar” para persistir as alterações deste contato no Banco de Dados.  😀

Conclusão

Com um fonte modularizado, fica fácil acrescentar novas funcionalidades sem ter que virar o código original do avesso.  Nos próximos posts, vamos começar a separar o processamento dos dados, e tentar deixar as funcionalidades do código mais dinâmicas.

Agradeço novamente a audiência, e desejo a todos TERABYTES DE SUCESSO !!!

Referências

 

2 comentários sobre “CRUD em AdvPL – Parte 09

    • Opa, perfeitamente. Rapaz, nem sabia que o Framework tinha feito essa classe FWREST client. De qualquer modo, os fontes que eu monto para o Blog partem de um ambiente sem as funções do ERP, para usar apenas as funções e classes base do AdvPL 😀

      Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s