ofx 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +48 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/lib/ofx.rb +20 -0
- data/lib/ofx/account.rb +10 -0
- data/lib/ofx/balance.rb +7 -0
- data/lib/ofx/foundation.rb +9 -0
- data/lib/ofx/parser.rb +42 -0
- data/lib/ofx/parser/ofx102.rb +84 -0
- data/lib/ofx/transaction.rb +13 -0
- data/lib/ofx/version.rb +8 -0
- data/spec/fixtures/sample.ofx +308 -0
- data/spec/ofx/account_spec.rb +44 -0
- data/spec/ofx/ofx102_spec.rb +24 -0
- data/spec/ofx/ofx_parser_spec.rb +61 -0
- data/spec/ofx/ofx_spec.rb +11 -0
- data/spec/ofx/transaction_spec.rb +103 -0
- data/spec/spec_helper.rb +14 -0
- metadata +79 -0
data/README.markdown
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
OFX
|
2
|
+
===
|
3
|
+
|
4
|
+
A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports OFX 1.0.2.
|
5
|
+
|
6
|
+
Works on both Ruby 1.8 and 1.9.
|
7
|
+
|
8
|
+
USAGE
|
9
|
+
-----
|
10
|
+
|
11
|
+
require "ofx"
|
12
|
+
|
13
|
+
OFX("file.ofx") do |ofx|
|
14
|
+
p ofx.account
|
15
|
+
p ofx.account.balance
|
16
|
+
p ofx.transactions
|
17
|
+
end
|
18
|
+
|
19
|
+
MAINTAINER
|
20
|
+
----------
|
21
|
+
|
22
|
+
* Nando Vieira (<http://simplesideias.com.br/>)
|
23
|
+
|
24
|
+
LICENSE:
|
25
|
+
--------
|
26
|
+
|
27
|
+
(The MIT License)
|
28
|
+
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
30
|
+
a copy of this software and associated documentation files (the
|
31
|
+
'Software'), to deal in the Software without restriction, including
|
32
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
33
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
34
|
+
permit persons to whom the Software is furnished to do so, subject to
|
35
|
+
the following conditions:
|
36
|
+
|
37
|
+
The above copyright notice and this permission notice shall be
|
38
|
+
included in all copies or substantial portions of the Software.
|
39
|
+
|
40
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
41
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
42
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
43
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
44
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
45
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
46
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
47
|
+
|
48
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "jeweler"
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
require File.dirname(__FILE__) + "/lib/ofx/version"
|
5
|
+
|
6
|
+
JEWEL = Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ofx"
|
8
|
+
gem.version = OFX::Version::STRING
|
9
|
+
gem.summary = "A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports OFX 1.0.2."
|
10
|
+
gem.description = <<-TXT
|
11
|
+
A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports OFX 1.0.2.
|
12
|
+
TXT
|
13
|
+
|
14
|
+
gem.authors = ["Nando Vieira"]
|
15
|
+
gem.email = "fnando.vieira@gmail.com"
|
16
|
+
gem.homepage = "http://github.com/fnando/ofx"
|
17
|
+
|
18
|
+
gem.has_rdoc = false
|
19
|
+
gem.files = %w(Rakefile ofx.gemspec VERSION README.markdown) + Dir["{bin,lib,spec}/**/*"]
|
20
|
+
|
21
|
+
gem.add_dependency "nokogiri"
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Build and install the gem"
|
25
|
+
desc "Generate gemspec and build gem"
|
26
|
+
task :build_gem do
|
27
|
+
File.open("VERSION", "w+") {|f| f << OFX::Version::STRING }
|
28
|
+
|
29
|
+
Rake::Task["gemspec"].invoke
|
30
|
+
Rake::Task["build"].invoke
|
31
|
+
end
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ["-c", "-f s"] }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/ofx.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "nokogiri"
|
5
|
+
rescue LoadError => e
|
6
|
+
require "rubygems"
|
7
|
+
require "nokogiri"
|
8
|
+
end
|
9
|
+
|
10
|
+
require "ofx/parser"
|
11
|
+
require "ofx/parser/ofx102"
|
12
|
+
require "ofx/foundation"
|
13
|
+
require "ofx/balance"
|
14
|
+
require "ofx/account"
|
15
|
+
require "ofx/transaction"
|
16
|
+
require "ofx/version"
|
17
|
+
|
18
|
+
def OFX(path, &block)
|
19
|
+
yield OFX::Parser::Base.new(path).parser
|
20
|
+
end
|
data/lib/ofx/account.rb
ADDED
data/lib/ofx/balance.rb
ADDED
data/lib/ofx/parser.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module OFX
|
2
|
+
module Parser
|
3
|
+
class Base
|
4
|
+
attr_reader :headers
|
5
|
+
attr_reader :body
|
6
|
+
attr_reader :content
|
7
|
+
attr_reader :parser
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@content = open(path).read
|
11
|
+
@headers, @body = prepare(content)
|
12
|
+
|
13
|
+
@parser = case @headers["VERSION"]
|
14
|
+
when "102"; OFX::Parser::OFX102.new(:headers => headers, :body => body)
|
15
|
+
else
|
16
|
+
raise OFX::Parser::InvalidVersion
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def prepare(content)
|
22
|
+
# Split headers & body
|
23
|
+
headers, body = content.dup.split(/\n{2,}|:?<OFX>/, 2)
|
24
|
+
|
25
|
+
# Parse headers. When value is NONE, convert it to nil.
|
26
|
+
headers = headers.to_enum(:each_line).inject({}) do |memo, line|
|
27
|
+
_, key, value = *line.match(/^(.*?):(.*?)(\r?\n)*$/)
|
28
|
+
memo[key] = value == "NONE" ? nil : value
|
29
|
+
memo
|
30
|
+
end
|
31
|
+
|
32
|
+
# Replace body tags to parse it with Nokogiri
|
33
|
+
body.gsub!(/>\s+</m, '><')
|
34
|
+
body.gsub!(/\s+</m, '<')
|
35
|
+
body.gsub!(/>\s+/m, '>')
|
36
|
+
body.gsub!(/<(\w+?)>([^<]+)/m, '<\1>\2</\1>')
|
37
|
+
|
38
|
+
[headers, body]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module OFX
|
2
|
+
module Parser
|
3
|
+
class OFX102
|
4
|
+
VERSION = "1.0.2"
|
5
|
+
|
6
|
+
ACCOUNT_TYPES = {
|
7
|
+
"CHECKING" => :checking
|
8
|
+
}
|
9
|
+
|
10
|
+
TRANSACTION_TYPES = {
|
11
|
+
"CREDIT" => :credit,
|
12
|
+
"DEBIT" => :debit,
|
13
|
+
"OTHER" => :other
|
14
|
+
}
|
15
|
+
|
16
|
+
attr_reader :headers
|
17
|
+
attr_reader :body
|
18
|
+
attr_reader :html
|
19
|
+
|
20
|
+
def initialize(options = {})
|
21
|
+
@headers = options[:headers]
|
22
|
+
@body = options[:body]
|
23
|
+
@html = Nokogiri::HTML.parse(body)
|
24
|
+
end
|
25
|
+
|
26
|
+
def account
|
27
|
+
@account ||= build_account
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def build_account
|
32
|
+
OFX::Account.new({
|
33
|
+
:bank_id => html.search("bankacctfrom > bankid").inner_text,
|
34
|
+
:id => html.search("bankacctfrom > acctid").inner_text,
|
35
|
+
:type => ACCOUNT_TYPES[html.search("bankacctfrom > accttype").inner_text],
|
36
|
+
:transactions => build_transactions,
|
37
|
+
:balance => build_balance,
|
38
|
+
:currency => html.search("bankmsgsrsv1 > stmttrnrs > stmtrs > curdef").inner_text
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_transactions
|
43
|
+
html.search("banktranlist > stmttrn").collect do |element|
|
44
|
+
build_transaction(element)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_transaction(element)
|
49
|
+
amount = element.search("trnamt").inner_text.to_f
|
50
|
+
|
51
|
+
OFX::Transaction.new({
|
52
|
+
:amount => amount,
|
53
|
+
:amount_in_pennies => (amount * 100).to_i,
|
54
|
+
:fit_id => element.search("fitid").inner_text,
|
55
|
+
:memo => element.search("memo").inner_text,
|
56
|
+
:payee => element.search("payee").inner_text,
|
57
|
+
:check_number => element.search("checknum").inner_text,
|
58
|
+
:ref_number => element.search("refnum").inner_text,
|
59
|
+
:posted_at => build_date(element.search("dtposted").inner_text),
|
60
|
+
:type => TRANSACTION_TYPES[element.search("trntype").inner_text]
|
61
|
+
})
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_date(date)
|
65
|
+
_, year, month, day, hour, minutes, seconds = *date.match(/(\d{4})(\d{2})(\d{2})(?:(\d{2})(\d{2})(\d{2}))?/)
|
66
|
+
|
67
|
+
date = "#{year}-#{month}-#{day} "
|
68
|
+
date << "#{hour}:#{minutes}:#{seconds}" if hour && minutes && seconds
|
69
|
+
|
70
|
+
Time.parse(date)
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_balance
|
74
|
+
amount = html.search("ledgerbal > balamt").inner_text.to_f
|
75
|
+
|
76
|
+
OFX::Balance.new({
|
77
|
+
:amount => amount,
|
78
|
+
:amount_in_pennies => (amount * 100).to_i,
|
79
|
+
:posted_at => build_date(html.search("ledgerbal > dtasof").inner_text)
|
80
|
+
})
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module OFX
|
2
|
+
class Transaction < Foundation
|
3
|
+
attr_accessor :amount
|
4
|
+
attr_accessor :amount_in_pennies
|
5
|
+
attr_accessor :check_number
|
6
|
+
attr_accessor :fit_id
|
7
|
+
attr_accessor :memo
|
8
|
+
attr_accessor :payee
|
9
|
+
attr_accessor :posted_at
|
10
|
+
attr_accessor :ref_number
|
11
|
+
attr_accessor :type
|
12
|
+
end
|
13
|
+
end
|
data/lib/ofx/version.rb
ADDED
@@ -0,0 +1,308 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
OFXHEADER:100
|
4
|
+
DATA:OFXSGML
|
5
|
+
VERSION:102
|
6
|
+
SECURITY:NONE
|
7
|
+
ENCODING:USASCII
|
8
|
+
CHARSET:1252
|
9
|
+
COMPRESSION:NONE
|
10
|
+
OLDFILEUID:NONE
|
11
|
+
NEWFILEUID:NONE
|
12
|
+
|
13
|
+
<OFX>
|
14
|
+
<SIGNONMSGSRSV1>
|
15
|
+
<SONRS>
|
16
|
+
<STATUS>
|
17
|
+
<CODE>0
|
18
|
+
<SEVERITY>INFO
|
19
|
+
</STATUS>
|
20
|
+
<DTSERVER>20091101192253
|
21
|
+
<LANGUAGE>POR
|
22
|
+
</SONRS>
|
23
|
+
</SIGNONMSGSRSV1>
|
24
|
+
<BANKMSGSRSV1>
|
25
|
+
<STMTTRNRS>
|
26
|
+
<TRNUID>1
|
27
|
+
<STATUS>
|
28
|
+
<CODE>0
|
29
|
+
<SEVERITY>INFO
|
30
|
+
</STATUS>
|
31
|
+
<STMTRS>
|
32
|
+
<CURDEF>BRL
|
33
|
+
<BANKACCTFROM>
|
34
|
+
<BANKID>0356
|
35
|
+
<ACCTID>03227113109
|
36
|
+
<ACCTTYPE>CHECKING
|
37
|
+
</BANKACCTFROM>
|
38
|
+
<BANKTRANLIST>
|
39
|
+
<DTSTART>20091009080000
|
40
|
+
<DTEND>20091103080000
|
41
|
+
<STMTTRN>
|
42
|
+
<TRNTYPE>DEBIT
|
43
|
+
<DTPOSTED>20091009080000
|
44
|
+
<TRNAMT>-35.34
|
45
|
+
<FITID>200910091
|
46
|
+
<CHECKNUM>0001223
|
47
|
+
<MEMO>COMPRA VISA ELECTRON
|
48
|
+
</STMTTRN><STMTTRN>
|
49
|
+
<TRNTYPE>CREDIT
|
50
|
+
<DTPOSTED>20091016080000
|
51
|
+
<TRNAMT>60.39
|
52
|
+
<FITID>200910162
|
53
|
+
<CHECKNUM>0880136
|
54
|
+
<MEMO>DEPOSITO POUP.CORRENTE
|
55
|
+
</STMTTRN>
|
56
|
+
|
57
|
+
<STMTTRN>
|
58
|
+
<TRNTYPE>OTHER</TRNTYPE>
|
59
|
+
<DTPOSTED>20091019120000[-3:BRT]</DTPOSTED>
|
60
|
+
<TRNAMT>-148.40</TRNAMT>
|
61
|
+
<FITID>200910191148400</FITID>
|
62
|
+
<CHECKNUM>000000101901</CHECKNUM>
|
63
|
+
<REFNUM>101.901</REFNUM>
|
64
|
+
<PAYEE>Pagto conta telefone</PAYEE>
|
65
|
+
<MEMO>Pagto conta telefone</MEMO>
|
66
|
+
</STMTTRN>
|
67
|
+
|
68
|
+
<STMTTRN>
|
69
|
+
<TRNTYPE>DEBIT
|
70
|
+
<DTPOSTED>20091013080000
|
71
|
+
<TRNAMT>-126.13
|
72
|
+
<FITID>200910131
|
73
|
+
<CHECKNUM>0001511
|
74
|
+
<MEMO>TITULO COBRANCA-IB
|
75
|
+
</STMTTRN><STMTTRN>
|
76
|
+
<TRNTYPE>DEBIT
|
77
|
+
<DTPOSTED>20091013080000
|
78
|
+
<TRNAMT>-232.23
|
79
|
+
<FITID>200910132
|
80
|
+
<CHECKNUM>0001511
|
81
|
+
<MEMO>TITULO COBRANCA-IB
|
82
|
+
</STMTTRN><STMTTRN>
|
83
|
+
<TRNTYPE>DEBIT
|
84
|
+
<DTPOSTED>20091013080000
|
85
|
+
<TRNAMT>-501.24
|
86
|
+
<FITID>200910133
|
87
|
+
<CHECKNUM>0001511
|
88
|
+
<MEMO>TITULO COBRANCA-IB
|
89
|
+
</STMTTRN><STMTTRN>
|
90
|
+
<TRNTYPE>DEBIT
|
91
|
+
<DTPOSTED>20091013080000
|
92
|
+
<TRNAMT>-719.03
|
93
|
+
<FITID>200910134
|
94
|
+
<CHECKNUM>0001511
|
95
|
+
<MEMO>TITULO COBRANCA-IB
|
96
|
+
</STMTTRN><STMTTRN>
|
97
|
+
<TRNTYPE>DEBIT
|
98
|
+
<DTPOSTED>20091013080000
|
99
|
+
<TRNAMT>-90.75
|
100
|
+
<FITID>200910135
|
101
|
+
<CHECKNUM>0001223
|
102
|
+
<MEMO>COMPRA VISA ELECTRON
|
103
|
+
</STMTTRN><STMTTRN>
|
104
|
+
<TRNTYPE>DEBIT
|
105
|
+
<DTPOSTED>20091013080000
|
106
|
+
<TRNAMT>-49.80
|
107
|
+
<FITID>200910136
|
108
|
+
<CHECKNUM>0001223
|
109
|
+
<MEMO>COMPRA VISA ELECTRON
|
110
|
+
</STMTTRN><STMTTRN>
|
111
|
+
<TRNTYPE>DEBIT
|
112
|
+
<DTPOSTED>20091013080000
|
113
|
+
<TRNAMT>-219.90
|
114
|
+
<FITID>200910137
|
115
|
+
<CHECKNUM>0001223
|
116
|
+
<MEMO>COMPRA VISA ELECTRON
|
117
|
+
</STMTTRN><STMTTRN>
|
118
|
+
<TRNTYPE>DEBIT
|
119
|
+
<DTPOSTED>20091013080000
|
120
|
+
<TRNAMT>-54.61
|
121
|
+
<FITID>200910138
|
122
|
+
<CHECKNUM>0001223
|
123
|
+
<MEMO>COMPRA VISA ELECTRON
|
124
|
+
</STMTTRN><STMTTRN>
|
125
|
+
<TRNTYPE>DEBIT
|
126
|
+
<DTPOSTED>20091013080000
|
127
|
+
<TRNAMT>-38.57
|
128
|
+
<FITID>200910139
|
129
|
+
<CHECKNUM>0002208
|
130
|
+
<MEMO>PAGTO CONTA TELEFONE -RIB
|
131
|
+
</STMTTRN><STMTTRN>
|
132
|
+
<TRNTYPE>DEBIT
|
133
|
+
<DTPOSTED>20091013080000
|
134
|
+
<TRNAMT>-119.40
|
135
|
+
<FITID>2009101310
|
136
|
+
<CHECKNUM>0002209
|
137
|
+
<MEMO>CONTA DE LUZ -RIB
|
138
|
+
</STMTTRN><STMTTRN>
|
139
|
+
<TRNTYPE>DEBIT
|
140
|
+
<DTPOSTED>20091013080000
|
141
|
+
<TRNAMT>-34.69
|
142
|
+
<FITID>2009101311
|
143
|
+
<CHECKNUM>0002208
|
144
|
+
<MEMO>PAGTO CONTA TELEFONE -RIB
|
145
|
+
</STMTTRN><STMTTRN>
|
146
|
+
<TRNTYPE>DEBIT
|
147
|
+
<DTPOSTED>20091013080000
|
148
|
+
<TRNAMT>-35.07
|
149
|
+
<FITID>2009101312
|
150
|
+
<CHECKNUM>0002231
|
151
|
+
<MEMO>IPTU / TAXAS SP -RIB
|
152
|
+
</STMTTRN><STMTTRN>
|
153
|
+
<TRNTYPE>DEBIT
|
154
|
+
<DTPOSTED>20091013080000
|
155
|
+
<TRNAMT>-259.10
|
156
|
+
<FITID>2009101313
|
157
|
+
<CHECKNUM>0001085
|
158
|
+
<MEMO>PGTO NET
|
159
|
+
</STMTTRN><STMTTRN>
|
160
|
+
<TRNTYPE>DEBIT
|
161
|
+
<DTPOSTED>20091013080000
|
162
|
+
<TRNAMT>-202.84
|
163
|
+
<FITID>2009101314
|
164
|
+
<CHECKNUM>0002606
|
165
|
+
<MEMO>PARC RC EXCLUSIVO 12
|
166
|
+
</STMTTRN><STMTTRN>
|
167
|
+
<TRNTYPE>DEBIT
|
168
|
+
<DTPOSTED>20091013080000
|
169
|
+
<TRNAMT>-272.77
|
170
|
+
<FITID>2009101315
|
171
|
+
<CHECKNUM>0002606
|
172
|
+
<MEMO>PARC RC EXCLUSIVO 08
|
173
|
+
</STMTTRN><STMTTRN>
|
174
|
+
<TRNTYPE>DEBIT
|
175
|
+
<DTPOSTED>20091014080000
|
176
|
+
<TRNAMT>-80.00
|
177
|
+
<FITID>200910141
|
178
|
+
<CHECKNUM>0010991
|
179
|
+
<MEMO>CHEQUE COMPENSADO
|
180
|
+
</STMTTRN><STMTTRN>
|
181
|
+
<TRNTYPE>DEBIT
|
182
|
+
<DTPOSTED>20091014080000
|
183
|
+
<TRNAMT>-177.00
|
184
|
+
<FITID>200910142
|
185
|
+
<CHECKNUM>0010986
|
186
|
+
<MEMO>CHEQUE COMPENSADO
|
187
|
+
</STMTTRN><STMTTRN>
|
188
|
+
<TRNTYPE>DEBIT
|
189
|
+
<DTPOSTED>20091014080000
|
190
|
+
<TRNAMT>-386.00
|
191
|
+
<FITID>200910143
|
192
|
+
<CHECKNUM>0011063
|
193
|
+
<MEMO>CHEQUE COMPENSADO
|
194
|
+
</STMTTRN><STMTTRN>
|
195
|
+
<TRNTYPE>DEBIT
|
196
|
+
<DTPOSTED>20091014080000
|
197
|
+
<TRNAMT>-12.19
|
198
|
+
<FITID>200910144
|
199
|
+
<CHECKNUM>0001223
|
200
|
+
<MEMO>COMPRA VISA ELECTRON
|
201
|
+
</STMTTRN><STMTTRN>
|
202
|
+
<TRNTYPE>DEBIT
|
203
|
+
<DTPOSTED>20091015080000
|
204
|
+
<TRNAMT>-41.00
|
205
|
+
<FITID>200910151
|
206
|
+
<CHECKNUM>0011064
|
207
|
+
<MEMO>CHEQUE COMPENSADO
|
208
|
+
</STMTTRN><STMTTRN>
|
209
|
+
<TRNTYPE>DEBIT
|
210
|
+
<DTPOSTED>20091016080000
|
211
|
+
<TRNAMT>-63.00
|
212
|
+
<FITID>200910161
|
213
|
+
<CHECKNUM>0010856
|
214
|
+
<MEMO>CHEQUE COMPENSADO
|
215
|
+
</STMTTRN><STMTTRN>
|
216
|
+
<TRNTYPE>DEBIT
|
217
|
+
<DTPOSTED>20091019080000
|
218
|
+
<TRNAMT>-51.00
|
219
|
+
<FITID>200910191
|
220
|
+
<CHECKNUM>0011065
|
221
|
+
<MEMO>CHEQUE COMPENSADO
|
222
|
+
</STMTTRN><STMTTRN>
|
223
|
+
<TRNTYPE>DEBIT
|
224
|
+
<DTPOSTED>20091019080000
|
225
|
+
<TRNAMT>-23.81
|
226
|
+
<FITID>200910192
|
227
|
+
<CHECKNUM>0001203
|
228
|
+
<MEMO>ASSINATURA ABRIL
|
229
|
+
</STMTTRN><STMTTRN>
|
230
|
+
<TRNTYPE>DEBIT
|
231
|
+
<DTPOSTED>20091020080000
|
232
|
+
<TRNAMT>-15.50
|
233
|
+
<FITID>200910201
|
234
|
+
<CHECKNUM>0001223
|
235
|
+
<MEMO>COMPRA VISA ELECTRON
|
236
|
+
</STMTTRN><STMTTRN>
|
237
|
+
<TRNTYPE>DEBIT
|
238
|
+
<DTPOSTED>20091021080000
|
239
|
+
<TRNAMT>-132.00
|
240
|
+
<FITID>200910211
|
241
|
+
<CHECKNUM>0011023
|
242
|
+
<MEMO>CHEQUE COMPENSADO
|
243
|
+
</STMTTRN><STMTTRN>
|
244
|
+
<TRNTYPE>CREDIT
|
245
|
+
<DTPOSTED>20091022080000
|
246
|
+
<TRNAMT>600.00
|
247
|
+
<FITID>200910221
|
248
|
+
<CHECKNUM>0001433
|
249
|
+
<MEMO>DOC REM 216.397.168-66
|
250
|
+
</STMTTRN><STMTTRN>
|
251
|
+
<TRNTYPE>DEBIT
|
252
|
+
<DTPOSTED>20091022080000
|
253
|
+
<TRNAMT>-22.40
|
254
|
+
<FITID>200910222
|
255
|
+
<CHECKNUM>0001223
|
256
|
+
<MEMO>COMPRA VISA ELECTRON
|
257
|
+
</STMTTRN><STMTTRN>
|
258
|
+
<TRNTYPE>DEBIT
|
259
|
+
<DTPOSTED>20091022080000
|
260
|
+
<TRNAMT>-73.16
|
261
|
+
<FITID>200910223
|
262
|
+
<CHECKNUM>0001223
|
263
|
+
<MEMO>COMPRA VISA ELECTRON
|
264
|
+
</STMTTRN><STMTTRN>
|
265
|
+
<TRNTYPE>DEBIT
|
266
|
+
<DTPOSTED>20091023080000
|
267
|
+
<TRNAMT>-61.36
|
268
|
+
<FITID>200910231
|
269
|
+
<CHECKNUM>0000292
|
270
|
+
<MEMO>CONTA AGUA/ESGOTO
|
271
|
+
</STMTTRN><STMTTRN>
|
272
|
+
<TRNTYPE>DEBIT
|
273
|
+
<DTPOSTED>20091026080000
|
274
|
+
<TRNAMT>-96.00
|
275
|
+
<FITID>200910261
|
276
|
+
<CHECKNUM>0002212
|
277
|
+
<MEMO>PAGTO FATURA REALVISA-RIB
|
278
|
+
</STMTTRN><STMTTRN>
|
279
|
+
<TRNTYPE>DEBIT
|
280
|
+
<DTPOSTED>20091030080000
|
281
|
+
<TRNAMT>-67.75
|
282
|
+
<FITID>200910301
|
283
|
+
<CHECKNUM>0011061
|
284
|
+
<MEMO>CHEQUE COMPENSADO
|
285
|
+
</STMTTRN><STMTTRN>
|
286
|
+
<TRNTYPE>DEBIT
|
287
|
+
<DTPOSTED>20091030080000
|
288
|
+
<TRNAMT>-25.88
|
289
|
+
<FITID>200910302
|
290
|
+
<CHECKNUM>0001223
|
291
|
+
<MEMO>COMPRA VISA ELECTRON
|
292
|
+
</STMTTRN><STMTTRN>
|
293
|
+
<TRNTYPE>DEBIT
|
294
|
+
<DTPOSTED>20091103080000
|
295
|
+
<TRNAMT>-89.03
|
296
|
+
<FITID>200911031
|
297
|
+
<CHECKNUM>0001223
|
298
|
+
<MEMO>COMPRA VISA ELECTRON
|
299
|
+
</STMTTRN>
|
300
|
+
</BANKTRANLIST>
|
301
|
+
<LEDGERBAL>
|
302
|
+
<BALAMT>598.44
|
303
|
+
<DTASOF>20091101
|
304
|
+
</LEDGERBAL>
|
305
|
+
</STMTRS>
|
306
|
+
</STMTTRNRS>
|
307
|
+
</BANKMSGSRSV1>
|
308
|
+
</OFX>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec/spec_helper"
|
2
|
+
|
3
|
+
describe OFX::Account do
|
4
|
+
before do
|
5
|
+
@ofx = OFX::Parser::Base.new("spec/fixtures/sample.ofx")
|
6
|
+
@parser = @ofx.parser
|
7
|
+
@account = @parser.account
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "account" do
|
11
|
+
it "should return currency" do
|
12
|
+
@account.currency.should == "BRL"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return bank id" do
|
16
|
+
@account.bank_id.should == "0356"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return id" do
|
20
|
+
@account.id.should == "03227113109"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return type" do
|
24
|
+
@account.type.should == :checking
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return transactions" do
|
28
|
+
@account.transactions.should be_a_kind_of(Array)
|
29
|
+
@account.transactions.size.should == 36
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return balance" do
|
33
|
+
@account.balance.amount.should == 598.44
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return balance in pennies" do
|
37
|
+
@account.balance.amount_in_pennies.should == 59844
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return balance date" do
|
41
|
+
@account.balance.posted_at.should == Time.parse("2009-11-01")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec/spec_helper"
|
2
|
+
|
3
|
+
describe OFX::Parser::OFX102 do
|
4
|
+
before do
|
5
|
+
@ofx = OFX::Parser::Base.new("spec/fixtures/sample.ofx")
|
6
|
+
@parser = @ofx.parser
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have a version" do
|
10
|
+
OFX::Parser::OFX102::VERSION.should == "1.0.2"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should set headers" do
|
14
|
+
@parser.headers.should == @ofx.headers
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set body" do
|
18
|
+
@parser.body.should == @ofx.body
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set account" do
|
22
|
+
@parser.account.should be_a_kind_of(OFX::Account)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec/spec_helper"
|
2
|
+
|
3
|
+
describe OFX::Parser do
|
4
|
+
before do
|
5
|
+
@ofx = OFX::Parser::Base.new("spec/fixtures/sample.ofx")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should read file" do
|
9
|
+
@ofx.content.should_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should set content" do
|
13
|
+
@ofx.content.should == open("spec/fixtures/sample.ofx").read
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set body" do
|
17
|
+
@ofx.body.should_not be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "headers" do
|
21
|
+
it "should have OFXHEADER" do
|
22
|
+
@ofx.headers["OFXHEADER"].should == "100"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have DATA" do
|
26
|
+
@ofx.headers["DATA"].should == "OFXSGML"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have VERSION" do
|
30
|
+
@ofx.headers["VERSION"].should == "102"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have SECURITY" do
|
34
|
+
@ofx.headers.should have_key("SECURITY")
|
35
|
+
@ofx.headers["SECURITY"].should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have ENCODING" do
|
39
|
+
@ofx.headers["ENCODING"].should == "USASCII"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have CHARSET" do
|
43
|
+
@ofx.headers["CHARSET"].should == "1252"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have COMPRESSION" do
|
47
|
+
@ofx.headers.should have_key("COMPRESSION")
|
48
|
+
@ofx.headers["COMPRESSION"].should be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should have OLDFILEUID" do
|
52
|
+
@ofx.headers.should have_key("OLDFILEUID")
|
53
|
+
@ofx.headers["OLDFILEUID"].should be_nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have NEWFILEUID" do
|
57
|
+
@ofx.headers.should have_key("NEWFILEUID")
|
58
|
+
@ofx.headers["NEWFILEUID"].should be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "spec/spec_helper"
|
2
|
+
|
3
|
+
describe OFX::Transaction do
|
4
|
+
before do
|
5
|
+
@ofx = OFX::Parser::Base.new("spec/fixtures/sample.ofx")
|
6
|
+
@parser = @ofx.parser
|
7
|
+
@account = @parser.account
|
8
|
+
end
|
9
|
+
|
10
|
+
context "debit" do
|
11
|
+
before do
|
12
|
+
@transaction = @account.transactions[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should set amount" do
|
16
|
+
@transaction.amount.should == -35.34
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set amount in pennies" do
|
20
|
+
@transaction.amount_in_pennies.should == -3534
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set fit id" do
|
24
|
+
@transaction.fit_id.should == "200910091"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should set memo" do
|
28
|
+
@transaction.memo.should == "COMPRA VISA ELECTRON"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should set check number" do
|
32
|
+
@transaction.check_number.should == "0001223"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have date" do
|
36
|
+
@transaction.posted_at.should == Time.parse("2009-10-09- 08:00:00")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should have type" do
|
40
|
+
@transaction.type.should == :debit
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "credit" do
|
45
|
+
before do
|
46
|
+
@transaction = @account.transactions[1]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should set amount" do
|
50
|
+
@transaction.amount.should == 60.39
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should set amount in pennies" do
|
54
|
+
@transaction.amount_in_pennies.should == 6039
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should set fit id" do
|
58
|
+
@transaction.fit_id.should == "200910162"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should set memo" do
|
62
|
+
@transaction.memo.should == "DEPOSITO POUP.CORRENTE"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should set check number" do
|
66
|
+
@transaction.check_number.should == "0880136"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should have date" do
|
70
|
+
@transaction.posted_at.should == Time.parse("2009-10-16 08:00:00")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have type" do
|
74
|
+
@transaction.type.should == :credit
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "with more info" do
|
79
|
+
before do
|
80
|
+
@transaction = @account.transactions[2]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should set payee" do
|
84
|
+
@transaction.payee.should == "Pagto conta telefone"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should set check number" do
|
88
|
+
@transaction.check_number.should == "000000101901"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have date" do
|
92
|
+
@transaction.posted_at.should == Time.parse("2009-10-19 12:00:00")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should have type" do
|
96
|
+
@transaction.type.should == :other
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should have reference number" do
|
100
|
+
@transaction.ref_number.should == "101.901"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
require "ofx"
|
7
|
+
|
8
|
+
Spec::Matchers.define :have_key do |key|
|
9
|
+
match do |hash|
|
10
|
+
hash.respond_to?(:keys) &&
|
11
|
+
hash.keys.kind_of?(Array) &&
|
12
|
+
hash.keys.include?(key)
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ofx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nando Vieira
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-11 00:00:00 -02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports OFX 1.0.2.
|
26
|
+
email: fnando.vieira@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.markdown
|
33
|
+
files:
|
34
|
+
- README.markdown
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- lib/ofx.rb
|
38
|
+
- lib/ofx/account.rb
|
39
|
+
- lib/ofx/balance.rb
|
40
|
+
- lib/ofx/foundation.rb
|
41
|
+
- lib/ofx/parser.rb
|
42
|
+
- lib/ofx/parser/ofx102.rb
|
43
|
+
- lib/ofx/transaction.rb
|
44
|
+
- lib/ofx/version.rb
|
45
|
+
- spec/fixtures/sample.ofx
|
46
|
+
- spec/ofx/account_spec.rb
|
47
|
+
- spec/ofx/ofx102_spec.rb
|
48
|
+
- spec/ofx/ofx_parser_spec.rb
|
49
|
+
- spec/ofx/ofx_spec.rb
|
50
|
+
- spec/ofx/transaction_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
52
|
+
has_rdoc: false
|
53
|
+
homepage: http://github.com/fnando/ofx
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --charset=UTF-8
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.3.1
|
75
|
+
signing_key:
|
76
|
+
specification_version: 2
|
77
|
+
summary: A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports OFX 1.0.2.
|
78
|
+
test_files: []
|
79
|
+
|