Skip to content
82 changes: 80 additions & 2 deletions lib/aba_file_validator.ex
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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"
Expand Down
13 changes: 13 additions & 0 deletions lib/util.ex
Original file line number Diff line number Diff line change
@@ -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?(<<dd::binary-2, mm::binary-2, yy::binary-2>>) 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
60 changes: 53 additions & 7 deletions test/aba_file_validator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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