stagecoach 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/.document +5 -0
- data/.project +12 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/.DS_Store +0 -0
- data/lib/ach.rb +5 -0
- data/lib/ach/creator.rb +485 -0
- data/lib/ach/iterator.rb +7 -0
- data/lib/ach/observer.rb +25 -0
- data/lib/ach/parser.rb +124 -0
- data/spec/ach_spec.rb +99 -0
- data/spec/cach_conf +6 -0
- data/spec/spec_helper.rb +14 -0
- metadata +178 -0
data/.DS_Store
ADDED
Binary file
|
data/.document
ADDED
data/.project
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<projectDescription>
|
3
|
+
<name>ach</name>
|
4
|
+
<comment></comment>
|
5
|
+
<projects>
|
6
|
+
</projects>
|
7
|
+
<buildSpec>
|
8
|
+
</buildSpec>
|
9
|
+
<natures>
|
10
|
+
<nature>org.radrails.rails.core.railsnature</nature>
|
11
|
+
</natures>
|
12
|
+
</projectDescription>
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec", "~> 2.3.0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.6.4"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
gem "mocha", "0.9.11"
|
14
|
+
gem "extensions", "0.6.0"
|
15
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.3)
|
5
|
+
extensions (0.6.0)
|
6
|
+
git (1.2.5)
|
7
|
+
jeweler (1.6.4)
|
8
|
+
bundler (~> 1.0)
|
9
|
+
git (>= 1.2.5)
|
10
|
+
rake
|
11
|
+
mocha (0.9.11)
|
12
|
+
rake
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rcov (0.9.11)
|
15
|
+
rspec (2.3.0)
|
16
|
+
rspec-core (~> 2.3.0)
|
17
|
+
rspec-expectations (~> 2.3.0)
|
18
|
+
rspec-mocks (~> 2.3.0)
|
19
|
+
rspec-core (2.3.1)
|
20
|
+
rspec-expectations (2.3.0)
|
21
|
+
diff-lcs (~> 1.1.2)
|
22
|
+
rspec-mocks (2.3.0)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
bundler (~> 1.0.0)
|
29
|
+
extensions (= 0.6.0)
|
30
|
+
jeweler (~> 1.6.4)
|
31
|
+
mocha (= 0.9.11)
|
32
|
+
rcov
|
33
|
+
rspec (~> 2.3.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Doug Reed
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= ach
|
2
|
+
|
3
|
+
WellsFargo ACH file generation gem from Billfloat.
|
4
|
+
|
5
|
+
== Contributing to ach
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Doug Reed. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "ach"
|
18
|
+
gem.homepage = "http://github.com/dougereed/ach"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = "WellsFargo ACH file generator"
|
21
|
+
gem.description = "WellsFargo ACH file generator"
|
22
|
+
gem.email = "dougereed@gmail.com"
|
23
|
+
gem.authors = ["Doug Reed"]
|
24
|
+
gem.files.include 'lib/ach/*'
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rspec/core'
|
30
|
+
require 'rspec/core/rake_task'
|
31
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
32
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
36
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "ach #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/ach.rb
ADDED
data/lib/ach/creator.rb
ADDED
@@ -0,0 +1,485 @@
|
|
1
|
+
require 'extensions/object'
|
2
|
+
|
3
|
+
module Ach
|
4
|
+
class Creator
|
5
|
+
|
6
|
+
def self.block_count(filelines)
|
7
|
+
filelines = ((filelines.to_f+1)/10)
|
8
|
+
return filelines.round
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.write_header(content,ach_filename)
|
12
|
+
ach_file = File.new(ach_filename.path,"a+")
|
13
|
+
ach_file.puts(content)
|
14
|
+
ach_file.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.mod_operation(routing_num_mod)
|
18
|
+
@rtnum = routing_num_mod.to_s.split(//)
|
19
|
+
@multiply = Array.new
|
20
|
+
@multiply.push(@rtnum[0].to_i * 3)
|
21
|
+
@multiply.push(@rtnum[1].to_i * 7)
|
22
|
+
@multiply.push(@rtnum[2].to_i * 1)
|
23
|
+
@multiply.push(@rtnum[3].to_i * 3)
|
24
|
+
@multiply.push(@rtnum[4].to_i * 7)
|
25
|
+
@multiply.push(@rtnum[5].to_i * 1)
|
26
|
+
@multiply.push(@rtnum[6].to_i * 3)
|
27
|
+
@multiply.push(@rtnum[7].to_i * 7)
|
28
|
+
@add = (@multiply[0] + @multiply[1] + @multiply[2] + @multiply[3] + @multiply[4] + @multiply[5] + @multiply[6] + @multiply[7])
|
29
|
+
if (@add % 10) == 0
|
30
|
+
return (@add % 10)
|
31
|
+
else
|
32
|
+
return ((@add + 10 - (@add % 10)) - @add)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.create_file(structure,iterator,ach_filename)
|
37
|
+
# records = iterator.get_entry_details
|
38
|
+
|
39
|
+
@create_ach_file = File.new(ach_filename,"w+")
|
40
|
+
@create_ach_file.close
|
41
|
+
|
42
|
+
@addenda_count = 1
|
43
|
+
@addenda_record_count = Array.new
|
44
|
+
@trace_number = 0
|
45
|
+
@trace_number_counter = Array.new
|
46
|
+
@sequence_number = 1
|
47
|
+
@entry_hash_collector = Array.new
|
48
|
+
|
49
|
+
@filecontrol_debits = []
|
50
|
+
@filecontrol_credits = []
|
51
|
+
@entrydetails_counter= []
|
52
|
+
|
53
|
+
SecurityHeaderRecord.new(
|
54
|
+
:security_header => structure[:bank_params][:security_header],
|
55
|
+
:write_to_file => @create_ach_file)
|
56
|
+
|
57
|
+
file_header_obj = FileHeaderRecord.new(
|
58
|
+
:record_type => "1",
|
59
|
+
:priority_code => "01",
|
60
|
+
:record_size => "094",
|
61
|
+
:blocking_factor => "10",
|
62
|
+
:file_creation_date => structure[:file_header_record][:file_creation_date],
|
63
|
+
:file_creation_time => structure[:file_header_record][:file_creation_time],
|
64
|
+
:format_code => "1",
|
65
|
+
:file_id => structure[:bank_params][:file_id_yml],
|
66
|
+
:bank_name => structure[:bank_params][:name],
|
67
|
+
:company_name => structure[:file_header_record][:company_name],
|
68
|
+
:file_id_modifier => structure[:file_header_record][:file_id_modifier],
|
69
|
+
:origination_bank => "WELLS FARGO",
|
70
|
+
:wellsfargo_routing_number => " 091000019",
|
71
|
+
:write_to_file => @create_ach_file)
|
72
|
+
|
73
|
+
structure[:batch_header_records].each_with_index do |bhr,index|
|
74
|
+
@batch_debit_collector = []
|
75
|
+
@batch_credit_collector = []
|
76
|
+
|
77
|
+
@batch_header_obj = BatchHeaderRecord.new(
|
78
|
+
:record_type => '5',
|
79
|
+
:service_class_code => bhr[:service_class_code],
|
80
|
+
:company_name => bhr[:company_name],
|
81
|
+
:company_discretionary_data => (bhr[:company_discretionary_data] ? bhr[:company_discretionary_data] : nil),
|
82
|
+
:company_id => structure[:bank_params][:company_id_yml],
|
83
|
+
:standard_entry_class_code => bhr[:standard_entry_class_code],
|
84
|
+
:company_entry_description => bhr[:company_entry_description],
|
85
|
+
:company_descriptive_date => (bhr[:company_descriptive_date] ? bhr[:company_descriptive_date] : nil),
|
86
|
+
:effective_entry_date => bhr[:effective_entry_date],
|
87
|
+
:batch_number => (index+1).to_s,
|
88
|
+
:originator_status_code => "1",
|
89
|
+
:wellsfargo_routing_number => structure[:bank_params][:routing_num_originating_dfi_yml],
|
90
|
+
:write_to_file => @create_ach_file)
|
91
|
+
|
92
|
+
#chunk which supports creation of entry_detail db entries. Send in batch db entry's id
|
93
|
+
@entry_details = iterator.get_entry_details
|
94
|
+
@entrydetails_counter << @entry_details.size.to_i
|
95
|
+
@entry_details.each do |i|
|
96
|
+
@receiving_dfi_routing_num = i[:receiving_dfi_routing_number]
|
97
|
+
rt_num_check_mod = mod_operation(@receiving_dfi_routing_num)
|
98
|
+
@trace_number_counter.push @trace_number
|
99
|
+
@trace_number+=1
|
100
|
+
|
101
|
+
entry_detail = EntryDetailRecord.new(
|
102
|
+
:transaction_code => i[:transaction_code],
|
103
|
+
:receiving_dfi_routing_num => @receiving_dfi_routing_num,
|
104
|
+
:rt_num_check => rt_num_check_mod,
|
105
|
+
:receiving_dfi_acc_num => i[:receiving_dfi_account_number],
|
106
|
+
:amount => i[:amount].to_s.sub(/[.]/,''),
|
107
|
+
:individual_id => i[:individual_id],
|
108
|
+
:individual_name => (i[:individual_name].nil? ? "" : i[:individual_name]),
|
109
|
+
:routing_number => structure[:bank_params][:routing_num_originating_dfi_yml],
|
110
|
+
:trace_number => @trace_number,
|
111
|
+
:settlement_id => i.respond_to?(:settlement_id) ? i[:settlement_id] : nil,
|
112
|
+
:loan_payment_id => i.respond_to?(:loan_payment_id) ? i[:loan_payment_id] : nil,
|
113
|
+
:write_to_file => @create_ach_file,
|
114
|
+
:db_entry_amount => i[:amount]) #amount for storing the ach_@entry_details_table
|
115
|
+
|
116
|
+
if (i[:transaction_code]=="22" or i[:transaction_code]=="32")
|
117
|
+
@batch_credit_collector.push i[:amount].to_f
|
118
|
+
else
|
119
|
+
@batch_debit_collector.push i[:amount].to_f
|
120
|
+
end
|
121
|
+
|
122
|
+
@rdfi_rtn_split = @receiving_dfi_routing_num.slice(0..7)
|
123
|
+
@rdfi_rtn_split.each {|i| @entry_hash_collector.push i.to_i}
|
124
|
+
@addenda_count+=1
|
125
|
+
@addenda_record_count.push @addenda_count
|
126
|
+
end
|
127
|
+
#TODO: REPLACE addendacount!!! @entry_details[:records].size
|
128
|
+
batch_control = BatchControlRecord.new(
|
129
|
+
:service_class_code => bhr[:service_class_code],
|
130
|
+
:addenda_count => @entry_details.size,
|
131
|
+
:entry_hash => @entry_hash_collector.inject(0) {|sum,i| sum+i},
|
132
|
+
:total_debits => @batch_debit_collector.inject(0) {|sum,i| sum+i}.to_s.sub(/[.]/,''),
|
133
|
+
:total_credits => @batch_credit_collector.inject(0) {|sum,i| sum+i}.to_s.sub(/[.]/,''),
|
134
|
+
:company_id => structure[:bank_params][:company_id_yml],
|
135
|
+
:routing_num => structure[:bank_params][:routing_num_originating_dfi_yml],
|
136
|
+
:batch_number => (index+1).to_s,
|
137
|
+
:write_to_file => @create_ach_file)
|
138
|
+
@batch_credit_collector.each {|x| @filecontrol_credits << x}
|
139
|
+
@batch_debit_collector.each {|x| @filecontrol_debits << x}
|
140
|
+
end
|
141
|
+
|
142
|
+
# rt_num_check_mod = mod_operation(structure[:bank_params][:receiving_dfi_routing_num])
|
143
|
+
|
144
|
+
@count_filelines = %x(wc -l #{"#{ach_filename}"}).split.first.to_i
|
145
|
+
@block_count = block_count(@count_filelines)
|
146
|
+
#((@trace_number_counter.last-1)+(@addenda_record_count.last-1)), #TODO: REPLACE THIS!!! @entry_details[:records].size
|
147
|
+
file_control = FileControlRecord.new(
|
148
|
+
:batch_count => structure[:batch_header_records].size,
|
149
|
+
:block_count => @block_count,
|
150
|
+
:entry_addenda => @entrydetails_counter.inject(0) {|sum,i| sum+i},
|
151
|
+
:entry_hash_total => @entry_hash_collector.inject(0) {|sum,i| sum+i},
|
152
|
+
:total_debits => @filecontrol_debits.inject(0) {|sum,i| sum+i}.to_s.sub(/[.]/,''),
|
153
|
+
:total_credits => @filecontrol_credits.inject(0) {|sum,i| sum+i}.to_s.sub(/[.]/,''),
|
154
|
+
:write_to_file => @create_ach_file)
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
class SecurityHeaderRecord
|
160
|
+
attr_accessor :security_header
|
161
|
+
def initialize(options={})
|
162
|
+
@security_header = options[:security_header]
|
163
|
+
@write_to_file = options[:write_to_file]
|
164
|
+
encode
|
165
|
+
end
|
166
|
+
|
167
|
+
protected
|
168
|
+
|
169
|
+
def encode
|
170
|
+
begin
|
171
|
+
file = @security_header.strip
|
172
|
+
Ach::Creator.write_header(file,@write_to_file)
|
173
|
+
rescue Exception => ex
|
174
|
+
puts "Exception while writing ach file -- #{ex.class} #{ex.message} #{ex.backtrace.pp_s}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class FileHeaderRecord
|
180
|
+
attr_accessor :record_type, :priority_code, :routing_number, :file_id, :record_size, :file_id_modifier
|
181
|
+
attr_accessor :blocking_factor, :format_code, :origination_bank, :bank,:company_name,:bank_name,:call_encode
|
182
|
+
attr_accessor :file_creation_date,:file_creation_time
|
183
|
+
def initialize(options={})
|
184
|
+
@record_type = options[:record_type]
|
185
|
+
@priority_code = options[:priority_code]
|
186
|
+
@routing_number = options[:routing_number]
|
187
|
+
@file_id = options[:file_id]
|
188
|
+
@record_size = options[:record_size]
|
189
|
+
@blocking_factor = options[:blocking_factor]
|
190
|
+
@file_creation_date = options[:file_creation_date]
|
191
|
+
@file_creation_time = options[:file_creation_time]
|
192
|
+
@format_code = options[:format_code]
|
193
|
+
@company_name = options[:company_name]
|
194
|
+
@bank_name = options[:bank_name]
|
195
|
+
@write_to_file = options[:write_to_file]
|
196
|
+
@file_id_modifier = options[:file_id_modifier]
|
197
|
+
@origination_bank = options[:origination_bank]
|
198
|
+
@wellsfargo_routing_number = options[:wellsfargo_routing_number]
|
199
|
+
@call_encode = encode
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.decode(record,processor)
|
203
|
+
# change method sig to decode(record,processor)
|
204
|
+
file_header = CustomOrderedHash.new
|
205
|
+
file_header.insert(:record_type,record[0].chr)
|
206
|
+
file_header.insert(:priority_code,record[1,2])
|
207
|
+
file_header.insert(:routing_number,record[4,9])
|
208
|
+
file_header.insert(:file_id,record[13,10])
|
209
|
+
file_header.insert(:file_creation_date, record[23,6])
|
210
|
+
file_header.insert(:file_creation_time,record[29,4])
|
211
|
+
file_header.insert(:file_id_mod,record[33,1])
|
212
|
+
file_header.insert(:record_size ,record[34,3])
|
213
|
+
file_header.insert(:blocking_factor, record[37,2])
|
214
|
+
file_header.insert(:format_code, record[39,1])
|
215
|
+
file_header.insert(:origination_bank, record[40,23])
|
216
|
+
file_header.insert(:company_name,record[63,23])
|
217
|
+
processor.process(file_header)
|
218
|
+
# log_dump ="#{@record_type}#{@priority_code}#{@routing_number}#{@file_id}#{@file_creation_time}#{@file_id_mod}#{@record_size}#{@blocking_factor}#{@format_code}#{@origination_bank}#{@company_name}"
|
219
|
+
# Batch::PartnersAchGenerateLog::AchLogGenerator.log_return_process(log_dump)
|
220
|
+
end
|
221
|
+
|
222
|
+
protected
|
223
|
+
|
224
|
+
def encode
|
225
|
+
begin
|
226
|
+
# file = "#{@record_type}#{@priority_code} #{@routing_number}#{@file_id}#{file_creation_date.strftime('%y%m%d')}#{file_creation_time.strftime('%H%M')}#{@file_id_modifier}094#{@blocking_factor}#{@format_code}WELLS FARGO Billfloat "
|
227
|
+
file = "#{@record_type}#{@priority_code}#{@wellsfargo_routing_number}#{@file_id}#{@file_creation_date.strftime('%y%m%d')}#{@file_creation_time.strftime('%H%M')}#{@file_id_modifier}#{@record_size}#{@blocking_factor}#{@format_code}#{@origination_bank} #{@company_name} "
|
228
|
+
Ach::Creator.write_header(file,@write_to_file)
|
229
|
+
rescue Exception => ex
|
230
|
+
puts "Exception writing ach file -- #{ex.message} #{ex.backtrace.pp_s}"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
class BatchHeaderRecord
|
237
|
+
attr_accessor :record_type, :service_class_code, :sec_code, :company_entry_desc,:company_name
|
238
|
+
attr_accessor :effective_entry_date, :batch_number, :company_id, :originator_status_code, :routing_number,:company_descriptive_date
|
239
|
+
attr_accessor :company_discretionary_data,:company_entry_description,:company_desc_date,:settlement_date,:ach_file_id,:call_encode
|
240
|
+
def initialize(options={})
|
241
|
+
@record_type = options[:record_type]
|
242
|
+
@service_class_code = options[:service_class_code]
|
243
|
+
@company_name = options[:company_name]
|
244
|
+
@company_discretionary_data = options[:company_discretionary_data]
|
245
|
+
@company_id = options[:company_id]
|
246
|
+
@sec_code = options[:standard_entry_class_code]
|
247
|
+
@company_entry_desc = options[:company_entry_description]
|
248
|
+
@company_desc_date = options[:company_descriptive_date]
|
249
|
+
@posting_date = options[:effective_entry_date]
|
250
|
+
@batch_number = options[:batch_number]
|
251
|
+
@originator_status_code = options[:originator_status_code]
|
252
|
+
@wellsfargo_routing_number = options[:wellsfargo_routing_number]
|
253
|
+
@ach_file_id = options[:ach_file_id]
|
254
|
+
@write_to_file = options[:write_to_file]
|
255
|
+
@call_encode = encode
|
256
|
+
end
|
257
|
+
|
258
|
+
def self.decode(record,processor)
|
259
|
+
batch_header = CustomOrderedHash.new
|
260
|
+
batch_header.insert(:record_type,record[0].chr)
|
261
|
+
batch_header.insert(:@service_class_code,record[1,3])
|
262
|
+
batch_header.insert(:company_name,record[4,16])
|
263
|
+
batch_header.insert(:company_disc_data,record[20,20])
|
264
|
+
batch_header.insert(:company_id,record[40,10])
|
265
|
+
batch_header.insert(:sec_code,record[50,3])
|
266
|
+
batch_header.insert(:company_entry_desc,record[53,10])
|
267
|
+
batch_header.insert(:company_desc_date,record[63,6])
|
268
|
+
batch_header.insert(:posting_date, record[69,6])
|
269
|
+
batch_header.insert(:settlement_date,record[75,3])
|
270
|
+
batch_header.insert(:originator_status_code,record[78,1])
|
271
|
+
batch_header.insert(:routing_number,record[79,8])
|
272
|
+
batch_header.insert(:batch_number,record[87,7])
|
273
|
+
processor.process(batch_header)
|
274
|
+
end
|
275
|
+
|
276
|
+
protected
|
277
|
+
|
278
|
+
def encode
|
279
|
+
begin
|
280
|
+
file = @record_type
|
281
|
+
file << @service_class_code
|
282
|
+
file << @company_name.ljust(16)
|
283
|
+
file << (@company_discretionary_data ? @company_discretionary_data.ljust(20) : "".ljust(20))
|
284
|
+
file << @company_id.to_s.ljust(10)
|
285
|
+
file << @sec_code.upcase.ljust(3)
|
286
|
+
file << @company_entry_desc.ljust(10)
|
287
|
+
file << (@company_desc_date ? @company_desc_date.ljust(6) : "".ljust(6))
|
288
|
+
# file << (Date.today-1).strftime("%m%d%y").ljust(6) # Company Descriptive Date
|
289
|
+
if @posting_date.is_a?(String)
|
290
|
+
file << Date.parse(@posting_date).strftime("%y%m%d").to_s.ljust(6)
|
291
|
+
else
|
292
|
+
file << @posting_date.strftime("%y%m%d").to_s.ljust(6)
|
293
|
+
end
|
294
|
+
file << "".ljust(3) # Settlement date - leave blank
|
295
|
+
file << @originator_status_code.to_s.ljust(1)
|
296
|
+
file << @wellsfargo_routing_number.to_s.ljust(8)
|
297
|
+
@batch_number = "0000000000000"+@batch_number.to_s
|
298
|
+
file << @batch_number[-7,7] #added one number and minus from batch num digit count
|
299
|
+
Ach::Creator.write_header(file,@write_to_file)
|
300
|
+
# batch_header_entry.reload
|
301
|
+
# return batch_header_entry.id
|
302
|
+
rescue Exception => ex
|
303
|
+
puts "Exception while writing ach file -- #{ex.class} #{ex.message} #{ex.backtrace.pp_s}"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
class EntryDetailRecord
|
310
|
+
attr_accessor :record_type, :transaction_code, :routing_number_check, :receiving_dfi_acc_num,:rt_num_check
|
311
|
+
attr_accessor :amount, :individual_id,:receiving_dfi_routing_num,:individual_id,:individual_name
|
312
|
+
attr_accessor :routing_number, :trace_number,:disc_data,:addenda_record_indicator,:ach_batch_id,:settlement_id,:db_entry_amount
|
313
|
+
def initialize(options = {})
|
314
|
+
@record_type = '6'
|
315
|
+
@transaction_code = options[:transaction_code]
|
316
|
+
@receiving_dfi_routing_num = options[:receiving_dfi_routing_num]
|
317
|
+
@receiving_dfi_acc_num = options[:receiving_dfi_acc_num]
|
318
|
+
@rt_num_check = options[:rt_num_check]
|
319
|
+
@amount = options[:amount]
|
320
|
+
@individual_id = options[:individual_id]
|
321
|
+
@individual_name = options[:individual_name]
|
322
|
+
@routing_number = options[:routing_number]
|
323
|
+
@trace_number = options[:trace_number]
|
324
|
+
@ach_batch_id = options[:ach_batch_id]
|
325
|
+
@settlement_id = options[:settlement_id]
|
326
|
+
@db_entry_amount = options[:db_entry_amount]
|
327
|
+
@write_to_file = options[:write_to_file]
|
328
|
+
encode
|
329
|
+
end
|
330
|
+
|
331
|
+
def self.decode(record,processor)
|
332
|
+
entry_detail = CustomOrderedHash.new
|
333
|
+
entry_detail.insert(:record_type,record[0].chr)
|
334
|
+
entry_detail.insert(:transaction_code, record[1,2])
|
335
|
+
entry_detail.insert(:receiving_dfi_routing_num,record[3,8])
|
336
|
+
entry_detail.insert(:rt_num_check,record[11,1])
|
337
|
+
entry_detail.insert(:receiving_dfi_acc_num,record[12,17])
|
338
|
+
entry_detail.insert(:amount,record[29,10])
|
339
|
+
entry_detail.insert(:individual_id,record[39,15])
|
340
|
+
entry_detail.insert(:individual_name,record[54,22])
|
341
|
+
entry_detail.insert(:disc_data,record[76,2])
|
342
|
+
entry_detail.insert(:addenda_record_indicator,record[78,1])
|
343
|
+
entry_detail.insert(:@trace_number,record[79,15])
|
344
|
+
processor.process(entry_detail)
|
345
|
+
end
|
346
|
+
|
347
|
+
protected
|
348
|
+
|
349
|
+
def encode
|
350
|
+
begin
|
351
|
+
file = @record_type
|
352
|
+
file << @transaction_code
|
353
|
+
file << @receiving_dfi_routing_num.to_s.split(//).first(8).to_s
|
354
|
+
file << @rt_num_check.to_s
|
355
|
+
file << @receiving_dfi_acc_num.to_s.split(//).last(17).to_s.ljust(17)
|
356
|
+
file << @amount.rjust(10,"0")
|
357
|
+
file << @individual_id.to_s.ljust(15)
|
358
|
+
file << @individual_name.slice(0..21).ljust(22)
|
359
|
+
file << "".ljust(2) #9. discretionary data
|
360
|
+
file << "0"
|
361
|
+
@trace_number = "000000000000000"+@trace_number.to_s
|
362
|
+
file << @routing_number+@trace_number[-7,7]
|
363
|
+
Ach::Creator.write_header(file,@write_to_file)
|
364
|
+
rescue Exception => ex
|
365
|
+
puts "Exception while writing ach file -- #{ex.class} #{ex.message} #{ex.backtrace.pp_s}"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
class BatchControlRecord
|
372
|
+
attr_accessor :record_type, :service_class_code, :addenda_count,:entry_hash,:company_id
|
373
|
+
attr_accessor :total_debits,:total_credits,:batch_number,:routing_num,:msg_authentication_code
|
374
|
+
def initialize(options={})
|
375
|
+
@record_type = '8'
|
376
|
+
@service_class_code = options[:service_class_code]
|
377
|
+
@addenda_count = options[:addenda_count]
|
378
|
+
@entry_hash=options[:entry_hash]
|
379
|
+
@total_debits = options[:total_debits]
|
380
|
+
@total_credits = options[:total_credits]
|
381
|
+
@company_id = options[:company_id]
|
382
|
+
@routing_num = options[:routing_num]
|
383
|
+
@batch_number = options[:batch_number]
|
384
|
+
@write_to_file = options[:write_to_file]
|
385
|
+
encode
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.decode(record,processor)
|
389
|
+
batch_control = CustomOrderedHash.new
|
390
|
+
batch_control.insert(:record_type,record[0].chr)
|
391
|
+
batch_control.insert(:service_class_code,record[1,3])
|
392
|
+
batch_control.insert(:addenda_count,record[4,6])
|
393
|
+
batch_control.insert(:entry_hash,record[10,10])
|
394
|
+
batch_control.insert(:total_debits, record[20,12])
|
395
|
+
batch_control.insert(:total_credits, record[32,12])
|
396
|
+
batch_control.insert(:company_id, record[44,10])
|
397
|
+
batch_control.insert(:msg_authentication_code, record[54,19])
|
398
|
+
batch_control.insert(:reserved,record[73,6])
|
399
|
+
batch_control.insert(:routing_num, record[79,8])
|
400
|
+
batch_control.insert(:batch_number, record[87,7])
|
401
|
+
processor.process(batch_control)
|
402
|
+
end
|
403
|
+
|
404
|
+
protected
|
405
|
+
|
406
|
+
def encode
|
407
|
+
begin
|
408
|
+
file = @record_type
|
409
|
+
file << @service_class_code.to_s
|
410
|
+
@addenda_digit_count = @addenda_count.to_s.split(//)
|
411
|
+
if @addenda_digit_count.size > 1
|
412
|
+
file << @addenda_count.to_s.rjust(5,"0")
|
413
|
+
else
|
414
|
+
file << @addenda_count.to_s.rjust(6,"0")
|
415
|
+
end
|
416
|
+
file << @entry_hash.to_s.rjust(10,"0")
|
417
|
+
file << @total_debits.rjust(12,"0")
|
418
|
+
file << @total_credits.rjust(12,"0")
|
419
|
+
file << @company_id.to_s
|
420
|
+
file << "".ljust(19)
|
421
|
+
file << "".ljust(6)
|
422
|
+
file << @routing_num
|
423
|
+
@batch_number = "0000000000000" + @batch_number.to_s
|
424
|
+
file << @batch_number[-7,7]
|
425
|
+
Ach::Creator.write_header(file,@write_to_file)
|
426
|
+
rescue Exception => ex
|
427
|
+
puts "Exception while writing ach file -- #{ex.class} #{ex.message} #{ex.backtrace.pp_s}"
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
end
|
432
|
+
|
433
|
+
class FileControlRecord
|
434
|
+
attr_accessor :record_type,:batch_count,:block_count,:entry_addenda
|
435
|
+
attr_accessor :entry_hash_total,:total_debits,:total_credits
|
436
|
+
def initialize(options={})
|
437
|
+
@record_type = '9'
|
438
|
+
@batch_count = options[:batch_count]
|
439
|
+
@block_count = options[:block_count]
|
440
|
+
@entry_addenda = options[:entry_addenda]
|
441
|
+
@entry_hash_total = options[:entry_hash_total]
|
442
|
+
@total_debits = options[:total_debits]
|
443
|
+
@total_credits = options[:total_credits]
|
444
|
+
@write_to_file = options[:write_to_file]
|
445
|
+
encode
|
446
|
+
end
|
447
|
+
|
448
|
+
def self.decode(record,processor)
|
449
|
+
file_control = CustomOrderedHash.new
|
450
|
+
file_control.insert(:record_type,record[0].chr)
|
451
|
+
file_control.insert(:batch_count, record[1,6])
|
452
|
+
file_control.insert(:block_count, record[7,6])
|
453
|
+
file_control.insert(:entry_addenda, record[13,8])
|
454
|
+
file_control.insert(:entry_hash_total, record[21,10])
|
455
|
+
file_control.insert(:total_debits, record[31,12])
|
456
|
+
file_control.insert(:total_credits, record[43,12])
|
457
|
+
processor.process(file_control)
|
458
|
+
end
|
459
|
+
|
460
|
+
protected
|
461
|
+
|
462
|
+
def encode
|
463
|
+
begin
|
464
|
+
file = @record_type
|
465
|
+
file << @batch_count.to_s.rjust(6,"0")
|
466
|
+
file << @block_count.to_s.rjust(6,"0")
|
467
|
+
file << @entry_addenda.to_s.rjust(8,"0")
|
468
|
+
@entry_hash_total_digit_count = @entry_hash_total.to_s.split(//)
|
469
|
+
if @entry_hash_total_digit_count.size >= 10
|
470
|
+
file << @entry_hash_total.to_s.slice(1..10).rjust(10,"0")
|
471
|
+
else
|
472
|
+
file << @entry_hash_total.to_s.slice(0..10).rjust(10,"0")
|
473
|
+
end
|
474
|
+
file << @total_debits.rjust(12,"0")
|
475
|
+
file << @total_credits.rjust(12,"0")
|
476
|
+
file << "".ljust(39)
|
477
|
+
Ach::Creator.write_header(file,@write_to_file)
|
478
|
+
rescue Exception => ex
|
479
|
+
puts "\n Exception writing ACH file -- #{ex}"
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
end
|
data/lib/ach/iterator.rb
ADDED
data/lib/ach/observer.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ach
|
2
|
+
class Observer
|
3
|
+
|
4
|
+
def file_header(hash)
|
5
|
+
raise Exception.new "This should be implemented!"
|
6
|
+
end
|
7
|
+
|
8
|
+
def batch_header(hash)
|
9
|
+
raise Exception.new "This should be implemented!"
|
10
|
+
end
|
11
|
+
|
12
|
+
def entry_detail(hash)
|
13
|
+
raise Exception.new "This should be implemented!"
|
14
|
+
end
|
15
|
+
|
16
|
+
def batch_control(hash)
|
17
|
+
raise Exception.new "This should be implemented!"
|
18
|
+
end
|
19
|
+
|
20
|
+
def file_control(hash)
|
21
|
+
raise Exception.new "This should be implemented!"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/ach/parser.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
module Ach
|
2
|
+
class Parser
|
3
|
+
def self.parse_file(observer)
|
4
|
+
raise Exception.new "No file supplied. Cannot proceed!" if observer.filename.nil?
|
5
|
+
File.open(observer.filename).each do |l|
|
6
|
+
case l[0].chr
|
7
|
+
when "1"
|
8
|
+
file_header = FileHeaderRecord.decode(l)
|
9
|
+
observer.file_header(file_header)
|
10
|
+
when "5"
|
11
|
+
batch_header = BatchHeaderRecord.decode(l)
|
12
|
+
observer.batch_header(batch_header)
|
13
|
+
when "6"
|
14
|
+
entry_detail = EntryDetailRecord.decode(l)
|
15
|
+
observer.entry_detail(entry_detail)
|
16
|
+
when "8"
|
17
|
+
batch_control = BatchControlRecord.decode(l)
|
18
|
+
observer.batch_control(batch_control)
|
19
|
+
when "9"
|
20
|
+
unless (l.count "9") == 94
|
21
|
+
file_control = FileControlRecord.decode(l)
|
22
|
+
observer.file_control(file_control)
|
23
|
+
end
|
24
|
+
else
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class FileHeaderRecord
|
31
|
+
def self.decode(record)
|
32
|
+
fh = {}
|
33
|
+
fh[:record_type] = record[0].chr
|
34
|
+
fh[:priority_code] = record[1,2]
|
35
|
+
fh[:wellsfargo_routing_number] = record[4,9]
|
36
|
+
fh[:file_id] = record[13,10]
|
37
|
+
fh[:file_creation_date] = record[23,6]
|
38
|
+
fh[:file_creation_time] = record[29,4]
|
39
|
+
fh[:file_id_modifier] = record[33,1]
|
40
|
+
fh[:record_size] = record[34,3]
|
41
|
+
fh[:blocking_factor] = record[37,2]
|
42
|
+
fh[:format_code] = record[39,1]
|
43
|
+
fh[:origination_bank] = record[40,23]
|
44
|
+
fh[:company_name] = record[63,23]
|
45
|
+
return fh
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class BatchHeaderRecord
|
50
|
+
def self.decode(record)
|
51
|
+
bh = {}
|
52
|
+
bh[:record_type] = record[0].chr
|
53
|
+
bh[:service_class_code] = record[1,3]
|
54
|
+
bh[:company_name] = record[4,16]
|
55
|
+
bh[:company_discretionary_data] = record[20,20]
|
56
|
+
bh[:company_id] = record[40,10]
|
57
|
+
bh[:standard_entry_class_code] = record[50,3]
|
58
|
+
bh[:company_entry_description] = record[53,10]
|
59
|
+
bh[:company_descriptive_date] = record[63,6]
|
60
|
+
bh[:effective_entry_date] = record[69,6]
|
61
|
+
bh[:settlement_date] = record[75,3]
|
62
|
+
bh[:originator_status_code] = record[78,1]
|
63
|
+
bh[:wellsfargo_routing_number] = record[79,8]
|
64
|
+
bh[:batch_number] = record[87,7]
|
65
|
+
return bh
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class EntryDetailRecord
|
70
|
+
def self.decode(record)
|
71
|
+
ed = {}
|
72
|
+
ed[:record_type] = record[0].chr
|
73
|
+
ed[:transaction_code] = record[1,2]
|
74
|
+
ed[:receiving_dfi_routing_number] = record[3,8]
|
75
|
+
ed[:routing_number_check_digit] = record[11,1]
|
76
|
+
ed[:receiving_dfi_account_number] = record[12,17]
|
77
|
+
ed[:amount] = record[29,10]
|
78
|
+
ed[:individual_id] = record[39,15]
|
79
|
+
ed[:individual_name] = record[54,22]
|
80
|
+
ed[:discretionary_data] = record[76,2]
|
81
|
+
ed[:addenda_record_indicator] = record[78,1]
|
82
|
+
ed[:trace_number] = record[79,15]
|
83
|
+
return ed
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class BatchControlRecord
|
88
|
+
def self.decode(record)
|
89
|
+
bcr = {}
|
90
|
+
bcr[:record_type] = record[0].chr
|
91
|
+
bcr[:service_class_code] = record[1,3]
|
92
|
+
bcr[:entry_addenda_count] = record[4,6]
|
93
|
+
bcr[:entry_hash] = record[10,10]
|
94
|
+
bcr[:total_batch_debit_entry_dollar_amount] = record[20,12]
|
95
|
+
bcr[:total_batch_credit_entry_dollar_amount] = record[32,12]
|
96
|
+
bcr[:company_id] = record[44,10]
|
97
|
+
bcr[:message_authentication_code] = record[54,19]
|
98
|
+
bcr[:blank] = record[73,6]
|
99
|
+
bcr[:wellsfargo_routing_number] = record[79,8]
|
100
|
+
bcr[:batch_number] = record[87,7]
|
101
|
+
return bcr
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class FileControlRecord
|
106
|
+
def self.decode(record)
|
107
|
+
fcr = {}
|
108
|
+
msg_codes = []
|
109
|
+
msg_codes << record[56,2] unless record[56,2].match(/\s/)
|
110
|
+
msg_codes << record [58,2] unless record[58,2].match(/\s/)
|
111
|
+
msg_codes << record[60,2] unless record[60,2].match(/\s/)
|
112
|
+
fcr[:record_type] = record[0].chr
|
113
|
+
fcr[:batch_count] = record[1,6]
|
114
|
+
fcr[:block_count] = record[7,6]
|
115
|
+
fcr[:entry_addenda_record_count] = record[13,8]
|
116
|
+
fcr[:entry_hash_total] = record[21,10]
|
117
|
+
fcr[:total_file_debit_entry_amount] = record[31,12]
|
118
|
+
fcr[:total_file_credit_entry_amount] = record[43,12]
|
119
|
+
fcr[:message_codes] = msg_codes unless msg_codes.empty?
|
120
|
+
return fcr
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
data/spec/ach_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
include Ach
|
4
|
+
describe "Ach file generation" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@structure = {}
|
8
|
+
@structure[:bank_params] = {}
|
9
|
+
@structure[:bank_params][:name] = "wellsfargo"
|
10
|
+
# bank_params[:receiving_dfi_routing_num] = BankRoutingNumber.find(25).routing_number
|
11
|
+
@structure[:bank_params][:routing_num_immediate_yml] = "082000073"
|
12
|
+
@structure[:bank_params][:routing_num_originating_dfi_yml] = "082000073"
|
13
|
+
@structure[:bank_params][:tax_id_yml] = "1234567895"
|
14
|
+
@structure[:bank_params][:file_id_yml] = "1234567895"
|
15
|
+
@structure[:bank_params][:company_id_yml] = "1234567895"
|
16
|
+
@structure[:bank_params][:security_header] = "security_header"
|
17
|
+
@structure[:bank_params][:originator_status_code] = "1"
|
18
|
+
@iterator = Ach::Iterator.new
|
19
|
+
filename = "testfile.txt"
|
20
|
+
bank_account_nums = []
|
21
|
+
bank_account_nums << "10022001"
|
22
|
+
inputs = {}
|
23
|
+
inputs[:records] = @settlements
|
24
|
+
inputs[:bank_data] = bank_account_nums
|
25
|
+
file_creation_date = Date.today
|
26
|
+
file_creation_time = DateTime.now
|
27
|
+
@structure[:file_header_record] = {}
|
28
|
+
@structure[:file_header_record][:file_creation_date] = file_creation_date
|
29
|
+
@structure[:file_header_record][:file_creation_time] = file_creation_time
|
30
|
+
@structure[:file_header_record][:company_name] = "Billfloat"
|
31
|
+
@structure[:file_header_record][:file_id_modifier] = "A"
|
32
|
+
|
33
|
+
batch = []
|
34
|
+
bhr = {}
|
35
|
+
bhr[:service_class_code] = '200'
|
36
|
+
bhr[:company_name] = "Billfloat"
|
37
|
+
bhr[:standard_entry_class_code] = "CCD"
|
38
|
+
bhr[:company_entry_description] = "SETTLED"
|
39
|
+
bhr[:effective_entry_date] = Date.today.to_s
|
40
|
+
batch << bhr
|
41
|
+
|
42
|
+
@structure[:batch_header_records] = batch
|
43
|
+
|
44
|
+
ed = {}
|
45
|
+
ed[:transaction_code] = "27"
|
46
|
+
ed[:individual_name] = "test"
|
47
|
+
ed[:individual_id] = "20"
|
48
|
+
ed[:amount] = "100.23"
|
49
|
+
ed[:receiving_dfi_routing_number] = "082000073"
|
50
|
+
ed[:receiving_dfi_account_number] = "654564654564"
|
51
|
+
ed[:loan_payment_id] = "32"
|
52
|
+
entry_detail = []
|
53
|
+
entry_detail << ed
|
54
|
+
|
55
|
+
@iterator.stubs(:get_entry_details).returns(entry_detail)
|
56
|
+
@observer = Ach::Observer.new
|
57
|
+
@observer.stubs(:file_header).returns(Hash.new)
|
58
|
+
@observer.stubs(:batch_header).returns(Hash.new)
|
59
|
+
@observer.stubs(:batch_control).returns(Hash.new)
|
60
|
+
@observer.stubs(:file_control).returns(Hash.new)
|
61
|
+
end
|
62
|
+
|
63
|
+
after(:all) do
|
64
|
+
test_files = Dir.glob("#{Dir.pwd}/*.txt")
|
65
|
+
unless test_files.empty?
|
66
|
+
test_files.each do |f|
|
67
|
+
if f.include?("_ach_")
|
68
|
+
File.delete(f)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should create ach file" do
|
75
|
+
filename = "_ach_#{rand(999)}.txt"
|
76
|
+
Ach::Creator.create_file(@structure,@iterator,filename)
|
77
|
+
File.exists?(filename).should == true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "test block count" do
|
81
|
+
fn = Ach::Creator.block_count(10)
|
82
|
+
fn.should_not be nil
|
83
|
+
fn.class.name.should == "Fixnum"
|
84
|
+
fn.should == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
it "test mod_operation" do
|
88
|
+
fn = Ach::Creator.mod_operation("082000073")
|
89
|
+
fn.should==3
|
90
|
+
fn = Ach::Creator.mod_operation("011000536")
|
91
|
+
fn.should==6
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should raise exception when no file is supplied" do
|
95
|
+
obs = Ach::Observer.new
|
96
|
+
expect {Ach::Parser.parse_file(nil,obs)}.should raise_error
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/spec/cach_conf
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
$$ADD ID=W5S87LF6 BID='NWFACH32708654'
|
2
|
+
101 09100001952708654971111181128A094101WELLS FARGO Billfloat
|
3
|
+
5200Billfloat 5270865497CCDPAYMENT 111117 1091000010000001
|
4
|
+
62708200007365498494654 00000113242 asim e 0091000010000001
|
5
|
+
820000000100082000070000000113240000000000005270865497 091000010000001
|
6
|
+
9000001000001000000010008200007000000011324000000000000 01
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rspec'
|
5
|
+
require 'ach'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.color_enabled = true
|
13
|
+
config.mock_with :mocha
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stagecoach
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Doug Reed
|
14
|
+
- Asim Abdul
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2012-01-11 00:00:00 Z
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
version: 2.3.0
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 23
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 0
|
49
|
+
- 0
|
50
|
+
version: 1.0.0
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: jeweler
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 7
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 6
|
65
|
+
- 4
|
66
|
+
version: 1.6.4
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rcov
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id004
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mocha
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - "="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 45
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
- 9
|
95
|
+
- 11
|
96
|
+
version: 0.9.11
|
97
|
+
type: :development
|
98
|
+
version_requirements: *id005
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: extensions
|
101
|
+
prerelease: false
|
102
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - "="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 7
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
- 6
|
111
|
+
- 0
|
112
|
+
version: 0.6.0
|
113
|
+
type: :development
|
114
|
+
version_requirements: *id006
|
115
|
+
description: WellsFargo ACH file generator
|
116
|
+
email: dougereed@gmail.com
|
117
|
+
executables: []
|
118
|
+
|
119
|
+
extensions: []
|
120
|
+
|
121
|
+
extra_rdoc_files:
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.rdoc
|
124
|
+
files:
|
125
|
+
- .DS_Store
|
126
|
+
- .document
|
127
|
+
- .project
|
128
|
+
- .rspec
|
129
|
+
- Gemfile
|
130
|
+
- Gemfile.lock
|
131
|
+
- LICENSE.txt
|
132
|
+
- README.rdoc
|
133
|
+
- Rakefile
|
134
|
+
- VERSION
|
135
|
+
- lib/.DS_Store
|
136
|
+
- lib/ach.rb
|
137
|
+
- lib/ach/creator.rb
|
138
|
+
- lib/ach/iterator.rb
|
139
|
+
- lib/ach/observer.rb
|
140
|
+
- lib/ach/parser.rb
|
141
|
+
- spec/ach_spec.rb
|
142
|
+
- spec/cach_conf
|
143
|
+
- spec/spec_helper.rb
|
144
|
+
homepage: http://github.com/dougereed/ach
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 3
|
158
|
+
segments:
|
159
|
+
- 0
|
160
|
+
version: "0"
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
hash: 3
|
167
|
+
segments:
|
168
|
+
- 0
|
169
|
+
version: "0"
|
170
|
+
requirements: []
|
171
|
+
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 1.8.15
|
174
|
+
signing_key:
|
175
|
+
specification_version: 3
|
176
|
+
summary: WellsFargo ACH file generator
|
177
|
+
test_files: []
|
178
|
+
|