ofx_for_ruby 0.1.4 → 0.1.6
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 +5 -5
- data/lib/ofx/1.0.2/parser.rb +20 -18
- data/lib/ofx/1.0.2/serializer.rb +15 -17
- data/lib/ofx/2.0.0/serializer.rb +25 -0
- data/lib/ofx/2.0.0/xml_parser.rb +78 -0
- data/lib/ofx/document.rb +7 -3
- data/lib/ofx/serializer.rb +26 -8
- data/lib/ofx/version.rb +1 -1
- data/ofx_for_ruby.gemspec +10 -4
- data/test/test_ofx_xml_parser.rb +43 -0
- data/test/test_serializer.rb +244 -0
- metadata +95 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e96380301ef72d29b924fba5825d9bad25e46ce40c200697dbd4a21bd284105b
|
|
4
|
+
data.tar.gz: f787102b4cea5960e2efe2467e31f082a7c82dccc1f19dfd3183bd938a47d95f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9a7ed0297f15bd693ebce58e792b5928daa5ef87155a20972e52daf24985a0a77553a8d2ea2619331fdecdac338a1f892c0b819e2a46b809425987566b26113a
|
|
7
|
+
data.tar.gz: 4588782f3013fede00ba5dd29759dd6b181ceac8dfa7d96da51cfa76958cfc35f2b051e0d5600c71ab3bec75bb6735e0d4a5eb4917ea65eef9daa70175e505c6
|
data/lib/ofx/1.0.2/parser.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#
|
|
2
2
|
# DO NOT MODIFY!!!!
|
|
3
|
-
# This file is automatically generated by Racc 1.
|
|
4
|
-
# from Racc
|
|
3
|
+
# This file is automatically generated by Racc 1.8.1
|
|
4
|
+
# from Racc grammar file "ofx_102.racc".
|
|
5
5
|
#
|
|
6
6
|
|
|
7
7
|
require 'racc/parser.rb'
|
|
@@ -62,16 +62,16 @@ end
|
|
|
62
62
|
##### State transition tables begin ###
|
|
63
63
|
|
|
64
64
|
racc_action_table = [
|
|
65
|
-
4,
|
|
66
|
-
17, 19, 20
|
|
65
|
+
4, 4, 4, 10, 12, 10, 12, 5, 7, 8,
|
|
66
|
+
16, 17, 19, 20 ]
|
|
67
67
|
|
|
68
68
|
racc_action_check = [
|
|
69
|
-
18,
|
|
70
|
-
10, 15, 17
|
|
69
|
+
6, 0, 18, 6, 6, 18, 18, 1, 4, 5,
|
|
70
|
+
7, 10, 15, 17 ]
|
|
71
71
|
|
|
72
72
|
racc_action_pointer = [
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
-1, 7, nil, nil, 5, 9, -2, 6, nil, nil,
|
|
74
|
+
8, nil, nil, nil, nil, 6, nil, 9, 0, nil,
|
|
75
75
|
nil, nil ]
|
|
76
76
|
|
|
77
77
|
racc_action_default = [
|
|
@@ -80,15 +80,15 @@ racc_action_default = [
|
|
|
80
80
|
-5, -11 ]
|
|
81
81
|
|
|
82
82
|
racc_goto_table = [
|
|
83
|
-
|
|
84
|
-
nil, nil,
|
|
83
|
+
6, 9, 1, 2, 3, nil, nil, nil, nil, nil,
|
|
84
|
+
nil, nil, 18, 21 ]
|
|
85
85
|
|
|
86
86
|
racc_goto_check = [
|
|
87
|
-
|
|
88
|
-
nil, nil,
|
|
87
|
+
4, 5, 1, 2, 3, nil, nil, nil, nil, nil,
|
|
88
|
+
nil, nil, 4, 5 ]
|
|
89
89
|
|
|
90
90
|
racc_goto_pointer = [
|
|
91
|
-
nil,
|
|
91
|
+
nil, 2, 3, 4, -3, -5, nil, nil, nil ]
|
|
92
92
|
|
|
93
93
|
racc_goto_default = [
|
|
94
94
|
nil, nil, nil, 15, nil, nil, 11, 13, 14 ]
|
|
@@ -140,6 +140,7 @@ Racc_arg = [
|
|
|
140
140
|
racc_shift_n,
|
|
141
141
|
racc_reduce_n,
|
|
142
142
|
racc_use_result_var ]
|
|
143
|
+
Ractor.make_shareable(Racc_arg) if defined?(Ractor)
|
|
143
144
|
|
|
144
145
|
Racc_token_to_s_table = [
|
|
145
146
|
"$end",
|
|
@@ -158,6 +159,7 @@ Racc_token_to_s_table = [
|
|
|
158
159
|
"content",
|
|
159
160
|
"aggregate",
|
|
160
161
|
"value" ]
|
|
162
|
+
Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
|
|
161
163
|
|
|
162
164
|
Racc_debug_parser = false
|
|
163
165
|
|
|
@@ -173,14 +175,14 @@ Racc_debug_parser = false
|
|
|
173
175
|
|
|
174
176
|
module_eval(<<'.,.,', 'ofx_102.racc', 25)
|
|
175
177
|
def _reduce_4(val, _values, result)
|
|
176
|
-
start_tag(val[1])
|
|
178
|
+
start_tag(val[1])
|
|
177
179
|
result
|
|
178
180
|
end
|
|
179
181
|
.,.,
|
|
180
182
|
|
|
181
183
|
module_eval(<<'.,.,', 'ofx_102.racc', 26)
|
|
182
184
|
def _reduce_5(val, _values, result)
|
|
183
|
-
end_tag(val[1])
|
|
185
|
+
end_tag(val[1])
|
|
184
186
|
result
|
|
185
187
|
end
|
|
186
188
|
.,.,
|
|
@@ -199,7 +201,7 @@ module_eval(<<'.,.,', 'ofx_102.racc', 26)
|
|
|
199
201
|
|
|
200
202
|
module_eval(<<'.,.,', 'ofx_102.racc', 36)
|
|
201
203
|
def _reduce_12(val, _values, result)
|
|
202
|
-
data_value(val[1])
|
|
204
|
+
data_value(val[1])
|
|
203
205
|
result
|
|
204
206
|
end
|
|
205
207
|
.,.,
|
|
@@ -209,7 +211,7 @@ def _reduce_none(val, _values, result)
|
|
|
209
211
|
end
|
|
210
212
|
|
|
211
213
|
end # class Parser
|
|
212
|
-
|
|
213
|
-
|
|
214
|
+
end # module OFX102
|
|
215
|
+
end # module OFX
|
|
214
216
|
|
|
215
217
|
|
data/lib/ofx/1.0.2/serializer.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
|
2
2
|
#
|
|
3
3
|
# This file is part of OFX for Ruby.
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# OFX for Ruby is free software; you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
|
7
7
|
# the Free Software Foundation; either version 3 of the License, or
|
|
8
8
|
# (at your option) any later version.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# OFX for Ruby is distributed in the hope that it will be useful,
|
|
11
11
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
12
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
13
|
# GNU General Public License for more details.
|
|
14
|
-
#
|
|
14
|
+
#
|
|
15
15
|
# You should have received a copy of the GNU General Public License
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
@@ -48,37 +48,35 @@ module OFX
|
|
|
48
48
|
body += message_set.to_ofx_102_s
|
|
49
49
|
end
|
|
50
50
|
body += "</OFX>\n"
|
|
51
|
-
|
|
52
|
-
# puts body
|
|
53
51
|
|
|
54
52
|
body
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
def from_http_response_body(body)
|
|
58
|
-
|
|
56
|
+
body = body.lstrip
|
|
57
|
+
|
|
58
|
+
end_of_header_index = body.index("<OFX>")
|
|
59
|
+
|
|
60
|
+
header_str = body[0...end_of_header_index].strip
|
|
61
|
+
body = body[end_of_header_index..-1]
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
header_pattern = /(\w+\:.*\r*\n)+\r*\n/
|
|
62
|
-
header_match = header_pattern.match(body)
|
|
63
|
-
if header_match.nil?
|
|
63
|
+
if header_str.nil? || header_str == ""
|
|
64
64
|
raise NotImplementedError, "OFX server returned unmatched ASCII"
|
|
65
|
-
return body
|
|
66
65
|
end
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
header = Header.from_ofx_102_s(header_str)
|
|
68
|
+
|
|
71
69
|
parser = OFX::OFX102::Parser.new
|
|
72
70
|
|
|
73
71
|
parser.scan_str body
|
|
74
|
-
|
|
72
|
+
|
|
75
73
|
if parser.documents.length > 1
|
|
76
74
|
raise NotImplementedError, "Multiple response documents"
|
|
77
75
|
end
|
|
78
|
-
|
|
76
|
+
|
|
79
77
|
# require 'pp'
|
|
80
78
|
# pp parser.ofx_hashes[0]
|
|
81
|
-
|
|
79
|
+
|
|
82
80
|
document = parser.documents[0]
|
|
83
81
|
document.header = header
|
|
84
82
|
document
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../1.0.2/serializer'
|
|
2
|
+
require File.dirname(__FILE__) + '/xml_parser'
|
|
3
|
+
|
|
4
|
+
module OFX
|
|
5
|
+
module OFX200
|
|
6
|
+
class Serializer
|
|
7
|
+
def self.xml_ofx?(body)
|
|
8
|
+
OFX::OFX200::XMLParser.xml_ofx?(body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def from_http_response_body(body)
|
|
12
|
+
body = body.to_s.lstrip
|
|
13
|
+
unless self.class.xml_ofx?(body)
|
|
14
|
+
raise NotImplementedError, 'OFX 2.x serializer only supports XML OFX documents'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
OFX::OFX200::XMLParser.new(body).to_document
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_http_post_body(document)
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'rexml/document'
|
|
2
|
+
|
|
3
|
+
module OFX
|
|
4
|
+
module OFX200
|
|
5
|
+
class XMLParser
|
|
6
|
+
def self.xml_ofx?(body)
|
|
7
|
+
body.to_s.lstrip =~ /\A(?:<\?xml\b[^?]*\?>\s*)?<\?OFX\b/i ? true : false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(body)
|
|
11
|
+
@body = body.to_s.lstrip
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def header
|
|
15
|
+
header = OFX::Header.new
|
|
16
|
+
processing_instruction_attributes.each do |key, value|
|
|
17
|
+
header[key] = value
|
|
18
|
+
end
|
|
19
|
+
header['DATA'] ||= 'OFXXML'
|
|
20
|
+
header
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_document
|
|
24
|
+
document = OFX::Document.from_ofx_hash(to_ofx_hash)
|
|
25
|
+
document.header = header
|
|
26
|
+
document
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_ofx_hash
|
|
30
|
+
{ document.root.name => element_to_hash_value(document.root) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def document
|
|
36
|
+
@document ||= REXML::Document.new(@body)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def processing_instruction_attributes
|
|
40
|
+
return {} unless ofx_processing_instruction
|
|
41
|
+
|
|
42
|
+
attributes = {}
|
|
43
|
+
ofx_processing_instruction.content.scan(/([A-Za-z0-9_.-]+)\s*=\s*("([^"]*)"|'([^']*)')/) do |match|
|
|
44
|
+
attributes[match[0]] = match[2] || match[3]
|
|
45
|
+
end
|
|
46
|
+
attributes
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def ofx_processing_instruction
|
|
50
|
+
document.children.find do |child|
|
|
51
|
+
child.is_a?(REXML::Instruction) && child.target.upcase == 'OFX'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def element_to_hash_value(element)
|
|
56
|
+
children = element.elements.to_a
|
|
57
|
+
return element.text.to_s.strip if children.empty?
|
|
58
|
+
|
|
59
|
+
hash = {}
|
|
60
|
+
children.each do |child|
|
|
61
|
+
append_child(hash, child.name, element_to_hash_value(child))
|
|
62
|
+
end
|
|
63
|
+
hash
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def append_child(hash, name, value)
|
|
67
|
+
previous = hash[name]
|
|
68
|
+
if previous.nil?
|
|
69
|
+
hash[name] = value
|
|
70
|
+
elsif previous.kind_of?(Array)
|
|
71
|
+
previous << value
|
|
72
|
+
else
|
|
73
|
+
hash[name] = [previous, value]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/ofx/document.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
|
2
2
|
#
|
|
3
3
|
# This file is part of OFX for Ruby.
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# OFX for Ruby is free software; you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
|
7
7
|
# the Free Software Foundation; either version 3 of the License, or
|
|
8
8
|
# (at your option) any later version.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# OFX for Ruby is distributed in the hope that it will be useful,
|
|
11
11
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
12
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
13
|
# GNU General Public License for more details.
|
|
14
|
-
#
|
|
14
|
+
#
|
|
15
15
|
# You should have received a copy of the GNU General Public License
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
@@ -26,5 +26,9 @@ module OFX
|
|
|
26
26
|
@message_sets = []
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
def self.from_ofx_hash(document_hash)
|
|
30
|
+
from_ofx_102_hash(document_hash)
|
|
31
|
+
end
|
|
32
|
+
|
|
29
33
|
end
|
|
30
34
|
end
|
data/lib/ofx/serializer.rb
CHANGED
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
|
2
2
|
#
|
|
3
3
|
# This file is part of OFX for Ruby.
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# OFX for Ruby is free software; you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
|
7
7
|
# the Free Software Foundation; either version 3 of the License, or
|
|
8
8
|
# (at your option) any later version.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# OFX for Ruby is distributed in the hope that it will be useful,
|
|
11
11
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
12
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
13
|
# GNU General Public License for more details.
|
|
14
|
-
#
|
|
14
|
+
#
|
|
15
15
|
# You should have received a copy of the GNU General Public License
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
require File.dirname(__FILE__) + '/1.0.2/serializer'
|
|
19
|
+
require File.dirname(__FILE__) + '/2.0.0/serializer'
|
|
19
20
|
|
|
20
21
|
module OFX
|
|
21
22
|
class Serializer
|
|
22
23
|
def self.get(version)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
version = OFX::Version.new(version)
|
|
25
|
+
|
|
26
|
+
if version == OFX::Version.new("1.0.2") || version == OFX::Version.new("1.0.3")
|
|
27
|
+
return OFX::OFX102::Serializer.new
|
|
28
|
+
elsif version.major == 2
|
|
29
|
+
return OFX::OFX200::Serializer.new
|
|
30
|
+
else
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.from_http_response_body(body)
|
|
36
|
+
body = body.to_s.lstrip
|
|
37
|
+
|
|
38
|
+
if OFX::OFX200::Serializer.xml_ofx?(body)
|
|
39
|
+
OFX::OFX200::Serializer.new.from_http_response_body(body)
|
|
40
|
+
else
|
|
41
|
+
OFX::OFX102::Serializer.new.from_http_response_body(body)
|
|
28
42
|
end
|
|
29
43
|
end
|
|
30
44
|
|
|
@@ -35,5 +49,9 @@ module OFX
|
|
|
35
49
|
def from_http_request_body(document)
|
|
36
50
|
raise NotImplementedError
|
|
37
51
|
end
|
|
52
|
+
|
|
53
|
+
def from_http_response_body(body)
|
|
54
|
+
self.class.from_http_response_body(body)
|
|
55
|
+
end
|
|
38
56
|
end
|
|
39
57
|
end
|
data/lib/ofx/version.rb
CHANGED
data/ofx_for_ruby.gemspec
CHANGED
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
|
6
6
|
s.name = "ofx_for_ruby"
|
|
7
7
|
s.version = OFX::VERSION.to_dotted_s
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
s.authors = ["Chris Guidry", "Patrick Bacon"]
|
|
11
11
|
s.description = "OFX for Ruby is a pure Ruby implementation of Open Financial Exchange specifications (1.0.2 through 2.1.1) for building both financial clients and servers, providing parsers/serializers for each version, and a uniform object model across all versions."
|
|
12
12
|
s.email = ["bacon@atomicobject.com"]
|
|
@@ -16,11 +16,17 @@ Gem::Specification.new do |s|
|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
17
17
|
s.require_paths = ["lib"]
|
|
18
18
|
s.homepage = "http://github.com/baconpat/ofx_for_ruby"
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
s.add_dependency "activesupport"
|
|
21
|
-
|
|
22
|
-
s.
|
|
21
|
+
s.add_dependency "bigdecimal"
|
|
22
|
+
s.add_dependency "logger"
|
|
23
|
+
s.add_dependency "rexml"
|
|
24
|
+
|
|
25
|
+
s.add_development_dependency "racc", "~> 1.8"
|
|
23
26
|
s.add_development_dependency "rexical", "1.0.5"
|
|
27
|
+
s.add_development_dependency "getoptlong"
|
|
28
|
+
s.add_development_dependency "ostruct"
|
|
24
29
|
s.add_development_dependency "pry"
|
|
25
30
|
s.add_development_dependency "rake"
|
|
31
|
+
s.add_development_dependency "minitest", "~> 5.27"
|
|
26
32
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
|
+
|
|
3
|
+
class OFXXMLParserTest < Minitest::Test
|
|
4
|
+
XML_OFX = '<?xml version="1.0" encoding="utf-8"?><?OFX OFXHEADER="200" VERSION="220" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?><OFX><SIGNONMSGSRSV1><SONRS><STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS><DTSERVER>20260627111438.091[-4:EDT]</DTSERVER><LANGUAGE>ENG</LANGUAGE><FI><ORG>Capital One Bank</ORG><FID>1001</FID></FI><INTU.BID>1236</INTU.BID></SONRS></SIGNONMSGSRSV1><BANKMSGSRSV1><STMTTRNRS><STMTRS><BANKTRANLIST><STMTTRN><FITID>1</FITID></STMTTRN><STMTTRN><FITID>2</FITID></STMTTRN></BANKTRANLIST></STMTRS></STMTTRNRS></BANKMSGSRSV1></OFX>'
|
|
5
|
+
|
|
6
|
+
def test_detects_xml_ofx_documents
|
|
7
|
+
assert OFX::OFX200::XMLParser.xml_ofx?(XML_OFX)
|
|
8
|
+
refute OFX::OFX200::XMLParser.xml_ofx?("OFXHEADER:100\nDATA:OFXSGML\n<OFX></OFX>")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_parses_processing_instruction_header
|
|
12
|
+
header = OFX::OFX200::XMLParser.new(XML_OFX).header
|
|
13
|
+
|
|
14
|
+
assert_equal OFX::Version.new('2.0.0'), header.header_version
|
|
15
|
+
assert_equal 'OFXXML', header.content_type
|
|
16
|
+
assert_equal OFX::Version.new('2.2.0'), header.document_version
|
|
17
|
+
assert_equal 'NONE', header.security
|
|
18
|
+
assert_equal 'NONE', header.previous_unique_identifier
|
|
19
|
+
assert_equal 'NONE', header.unique_identifier
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_converts_xml_tree_to_ofx_hash
|
|
23
|
+
ofx_hash = OFX::OFX200::XMLParser.new(XML_OFX).to_ofx_hash
|
|
24
|
+
|
|
25
|
+
sonrs = ofx_hash['OFX']['SIGNONMSGSRSV1']['SONRS']
|
|
26
|
+
assert_equal '0', sonrs['STATUS']['CODE']
|
|
27
|
+
assert_equal 'INFO', sonrs['STATUS']['SEVERITY']
|
|
28
|
+
assert_equal '20260627111438.091[-4:EDT]', sonrs['DTSERVER']
|
|
29
|
+
assert_equal 'Capital One Bank', sonrs['FI']['ORG']
|
|
30
|
+
assert_equal '1236', sonrs['INTU.BID']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_repeated_xml_tags_become_arrays
|
|
34
|
+
ofx_hash = OFX::OFX200::XMLParser.new(XML_OFX).to_ofx_hash
|
|
35
|
+
transactions = ofx_hash['OFX']['BANKMSGSRSV1']['STMTTRNRS']['STMTRS']['BANKTRANLIST']['STMTTRN']
|
|
36
|
+
|
|
37
|
+
assert_equal [{'FITID' => '1'}, {'FITID' => '2'}], transactions
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_top_level_serializer_get_returns_ofx200_serializer_for_ofx2_versions
|
|
41
|
+
assert_instance_of OFX::OFX200::Serializer, OFX::Serializer.get(OFX::Version.new('2.2.0'))
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
|
+
|
|
3
|
+
class OFXParserTest < Minitest::Test
|
|
4
|
+
def test_parse_with_no_newline_after_header
|
|
5
|
+
body = <<-EOS
|
|
6
|
+
|
|
7
|
+
OFXHEADER:100
|
|
8
|
+
DATA:OFXSGML
|
|
9
|
+
VERSION:102
|
|
10
|
+
SECURITY:NONE
|
|
11
|
+
ENCODING:USASCII
|
|
12
|
+
CHARSET:1252
|
|
13
|
+
COMPRESSION:NONE
|
|
14
|
+
OLDFILEUID:NONE
|
|
15
|
+
NEWFILEUID:NONE
|
|
16
|
+
<OFX>
|
|
17
|
+
<SIGNONMSGSRSV1>
|
|
18
|
+
<SONRS>
|
|
19
|
+
<STATUS>
|
|
20
|
+
<CODE>0
|
|
21
|
+
<SEVERITY>INFO
|
|
22
|
+
</STATUS>
|
|
23
|
+
<DTSERVER>20221013120000[0:GMT]
|
|
24
|
+
<LANGUAGE>ENG
|
|
25
|
+
<FI>
|
|
26
|
+
<ORG>B1
|
|
27
|
+
<FID>10898
|
|
28
|
+
</FI>
|
|
29
|
+
<INTU.BID>10898
|
|
30
|
+
</SONRS>
|
|
31
|
+
</SIGNONMSGSRSV1>
|
|
32
|
+
<BANKMSGSRSV1>
|
|
33
|
+
<STMTTRNRS>
|
|
34
|
+
<TRNUID>1
|
|
35
|
+
<STATUS>
|
|
36
|
+
<CODE>0
|
|
37
|
+
<SEVERITY>INFO
|
|
38
|
+
<MESSAGE>Success
|
|
39
|
+
</STATUS>
|
|
40
|
+
<STMTRS>
|
|
41
|
+
<CURDEF>USD
|
|
42
|
+
<BANKACCTFROM>
|
|
43
|
+
<BANKID>0713456513
|
|
44
|
+
<ACCTID>123456788
|
|
45
|
+
<ACCTTYPE>CHECKING
|
|
46
|
+
</BANKACCTFROM>
|
|
47
|
+
<BANKTRANLIST>
|
|
48
|
+
<DTSTART>20221003120000[0:GMT]
|
|
49
|
+
<DTEND>20221012120000[0:GMT]
|
|
50
|
+
<STMTTRN>
|
|
51
|
+
<TRNTYPE>DEBIT
|
|
52
|
+
<DTPOSTED>20221012120000[0:GMT]
|
|
53
|
+
<TRNAMT>-100.01
|
|
54
|
+
<FITID>202210120
|
|
55
|
+
<NAME>CAPITAL ONE N.A. CAPITALONE 0000
|
|
56
|
+
<MEMO>0234345d WEB ID: 15234563
|
|
57
|
+
</STMTTRN>
|
|
58
|
+
</BANKTRANLIST>
|
|
59
|
+
<LEDGERBAL>
|
|
60
|
+
<BALAMT>29.03
|
|
61
|
+
<DTASOF>20221013120000[0:GMT]
|
|
62
|
+
</LEDGERBAL>
|
|
63
|
+
<AVAILBAL>
|
|
64
|
+
<BALAMT>30.06
|
|
65
|
+
<DTASOF>20221013120000[0:GMT]
|
|
66
|
+
</AVAILBAL>
|
|
67
|
+
</STMTRS>
|
|
68
|
+
</STMTTRNRS>
|
|
69
|
+
</BANKMSGSRSV1>
|
|
70
|
+
</OFX>
|
|
71
|
+
EOS
|
|
72
|
+
|
|
73
|
+
document = OFX::Serializer.from_http_response_body(body)
|
|
74
|
+
|
|
75
|
+
signon_message_set = document.message_sets[0]
|
|
76
|
+
signon_response = signon_message_set.responses[0]
|
|
77
|
+
|
|
78
|
+
banking_statement_message_set = document.message_sets[1]
|
|
79
|
+
banking_statement_response = banking_statement_message_set.responses[0]
|
|
80
|
+
|
|
81
|
+
assert_equal '123456788', banking_statement_response.account.account_identifier
|
|
82
|
+
assert_equal '0713456513', banking_statement_response.account.bank_identifier
|
|
83
|
+
assert_equal '30.06', banking_statement_response.available_balance.amount
|
|
84
|
+
assert_equal '29.03', banking_statement_response.ledger_balance.amount
|
|
85
|
+
|
|
86
|
+
transactions = banking_statement_response.transactions
|
|
87
|
+
assert_equal 1, transactions.size
|
|
88
|
+
|
|
89
|
+
transaction = transactions.first
|
|
90
|
+
assert_equal '-100.01', transaction.amount.to_f.to_s
|
|
91
|
+
assert_equal 'CAPITAL ONE N.A. CAPITALONE 0000', transaction.payee
|
|
92
|
+
assert_equal :debit, transaction.transaction_type
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_with_newline_after_header
|
|
96
|
+
body =
|
|
97
|
+
"OFXHEADER:100
|
|
98
|
+
DATA:OFXSGML
|
|
99
|
+
VERSION:102
|
|
100
|
+
SECURITY:NONE
|
|
101
|
+
ENCODING:USASCII
|
|
102
|
+
CHARSET:1252
|
|
103
|
+
COMPRESSION:NONE
|
|
104
|
+
OLDFILEUID:NONE
|
|
105
|
+
NEWFILEUID:NONE
|
|
106
|
+
|
|
107
|
+
<OFX>
|
|
108
|
+
<SIGNONMSGSRSV1>
|
|
109
|
+
<SONRS>
|
|
110
|
+
<STATUS>
|
|
111
|
+
<CODE>0
|
|
112
|
+
<SEVERITY>INFO
|
|
113
|
+
</STATUS>
|
|
114
|
+
<DTSERVER>20221013120000[0:GMT]
|
|
115
|
+
<LANGUAGE>ENG
|
|
116
|
+
<FI>
|
|
117
|
+
<ORG>B1
|
|
118
|
+
<FID>10898
|
|
119
|
+
</FI>
|
|
120
|
+
<INTU.BID>10898
|
|
121
|
+
</SONRS>
|
|
122
|
+
</SIGNONMSGSRSV1>
|
|
123
|
+
<BANKMSGSRSV1>
|
|
124
|
+
<STMTTRNRS>
|
|
125
|
+
<TRNUID>1
|
|
126
|
+
<STATUS>
|
|
127
|
+
<CODE>0
|
|
128
|
+
<SEVERITY>INFO
|
|
129
|
+
<MESSAGE>Success
|
|
130
|
+
</STATUS>
|
|
131
|
+
<STMTRS>
|
|
132
|
+
<CURDEF>USD
|
|
133
|
+
<BANKACCTFROM>
|
|
134
|
+
<BANKID>0713456513
|
|
135
|
+
<ACCTID>123456788
|
|
136
|
+
<ACCTTYPE>CHECKING
|
|
137
|
+
</BANKACCTFROM>
|
|
138
|
+
<BANKTRANLIST>
|
|
139
|
+
<DTSTART>20221003120000[0:GMT]
|
|
140
|
+
<DTEND>20221012120000[0:GMT]
|
|
141
|
+
<STMTTRN>
|
|
142
|
+
<TRNTYPE>DEBIT
|
|
143
|
+
<DTPOSTED>20221012120000[0:GMT]
|
|
144
|
+
<TRNAMT>-100.01
|
|
145
|
+
<FITID>202210120
|
|
146
|
+
<NAME>CAPITAL ONE N.A. CAPITALONE 0000
|
|
147
|
+
<MEMO>0234345d WEB ID: 15234563
|
|
148
|
+
</STMTTRN>
|
|
149
|
+
</BANKTRANLIST>
|
|
150
|
+
<LEDGERBAL>
|
|
151
|
+
<BALAMT>29.03
|
|
152
|
+
<DTASOF>20221013120000[0:GMT]
|
|
153
|
+
</LEDGERBAL>
|
|
154
|
+
<AVAILBAL>
|
|
155
|
+
<BALAMT>30.06
|
|
156
|
+
<DTASOF>20221013120000[0:GMT]
|
|
157
|
+
</AVAILBAL>
|
|
158
|
+
</STMTRS>
|
|
159
|
+
</STMTTRNRS>
|
|
160
|
+
</BANKMSGSRSV1>
|
|
161
|
+
</OFX>"
|
|
162
|
+
|
|
163
|
+
serializer = OFX::OFX102::Serializer.new
|
|
164
|
+
document = serializer.from_http_response_body(body)
|
|
165
|
+
|
|
166
|
+
# require 'pp'
|
|
167
|
+
# pp document
|
|
168
|
+
|
|
169
|
+
signon_message_set = document.message_sets[0]
|
|
170
|
+
signon_response = signon_message_set.responses[0]
|
|
171
|
+
|
|
172
|
+
signon_message_set = document.message_sets[0]
|
|
173
|
+
signon_response = signon_message_set.responses[0]
|
|
174
|
+
|
|
175
|
+
banking_statement_message_set = document.message_sets[1]
|
|
176
|
+
banking_statement_response = banking_statement_message_set.responses[0]
|
|
177
|
+
|
|
178
|
+
assert_equal '123456788', banking_statement_response.account.account_identifier
|
|
179
|
+
assert_equal '0713456513', banking_statement_response.account.bank_identifier
|
|
180
|
+
assert_equal '30.06', banking_statement_response.available_balance.amount
|
|
181
|
+
assert_equal '29.03', banking_statement_response.ledger_balance.amount
|
|
182
|
+
|
|
183
|
+
transactions = banking_statement_response.transactions
|
|
184
|
+
assert_equal 1, transactions.size
|
|
185
|
+
|
|
186
|
+
transaction = transactions.first
|
|
187
|
+
assert_equal '-100.01', transaction.amount.to_f.to_s
|
|
188
|
+
assert_equal 'CAPITAL ONE N.A. CAPITALONE 0000', transaction.payee
|
|
189
|
+
assert_equal :debit, transaction.transaction_type
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def test_capitalone_ofx
|
|
193
|
+
body = <<-EOS
|
|
194
|
+
<?xml version="1.0" encoding="utf-8"?><?OFX OFXHEADER="200" VERSION="220" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?><OFX><SIGNONMSGSRSV1><SONRS><STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS><DTSERVER>20260627111438.091[-4:EDT]</DTSERVER><LANGUAGE>ENG</LANGUAGE><FI><ORG>Capital One Bank</ORG><FID>1001</FID></FI><INTU.BID>1236</INTU.BID></SONRS></SIGNONMSGSRSV1><BANKMSGSRSV1><STMTTRNRS><TRNUID>0</TRNUID><STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS><STMTRS><CURDEF>USD</CURDEF><BANKACCTFROM><BANKID>0123456789</BANKID><ACCTID>1234</ACCTID><ACCTTYPE>SAVINGS</ACCTTYPE></BANKACCTFROM><BANKTRANLIST><DTSTART>20260528000000.000[-4:EDT]</DTSTART><DTEND>20260627000000.000[-4:EDT]</DTEND><STMTTRN><TRNTYPE>CREDIT</TRNTYPE><DTPOSTED>20260626000000.000[-4:EDT]</DTPOSTED><TRNAMT>115</TRNAMT><FITID>20260626405</FITID><MEMO>Deposit from SOME PAYROLL</MEMO></STMTTRN></BANKTRANLIST><LEDGERBAL><BALAMT>200.31</BALAMT><DTASOF>20260627111438.091[-4:EDT]</DTASOF></LEDGERBAL></STMTRS></STMTTRNRS></BANKMSGSRSV1></OFX>
|
|
195
|
+
EOS
|
|
196
|
+
|
|
197
|
+
document = OFX::Serializer.from_http_response_body(body)
|
|
198
|
+
|
|
199
|
+
assert_equal OFX::Version.new('2.0.0'), document.header.header_version
|
|
200
|
+
assert_equal 'OFXXML', document.header.content_type
|
|
201
|
+
assert_equal OFX::Version.new('2.2.0'), document.header.document_version
|
|
202
|
+
assert_equal 'NONE', document.header.security
|
|
203
|
+
assert_equal 'NONE', document.header.previous_unique_identifier
|
|
204
|
+
assert_equal 'NONE', document.header.unique_identifier
|
|
205
|
+
|
|
206
|
+
signon_message_set = document.message_sets[0]
|
|
207
|
+
signon_response = signon_message_set.responses[0]
|
|
208
|
+
|
|
209
|
+
assert_equal 0, signon_response.status.code
|
|
210
|
+
assert_equal :information, signon_response.status.severity
|
|
211
|
+
assert_equal '20260627111438', signon_response.date.strftime('%Y%m%d%H%M%S')
|
|
212
|
+
assert_equal 'ENG', signon_response.language
|
|
213
|
+
assert_equal 'Capital One Bank', signon_response.financial_institution_identification.organization
|
|
214
|
+
assert_equal '1001', signon_response.financial_institution_identification.financial_institution_identifier
|
|
215
|
+
|
|
216
|
+
banking_statement_message_set = document.message_sets[1]
|
|
217
|
+
banking_statement_response = banking_statement_message_set.responses[0]
|
|
218
|
+
|
|
219
|
+
assert_equal '0', banking_statement_response.transaction_identifier
|
|
220
|
+
assert_equal 0, banking_statement_response.status.code
|
|
221
|
+
assert_equal :information, banking_statement_response.status.severity
|
|
222
|
+
assert_equal 'USD', banking_statement_response.default_currency
|
|
223
|
+
assert_equal '1234', banking_statement_response.account.account_identifier
|
|
224
|
+
assert_equal '0123456789', banking_statement_response.account.bank_identifier
|
|
225
|
+
assert_equal :savings, banking_statement_response.account.account_type
|
|
226
|
+
assert_nil banking_statement_response.available_balance
|
|
227
|
+
assert_equal '200.31', banking_statement_response.ledger_balance.amount
|
|
228
|
+
assert_equal '20260627111438', banking_statement_response.ledger_balance.as_of.strftime('%Y%m%d%H%M%S')
|
|
229
|
+
assert_equal '20260528000000', banking_statement_response.transaction_range.begin.strftime('%Y%m%d%H%M%S')
|
|
230
|
+
assert_equal '20260627000000', banking_statement_response.transaction_range.end.strftime('%Y%m%d%H%M%S')
|
|
231
|
+
|
|
232
|
+
transactions = banking_statement_response.transactions
|
|
233
|
+
assert_equal 1, transactions.size
|
|
234
|
+
|
|
235
|
+
transaction = transactions.first
|
|
236
|
+
assert_equal '115'.to_d, transaction.amount
|
|
237
|
+
assert_equal 'USD', transaction.currency
|
|
238
|
+
assert_equal '20260626000000', transaction.date_posted.strftime('%Y%m%d%H%M%S')
|
|
239
|
+
assert_equal '20260626405', transaction.financial_institution_transaction_identifier
|
|
240
|
+
assert_nil transaction.payee
|
|
241
|
+
assert_equal 'Deposit from SOME PAYROLL', transaction.memo
|
|
242
|
+
assert_equal :credit, transaction.transaction_type
|
|
243
|
+
end
|
|
244
|
+
end
|
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ofx_for_ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Guidry
|
|
8
8
|
- Patrick Bacon
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: activesupport
|
|
@@ -25,20 +24,62 @@ dependencies:
|
|
|
25
24
|
- - ">="
|
|
26
25
|
- !ruby/object:Gem::Version
|
|
27
26
|
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bigdecimal
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: logger
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rexml
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
28
69
|
- !ruby/object:Gem::Dependency
|
|
29
70
|
name: racc
|
|
30
71
|
requirement: !ruby/object:Gem::Requirement
|
|
31
72
|
requirements:
|
|
32
|
-
- -
|
|
73
|
+
- - "~>"
|
|
33
74
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 1.
|
|
75
|
+
version: '1.8'
|
|
35
76
|
type: :development
|
|
36
77
|
prerelease: false
|
|
37
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
79
|
requirements:
|
|
39
|
-
- -
|
|
80
|
+
- - "~>"
|
|
40
81
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: 1.
|
|
82
|
+
version: '1.8'
|
|
42
83
|
- !ruby/object:Gem::Dependency
|
|
43
84
|
name: rexical
|
|
44
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -53,6 +94,34 @@ dependencies:
|
|
|
53
94
|
- - '='
|
|
54
95
|
- !ruby/object:Gem::Version
|
|
55
96
|
version: 1.0.5
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: getoptlong
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: ostruct
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
56
125
|
- !ruby/object:Gem::Dependency
|
|
57
126
|
name: pry
|
|
58
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -81,6 +150,20 @@ dependencies:
|
|
|
81
150
|
- - ">="
|
|
82
151
|
- !ruby/object:Gem::Version
|
|
83
152
|
version: '0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: minitest
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - "~>"
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '5.27'
|
|
160
|
+
type: :development
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - "~>"
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '5.27'
|
|
84
167
|
description: OFX for Ruby is a pure Ruby implementation of Open Financial Exchange
|
|
85
168
|
specifications (1.0.2 through 2.1.1) for building both financial clients and servers,
|
|
86
169
|
providing parsers/serializers for each version, and a uniform object model across
|
|
@@ -124,6 +207,8 @@ files:
|
|
|
124
207
|
- lib/ofx/1.0.2/statements.rb
|
|
125
208
|
- lib/ofx/1.0.2/status.rb
|
|
126
209
|
- lib/ofx/1.0.2/wire_funds_transfer_message_set.rb
|
|
210
|
+
- lib/ofx/2.0.0/serializer.rb
|
|
211
|
+
- lib/ofx/2.0.0/xml_parser.rb
|
|
127
212
|
- lib/ofx/banking_message_set.rb
|
|
128
213
|
- lib/ofx/credit_card_statement_message_set.rb
|
|
129
214
|
- lib/ofx/document.rb
|
|
@@ -167,11 +252,12 @@ files:
|
|
|
167
252
|
- test/citi/test_signup_account_information.rb
|
|
168
253
|
- test/test_helper.rb
|
|
169
254
|
- test/test_ofx_version.rb
|
|
255
|
+
- test/test_ofx_xml_parser.rb
|
|
170
256
|
- test/test_parser.rb
|
|
257
|
+
- test/test_serializer.rb
|
|
171
258
|
homepage: http://github.com/baconpat/ofx_for_ruby
|
|
172
259
|
licenses: []
|
|
173
260
|
metadata: {}
|
|
174
|
-
post_install_message:
|
|
175
261
|
rdoc_options: []
|
|
176
262
|
require_paths:
|
|
177
263
|
- lib
|
|
@@ -186,9 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
186
272
|
- !ruby/object:Gem::Version
|
|
187
273
|
version: '0'
|
|
188
274
|
requirements: []
|
|
189
|
-
|
|
190
|
-
rubygems_version: 2.6.12
|
|
191
|
-
signing_key:
|
|
275
|
+
rubygems_version: 3.6.9
|
|
192
276
|
specification_version: 4
|
|
193
277
|
summary: Pure Ruby implementation of Open Financial Exchange specifications
|
|
194
278
|
test_files: []
|