ofx 0.3.4 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f010daf75c910a87b19c737c27a0970a4a410f5e5b6ba5916f4546e2bb5f9abb
4
- data.tar.gz: abf6b0090855e5c063ce2d627e8f2b4907be64a71289cb520d4ae4bf7687371e
3
+ metadata.gz: 98b2accf4fa4b1b9d0d8168e4518140484b69be77dfc114d5924eea1cf6eb912
4
+ data.tar.gz: c7eb6a605614095ac31ffcc840965a965146f803453652a37d1d2855e2dbc5e4
5
5
  SHA512:
6
- metadata.gz: f3ccb6719848c32e3047243715a3ec2aabbc80b2f241bfd2ff7dcbda819bf1baeb3086ee751459a28643345d4272bf4b4481dd56ba727f9ebf94ea6a680d4cf0
7
- data.tar.gz: 48076b4428d20fa368544099691ebe1bf877b724b49cfce83265545a84b62b07e45759e00ae0febaf254090d53c157a1f9b7b6340f5c9d59237aa1847e590ca5
6
+ metadata.gz: daf84f358d5810cfa9916dcce97bedb6297718f1db96e9bf347a5fef041c35eafa4e7934e0509a0c0133199ef678713ebba377afdde3f8172f523808abfb1ea4
7
+ data.tar.gz: 3bee29bfb6338c36842e5b08321944c3b4c668e607b3c980b2acba9dfa530941f17157ca0ca8921cb6479e380a33c4145a309e5f5cdf482a8147c06fa98627c2
data/README.rdoc CHANGED
@@ -1,7 +1,7 @@
1
1
  = OFX
2
2
 
3
- {<img src="https://badge.fury.io/rb/ofx.png" alt="Gem Version" />}[http://badge.fury.io/rb/ofx]
4
- {<img src="https://travis-ci.org/annacruz/ofx.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/annacruz/ofx]
3
+ {<img src="https://badge.fury.io/rb/ofx.svg" alt="Gem Version" />}[https://badge.fury.io/rb/ofx]
4
+ {<img src="https://github.com/annacruz/ofx/actions/workflows/config.yml/badge.svg" alt="Build Status" />}[https://github.com/annacruz/ofx/actions]
5
5
 
6
6
  A simple OFX (Open Financial Exchange) parser built on top of Nokogiri. Currently supports both OFX 1.0.2 and 2.1.1.
7
7
 
@@ -14,7 +14,7 @@ module OFX
14
14
 
15
15
  TRANSACTION_TYPES = %w[
16
16
  ATM CASH CHECK CREDIT DEBIT DEP DIRECTDEBIT DIRECTDEP DIV
17
- FEE INT OTHER PAYMENT POS REPEATPMT SRVCHG XFER
17
+ FEE INT OTHER PAYMENT POS REPEATPMT SRVCHG XFER IN OUT
18
18
  ].each_with_object({}) do |tran_type, hash|
19
19
  hash[tran_type] = tran_type.downcase.to_sym
20
20
  end
@@ -23,7 +23,7 @@ module OFX
23
23
  'INFO' => :info,
24
24
  'WARN' => :warn,
25
25
  'ERROR' => :error
26
- }.freeza
26
+ }.freeze
27
27
 
28
28
  attr_reader :headers, :body, :html
29
29
 
@@ -52,7 +52,7 @@ module OFX
52
52
 
53
53
  def self.parse_headers(header_text)
54
54
  # Change single CR's to LF's to avoid issues with some banks
55
- header_text.gsub!(/\r(?!\n)/, '\n')
55
+ header_text.gsub!(/\r(?!\n)/, "\n")
56
56
 
57
57
  # Parse headers. When value is NONE, convert it to nil.
58
58
  headers = header_text.to_enum(:each_line).each_with_object({}) do |line, memo|
@@ -134,7 +134,7 @@ module OFX
134
134
  check_number: element.search('checknum').inner_text,
135
135
  ref_number: element.search('refnum').inner_text,
136
136
  posted_at: build_date(element.search('dtposted').inner_text),
137
- occurred_at:,
137
+ occurred_at: occurred_at,
138
138
  type: build_type(element),
139
139
  sic: element.search('sic').inner_text
140
140
  })
