Current section
Files
Jump to
Current section
Files
lib/ex_gtin.ex
defmodule ExGtin do
@moduledoc """
Documentation for ExGtin. This library provides
functionality for validating GTIN compliant codes.
"""
@doc """
Check for valid GTIN-8, GTIN-12, GTIN-13, GTIN-14, GSIN, SSCC codes
Returns `{:ok}` or `{:error}`
## Examples
iex> ExGtin.gtin_check_digit("6291041500213")
{:ok}
iex> ExGtin.gtin_check_digit("6291041500214")
{:error}
"""
@spec gtin_check_digit(string) :: { atom }
def gtin_check_digit(number) when is_bitstring(number) do
number
|> String.codepoints
|> Enum.map(fn(x) -> String.to_integer(x) end)
|> gtin_check_digit
end
@spec gtin_check_digit(number) :: { atom }
def gtin_check_digit(number) when is_number(number), do: gtin_check_digit(Integer.digits(number))
@spec gtin_check_digit(list(number)) :: { atom }
def gtin_check_digit(number) do
{code, check_digit} = Enum.split(number, length(number) - 1)
calculated_check_digit = code
|> multiply_and_sum_array
|> subtract_from_nearest_multiple_of_ten
case calculated_check_digit == Enum.at(check_digit, 0) do
true -> {:ok}
_ -> {:error}
end
end
@doc """
Calculates the sum of the digits in a string and multiplied value based on index order
Returns sum of values
## Examples
iex> ExGtin.multiply_and_sum_array([6,2,9,1,0,4,1,5,0,0,2,1])
57
"""
@spec multiply_and_sum_array(list(number)) :: number
def multiply_and_sum_array(numbers) do
numbers
|> Enum.reverse
|> Stream.with_index
|> Enum.reduce(0, fn({num, idx}, acc) ->
acc + (num * mult_by_index_code(idx))
end)
end
@doc """
Calculates the difference of the highest rounded multiple of 10
Returns the difference of the highest rounded multiple of 10
## Examples
iex> ExGtin.subtract_from_nearest_multiple_of_ten(57)
3
"""
@spec subtract_from_nearest_multiple_of_ten(number) :: number
def subtract_from_nearest_multiple_of_ten(number) do
mod(10 - mod(number, 10), 10)
end
def mult_by_index_code(index) do
case mod(index, 2) do
0 -> 3
_ -> 1
end
end
defp mod(x,y) when x > 0, do: rem(x, y);
defp mod(x,y) when x < 0, do: rem(y+x, y);
defp mod(0,_y), do: 0
end