ukraine-taxid-ex/lib/ukraine_taxid_ex/base_validator.ex

63 lines
2.3 KiB
Elixir

defmodule UkraineTaxidEx.BaseValidator do
@callback validate(code :: String.t()) ::
{:ok, code :: String.t()}
| {:error,
:length_too_short | :length_too_long | :invalid_length | :invalid_checksum}
@callback violates_length?(code :: String.t()) :: boolean
@callback violates_length_too_short?(code :: String.t()) :: boolean
@callback violates_length_too_long?(code :: String.t()) :: boolean
@callback violates_checksum?(code :: String.t()) :: boolean
defmacro __using__(_) do
quote do
alias UkraineTaxidEx.BaseValidator
@behaviour UkraineTaxidEx.BaseValidator
import UkraineTaxidEx.Commons, only: [digits: 1, digits_and_check_digit: 1, error: 1, ok: 1]
@impl BaseValidator
@spec validate(String.t()) ::
{:ok, String.t()}
| {:error,
:length_too_short | :length_too_long | :invalid_length | :invalid_checksum}
def validate(string) do
cond do
violates_length_too_short?(string) -> error(:length_too_short)
violates_length_too_long?(string) -> error(:length_too_long)
violates_checksum?(string) -> error(:invalid_checksum)
true -> ok(string)
end
end
@doc "Check whether a given EDRPOU violates the required length"
@impl BaseValidator
@spec violates_length?(code :: String.t()) :: boolean
def violates_length?(code), do: String.length(code) != length()
@doc "Check whether a given EDRPOU too short"
@impl BaseValidator
@spec violates_length_too_short?(code :: String.t()) :: boolean
def violates_length_too_short?(code), do: String.length(code) < length()
@doc "Check whether a given EDRPOU too long"
@impl BaseValidator
@spec violates_length_too_long?(code :: String.t()) :: boolean
def violates_length_too_long?(code), do: String.length(code) > length()
@doc "Check whether a given EDRPOU has correct checksum"
@impl BaseValidator
@spec violates_checksum?(code :: String.t()) :: boolean
def violates_checksum?(code) do
{digits, check_digit} =
code
|> digits()
|> digits_and_check_digit()
check_sum = check_sum(digits)
check_sum != check_digit
end
end
end
end