defmodule Gusex.Validators.Nip do @moduledoc """ Module for handling Polish NIP (Tax Identification Number) validation. This module provides functions to validate NIP numbers according to the official rules. NIP is a 10-digit number where the last digit is a checksum calculated from the first nine digits. The checksum is calculated using a specific set of factors applied to the first nine digits. """ @factors [6, 5, 7, 2, 3, 4, 5, 6, 7] @doc """ Validates a NIP number. Accepts a string representation of the NIP. Returns `true` if valid, `false` otherwise. """ @spec valid?(String.t()) :: boolean() def valid?(nip) when is_binary(nip) do digits = Regex.replace(~r/[\s\-−‒–—‒—―]/u, nip, "") cond do String.length(digits) != 10 -> false not String.match?(digits, ~r/^\d{10}$/) -> false true -> check(digits) end end # def valid?(nip) when is_integer(nip), do: valid?(String.pad_leading(Integer.to_string(nip), 10, "0")) def valid?(_), do: false defp check(<>) do sum = @factors |> Enum.with_index() |> Enum.reduce(0, fn {factor, idx}, acc -> acc + factor * (String.at(nip, idx) |> String.to_integer()) end) checksum = rem(sum, 11) checksum != 10 and checksum == String.at(nip, 9) |> String.to_integer() end end