aba 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 035b4d53937aa04c7e72ef453991925a744533eb
4
- data.tar.gz: 3f80ba614237f025a5a269ae2f7485ad6805ac6c
3
+ metadata.gz: f11f3830479ca1fad3b854bb9459f99ce7dc8f5a
4
+ data.tar.gz: f793d6648ffc17e7589b2c5db57b26f548c5800e
5
5
  SHA512:
6
- metadata.gz: db7069fdba989915c2abfe634991af7443d3f24cbdd1b95bd1f4001118e7f369b2f4cd0cdcf3ca8833f0801e42beeaf4cf639c18c0efc3ee47dc0010ce72de27
7
- data.tar.gz: c9591d89dfe8f8c9177debc5791603f4ef923e2c48176887b98e4e040ed6d125ea294af654b367e61b03b487bed2d571e4118e8c4759c718f546bf6d33b5e767
6
+ metadata.gz: b350430aa9ee2c21cfa6d239c6871fcb3626f724dbd67d5cc5d58dac4d627c16b1e2873d1d4c4e9e80e0ca11acec6a5dfede5bae8b8184fcd8ab182ced99e7d9
7
+ data.tar.gz: 356d63f3de331b90a69fc8d586690eb793fa606c8544f4bfc481a8a055ee96811c98a76158617db3e773f13a126eab2a0b53f62d5ac0ddcf0985e1f09ce8bec3
data/.rspec CHANGED
@@ -1 +1,3 @@
1
- --color
1
+ --color
2
+ --require spec_helper
3
+ --format d
@@ -2,6 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.2
6
- - 2.2.2
7
- script: bundle exec rspec spec
5
+ - 2.1.7
6
+ - 2.2.3
7
+ script: bundle exec rspec spec
data/README.md CHANGED
@@ -10,29 +10,29 @@ Generates ABA (Australian Banking Association) file format output
10
10
  require 'aba'
11
11
 
12
12
  # Initialise ABA
