ofx_reader 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 412056e9bc0138a1aa7612277e4678942fa1e8a514ef3af9c84133e337cba320
4
- data.tar.gz: c2a011b0b3d7002fecc96b7923bf827969fb9c7db28e5deb02bb59dad2da1bc6
3
+ metadata.gz: 7a6ac416c757355d3778f28d52cb2316ae348ef00fe43fee01afba99aac927c5
4
+ data.tar.gz: 6e49a814941761ecf810494ca558cc4d7b7b34e06ab60549844092f955e02b0e
5
5
  SHA512:
6
- metadata.gz: 3f4a500d8b8d3d7dccc9601d1a97ab572c7d4506a990ed0198b1e004a70aa3987a196467c5d30d09ad6561fcb6b6ce9e93fec3a16aa3ae6fdd74c414e67aa2cb
7
- data.tar.gz: 74c34eb7b255ab0438d5ba9bacc9861efc45734ff0f079f88cecf3ad129f0e7671dca56e3875ab02c1e0304d8987136c22dbf75a0ab300a55ac070594e4e8493
6
+ metadata.gz: 48a4ac09429acc7d5b335bdcf37641081d1224412fb5d3e6bc46e78ecb163159b25ec3055acab754a2c51a89dfc987402837c9742f9b35649232fcfc3ea4e1ae
7
+ data.tar.gz: 57048f3e3040131aa1b0b6286cb6fecbf49cc585a32d3d2c9056a7d02931b0f9bcf7420e65a954770b1936e0f05b16202dd790a92a7252b4290e65e854a891ab
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  *.gem
13
+ .DS_Store
data/Gemfile.lock CHANGED
@@ -2,17 +2,27 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  ofx_reader (0.1.3)
5
+ activesupport (> 4)
5
6
  nokogiri (~> 1.8)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
11
+ activesupport (5.1.4)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (~> 0.7)
14
+ minitest (~> 5.1)
15
+ tzinfo (~> 1.1)
10
16
  coderay (1.1.2)
17
+ concurrent-ruby (1.0.5)
11
18
  diff-lcs (1.3)
12
19
  docile (1.1.5)
20
+ i18n (0.9.1)
21
+ concurrent-ruby (~> 1.0)
13
22
  json (2.1.0)
14
23
  method_source (0.9.0)
15
24
  mini_portile2 (2.3.0)
25
+ minitest (5.10.3)
16
26
  nokogiri (1.8.1)
17
27
  mini_portile2 (~> 2.3.0)
18
28
  pry (0.11.3)
@@ -37,6 +47,9 @@ GEM
37
47
  json (>= 1.8, < 3)
38
48
  simplecov-html (~> 0.10.0)
39
49
  simplecov-html (0.10.2)
50
+ thread_safe (0.3.6)
51
+ tzinfo (1.2.4)
52
+ thread_safe (~> 0.1)
40
53
 
41
54
  PLATFORMS
42
55
  ruby
data/exe/ofx_reader CHANGED
@@ -6,7 +6,7 @@ require 'ofx_reader'
6
6
  if ARGV[0]
7
7
  if File.exist?(ARGV[0])
8
8
  ofx_text = File.read(ARGV[0])
9
- ofx = OFXReader::Parser::OFX102.new(ofx_text)
9
+ ofx = OFXReader.(ofx_text)
10
10
  pp ofx.headers
11
11
  pp ofx.account
12
12
  pp ofx.transactions
@@ -0,0 +1,4 @@
1
+ module OFXReader
2
+ class OFXWithoutBankAccountError < StandardError
3
+ end
4
+ end
@@ -1,2 +1,4 @@
1
- class UnsupportedOFXVersionError < StandardError
1
+ module OFXReader
2
+ class UnsupportedOFXVersionError < StandardError
3
+ end
2
4
  end
@@ -5,10 +5,12 @@ module OFXReader
5
5
  require 'time'
6
6
 
7
7
  attr_reader :header, :body
8
+ attr_reader :strict
8
9
  attr_reader :headers, :account, :transactions
9
10
 
10
- def initialize(content)
11
+ def initialize(content, strict: false)
11
12
  content = content.encode("UTF-8", "ISO-8859-1")
13
+ @strict = strict
12
14
  @header, @body = content.dup.split(/(?=<OFX>)/, 2)
13
15
  @headers = parse_headers(header)
14
16
  @account, @transactions = parse_body(body)
@@ -16,19 +18,24 @@ module OFXReader
16
18
 
17
19
  private
18
20
 
19
- def parse_headers(headers)
20
- headers.each_line.with_object({}) do |line, hash|
21
+ def parse_headers(header)
22
+ header.gsub("\r", "\n").each_line.with_object({}) do |line, hash|
21
23
  _, k, v = *line.match(/^(.*?):(.*?)\s*(\r?\n)*$/)
22
24
  hash[k.downcase.to_sym] = v unless v.nil?
