From 48672584c7cf1ab2f7995aad8352b39d30d33746 Mon Sep 17 00:00:00 2001 From: Danylo Negrienko Date: Sat, 28 Dec 2024 20:10:01 -0500 Subject: [PATCH] Added main module to analize format of tax_id and define EDRPOU or ITIN Bumped to 0.1.3 --- README.md | 2 +- lib/ukraine_taxid_ex.ex | 51 ++++++++++++++++++++++++ lib/ukraine_taxid_ex/base_parser.ex | 2 +- mix.exs | 2 +- test/ukraine_taxid_ex_test.exs | 60 +++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 295b6e2..28f875e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The package can be installed by adding `ukraine_tax_id` to your list of dependen ```elixir def deps do [ - {:ukraine_tax_id, "~> 0.1.1"} + {:ukraine_tax_id, "~> 0.1.3"} ] end ``` diff --git a/lib/ukraine_taxid_ex.ex b/lib/ukraine_taxid_ex.ex index 3bd2235..906272c 100644 --- a/lib/ukraine_taxid_ex.ex +++ b/lib/ukraine_taxid_ex.ex @@ -1,5 +1,56 @@ defmodule UkraineTaxidEx do + @itin_length UkraineTaxidEx.Itin.length() + @edrpou_length UkraineTaxidEx.Edrpou.length() + @moduledoc """ Documentation for `UkraineTaxidEx`. """ + + @doc """ + `determine/1`: Takes a tax ID string and identifies its type based on length + + - Returns `{:ok, UkraineTaxidEx.Itin}` for ITIN numbers + - Returns `{:ok, UkraineTaxidEx.Edrpou}` for EDRPOU numbers + - Returns an error if the length is invalid + """ + def determine(tax_id) when is_binary(tax_id) do + case String.length(tax_id) do + @itin_length -> {:ok, UkraineTaxidEx.Itin} + @edrpou_length -> {:ok, UkraineTaxidEx.Edrpou} + _ -> {:error, "Invalid tax ID length"} + end + end + + @doc """ + `parse/1`: Determines the tax ID type and parses it using the appropriate parser + + - Uses `Module.concat` to dynamically find the correct parser module + - Returns a tuple with status, result, and type information + """ + def parse(tax_id) do + case determine(tax_id) do + {:ok, type} -> + parser = Module.concat(type, "Parser") + {status, result} = parser.parse(tax_id) + {status, result, type} + + {:error, error} -> + {:error, error} + end + end + + @doc """ + `validate/1`: Validates a tax ID by attempting to parse it + + - Returns `:ok` if valid + - Returns error tuples with details if invalid + """ + + def validate(tax_id) do + case parse(tax_id) do + {:ok, _, _} -> :ok + {:error, error, type} -> {:error, error, type} + {:error, error} -> {:error, error} + end + end end diff --git a/lib/ukraine_taxid_ex/base_parser.ex b/lib/ukraine_taxid_ex/base_parser.ex index ccf3cce..b79b161 100644 --- a/lib/ukraine_taxid_ex/base_parser.ex +++ b/lib/ukraine_taxid_ex/base_parser.ex @@ -24,7 +24,7 @@ defmodule UkraineTaxidEx.BaseParser do @impl BaseParser @spec parse(data :: string_or_ok, options :: BaseParser.options()) :: struct_or_error() - def parse(data, options \\ [normalize?: false, clean?: false]) + def parse(data, options \\ [normalize?: false, clean?: true]) def parse({:ok, string}, options), do: parse(string, options) def parse({:error, error}, _options), do: {:error, error} diff --git a/mix.exs b/mix.exs index 3569ee4..b6b2099 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule UkraineTaxidEx.MixProject do @module UkraineTaxidEx @source_url "https://g.tulz.dev/opensource/ukraine-taxid-ex" @docs_url "https://hexdocs.pm/#{@app}" - @version "0.1.2" + @version "0.1.3" def project do [ diff --git a/test/ukraine_taxid_ex_test.exs b/test/ukraine_taxid_ex_test.exs index 7d37e2f..c7e9c6d 100644 --- a/test/ukraine_taxid_ex_test.exs +++ b/test/ukraine_taxid_ex_test.exs @@ -1,4 +1,64 @@ defmodule UkraineTaxidExTest do use ExUnit.Case, async: true doctest UkraineTaxidEx + + describe "determine/1" do + test "correctly identifies ITIN tax ID" do + assert {:ok, UkraineTaxidEx.Itin} = UkraineTaxidEx.determine("1234567890") + end + + test "correctly identifies EDRPOU tax ID" do + assert {:ok, UkraineTaxidEx.Edrpou} = UkraineTaxidEx.determine("12345678") + end + + test "returns error for invalid length" do + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("123") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("1234") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("12345") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("123456") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("1234567") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("123456789") + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.determine("12345678901") + end + end + + describe "parse/1" do + test "successfully parses valid ITIN" do + assert {:ok, %{code: "1759013776"}, UkraineTaxidEx.Itin} = + UkraineTaxidEx.parse("1759013776") + end + + test "successfully parses valid EDRPOU" do + assert {:ok, %{code: "30283027"}, UkraineTaxidEx.Edrpou} = + UkraineTaxidEx.parse("30283027") + end + + test "returns error for invalid tax ID" do + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.parse("123") + end + + test "returns :length_too_short error for invalid format tax id (valid length but invalid after clean)" do + assert {:error, :length_too_short, UkraineTaxidEx.Itin} = + UkraineTaxidEx.parse("abcdefghij") + + assert {:error, :length_too_short, UkraineTaxidEx.Edrpou} = + UkraineTaxidEx.parse("abcdefgh") + end + end + + describe "validate/1" do + test "returns :invalid_checksum for ITIN with invalid checksum" do + assert {:error, :invalid_checksum, UkraineTaxidEx.Itin} = + UkraineTaxidEx.validate("1234567890") + end + + test "returns :invalid_checksum for EDRPOU with invalid checksum" do + assert {:error, :invalid_checksum, UkraineTaxidEx.Edrpou} = + UkraineTaxidEx.validate("12345679") + end + + test "returns error for invalid tax ID" do + assert {:error, "Invalid tax ID length"} = UkraineTaxidEx.validate("123") + end + end end