@@ -164,7 +164,7 @@ module OFX
164
164
  offset = '+0000'
165
165
  end
166
166
 
167
- date << ' #{offset}'
167
+ date << " #{offset}"
168
168
 
169
169
  Time.parse(date)
170
170
  end
@@ -178,9 +178,9 @@ module OFX
178
178
  end
179
179
 
180
180
  OFX::Balance.new({
181
- amount:,
181
+ amount: amount,
182
182
  amount_in_pennies: (amount * 100).to_i,
183
- posted_at:
183
+ posted_at: posted_at
184
184
  })
185
185
  end
186
186
 
@@ -189,7 +189,7 @@ module OFX
189
189
  amount = to_decimal(node.search('availbal > balamt').inner_text)
190
190
 
191
191
  OFX::Balance.new({
192
- amount:,
192
+ amount: amount,
193
193
  amount_in_pennies: (amount * 100).to_i,
194
194
  posted_at: build_date(node.search('availbal > dtasof').inner_text)
195
195
  })
@@ -198,6 +198,8 @@ module OFX
198
198
 
199
199
  def to_decimal(amount)
200
200
  BigDecimal(amount.to_s.gsub(',', '.'))
201
+ rescue ArgumentError
202
+ BigDecimal('0.0')
201
203
  end
202
204
  end
203
205
  end
data/lib/ofx/parser.rb CHANGED
@@ -17,7 +17,7 @@ module OFX
17
17
  end
18
18
 
19
19
  case headers["VERSION"]
20
- when /102/ then
20
+ when /100|102/ then
21
21
  @parser = OFX102.new(:headers => headers, :body => body)
22
22
  when /103/ then
23
23
  @parser = OFX103.new(:headers => headers, :body => body)
data/lib/ofx/version.rb CHANGED
@@ -2,7 +2,7 @@ module OFX
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- PATCH = 4
5
+ PATCH = 6
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  end
@@ -39,7 +39,7 @@ describe OFX::Parser::OFX102 do
39
39
  it "should know about all transaction types" do
40
40
  valid_types = [
41
41
  'CREDIT', 'DEBIT', 'INT', 'DIV', 'FEE', 'SRVCHG', 'DEP', 'ATM', 'POS', 'XFER',
42
- 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER'
42
+ 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER', 'IN', 'OUT'
43
43
  ]
44
44
  valid_types.sort.should == OFX::Parser::OFX102::TRANSACTION_TYPES.keys.sort
45
45
 
@@ -39,7 +39,7 @@ describe OFX::Parser::OFX103 do
39
39
  it "should know about all transaction types" do
40
40
  valid_types = [
41
41
  'CREDIT', 'DEBIT', 'INT', 'DIV', 'FEE', 'SRVCHG', 'DEP', 'ATM', 'POS', 'XFER',
42
- 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER'
42
+ 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER', 'IN', 'OUT'
43
43
  ]
44
44
  valid_types.sort.should == OFX::Parser::OFX103::TRANSACTION_TYPES.keys.sort
45
45
 
@@ -47,8 +47,16 @@ describe OFX::Parser do
47
47
  }.should raise_error(OFX::UnsupportedFileError)
48
48
  end
49
49
 
50
- it "should use 211 parser to parse version 200 ofx files" do
51
- OFX::Parser::OFX211.stub(:new).and_return('ofx-211-parser')
50
+ it "uses 102 parser to parse version 100 ofx files" do
51
+ expect(OFX::Parser::OFX102).to receive(:new).and_return('ofx-102-parser')
52
+
53
+ ofx = OFX::Parser::Base.new(ofx_2_example('100'))
54
+ expect(ofx.parser).to eql 'ofx-102-parser'
55
+ end
56
+
57
+ it "uses 211 parser to parse version 200 ofx files" do
58
+ expect(OFX::Parser::OFX211).to receive(:new).and_return('ofx-211-parser')
59
+
52
60
  ofx = OFX::Parser::Base.new(ofx_2_example('200'))
