aba_generator 0.3.1 → 1.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 +4 -4
- data/README.md +22 -1
- data/lib/aba_generator.rb +94 -1
- data/lib/aba_generator/balancing_line.rb +9 -0
- data/lib/aba_generator/core_ext/symbol.rb +17 -0
- data/lib/aba_generator/definition.rb +51 -0
- data/lib/aba_generator/fixed_width/column.rb +85 -0
- data/lib/aba_generator/fixed_width/definition.rb +31 -0
- data/lib/aba_generator/fixed_width/generator.rb +20 -0
- data/lib/aba_generator/fixed_width/parser.rb +47 -0
- data/lib/aba_generator/fixed_width/section.rb +91 -0
- data/lib/aba_generator/fixed_width_generator.rb +71 -0
- data/lib/aba_generator/footer.rb +9 -0
- data/lib/aba_generator/header.rb +17 -0
- data/lib/aba_generator/row.rb +9 -0
- data/lib/aba_generator/version.rb +1 -1
- metadata +13 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4ae57548c24971d2f8663b37074f196e43a6b0907253bb26bc939fe92d4ef71
|
4
|
+
data.tar.gz: 6fecbc8f643baecc95472091eff95ae4c8300a5a8eb849f6b223cfc55e84f496
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 652181f14e1716ab1c45d4be01ba7cb7f66efdf9528bf2bacd40ae3d84938b1082e50d17864248ecdef87ed373ef2134be6ba6064e797b216b4733cc5bdcc086
|
7
|
+
data.tar.gz: 7a54c370356480de890668e3b1b18b59c7d630ac17059f7eccb0b4b62cf2ae824ff3ff1d89a7e54b221a5b1076d5be2db9492ec67205ff919308ee62205631f3
|
data/README.md
CHANGED
@@ -22,7 +22,28 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
```ruby
|
26
|
+
aba = AbaGenerator.new(
|
27
|
+
instutition_code: "CBA",
|
28
|
+
description: "PAYROLL",
|
29
|
+
source_bsb: "123-456",
|
30
|
+
source_account_number: "123456789",
|
31
|
+
remitter_name: "TEST",
|
32
|
+
include_balancing_line: true # defaults to false
|
33
|
+
)
|
34
|
+
|
35
|
+
@payments.each do |payment|
|
36
|
+
aba.add_row(
|
37
|
+
bsb: '123-456',
|
38
|
+
account_number: '1234567',
|
39
|
+
account_name: 'J E SMITH',
|
40
|
+
amount: 100.00,
|
41
|
+
reference: "Payroll #{Time.new.strftime('%m-%d')}"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
output = aba.generate
|
46
|
+
```
|
26
47
|
|
27
48
|
## Development
|
28
49
|
|
data/lib/aba_generator.rb
CHANGED
@@ -2,9 +2,102 @@ require 'aba_generator/version'
|
|
2
2
|
require 'ostruct'
|
3
3
|
require 'aba_generator/core_ext/symbol'
|
4
4
|
require 'aba_generator/fixed_width_generator'
|
5
|
+
require 'aba_generator/fixed_width/column'
|
6
|
+
require 'aba_generator/fixed_width/definition'
|
7
|
+
require 'aba_generator/fixed_width/generator'
|
8
|
+
require 'aba_generator/fixed_width/parser'
|
9
|
+
require 'aba_generator/fixed_width/section'
|
10
|
+
require 'aba_generator/header'
|
11
|
+
require 'aba_generator/row'
|
12
|
+
require 'aba_generator/balancing_line'
|
13
|
+
require 'aba_generator/footer'
|
5
14
|
|
6
15
|
module AbaGenerator
|
7
16
|
class Error < StandardError; end
|
8
17
|
|
9
|
-
|
18
|
+
def initialize(options = {})
|
19
|
+
# OPTIONS
|
20
|
+
# institution_code
|
21
|
+
# user_name
|
22
|
+
# user_id
|
23
|
+
# description
|
24
|
+
# source_bsb
|
25
|
+
# source_account_number
|
26
|
+
# remitter_name
|
27
|
+
# include_balancing_line
|
28
|
+
|
29
|
+
@options = options
|
30
|
+
AbaGenerator::Definition.define_fixed_width(@options)
|
31
|
+
|
32
|
+
results = {}
|
33
|
+
|
34
|
+
# Define the Header
|
35
|
+
results[:header] = AbaGenerator::Header.new(@options)
|
36
|
+
results[:body] = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate(records)
|
40
|
+
AbaGenerator::Definition.define_fixed_width
|
41
|
+
|
42
|
+
# Create totals
|
43
|
+
total = 0
|
44
|
+
|
45
|
+
# # Create the record rows
|
46
|
+
# records.each do |p|
|
47
|
+
# results[:body] << {
|
48
|
+
# :record_type => 1,
|
49
|
+
# :bsb => p.bank_account.bsb_sep,
|
50
|
+
# :account_number => ('%9.9s' % p.bank_account.full_account_number),
|
51
|
+
# :txcode => 53,
|
52
|
+
# :amount => sprintf("%0.10d", (p.amount * 100).to_i),
|
53
|
+
# :account_name => p.bank_account.account_name.truncate(32, omission: '').upcase,
|
54
|
+
# :reference => "PRIZE #{p.prize.prize_number}",
|
55
|
+
# :source_bsb => @options[:source_bsb],
|
56
|
+
# :source_account_number => ('%9.9s' % @options[:source_account_number]),
|
57
|
+
# :remitter_name => @options[:remitter_name].truncate(16, omission: '')
|
58
|
+
# }
|
59
|
+
# total += p.amount
|
60
|
+
# end
|
61
|
+
|
62
|
+
# if @options[:include_balancing_line]
|
63
|
+
# results[:body] << {
|
64
|
+
# :record_type => 1,
|
65
|
+
# :bsb => @options[:source_bsb],
|
66
|
+
# :account_number => ('%9.9s' % @options[:source_account_number]),
|
67
|
+
# :txcode => 13,
|
68
|
+
# :amount => sprintf("%0.10d", (total*100).to_i),
|
69
|
+
# :account_name => @options[:remitter_name].truncate(16, omission: ''),
|
70
|
+
# :reference => @options[:description],
|
71
|
+
# :source_bsb => @options[:source_bsb],
|
72
|
+
# :source_account_number => ('%9.9s' % @options[:source_account_number]),
|
73
|
+
# :remitter_name => @options[:remitter_name].truncate(16, omission: '')
|
74
|
+
# }
|
75
|
+
# end
|
76
|
+
|
77
|
+
# # Create the footer, with totals
|
78
|
+
# if @options[:include_balancing_line]
|
79
|
+
# results[:footer] = [{
|
80
|
+
# :record_type => 7,
|
81
|
+
# :bsb_filler => "999-999",
|
82
|
+
# :net_total => 0,
|
83
|
+
# :credit_total => sprintf("%0.10d", (total*100).to_i),
|
84
|
+
# :debit_total => sprintf("%0.10d", (total*100).to_i),
|
85
|
+
# :records_count => (records.count + 1)
|
86
|
+
# }]
|
87
|
+
# else
|
88
|
+
# results[:footer] = [{
|
89
|
+
# :record_type => 7,
|
90
|
+
# :bsb_filler => "999-999",
|
91
|
+
# :net_total => sprintf("%0.10d", (total*100).to_i),
|
92
|
+
# :credit_total => sprintf("%0.10d", (total*100).to_i),
|
93
|
+
# :debit_total => 0,
|
94
|
+
# :records_count => records.count
|
95
|
+
# }]
|
96
|
+
# end
|
97
|
+
|
98
|
+
# Render the output as a string
|
99
|
+
FixedWidthGenerator.generate(:aba, results)
|
100
|
+
|
101
|
+
end
|
102
|
+
|
10
103
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#
|
2
|
+
# Taken from ActiveSupport 2.3.5 lib/active_support/core_ext/symbol.rb
|
3
|
+
#
|
4
|
+
unless :to_proc.respond_to?(:to_proc)
|
5
|
+
class Symbol
|
6
|
+
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
|
7
|
+
#
|
8
|
+
# # The same as people.collect { |p| p.name }
|
9
|
+
# people.collect(&:name)
|
10
|
+
#
|
11
|
+
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
|
12
|
+
# people.select(&:manager?).collect(&:salary)
|
13
|
+
def to_proc
|
14
|
+
Proc.new { |*args| args.shift.__send__(self, *args) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class AbaGenerator
|
2
|
+
class Definition
|
3
|
+
|
4
|
+
def self.define_fixed_width(options={})
|
5
|
+
# Create a FixedWidthGenerator::Defintion to describe ABA file format
|
6
|
+
FixedWidthGenerator.define :aba do |d|
|
7
|
+
# Create the ABA DESCRIPTION line
|
8
|
+
d.header(:align => :left) do |header|
|
9
|
+
header.column :record_type, 1, :parser => :to_i
|
10
|
+
header.spacer 17
|
11
|
+
header.column :reel_sequence_number, 2
|
12
|
+
header.column :institution_code, 3
|
13
|
+
header.spacer 7
|
14
|
+
header.column :user_name, 26
|
15
|
+
header.column :user_id, 6, :padding => "0"
|
16
|
+
header.column :description, 12
|
17
|
+
header.column :process_date, 6
|
18
|
+
header.spacer 40
|
19
|
+
end
|
20
|
+
|
21
|
+
d.body(:align => :left) do |body|
|
22
|
+
body.column :record_type, 1, :parser => :to_i
|
23
|
+
body.column :bsb, 7
|
24
|
+
body.column :account_number, 9
|
25
|
+
body.column :indicator, 1
|
26
|
+
body.column :txcode, 2
|
27
|
+
body.column :amount, 10
|
28
|
+
body.column :account_name, 32
|
29
|
+
body.column :reference, 18
|
30
|
+
body.column :source_bsb, 7
|
31
|
+
body.column :source_account_number, 9
|
32
|
+
body.column :remitter_name, 16
|
33
|
+
body.column :withholding_tax_amt, 8, padding: "0"
|
34
|
+
end
|
35
|
+
|
36
|
+
d.footer(:align => :right) do |footer|
|
37
|
+
footer.column :record_type, 1, :parser => :to_i
|
38
|
+
footer.column :bsb_filler, 7
|
39
|
+
footer.spacer 12
|
40
|
+
footer.column :net_total, 10, :padding => "0"
|
41
|
+
footer.column :credit_total, 10, :padding => "0"
|
42
|
+
footer.column :debit_total, 10, :padding => "0"
|
43
|
+
footer.spacer 24
|
44
|
+
footer.column :records_count, 6, :padding => "0"
|
45
|
+
footer.spacer 40
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class Column
|
3
|
+
DEFAULT_PADDING = ' '
|
4
|
+
DEFAULT_ALIGNMENT = :right
|
5
|
+
DEFAULT_TRUNCATE = false
|
6
|
+
DEFAULT_FORMATTER = :to_s
|
7
|
+
|
8
|
+
attr_reader :name, :length, :alignment, :padding, :truncate, :group, :unpacker
|
9
|
+
|
10
|
+
def initialize(name, length, options={})
|
11
|
+
assert_valid_options(options)
|
12
|
+
@name = name
|
13
|
+
@length = length
|
14
|
+
@alignment = options[:align] || DEFAULT_ALIGNMENT
|
15
|
+
@padding = options[:padding] || DEFAULT_PADDING
|
16
|
+
@truncate = options[:truncate] || DEFAULT_TRUNCATE
|
17
|
+
|
18
|
+
@group = options[:group]
|
19
|
+
|
20
|
+
@unpacker = "A#{@length}"
|
21
|
+
|
22
|
+
@parser = options[:parser]
|
23
|
+
@parser ||= case @alignment
|
24
|
+
when :right then :lstrip
|
25
|
+
when :left then :rstrip
|
26
|
+
end
|
27
|
+
@parser = @parser.to_proc if @parser.is_a?(Symbol)
|
28
|
+
|
29
|
+
@formatter = options[:formatter]
|
30
|
+
@formatter ||= DEFAULT_FORMATTER
|
31
|
+
@formatter = @formatter.to_proc if @formatter.is_a?(Symbol)
|
32
|
+
|
33
|
+
@nil_blank = options[:nil_blank]
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(value)
|
37
|
+
if @nil_blank && blank?(value)
|
38
|
+
return nil
|
39
|
+
else
|
40
|
+
@parser.call(value)
|
41
|
+
end
|
42
|
+
rescue
|
43
|
+
raise ParserError.new("The value '#{value}' could not be parsed: #{$!}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def format(value)
|
47
|
+
pad(
|
48
|
+
validate_size(
|
49
|
+
@formatter.call(value)
|
50
|
+
)
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
BLANK_REGEX = /^\s*$/
|
56
|
+
def blank?(value)
|
57
|
+
value =~ BLANK_REGEX
|
58
|
+
end
|
59
|
+
|
60
|
+
def pad(value)
|
61
|
+
case @alignment
|
62
|
+
when :left
|
63
|
+
value.ljust(@length, @padding)
|
64
|
+
when :right
|
65
|
+
value.rjust(@length, @padding)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def assert_valid_options(options)
|
70
|
+
unless options[:align].nil? || [:left, :right].include?(options[:align])
|
71
|
+
raise ArgumentError.new("Option :align only accepts :right (default) or :left")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate_size(result)
|
76
|
+
return result if result.length <= @length
|
77
|
+
raise FixedWidthGenerator::FormattedStringExceedsLengthError.new(
|
78
|
+
"The formatted value '#{result}' in column '#{@name}' exceeds the allowed length of #{@length} chararacters.") unless @truncate
|
79
|
+
case @alignment
|
80
|
+
when :right then result[-@length,@length]
|
81
|
+
when :left then result[0,@length]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class Definition
|
3
|
+
attr_reader :sections, :templates, :options
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@sections = []
|
7
|
+
@templates = {}
|
8
|
+
@options = { :align => :right }.merge(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def section(name, options={}, &block)
|
12
|
+
raise DuplicateSectionNameError.new("Duplicate section name: '#{name}'") if @sections.detect{|s| s.name == name }
|
13
|
+
|
14
|
+
section = FixedWidthGenerator::Section.new(name, @options.merge(options))
|
15
|
+
section.definition = self
|
16
|
+
yield(section)
|
17
|
+
@sections << section
|
18
|
+
section
|
19
|
+
end
|
20
|
+
|
21
|
+
def template(name, options={}, &block)
|
22
|
+
section = FixedWidthGenerator::Section.new(name, @options.merge(options))
|
23
|
+
yield(section)
|
24
|
+
@templates[name] = section
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(method, *args, &block)
|
28
|
+
section(method, *args, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class Generator
|
3
|
+
|
4
|
+
def initialize(definition)
|
5
|
+
@definition = definition
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate(data)
|
9
|
+
@builder = []
|
10
|
+
@definition.sections.each do |section|
|
11
|
+
content = data[section.name]
|
12
|
+
arrayed_content = content.is_a?(Array) ? content : [content]
|
13
|
+
raise FixedWidthGenerator::RequiredSectionEmptyError.new("Required section '#{section.name}' was empty.") if (content.nil? || content.empty?) && !section.optional
|
14
|
+
arrayed_content.each {|row| @builder << section.format(row) }
|
15
|
+
end
|
16
|
+
@builder.join("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class Parser
|
3
|
+
def initialize(definition, file)
|
4
|
+
@definition = definition
|
5
|
+
@file = file
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse
|
9
|
+
@parsed = {}
|
10
|
+
@content = read_file
|
11
|
+
unless @content.empty?
|
12
|
+
@definition.sections.each do |section|
|
13
|
+
rows = fill_content(section)
|
14
|
+
raise FixedWidthGenerator::RequiredSectionNotFoundError.new("Required section '#{section.name}' was not found.") unless rows > 0 || section.optional
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@parsed
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def read_file
|
23
|
+
@file.readlines.map(&:chomp)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fill_content(section)
|
27
|
+
matches = 0
|
28
|
+
loop do
|
29
|
+
line = @content.first
|
30
|
+
break unless section.match(line)
|
31
|
+
add_to_section(section, line)
|
32
|
+
matches += 1
|
33
|
+
@content.shift
|
34
|
+
end
|
35
|
+
matches
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_to_section(section, line)
|
39
|
+
if section.singular
|
40
|
+
@parsed[section.name] = section.parse(line)
|
41
|
+
else
|
42
|
+
@parsed[section.name] ||= []
|
43
|
+
@parsed[section.name] << section.parse(line)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class Section
|
3
|
+
attr_accessor :definition, :optional, :singular
|
4
|
+
attr_reader :name, :columns, :options
|
5
|
+
|
6
|
+
def initialize(name, options={})
|
7
|
+
@name = name
|
8
|
+
@options = options
|
9
|
+
@columns = []
|
10
|
+
@trap = options[:trap]
|
11
|
+
@optional = options[:optional] || false
|
12
|
+
@singular = options[:singular] || false
|
13
|
+
end
|
14
|
+
|
15
|
+
def column(name, length, options={})
|
16
|
+
if column_names_by_group(options[:group]).include?(name)
|
17
|
+
raise FixedWidthGenerator::DuplicateColumnNameError.new("You have already defined a column named '#{name}' in the '#{options[:group].inspect}' group.")
|
18
|
+
end
|
19
|
+
if column_names_by_group(nil).include?(options[:group])
|
20
|
+
raise FixedWidthGenerator::DuplicateGroupNameError.new("You have already defined a column named '#{options[:group]}'; you cannot have a group and column of the same name.")
|
21
|
+
end
|
22
|
+
if group_names.include?(name)
|
23
|
+
raise FixedWidthGenerator::DuplicateGroupNameError.new("You have already defined a group named '#{name}'; you cannot have a group and column of the same name.")
|
24
|
+
end
|
25
|
+
|
26
|
+
col = Column.new(name, length, @options.merge(options))
|
27
|
+
@columns << col
|
28
|
+
col
|
29
|
+
end
|
30
|
+
|
31
|
+
def spacer(length, spacer=nil)
|
32
|
+
options = {}
|
33
|
+
options[:padding] = spacer if spacer
|
34
|
+
column(:spacer, length, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def trap(&block)
|
38
|
+
@trap = block
|
39
|
+
end
|
40
|
+
|
41
|
+
def template(name)
|
42
|
+
template = @definition.templates[name]
|
43
|
+
raise ArgumentError.new("Template '#{name}' not found as a known template.") unless template
|
44
|
+
@columns += template.columns
|
45
|
+
# Section options should trump template options
|
46
|
+
@options = template.options.merge(@options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def format(data)
|
50
|
+
@columns.map do |c|
|
51
|
+
hash = c.group ? data[c.group] : data
|
52
|
+
c.format(hash[c.name])
|
53
|
+
end.join
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse(line)
|
57
|
+
line_data = line.unpack(unpacker)
|
58
|
+
row = group_names.inject({}) {|h,g| h[g] = {}; h }
|
59
|
+
|
60
|
+
@columns.each_with_index do |c, i|
|
61
|
+
next if c.name == :spacer
|
62
|
+
assignee = c.group ? row[c.group] : row
|
63
|
+
assignee[c.name] = c.parse(line_data[i])
|
64
|
+
end
|
65
|
+
|
66
|
+
row
|
67
|
+
end
|
68
|
+
|
69
|
+
def match(raw_line)
|
70
|
+
raw_line.nil? ? false : @trap.call(raw_line)
|
71
|
+
end
|
72
|
+
|
73
|
+
def method_missing(method, *args)
|
74
|
+
column(method, *args)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def column_names_by_group(group)
|
80
|
+
@columns.select{|c| c.group == group }.map(&:name) - [:spacer]
|
81
|
+
end
|
82
|
+
|
83
|
+
def group_names
|
84
|
+
@columns.map(&:group).compact.uniq
|
85
|
+
end
|
86
|
+
|
87
|
+
def unpacker
|
88
|
+
@unpacker ||= @columns.map(&:unpacker).join
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class FixedWidthGenerator
|
2
|
+
class ParserError < RuntimeError; end
|
3
|
+
class DuplicateColumnNameError < StandardError; end
|
4
|
+
class DuplicateGroupNameError < StandardError; end
|
5
|
+
class DuplicateSectionNameError < StandardError; end
|
6
|
+
class RequiredSectionNotFoundError < StandardError; end
|
7
|
+
class RequiredSectionEmptyError < StandardError; end
|
8
|
+
class FormattedStringExceedsLengthError < StandardError; end
|
9
|
+
class ColumnMismatchError < StandardError; end
|
10
|
+
|
11
|
+
#
|
12
|
+
# [name] a symbol to reference this file definition later
|
13
|
+
# [option] a hash of default options for all sub-elements
|
14
|
+
# and a block that defines the sections of the file.
|
15
|
+
#
|
16
|
+
# returns: +Definition+ instance for this file description.
|
17
|
+
#
|
18
|
+
def self.define(name, options={}) # yields definition
|
19
|
+
definition = Definition.new(options)
|
20
|
+
yield(definition)
|
21
|
+
definitions[name] = definition
|
22
|
+
definition
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# [data] nested hash describing the contents of the sections
|
27
|
+
# [definition_name] symbol +name+ used in +define+
|
28
|
+
#
|
29
|
+
# returns: string of the transformed +data+ (into fixed-width records).
|
30
|
+
#
|
31
|
+
def self.generate(definition_name, data)
|
32
|
+
definition = definition(definition_name)
|
33
|
+
raise ArgumentError.new("Definition name '#{name}' was not found.") unless definition
|
34
|
+
generator = Generator.new(definition)
|
35
|
+
generator.generate(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# [file] IO object to write the +generate+d data
|
40
|
+
# [definition_name] symbol +name+ used in +define+
|
41
|
+
# [data] nested hash describing the contents of the sections
|
42
|
+
#
|
43
|
+
# writes transformed data to +file+ object as fixed-width records.
|
44
|
+
#
|
45
|
+
def self.write(file, definition_name, data)
|
46
|
+
file.write(generate(definition_name, data))
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# [file] IO object from which to read the fixed-width text records
|
51
|
+
# [definition_name] symbol +name+ used in +define+
|
52
|
+
#
|
53
|
+
# returns: parsed text records in a nested hash.
|
54
|
+
#
|
55
|
+
def self.parse(file, definition_name)
|
56
|
+
definition = definition(definition_name)
|
57
|
+
raise ArgumentError.new("Definition name '#{definition_name}' was not found.") unless definition
|
58
|
+
parser = Parser.new(definition, file)
|
59
|
+
parser.parse
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def self.definitions
|
65
|
+
@@definitions ||= {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.definition(name)
|
69
|
+
definitions[name]
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AbaGenerator
|
2
|
+
class Header
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
[{
|
6
|
+
:record_type => 0,
|
7
|
+
:reel_sequence_number => "01",
|
8
|
+
:institution_code => options[:institution_code],
|
9
|
+
:user_name => options[:user_name],
|
10
|
+
:user_id => (options[:user_id] || '000000'),
|
11
|
+
:description => options[:description],
|
12
|
+
:process_date => Time.new.strftime("%d%m%y")
|
13
|
+
}]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aba_generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keegan Bakker
|
@@ -27,6 +27,18 @@ files:
|
|
27
27
|
- bin/console
|
28
28
|
- bin/setup
|
29
29
|
- lib/aba_generator.rb
|
30
|
+
- lib/aba_generator/balancing_line.rb
|
31
|
+
- lib/aba_generator/core_ext/symbol.rb
|
32
|
+
- lib/aba_generator/definition.rb
|
33
|
+
- lib/aba_generator/fixed_width/column.rb
|
34
|
+
- lib/aba_generator/fixed_width/definition.rb
|
35
|
+
- lib/aba_generator/fixed_width/generator.rb
|
36
|
+
- lib/aba_generator/fixed_width/parser.rb
|
37
|
+
- lib/aba_generator/fixed_width/section.rb
|
38
|
+
- lib/aba_generator/fixed_width_generator.rb
|
39
|
+
- lib/aba_generator/footer.rb
|
40
|
+
- lib/aba_generator/header.rb
|
41
|
+
- lib/aba_generator/row.rb
|
30
42
|
- lib/aba_generator/version.rb
|
31
43
|
homepage: https://github.com/audata/aba_generator
|
32
44
|
licenses:
|