Looplex Knowledge Base
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 deifs
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") ) } } }}