53
61
  ofx.parser.should == 'ofx-211-parser'
54
62
  end
@@ -59,6 +67,13 @@ describe OFX::Parser do
59
67
  ofx.parser.should == 'ofx-211-parser'
60
68
  end
61
69
 
70
+ it "uses 211 parser to parse version 220 ofx files" do
71
+ expect(OFX::Parser::OFX211).to receive(:new).and_return('ofx-211-parser')
72
+
73
+ ofx = OFX::Parser::Base.new(ofx_2_example('220'))
74
+ expect(ofx.parser).to eql 'ofx-211-parser'
75
+ end
76
+
62
77
  describe "headers" do
63
78
  it "should have OFXHEADER" do
64
79
  @ofx.headers["OFXHEADER"].should == "100"
@@ -101,17 +116,15 @@ describe OFX::Parser do
101
116
  end
102
117
 
103
118
  it "should parse headers with CR and without LF" do
119
+ header = %{OFXHEADER:100\rDATA:OFXSGML\rVERSION:102\rSECURITY:NONE\rENCODING:USASCII\rCHARSET:1252\rCOMPRESSION:NONE\rOLDFILEUID:NONE\rNEWFILEUID:NONE\r}
120
+ body = open("spec/fixtures/sample.ofx").read.split(/<OFX>/, 2)[1]
121
+ ofx_with_carriage_return = header + "<OFX>" + body
122
+
104
123
  @ofx = OFX::Parser::Base.new(ofx_with_carriage_return)
105
124
  @ofx.headers.size.should be(9)
106
125
  end
107
126
  end
108
127
 
109
- def ofx_with_carriage_return
110
- header = %{OFXHEADER:100\rDATA:OFXSGML\rVERSION:102\rSECURITY:NONE\rENCODING:USASCII\rCHARSET:1252\rCOMPRESSION:NONE\rOLDFILEUID:NONE\rNEWFILEUID:NONE\r}
111
- body = open("spec/fixtures/sample.ofx").read.split(/<OFX>/, 2)[1]
112
- header + "<OFX>" + body
113
- end
114
-
115
128
  def ofx_2_example(version)
116
129
  <<-EndOfx
117
130
  <?xml version="1.0" encoding="US-ASCII"?>
@@ -13,43 +13,43 @@ describe OFX::Transaction do
13
13
  end
14
14
 
15
15
  it "should set amount" do
16
- @transaction.amount.should == BigDecimal('-35.34')
16
+ expect(@transaction.amount).to eql BigDecimal('-35.34')
17
17
  end
18
18
 
19
19
  it "should cast amount to BigDecimal" do
20
- @transaction.amount.class.should == BigDecimal
20
+ expect(@transaction.amount.class).to be BigDecimal
21
21
  end
22
22
 
23
23
  it "should set amount in pennies" do
24
- @transaction.amount_in_pennies.should == -3534
24
+ expect(@transaction.amount_in_pennies).to eql -3534
25
25
  end
26
26
 
27
27
  it "should set fit id" do
28
- @transaction.fit_id.should == "200910091"
28
+ expect(@transaction.fit_id).to eql "200910091"
29
29
  end
30
30
 
31
31
  it "should set memo" do
32
- @transaction.memo.should == "COMPRA VISA ELECTRON"
32
+ expect(@transaction.memo).to eql "COMPRA VISA ELECTRON"
33
33
  end
34
34
 
35
35
  it "should set check number" do
36
- @transaction.check_number.should == "0001223"
36
+ expect(@transaction.check_number).to eql "0001223"
37
37
  end
38
38
 
39
39
  it "should have date" do
40
- @transaction.posted_at.should == Time.parse("2009-10-09 08:00:00 +0000")
40
+ expect(@transaction.posted_at).to eql Time.parse("2009-10-09 08:00:00 +0000")
41
41
  end
