From acc97c70e843b353bdfc01b6c5ebdc8560778be3 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:08:22 +0800 Subject: [PATCH 1/7] refactor: updated readme Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a77c0d0..76a8cae 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # ABA File Validator -[![CI](https://github.com/alt-ctrl-dev/aba_file_validator/actions/workflows/ci.yml/badge.svg)](https://github.com/alt-ctrl-dev/aba_file_validator/actions/workflows/ci.yml) - +[![Unit tests](https://github.com/alt-ctrl-dev/aba_file_validator/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/alt-ctrl-dev/aba_file_validator/actions/workflows/ci.yml) ## Installation From b66f1980e53fff5f1c2f076c0764053dfc5d4b47 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:11:37 +0800 Subject: [PATCH 2/7] refactor: assuming the year as the 20XX Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- lib/util.ex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/util.ex b/lib/util.ex index 58abf31..ef7c150 100644 --- a/lib/util.ex +++ b/lib/util.ex @@ -1,11 +1,10 @@ defmodule AbaFileValidator.Utils do - def correct_length?(entry, n) when is_binary(entry), do: String.length(entry) == n + 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) + NaiveDateTime.new(2000+yy, mm, dd, 0, 0, 0) |> case do {:ok, _} -> true {:error, _} -> false From 648da9e576e0aca9b33be63e9c826746e946de43 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:20:33 +0800 Subject: [PATCH 3/7] test: updated new test Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- test/aba_file_validator_test.exs | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/aba_file_validator_test.exs b/test/aba_file_validator_test.exs index 811a35e..50d2420 100644 --- a/test/aba_file_validator_test.exs +++ b/test/aba_file_validator_test.exs @@ -70,5 +70,52 @@ defmodule AbaFileValidatorTest do assert AbaFileValidator.get_descriptive_record(entry) == {:error, :invalid_format, [:reel_sequence_number]} end + test "returns an error if empty string" do + entry = + "0 " + + assert AbaFileValidator.get_descriptive_record(entry) == + {:error, :invalid_format} + end + end + + describe "AbaFileValidator.get_file_total_record/1" do + test "validates succesfully" do + entry = + "7999-999 000000000000000353890000035389 000002 " + + assert AbaFileValidator.get_file_total_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_file_total_record("7") == {:error, :incorrect_length} + end + + test "returns an error if incorrect length with incorrect starting code" do + assert AbaFileValidator.get_file_total_record("1") == {:error, :incorrect_length} + end + + test "returns an error if incorrect starting code" do + entry = + "1 01CBA test 301500221212121227121222 " + + assert AbaFileValidator.get_file_total_record(entry) == + {:error, :incorrect_starting_code} + end + + test "returns an error if invalid string" do + entry = + "7999 999 000000000000000353890000035389 000002 " + + assert AbaFileValidator.get_file_total_record(entry) == + {:error, :invalid_format} + end + test "returns an error if empty string" do + entry = + "7 " + + assert AbaFileValidator.get_descriptive_record(entry) == + {:error, :invalid_format} + end end end From fea618b88f3ec8464d74adf512460cc7e73686a4 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:20:49 +0800 Subject: [PATCH 4/7] refactor: added new method Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- lib/aba_file_validator.ex | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/lib/aba_file_validator.ex b/lib/aba_file_validator.ex index 40e7eb8..3b3dedd 100644 --- a/lib/aba_file_validator.ex +++ b/lib/aba_file_validator.ex @@ -99,6 +99,73 @@ defmodule AbaFileValidator do end end + @doc """ + Get the entries as part of the file total record + + ## Examples + + iex> AbaFileValidator.get_file_total_record(1) + {:error, :invalid_input} + + iex> AbaFileValidator.get_file_total_record("11") + {:error, :incorrect_length} + + iex> AbaFileValidator.get_file_total_record("01") + {:error, :incorrect_length} + + iex> AbaFileValidator.get_file_total_record("1 01CBA test 301500221212121227121222 ") + {:error, :incorrect_starting_code} + + iex> AbaFileValidator.get_file_total_record("0 CBA test 301500221212121227121222 ") + {:error, :invalid_format} + + iex> AbaFileValidator.get_file_total_record("0 01CBA test 301500221212121227121222 ") + {:ok, "01", "CBA", "test ", "301500", "221212121227", "121222"} + + """ + def get_file_total_record(entry) when not is_binary(entry) do + {:error, :invalid_input} + end + + def get_file_total_record(entry) do + if not correct_length?(entry, 120) do + {:error, :incorrect_length} + else + {code, entry} = String.split_at(entry, 1) + + if code != "7" do + {:error, :incorrect_starting_code} + else + {bsb_filler, entry} = String.split_at(entry, 7) + {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 == "7", + true <- correct_length?(bsb_filler, 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 From e799e1af93f158c4644c664340bd475de673a98c Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:26:34 +0800 Subject: [PATCH 5/7] fix: refactor after rebase Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- lib/util.ex | 21 ++++++++++++++------- test/aba_file_validator_test.exs | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/util.ex b/lib/util.ex index ef7c150..d660b88 100644 --- a/lib/util.ex +++ b/lib/util.ex @@ -1,13 +1,20 @@ defmodule AbaFileValidator.Utils do - def correct_length?(entry,n) when is_binary(entry), do: String.length(entry) == n + 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(2000+yy, mm, dd, 0, 0, 0) - |> case do - {:ok, _} -> true - {:error, _} -> false - end + if string_empty?(dd) or + string_empty?(mm) or + string_empty?(yy) do + false + else + [yy, mm, dd] = for i <- [yy, mm, dd], do: String.to_integer(i) + + NaiveDateTime.new(2000 + yy, mm, dd, 0, 0, 0) + |> case do + {:ok, _} -> true + {:error, _} -> false + end + end end end diff --git a/test/aba_file_validator_test.exs b/test/aba_file_validator_test.exs index 50d2420..23c3590 100644 --- a/test/aba_file_validator_test.exs +++ b/test/aba_file_validator_test.exs @@ -70,12 +70,21 @@ defmodule AbaFileValidatorTest do assert AbaFileValidator.get_descriptive_record(entry) == {:error, :invalid_format, [:reel_sequence_number]} end + test "returns an error if empty string" do entry = "0 " assert AbaFileValidator.get_descriptive_record(entry) == - {:error, :invalid_format} + {:error, :invalid_format, + [ + :reel_sequence_number, + :bank_abbreviation, + :user_preferred_specification, + :user_id_number, + :description, + :date + ]} end end @@ -84,7 +93,9 @@ defmodule AbaFileValidatorTest do entry = "7999-999 000000000000000353890000035389 000002 " - assert AbaFileValidator.get_file_total_record(entry) == {:ok, "01", "CBA", "test ", "301500", "221212121227", "121222"} + assert AbaFileValidator.get_file_total_record(entry) == + {:ok, "01", "CBA", "test ", "301500", "221212121227", + "121222"} end test "returns an error if incorrect length with correct starting code" do @@ -110,6 +121,7 @@ defmodule AbaFileValidatorTest do assert AbaFileValidator.get_file_total_record(entry) == {:error, :invalid_format} end + test "returns an error if empty string" do entry = "7 " From dde716cf1e2e71e2dabde2740932276be01da533 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:50:24 +0800 Subject: [PATCH 6/7] feature: added file record method Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- lib/aba_file_validator.ex | 78 +++++++++++++++++++++----------- test/aba_file_validator_test.exs | 18 ++++++-- 2 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/aba_file_validator.ex b/lib/aba_file_validator.ex index 3b3dedd..6422669 100644 --- a/lib/aba_file_validator.ex +++ b/lib/aba_file_validator.ex @@ -116,11 +116,14 @@ defmodule AbaFileValidator do iex> AbaFileValidator.get_file_total_record("1 01CBA test 301500221212121227121222 ") {:error, :incorrect_starting_code} - iex> AbaFileValidator.get_file_total_record("0 CBA test 301500221212121227121222 ") - {:error, :invalid_format} + iex> AbaFileValidator.get_file_total_record("7999 999 000000000000000353890000035388 000002 ") + {:error, :invalid_format, [:bsb_filler, :net_total_mismatch ]} - iex> AbaFileValidator.get_file_total_record("0 01CBA test 301500221212121227121222 ") - {:ok, "01", "CBA", "test ", "301500", "221212121227", "121222"} + iex> AbaFileValidator.get_file_total_record("7 ") + {:error, :invalid_format, [:bsb_filler, :net_total, :total_credit, :total_debit, :record_count]} + + iex> AbaFileValidator.get_file_total_record("7999-999 000000000000000353890000035389 000002 ") + {:ok, "0000000000", "0000035389", "0000035389", "000002"} """ def get_file_total_record(entry) when not is_binary(entry) do @@ -137,30 +140,53 @@ defmodule AbaFileValidator do {:error, :incorrect_starting_code} else {bsb_filler, entry} = String.split_at(entry, 7) - {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) + {first_blank, entry} = String.split_at(entry, 12) + {net_total, entry} = String.split_at(entry, 10) + {total_credit, entry} = String.split_at(entry, 10) + {total_debit, entry} = String.split_at(entry, 10) + {mid_blank, entry} = String.split_at(entry, 24) + {record_count, last_blank} = String.split_at(entry, 6) + + errors = [] + + errors = if bsb_filler !== "999-999", do: errors ++ [:bsb_filler], else: errors + + errors = + if not correct_length?(first_blank, 12), do: errors ++ [:first_blank], else: errors + + errors = if not correct_length?(last_blank, 40), do: errors ++ [:last_blank], else: errors + + errors = if not correct_length?(mid_blank, 24), do: errors ++ [:mid_blank], else: errors + + errors = if string_empty?(net_total), do: errors ++ [:net_total], else: errors + + errors = if string_empty?(total_credit), do: errors ++ [:total_credit], else: errors + + errors = + if string_empty?(total_debit), + do: errors ++ [:total_debit], + else: errors + + errors = if string_empty?(record_count), do: errors ++ [:record_count], else: errors + + errors = + unless string_empty?(net_total) and string_empty?(total_credit) and + string_empty?(total_debit) do + net_amount = String.to_integer(net_total) + credit_amount = String.to_integer(total_credit) + debit_amount = String.to_integer(total_debit) + + if net_amount !== credit_amount - debit_amount, + do: errors ++ [:net_total_mismatch], + else: errors + else + errors + end - with true <- code == "7", - true <- correct_length?(bsb_filler, 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} + if(length(errors) > 0) do + {:error, :invalid_format, errors} else - _error -> - {:error, :invalid_format} + {:ok, net_total, total_credit, total_debit, record_count} end end end diff --git a/test/aba_file_validator_test.exs b/test/aba_file_validator_test.exs index 23c3590..b9cb942 100644 --- a/test/aba_file_validator_test.exs +++ b/test/aba_file_validator_test.exs @@ -94,8 +94,7 @@ defmodule AbaFileValidatorTest do "7999-999 000000000000000353890000035389 000002 " assert AbaFileValidator.get_file_total_record(entry) == - {:ok, "01", "CBA", "test ", "301500", "221212121227", - "121222"} + {:ok, "0000000000", "0000035389", "0000035389", "000002"} end test "returns an error if incorrect length with correct starting code" do @@ -119,15 +118,24 @@ defmodule AbaFileValidatorTest do "7999 999 000000000000000353890000035389 000002 " assert AbaFileValidator.get_file_total_record(entry) == - {:error, :invalid_format} + {:error, :invalid_format, [:bsb_filler]} end test "returns an error if empty string" do entry = "7 " - assert AbaFileValidator.get_descriptive_record(entry) == - {:error, :invalid_format} + assert AbaFileValidator.get_file_total_record(entry) == + {:error, :invalid_format, + [:bsb_filler, :net_total, :total_credit, :total_debit, :record_count]} + end + + test "returns an error if balance don't match" do + entry = + "7999 999 000000000000000353890000035388 000002 " + + assert AbaFileValidator.get_file_total_record(entry) == + {:error, :invalid_format, [:bsb_filler, :net_total_mismatch]} end end end From 2f7cd9e0a299f2b84f953122db3d38c0bc72b253 Mon Sep 17 00:00:00 2001 From: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> Date: Sun, 2 Apr 2023 00:02:52 +0800 Subject: [PATCH 7/7] refactor: added more tests Signed-off-by: alt-ctrl-dev <1557519+alt-ctrl-dev@users.noreply.github.com> --- lib/aba_file_validator.ex | 27 +++++++++++++++++++++------ test/aba_file_validator_test.exs | 16 ++++++++++++---- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/aba_file_validator.ex b/lib/aba_file_validator.ex index 6422669..d862f24 100644 --- a/lib/aba_file_validator.ex +++ b/lib/aba_file_validator.ex @@ -116,21 +116,26 @@ defmodule AbaFileValidator do iex> AbaFileValidator.get_file_total_record("1 01CBA test 301500221212121227121222 ") {:error, :incorrect_starting_code} - iex> AbaFileValidator.get_file_total_record("7999 999 000000000000000353890000035388 000002 ") + iex> AbaFileValidator.get_file_total_record("7999 999 000000000000000353890000035388 000000 ") {:error, :invalid_format, [:bsb_filler, :net_total_mismatch ]} iex> AbaFileValidator.get_file_total_record("7 ") {:error, :invalid_format, [:bsb_filler, :net_total, :total_credit, :total_debit, :record_count]} - iex> AbaFileValidator.get_file_total_record("7999-999 000000000000000353890000035389 000002 ") - {:ok, "0000000000", "0000035389", "0000035389", "000002"} + iex> AbaFileValidator.get_file_total_record("7999 999 000000000000000353890000035388 000002 ") + {:error, :invalid_format, [:bsb_filler, :net_total_mismatch, :records_mismatch]} + + iex> AbaFileValidator.get_file_total_record("7999-999 000000000000000353890000035389 000000 ") + {:ok, 0, 35389, 35389, 0} """ - def get_file_total_record(entry) when not is_binary(entry) do + def get_file_total_record(entry, records \\ 0) + + def get_file_total_record(entry, _records) when not is_binary(entry) do {:error, :invalid_input} end - def get_file_total_record(entry) do + def get_file_total_record(entry, records) when is_number(records) do if not correct_length?(entry, 120) do {:error, :incorrect_length} else @@ -183,10 +188,20 @@ defmodule AbaFileValidator do errors end + errors = + unless string_empty?(record_count) do + if records !== String.to_integer(record_count), + do: errors ++ [:records_mismatch], + else: errors + else + errors + end + if(length(errors) > 0) do {:error, :invalid_format, errors} else - {:ok, net_total, total_credit, total_debit, record_count} + {:ok, String.to_integer(net_total), String.to_integer(total_credit), + String.to_integer(total_debit), String.to_integer(record_count)} end end end diff --git a/test/aba_file_validator_test.exs b/test/aba_file_validator_test.exs index b9cb942..1bbf871 100644 --- a/test/aba_file_validator_test.exs +++ b/test/aba_file_validator_test.exs @@ -91,10 +91,10 @@ defmodule AbaFileValidatorTest do describe "AbaFileValidator.get_file_total_record/1" do test "validates succesfully" do entry = - "7999-999 000000000000000353890000035389 000002 " + "7999-999 000000000000000353890000035389 000000 " assert AbaFileValidator.get_file_total_record(entry) == - {:ok, "0000000000", "0000035389", "0000035389", "000002"} + {:ok, 0, 35389, 35389, 0} end test "returns an error if incorrect length with correct starting code" do @@ -115,7 +115,7 @@ defmodule AbaFileValidatorTest do test "returns an error if invalid string" do entry = - "7999 999 000000000000000353890000035389 000002 " + "7999 999 000000000000000353890000035389 000000 " assert AbaFileValidator.get_file_total_record(entry) == {:error, :invalid_format, [:bsb_filler]} @@ -132,10 +132,18 @@ defmodule AbaFileValidatorTest do test "returns an error if balance don't match" do entry = - "7999 999 000000000000000353890000035388 000002 " + "7999 999 000000000000000353890000035388 000000 " assert AbaFileValidator.get_file_total_record(entry) == {:error, :invalid_format, [:bsb_filler, :net_total_mismatch]} end + + test "returns an error if records don't match" do + entry = + "7999 999 000000000000000353890000035389 000002 " + + assert AbaFileValidator.get_file_total_record(entry) == + {:error, :invalid_format, [:bsb_filler, :records_mismatch]} + end end end