23
25
  end
24
26
  end
25
27
 
26
28
  def parse_body(body)
27
- body.gsub!(/>\s+</m, '><')
28
- body.gsub!(/\s+</m, '<')
29
- body.gsub!(/>\s+/m, '>')
30
- body.gsub!(/<(\w+?)>([^<]+)/m, '<\1>\2</\1>')
31
- parser.new(::Nokogiri::XML(body)).parse
29
+ doc = ::Nokogiri::XML(body)
30
+ if doc.errors.any?
31
+ body.gsub!(/>\s+</m, '><')
32
+ body.gsub!(/\s+</m, '<')
33
+ body.gsub!(/>\s+/m, '>')
34
+ body.gsub!(/<(\w+?)>([^<]+)/m, '<\1>\2</\1>')
35
+ end
36
+ doc = ::Nokogiri::XML(body)
37
+
38
+ parser.new(doc, strict).parse
32
39
  end
33
40
 
34
41
  def parser
@@ -1,30 +1,50 @@
1
1
  module OFXReader
2
2
  module Parser
3
- class OFX102 < Struct.new(:ofx_body)
3
+ class OFX102 < Struct.new(:ofx_body, :strict)
4
4
  def parse
5
+ raise OFXReader::OFXWithoutBankAccountError if empty_account?
5
6
  [account, transactions]
6
7
  end
7
8
 
8
9
  def account
9
- {
10
- bank_id: ofx_body.search('BANKACCTFROM BANKID').inner_text,
11
- account_id: ofx_body.search('BANKACCTFROM ACCTID').inner_text,
12
- }
10
+ build_account(
11
+ build(ofx_body.search('BANKACCTFROM'))
12
+ )
13
+ end
14
+
15
+ def build_account(hash)
16
+ full_account = [
17
+ hash.dig(:branchid),
18
+ hash.dig(:acctid)
19
+ ].compact.join(' - ')
20
+
21
+ hash.merge!({
22
+ full_account: full_account
23
+ }) if hash.dig(:acctid).present?
24
+
25
+ hash
13
26
  end
14
27
 
15
28
  def transactions
16
29
  ofx_body.search('BANKTRANLIST STMTTRN').map do |node|
17
- build_transaction(node)
30
+ build(node)
18
31
  end
19
32
  end
20
33
 
21
34
  private
22
35
 
23
- def build_transaction(node)
36
+ def build(node)
24
37
  node.children.map.with_object({}) do |field, hash|
25
- hash[field.name.downcase.to_sym] = field.text
38
+ # Avoid Nokogiri::XML::Text
39
+ if field.is_a?(Nokogiri::XML::Element)
40
+ hash[field.name.downcase.to_sym] = field.text
41
+ end
26
42
  end
27
43
  end
44
+
45
+ def empty_account?
46
+ (account.dig(:bankid).blank? && account.dig(:acctid).blank?) && strict
47
+ end
28
48
  end
29
49
  end
30
50
  end
@@ -1,3 +1,3 @@
1
1
  module OFXReader
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
data/lib/ofx_reader.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "ofx_reader/version"
2
+ require "active_support/core_ext/object"
2
3
 
3
4
  begin
4
5
  require "pry"
@@ -6,6 +7,7 @@ rescue LoadError
6
7
  end
7
8
 
8
9
  require "ofx_reader/errors/unsupported_ofx_version_error"
10
+ require "ofx_reader/errors/ofx_without_bank_account_error"
9
11
  require "ofx_reader/parser/base"
10
12
  require "ofx_reader/parser/ofx_102"
11
13
 
@@ -25,7 +27,7 @@ module OFXReader
25
27
  # 'REPEATPMT', 'SRVCHG', 'XFER',
26
28
  # ]
27
29
 
28
- def self.call(ofx_text)
29
- OFXReader::Parser::Base.new(ofx_text)
30
+ def self.call(ofx_text, strict: false)
31
+ OFXReader::Parser::Base.new(ofx_text, strict: strict)
30
32
  end
31
33
  end
data/ofx_reader.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "nokogiri", "~> 1.8"
22
+ spec.add_dependency "activesupport", "> 4"
22
23
  spec.add_development_dependency "bundler", "~> 1.16"
23
24
  spec.add_development_dependency "rake", "~> 10.0"
24
25
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ofx_reader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francisco Martins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-14 00:00:00.000000000 Z
11
+ date: 2017-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -99,6 +113,7 @@ files:
99
113
  - bin/setup
100
114
  - exe/ofx_reader
101
115
  - lib/ofx_reader.rb
116
+ - lib/ofx_reader/errors/ofx_without_bank_account_error.rb
102
117
  - lib/ofx_reader/errors/unsupported_ofx_version_error.rb
103
118
  - lib/ofx_reader/parser/base.rb
104
119
  - lib/ofx_reader/parser/ofx_102.rb