42
42
 
43
43
  it 'should have user date' do
44
- @transaction.occurred_at.should == Time.parse("2009-09-09 08:00:00 +0000")
44
+ expect(@transaction.occurred_at).to eql Time.parse("2009-09-09 08:00:00 +0000")
45
45
  end
46
46
 
47
47
  it "should have type" do
48
- @transaction.type.should == :debit
48
+ expect(@transaction.type).to eql :debit
49
49
  end
50
50
 
51
51
  it "should have sic" do
52
- @transaction.sic.should == '5072'
52
+ expect(@transaction.sic).to eql '5072'
53
53
  end
54
54
  end
55
55
 
@@ -59,39 +59,39 @@ describe OFX::Transaction do
59
59
  end
60
60
 
61
61
  it "should set amount" do
62
- @transaction.amount.should == BigDecimal('60.39')
62
+ expect(@transaction.amount).to eql BigDecimal('60.39')
63
63
  end
64
64
 
65
65
  it "should set amount in pennies" do
66
- @transaction.amount_in_pennies.should == 6039
66
+ expect(@transaction.amount_in_pennies).to eql 6039
67
67
  end
68
68
 
69
69
  it "should set fit id" do
70
- @transaction.fit_id.should == "200910162"
70
+ expect(@transaction.fit_id).to eql "200910162"
71
71
  end
72
72
 
73
73
  it "should set memo" do
74
- @transaction.memo.should == "DEPOSITO POUP.CORRENTE"
74
+ expect(@transaction.memo).to eql "DEPOSITO POUP.CORRENTE"
75
75
  end
76
76
 
77
77
  it "should set check number" do
78
- @transaction.check_number.should == "0880136"
78
+ expect(@transaction.check_number).to eql "0880136"
79
79
  end
80
80
 
81
81
  it "should have date" do
82
- @transaction.posted_at.should == Time.parse("2009-10-16 08:00:00 +0000")
82
+ expect(@transaction.posted_at).to eql Time.parse("2009-10-16 08:00:00 +0000")
83
83
  end
84
84
 
85
85
  it "should have user date" do
86
- @transaction.occurred_at.should == Time.parse("2009-09-16 08:00:00 +0000")
86
+ expect(@transaction.occurred_at).to eql Time.parse("2009-09-16 08:00:00 +0000")
87
87
  end
88
88
 
89
89
  it "should have type" do
90
- @transaction.type.should == :credit
90
+ expect(@transaction.type).to eql :credit
91
91
  end
92
92
 
93
93
  it "should have empty sic" do
94
- @transaction.sic.should == ''
94
+ expect(@transaction.sic).to eql ''
95
95
  end
96
96
  end
97
97
 
@@ -101,27 +101,27 @@ describe OFX::Transaction do
101
101
  end
102
102
 
103
103
  it "should set payee" do
104
- @transaction.payee.should == "Pagto conta telefone"
104
+ expect(@transaction.payee).to eql "Pagto conta telefone"
105
105
  end
106
106
 
107
107
  it "should set check number" do
108
- @transaction.check_number.should == "000000101901"
108
+ expect(@transaction.check_number).to eql "000000101901"
109
109
  end
110
110
 
111
111
  it "should have date" do
112
- @transaction.posted_at.should == Time.parse("2009-10-19 12:00:00 -0300")
112
+ expect(@transaction.posted_at).to eql Time.parse("2009-10-19 12:00:00 -0300")
113
113
  end
114
114
 
115
115
  it "should have user date" do
116
- @transaction.occurred_at.should == Time.parse("2009-10-17 12:00:00 -0300")
116
+ expect(@transaction.occurred_at).to eql Time.parse("2009-10-17 12:00:00 -0300")
117
117
  end
118
118
 
119
119
  it "should have type" do
120
- @transaction.type.should == :other
120
+ expect(@transaction.type).to eql :other
121
121
  end
122
122
 
123
123
  it "should have reference number" do
