salt-parser 0.0.1
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +88 -0
- data/README.rdoc +39 -0
- data/Rakefile +7 -0
- data/lib/ofx/account.rb +28 -0
- data/lib/ofx/accounts.rb +9 -0
- data/lib/ofx/balance.rb +15 -0
- data/lib/ofx/builder.rb +61 -0
- data/lib/ofx/dependencies.rb +13 -0
- data/lib/ofx/parser/base.rb +366 -0
- data/lib/ofx/parser/ofx102.rb +28 -0
- data/lib/ofx/parser/ofx211.rb +21 -0
- data/lib/ofx/sign_on.rb +18 -0
- data/lib/ofx/transaction.rb +28 -0
- data/lib/qif/account.rb +19 -0
- data/lib/qif/accounts.rb +54 -0
- data/lib/qif/builder.rb +37 -0
- data/lib/qif/dependencies.rb +8 -0
- data/lib/qif/parser.rb +68 -0
- data/lib/qif/transaction.rb +28 -0
- data/lib/salt-parser/accounts.rb +11 -0
- data/lib/salt-parser/base.rb +19 -0
- data/lib/salt-parser/builder.rb +24 -0
- data/lib/salt-parser/errors.rb +14 -0
- data/lib/salt-parser/version.rb +8 -0
- data/salt-parser.gemspec +24 -0
- data/spec/ofx/account_spec.rb +97 -0
- data/spec/ofx/accounts_response_spec.rb +45 -0
- data/spec/ofx/accounts_spec.rb +34 -0
- data/spec/ofx/balance_spec.rb +32 -0
- data/spec/ofx/builder_spec.rb +136 -0
- data/spec/ofx/error_request_spec.rb +37 -0
- data/spec/ofx/fixtures/accounts_partial.ofx +52 -0
- data/spec/ofx/fixtures/accounts_request.ofx +11 -0
- data/spec/ofx/fixtures/accounts_response.ofx +109 -0
- data/spec/ofx/fixtures/avatar.gif +0 -0
- data/spec/ofx/fixtures/bb.ofx +700 -0
- data/spec/ofx/fixtures/credit_card_response.ofx +52 -0
- data/spec/ofx/fixtures/creditcard.ofx +79 -0
- data/spec/ofx/fixtures/creditcard_transactions_request.ofx +11 -0
- data/spec/ofx/fixtures/creditcards_partial.ofx +85 -0
- data/spec/ofx/fixtures/date_missing.ofx +73 -0
- data/spec/ofx/fixtures/empty_balance.ofx +44 -0
- data/spec/ofx/fixtures/invalid_version.ofx +308 -0
- data/spec/ofx/fixtures/investment_transactions_response.ofx +108 -0
- data/spec/ofx/fixtures/investment_transactions_response2.ofx +200 -0
- data/spec/ofx/fixtures/investments_with_mkval.ofx +99 -0
- data/spec/ofx/fixtures/missing_headers.ofx +47 -0
- data/spec/ofx/fixtures/mixed_accountinfo_response.ofx +58 -0
- data/spec/ofx/fixtures/ms_money.ofx +52 -0
- data/spec/ofx/fixtures/request_error.ofx +39 -0
- data/spec/ofx/fixtures/request_error2.ofx +39 -0
- data/spec/ofx/fixtures/request_error3.ofx +36 -0
- data/spec/ofx/fixtures/sample_examples/sample_401K_loan.qfx +651 -0
- data/spec/ofx/fixtures/sample_examples/sample_banking.qbo +258 -0
- data/spec/ofx/fixtures/sample_examples/sample_banking.qfx +258 -0
- data/spec/ofx/fixtures/sample_examples/sample_banking_multiacct.qfx +284 -0
- data/spec/ofx/fixtures/sample_examples/sample_credit_card.qfx +257 -0
- data/spec/ofx/fixtures/sample_examples/sample_investment.qfx +654 -0
- data/spec/ofx/fixtures/transactions_empty.ofx +60 -0
- data/spec/ofx/fixtures/utf8.ofx +65 -0
- data/spec/ofx/fixtures/v102.ofx +314 -0
- data/spec/ofx/fixtures/v202.ofx +22 -0
- data/spec/ofx/fixtures/v211.ofx +85 -0
- data/spec/ofx/investment_accounts_spec.rb +70 -0
- data/spec/ofx/ofx102_spec.rb +44 -0
- data/spec/ofx/ofx211_spec.rb +68 -0
- data/spec/ofx/ofx_parser_spec.rb +100 -0
- data/spec/ofx/sign_on_spec.rb +49 -0
- data/spec/ofx/transaction_spec.rb +157 -0
- data/spec/qif/account_spec.rb +42 -0
- data/spec/qif/fixtures/3_records_ddmmyy.qif +19 -0
- data/spec/qif/fixtures/3_records_ddmmyyyy.qif +19 -0
- data/spec/qif/fixtures/3_records_dmyy.qif +19 -0
- data/spec/qif/fixtures/3_records_invalid_header.qif +20 -0
- data/spec/qif/fixtures/3_records_mdyy.qif +19 -0
- data/spec/qif/fixtures/3_records_mmddyy.qif +19 -0
- data/spec/qif/fixtures/3_records_mmddyyyy.qif +19 -0
- data/spec/qif/fixtures/3_records_spaced.qif +19 -0
- data/spec/qif/fixtures/bank_account.qif +19 -0
- data/spec/qif/fixtures/empty_body.qif +1 -0
- data/spec/qif/fixtures/empty_header.qif +18 -0
- data/spec/qif/fixtures/incompatible_date_formats.qif +13 -0
- data/spec/qif/fixtures/invalid_date_format.qif +7 -0
- data/spec/qif/fixtures/not_a_QIF_file.txt +3 -0
- data/spec/qif/fixtures/quicken_non_investement_account.qif +30 -0
- data/spec/qif/fixtures/unknown_account.qif +20 -0
- data/spec/qif/fixtures/various_date_format.qif +19 -0
- data/spec/qif/fixtures/with_categories_list.qif +8669 -0
- data/spec/qif/parser_spec.rb +156 -0
- data/spec/qif/transaction_spec.rb +18 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/fixture.rb +9 -0
- metadata +208 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Ofx
|
3
|
+
module Parser
|
4
|
+
class OFX102 < SaltParser::Ofx::Parser::Base
|
5
|
+
VERSION = "1.0.2"
|
6
|
+
|
7
|
+
def self.parse_headers(header_text)
|
8
|
+
# TODO: refactor
|
9
|
+
# Change single CR's to LF's to avoid issues with some banks
|
10
|
+
header_text.gsub!(/\r(?!\n)/, "\n")
|
11
|
+
|
12
|
+
# Parse headers. When value is NONE, convert it to nil.
|
13
|
+
headers = header_text.to_enum(:each_line).inject({}) do |memo, line|
|
14
|
+
_, key, value = *line.match(/^(.*?):(.*?)\s*(\r?\n)*$/)
|
15
|
+
|
16
|
+
unless key.nil?
|
17
|
+
memo[key] = value == "NONE" ? nil : value
|
18
|
+
end
|
19
|
+
|
20
|
+
memo
|
21
|
+
end
|
22
|
+
|
23
|
+
return headers unless headers.empty?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Ofx
|
3
|
+
module Parser
|
4
|
+
class OFX211 < SaltParser::Ofx::Parser::Base
|
5
|
+
VERSION = "2.1.1"
|
6
|
+
|
7
|
+
def self.parse_headers(header_text)
|
8
|
+
Nokogiri::XML(header_text).children.each do |element|
|
9
|
+
if element.name == "OFX"
|
10
|
+
headers = element.text.gsub("\"",'')
|
11
|
+
.split(/\s+/)
|
12
|
+
.map { |el| el.split("=") }
|
13
|
+
.flatten
|
14
|
+
return Hash[*headers]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/ofx/sign_on.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Ofx
|
3
|
+
class SignOn < SaltParser::Base
|
4
|
+
attr_accessor :language, :fi_id, :fi_name, :code, :severity, :message
|
5
|
+
|
6
|
+
def to_hash
|
7
|
+
{
|
8
|
+
:language => language,
|
9
|
+
:fi_id => fi_id,
|
10
|
+
:fi_name => fi_name,
|
11
|
+
:code => code,
|
12
|
+
:severity => severity,
|
13
|
+
:message => message
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Ofx
|
3
|
+
class Transaction < SaltParser::Base
|
4
|
+
attr_accessor :amount, :amount_in_pennies, :check_number, :fit_id,
|
5
|
+
:memo, :name, :payee, :posted_at, :ref_number, :type,
|
6
|
+
:sic, :units, :unit_price, :account_id
|
7
|
+
|
8
|
+
def to_hash
|
9
|
+
{
|
10
|
+
:amount => amount,
|
11
|
+
:amount_in_pennies => amount_in_pennies,
|
12
|
+
:check_number => check_number,
|
13
|
+
:fit_id => fit_id,
|
14
|
+
:memo => memo,
|
15
|
+
:name => name,
|
16
|
+
:payee => payee,
|
17
|
+
:posted_at => posted_at,
|
18
|
+
:ref_number => ref_number,
|
19
|
+
:type => type,
|
20
|
+
:sic => sic,
|
21
|
+
:units => units,
|
22
|
+
:unit_price => unit_price,
|
23
|
+
:account_id => account_id
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/qif/account.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Qif
|
3
|
+
class Account < SaltParser::Base
|
4
|
+
attr_accessor :name, :type, :transactions
|
5
|
+
|
6
|
+
def identifier
|
7
|
+
name
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_hash
|
11
|
+
{
|
12
|
+
:name => name,
|
13
|
+
:type => type,
|
14
|
+
:transactions => transactions.map(&:to_hash)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/qif/accounts.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Qif
|
3
|
+
class Accounts < SaltParser::Accounts
|
4
|
+
SUPPORTED_ACCOUNTS = {
|
5
|
+
"!Type:Bank" => {
|
6
|
+
"type" => "bank_account",
|
7
|
+
"name" => "Bank account"
|
8
|
+
},
|
9
|
+
"!Type:Cash" => {
|
10
|
+
"type" => "cash",
|
11
|
+
"name" => "Cash account"
|
12
|
+
},
|
13
|
+
"!Type:CCard" => {
|
14
|
+
"type" => "credit_card",
|
15
|
+
"name" => "Credit card account"
|
16
|
+
},
|
17
|
+
"!Type:Oth A" => {
|
18
|
+
"type" => "asset",
|
19
|
+
"name" => "Asset account"
|
20
|
+
},
|
21
|
+
"!Type:Oth L" => {
|
22
|
+
"type" => "liability_account",
|
23
|
+
"name" => "Liability account"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
SUPPORTED_ACCOUNTS.default = {
|
27
|
+
"type" => "account",
|
28
|
+
"name" => "account"
|
29
|
+
}
|
30
|
+
NOT_SUPPORTED_ACCOUNTS = {
|
31
|
+
"!Account" => {
|
32
|
+
"type" => "account_list",
|
33
|
+
"name" => "Account list or which account follows"
|
34
|
+
},
|
35
|
+
"!Type:Cat" => {
|
36
|
+
"type" => "category_list",
|
37
|
+
"name" => "Category list"
|
38
|
+
},
|
39
|
+
"!Type:Class" => {
|
40
|
+
"type" => "class_list",
|
41
|
+
"name" => "Class list"
|
42
|
+
},
|
43
|
+
"!Type:Memorized" => {
|
44
|
+
"type" => "memorized_transaction_list",
|
45
|
+
"name" => "Memorized transaction list"
|
46
|
+
},
|
47
|
+
"!Type:Invoice" => {
|
48
|
+
"type" => "invoice",
|
49
|
+
"name" => "Invoice (Quicken for Business only)"
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/qif/builder.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Qif
|
3
|
+
class Builder < SaltParser::Builder
|
4
|
+
|
5
|
+
def initialize(resource, date_format="%m/%d/%Y")
|
6
|
+
resource = open_resource(resource)
|
7
|
+
resource.rewind
|
8
|
+
|
9
|
+
@content = convert_to_utf8(resource.read)
|
10
|
+
prepare(content)
|
11
|
+
|
12
|
+
@parser = Parser.new(:headers => headers, :body => body, :date_format => date_format)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def prepare(content)
|
18
|
+
# ignore internal Quicken information
|
19
|
+
# http://en.wikipedia.org/wiki/Quicken_Interchange_Format#Header_line
|
20
|
+
split_content = content.split(/(^!.+)/).reject(&:blank?).map(&:strip)
|
21
|
+
split_content.each_slice(2) do |slice|
|
22
|
+
if slice.length == 1
|
23
|
+
@body = slice.first
|
24
|
+
else
|
25
|
+
next if Qif::Accounts::NOT_SUPPORTED_ACCOUNTS.keys.include?(slice.first)
|
26
|
+
@headers = slice.first
|
27
|
+
@body = slice.last
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if body.nil? or body.match(/(^!.+)/)
|
32
|
+
raise SaltParser::Error::EmptyFileBody
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/qif/parser.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Qif
|
3
|
+
class Parser
|
4
|
+
attr_reader :headers, :body, :accounts, :date_format
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@headers = options[:headers].try(:chomp)
|
8
|
+
@body = options[:body]
|
9
|
+
@date_format = options[:date_format]
|
10
|
+
@accounts = Qif::Accounts.new
|
11
|
+
parse_account
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
{ :accounts => accounts.to_hash }
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_account
|
19
|
+
@accounts << Qif::Account.new({
|
20
|
+
:name => Qif::Accounts::SUPPORTED_ACCOUNTS[headers]["name"],
|
21
|
+
:type => Qif::Accounts::SUPPORTED_ACCOUNTS[headers]["type"],
|
22
|
+
:transactions => build_transactions
|
23
|
+
})
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_transactions
|
27
|
+
transactions_array = body.split("^").reject(&:blank?)
|
28
|
+
check_dates(transactions_array)
|
29
|
+
|
30
|
+
transactions_array.each_with_object([]) do |transaction, transactions|
|
31
|
+
transaction_hash = build_transaction_hash(transaction.split("\n"))
|
32
|
+
transactions << Qif::Transaction.new(transaction_hash) unless transaction_hash.empty?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_transaction_hash(rows)
|
37
|
+
hash = {}
|
38
|
+
rows.map do |row|
|
39
|
+
type = Qif::Transaction::SUPPORTED_FIELDS[row[0].try(:upcase)]
|
40
|
+
next unless type
|
41
|
+
hash[type] = type == :date ? parse_date(row[1..-1]) : row[1..-1].strip
|
42
|
+
end
|
43
|
+
hash[:date].nil? ? {} : hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_date(row)
|
47
|
+
date = Date.strptime(row, date_format)
|
48
|
+
raise ArgumentError if date.year < 1900
|
49
|
+
date.as_json
|
50
|
+
rescue ArgumentError => error
|
51
|
+
Chronic.parse(row, :endian_precedence => [:middle, :little]).to_date.as_json
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_dates(transactions_array)
|
55
|
+
dates = transactions_array.map{ |transaction| transaction.split("\n") }
|
56
|
+
.flatten
|
57
|
+
.select{ |line| line.match(/^D/) }
|
58
|
+
.map{ |line| line[1..-1] }
|
59
|
+
|
60
|
+
dates.each do |row|
|
61
|
+
unless Chronic.parse(row)
|
62
|
+
raise SaltParser::Error::UnsupportedDateFormat.new
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Qif
|
3
|
+
class Transaction < SaltParser::Base
|
4
|
+
SUPPORTED_FIELDS = {
|
5
|
+
"D" => :date , # Date
|
6
|
+
"T" => :amount , # Amount
|
7
|
+
"C" => :status , # Cleared status
|
8
|
+
"N" => :number , # Num (check or reference number)
|
9
|
+
"P" => :payee , # Payee
|
10
|
+
"M" => :memo , # Memo
|
11
|
+
"L" => :category # Category (Category/Subcategory/Transfer/Class)
|
12
|
+
}
|
13
|
+
SUPPORTED_FIELDS.values.each{ |field| attr_accessor field }
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
{
|
17
|
+
:date => date,
|
18
|
+
:amount => amount,
|
19
|
+
:status => status,
|
20
|
+
:number => number,
|
21
|
+
:payee => payee,
|
22
|
+
:memo => memo,
|
23
|
+
:category => category
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext"
|
3
|
+
|
4
|
+
module SaltParser
|
5
|
+
class Base
|
6
|
+
def initialize(attrs)
|
7
|
+
attrs.each do |key, value|
|
8
|
+
send("#{key}=", value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require_relative "accounts"
|
15
|
+
require_relative "errors"
|
16
|
+
require_relative "builder"
|
17
|
+
|
18
|
+
require "ofx/dependencies"
|
19
|
+
require "qif/dependencies"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SaltParser
|
2
|
+
class Builder
|
3
|
+
attr_reader :headers, :body, :content, :parser
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def open_resource(resource)
|
8
|
+
if resource.respond_to?(:read)
|
9
|
+
resource
|
10
|
+
else
|
11
|
+
open(resource)
|
12
|
+
end
|
13
|
+
rescue Exception
|
14
|
+
StringIO.new(resource)
|
15
|
+
end
|
16
|
+
|
17
|
+
def convert_to_utf8(string)
|
18
|
+
return string if Kconv.isutf8(string)
|
19
|
+
string.encode(Encoding::UTF_8.to_s, Encoding::ISO_8859_1.to_s)
|
20
|
+
rescue Exception
|
21
|
+
raise SaltParser::Error::InvalidEncoding
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SaltParser
|
2
|
+
module Error
|
3
|
+
class EmptyFileBody < StandardError; end
|
4
|
+
class InvalidEncoding < StandardError; end
|
5
|
+
class ParseError < StandardError
|
6
|
+
AMOUNT = "Error while parsing numeric field."
|
7
|
+
TIME = "Error while parsing time field."
|
8
|
+
FLOAT = "Error while parsing float field."
|
9
|
+
end
|
10
|
+
class RequestError < StandardError; end
|
11
|
+
class UnsupportedDateFormat < StandardError; end
|
12
|
+
class UnsupportedFileError < StandardError; end
|
13
|
+
end
|
14
|
+
end
|
data/salt-parser.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "salt-parser/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "salt-parser"
|
7
|
+
s.version = SaltParser::Version::STRING
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["saltedge team"]
|
10
|
+
s.email = ["support@saltedge.com"]
|
11
|
+
s.homepage = "http://example.com"
|
12
|
+
s.summary = "Gem for parsing OFX, HBCI, QIF and SWIFT formats."
|
13
|
+
s.description = "Gem for parsing OFX, HBCI, QIF and SWIFT formats."
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |file| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency "nokogiri"
|
20
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
21
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "pry-byebug"
|
24
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SaltParser::Ofx::Account do
|
4
|
+
let(:ofx) { SaltParser::Ofx::Builder.new("spec/ofx/fixtures/v102.ofx") }
|
5
|
+
let(:parser) { ofx.parser }
|
6
|
+
let(:account) { parser.accounts.first }
|
7
|
+
let(:hash) { account.to_hash }
|
8
|
+
|
9
|
+
describe "account" do
|
10
|
+
context "Bank account" do
|
11
|
+
it "should return currency" do
|
12
|
+
account.currency.should == "BRL"
|
13
|
+
hash[:currency].should == account.currency
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return bank id" do
|
17
|
+
account.bank_id.should == "0356"
|
18
|
+
hash[:bank_id].should == account.bank_id
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return id" do
|
22
|
+
account.id.should == "03227113109"
|
23
|
+
hash[:id].should == account.id
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return type" do
|
27
|
+
account.type.should == :checking
|
28
|
+
hash[:type].should == account.type
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return transactions" do
|
32
|
+
account.transactions.should be_a_kind_of(Array)
|
33
|
+
account.transactions.size.should == 36
|
34
|
+
hash[:transactions].should be_a_kind_of(Array)
|
35
|
+
hash[:transactions].size.should == account.transactions.size
|
36
|
+
hash[:transactions].first.should == account.transactions.first.to_hash
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return balance" do
|
40
|
+
account.balance.amount.should == 598.44
|
41
|
+
hash[:balance][:amount].should == account.balance.amount
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return balance in pennies" do
|
45
|
+
account.balance.amount_in_pennies.should == 59844
|
46
|
+
hash[:balance][:amount_in_pennies].should == account.balance.amount_in_pennies
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return balance date" do
|
50
|
+
account.balance.posted_at.should == Time.parse("2009-11-01")
|
51
|
+
hash[:balance][:posted_at].should == Time.parse("2009-11-01")
|
52
|
+
end
|
53
|
+
|
54
|
+
context "available_balance" do
|
55
|
+
it "should return available balance" do
|
56
|
+
account.available_balance.amount.should == 1555.99
|
57
|
+
hash[:available_balance][:amount].should == account.available_balance.amount
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return available balance in pennies" do
|
61
|
+
account.available_balance.amount_in_pennies.should == 155599
|
62
|
+
hash[:available_balance][:amount_in_pennies].should == account.available_balance.amount_in_pennies
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return available balance date" do
|
66
|
+
account.available_balance.posted_at.should == Time.parse("2009-11-01")
|
67
|
+
hash[:available_balance][:posted_at].should == account.available_balance.posted_at
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return nil if AVAILBAL not found" do
|
71
|
+
ofx = SaltParser::Ofx::Builder.new("spec/ofx/fixtures/utf8.ofx")
|
72
|
+
account = ofx.parser.accounts.first
|
73
|
+
account.available_balance.should be_nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "Credit Card" do
|
79
|
+
let(:ofx) { SaltParser::Ofx::Builder.new("spec/ofx/fixtures/v211.ofx") }
|
80
|
+
let(:account) { parser.accounts.last }
|
81
|
+
|
82
|
+
it "should return id" do
|
83
|
+
account.id.should == "123412341234"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return currency" do
|
87
|
+
account.currency.should == "USD"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "#to_hash" do
|
92
|
+
it "should return Hash" do
|
93
|
+
hash.should be_a_kind_of(Hash)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Bank accounts response" do
|
4
|
+
let(:ofx) { SaltParser::Ofx::Builder.new("spec/ofx/fixtures/accounts_response.ofx") }
|
5
|
+
let(:parser) { ofx.parser }
|
6
|
+
let(:accounts) { parser.accounts }
|
7
|
+
|
8
|
+
describe "accounts" do
|
9
|
+
it "should parse bank account from bank response" do
|
10
|
+
accounts.size.should == 5
|
11
|
+
accounts.first.to_hash.should == {
|
12
|
+
:bank_id => "123456789",
|
13
|
+
:id => "1234567890",
|
14
|
+
:name => "SILVERWIZ SAVINGS",
|
15
|
+
:broker_id => nil,
|
16
|
+
:type => :savings,
|
17
|
+
:units => nil,
|
18
|
+
:unit_price => nil,
|
19
|
+
:currency => "",
|
20
|
+
:balance => nil,
|
21
|
+
:transactions => [],
|
22
|
+
:available_balance => nil
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "sign_on" do
|
28
|
+
it "should parse sign_on data from bank response" do
|
29
|
+
parser.sign_on.to_hash.should == {
|
30
|
+
:language => "ENG",
|
31
|
+
:fi_id => "10898",
|
32
|
+
:fi_name => "B1",
|
33
|
+
:code => "0",
|
34
|
+
:severity => "INFO",
|
35
|
+
:message => "SUCCESS"
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "errors" do
|
41
|
+
it "should not have any errors" do
|
42
|
+
parser.errors.size.should be_zero
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SaltParser::Ofx::Accounts do
|
4
|
+
let(:ofx) { SaltParser::Ofx::Builder.new("spec/ofx/fixtures/v211.ofx") }
|
5
|
+
let(:accounts) { ofx.parser.accounts }
|
6
|
+
let(:hash) { accounts.to_hash }
|
7
|
+
|
8
|
+
describe "accounts" do
|
9
|
+
it "should return multiple accounts" do
|
10
|
+
accounts.size.should == 2
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#find" do
|
14
|
+
it "returns first by id" do
|
15
|
+
accounts.find("123456").class.should == SaltParser::Ofx::Account
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#find_by_transaction" do
|
20
|
+
it "returns first by transaction's account_id and it's currency code" do
|
21
|
+
account = accounts.first
|
22
|
+
transaction = account.transactions.first
|
23
|
+
accounts.find_by_transaction(transaction).should == account
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#to_hash" do
|
28
|
+
it "should return array of Hashes" do
|
29
|
+
hash.should be_a_kind_of(Array)
|
30
|
+
hash.first.should be_a_kind_of(Hash)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SaltParser::Ofx::Balance do
|
4
|
+
let(:ofx) { SaltParser::Ofx::Builder.new("spec/ofx/fixtures/v102.ofx") }
|
5
|
+
let(:parser) { ofx.parser }
|
6
|
+
let(:account) { parser.accounts.first }
|
7
|
+
let(:balance) { account.balance }
|
8
|
+
let(:hash) { balance.to_hash }
|
9
|
+
|
10
|
+
describe "balance" do
|
11
|
+
it "should return amount" do
|
12
|
+
balance.amount.should == 598.44
|
13
|
+
hash[:amount].should == balance.amount
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return amount_in_pennies" do
|
17
|
+
balance.amount_in_pennies.should == 59844
|
18
|
+
hash[:amount_in_pennies].should == balance.amount_in_pennies
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return posted_at" do
|
22
|
+
balance.posted_at.should == Time.parse("2009-11-01")
|
23
|
+
hash[:posted_at].should == balance.posted_at
|
24
|
+
end
|
25
|
+
|
26
|
+
context "#to_hash" do
|
27
|
+
it "should return Hash" do
|
28
|
+
hash.should be_a_kind_of(Hash)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|