Pular para o conteúdo

Lógica de consulta de CEP via API

A API

Neste exemplo, usamos a API da ViaCEP. Para mais informações sobre a API, acesse a documentação no site viacep.com.br.

Tubes usados

Os principais tubes usados nesta lógica são: o APIGet e o cache. O tube APIGet é usado para fazer a requisição dos dados via API, enquanto o tube cache é usado para armazenar as informações recebidas do APIGet no cache do documento e, assim, evitar que haja novas requisições toda vez que o template é executado. Você pode obter mais informações sobre os tubes usados na documentação de cada tube.

Declarações

  • list[Uf]: É uma lista associativa dos Estados, cujas chaves são o nome do Estado, a sigla e respectiva preposição. O retorno da API de CEP é apenas a sigla do Estado. Com a lista associativa, podemos acessar também o nome completo e a preposição.
  • struct[STR_Endereco]: É a estrutura de endereço. Contém os fields:
  • [inputCEP]: recebe o input do usuário no formato XXXXX-XXX, que é formatado e atribuído ao field [cepSemTracos].
  • [cepSemTracos]: recebe o CEP no formato XXXXXXXX. Antes de realizar a atribuição, usamos o tube isNotEmpty para verificar se o usuário já preencheu o field [inputCEP] e evitar a execução do tube sem valores preenchidos. Utilizamos o tube replace para substituir o traço por uma string vazia. Além disso, usamos o field [cepSemTracos] no endpoint do APIGet e como key no <cepCacheConfig>.
  • [strInfoAPI]: estrutura que contém os fields retornados pela API de CEP. Nela temos o field [listaUF]. Note que o retorno da API (sigla do Estado) será contido na variável [uf] e, em seguida, utilizaremos uma sequência de ifs no loaders para atribuir corretamente o valor da lista [listaUF] para que possamos utilizar as respectivas informações relacionadas ao Estado (nome por extenso e preposições) ao longo do template.

Note também que o field que recebe o input do usuário está fora da estrutura principal. É preciso separar o field que recebe o input do usuário da estrutura que recebe as informações da API e é usada no tube cache. Caso contrário, o cache não irá atualizar as informações caso haja alguma alteração no [inputCEP].

+<strPrincipal> : Struct: Essa estrutura foi declarada apenas para simularmos a situação mais corriqueira, que é a estrutura de endereço dentro de outra estrutura de qualificação, por exemplo.

<cepCacheConfig>: Essa estrutura é usada para configurar o tube cache. Para mais informações, acesse a documentação do tube.

Lógica

Começamos analisando se há alteração no field [inputCEP] com o tube hasChanged. Isso é necessário para que toda vez que haja alterações no field a lógica seja executada novamente, o mesmo ocorre na primeira vez que o campo é preenchido.

if (<strPrincipal.strEndereco.inputCEP>.hasChanged())

O tube clear limpa todas as informações da [strInfoAPI] para que seja possível armazenar novas informações quando houver alterações.

<strPrincipal.strEndereco.strInfoAPI>.clear()

Dentro da estrutura de cache, o field [key] corresponderá ao field [cepSemTracos]. O CEP é usado como key para que a individualização de informações ocorra com o número de CEP.

<cepCacheConfig.key> = <strPrincipal.strEndereco.cepSemTracos>

Finalizamos com o uso do tube cache. Como a origem dos dados é o retorno do tube APIGet, usamos o APIGet dentro do parâmetro dataOrigin do tube cache.

cache(
<cepCacheConfig>, // cacheConfig
<strPrincipal.strEndereco.strInfoAPI>, // dataReceiver
APIGet(<strPrincipal.strEndereco.strInfoAPI>, null, "https://viacep.com.br/ws/" & <strPrincipal.strEndereco.cepSemTracos> & "/json/", "localidade:cidade, complemento:null") // dataOrigin
)

Template de exemplo