124
- @transaction.ref_number.should == "101.901"
124
+ expect(@transaction.ref_number).to eql "101.901"
125
125
  end
126
126
  end
127
127
 
@@ -131,7 +131,7 @@ describe OFX::Transaction do
131
131
  end
132
132
 
133
133
  it "should set name" do
134
- @transaction.name.should == "Pagto conta telefone"
134
+ expect(@transaction.name).to eql "Pagto conta telefone"
135
135
  end
136
136
  end
137
137
 
@@ -144,22 +144,22 @@ describe OFX::Transaction do
144
144
 
145
145
  it "should return dep" do
146
146
  @transaction = @account.transactions[9]
147
- @transaction.type.should == :dep
147
+ expect(@transaction.type).to eql :dep
148
148
  end
149
149
 
150
150
  it "should return xfer" do
151
151
  @transaction = @account.transactions[18]
152
- @transaction.type.should == :xfer
152
+ expect(@transaction.type).to eql :xfer
153
153
  end
154
154
 
155
155
  it "should return cash" do
156
156
  @transaction = @account.transactions[45]
157
- @transaction.type.should == :cash
157
+ expect(@transaction.type).to eql :cash
158
158
  end
159
159
 
160
160
  it "should return check" do
161
161
  @transaction = @account.transactions[0]
162
- @transaction.type.should == :check
162
+ expect(@transaction.type).to eql :check
163
163
  end
164
164
  end
165
165
 
@@ -176,11 +176,11 @@ describe OFX::Transaction do
176
176
  end
177
177
 
178
178
  it "should set amount" do
179
- @transaction.amount.should == BigDecimal('-11.76')
179
+ expect(@transaction.amount).to eql BigDecimal('-11.76')
180
180
  end
181
181
 
182
182
  it "should set amount in pennies" do
183
- @transaction.amount_in_pennies.should == -1176
183
+ expect(@transaction.amount_in_pennies).to eql -1176
184
184
  end
185
185
  end
186
186
 
@@ -190,12 +190,31 @@ describe OFX::Transaction do
190
190
  end
191
191
 
192
192
  it "should set amount" do
193
- @transaction.amount.should == BigDecimal('47.01')
193
+ expect(@transaction.amount).to eql BigDecimal('47.01')
194
194
  end
195
195
 
196
196
  it "should set amount in pennies" do
197
- @transaction.amount_in_pennies.should == 4701
197
+ expect(@transaction.amount_in_pennies).to eql 4701
198
198
  end
199
199
  end
200
200
  end
201
+
202
+ context "invalid decimal values" do
203
+ before do
204
+ @ofx = OFX::Parser::Base.new("spec/fixtures/cef_malformed_decimal.ofx")
205
+ @parser = @ofx.parser
206
+ end
207
+
208
+ it "should not raise error" do
209
+ expect { @parser.account.transactions }.to_not raise_error
210
+ end
211
+
212
+ it "should return zero in amount" do
213
+ expect(@parser.account.transactions[0].amount).to eql BigDecimal('0.0')
214
+ end
215
+
216
+ it "should return zero in amount_in_pennies" do
217
+ expect(@parser.account.transactions[0].amount_in_pennies).to eql 0
218
+ end
219
+ end
201
220
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "ofx"
2
+ require "byebug"
2
3
 
3
4
  RSpec::Matchers.define :have_key do |key|
4
5
  match do |hash|
@@ -7,3 +8,7 @@ RSpec::Matchers.define :have_key do |key|
7
8
  hash.keys.include?(key)
8
9
  end
9
10
  end
11
+
12
+ RSpec.configure do |c|
13
+ c.filter_run_when_matching :focus
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ofx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
@@ -9,22 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-02-22 00:00:00.000000000 Z
12
+ date: 2025-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: 1.13.1
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 1.16.0
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
- - - "~>"
28
+ - - ">="
26
29
  - !ruby/object:Gem::Version
27
30
  version: 1.13.1
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.16.0
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: byebug
30
36
  requirement: !ruby/object:Gem::Requirement