ofx 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+