gnucash 1.0.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.
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +23 -0
- data/gnucash.gemspec +27 -0
- data/lib/gnucash.rb +17 -0
- data/lib/gnucash/account.rb +91 -0
- data/lib/gnucash/account_transaction.rb +23 -0
- data/lib/gnucash/book.rb +84 -0
- data/lib/gnucash/transaction.rb +41 -0
- data/lib/gnucash/value.rb +97 -0
- data/lib/gnucash/version.rb +4 -0
- data/spec/books/sample-text.gnucash +30246 -0
- data/spec/books/sample.gnucash +0 -0
- data/spec/gnucash/account_spec.rb +40 -0
- data/spec/gnucash/book_spec.rb +39 -0
- data/spec/gnucash/transaction_spec.rb +38 -0
- data/spec/gnucash/value_spec.rb +96 -0
- data/spec/gnucash_spec.rb +12 -0
- data/spec/spec_helper.rb +5 -0
- metadata +172 -0
Binary file
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gnucash
|
2
|
+
describe Account do
|
3
|
+
before(:all) do
|
4
|
+
# just read the file once
|
5
|
+
@book = Gnucash.open("spec/books/sample.gnucash")
|
6
|
+
@checking = @book.find_account_by_full_name("Assets::Current Assets::Checking Account")
|
7
|
+
@salary = @book.find_account_by_full_name("Income::Salary")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "gives access to the account name" do
|
11
|
+
@salary.name.should == "Salary"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "gives access to the fully-qualified account name" do
|
15
|
+
@checking.full_name.should == "Assets::Current Assets::Checking Account"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "gives access to the final balance" do
|
19
|
+
@checking.final_balance.should == Value.new(19743000)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.balance_on' do
|
23
|
+
it "returns 0 if the given date is before the account's first transaction" do
|
24
|
+
@checking.balance_on("2006-12-12").should == Value.new(0)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns the final balance if the given date is after the account's last transaction" do
|
28
|
+
@checking.balance_on("2013-10-10").should == @checking.final_balance
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns the balance on the given date" do
|
32
|
+
@checking.balance_on("2012-12-25").should == Value.new(19688000)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "includes transactions that occur on the given date" do
|
36
|
+
@checking.balance_on("2007-03-27").should == Value.new(780000)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Gnucash
|
2
|
+
describe Book do
|
3
|
+
context "with errors" do
|
4
|
+
it "raises an error for unexpected XML" do
|
5
|
+
gr = "gr"
|
6
|
+
Zlib::GzipReader.should_receive(:open).and_return(gr)
|
7
|
+
gr.should_receive(:read).and_return(nil)
|
8
|
+
ng = "ng"
|
9
|
+
Nokogiri.should_receive(:XML).and_return(ng)
|
10
|
+
ng.should_receive(:xpath).with('/gnc-v2/gnc:book').and_return([])
|
11
|
+
|
12
|
+
expect { Gnucash::Book.new('file name') }.to raise_error "Error: Expected to find one gnc:book entry"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "without errors" do
|
17
|
+
before(:all) do
|
18
|
+
# just open the test file once
|
19
|
+
@subject = Gnucash.open("spec/books/sample.gnucash")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "records the date of the earliest transaction" do
|
23
|
+
@subject.start_date.should == "2007-01-01"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "records the date of the last transaction" do
|
27
|
+
@subject.end_date.should == "2012-12-28"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "lets you find an account by id" do
|
31
|
+
@subject.find_account_by_id("67e6e7daadc35716eb6152769373e974").name.should == "Savings Account"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "lets you find an account by full name" do
|
35
|
+
@subject.find_account_by_full_name("Assets::Current Assets::Savings Account").id.should == "67e6e7daadc35716eb6152769373e974"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gnucash
|
2
|
+
describe Transaction do
|
3
|
+
context "with errors" do
|
4
|
+
it "raises an error for unexpected XML" do
|
5
|
+
book = "book"
|
6
|
+
node = "node"
|
7
|
+
text = "text"
|
8
|
+
split_node = "split_node"
|
9
|
+
value_text = "value_text"
|
10
|
+
account_text = "account_text"
|
11
|
+
|
12
|
+
node.should_receive(:xpath).with('trn:id').and_return(text)
|
13
|
+
text.stub(:text) {"hi there"}
|
14
|
+
node.should_receive(:xpath).with('trn:date-posted/ts:date').and_return(text)
|
15
|
+
value_text.should_receive(:text).and_return("1177/100")
|
16
|
+
account_text.should_receive(:text).and_return("a1s2d3f4")
|
17
|
+
split_node.should_receive(:xpath).with("split:value").and_return(value_text)
|
18
|
+
split_node.should_receive(:xpath).with("split:account").and_return(account_text)
|
19
|
+
node.should_receive(:xpath).with('trn:description').and_return(text)
|
20
|
+
node.should_receive(:xpath).with('trn:splits/trn:split').and_return([split_node])
|
21
|
+
book.should_receive(:find_account_by_id).and_return(nil)
|
22
|
+
|
23
|
+
expect { Transaction.new(book, node) }.to raise_error /Could not find account/
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "without errors" do
|
28
|
+
before(:all) do
|
29
|
+
@book = Gnucash.open("spec/books/sample.gnucash")
|
30
|
+
@txn = @book.find_account_by_full_name("Assets::Current Assets::Cash in Wallet").transactions.first
|
31
|
+
end
|
32
|
+
|
33
|
+
it "keeps track of the transaction description" do
|
34
|
+
@txn.description.should == "Opening Balance"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Gnucash
|
2
|
+
describe Value do
|
3
|
+
describe '.zero' do
|
4
|
+
it 'creates a Value object with value 0' do
|
5
|
+
Value.zero.val.should == 0
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
it "raises an error when an unexpected string is given" do
|
10
|
+
expect { Value.new("1234") }.to raise_error /Unexpected value string/
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises an error when an unexpected type is given" do
|
14
|
+
expect { Value.new(Object.new) }.to raise_error /Unexpected value type/
|
15
|
+
end
|
16
|
+
|
17
|
+
it "allows construction from a string" do
|
18
|
+
Value.new("5678/100").val.should == 5678
|
19
|
+
end
|
20
|
+
|
21
|
+
it "converts the value to the expected string representation" do
|
22
|
+
Value.new("5678/100").to_s.should == "56.78"
|
23
|
+
Value.new("1000231455/100").to_s.should == "10002314.55"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "allows adding two value objects" do
|
27
|
+
a = Value.new("1234/100")
|
28
|
+
b = Value.new("2345/100")
|
29
|
+
c = a + b
|
30
|
+
c.to_s.should == "35.79"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "allows adding a Value object to a Numeric" do
|
34
|
+
a = Value.new("1234/100")
|
35
|
+
b = 15
|
36
|
+
c = a + b
|
37
|
+
c.should == 27.34
|
38
|
+
end
|
39
|
+
|
40
|
+
it "allows subtracting two value objects" do
|
41
|
+
a = Value.new("-12300/100")
|
42
|
+
b = Value.new("99/100")
|
43
|
+
c = a - b
|
44
|
+
c.to_s.should == "-123.99"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "allows subtracting a Numeric from a Value object" do
|
48
|
+
a = Value.new("890/100")
|
49
|
+
b = 7.8
|
50
|
+
c = a - b
|
51
|
+
c.should == 1.1
|
52
|
+
end
|
53
|
+
|
54
|
+
it "allows multiplying a Value by a Numeric" do
|
55
|
+
a = Value.new("100/100")
|
56
|
+
b = 12
|
57
|
+
c = a * b
|
58
|
+
c.should == 12.00
|
59
|
+
end
|
60
|
+
|
61
|
+
it "allows dividing a Value by a Numeric" do
|
62
|
+
a = Value.new("150000/100")
|
63
|
+
b = 150
|
64
|
+
c = a / b
|
65
|
+
c.should == 10.0
|
66
|
+
end
|
67
|
+
|
68
|
+
it "formats the number with two decimal places" do
|
69
|
+
Value.new("1400/100").to_s.should == "14.00"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "supports comparisons between two Value objects" do
|
73
|
+
Value.new("1234/100").should == Value.new(1234)
|
74
|
+
(Value.new("89/100") < Value.new("100/100")).should be_true
|
75
|
+
(Value.new("1234/100") > Value.new("222/100")).should be_true
|
76
|
+
end
|
77
|
+
|
78
|
+
context "errors" do
|
79
|
+
it "raises an error when attempting to add an unknown object type" do
|
80
|
+
expect { Value.new(33) + nil }.to raise_error /Unexpected argument/i
|
81
|
+
end
|
82
|
+
|
83
|
+
it "raises an error when attempting to subtract an unknown object type" do
|
84
|
+
expect { Value.new(33) - nil }.to raise_error /Unexpected argument/i
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises an error when attempting to multiply by an unknown object type" do
|
88
|
+
expect { Value.new(33) * nil }.to raise_error /Unexpected argument/i
|
89
|
+
end
|
90
|
+
|
91
|
+
it "raises an error when attempting to divide by an unknown object type" do
|
92
|
+
expect { Value.new(33) / nil }.to raise_error /Unexpected argument/i
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
describe Gnucash do
|
2
|
+
describe '.open' do
|
3
|
+
it 'opens a gzipped gnucash book' do
|
4
|
+
book = Gnucash.open("spec/books/sample.gnucash")
|
5
|
+
book.is_a?(Gnucash::Book).should be_true
|
6
|
+
end
|
7
|
+
it 'opens a plain text gnucash book' do
|
8
|
+
book = Gnucash.open("spec/books/sample-text.gnucash")
|
9
|
+
book.is_a?(Gnucash::Book).should be_true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gnucash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josh Holtrop
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: simplecov
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec-core
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec-expectations
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec-mocks
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Ruby library for extracting data from GnuCash data files
|
111
|
+
email:
|
112
|
+
- jholtrop@gmail.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- .rspec
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- gnucash.gemspec
|
124
|
+
- lib/gnucash.rb
|
125
|
+
- lib/gnucash/account.rb
|
126
|
+
- lib/gnucash/account_transaction.rb
|
127
|
+
- lib/gnucash/book.rb
|
128
|
+
- lib/gnucash/transaction.rb
|
129
|
+
- lib/gnucash/value.rb
|
130
|
+
- lib/gnucash/version.rb
|
131
|
+
- spec/books/sample-text.gnucash
|
132
|
+
- spec/books/sample.gnucash
|
133
|
+
- spec/gnucash/account_spec.rb
|
134
|
+
- spec/gnucash/book_spec.rb
|
135
|
+
- spec/gnucash/transaction_spec.rb
|
136
|
+
- spec/gnucash/value_spec.rb
|
137
|
+
- spec/gnucash_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
homepage: ''
|
140
|
+
licenses: []
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ! '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 1.8.23
|
160
|
+
signing_key:
|
161
|
+
specification_version: 3
|
162
|
+
summary: Extract data from GnuCash data files
|
163
|
+
test_files:
|
164
|
+
- spec/books/sample-text.gnucash
|
165
|
+
- spec/books/sample.gnucash
|
166
|
+
- spec/gnucash/account_spec.rb
|
167
|
+
- spec/gnucash/book_spec.rb
|
168
|
+
- spec/gnucash/transaction_spec.rb
|
169
|
+
- spec/gnucash/value_spec.rb
|
170
|
+
- spec/gnucash_spec.rb
|
171
|
+
- spec/spec_helper.rb
|
172
|
+
has_rdoc:
|