ofx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ module OFX
2
+ class Account < Foundation
3
+ attr_accessor :balance
4
+ attr_accessor :bank_id
5
+ attr_accessor :currency
6
+ attr_accessor :id
7
+ attr_accessor :transactions
8
+ attr_accessor :type
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module OFX
2
+ class Balance < Foundation
3
+ attr_accessor :amount
4
+ attr_accessor :amount_in_pennies
5
+ attr_accessor :posted_at
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module OFX
2
+ class Foundation
3
+ def initialize(attrs)
4
+ attrs.each do |key, value|
5
+ send("#{key}=", value)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,8 @@
1
+ module OFX
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 0
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
+ end
8
+ end
@@ -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,11 @@
1
+ require "spec/spec_helper"
2
+
3
+ describe OFX do
4
+ describe "#OFX" do
5
+ it "should yield an OFX instance" do
6
+ OFX("spec/fixtures/sample.ofx") do |ofx|
7
+ ofx.should be_kind_of(OFX::Parser::OFX102)
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -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
+