From 10fa8c63cb12fc5861464e7698715b8b42d3984d Mon Sep 17 00:00:00 2001 From: David Lindes Date: Wed, 29 Dec 2021 17:50:34 -0800 Subject: [PATCH 1/3] Parser#initialize: read file when filename given It seems natural to pass a filename to initialize, so if whatever we're given is a file that exists, read its contents instead of using it as string data directly. (It occurs to me that we may want to duplicate the string otherwise, but I'm unsure what other use cases might be present that I'm not thinking of, so I'm leaving that out for now.) Fixes #2 Note: Chosing to bump version to 0.2.2 because rubygems has a 0.2.1 from somewhere that I couldn't find. This change technically Copyright 2021 by David Lindes, and I agree to license it under the same terms as the rest of this repository. --- lib/quicken_parser/parser.rb | 3 ++- lib/quicken_parser/version.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/quicken_parser/parser.rb b/lib/quicken_parser/parser.rb index d94c517..e95053c 100644 --- a/lib/quicken_parser/parser.rb +++ b/lib/quicken_parser/parser.rb @@ -4,7 +4,8 @@ module QuickenParser class Parser #:nodoc: def initialize(source) - @input = source.respond_to?(:read) ? source.read : source + @input = source.respond_to?(:read) ? source.read : + File.exists?(source) ? File.open(source).read : source end def parse diff --git a/lib/quicken_parser/version.rb b/lib/quicken_parser/version.rb index 2965990..59c9725 100644 --- a/lib/quicken_parser/version.rb +++ b/lib/quicken_parser/version.rb @@ -1,3 +1,3 @@ module QuickenParser - VERSION = "0.2.0" + VERSION = "0.2.2" end From b53ec2a77f19f5998d7f0612aa9f03b4a5115de0 Mon Sep 17 00:00:00 2001 From: David Lindes Date: Wed, 19 Jan 2022 17:50:11 -0800 Subject: [PATCH 2/3] removed obsolete has_rdoc from gemspec --- quicken_parser.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/quicken_parser.gemspec b/quicken_parser.gemspec index 50d0a1d..282ed81 100644 --- a/quicken_parser.gemspec +++ b/quicken_parser.gemspec @@ -13,7 +13,6 @@ Gem::Specification.new do |s| s.email = %q{francois@teksol.info} s.extra_rdoc_files = ["README", "LICENSE", "TODO"] s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/quicken_parser", "lib/quicken_parser/account.rb", "lib/quicken_parser/parser.rb", "lib/quicken_parser/transaction.rb", "lib/quicken_parser/transactions.rb", "lib/quicken_parser.rb", "test/account_test.rb", "test/fixtures", "test/fixtures/no_memo.txt", "test/fixtures/one_account.txt", "test/fixtures/one_cc.txt", "test/fixtures/two_accounts.txt", "test/money_test.rb", "test/parser_test.rb", "test/test_helper.rb", "test/transaction_test.rb", "test/transactions_test.rb"] - s.has_rdoc = true s.homepage = %q{http://github.com/francois/quicken_parser} s.require_paths = ["lib"] s.rubygems_version = %q{1.3.2} From e7069f735d01cf75e080cf6c5e1044b8aba2df6a Mon Sep 17 00:00:00 2001 From: David Lindes Date: Wed, 19 Jan 2022 18:00:58 -0800 Subject: [PATCH 3/3] added new metadata api This allows access to some additional information in the file, like the date that it was reported to have been generated. To accomodate this, QuickenParser::parser has been added, which is just like the old QuickenParser::parse (which still exists, with unchanged semantics), except that instead of returning the Parser#accounts array, it returns the Parser object itself, which one can then call #accounts and/or #metadata on as one pleases. --- lib/quicken_parser.rb | 11 ++++++++++- lib/quicken_parser/parser.rb | 27 +++++++++++++++++++++++++++ lib/quicken_parser/version.rb | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/quicken_parser.rb b/lib/quicken_parser.rb index 23eb8b4..b28d373 100644 --- a/lib/quicken_parser.rb +++ b/lib/quicken_parser.rb @@ -5,7 +5,16 @@ require "money" module QuickenParser + # New API (in version 0.3.0), to allow direct access to the Parser + # object, which (now) has other (potentially) useful methods than just + # #accounts (notably: #metadata): + def self.parser(stream_or_string) + Parser.new(stream_or_string).parse + end + + # For backwards compatability, we still provide a version (by the + # original name) that gives #accounts back: def self.parse(stream_or_string) - Parser.new(stream_or_string).parse.accounts + parser(stream_or_string).accounts end end diff --git a/lib/quicken_parser/parser.rb b/lib/quicken_parser/parser.rb index e95053c..67ffbf7 100644 --- a/lib/quicken_parser/parser.rb +++ b/lib/quicken_parser/parser.rb @@ -32,6 +32,33 @@ def accounts @accounts end + def metadata + # Note: I expect only one of these: + REXML::XPath.each(@doc.root, "//SONRS") do |xml| + @metadata = metadata_from_xml(xml) + end + @metadata + end + + def metadata_from_xml(xml) + # https://schemas.liquid-technologies.com/ofx/2.1.1/?page=sonrs.html + { + status: { + code: REXML::XPath.first(xml, ".//STATUS/CODE").text, + severity: REXML::XPath.first(xml, ".//STATUS/SEVERITY").text, + }, + server_date: Time.parse(REXML::XPath.first(xml, ".//DTSERVER").text + "Z"), + lang: REXML::XPath.first(xml, ".//LANGUAGE").text, + profile_date: Time.parse(REXML::XPath.first(xml, ".//DTPROFUP").text + "Z"), + financial_institution: { + name: REXML::XPath.first(xml, ".//FI/ORG").text, + id: REXML::XPath.first(xml, ".//FI/FID").text, + }, + # Not in the above-linked spec, but seen in a QFX file: + user: REXML::XPath.first(xml, ".//INTU.USERID").text, + } + end + def cc_account_from_xml(xml) currency = REXML::XPath.first(xml, ".//CURDEF").text bank_id = nil diff --git a/lib/quicken_parser/version.rb b/lib/quicken_parser/version.rb index 59c9725..9ed6f65 100644 --- a/lib/quicken_parser/version.rb +++ b/lib/quicken_parser/version.rb @@ -1,3 +1,3 @@ module QuickenParser - VERSION = "0.2.2" + VERSION = "0.3.0" end