diff --git a/lib/aba_file_validator.ex b/lib/aba_file_validator.ex index 683a9c7..194f724 100644 --- a/lib/aba_file_validator.ex +++ b/lib/aba_file_validator.ex @@ -1,8 +1,81 @@ defmodule AbaFileValidator do + import __MODULE__.Utils, only: [correct_length?: 2, string_empty?: 1, valid_date?: 1] + @moduledoc """ Documentation for `AbaFileValidator`. """ + @spec get_descriptive_record(binary) :: + {:error, :incorrect_length | :incorrect_starting_code | :invalid_format} + | {:ok, binary(), binary(), binary(), binary(), binary(), binary()} + @doc """ + Get the entries as part of the descriptiive record + + ## Examples + + iex> AbaFileValidator.get_descriptive_record(1) + {:error, :invalid_input} + + iex> AbaFileValidator.get_descriptive_record("11") + {:error, :incorrect_length} + + iex> AbaFileValidator.get_descriptive_record("01") + {:error, :incorrect_length} + + iex> AbaFileValidator.get_descriptive_record("1 01CBA test 301500221212121227121222 ") + {:error, :incorrect_starting_code} + + iex> AbaFileValidator.get_descriptive_record("0 CBA test 301500221212121227121222 ") + {:error, :invalid_format} + + iex> AbaFileValidator.get_descriptive_record("0 01CBA test 301500221212121227121222 ") + {:ok, "01", "CBA", "test ", "301500", "221212121227", "121222"} + + """ + def get_descriptive_record(entry) when not is_binary(entry) do + {:error, :invalid_input} + end + + def get_descriptive_record(entry) do + if not correct_length?(entry, 120) do + {:error, :incorrect_length} + else + {code, entry} = String.split_at(entry, 1) + + if code != "0" do + {:error, :incorrect_starting_code} + else + {first_blank, entry} = String.split_at(entry, 17) + {reel_sequence_number, entry} = String.split_at(entry, 2) + {bank_abbreviation, entry} = String.split_at(entry, 3) + {mid_blank, entry} = String.split_at(entry, 7) + {user_preferred_specification, entry} = String.split_at(entry, 26) + {user_id_number, entry} = String.split_at(entry, 6) + {description, entry} = String.split_at(entry, 12) + {date, last_blank} = String.split_at(entry, 6) + + with true <- code == "0", + true <- correct_length?(first_blank, 17), + true <- correct_length?(mid_blank, 7), + true <- correct_length?(last_blank, 40), + false <- string_empty?(reel_sequence_number), + false <- string_empty?(bank_abbreviation), + false <- string_empty?(user_preferred_specification), + false <- string_empty?(user_id_number), + false <- string_empty?(description), + true <- valid_date?(date), + false <- string_empty?(date) do + {:ok, reel_sequence_number, bank_abbreviation, user_preferred_specification, + user_id_number, description, date} + else + _error -> + {:error, :invalid_format} + end + end + end + end + + @spec get_transaction_code_description(any) :: :error | binary() @doc """ Get a description for a given transaction code @@ -17,8 +90,13 @@ defmodule AbaFileValidator do """ def get_transaction_code_description(13), do: "Externally initiated debit items" def get_transaction_code_description("13"), do: "Externally initiated debit items" - def get_transaction_code_description(50), do: "Externally initiated credit items with the exception of those bearing Transaction Codes" - def get_transaction_code_description("50"), do: "Externally initiated credit items with the exception of those bearing Transaction Codes" + + def get_transaction_code_description(50), + do: "Externally initiated credit items with the exception of those bearing Transaction Codes" + + def get_transaction_code_description("50"), + do: "Externally initiated credit items with the exception of those bearing Transaction Codes" + def get_transaction_code_description(51), do: "Australian Government Security Interest" def get_transaction_code_description("51"), do: "Australian Government Security Interest" def get_transaction_code_description(52), do: "Family Allowance" diff --git a/lib/util.ex b/lib/util.ex new file mode 100644 index 0000000..c996b49 --- /dev/null +++ b/lib/util.ex @@ -0,0 +1,13 @@ +defmodule AbaFileValidator.Utils do + def correct_length?(entry,n) when is_binary(entry), do: String.length(entry) == n + def string_empty?(entry) when is_binary(entry), do: String.trim(entry) |> String.length() == 0 + + def valid_date?(<>) do + [yy, mm, dd] = for i <- [yy, mm, dd], do: String.to_integer(i) + NaiveDateTime.new(yy, mm, dd, 0, 0, 0) + |> case do + {:ok, _} -> true + {:error, _} -> false + end + end +end diff --git a/test/aba_file_validator_test.exs b/test/aba_file_validator_test.exs index 577132a..e636a57 100644 --- a/test/aba_file_validator_test.exs +++ b/test/aba_file_validator_test.exs @@ -2,14 +2,27 @@ defmodule AbaFileValidatorTest do use ExUnit.Case doctest AbaFileValidator - test "transaction code description" do + test "AbaFileValidator.get_transaction_code_description/1" do assert AbaFileValidator.get_transaction_code_description(11) == :error - assert AbaFileValidator.get_transaction_code_description(13) == "Externally initiated debit items" - assert AbaFileValidator.get_transaction_code_description("13") == "Externally initiated debit items" - assert AbaFileValidator.get_transaction_code_description(50) == "Externally initiated credit items with the exception of those bearing Transaction Codes" - assert AbaFileValidator.get_transaction_code_description("50") == "Externally initiated credit items with the exception of those bearing Transaction Codes" - assert AbaFileValidator.get_transaction_code_description(51) == "Australian Government Security Interest" - assert AbaFileValidator.get_transaction_code_description("51") == "Australian Government Security Interest" + + assert AbaFileValidator.get_transaction_code_description(13) == + "Externally initiated debit items" + + assert AbaFileValidator.get_transaction_code_description("13") == + "Externally initiated debit items" + + assert AbaFileValidator.get_transaction_code_description(50) == + "Externally initiated credit items with the exception of those bearing Transaction Codes" + + assert AbaFileValidator.get_transaction_code_description("50") == + "Externally initiated credit items with the exception of those bearing Transaction Codes" + + assert AbaFileValidator.get_transaction_code_description(51) == + "Australian Government Security Interest" + + assert AbaFileValidator.get_transaction_code_description("51") == + "Australian Government Security Interest" + assert AbaFileValidator.get_transaction_code_description(52) == "Family Allowance" assert AbaFileValidator.get_transaction_code_description("52") == "Family Allowance" assert AbaFileValidator.get_transaction_code_description(53) == "Pay" @@ -23,4 +36,37 @@ defmodule AbaFileValidatorTest do assert AbaFileValidator.get_transaction_code_description(57) == "Debenture/Note Interest" assert AbaFileValidator.get_transaction_code_description("57") == "Debenture/Note Interest" end + + describe "AbaFileValidator.get_descriptive_record/1" do + test "validates succesfully" do + entry = + "0 01CBA test 301500221212121227121222 " + + assert AbaFileValidator.get_descriptive_record(entry) == {:ok, "01", "CBA", "test ", "301500", "221212121227", "121222"} + end + + test "returns an error if incorrect length with correct starting code" do + assert AbaFileValidator.get_descriptive_record("0") == {:error, :incorrect_length} + end + + test "returns an error if incorrect length with incorrect starting code" do + assert AbaFileValidator.get_descriptive_record("1") == {:error, :incorrect_length} + end + + test "returns an error if incorrect starting code" do + entry = + "1 01CBA test 301500221212121227121222 " + + assert AbaFileValidator.get_descriptive_record(entry) == + {:error, :incorrect_starting_code} + end + + test "returns an error if invalid string" do + entry = + "0 CBA test 301500221212121227121222 " + + assert AbaFileValidator.get_descriptive_record(entry) == + {:error, :invalid_format} + end + end end