template[TEMP_API_CEP] {
metainfo {
language = "pt_BR"
name = "Lógica de CEP - APIGet e cache"
}
body {
declarations {
-<cepCacheConfig> : struct[CacheConfig] {
name = "CacheConfig"
fields {
+[key] : String {
name = "key"
default = "key1"
},
+[scope] : List("operand", "document", "template") {
name = "scope"
default = "operand"
atomic = true
},
+[secondsToExpire] : Integer {
name = "seconds"
default = 300
},
+[cacheVoid] : Boolean{
name = "cacheVoid"
default = false
}
}
},
list[Uf] {
name = "UF"
fields = {"Nome", "Sigla", "Preposição"}
options = (
{"São Paulo","SP","de"},
{"Acre","AC","do"},
{"Alagoas","AL","de"},
{"Amapá","AP","do"},
{"Amazonas","AM","do"},
{"Bahia","BA","da"},
{"Ceará","CE","do"},
{"Distrito Federal","DF","do"},
{"Espírito Santo","ES","do"},
{"Goiás","GO","de"},
{"Maranhão","MA","do"},
{"Mato Grosso","MT","de"},
{"Mato Grosso do Sul","MS","de"},
{"Minas Gerais","MG","de"},
{"Paraná","PR","do"},
{"Paraíba","PB","da"},
{"Pará","PA","do"},
{"Pernambuco","PE","de"},
{"Piauí","PI","do"},
{"Rio de Janeiro","RJ","do"},
{"Rio Grande do Norte","RN","do"},
{"Rio Grande do Sul","RS","do"},
{"Rondônia","RO","de"},
{"Roraima","RR","de"},
{"Santa Catarina","SC","de"},
{"Sergipe","SE","de"},
{"Tocantins","TO","do"}
)
type = "String"
},
struct[STR_Endereco] {
fields {
+[inputCEP] : String where ("\d\d\d\d\d-\d\d\d"){
name = "CEP"
},
-[cepSemTracos] : String,
+[strInfoAPI] : Struct {
name = "Logradouro"
fields {
-[cep] : String {
name = "CEP"
},
+[logradouro] : String {
name = "Logradouro"
},
&[numero] : String {
name = "Número"
},
&[complemento] : String {
name = "Complemento"
},
&[bairro] : String {
name = "Bairro"
},
+[cidade] : String {
name = "Cidade"
},
+[listaUF] : List[Uf] {
atomic = true
name = "Estado"
},
-[uf] : String
}
loaders {
if ([uf] == "SP") {[listaUF].default = "São Paulo"}
elseif ([uf] == "AC") {[listaUF].default = "Acre"}
elseif ([uf] == "AL") {[listaUF].default = "Alagoas"}
elseif ([uf] == "AP") {[listaUF].default = "Amapá"}
elseif ([uf] == "AM") {[listaUF].default = "Amazonas"}
elseif ([uf] == "BA") {[listaUF].default = "Bahia"}
elseif ([uf] == "CE") {[listaUF].default = "Ceará"}
elseif ([uf] == "DF") {[listaUF].default = "Distrito Federal"}
elseif ([uf] == "ES") {[listaUF].default = "Espírito Santo"}
elseif ([uf] == "GO") {[listaUF].default = "Goiás"}
elseif ([uf] == "MA") {[listaUF].default = "Maranhão"}
elseif ([uf] == "MT") {[listaUF].default = "Mato Grosso"}
elseif ([uf] == "MS") {[listaUF].default = "Mato Grosso do Sul"}
elseif ([uf] == "MG") {[listaUF].default = "Minas Gerais"}
elseif ([uf] == "PR") {[listaUF].default = "Paraná"}
elseif ([uf] == "PB") {[listaUF].default = "Paraíba"}
elseif ([uf] == "PA") {[listaUF].default = "Pará"}
elseif ([uf] == "PE") {[listaUF].default = "Pernambuco"}
elseif ([uf] == "PI") {[listaUF].default = "Piauí"}
elseif ([uf] == "RJ") {[listaUF].default = "Rio de Janeiro"}
elseif ([uf] == "RN") {[listaUF].default = "Rio Grande do Norte"}
elseif ([uf] == "RS") {[listaUF].default = "Rio Grande do Sul"}
elseif ([uf] == "RO") {[listaUF].default = "Rondônia"}
elseif ([uf] == "RR") {[listaUF].default = "Roraima"}
elseif ([uf] == "SC") {[listaUF].default = "Santa Catarina"}
elseif ([uf] == "SE") {[listaUF].default = "Sergipe"}
elseif ([uf] == "TO") {[listaUF].default = "Tocantins"}
}
}
}
loaders {
if ([inputCEP].length() == 9) {
[cepSemTracos] = [inputCEP],
[cepSemTracos] = [cepSemTracos].replace("-", "")
}
}
},
+<strPrincipal> : Struct {
name = "Estrutura Principal"
fields {
+[strEndereco] : STR_Endereco {
name = "Endereço"
}
}
}
}
operations {
<strPrincipal>.ask(),
if (<strPrincipal.strEndereco.inputCEP>.hasChanged()) {
<strPrincipal.strEndereco.strInfoAPI>.clear(),
<cepCacheConfig.key> = <strPrincipal.strEndereco.cepSemTracos>,
cache(
<cepCacheConfig>,
<strPrincipal.strEndereco.strInfoAPI>,
APIGet(<strPrincipal.strEndereco.strInfoAPI>, null, "https://viacep.com.br/ws/" & <strPrincipal.strEndereco.cepSemTracos> & "/json/", "localidade:cidade, complemento:null")
)
}
}
}
}