aba 0.5.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -0
- data/README.md +10 -9
- data/Rakefile +2 -0
- data/aba.gemspec +4 -3
- data/lib/aba/batch.rb +26 -13
- data/lib/aba/entry.rb +4 -2
- data/lib/aba/return.rb +3 -2
- data/lib/aba/transaction.rb +7 -34
- data/lib/aba/validations.rb +10 -13
- data/lib/aba/version.rb +3 -1
- data/lib/aba.rb +2 -0
- data/spec/lib/aba/batch_spec.rb +101 -41
- data/spec/lib/aba/return_spec.rb +36 -14
- data/spec/lib/aba/transaction_spec.rb +53 -17
- data/spec/lib/aba/validations_spec.rb +16 -16
- data/spec/lib/aba_spec.rb +2 -0
- data/spec/spec_helper.rb +3 -0
- metadata +12 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c71962d082a5f069278f49f74ebeba542179be98dfe151ba74f6d348bee4b1f9
|
4
|
+
data.tar.gz: db6ce6a6b139f5ace5c1f386c779d629937c563e26dc541f97dc2f11734bf12e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c8bd0f8e21b4a911a439870df82b5663721d696a1d31a7e33fab9b8477c9d254202560c72952d8effc6df8b275653cf64b1b28daac1123f2ed0ac04b8749f1a
|
7
|
+
data.tar.gz: 204e6e3aa265fce388428b9ead10b510a1094d1030af3c19e1b75016fb00c78c510d31af782c24b9e13fabc0658ec28d42eee931f87ebfde3e92b58d18c30976
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## v1.0.2, 25 July 2022
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Enforce ABA validation:
|
8
|
+
- Amount (in cents) cannot exceed 10 characters.
|
9
|
+
- Total debit amount (in cents) cannot exceed 10 characters.
|
10
|
+
- Total credit amount (in cents) cannot exceed 10 characters.
|
11
|
+
|
12
|
+
## v1.0.1, 11 January 2021
|
13
|
+
|
14
|
+
### BUG FIX
|
15
|
+
|
16
|
+
Account numbers/alphas validation should be case insensitive
|
17
|
+
|
18
|
+
## v1.0.0, 12 July 2020
|
19
|
+
|
20
|
+
### BREAKING CHANGES
|
21
|
+
|
22
|
+
- Positive (`n`) and negative (`-n`) values are now treated the same. e.g `5`
|
23
|
+
and `-5` are both processed as `5`, without any signage. To differentiate
|
24
|
+
between a debit and credit, use the correct [Transaction
|
25
|
+
Code](https://github.com/andrba/aba/blob/58446f5b0ef822e9792e9399b4af647319b13515/lib/aba/transaction.rb#L106-L112)
|
26
|
+
- Removed default values for transactions records to avoid generation of
|
27
|
+
potentially incorrect records. Safety first!
|
28
|
+
- Minimum Ruby version is now 2.5
|
29
|
+
|
30
|
+
### NEW FEATURE
|
31
|
+
|
32
|
+
- You can now add a *return* record to be used when you'd like to return a
|
33
|
+
credit or a debit to another financial institution (OFI).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -65,28 +65,29 @@ There are a few ways to create a complete set of ABA data:
|
|
65
65
|
```ruby
|
66
66
|
# Transactions added to the defined ABA object variable
|
67
67
|
aba = Aba.batch financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615
|
68
|
-
aba.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000
|
69
|
-
aba.add_transaction bsb: '456-789', account_number: '123-456-789', amount:
|
68
|
+
aba.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000, transaction_code: 50
|
69
|
+
aba.add_transaction bsb: '456-789', account_number: '123-456-789', amount: 10000, transaction_code: 13
|
70
70
|
|
71
71
|
# Transactions passed individually inside a block
|
72
72
|
aba = Aba.batch financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615 do |a|
|
73
|
-
a.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000
|
74
|
-
a.add_transaction bsb: '456-789', account_number: '123-456-789', amount:
|
73
|
+
a.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000, transaction_code: 50
|
74
|
+
a.add_transaction bsb: '456-789', account_number: '123-456-789', amount: 10000, transaction_code: 13
|
75
75
|
end
|
76
76
|
|
77
77
|
# Transactions as an array passed to the second param of Aba.batch
|
78
78
|
aba = Aba.batch(
|
79
79
|
{ financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615 },
|
80
80
|
[
|
81
|
-
{ bsb: '123-456', account_number: '000-123-456', amount: 50000 },
|
82
|
-
{ bsb: '456-789', account_number: '123-456-789', amount:
|
81
|
+
{ bsb: '123-456', account_number: '000-123-456', amount: 50000, transaction_code: 50 },
|
82
|
+
{ bsb: '456-789', account_number: '123-456-789', amount: 10000, transaction_code: 13 }
|
83
83
|
]
|
84
84
|
)
|
85
|
-
|
86
|
-
# NOTE: Be careful with negative transaction amounts! transaction_code will not
|
87
|
-
# be set to debit automatically!
|
88
85
|
```
|
89
86
|
|
87
|
+
> **Note:** Positive (`n`) and negative (`-n`) values are now treated the same.
|
88
|
+
> e.g `5` and `-5` are both processed as `5`, without any signage.
|
89
|
+
> To differentiate between a debit and credit, use the correct [Transaction Code](https://github.com/andrba/aba/blob/58446f5b0ef822e9792e9399b4af647319b13515/lib/aba/transaction.rb#L106-L112)
|
90
|
+
|
90
91
|
Validation errors can be caught in several ways:
|
91
92
|
|
92
93
|
```ruby
|
data/Rakefile
CHANGED
data/aba.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# coding: utf-8
|
2
4
|
lib = File.expand_path('../lib', __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
@@ -18,9 +20,8 @@ Gem::Specification.new do |spec|
|
|
18
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
21
|
spec.require_paths = ["lib"]
|
20
22
|
|
21
|
-
spec.add_development_dependency "
|
22
|
-
spec.add_development_dependency "
|
23
|
-
spec.add_development_dependency "pry"
|
23
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
24
|
+
spec.add_development_dependency "pry", "~> 0.13"
|
24
25
|
spec.add_development_dependency "rspec", "~> 3.0"
|
25
26
|
|
26
27
|
spec.required_ruby_version = '>= 2.5.0'
|
data/lib/aba/batch.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Aba
|
2
4
|
class Batch
|
3
5
|
include Aba::Validations
|
@@ -28,6 +30,9 @@ class Aba
|
|
28
30
|
validates_length :process_at, 6
|
29
31
|
validates_integer :process_at, false
|
30
32
|
|
33
|
+
# Totals
|
34
|
+
validates_max_length :debit_total_amount, 10
|
35
|
+
validates_max_length :credit_total_amount, 10
|
31
36
|
|
32
37
|
def initialize(attrs = {}, transactions = [])
|
33
38
|
attrs.each do |key, value|
|
@@ -87,7 +92,10 @@ class Aba
|
|
87
92
|
# Build errors
|
88
93
|
all_errors = {}
|
89
94
|
all_errors[:aba] = self.error_collection unless self.error_collection.empty?
|
90
|
-
entry_error_collection = entries.each_with_index
|
95
|
+
entry_error_collection = entries.each_with_index
|
96
|
+
.map { |t, i| [i, t.error_collection] }
|
97
|
+
.reject { |e| e[1].nil? || e[1].empty? }
|
98
|
+
.to_h
|
91
99
|
all_errors[:entries] = entry_error_collection unless entry_error_collection.empty?
|
92
100
|
|
93
101
|
all_errors unless all_errors.empty?
|
@@ -165,15 +173,8 @@ class Aba
|
|
165
173
|
end
|
166
174
|
|
167
175
|
def batch_control_record
|
168
|
-
|
169
|
-
|
170
|
-
debit_total_amount = 0
|
171
|
-
|
172
|
-
entries.each do |t|
|
173
|
-
net_total_amount += t.amount.to_i
|
174
|
-
credit_total_amount += t.amount.to_i if t.amount.to_i > 0
|
175
|
-
debit_total_amount += t.amount.to_i if t.amount.to_i < 0
|
176
|
-
end
|
176
|
+
cached_credit_total_amount = credit_total_amount
|
177
|
+
cached_debit_total_amount = debit_total_amount
|
177
178
|
|
178
179
|
# Record type
|
179
180
|
# Max: 1
|
@@ -193,17 +194,17 @@ class Aba
|
|
193
194
|
# Net total
|
194
195
|
# Max: 10
|
195
196
|
# Char position: 21-30
|
196
|
-
output +=
|
197
|
+
output += (cached_credit_total_amount - cached_debit_total_amount).abs.to_s.rjust(10, "0")
|
197
198
|
|
198
199
|
# Credit Total Amount
|
199
200
|
# Max: 10
|
200
201
|
# Char position: 31-40
|
201
|
-
output +=
|
202
|
+
output += cached_credit_total_amount.to_s.rjust(10, "0")
|
202
203
|
|
203
204
|
# Debit Total Amount
|
204
205
|
# Max: 10
|
205
206
|
# Char position: 41-50
|
206
|
-
output +=
|
207
|
+
output += cached_debit_total_amount.to_s.rjust(10, "0")
|
207
208
|
|
208
209
|
# Reserved
|
209
210
|
# Max: 24
|
@@ -220,5 +221,17 @@ class Aba
|
|
220
221
|
# Char position: 81-120
|
221
222
|
output += " " * 40
|
222
223
|
end
|
224
|
+
|
225
|
+
def credit_total_amount
|
226
|
+
credit_total_amount ||= entries.reject(&:debit?).sum(&method(:entry_amount))
|
227
|
+
end
|
228
|
+
|
229
|
+
def debit_total_amount
|
230
|
+
entries.select(&:debit?).sum(&method(:entry_amount))
|
231
|
+
end
|
232
|
+
|
233
|
+
def entry_amount(entry)
|
234
|
+
entry.amount.to_s[/\A\-?\d+\z/] ? Integer(entry.amount).abs : 0
|
235
|
+
end
|
223
236
|
end
|
224
237
|
end
|
data/lib/aba/entry.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Aba
|
2
4
|
class Entry
|
3
5
|
def initialize(attrs = {})
|
@@ -7,11 +9,11 @@ class Aba
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def credit?
|
10
|
-
|
12
|
+
Validations::CREDIT_TRANSACTION_CODES.include?(transaction_code.to_i)
|
11
13
|
end
|
12
14
|
|
13
15
|
def debit?
|
14
|
-
transaction_code.to_i
|
16
|
+
Validations::DEBIT_TRANSACTION_CODES.include?(transaction_code.to_i)
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
data/lib/aba/return.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Aba
|
2
4
|
class Return < Entry
|
3
5
|
include Aba::Validations
|
@@ -20,7 +22,7 @@ class Aba
|
|
20
22
|
validates_transaction_code :transaction_code
|
21
23
|
|
22
24
|
# Amount
|
23
|
-
|
25
|
+
validates_integer :amount
|
24
26
|
|
25
27
|
# Original Day of Processing
|
26
28
|
validates_integer :original_processing_day, :unsigned
|
@@ -45,7 +47,6 @@ class Aba
|
|
45
47
|
validates_max_length :name_of_remitter, 16
|
46
48
|
validates_becs :name_of_remitter
|
47
49
|
|
48
|
-
|
49
50
|
# Allow dashes to be input, but remove them from output
|
50
51
|
def account_number
|
51
52
|
@account_number ? @account_number.to_s.delete('-') : nil
|
data/lib/aba/transaction.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Aba
|
2
4
|
class Transaction < Entry
|
3
5
|
include Aba::Validations
|
@@ -19,7 +21,8 @@ class Aba
|
|
19
21
|
validates_transaction_code :transaction_code
|
20
22
|
|
21
23
|
# Amount
|
22
|
-
|
24
|
+
validates_integer :amount
|
25
|
+
validates_max_length :amount, 10
|
23
26
|
|
24
27
|
# Account Name
|
25
28
|
validates_max_length :account_name, 32
|
@@ -37,51 +40,21 @@ class Aba
|
|
37
40
|
validates_max_length :name_of_remitter, 16
|
38
41
|
validates_becs :name_of_remitter
|
39
42
|
|
40
|
-
|
41
43
|
# Allow dashes to be input, but remove them from output
|
42
44
|
def account_number
|
43
45
|
@account_number ? @account_number.to_s.gsub('-', '') : nil
|
44
46
|
end
|
45
47
|
|
46
|
-
#
|
48
|
+
# Sane default for majority of use cases as per BECS
|
47
49
|
def indicator
|
48
|
-
@indicator ||
|
49
|
-
end
|
50
|
-
|
51
|
-
# Fall back to 50
|
52
|
-
def transaction_code
|
53
|
-
@transaction_code || 50
|
54
|
-
end
|
55
|
-
|
56
|
-
# Fall back to 0
|
57
|
-
def amount
|
58
|
-
@amount || 0
|
59
|
-
end
|
60
|
-
|
61
|
-
# Fall back to empty string
|
62
|
-
def account_name
|
63
|
-
@account_name || ''
|
50
|
+
@indicator || ' '
|
64
51
|
end
|
65
52
|
|
66
|
-
#
|
53
|
+
# Optional as per BECS
|
67
54
|
def lodgement_reference
|
68
55
|
@lodgement_reference || ''
|
69
56
|
end
|
70
57
|
|
71
|
-
# Fall back to BSB
|
72
|
-
def trace_bsb
|
73
|
-
@trace_bsb || bsb
|
74
|
-
end
|
75
|
-
|
76
|
-
# Fall back to Account Number
|
77
|
-
def trace_account_number
|
78
|
-
@trace_account_number ? @trace_account_number.to_s.gsub('-', '') : account_number
|
79
|
-
end
|
80
|
-
|
81
|
-
def name_of_remitter
|
82
|
-
@name_of_remitter || ''
|
83
|
-
end
|
84
|
-
|
85
58
|
def to_s
|
86
59
|
raise RuntimeError, 'Transaction data is invalid - check the contents of `errors`' unless valid?
|
87
60
|
|
data/lib/aba/validations.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Aba
|
2
4
|
module Validations
|
3
5
|
attr_accessor :error_collection
|
4
6
|
|
5
7
|
BECS_PATTERN = /\A[\w\+\-\@\ \$\!\%\&\(\)\*\.\/\#\=\:\;\?\,\'\[\]\_\^]*\Z/
|
6
8
|
INDICATORS = [' ', 'N', 'T', 'W', 'X', 'Y']
|
9
|
+
DEBIT_TRANSACTION_CODES = [13]
|
10
|
+
CREDIT_TRANSACTION_CODES = [50, 51, 52, 53, 54, 55, 56, 57]
|
7
11
|
|
8
12
|
def self.included(base)
|
9
13
|
base.instance_eval do
|
@@ -13,6 +17,10 @@ class Aba
|
|
13
17
|
base.send :extend, ClassMethods
|
14
18
|
end
|
15
19
|
|
20
|
+
def self.transaction_codes
|
21
|
+
DEBIT_TRANSACTION_CODES + CREDIT_TRANSACTION_CODES
|
22
|
+
end
|
23
|
+
|
16
24
|
def valid?
|
17
25
|
!has_errors?
|
18
26
|
end
|
@@ -46,14 +54,8 @@ class Aba
|
|
46
54
|
else
|
47
55
|
self.error_collection << "#{attribute} must be an unsigned number" unless value.to_s =~ /\A\d+\Z/
|
48
56
|
end
|
49
|
-
when :matches_transaction_code
|
50
|
-
if debit? && value.to_i > 0
|
51
|
-
self.error_collection << "#{attribute} is positive but the transaction type is a debit"
|
52
|
-
elsif credit? && value.to_i < 0
|
53
|
-
self.error_collection << "#{attribute} is negative but the transaction type is a credit"
|
54
|
-
end
|
55
57
|
when :account_number
|
56
|
-
if value.to_s =~ /\A[0\ ]+\Z/ || value.to_s !~ /\A[a-z\d\ ]{1,9}\Z/
|
58
|
+
if value.to_s =~ /\A[0\ ]+\Z/ || value.to_s !~ /\A[a-z\d\ ]{1,9}\Z/i
|
57
59
|
self.error_collection << "#{attribute} must be a valid account number"
|
58
60
|
end
|
59
61
|
when :becs
|
@@ -62,7 +64,7 @@ class Aba
|
|
62
64
|
list = INDICATORS.join('\', \'')
|
63
65
|
self.error_collection << "#{attribute} must be a one of '#{list}'" unless INDICATORS.include?(value.to_s)
|
64
66
|
when :transaction_code
|
65
|
-
self.error_collection << "#{attribute} must be
|
67
|
+
self.error_collection << "#{attribute} must be one of #{Validations.transaction_codes.join(', ')}" unless Validations.transaction_codes.include?(value.to_i)
|
66
68
|
end
|
67
69
|
end
|
68
70
|
end
|
@@ -94,11 +96,6 @@ class Aba
|
|
94
96
|
add_validation_attribute(attribute, :integer, signed)
|
95
97
|
end
|
96
98
|
|
97
|
-
def validates_amount(attribute)
|
98
|
-
add_validation_attribute(attribute, :integer, true)
|
99
|
-
add_validation_attribute(attribute, :matches_transaction_code)
|
100
|
-
end
|
101
|
-
|
102
99
|
def validates_account_number(attribute)
|
103
100
|
add_validation_attribute(attribute, :account_number)
|
104
101
|
end
|
data/lib/aba/version.rb
CHANGED
data/lib/aba.rb
CHANGED
data/spec/lib/aba/batch_spec.rb
CHANGED
@@ -1,40 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding: UTF-8
|
2
4
|
|
3
5
|
require "spec_helper"
|
4
6
|
|
5
7
|
describe Aba::Batch do
|
6
|
-
subject(:batch)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
trace_account_number: '45656733', name_of_remitter: 'Remitter')
|
15
|
-
end
|
8
|
+
subject(:batch) do
|
9
|
+
Aba::Batch.new(
|
10
|
+
financial_institution: "WPC",
|
11
|
+
user_name: "John Doe",
|
12
|
+
user_id: "466364",
|
13
|
+
description: "Payroll",
|
14
|
+
process_at: "190615",
|
15
|
+
)
|
16
16
|
end
|
17
|
-
before { transactions.each { |trx| batch.add_transaction(trx) } }
|
18
|
-
|
19
|
-
let(:return_amounts) { [[53, 3], [13, -2]] }
|
20
|
-
let(:returns) do
|
21
|
-
return_amounts.map do |(transaction_code, amount)|
|
22
|
-
Aba::Return.new(bsb: '453-543', account_number: '45656733', amount: amount,
|
23
|
-
account_name: 'John Doe', transaction_code: transaction_code,
|
24
|
-
lodgement_reference: 'R435564', trace_bsb: '342-342',
|
25
|
-
trace_account_number: '3244654', name_of_remitter: 'Remitter',
|
26
|
-
return_code: 8, original_user_id: 654321,
|
27
|
-
original_processing_day: 12,
|
28
17
|
|
18
|
+
let(:transactions_attributes) { [{amount: 30, transaction_code: 50}, {amount: 20, transaction_code: 13}] }
|
19
|
+
let(:returns_attributes) { [{amount: 3, transaction_code: 50}, {amount: 2, transaction_code: 13}] }
|
20
|
+
|
21
|
+
before do
|
22
|
+
transactions_attributes.each do |attr|
|
23
|
+
transaction = Aba::Transaction.new(
|
24
|
+
bsb: '342-342',
|
25
|
+
account_number: '3244654',
|
26
|
+
amount: attr[:amount],
|
27
|
+
account_name: 'John Doe',
|
28
|
+
transaction_code: attr[:transaction_code],
|
29
|
+
lodgement_reference: 'R435564',
|
30
|
+
trace_bsb: '453-543',
|
31
|
+
trace_account_number: '45656733',
|
32
|
+
name_of_remitter: 'Remitter',
|
29
33
|
)
|
34
|
+
|
35
|
+
batch.add_transaction(transaction)
|
36
|
+
end
|
37
|
+
|
38
|
+
returns_attributes.map do |attr|
|
39
|
+
ret = Aba::Return.new(
|
40
|
+
bsb: '453-543',
|
41
|
+
account_number: '45656733',
|
42
|
+
amount: attr[:amount],
|
43
|
+
account_name: 'John Doe',
|
44
|
+
transaction_code: attr[:transaction_code],
|
45
|
+
lodgement_reference: 'R435564',
|
46
|
+
trace_bsb: '342-342',
|
47
|
+
trace_account_number: '3244654',
|
48
|
+
name_of_remitter: 'Remitter',
|
49
|
+
return_code: 8,
|
50
|
+
original_user_id: 654321,
|
51
|
+
original_processing_day: 12,
|
52
|
+
)
|
53
|
+
|
54
|
+
batch.add_return(ret)
|
30
55
|
end
|
31
56
|
end
|
32
|
-
before { returns.each { |trx| batch.add_return(trx) } }
|
33
57
|
|
34
58
|
describe "#to_s" do
|
35
|
-
|
36
59
|
context 'when descriptive record' do
|
37
|
-
|
38
60
|
context 'without bsb' do
|
39
61
|
it "should return a string containing the descriptive record without the bsb" do
|
40
62
|
expect(batch.to_s).to include("0 01WPC John Doe 466364Payroll 190615 \r\n")
|
@@ -43,6 +65,7 @@ describe Aba::Batch do
|
|
43
65
|
|
44
66
|
context 'with bsb' do
|
45
67
|
before { batch.bsb = "123-345" }
|
68
|
+
|
46
69
|
it "should return a string containing the descriptive record with the bsb" do
|
47
70
|
expect(batch.to_s).to include("0123-345 01WPC John Doe 466364Payroll 190615 \r\n")
|
48
71
|
end
|
@@ -51,50 +74,87 @@ describe Aba::Batch do
|
|
51
74
|
|
52
75
|
|
53
76
|
context 'when detail record' do
|
54
|
-
|
55
77
|
it "should contain transaction & return records" do
|
56
|
-
expect(batch.to_s).to include("1342-342 3244654
|
78
|
+
expect(batch.to_s).to include("1342-342 3244654 500000000030John Doe R435564 453-543 45656733Remitter 00000000\r\n")
|
57
79
|
expect(batch.to_s).to include("1342-342 3244654 130000000020John Doe R435564 453-543 45656733Remitter 00000000\r\n")
|
58
|
-
expect(batch.to_s).to include("2453-543
|
80
|
+
expect(batch.to_s).to include("2453-543 456567338500000000003John Doe R435564 342-342 3244654Remitter 12654321\r\n")
|
59
81
|
expect(batch.to_s).to include("2453-543 456567338130000000002John Doe R435564 342-342 3244654Remitter 12654321\r\n")
|
60
82
|
end
|
61
83
|
end
|
62
84
|
|
63
85
|
context 'when file total record' do
|
64
|
-
|
65
86
|
context 'with unbalanced transactions' do
|
66
87
|
it "should return a string where the net total is not zero" do
|
67
88
|
expect(batch.to_s).to include("7999-999 000000001100000000330000000022 000004 ")
|
89
|
+
# | Total || Credit || Debit |
|
68
90
|
end
|
69
91
|
end
|
70
92
|
|
71
93
|
context 'with balanced transactions' do
|
72
|
-
let(:
|
73
|
-
|
94
|
+
let(:transactions_attributes) do
|
95
|
+
[{amount: 30, transaction_code: 50}, {amount: 30, transaction_code: 13}, {amount: 30, transaction_code: 50}]
|
96
|
+
end
|
97
|
+
let(:returns_attributes) do
|
98
|
+
[{amount: 3, transaction_code: 50}, {amount: 3, transaction_code: 13}, {amount: 30, transaction_code: 13}]
|
99
|
+
end
|
100
|
+
|
74
101
|
it "should return a string where the net total is zero" do
|
75
|
-
expect(batch.to_s).to include("7999-999
|
102
|
+
expect(batch.to_s).to include("7999-999 000000000000000000630000000063 000006 ")
|
103
|
+
# | Total || Credit || Debit |
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'with negative values supplied for the amounts' do
|
108
|
+
let(:transactions_attributes) { [{amount: -30, transaction_code: 50}, {amount: -20, transaction_code: 13}] }
|
109
|
+
let(:returns_attributes) { [{amount: -3, transaction_code: 50}, {amount: 2, transaction_code: 13}] }
|
110
|
+
|
111
|
+
it 'should return a string where the amount segments rely on the transaction code, not the amount sign' do
|
112
|
+
expect(batch.to_s).to include("7999-999 000000001100000000330000000022 000004 ")
|
113
|
+
# | Total || Credit || Debit |
|
76
114
|
end
|
115
|
+
|
77
116
|
end
|
78
117
|
end
|
79
118
|
end
|
80
119
|
|
81
120
|
describe "#errors" do
|
82
|
-
|
83
|
-
let(:errors) { subject.errors }
|
84
|
-
|
85
121
|
it "is empty" do
|
86
|
-
expect(errors).to be_nil
|
122
|
+
expect(batch.errors).to be_nil
|
87
123
|
end
|
88
124
|
|
89
125
|
context "with an invalid amount" do
|
90
|
-
let(:
|
91
|
-
[
|
126
|
+
let(:transactions_attributes) do
|
127
|
+
[{amount: 1, transaction_code: 50}, {amount: 'abc', transaction_code: 13}, {amount: 'def', transaction_code: 50}]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "reports the errors" do
|
131
|
+
expect(batch.errors).to eq(:entries => { 1 => ["amount must be a number"], 2 => ["amount must be a number"] })
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with an invalid credit total (exceeding 10 characters)" do
|
136
|
+
let(:transactions_attributes) do
|
137
|
+
[
|
138
|
+
{amount: 9999999999, transaction_code: 50},
|
139
|
+
{amount: 9999999999, transaction_code: 50},
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
it "reports the errors" do
|
144
|
+
expect(batch.errors).to include(aba: ["credit_total_amount length must not exceed 10 characters"])
|
92
145
|
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with an invalid debit total amount (exceeding 10 characters)" do
|
149
|
+
let(:transactions_attributes) do
|
150
|
+
[
|
151
|
+
{amount: 9999999999, transaction_code: 13},
|
152
|
+
{amount: 9999999999, transaction_code: 13},
|
153
|
+
]
|
154
|
+
end
|
155
|
+
|
93
156
|
it "reports the errors" do
|
94
|
-
expect(errors).to
|
95
|
-
1 => ["amount is negative but the transaction type is a credit"],
|
96
|
-
2 => ["amount must be a number"]
|
97
|
-
})
|
157
|
+
expect(batch.errors).to include(aba: ["debit_total_amount length must not exceed 10 characters"])
|
98
158
|
end
|
99
159
|
end
|
100
160
|
end
|
data/spec/lib/aba/return_spec.rb
CHANGED
@@ -1,24 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding: UTF-8
|
2
4
|
|
3
5
|
require "spec_helper"
|
4
6
|
|
5
7
|
describe Aba::Return do
|
6
|
-
let(:transaction_params) { {
|
7
|
-
:trace_account_number => 23432342,
|
8
|
-
:transaction_code => 53,
|
9
|
-
:amount => 50050,
|
10
|
-
:account_name => "John Doe",
|
11
|
-
:trace_bsb => "345-453",
|
12
|
-
:return_code => 8,
|
13
|
-
:lodgement_reference => "R45343",
|
14
|
-
:bsb => "123-234",
|
15
|
-
:account_number => "4647642",
|
16
|
-
:name_of_remitter => "Remitter",
|
17
|
-
:original_processing_day => "07",
|
18
|
-
:original_user_id => "054321",
|
19
|
-
} }
|
20
8
|
subject(:transaction) { Aba::Return.new(transaction_params) }
|
21
9
|
|
10
|
+
let(:transaction_attributes) { {amount: 50050, transaction_code: 53} }
|
11
|
+
let(:transaction_params) do
|
12
|
+
{
|
13
|
+
:trace_account_number => 23432342,
|
14
|
+
:transaction_code => transaction_attributes[:transaction_code],
|
15
|
+
:amount => transaction_attributes[:amount],
|
16
|
+
:account_name => "John Doe",
|
17
|
+
:trace_bsb => "345-453",
|
18
|
+
:return_code => 8,
|
19
|
+
:lodgement_reference => "R45343",
|
20
|
+
:bsb => "123-234",
|
21
|
+
:account_number => "4647642",
|
22
|
+
:name_of_remitter => "Remitter",
|
23
|
+
:original_processing_day => "07",
|
24
|
+
:original_user_id => "054321",
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
22
28
|
describe "#to_s" do
|
23
29
|
it "should create a transaction row" do
|
24
30
|
expect(subject.to_s).to include(
|
@@ -31,6 +37,22 @@ describe Aba::Return do
|
|
31
37
|
# | +-trace_bsb
|
32
38
|
# +-lodgement_reference
|
33
39
|
end
|
40
|
+
|
41
|
+
context 'when supplied amount is negative' do
|
42
|
+
let(:transaction_attributes) { {amount: -50050, transaction_code: 53} }
|
43
|
+
|
44
|
+
it "should create a transaction row where the amount does not have a sign" do
|
45
|
+
expect(subject.to_s).to include(
|
46
|
+
"2123-234 46476428530000050050John Doe R45343 345-453 23432342Remitter 07054321")
|
47
|
+
# | | || | | | | | | | |
|
48
|
+
# +-bsb | || +-amount +-account_name | | | | | +-original_user_id
|
49
|
+
# | |+-transaction_code | | | | +-original_processing_day
|
50
|
+
# | +-return_code | | | +-name_of_remitter
|
51
|
+
# +-account_number | | +-trace_account_number
|
52
|
+
# | +-trace_bsb
|
53
|
+
# +-lodgement_reference
|
54
|
+
end
|
55
|
+
end
|
34
56
|
end
|
35
57
|
|
36
58
|
describe "#valid?" do
|
@@ -1,27 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding: UTF-8
|
2
4
|
|
3
5
|
require "spec_helper"
|
4
6
|
|
5
7
|
describe Aba::Transaction do
|
6
|
-
let(:transaction_params) { {
|
7
|
-
:account_number => 23432342,
|
8
|
-
:transaction_code => 53,
|
9
|
-
:amount => 50050,
|
10
|
-
:account_name => "John Doe",
|
11
|
-
:bsb => "345-453",
|
12
|
-
:witholding_amount => 87,
|
13
|
-
:indicator => "W",
|
14
|
-
:lodgement_reference => "R45343",
|
15
|
-
:trace_bsb => "123-234",
|
16
|
-
:trace_account_number => "4647642",
|
17
|
-
:name_of_remitter => "Remitter"
|
18
|
-
} }
|
19
8
|
subject(:transaction) { Aba::Transaction.new(transaction_params) }
|
20
9
|
|
10
|
+
let(:transaction_attributes) { {amount: 50050, transaction_code: 53} }
|
11
|
+
|
12
|
+
let(:transaction_params) do
|
13
|
+
{
|
14
|
+
:account_number => 23432342,
|
15
|
+
:transaction_code => transaction_attributes[:transaction_code],
|
16
|
+
:amount => transaction_attributes[:amount],
|
17
|
+
:account_name => "John Doe",
|
18
|
+
:bsb => "345-453",
|
19
|
+
:witholding_amount => 87,
|
20
|
+
:indicator => "W",
|
21
|
+
:lodgement_reference => "R45343",
|
22
|
+
:trace_bsb => "123-234",
|
23
|
+
:trace_account_number => "4647642",
|
24
|
+
:name_of_remitter => "Remitter",
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
21
28
|
describe "#to_s" do
|
22
29
|
it "should create a transaction row" do
|
23
30
|
expect(subject.to_s).to include("1345-453 23432342W530000050050John Doe R45343 123-234 4647642Remitter 00000087")
|
24
31
|
end
|
32
|
+
|
33
|
+
context 'when supplied amount is negative' do
|
34
|
+
let(:transaction_attributes) { {amount: -50050, transaction_code: 53} }
|
35
|
+
|
36
|
+
it "should create a transaction row where the amount does not have a sign" do
|
37
|
+
expect(subject.to_s).to include("1345-453 23432342W530000050050John Doe R45343 123-234 4647642Remitter 00000087")
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
27
42
|
describe "#valid?" do
|
@@ -29,10 +44,31 @@ describe Aba::Transaction do
|
|
29
44
|
expect(subject.valid?).to eq true
|
30
45
|
end
|
31
46
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
47
|
+
context "without bsb param" do
|
48
|
+
before do
|
49
|
+
transaction_params.delete(:bsb)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "is invalid" do
|
53
|
+
expect(subject.valid?).to eq false
|
54
|
+
expect(subject.errors).to eq ["bsb format is incorrect"]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ":amount" do
|
59
|
+
subject(:transaction) { Aba::Transaction.new(transaction_params.merge(amount: amount)) }
|
60
|
+
|
61
|
+
context "with 10 digits" do
|
62
|
+
let(:amount) { "1234567890" }
|
63
|
+
|
64
|
+
it { is_expected.to be_valid }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with 11 digits" do
|
68
|
+
let(:amount) { "12345678901" }
|
69
|
+
|
70
|
+
it { is_expected.not_to be_valid }
|
71
|
+
end
|
36
72
|
end
|
37
73
|
end
|
38
74
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding: UTF-8
|
2
4
|
|
3
5
|
require "spec_helper"
|
@@ -138,8 +140,7 @@ describe Aba::Validations do
|
|
138
140
|
expect(subject.errors).to eq ["attr1 must be a valid account number"]
|
139
141
|
|
140
142
|
subject.attr1 = "00 0A0"
|
141
|
-
expect(subject.valid?).to eq
|
142
|
-
expect(subject.errors).to eq ["attr1 must be a valid account number"]
|
143
|
+
expect(subject.valid?).to eq true
|
143
144
|
|
144
145
|
subject.attr1 = "00 111"
|
145
146
|
expect(subject.valid?).to eq true
|
@@ -152,6 +153,9 @@ describe Aba::Validations do
|
|
152
153
|
|
153
154
|
subject.attr1 = "aa aaa"
|
154
155
|
expect(subject.valid?).to eq true
|
156
|
+
|
157
|
+
subject.attr1 = "1A2B3C"
|
158
|
+
expect(subject.valid?).to eq true
|
155
159
|
end
|
156
160
|
|
157
161
|
it "should validate becs" do
|
@@ -180,35 +184,31 @@ describe Aba::Validations do
|
|
180
184
|
|
181
185
|
subject.attr1 = "$"
|
182
186
|
expect(subject.valid?).to eq false
|
183
|
-
list =
|
187
|
+
list = described_class::INDICATORS.join('\', \'')
|
184
188
|
expect(subject.errors).to eq ["attr1 must be a one of '#{list}'"]
|
185
189
|
|
186
|
-
subject.attr1 =
|
190
|
+
subject.attr1 = described_class::INDICATORS.sample
|
187
191
|
expect(subject.valid?).to eq true
|
188
192
|
end
|
189
193
|
|
190
194
|
it "should validate transaction code" do
|
191
195
|
clean_room.instance_eval do
|
192
|
-
attr_accessor :
|
193
|
-
validates_transaction_code :
|
196
|
+
attr_accessor :transaction_code
|
197
|
+
validates_transaction_code :transaction_code
|
194
198
|
end
|
195
199
|
|
196
|
-
subject.
|
197
|
-
expect(subject.valid?).to eq false
|
198
|
-
expect(subject.errors).to eq ["attr1 must be a 2 digit number"]
|
199
|
-
|
200
|
-
subject.attr1 = "123"
|
200
|
+
subject.transaction_code = "AA"
|
201
201
|
expect(subject.valid?).to eq false
|
202
|
-
expect(subject.errors).to eq ["
|
202
|
+
expect(subject.errors).to eq ["transaction_code must be one of #{described_class::transaction_codes.join(', ')}"]
|
203
203
|
|
204
|
-
subject.
|
204
|
+
subject.transaction_code = "1"
|
205
205
|
expect(subject.valid?).to eq false
|
206
|
-
expect(subject.errors).to eq ["
|
206
|
+
expect(subject.errors).to eq ["transaction_code must be one of #{described_class::transaction_codes.join(', ')}"]
|
207
207
|
|
208
|
-
subject.
|
208
|
+
subject.transaction_code = "13"
|
209
209
|
expect(subject.valid?).to eq true
|
210
210
|
|
211
|
-
subject.
|
211
|
+
subject.transaction_code = 50
|
212
212
|
expect(subject.valid?).to eq true
|
213
213
|
end
|
214
214
|
end
|
data/spec/lib/aba_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Bazhutkin
|
@@ -9,50 +9,36 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: bundler
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '0'
|
21
|
-
type: :development
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '0'
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: rake
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
31
17
|
requirements:
|
32
|
-
- - "
|
18
|
+
- - "~>"
|
33
19
|
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
20
|
+
version: '13.0'
|
35
21
|
type: :development
|
36
22
|
prerelease: false
|
37
23
|
version_requirements: !ruby/object:Gem::Requirement
|
38
24
|
requirements:
|
39
|
-
- - "
|
25
|
+
- - "~>"
|
40
26
|
- !ruby/object:Gem::Version
|
41
|
-
version: '0'
|
27
|
+
version: '13.0'
|
42
28
|
- !ruby/object:Gem::Dependency
|
43
29
|
name: pry
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
45
31
|
requirements:
|
46
|
-
- - "
|
32
|
+
- - "~>"
|
47
33
|
- !ruby/object:Gem::Version
|
48
|
-
version: '0'
|
34
|
+
version: '0.13'
|
49
35
|
type: :development
|
50
36
|
prerelease: false
|
51
37
|
version_requirements: !ruby/object:Gem::Requirement
|
52
38
|
requirements:
|
53
|
-
- - "
|
39
|
+
- - "~>"
|
54
40
|
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
41
|
+
version: '0.13'
|
56
42
|
- !ruby/object:Gem::Dependency
|
57
43
|
name: rspec
|
58
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,6 +64,7 @@ files:
|
|
78
64
|
- ".gitignore"
|
79
65
|
- ".rspec"
|
80
66
|
- ".travis.yml"
|
67
|
+
- CHANGELOG.md
|
81
68
|
- Gemfile
|
82
69
|
- LICENSE
|
83
70
|
- README.md
|
@@ -115,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
102
|
- !ruby/object:Gem::Version
|
116
103
|
version: '0'
|
117
104
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
105
|
+
rubygems_version: 3.1.6
|
119
106
|
signing_key:
|
120
107
|
specification_version: 4
|
121
108
|
summary: ABA File Generator
|