Skip to content

Commit 0fbd187

Browse files
ketsalkuetspalinjj-glez
authored andcommitted
Se agrega validación de còdigo de Estado (#26)
1 parent e957bbb commit 0fbd187

File tree

12 files changed

+1080
-545
lines changed

12 files changed

+1080
-545
lines changed

.formatter.exs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[
2+
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
3+
]

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ erl_crash.dump
2020
*.ez
2121
.idea/
2222
*.iml
23+
24+
# Variables de Entorno
25+
.env

lib/burox.ex

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ defmodule Burox do
55
alias Burox.Request.Encoder
66
alias Burox.Response.Parser
77
alias Burox.Utils
8+
alias Burox.Utils.Validator
89

910
require Logger
1011

@@ -16,12 +17,11 @@ defmodule Burox do
1617
{:ok, term}
1718
1819
"""
19-
@spec solicitar(Request.t) :: {:ok, term} | {:error, term}
20+
@spec solicitar(Request.t()) :: {:ok, term} | {:error, term}
2021
def solicitar(peticion) do
2122
solicitar(peticion, "507")
2223
end
2324

24-
2525
@doc """
2626
Solicita la información crediticia de una persona al buró de crédito
2727
## Ejemplos
@@ -30,34 +30,24 @@ defmodule Burox do
3030
{:ok, term}
3131
3232
"""
33-
@spec solicitar(Request.t, String.t) :: {:ok, term} | {:error, term}
33+
@spec solicitar(Request.t(), String.t()) :: {:ok, term} | {:error, term}
3434
def solicitar(data, codigo_producto) do
35-
peticion = Utils.to_struct(data, Burox.Request)
36-
Logger.info "Petición:\n#{inspect peticion}"
37-
38-
request_string = Encoder.encode_buro(peticion, codigo_producto)
39-
Logger.info "Cadena de petición:\n#{inspect request_string}"
40-
41-
buro_service = Application.get_env(:burox, :buro_service)
4235

43-
with {:ok, buro_response} <- buro_service.post(request_string, codigo_producto) do
44-
Logger.info "Respuesta del buro: \n #{buro_response}"
36+
with {:ok, request} <- Validator.valid?(data) do
37+
request_string = Encoder.encode_buro(request, codigo_producto)
38+
buro_service = Application.get_env(:burox, :buro_service)
4539

46-
response = Parser.process_response(buro_response)
47-
Logger.info "Respuesta:\n#{inspect response}"
40+
with {:ok, buro_response} <- buro_service.post(request_string, codigo_producto) do
41+
response = Parser.process_response(buro_response)
4842

49-
retorno = %{
50-
cadena_peticion: request_string,
51-
respuesta: response,
52-
cadena_respuesta: String.slice(buro_response, 0..-2)
53-
}
43+
retorno = %{
44+
cadena_peticion: request_string,
45+
respuesta: response,
46+
cadena_respuesta: String.slice(buro_response, 0..-2)
47+
}
5448

55-
case peticion do
56-
%Request{} -> {:ok, retorno}
57-
_ -> {:error, retorno}
49+
{:ok, retorno}
5850
end
5951
end
60-
6152
end
62-
6353
end
Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,16 @@ defmodule Burox.BuroService.Socket do
1111
Función para consultar información del Buró de Crédito
1212
De manera síncrona
1313
"""
14-
@spec post(String.t, String.t) :: String.t
14+
@spec post(String.t(), String.t()) :: String.t()
1515
def post(data, codigo_producto) do
16-
1716
config_url = if codigo_producto == "107", do: :buro_url_prospector, else: :buro_url
1817
buro_url = Application.get_env(:burox, config_url)
19-
Logger.info "URL del Buró: #{buro_url}"
2018

2119
if is_nil(buro_url) do
2220
raise Burox.Error, message: "Debe configurarse la url del Buró de Crédito"
2321
end
2422

2523
with {:ok, sock} <- Socket.connect(buro_url) do
26-
Logger.info "Connected"
2724
Socket.Stream.send!(sock, data <> <<19>>)
2825
response = get_response(sock)
2926

@@ -34,19 +31,18 @@ defmodule Burox.BuroService.Socket do
3431
end
3532
else
3633
{:error, reason} -> {:error, reason}
37-
_ -> {:error, %{error: %{message: "No se puede conectar al Buró de Crédito"}}}
34+
_ -> {:error, %{error: %{message: "No se puede conectar al Buró de Crédito"}}}
3835
end
3936
end
4037

4138
# Concatena toda la respuesta del Stream
4239
defp get_response(sock) do
4340
response = Socket.Stream.recv!(sock)
4441

45-
if String.ends_with? response, <<19>> do
42+
if String.ends_with?(response, <<19>>) do
4643
response
4744
else
4845
response <> get_response(sock)
4946
end
5047
end
51-
5248
end
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ defmodule Burox.BuroService do
33
Este módulo contiene la lógica para mandar y
44
recibir información del buro de crédito
55
"""
6-
@callback post(String.t(), String.t) :: String.t()
6+
@callback post(String.t(), String.t()) :: String.t()
77
end

lib/burox/utils/state_code.ex

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
defmodule Burox.Utils.StateCode do
2+
@moduledoc """
3+
Módulo que ayuda a asignar el código correcto para cada Estado o
4+
vaidar si un código dado en correcto
5+
"""
6+
7+
@states_codes [
8+
Aguascalientes: "AGS",
9+
"Baja California": "BCN",
10+
"Baja California Sur": "BCN",
11+
Campeche: "CAM",
12+
Chiapas: "CHS",
13+
Chihuahua: "CHI",
14+
"Ciudad de México": "CDMX",
15+
Coahuila: "COA",
16+
Colima: "COL",
17+
Durango: "DGO",
18+
"Estado de México": "EM",
19+
Guanajuato: "GTO",
20+
Guerrero: "GRO",
21+
Hidalgo: "HGO",
22+
Jalisco: "JAL",
23+
"Michoacán": "MICH",
24+
Morelos: "MOR",
25+
Nayarit: "NAY",
26+
"Nuevo León": "NL",
27+
Oaxaca: "OAX",
28+
Puebla: "PUE",
29+
"Querétaro": "QRO",
30+
"Quintana Roo": "QR",
31+
"San Luis Potosí": "SLP",
32+
Sinaloa: "SIN",
33+
Sonora: "SON",
34+
Tabasco: "TAB",
35+
Tamaulipas: "TAM",
36+
Tlaxcala: "TLAX",
37+
Veracruz: "VER",
38+
"Yucatán": "YUC",
39+
Zacatecas: "ZAC"
40+
]
41+
42+
@doc """
43+
Retorna el código del Estado que más se parezca al nombre enviado
44+
"""
45+
@spec assign(String.t()) :: String.t()
46+
def assign(state_name) do
47+
@states_codes
48+
|> Enum.max_by(fn {name, code} ->
49+
String.jaro_distance(state_name, to_string(name))
50+
end)
51+
|> elem(1)
52+
end
53+
54+
@doc """
55+
Valida si el código pertenece a un Estado
56+
"""
57+
@spec valid?(String.t()) :: bool
58+
def valid?(untested_code) do
59+
@states_codes
60+
|> Enum.find(fn {_name, code} -> code == untested_code end)
61+
|> Kernel.!=(nil)
62+
end
63+
end

lib/burox/utils/validator.ex

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
defmodule Burox.Utils.Validator do
2+
@moduledoc """
3+
Sirve para validar los parámetros en la petición del Buró
4+
"""
5+
alias Burox.Request
6+
alias Burox.Request.Direccion
7+
alias Burox.Utils.StateCode
8+
alias Burox.Utils
9+
10+
require Logger
11+
12+
@doc """
13+
Valida si los datos de la petición son correctos, de lo contrario regresa
14+
los errores
15+
"""
16+
@spec valid?(map()) :: {:ok, term} | {:error, term}
17+
def valid?(data) do
18+
request = Utils.to_struct(data, Request)
19+
20+
case request do
21+
%Request{} ->
22+
if Vex.valid?(request) do
23+
request
24+
|> validate_state()
25+
|> validate_address()
26+
else
27+
{:error, Vex.errors(request)}
28+
end
29+
30+
error ->
31+
{:error, error}
32+
end
33+
end
34+
35+
@doc """
36+
Valida el código del estado, si es incorrecto lo cambia por uno que si lo sea
37+
"""
38+
@spec validate_state(Request.t()) :: Request.t()
39+
def validate_state(request) do
40+
with %Request{direccion: address} <- request,
41+
%{estado: state_code} <- address do
42+
address = struct(Direccion, address)
43+
44+
new_code = if StateCode.valid?(state_code), do: state_code, else: StateCode.assign(state_code)
45+
%Request{request | direccion: %Direccion{address | estado: new_code}}
46+
end
47+
end
48+
49+
# Valida si los datos enviados en la dirección son correctos
50+
defp validate_address(request) do
51+
if Direccion.valid?(request.direccion) do
52+
{:ok, request}
53+
else
54+
{:error, Vex.errors(request.direccion)}
55+
end
56+
end
57+
58+
end

lib/request/request.ex

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
defmodule Burox.Request.Encabezado do
22
@moduledoc false
3-
43
defstruct [
54
:codigo_de_producto,
65
:pais,
7-
:clave_del_usuario,
6+
:clave_del_usuario
87
]
98
end
109

1110
defmodule Burox.Request.Autenticacion do
12-
@moduledoc false
11+
@moduledoc false
1312
defstruct [
1413
:tipo_reporte,
1514
:tipo_salida,
1615
:referencia_del_operador,
1716
:cuenta_con_tarjeta_de_credito,
1817
:ultimos_cuatro_digitos,
1918
:ha_ejercido_un_credito_hipotecario,
20-
:ha_ejercido_un_credito_automotriz_en_los_ultimos_24_meses,
19+
:ha_ejercido_un_credito_automotriz_en_los_ultimos_24_meses
2120
]
2221
end
2322

@@ -32,6 +31,8 @@ defmodule Burox.Request.Persona do
3231
:fecha_de_nacimiento,
3332
:rfc
3433
]
34+
35+
use Vex.Struct
3536
end
3637

3738
defmodule Burox.Request.Direccion do
@@ -46,6 +47,50 @@ defmodule Burox.Request.Direccion do
4647
:codigo_postal,
4748
:origen_del_domicilio
4849
]
50+
51+
use Vex.Struct
52+
53+
validates(:primera_linea_de_direccion,
54+
presence: true,
55+
length: [max: 40],
56+
format: ~r(^[[:alnum:]\s]+$)
57+
)
58+
59+
validates(:colonia,
60+
presence: true,
61+
length: [max: 40],
62+
format: ~r(^[[:alpha:]\s]+$)
63+
)
64+
65+
validates(:municipio,
66+
presence: true,
67+
length: [max: 40],
68+
format: ~r(^[[:alpha:]\s]+$)
69+
)
70+
71+
validates(:ciudad,
72+
presence: true,
73+
length: [max: 40],
74+
format: ~r(^[[:alpha:]\s]+$)
75+
)
76+
77+
validates(:estado,
78+
presence: true,
79+
length: [max: 4],
80+
format: ~r(^[[:alpha:]\s]+$)
81+
)
82+
83+
validates(:codigo_postal,
84+
presence: true,
85+
length: [is: 5],
86+
format: ~r(^[[:digit:]]+$)
87+
)
88+
89+
validates(:origen_del_domicilio,
90+
presence: true,
91+
length: [is: 2],
92+
format: ~r(^[A-Z]+$)
93+
)
4994
end
5095

5196
defmodule Burox.Request do
@@ -56,10 +101,13 @@ defmodule Burox.Request do
56101

57102
@enforce_keys [:persona, :direccion]
58103

59-
defstruct [
60-
autenticacion: %Request.Autenticacion{},
61-
encabezado: %Request.Encabezado{},
62-
persona: %Request.Persona{},
63-
direccion: %Request.Direccion{}
64-
]
104+
defstruct autenticacion: %Request.Autenticacion{},
105+
encabezado: %Request.Encabezado{},
106+
persona: %Request.Persona{},
107+
direccion: %Request.Direccion{}
108+
109+
use Vex.Struct
110+
111+
validates(:persona, presence: true)
112+
validates(:direccion, presence: true)
65113
end

mix.exs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ defmodule Burox.Mixfile do
44
def project do
55
[
66
app: :burox,
7-
version: "0.1.0",
8-
elixir: "~> 1.5",
9-
start_permanent: Mix.env == :prod,
7+
version: "0.2.0",
8+
elixir: "~> 1.7",
9+
start_permanent: Mix.env() == :prod,
1010
deps: deps()
1111
]
1212
end
@@ -19,10 +19,11 @@ defmodule Burox.Mixfile do
1919

2020
defp deps do
2121
[
22-
{:credo, "~> 0.9.0-rc1", only: [:dev, :test], runtime: false},
23-
{:ex_doc, "~> 0.16", only: :dev, runtime: false},
24-
{:socket, "~> 0.3.2"},
25-
{:mox, "~> 0.3", only: :test}
22+
{:credo, "~> 0.10.0", only: [:dev, :test], runtime: false},
23+
{:ex_doc, "~> 0.19", only: :dev, runtime: false},
24+
{:socket, "~> 0.3.2"},
25+
{:mox, "~> 0.4", only: :test},
26+
{:vex, "~> 0.7"}
2627
]
2728
end
2829
end

0 commit comments

Comments
 (0)