wage_slave 2.0.0
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 +7 -0
- data/.env.example +5 -0
- data/.gitignore +22 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +10 -0
- data/bin/console +27 -0
- data/bin/setup +8 -0
- data/lib/wage_slave.rb +16 -0
- data/lib/wage_slave/aba.rb +75 -0
- data/lib/wage_slave/aba/descriptive_record.rb +97 -0
- data/lib/wage_slave/aba/detail_collection.rb +33 -0
- data/lib/wage_slave/aba/detail_record.rb +145 -0
- data/lib/wage_slave/aba/record.rb +9 -0
- data/lib/wage_slave/configuration.rb +47 -0
- data/lib/wage_slave/validation.rb +98 -0
- data/lib/wage_slave/validators/descriptive_record_validator.rb +41 -0
- data/lib/wage_slave/validators/detail_record_validator.rb +57 -0
- data/lib/wage_slave/version.rb +3 -0
- data/travis.yml +3 -0
- data/wage_slave.gemspec +28 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 24c6b5c6e8da902e4fa340e8fee0286950d7f657
|
4
|
+
data.tar.gz: 0a0e36576e6218da70432406087466458a64acf3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e69be9f0670ea23e89440be5fac0ad0fb1cd4bf0bf6bee471d073ea8cbfd3d6c8844ad154023682b0efb186b75ad7e823b0d3677e2d2e92f8af9608112359a4f
|
7
|
+
data.tar.gz: bf29ce045b85eafddbd8b495b8083102d617f3d864f3a12b04dbc481bbeb6b91c5cae0f6d3e76eb20829b34e5c90e945e3b436efad65692e8158891cccdf6fdf
|
data/.env.example
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
.ruby-version
|
11
|
+
.ruby-gemset
|
12
|
+
*.tmp
|
13
|
+
*.swp
|
14
|
+
*.swo
|
15
|
+
*~
|
16
|
+
.DS_Store
|
17
|
+
.env
|
18
|
+
*.pem
|
19
|
+
.idea
|
20
|
+
.idea/**/*
|
21
|
+
.idea/*
|
22
|
+
.gem
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 mesge
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# WageSlave
|
2
|
+
[](https://travis-ci.org/noyelling/wage_slave)
|
3
|
+
|
4
|
+
A toolkit for generating and working with bulk payment files in various banking formats.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'wage_slave'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install wage_slave
|
21
|
+
|
22
|
+
## Formats
|
23
|
+
|
24
|
+
WageSlave can generate payment files in the following formats:
|
25
|
+
|
26
|
+
### Available
|
27
|
+
|
28
|
+
1. [ABA / Cemtext](https://www.cemtexaba.com/aba-format) (Australian Banks)
|
29
|
+
|
30
|
+
### Coming soon
|
31
|
+
|
32
|
+
1. [NZ-DE](http://help.westpac.com.au/help/content/col/documents/pdfs/olpimportnzde.pdf) (New Zealand Direct Entry File Format)
|
33
|
+
2. [IB4B](https://www.bnz.co.nz/assets/business-banking-help-support/internet-banking/ib4b-file-format-guide.pdf) (Bank of New Zealand)
|
34
|
+
3. More...
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
Configure your application with information relating to your financial institution. For Rails applications this should be kept in
|
39
|
+
an initializer. Keep this information secure and out of version control.
|
40
|
+
|
41
|
+
### Configuration
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
WageSlave.configure do | config |
|
45
|
+
config.financial_institution = "ANZ" # Name of your bank
|
46
|
+
config.bank_code = "123-456" # i.e. BSB, Sort code etc
|
47
|
+
config.user_id = "12345678" # i.e. CRN, Acc no. etc
|
48
|
+
config.description = "A default description for all WageSlave transactions"
|
49
|
+
config.user_name = "Username"
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
### ABA / Cemtext
|
54
|
+
|
55
|
+
A bulk payment file that works with most Australian banks.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
|
59
|
+
# Build individual transactions
|
60
|
+
transactions = [
|
61
|
+
{ name: "John Doe", account_number: "12345678", bsb: "999-999", amount: 5000 },
|
62
|
+
{ name: "Jane Doe", account_number: "87654321", bsb: "999-999", amount: 6000 }
|
63
|
+
]
|
64
|
+
|
65
|
+
# Create an ABA object
|
66
|
+
aba = WageSlave::ABA.new(transactions)
|
67
|
+
|
68
|
+
# Print in ABA format
|
69
|
+
# Validation errors will raise a RuntimeError when calling #to_s on an ABA object.
|
70
|
+
aba.to_s
|
71
|
+
|
72
|
+
```
|
73
|
+
|
74
|
+
## Development
|
75
|
+
|
76
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `ruby bin/console` for an interactive prompt that will allow you to experiment.
|
77
|
+
|
78
|
+
## Contributing
|
79
|
+
|
80
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/noyelling/wage_slave.
|
81
|
+
|
82
|
+
## License
|
83
|
+
|
84
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
85
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << 'spec'
|
6
|
+
t.pattern = "spec/*_spec.rb"
|
7
|
+
t.test_files = FileList['spec/wage_slave/services/*_spec.rb', 'spec/wage_slave/*_spec.rb', 'spec/wage_slave/aba/*_spec.rb' ]
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
data/bin/console
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "wage_slave"
|
5
|
+
require 'dotenv'
|
6
|
+
|
7
|
+
Dotenv.load
|
8
|
+
|
9
|
+
# Configure Application with Demo API Keys
|
10
|
+
WageSlave.configure do | config |
|
11
|
+
config.financial_institution = "ANZ"
|
12
|
+
config.bank_code = "123-456"
|
13
|
+
config.account_number = "12345678"
|
14
|
+
config.user_id = "000001"
|
15
|
+
config.description = "PAYROLL"
|
16
|
+
config.user_name = "No Yelling"
|
17
|
+
end
|
18
|
+
|
19
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
20
|
+
# with your gem easier. You can also use a different console, if you like.
|
21
|
+
|
22
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
23
|
+
# require "pry"
|
24
|
+
# Pry.start
|
25
|
+
|
26
|
+
require "irb"
|
27
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/wage_slave.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Require config
|
2
|
+
require 'wage_slave/configuration'
|
3
|
+
|
4
|
+
# Require validation base
|
5
|
+
require 'wage_slave/validation'
|
6
|
+
|
7
|
+
# Require modules
|
8
|
+
require 'wage_slave/aba'
|
9
|
+
require 'wage_slave/aba/record'
|
10
|
+
require 'wage_slave/aba/detail_collection'
|
11
|
+
require 'wage_slave/aba/descriptive_record'
|
12
|
+
require 'wage_slave/aba/detail_record'
|
13
|
+
|
14
|
+
# Require validators
|
15
|
+
require 'wage_slave/validators/detail_record_validator'
|
16
|
+
require 'wage_slave/validators/descriptive_record_validator'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
|
4
|
+
attr_reader :descriptive_record, :details
|
5
|
+
|
6
|
+
def initialize(transactions = [])
|
7
|
+
@descriptive_record = WageSlave::ABA::DescriptiveRecord.new
|
8
|
+
@details = WageSlave::ABA::DetailCollection.new(transactions)
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# This method was adapted from https://github.com/andrba/aba which is released under MIT.
|
13
|
+
# See /LICENSE.txt for details.
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
output = @descriptive_record.to_s + "\r\n"
|
17
|
+
output += @details.to_s + "\r\n"
|
18
|
+
|
19
|
+
# Record Type
|
20
|
+
# Size: 1
|
21
|
+
# Char position: 1
|
22
|
+
# Must be 7
|
23
|
+
output += "7"
|
24
|
+
|
25
|
+
# BSB format filler
|
26
|
+
# Size: 7
|
27
|
+
# Char position: 2-8
|
28
|
+
# Must be 999-999
|
29
|
+
output += "999-999"
|
30
|
+
|
31
|
+
# Reserved
|
32
|
+
# Size: 12
|
33
|
+
# Char position: 9-20
|
34
|
+
# Blank filled
|
35
|
+
output += " " * 12
|
36
|
+
|
37
|
+
# Net total amount
|
38
|
+
# Size: 10
|
39
|
+
# Char position: 21-30
|
40
|
+
# Right justified, zero filled.
|
41
|
+
output += @details.net_total.abs.to_s.rjust(10, "0")
|
42
|
+
|
43
|
+
# Credit total amount
|
44
|
+
# Size: 10
|
45
|
+
# Char position: 31-40
|
46
|
+
# Right justified, zero filled.
|
47
|
+
output += @details.credit_total.abs.to_s.rjust(10, "0")
|
48
|
+
|
49
|
+
# Debit total amount
|
50
|
+
# Size: 10
|
51
|
+
# Char position: 41-50
|
52
|
+
# Right justified, zero filled.
|
53
|
+
output += @details.debit_total.abs.to_s.rjust(10, "0")
|
54
|
+
|
55
|
+
# Reserved
|
56
|
+
# Size: 24
|
57
|
+
# Char position: 51-74
|
58
|
+
# Blank filled
|
59
|
+
output += " " * 24
|
60
|
+
|
61
|
+
# Count of Type 1 records
|
62
|
+
# Size: 6
|
63
|
+
# Char position: 75-80
|
64
|
+
# Right justified, zero filled.
|
65
|
+
output += @details.size.to_s.rjust(6, "0")
|
66
|
+
|
67
|
+
# Reserved
|
68
|
+
# Size: 40
|
69
|
+
# Char position: 81-120
|
70
|
+
# Blank filled
|
71
|
+
output += " " * 40
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
class DescriptiveRecord < WageSlave::ABA::Record
|
4
|
+
|
5
|
+
include WageSlave::Validation
|
6
|
+
|
7
|
+
##
|
8
|
+
# Reel sequence becomes important for payment runs of multiple ABA files.
|
9
|
+
# It is incremented each time a descriptive record is created.
|
10
|
+
|
11
|
+
@@reel_sequence = 0
|
12
|
+
|
13
|
+
attr_reader :bsb, :financial_institution, :user_name, :user_id, :description, :process_at, :reel_sequence
|
14
|
+
|
15
|
+
def initialize(attrs = {})
|
16
|
+
@type = "0"
|
17
|
+
@bsb = WageSlave.configuration.bank_code
|
18
|
+
@financial_institution = WageSlave.configuration.financial_institution
|
19
|
+
@user_name = WageSlave.configuration.user_name
|
20
|
+
@user_id = WageSlave.configuration.user_id
|
21
|
+
@description = WageSlave.configuration.description
|
22
|
+
@process_at = attrs[:process_at] || Date.today
|
23
|
+
|
24
|
+
# Bump reel sequence number.
|
25
|
+
@reel_sequence = '%02d' % @@reel_sequence+=1
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# This method was adapted from https://github.com/andrba/aba which is released under MIT.
|
30
|
+
# See /LICENSE.txt for details.
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
raise RuntimeError.new "Descriptive record is invalid. Check the contents of 'errors'" unless self.valid?
|
34
|
+
|
35
|
+
# Record type
|
36
|
+
# Size: 1
|
37
|
+
# Char position: 1
|
38
|
+
# Must be 0
|
39
|
+
output = @type
|
40
|
+
|
41
|
+
# Optional branch number of the funds account
|
42
|
+
# Char position: 2-18
|
43
|
+
# Size: 17
|
44
|
+
# Format: XXX-XXX
|
45
|
+
# Blank filled
|
46
|
+
output += @bsb.nil? ? " " * 17 : @bsb.to_s.ljust(17)
|
47
|
+
|
48
|
+
# Sequence number
|
49
|
+
# Char position: 19-20
|
50
|
+
# Size: 2
|
51
|
+
# Zero padded
|
52
|
+
output += @reel_sequence
|
53
|
+
|
54
|
+
# Name of user financial instituion
|
55
|
+
# Size: 3
|
56
|
+
# Char position: 21-23
|
57
|
+
output += @financial_institution.to_s
|
58
|
+
|
59
|
+
# Reserved
|
60
|
+
# Size: 7
|
61
|
+
# Char position: 24-30
|
62
|
+
output += " " * 7
|
63
|
+
|
64
|
+
# Name of User supplying File
|
65
|
+
# Char position: 31-56
|
66
|
+
# Size: 26
|
67
|
+
# Full BECS character set valid
|
68
|
+
# Blank filled
|
69
|
+
output += @user_name.to_s.ljust(26)
|
70
|
+
|
71
|
+
# Direct Entry User ID
|
72
|
+
# Char position: 57-62
|
73
|
+
# Size: 6
|
74
|
+
# Zero padded
|
75
|
+
output += @user_id.to_s.rjust(6, "0")
|
76
|
+
|
77
|
+
# Description of payments in the file (e.g. Payroll, Creditors etc.)
|
78
|
+
# Char position: 63-74
|
79
|
+
# Size: 12
|
80
|
+
# Full BECS character set valid
|
81
|
+
# Blank filled
|
82
|
+
output += @description.to_s.ljust(12)
|
83
|
+
|
84
|
+
# Date on which the payment is to be processed
|
85
|
+
# Char position: 75-80
|
86
|
+
# Size: 6
|
87
|
+
output += @process_at.strftime("%d%m%y")
|
88
|
+
|
89
|
+
# Reserved
|
90
|
+
# Size: 40
|
91
|
+
# Char position: 81-120
|
92
|
+
output += " " * 40
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
class DetailCollection < Array
|
4
|
+
|
5
|
+
def initialize(details = [])
|
6
|
+
self.concat(
|
7
|
+
details.map { |d| WageSlave::ABA::DetailRecord.new(d) }
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
def net_total
|
12
|
+
self.credit_total + self.debit_total
|
13
|
+
end
|
14
|
+
|
15
|
+
def credit_total
|
16
|
+
self
|
17
|
+
.select { |d| d.amount > 0 }
|
18
|
+
.reduce(0) { |acc, n| acc + n.amount }
|
19
|
+
end
|
20
|
+
|
21
|
+
def debit_total
|
22
|
+
self
|
23
|
+
.select { |d| d.amount < 0 }
|
24
|
+
.reduce(0) { |acc, n| acc + n.amount }
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
self.map(&:to_s).join("\r\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
class DetailRecord < WageSlave::ABA::Record
|
4
|
+
|
5
|
+
include WageSlave::Validation
|
6
|
+
|
7
|
+
# Key Value
|
8
|
+
# ===========
|
9
|
+
# "N" For new or varied Bank/State/Branch number or name details, otherwise blank filled.
|
10
|
+
#
|
11
|
+
# Withholding Tax Indicators
|
12
|
+
# ==========================
|
13
|
+
# "W" Dividend paid to a resident of a country where a double tax agreement is in force.
|
14
|
+
# "X" Dividend paid to a resident of any other country.
|
15
|
+
# "Y" Interest paid to all non-residents.
|
16
|
+
|
17
|
+
@@indicators = Set.new ["N", "W", "X", "Y"]
|
18
|
+
|
19
|
+
# Code Transaction Description
|
20
|
+
# =============================
|
21
|
+
# 13 Externally initiated debit items
|
22
|
+
# 50 Externally initiated credit items with the exception of those bearing Transaction Codes
|
23
|
+
# 51 Australian Government Security Interest
|
24
|
+
# 52 Family Allowance
|
25
|
+
# 53 Pay
|
26
|
+
# 54 Pension
|
27
|
+
# 55 Allotment
|
28
|
+
# 56 Dividend
|
29
|
+
# 57 Debenture/Note Interest
|
30
|
+
|
31
|
+
@@transaction_codes = Set.new [
|
32
|
+
"13", "50", "51", "52", "53", "54", "55", "56", "57"
|
33
|
+
]
|
34
|
+
|
35
|
+
attr_reader :bsb, :account_number, :indicator, :transaction_code, :amount, :name,
|
36
|
+
:lodgement_reference, :trace_bsb, :trace_account, :remitter, :witholding_amount
|
37
|
+
|
38
|
+
def initialize(attrs={})
|
39
|
+
@type = "1"
|
40
|
+
@bsb = attrs[:bsb]
|
41
|
+
@account_number = attrs[:account_number]
|
42
|
+
self.indicator = attrs[:indicator] || "N"
|
43
|
+
self.transaction_code = attrs[:transaction_code] || "53"
|
44
|
+
@amount = attrs[:amount] || 0
|
45
|
+
@name = attrs[:name]
|
46
|
+
@lodgement_reference = attrs[:lodgement_reference] || WageSlave.configuration.user_name
|
47
|
+
@trace_bsb = attrs[:trace_bsb] || WageSlave.configuration.bank_code
|
48
|
+
@trace_account = attrs[:trace_account] || WageSlave.configuration.account_number
|
49
|
+
@remitter = attrs[:remitter] || WageSlave.configuration.user_name
|
50
|
+
@witholding_amount = attrs[:tax_withholding] || 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def transaction_code=(code)
|
54
|
+
@transaction_code = code if @@transaction_codes.include? code
|
55
|
+
end
|
56
|
+
|
57
|
+
def indicator=(key)
|
58
|
+
@indicator = key if @@indicators.include? key
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# This method was adapted from https://github.com/andrba/aba which is released under MIT.
|
63
|
+
# See /LICENSE.txt for details.
|
64
|
+
|
65
|
+
def to_s
|
66
|
+
raise RuntimeError.new "Detail record is invalid. Check the contents of 'errors'" unless self.valid?
|
67
|
+
|
68
|
+
# Record type
|
69
|
+
# Size: 1
|
70
|
+
# Char position: 1
|
71
|
+
# Must be 1
|
72
|
+
output = @type
|
73
|
+
|
74
|
+
# BSB of account
|
75
|
+
# Size: 7
|
76
|
+
# Char position: 2-8
|
77
|
+
# Format: XXX-XXX
|
78
|
+
output += @bsb.to_s
|
79
|
+
|
80
|
+
# Account number
|
81
|
+
# Size: 9
|
82
|
+
# Char position: 9-17
|
83
|
+
# Blank filled, right justified.
|
84
|
+
output += @account_number.to_s.rjust(9, " ")
|
85
|
+
|
86
|
+
# Indicator
|
87
|
+
# Size: 1
|
88
|
+
# Char position: 18
|
89
|
+
# Valid entries: N, W, X or Y.
|
90
|
+
output += @indicator.to_s.ljust(1, " ")
|
91
|
+
|
92
|
+
# Transaction Code
|
93
|
+
# Size: 2
|
94
|
+
# Char position: 19-20
|
95
|
+
output += @transaction_code.to_s
|
96
|
+
|
97
|
+
# Amount to be credited or debited
|
98
|
+
# Size: 10
|
99
|
+
# Char position: 21-30
|
100
|
+
# Numeric only, shown in cents. Right justified, zero filled.
|
101
|
+
output += @amount.to_i.abs.to_s.rjust(10, "0")
|
102
|
+
|
103
|
+
# Title of Account
|
104
|
+
# Full BECS character set valid
|
105
|
+
# Size: 32
|
106
|
+
# Char position: 31-62
|
107
|
+
# Blank filled, left justified.
|
108
|
+
output += @name.to_s.ljust(32, " ")
|
109
|
+
|
110
|
+
# Lodgement Reference Produced on the recipient’s Account Statement.
|
111
|
+
# Size: 18
|
112
|
+
# Char position: 63-80
|
113
|
+
# Full BECS character set valid
|
114
|
+
# Blank filled, left justified.
|
115
|
+
output += @lodgement_reference.to_s.ljust(18, " ")
|
116
|
+
|
117
|
+
# Trace BSB Number
|
118
|
+
# Size: 7
|
119
|
+
# Char position: 81-87
|
120
|
+
# Format: XXX-XXX
|
121
|
+
output += @trace_bsb.to_s
|
122
|
+
|
123
|
+
# Trace Account Number
|
124
|
+
# Size: 9
|
125
|
+
# Char position: 88-96
|
126
|
+
# Blank filled, right justified.
|
127
|
+
output += @trace_account.to_s.rjust(9, " ")
|
128
|
+
|
129
|
+
# Name of Remitter Produced on the recipient’s Account Statement
|
130
|
+
# Size: 16
|
131
|
+
# Char position: 97-112
|
132
|
+
# Full BECS character set valid
|
133
|
+
# Blank filled, left justified.
|
134
|
+
output += @remitter.to_s.ljust(16, " ")
|
135
|
+
|
136
|
+
# Withholding amount in cents
|
137
|
+
# Size: 8
|
138
|
+
# Char position: 113-120
|
139
|
+
# Numeric only, shown in cents. Right justified, zero filled.
|
140
|
+
output += @witholding_amount.abs.to_s.rjust(8, "0")
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module WageSlave
|
2
|
+
|
3
|
+
##
|
4
|
+
# Configuration for WageSlave
|
5
|
+
#
|
6
|
+
# @financial_institution is your bank
|
7
|
+
# @bank_code is your BSB for Australian banks
|
8
|
+
# @user_id is your banking account ID
|
9
|
+
# @description is the default description for transactions
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
attr_accessor :financial_institution, :bank_code, :user_id, :user_name, :account_number, :description
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@financial_institution = nil
|
16
|
+
@bank_code = nil
|
17
|
+
@account_number = nil
|
18
|
+
@user_id = "000001"
|
19
|
+
@user_name = nil
|
20
|
+
@description = "Payroll"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Simple way to configure WageSlave
|
27
|
+
# WageSlave.configure do | config |
|
28
|
+
# config.bank_code = "123-234"
|
29
|
+
# end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
attr_writer :configuration
|
33
|
+
|
34
|
+
def configuration
|
35
|
+
@configuration ||= Configuration.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset
|
39
|
+
@configuration = Configuration.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def configure
|
43
|
+
yield(configuration)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# A module mixin for simple Ruby data validation. No Rails needed. Basic, but highly extentable with different kinds of
|
2
|
+
# validators. You can create new validation types by adding to the case statement on line 77, and adding an accompanying
|
3
|
+
# method.
|
4
|
+
|
5
|
+
module WageSlave
|
6
|
+
|
7
|
+
module Validation
|
8
|
+
def valid?
|
9
|
+
klass = Object.const_get("#{self.class.name}Validator")
|
10
|
+
@validator = klass.new(self)
|
11
|
+
@validator.valid?
|
12
|
+
end
|
13
|
+
|
14
|
+
def errors
|
15
|
+
return {} unless defined?(@validator)
|
16
|
+
@validator.errors
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class ValidationErrors
|
21
|
+
attr_accessor :all
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@all = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def add(name, msg)
|
28
|
+
(@all[name] ||= []) << msg
|
29
|
+
end
|
30
|
+
|
31
|
+
def full_messages
|
32
|
+
@all.map do |e|
|
33
|
+
"#{e.first.capitalize} #{e.last.join(' & ')}. "
|
34
|
+
end.join
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Validate
|
39
|
+
def self.included(base)
|
40
|
+
base.send(:include, InstanceMethods)
|
41
|
+
base.extend(ClassMethods)
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
attr_reader :object, :errors
|
46
|
+
|
47
|
+
def initialize(object)
|
48
|
+
@object = object
|
49
|
+
@errors = ValidationErrors.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?
|
53
|
+
self.class.validators.each { |args| validate(args) }
|
54
|
+
@errors.all.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def validate(args)
|
60
|
+
case
|
61
|
+
when args[1].key?(:with)
|
62
|
+
with_validator(*args)
|
63
|
+
when args[1].key?(:type)
|
64
|
+
type_validator(*args)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def with_validator(name, options)
|
69
|
+
fail unless options[:with].call(@object)
|
70
|
+
rescue
|
71
|
+
@errors.add(name, options[:msg])
|
72
|
+
end
|
73
|
+
|
74
|
+
def type_validator(name, options)
|
75
|
+
return if @object.send(name).is_a?(options[:type])
|
76
|
+
@errors.add(name, "must be a #{options[:type].name}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module ClassMethods
|
81
|
+
def validates(*args)
|
82
|
+
create_validation(args)
|
83
|
+
end
|
84
|
+
|
85
|
+
def validators
|
86
|
+
@validators
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def create_validation(args)
|
92
|
+
@validators = [] unless defined?(@validators)
|
93
|
+
@validators << args
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
class DescriptiveRecordValidator
|
4
|
+
|
5
|
+
include WageSlave::Validate
|
6
|
+
|
7
|
+
validates :type,
|
8
|
+
with: proc { |p| p.type === "0" },
|
9
|
+
msg: "must be '0'"
|
10
|
+
|
11
|
+
validates :bsb,
|
12
|
+
with: proc { |p| p.bsb.nil? ? true : p.bsb.to_s =~ /^\d{3}-\d{3}$/ },
|
13
|
+
msg: "is not in the required format (xxx-xxx)"
|
14
|
+
|
15
|
+
validates :financial_institution,
|
16
|
+
with: proc { |p| p.financial_institution.to_s.length === 3 },
|
17
|
+
msg: "must be valid 3 character abbreviation of an Australian financial institution"
|
18
|
+
|
19
|
+
validates :user_name,
|
20
|
+
with: proc { |p| p.user_name.to_s.length <= 26 },
|
21
|
+
msg: "must not exceed 26 characters"
|
22
|
+
|
23
|
+
validates :user_id,
|
24
|
+
with: proc { |p| p.user_id.to_s =~ /^\d{6}$/ },
|
25
|
+
msg: "must not exceed 6 characters and may only be numeric"
|
26
|
+
|
27
|
+
validates :description,
|
28
|
+
with: proc { |p| p.description.to_s.length <= 12 },
|
29
|
+
msg: "must not exceed 12 characters"
|
30
|
+
|
31
|
+
validates :process_at,
|
32
|
+
with: proc { |p| p.process_at.is_a? Date },
|
33
|
+
msg: "must be an instance of Date"
|
34
|
+
|
35
|
+
validates :reel_sequence,
|
36
|
+
with: proc { |p| p.reel_sequence =~ /^\d{2}$/ },
|
37
|
+
msg: "must be 2 digits up to 99"
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module WageSlave
|
2
|
+
class ABA
|
3
|
+
class DetailRecordValidator
|
4
|
+
|
5
|
+
include WageSlave::Validate
|
6
|
+
|
7
|
+
validates :type,
|
8
|
+
with: proc { |p| p.type === '1' },
|
9
|
+
msg: "must be '1'"
|
10
|
+
|
11
|
+
validates :bsb,
|
12
|
+
with: proc { |p| p.bsb =~ /^\d{3}-\d{3}$/ },
|
13
|
+
msg: "is not in the required format (xxx-xxx)"
|
14
|
+
|
15
|
+
validates :account_number,
|
16
|
+
with: proc { |p| p.account_number.to_s =~ /^[\d\- ]{1,9}$/ && p.account_number !~ /^0*$/ },
|
17
|
+
msg: "not a valid account number"
|
18
|
+
|
19
|
+
validates :indicator,
|
20
|
+
type: String,
|
21
|
+
msg: "must be defined as a String"
|
22
|
+
|
23
|
+
validates :transaction_code,
|
24
|
+
type: String,
|
25
|
+
msg: "must be defined as a String"
|
26
|
+
|
27
|
+
validates :amount,
|
28
|
+
with: proc { |p| p.amount > 0 && p.amount <= 9_999_999_999 },
|
29
|
+
msg: "must be greater than 0 and less than 10,000,000,000"
|
30
|
+
|
31
|
+
validates :name,
|
32
|
+
with: proc { |p| p.name.to_s.length > 0 && p.name.to_s.length <= 32 },
|
33
|
+
msg: "is required and must not be longer than 32 characters"
|
34
|
+
|
35
|
+
validates :lodgement_reference,
|
36
|
+
with: proc { |p| p.lodgement_reference.to_s.length > 0 && p.lodgement_reference.to_s.length <= 18 },
|
37
|
+
msg: "is required and must not be longer than 18 characters"
|
38
|
+
|
39
|
+
validates :trace_bsb,
|
40
|
+
with: proc { |p| p.trace_bsb =~ /^\d{3}-\d{3}$/ },
|
41
|
+
msg: "is not in the required format (xxx-xxx)"
|
42
|
+
|
43
|
+
validates :trace_account,
|
44
|
+
with: proc { |p| p.trace_account.to_s =~ /^[\d\- ]{1,9}$/ && p.trace_account !~ /^0*$/ },
|
45
|
+
msg: "not a valid account number"
|
46
|
+
|
47
|
+
validates :remitter,
|
48
|
+
with: proc { |p| p.remitter.to_s.length > 0 && p.remitter.to_s.length <= 16 },
|
49
|
+
msg: "is required and must not be longer than 16 characters"
|
50
|
+
|
51
|
+
validates :witholding_amount,
|
52
|
+
with: proc { |p| p.witholding_amount <= 99_999_999 },
|
53
|
+
msg: "must be less than 100,000,000"
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/travis.yml
ADDED
data/wage_slave.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wage_slave/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wage_slave"
|
8
|
+
spec.version = WageSlave::VERSION
|
9
|
+
spec.authors = ["James Gemmell", "Jasper Boyschau"]
|
10
|
+
spec.email = ["dev@noyelling.com.au"]
|
11
|
+
|
12
|
+
spec.summary = %q{Generate ABA, NZ-DE and IB4B direct entry files.}
|
13
|
+
spec.description = %q{A toolkit for generating and working with bulk payment files in various banking formats.}
|
14
|
+
spec.homepage = "http://github.com/noyelling/wage_slave"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
25
|
+
spec.add_development_dependency "mocha", "~> 1.1"
|
26
|
+
spec.add_development_dependency "dotenv", "~> 2.1"
|
27
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.1"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wage_slave
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Gemmell
|
8
|
+
- Jasper Boyschau
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-08-31 00:00:00.000000000 Z
|
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: '1.11'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.11'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: minitest
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '5.0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '5.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: mocha
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.1'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.1'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: dotenv
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.1'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.1'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: minitest-reporters
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '1.1'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.1'
|
98
|
+
description: A toolkit for generating and working with bulk payment files in various
|
99
|
+
banking formats.
|
100
|
+
email:
|
101
|
+
- dev@noyelling.com.au
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".env.example"
|
107
|
+
- ".gitignore"
|
108
|
+
- ".travis.yml"
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- lib/wage_slave.rb
|
116
|
+
- lib/wage_slave/aba.rb
|
117
|
+
- lib/wage_slave/aba/descriptive_record.rb
|
118
|
+
- lib/wage_slave/aba/detail_collection.rb
|
119
|
+
- lib/wage_slave/aba/detail_record.rb
|
120
|
+
- lib/wage_slave/aba/record.rb
|
121
|
+
- lib/wage_slave/configuration.rb
|
122
|
+
- lib/wage_slave/validation.rb
|
123
|
+
- lib/wage_slave/validators/descriptive_record_validator.rb
|
124
|
+
- lib/wage_slave/validators/detail_record_validator.rb
|
125
|
+
- lib/wage_slave/version.rb
|
126
|
+
- travis.yml
|
127
|
+
- wage_slave.gemspec
|
128
|
+
homepage: http://github.com/noyelling/wage_slave
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 2.4.8
|
149
|
+
signing_key:
|
150
|
+
specification_version: 4
|
151
|
+
summary: Generate ABA, NZ-DE and IB4B direct entry files.
|
152
|
+
test_files: []
|