Packages

Package for validating Spanish id numbers

Current section

Files

Jump to
elixir_dni lib elixir_dni.ex
Raw

lib/elixir_dni.ex

defmodule ElixirDni do
@moduledoc """
Validates Spanish national id numbers (DNI, NIE). Methods for id type, and to
get the valid verification letter (the last letter of the number).
"""
@id_types [{~r/\d{8}[a-zA-Z]{1}/, :dni},{~r/[XYZ]\d{7}[a-zA-Z]{1}/, :nie}]
@doc """
Returns :nie, :dni, or nil for vaild id numbers
"""
@spec id_type(String.t) :: atom
def id_type(dni) when is_binary(dni) do
{_, type} = Enum.find(@id_types, {nil, :unknown}, fn {reg, type} ->
String.match?(dni, reg)
end)
type
end
defp nie_letters do
%{X: 0, Y: 1, Z: 2}
end
defp current_check_letter(dni) do
dni
|> String.last
|> String.upcase
end
defp leading(dni) do
dni
|> String.first
|> String.upcase
|> String.to_atom
end
defp parse_digits(:dni, dni) do
String.slice(dni, 0..-2)
end
defp parse_digits(:nie, dni) do
ending = String.slice(dni, 1..-2)
prefix = nie_letters()[leading(dni)] |> Integer.to_string
Enum.join([prefix, ending])
end
defp calculate_check(dni) do
type = id_type(dni)
digits = parse_digits(type, dni)|> String.to_integer
Integer.mod(digits, 23)
end
defp verifiers do
%{
0 => "T", 1 => "R", 2 => "W", 3 => "A", 4 => "G", 5 => "M",
6 => "Y", 7 => "F", 8 => "P", 9 => "D", 10 => "X", 11 => "B",
12 => "N", 13 => "J", 14 => "Z" ,15 => "S", 16 => "Q",
17 => "V", 18 => "H", 19 => "L", 20 => "C", 21 => "K", 22 => "E"
}
end
@doc """
Returns what the correct verfication letter should be
"""
@spec valid_check_letter(String.t) :: String.t
def valid_check_letter(dni) when is_binary(dni) do
result = Enum.filter verifiers(), fn {key, _value} ->
key == calculate_check(dni)
end
result
|> List.first
|> elem(1)
end
@doc """
Returns boolean to check for valid id number
"""
@spec valid?(String.t) :: boolean
def valid?(dni) do
id_type(dni) in [:nie, :dni] && (current_check_letter(dni) == valid_check_letter(dni))
end
end