13
- aba = Aba.new(
13
+ aba = Aba.batch(
14
14
  bsb: "123-345", # Optional (Not required by NAB)
15
- financial_institution: "WPC",
15
+ financial_institution: "WPC",
16
16
  user_name: "John Doe",
17
- user_id: "466364",
18
- description: "Payroll",
17
+ user_id: "466364",
18
+ description: "Payroll",
19
19
  process_at: Time.now.strftime("%d%m%y")
20
20
  )
21
21
 
22
22
  # Add transactions
23
23
  10.times do
24
24
  aba.add_transaction(
25
- Aba::Transaction.new(
26
- bsb: "342-342",
27
- account_number: "3244654",
25
+ {
26
+ bsb: "342-342",
27
+ account_number: "3244654",
28
28
  amount: 10000, # Amount in cents
29
- account_name: "John Doe",
29
+ account_name: "John Doe",
30
30
  transaction_code: 53,
31
- lodgement_reference: "R435564",
32
- trace_bsb: "453-543",
33
- trace_account_number: "45656733",
31
+ lodgement_reference: "R435564",
32
+ trace_bsb: "453-543",
33
+ trace_account_number: "45656733",
34
34
  name_of_remitter: "Remitter"
35
- )
35
+ }
36
36
  )
37
37
  end
38
38
 
@@ -40,6 +40,66 @@ puts aba.to_s # View output
40
40
  File.write("/Users/me/dd_#{Time.now.to_i}.aba", aba.to_s) # or write output to file
41
41
  ```
42
42
 
43
+ There are a few ways to create a complete set of ABA data:
44
+
45
+ ```ruby
46
+ # Transactions added to the defined ABA object variable
47
+ aba = Aba.batch financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615
48
+ aba.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000
49
+ aba.add_transaction bsb: '456-789', account_number: '123-456-789', amount: '-10000', transaction_code: 13
50
+
51
+ # Transactions passed individually inside a block
52
+ aba = Aba.batch financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615 do |a|
53
+ a.add_transaction bsb: '123-456', account_number: '000-123-456', amount: 50000
54
+ a.add_transaction bsb: '456-789', account_number: '123-456-789', amount: '-10000', transaction_code: 13
55
+ end
56
+
57
+ # Transactions as an array passed to the second param of Aba.batch
58
+ aba = Aba.batch(
59
+ { financial_institution: 'ANZ', user_name: 'Joe Blow', user_id: 123456, process_at: 200615 },
60
+ [
61
+ { bsb: '123-456', account_number: '000-123-456', amount: 50000 },
62
+ { bsb: '456-789', account_number: '123-456-789', amount: '-10000', transaction_code: 13 }
63
+ ]
64
+ )
65
+
66
+ # NOTE: Be careful with negative transaction amounts! transaction_code will not
67
+ # be set to debit automatically!
68
+ ```
69
+
70
+ Validation errors can be caught in several ways:
71
+
72
+ ```ruby
73
+ # Create an ABA object with invalid character in the user_name
74
+ aba = Aba.batch(
75
+ financial_institution: "ANZ",
76
+ user_name: "Jøhn Doe",
77
+ user_id: "123456",
78
+ process_at: Time.now.strftime("%d%m%y")
79
+ )
80
+
81
+ # Add a transaction with a bad BSB
82
+ aba.add_transaction(
83
+ bsb: "abc-123",
84
+ account_number: "000123456"
85
+ )
86
+
87
+ # Is the data valid?
88
+ aba.valid?
89
+ # Returns: false
90
+
91
+ # Return a structured array of errors
92
+ puts aba.errors
93
+ # Returns:
94
+ # {:aba => ["user_name must not contain invalid characters"],
95
+ # :transactions =>
96
+ # {0 => ["bsb format is incorrect", "trace_bsb format is incorrect"]}}
97
+ ```
98
+
99
+ Validation errors will stop parsing of the data to an ABA formatted string using
100
+ `to_s`. `aba.to_s` will raise a `RuntimeError` instead of returning output.
101
+
102
+
43
103
  ## Installation
44
104
 
45
105
  Add this line to your application's Gemfile:
data/lib/aba.rb CHANGED
@@ -1,159 +1,10 @@
1
1
  require "aba/version"
2
2
  require "aba/validations"
3
+ require "aba/batch"
3
4
  require "aba/transaction"
4
5
 
5
6
  class Aba
6
- include Aba::Validations
7
-
8
- attr_accessor :bsb, :financial_institution, :user_name, :user_id, :description, :process_at
9
-
10
- validates_bsb :bsb, allow_blank: true
11
-
12
- validates_max_length :user_name, 26
13
- validates_max_length :user_id, 6
14
- validates_max_length :description, 12
15
-
16
- validates_length :financial_institution, 3
17
- validates_length :process_at, 6
18
-
19
- def initialize(attrs = {})
20
- attrs.each do |key, value|
21
- send("#{key}=", value)
22
- end
23
-
24
- @transactions = []
25
-
26
- yield self if block_given?
27
- end
28
-
29
- def to_s
30
- # Descriptive record
31
- output = "#{descriptive_record}\r\n"
32
-
33
- # Transactions records
34
- output += @transactions.map{ |t| t.to_s }.join("\r\n")
35
-
36
- # Batch control record
37
- output += "\r\n#{batch_control_record}"
38
- end
39
-
40
- def add_transaction(transaction)
41
- @transactions << transaction
42
- end
43
-
44
- private
45
-
46
- def descriptive_record
47
- # Record type
48
- # Max: 1
49
- # Char position: 1
50
- output = "0"
51
-
52
- # Optional branch number of the funds account with a hyphen in the 4th character position
53
- # Char position: 2-18
54
- # Max: 17
55
- # Blank filled
56
- output += self.bsb.nil? ? " " * 17 : self.bsb.to_s.ljust(17)
57
-
58
- # Sequence number
59
- # Char position: 19-20
60
- # Max: 2
61
- # Zero padded
62
- output += "01"
63
-
64
- # Name of user financial instituion
65
- # Max: 3
66
- # Char position: 21-23
67
- output += self.financial_institution.to_s
68
-
69
- # Reserved
70
- # Max: 7
71
- # Char position: 24-30
72
- output += " " * 7
73
-
74
- # Name of User supplying File
75
- # Char position: 31-56
76
- # Max: 26
77
- # Blank filled
78
- output += self.user_name.to_s.ljust(26)
79
-
80
- # Direct Entry User ID
81
- # Char position: 57-62
82
- # Max: 6
83
- # Zero padded
84
- output += self.user_id.to_s.rjust(6, "0")
85
-
86
- # Description of payments in the file (e.g. Payroll, Creditors etc.)
87
- # Char position: 63-74
88
- # Max: 12
89
- # Blank filled
90
- output += self.description.to_s.ljust(12)
91
-
92
- # Date on which the payment is to be processed
93
- # Char position: 75-80
94
- # Max: 6
95
- output += self.process_at.rjust(6, "0")
96
-
97
- # Reserved
98
- # Max: 40
99
- # Char position: 81-120
100
- output += " " * 40
101
- end
102
-
103
- def batch_control_record
104
- net_total_amount = 0
105
- credit_total_amount = 0
106
- debit_total_amount = 0
107
-
108
- @transactions.each do |t|
109
- net_total_amount += t.amount
110
- credit_total_amount += t.amount if t.amount > 0
111
- debit_total_amount += t.amount if t.amount < 0
112
- end
113
-
114
- # Record type
115
- # Max: 1
116
- # Char position: 1
117
- output = "7"
118
-
119
- # BSB Format Filler
120
- # Max: 7
121
- # Char position: 2-8
122
- output += "999-999"
123
-
124
- # Reserved
125
- # Max: 12
126
- # Char position: 9-20
127
- output += " " * 12
128
-
129
- # Net total
130
- # Max: 10
131
- # Char position: 21-30
132
- output += net_total_amount.abs.to_s.rjust(10, "0")
133
-
134
- # Credit Total Amount
135
- # Max: 10
136
- # Char position: 31-40
137
- output += credit_total_amount.abs.to_s.rjust(10, "0")
138
-
139
- # Debit Total Amount
140
- # Max: 10
141
- # Char position: 41-50
142
- output += debit_total_amount.abs.to_s.rjust(10, "0")
143
-
144
- # Reserved
145
- # Max: 24
146
- # Char position: 51-74
147
- output += " " * 24
148
-
149
- # Total Item Count
150
- # Max: 6
151
- # Char position: 75-80
152
- output += @transactions.size.to_s.rjust(6, "0")
153
-
154
- # Reserved
155
- # Max: 40
156
- # Char position: 81-120
157
- output += " " * 40
7
+ def self.batch(attrs = {}, transactions = [])
8
+ Aba::Batch.new(attrs, transactions)
158
9
  end
159
10
  end
@@ -0,0 +1,218 @@
1
+ class Aba
2
+ class Batch
3
+ include Aba::Validations
4
+
5
+ attr_accessor :bsb, :financial_institution, :user_name, :user_id, :description, :process_at, :transactions
6
+
7
+ # BSB
8
+ validates_bsb :bsb, allow_blank: true
9
+
10
+ # Financial Institution
11
+ validates_length :financial_institution, 3
12
+
13
+ # User Name
14
+ validates_presence_of :user_name
15
+ validates_max_length :user_name, 26
16
+ validates_becs :user_name
17
+
18
+ # User ID
19
+ validates_presence_of :user_id
20
+ validates_max_length :user_id, 6
21
+ validates_integer :user_id, false
22
+
23
+ # Description
24
+ validates_max_length :description, 12
25
+ validates_becs :description
26
+
27
+ # Process at Date
28
+ validates_length :process_at, 6
29
+ validates_integer :process_at, false
30
+
31
+
32
+ def initialize(attrs = {}, transactions = [])
33
+ attrs.each do |key, value|
34
+ send("#{key}=", value)
35
+ end
36
+
37
+ @transaction_index = 0
38
+ @transactions = {}
39
+
40
+ unless transactions.nil? || transactions.empty?
41
+ transactions.to_a.each do |t|
42
+ self.add_transaction(t) unless t.nil? || t.empty?
43
+ end
44
+ end
45
+
46
+ yield self if block_given?
47
+ end
48
+
49
+ def to_s
50
+ raise RuntimeError, 'No transactions present - add one using `add_transaction`' if @transactions.empty?
51
+ raise RuntimeError, 'ABA data is invalid - check the contents of `errors`' unless valid?
52
+
53
+ # Descriptive record
54
+ output = "#{descriptive_record}\r\n"
55
+
56
+ # Transactions records
57
+ output += @transactions.map{ |t| t[1].to_s }.join("\r\n")
58
+
59
+ # Batch control record
60
+ output += "\r\n#{batch_control_record}"
61
+ end
62
+
63
+ def add_transaction(attrs = {})
64
+ if attrs.instance_of?(Aba::Transaction)
65
+ transaction = attrs
66
+ else
67
+ transaction = Aba::Transaction.new(attrs)
68
+ end
69
+ @transactions[@transaction_index] = transaction
70
+ @transaction_index += 1
71
+ transaction
72
+ end
73
+
74
+ def transactions_valid?
75
+ !has_transaction_errors?
76
+ end
77
+
78
+ def valid?
79
+ !has_errors? && transactions_valid?
80
+ end
81
+
82
+ def errors
83
+ # Run validations
84
+ has_errors?
85
+ has_transaction_errors?
86
+
87
+ # Build errors
88
+ all_errors = {}
89
+ all_errors[:aba] = self.error_collection unless self.error_collection.empty?
90
+ transaction_error_collection = @transactions.each_with_index.map{ |(k, t), i| [k, t.error_collection] }.reject{ |e| e[1].nil? || e[1].empty? }.to_h
91
+ all_errors[:transactions] = transaction_error_collection unless transaction_error_collection.empty?
92
+
93
+ all_errors unless all_errors.empty?
94
+ end
95
+
96
+ private
97
+
98
+ def has_transaction_errors?
99
+ @transactions.map{ |t| t[1].valid? }.include?(false)
100
+ end
101
+
102
+ def descriptive_record
103
+ # Record type
104
+ # Max: 1
105
+ # Char position: 1
106
+ output = "0"
107
+
108
+ # Optional branch number of the funds account with a hyphen in the 4th character position
109
+ # Char position: 2-18
110
+ # Max: 17
111
+ # Blank filled
112
+ output += self.bsb.nil? ? " " * 17 : self.bsb.to_s.ljust(17)
113
+
114
+ # Sequence number
115
+ # Char position: 19-20
116
+ # Max: 2
117
+ # Zero padded
118
+ output += "01"
119
+
120
+ # Name of user financial instituion
121
+ # Max: 3
122
+ # Char position: 21-23
123
+ output += self.financial_institution.to_s
124
+
125
+ # Reserved
126
+ # Max: 7
127
+ # Char position: 24-30
128
+ output += " " * 7
129
+
130
+ # Name of User supplying File
131
+ # Char position: 31-56
132
+ # Max: 26
133
+ # Full BECS character set valid
134
+ # Blank filled
135
+ output += self.user_name.to_s.ljust(26)
136
+
137
+ # Direct Entry User ID
138
+ # Char position: 57-62
139
+ # Max: 6
140
+ # Zero padded
141
+ output += self.user_id.to_s.rjust(6, "0")
142
+
143
+ # Description of payments in the file (e.g. Payroll, Creditors etc.)
144
+ # Char position: 63-74
145
+ # Max: 12
146
+ # Full BECS character set valid
147
+ # Blank filled
148
+ output += self.description.to_s.ljust(12)
149
+
150
+ # Date on which the payment is to be processed
151
+ # Char position: 75-80
152
+ # Max: 6
153
+ output += self.process_at.to_s.rjust(6, "0")
154
+
155
+ # Reserved
156
+ # Max: 40
157
+ # Char position: 81-120
158
+ output += " " * 40
159
+ end
160
+
161
+ def batch_control_record
162
+ net_total_amount = 0
163
+ credit_total_amount = 0
164
+ debit_total_amount = 0
165
+
166
+ @transactions.each do |t|
167
+ net_total_amount += t[1].amount.to_i
168
+ credit_total_amount += t[1].amount.to_i if t[1].amount.to_i > 0
169
+ debit_total_amount += t[1].amount.to_i if t[1].amount.to_i < 0
170
+ end
171
+
172
+ # Record type
173
+ # Max: 1
174
+ # Char position: 1
175
+ output = "7"
176
+
177
+ # BSB Format Filler
178
+ # Max: 7
179
+ # Char position: 2-8
180
+ output += "999-999"
181
+
182
+ # Reserved
183
+ # Max: 12
184
+ # Char position: 9-20
185
+ output += " " * 12
186
+
187
+ # Net total
188
+ # Max: 10
189
+ # Char position: 21-30
190
+ output += net_total_amount.abs.to_s.rjust(10, "0")
191
+
192
+ # Credit Total Amount
193
+ # Max: 10
194
+ # Char position: 31-40
195
+ output += credit_total_amount.abs.to_s.rjust(10, "0")
196
+
197
+ # Debit Total Amount
198
+ # Max: 10
199
+ # Char position: 41-50
200
+ output += debit_total_amount.abs.to_s.rjust(10, "0")
201
+
202
+ # Reserved
203
+ # Max: 24
204
+ # Char position: 51-74
205
+ output += " " * 24
206
+
207
+ # Total Item Count
208
+ # Max: 6
209
+ # Char position: 75-80
210
+ output += @transactions.size.to_s.rjust(6, "0")
211
+
212
+ # Reserved
213
+ # Max: 40
214
+ # Char position: 81-120
215
+ output += " " * 40
216
+ end
217
+ end
218
+ end
@@ -2,30 +2,95 @@ class Aba
2
2
  class Transaction
3
3
  include Aba::Validations
4
4
 
5
- attr_accessor :account_number, :transaction_code, :amount, :account_name,
5
+ attr_accessor :account_number, :transaction_code, :amount, :account_name,
6
6
  :bsb, :trace_bsb, :trace_account_number, :name_of_remitter,
7
7
  :witholding_amount, :indicator, :lodgement_reference
8
8
 
9
- validates_bsb :bsb
10
- validates_bsb :trace_bsb
11
-
12
- validates_integer :amount
9
+ # BSB
10
+ validates_bsb :bsb
11
+
12
+ # Account Number
13
+ validates_account_number :account_number
14
+
15
+ # Indicator
16
+ validates_indicator :indicator
17
+
18
+ # Transaction Code
19
+ validates_transaction_code :transaction_code
20
+
21
+ # Amount
22
+ validates_integer :amount
23
+
24
+ # Account Name
25
+ validates_max_length :account_name, 32
26
+ validates_becs :account_name
27
+
28
+ # Lodgement Reference
29
+ validates_max_length :lodgement_reference, 18
30
+ validates_becs :lodgement_reference
31
+
32
+ # Trace Record
33
+ validates_bsb :trace_bsb
34
+ validates_account_number :trace_account_number
35
+
36
+ # Name of Remitter
37
+ validates_max_length :name_of_remitter, 16
38
+ validates_becs :name_of_remitter
13
39
 
14
- validates_max_length :account_number, 9
15
- validates_max_length :indicator, 1
16
- validates_max_length :transaction_code, 2
17
- validates_max_length :account_name, 32
18
- validates_max_length :lodgement_reference, 18
19
- validates_max_length :trace_account_number, 9
20
- validates_max_length :name_of_remitter, 16
21
40
 
22
41
  def initialize(attrs = {})
23
42
  attrs.each do |key, value|
24
43
  send("#{key}=", value)
25
44
  end
26
45
  end
27
-
46
+
47
+ # Allow dashes to be input, but remove them from output
48
+ def account_number
49
+ @account_number ? @account_number.to_s.gsub('-', '') : nil
50
+ end
51
+
52
+ # Fall back to blank string
53
+ def indicator
54
+ @indicator || Aba::Validations::INDICATORS.first
55
+ end
56
+
57
+ # Fall back to 50
58
+ def transaction_code
59
+ @transaction_code || 50
60
+ end
61
+
62
+ # Fall back to 0
63
+ def amount
64
+ @amount || 0
65
+ end
66
+
67
+ # Fall back to empty string
68
+ def account_name
69
+ @account_name || ''
70
+ end
71
+
72
+ # Fall back to empty string
73
+ def lodgement_reference
74
+ @lodgement_reference || ''
75
+ end
76
+
77
+ # Fall back to BSB
78
+ def trace_bsb
79
+ @trace_bsb || bsb
80
+ end
81
+
82
+ # Fall back to Account Number
83
+ def trace_account_number
84
+ @trace_account_number ? @trace_account_number.to_s.gsub('-', '') : account_number
85
+ end
86
+
87
+ def name_of_remitter
88
+ @name_of_remitter || ''
89
+ end
90
+
28
91
  def to_s
92
+ raise RuntimeError, 'Transaction data is invalid - check the contents of `errors`' unless valid?
93
+
29
94
  # Record type
30
95
  output = "1"
31
96
 
@@ -33,41 +98,46 @@ class Aba
33
98
  output += bsb
34
99
 
35
100
  # Account number
101
+ #raise RuntimeError, 'Transaction is missing account_number' unless account_number
36
102
  output += account_number.to_s.rjust(9, " ")
37
103
 
38
104
  # Withholding Tax Indicator
39
105
  # "N" – for new or varied Bank/State/Branch number or name details, otherwise blank filled.
106
+ # "T" - for a drawing under a Transaction Negotiation Authority.
40
107
  # "W" – dividend paid to a resident of a country where a double tax agreement is in force.
41
108
  # "X" – dividend paid to a resident of any other country.
42
109
  # "Y" – interest paid to all non-residents.
43
110
  output += indicator.to_s.ljust(1, " ")
44
111
 
45
112
  # Transaction Code
46
- # 50 General Credit.
47
- # 53 Payroll.
48
- # 54 Pension.
49
- # 56 Dividend.
50
- # 57 Debenture Interest.
113
+ # 50 General Credit.
114
+ # 53 Payroll.
115
+ # 54 Pension.
116
+ # 56 Dividend.
117
+ # 57 Debenture Interest.
51
118
  # 13 General Debit.
52
119
  output += transaction_code.to_s
53
120
 
54
121
  # Amount to be credited or debited
55
- output += amount.abs.to_s.rjust(10, "0")
122
+ output += amount.to_i.abs.to_s.rjust(10, "0")
56
123
 
57
124
  # Title of Account
58
- output += account_name.ljust(32, " ")
125
+ # Full BECS character set valid
126
+ output += account_name.to_s.ljust(32, " ")
59
127
 
60
- # Lodgement Reference Produced on the recipient’s Account Statement.
61
- output += lodgement_reference.ljust(18, " ")
128
+ # Lodgement Reference Produced on the recipient’s Account Statement.
129
+ # Full BECS character set valid
130
+ output += lodgement_reference.to_s.ljust(18, " ")
62
131
 
63
132
  # Trace BSB Number
64
133
  output += trace_bsb
65
134
 
66
- # Trace Account Number
135
+ # Trace Account Number
67
136
  output += trace_account_number.to_s.rjust(9, " ")
68
137
 
69
138
  # Name of Remitter Produced on the recipient’s Account Statement
70
- output += name_of_remitter.ljust(16, " ")
139
+ # Full BECS character set valid
140
+ output += name_of_remitter.to_s.ljust(16, " ")
71
141
 
72
142
  # Withholding amount in cents
73
143
  output += (witholding_amount || 0).abs.to_s.rjust(8, "0")
@@ -1,6 +1,9 @@
1
1
  class Aba
2
2
  module Validations
3
- attr_accessor :errors
3
+ attr_accessor :error_collection
4
+
5
+ BECS_PATTERN = /\A[\w\+\-\@\ \$\!\%\&\(\)\*\.\/\#\=\:\;\?\,\'\[\]\_\^]*\Z/
6
+ INDICATORS = [' ', 'N', 'T', 'W', 'X', 'Y']
4
7
 
5
8
  def self.included(base)
6
9
  base.instance_eval do
@@ -10,9 +13,17 @@ class Aba
10
13
  base.send :extend, ClassMethods
11
14
  end
12
15
 
13
- # Run all validations
14
16
  def valid?
15
- self.errors = []
17
+ !has_errors?
18
+ end
19
+
20
+ alias_method 'errors', 'error_collection'
21
+
22
+ private
23
+
24
+ # Run all validations
25
+ def has_errors?
26
+ self.error_collection = []
16
27
 
17
28
  self.class.instance_variable_get(:@_validations).each do |attribute, validations|
18
29
  value = send(attribute)
@@ -20,27 +31,42 @@ class Aba
20
31
  validations.each do |type, param|
21
32
  case type
22
33
  when :presence
23
- self.errors << "#{attribute} is empty" if value.nil? || value.to_s.empty?
34
+ self.error_collection << "#{attribute} is empty" if value.nil? || value.to_s.empty?
24
35
  when :bsb
25
36
  unless((param && value.nil?) || value =~ /^\d{3}-\d{3}$/)
26
- self.errors << "#{attribute} format is incorrect"
37
+ self.error_collection << "#{attribute} format is incorrect"
27
38
  end
28
39
  when :max_length
29
- self.errors << "#{attribute} length must not exceed #{param} characters" if value.to_s.length > param
40
+ self.error_collection << "#{attribute} length must not exceed #{param} characters" if value.to_s.length > param
30
41
  when :length
31
- self.errors << "#{attribute} length must be exactly #{param} characters" if value.to_s.length != param
42
+ self.error_collection << "#{attribute} length must be exactly #{param} characters" if value.to_s.length != param
32
43
  when :integer
33
- self.errors << "#{attribute} must be an integer" unless value.to_s =~ /\A[+-]?\d+\Z/
44
+ if param
45
+ self.error_collection << "#{attribute} must be a number" unless value.to_s =~ /\A[+-]?\d+\Z/
46
+ else
47
+ self.error_collection << "#{attribute} must be an unsigned number" unless value.to_s =~ /\A\d+\Z/
48
+ end
49
+ when :account_number
50
+ if value.to_s =~ /\A[0\ ]+\Z/ || value.to_s !~ /\A[a-z\d\ ]{1,9}\Z/
51
+ self.error_collection << "#{attribute} must be a valid account number"
52
+ end
53
+ when :becs
54
+ self.error_collection << "#{attribute} must not contain invalid characters" unless value.to_s =~ BECS_PATTERN
55
+ when :indicator
56
+ list = INDICATORS.join('\', \'')
57
+ self.error_collection << "#{attribute} must be a one of '#{list}'" unless INDICATORS.include?(value.to_s)
58
+ when :transaction_code
59
+ self.error_collection << "#{attribute} must be a 2 digit number" unless value.to_s =~ /\A\d{2,2}\Z/
34
60
  end
35
61
  end
36
62
  end
37
63
 
38
- self.errors.empty?
64
+ !self.error_collection.empty?
39
65
  end
40
-
66
+
41
67
  module ClassMethods
42
68
  def validates_presence_of(*attributes)
43
- attributes.each do |a|
69
+ attributes.each do |a|
44
70
  add_validation_attribute(a, :presence)
45
71
  end
46
72
  end
@@ -58,8 +84,24 @@ class Aba
58
84
  add_validation_attribute(attribute, :length, length)
59
85
  end
60
86
 
61
- def validates_integer(attribute)
62
- add_validation_attribute(attribute, :integer)
87
+ def validates_integer(attribute, signed = true)
88
+ add_validation_attribute(attribute, :integer, signed)
89
+ end
90
+
91
+ def validates_account_number(attribute)
92
+ add_validation_attribute(attribute, :account_number)
93
+ end
94
+
95
+ def validates_becs(attribute)
96
+ add_validation_attribute(attribute, :becs)
97
+ end
98
+
99
+ def validates_indicator(attribute)
100
+ add_validation_attribute(attribute, :indicator)
101
+ end
102
+
103
+ def validates_transaction_code(attribute)
104
+ add_validation_attribute(attribute, :transaction_code)
63
105
  end
64
106
 
65
107
  private
@@ -1,3 +1,3 @@
1
1
  class Aba
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,7 +1,9 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "spec_helper"
2
4
 
3
- describe Aba do
4
- let(:aba) { Aba.new(financial_institution: "WPC", user_name: "John Doe",
5
+ describe Aba::Batch do
6
+ let(:aba) { Aba::Batch.new(financial_institution: "WPC", user_name: "John Doe",
5
7
  user_id: "466364", description: "Payroll", process_at: "190615") }
6
8
  let(:transaction_values) { [30, -20] }
7
9
  let(:transactions) do
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Aba::Transaction do
@@ -10,8 +12,8 @@ describe Aba::Transaction do
10
12
  :witholding_amount => 87,
11
13
  :indicator => "W",
12
14
  :lodgement_reference => "R45343",
13
- :trace_bsb => "123-234",
14
- :trace_account_number => "4647642",
15
+ :trace_bsb => "123-234",
16
+ :trace_account_number => "4647642",
15
17
  :name_of_remitter => "Remitter"
16
18
  } }
17
19
  subject(:transaction) { Aba::Transaction.new(transaction_params) }
@@ -0,0 +1,215 @@
1
+ # encoding: UTF-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Aba::Validations do
6
+ let(:clean_room) do
7
+ Class.new(Object) do
8
+ include Aba::Validations
9
+ end
10
+ end
11
+
12
+ subject(:test_instance) { clean_room.new }
13
+
14
+ describe "#valid?" do
15
+ it "should validate presence of attrs" do
16
+ clean_room.instance_eval do
17
+ attr_accessor :attr1
18
+ validates_presence_of :attr1
19
+ end
20
+
21
+ expect(subject.valid?).to eq false
22
+ expect(subject.errors).to eq ["attr1 is empty"]
23
+
24
+ subject.attr1 = "hello!"
25
+ expect(subject.valid?).to eq true
26
+ end
27
+
28
+ it "should validate bsb format" do
29
+ clean_room.instance_eval do
30
+ attr_accessor :attr1
31
+ validates_bsb :attr1
32
+ end
33
+
34
+ subject.attr1 = "234456"
35
+ expect(subject.valid?).to eq false
36
+ expect(subject.errors).to eq ["attr1 format is incorrect"]
37
+
38
+ subject.attr1 = "234-456"
39
+ expect(subject.valid?).to eq true
40
+ end
41
+
42
+ it "should validate max length" do
43
+ clean_room.instance_eval do
44
+ attr_accessor :attr1
45
+ validates_max_length :attr1, 5
46
+ end
47
+
48
+ subject.attr1 = "234456642"
49
+ expect(subject.valid?).to eq false
50
+ expect(subject.errors).to eq ["attr1 length must not exceed 5 characters"]
51
+
52
+ subject.attr1 = "23445"
53
+ expect(subject.valid?).to eq true
54
+
55
+ subject.attr1 = "2344"
56
+ expect(subject.valid?).to eq true
57
+ end
58
+
59
+ it "should validate length" do
60
+ clean_room.instance_eval do
61
+ attr_accessor :attr1
62
+ validates_length :attr1, 5
63
+ end
64
+
65
+ subject.attr1 = "234456642"
66
+ expect(subject.valid?).to eq false
67
+ expect(subject.errors).to eq ["attr1 length must be exactly 5 characters"]
68
+
69
+ subject.attr1 = "23445"
70
+ expect(subject.valid?).to eq true
71
+
72
+ subject.attr1 = "2344"
73
+ expect(subject.valid?).to eq false
74
+ expect(subject.errors).to eq ["attr1 length must be exactly 5 characters"]
75
+ end
76
+
77
+ it "should validate signed integer" do
78
+ clean_room.instance_eval do
79
+ attr_accessor :attr1
80
+ validates_integer :attr1
81
+ end
82
+
83
+ subject.attr1 = "+1234A"
84
+ expect(subject.valid?).to eq false
85
+ expect(subject.errors).to eq ["attr1 must be a number"]
86
+
87
+ subject.attr1 = "+1234"
88
+ expect(subject.valid?).to eq true
89
+
90
+ subject.attr1 = "-1234"
91
+ expect(subject.valid?).to eq true
92
+
93
+ subject.attr1 = "1234"
94
+ expect(subject.valid?).to eq true
95
+ end
96
+
97
+ it "should validate unsigned integer" do
98
+ clean_room.instance_eval do
99
+ attr_accessor :attr1
100
+ validates_integer :attr1, false
101
+ end
102
+
103
+ subject.attr1 = "1234A"
104
+ expect(subject.valid?).to eq false
105
+ expect(subject.errors).to eq ["attr1 must be an unsigned number"]
106
+
107
+ subject.attr1 = "+1234"
108
+ expect(subject.valid?).to eq false
109
+ expect(subject.errors).to eq ["attr1 must be an unsigned number"]
110
+
111
+ subject.attr1 = "-1234"
112
+ expect(subject.valid?).to eq false
113
+ expect(subject.errors).to eq ["attr1 must be an unsigned number"]
114
+
115
+ subject.attr1 = "1234"
116
+ expect(subject.valid?).to eq true
117
+
118
+ subject.attr1 = 1234
119
+ expect(subject.valid?).to eq true
120
+ end
121
+
122
+ it "should validate account number" do
123
+ clean_room.instance_eval do
124
+ attr_accessor :attr1
125
+ validates_account_number :attr1
126
+ end
127
+
128
+ subject.attr1 = " "
129
+ expect(subject.valid?).to eq false
130
+ expect(subject.errors).to eq ["attr1 must be a valid account number"]
131
+
132
+ subject.attr1 = "000000"
133
+ expect(subject.valid?).to eq false
134
+ expect(subject.errors).to eq ["attr1 must be a valid account number"]
135
+
136
+ subject.attr1 = "00 0 0"
137
+ expect(subject.valid?).to eq false
138
+ expect(subject.errors).to eq ["attr1 must be a valid account number"]
139
+
140
+ subject.attr1 = "00 0A0"
141
+ expect(subject.valid?).to eq false
142
+ expect(subject.errors).to eq ["attr1 must be a valid account number"]
143
+
144
+ subject.attr1 = "00 111"
145
+ expect(subject.valid?).to eq true
146
+
147
+ subject.attr1 = "0a 111"
148
+ expect(subject.valid?).to eq true
149
+
150
+ subject.attr1 = "aaaaaa"
151
+ expect(subject.valid?).to eq true
152
+
153
+ subject.attr1 = "aa aaa"
154
+ expect(subject.valid?).to eq true
155
+ end
156
+
157
+ it "should validate becs" do
158
+ clean_room.instance_eval do
159
+ attr_accessor :attr1
160
+ validates_becs :attr1
161
+ end
162
+
163
+ subject.attr1 = "abc123 é"
164
+ expect(subject.valid?).to eq false
165
+ expect(subject.errors).to eq ["attr1 must not contain invalid characters"]
166
+
167
+ subject.attr1 = "abc123 ~"
168
+ expect(subject.valid?).to eq false
169
+ expect(subject.errors).to eq ["attr1 must not contain invalid characters"]
170
+
171
+ subject.attr1 = "abc123"
172
+ expect(subject.valid?).to eq true
173
+ end
174
+
175
+ it "should validate indicator" do
176
+ clean_room.instance_eval do
177
+ attr_accessor :attr1
178
+ validates_indicator :attr1
179
+ end
180
+
181
+ subject.attr1 = "$"
182
+ expect(subject.valid?).to eq false
183
+ list = Aba::Validations::INDICATORS.join('\', \'')
184
+ expect(subject.errors).to eq ["attr1 must be a one of '#{list}'"]
185
+
186
+ subject.attr1 = Aba::Validations::INDICATORS.sample
187
+ expect(subject.valid?).to eq true
188
+ end
189
+
190
+ it "should validate transaction code" do
191
+ clean_room.instance_eval do
192
+ attr_accessor :attr1
193
+ validates_transaction_code :attr1
194
+ end
195
+
196
+ subject.attr1 = "AA"
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"
201
+ expect(subject.valid?).to eq false
202
+ expect(subject.errors).to eq ["attr1 must be a 2 digit number"]
203
+
204
+ subject.attr1 = "1"
205
+ expect(subject.valid?).to eq false
206
+ expect(subject.errors).to eq ["attr1 must be a 2 digit number"]
207
+
208
+ subject.attr1 = "15"
209
+ expect(subject.valid?).to eq true
210
+
211
+ subject.attr1 = 15
212
+ expect(subject.valid?).to eq true
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: UTF-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Aba do
6
+ describe ".batch" do
7
+ it "initialize instance of Aba::Batch with passed arguments" do
8
+ attributes = double.as_null_object
9
+ transactions = double.as_null_object
10
+
11
+ expect(Aba::Batch).to receive(:new).with(attributes, transactions)
12
+ described_class.batch(attributes, transactions)
13
+ end
14
+
15
+ it "returns instance of Aba::Batch" do
16
+ obj = described_class.batch(double.as_null_object, double.as_null_object)
17
+
18
+ expect(obj).to be_a(Aba::Batch)
19
+ end
20
+ end
21
+ end
@@ -5,4 +5,6 @@ require "aba"
5
5
 
6
6
  RSpec.configure do |config|
7
7
  config.order = :random
8
+ config.filter_run :focus
9
+ config.run_all_when_everything_filtered = true
8
10
  end
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.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Bazhutkin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-06-16 00:00:00.000000000 Z
12
+ date: 2015-09-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -84,13 +84,15 @@ files:
84
84
  - Rakefile
85
85
  - aba.gemspec
86
86
  - lib/aba.rb
87
+ - lib/aba/batch.rb
87
88
  - lib/aba/transaction.rb
88
89
  - lib/aba/validations.rb
89
90
  - lib/aba/version.rb
90
- - spec/aba_spec.rb
91
+ - spec/lib/aba/batch_spec.rb
92
+ - spec/lib/aba/transaction_spec.rb
93
+ - spec/lib/aba/validations_spec.rb
94
+ - spec/lib/aba_spec.rb
91
95
  - spec/spec_helper.rb
92
- - spec/transaction_spec.rb
93
- - spec/validations_spec.rb
94
96
  homepage: https://github.com/andrba/aba
95
97
  licenses:
96
98
  - MIT
@@ -116,7 +118,8 @@ signing_key:
116
118
  specification_version: 4
117
119
  summary: ABA File Generator
118
120
  test_files:
119
- - spec/aba_spec.rb
121
+ - spec/lib/aba/batch_spec.rb
122
+ - spec/lib/aba/transaction_spec.rb
123
+ - spec/lib/aba/validations_spec.rb
124
+ - spec/lib/aba_spec.rb
120
125
  - spec/spec_helper.rb
121
- - spec/transaction_spec.rb
122
- - spec/validations_spec.rb
@@ -1,47 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Aba::Validations do
4
- let(:clean_room) do
5
- Class.new(Object) do
6
- include Aba::Validations
7
- end
8
- end
9
-
10
- subject(:test_instance) { clean_room.new }
11
-
12
- describe "#valid?" do
13
- it "should validate presence of attrs" do
14
- clean_room.instance_eval do
15
- attr_accessor :attr1
16
- validates_presence_of :attr1
17
- end
18
-
19
- expect(subject.valid?).to eq false
20
- expect(subject.errors).to eq ["attr1 is empty"]
21
- end
22
-
23
- it "should validate bsb format" do
24
- clean_room.instance_eval do
25
- attr_accessor :attr1
26
- validates_bsb :attr1
27
- end
28
-
29
- subject.attr1 = "234456"
30
-
31
- expect(subject.valid?).to eq false
32
- expect(subject.errors).to eq ["attr1 format is incorrect"]
33
- end
34
-
35
- it "should validate length" do
36
- clean_room.instance_eval do
37
- attr_accessor :attr1
38
- validates_max_length :attr1, 5
39
- end
40
-
41
- subject.attr1 = "234456642"
42
-
43
- expect(subject.valid?).to eq false
44
- expect(subject.errors).to eq ["attr1 length must not exceed 5 characters"]
45
- end
46
- end
47
- end