treasurer 0.9.5 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.rdoc +113 -14
- data/VERSION +1 -1
- data/lib/treasurer.rb +2 -0
- data/lib/treasurer/account_choices.rb +311 -0
- data/lib/treasurer/commands.rb +14 -2
- data/lib/treasurer/report.rb +2 -0
- data/test/test_treasurer.rb +7 -6
- data/treasurer.gemspec +10 -6
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa1cd8cf039ac26719b8c9f7a0d4cd998fee36a7
|
4
|
+
data.tar.gz: 6554a1e9fee7d50569901c09dc8098a99a5f7715
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f533dbabc3652f5fe247b6da688c36868bfdf7ea5a7c492ac39d5aadea3c2c0f0196c2a64ed2cbf6998ba7e6f92395387891a6d8eb05f0578740c8d2d41e06d
|
7
|
+
data.tar.gz: 14dedc8ea9f1c89b44e8eb053a5157e8c824c7fab2aab7f9dd0792872466a21f6d6b94f40de10d77a8c31608378c0a130c4136752dc852114cd9accff037cebf
|
data/Gemfile
CHANGED
@@ -3,8 +3,9 @@ source "http://rubygems.org"
|
|
3
3
|
# Example:
|
4
4
|
gem "activesupport", ">= 5.0.0"
|
5
5
|
gem "coderunner", ">= 0.14.16"
|
6
|
-
gem "budgetcrmod", "~> 0.
|
6
|
+
gem "budgetcrmod", "~> 0.5.0"
|
7
7
|
gem "command-line-flunky", ">= 1.0.0"
|
8
|
+
gem "sqlite3", "~> 1.3"
|
8
9
|
|
9
10
|
# Add dependencies to develop your gem here.
|
10
11
|
# Include everything needed to run rake, tests, features, etc.
|
data/README.rdoc
CHANGED
@@ -1,19 +1,118 @@
|
|
1
|
-
=
|
1
|
+
= SQLite3/Ruby Interface
|
2
2
|
|
3
|
-
|
3
|
+
* https://github.com/sparklemotion/sqlite3-ruby
|
4
|
+
* http://groups.google.com/group/sqlite3-ruby
|
5
|
+
* http://rubygems.org/gems/sqlite3
|
6
|
+
* http://www.rubydoc.info/gems/sqlite3/frames
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
-
* Fork the project.
|
10
|
-
* Start a feature/bugfix branch.
|
11
|
-
* Commit and push until you are happy with your contribution.
|
12
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
8
|
+
{<img src="https://travis-ci.org/sparklemotion/sqlite3-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/sparklemotion/sqlite3-ruby]
|
14
9
|
|
15
|
-
==
|
10
|
+
== DESCRIPTION
|
16
11
|
|
17
|
-
|
18
|
-
|
12
|
+
This module allows Ruby programs to interface with the SQLite3
|
13
|
+
database engine (http://www.sqlite.org). You must have the
|
14
|
+
SQLite engine installed in order to build this module.
|
15
|
+
|
16
|
+
Note that this module is only compatible with SQLite 3.6.16 or newer.
|
17
|
+
|
18
|
+
== SYNOPSIS
|
19
|
+
|
20
|
+
require "sqlite3"
|
21
|
+
|
22
|
+
# Open a database
|
23
|
+
db = SQLite3::Database.new "test.db"
|
24
|
+
|
25
|
+
# Create a table
|
26
|
+
rows = db.execute <<-SQL
|
27
|
+
create table numbers (
|
28
|
+
name varchar(30),
|
29
|
+
val int
|
30
|
+
);
|
31
|
+
SQL
|
32
|
+
|
33
|
+
# Execute a few inserts
|
34
|
+
{
|
35
|
+
"one" => 1,
|
36
|
+
"two" => 2,
|
37
|
+
}.each do |pair|
|
38
|
+
db.execute "insert into numbers values ( ?, ? )", pair
|
39
|
+
end
|
40
|
+
|
41
|
+
# Find a few rows
|
42
|
+
db.execute( "select * from numbers" ) do |row|
|
43
|
+
p row
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create another table with multiple columns
|
47
|
+
|
48
|
+
db.execute <<-SQL
|
49
|
+
create table students (
|
50
|
+
name varchar(50),
|
51
|
+
email varchar(50),
|
52
|
+
grade varchar(5),
|
53
|
+
blog varchar(50)
|
54
|
+
);
|
55
|
+
SQL
|
56
|
+
|
57
|
+
# Execute inserts with parameter markers
|
58
|
+
db.execute("INSERT INTO students (name, email, grade, blog)
|
59
|
+
VALUES (?, ?, ?, ?)", ["Jane", "me@janedoe.com", "A", "http://blog.janedoe.com"])
|
60
|
+
|
61
|
+
db.execute( "select * from students" ) do |row|
|
62
|
+
p row
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
== Compilation and Installation
|
67
|
+
|
68
|
+
Install SQLite3, enabling the option SQLITE_ENABLE_COLUMN_METADATA (see
|
69
|
+
www.sqlite.org/compile.html for details).
|
70
|
+
|
71
|
+
Then do the following:
|
72
|
+
|
73
|
+
ruby setup.rb config
|
74
|
+
ruby setup.rb setup
|
75
|
+
ruby setup.rb install
|
76
|
+
|
77
|
+
Alternatively, you can download and install the RubyGem package for
|
78
|
+
SQLite3/Ruby (you must have RubyGems and SQLite3 installed, first):
|
79
|
+
|
80
|
+
gem install sqlite3
|
81
|
+
|
82
|
+
If you have sqlite3 installed in a non-standard location, you can specify the location of the include and lib files by doing:
|
83
|
+
|
84
|
+
gem install sqlite3 -- --with-sqlite3-include=/opt/local/include \
|
85
|
+
--with-sqlite3-lib=/opt/local/lib
|
86
|
+
|
87
|
+
= SUPPORT!!!
|
88
|
+
|
89
|
+
== OMG! Something has gone wrong! Where do I get help?
|
90
|
+
|
91
|
+
The best place to get help is from the
|
92
|
+
{sqlite3-ruby mailing list}[http://groups.google.com/group/sqlite3-ruby] which
|
93
|
+
can be found here:
|
94
|
+
|
95
|
+
* http://groups.google.com/group/sqlite3-ruby
|
96
|
+
|
97
|
+
== I've found a bug! Where do I file it?
|
98
|
+
|
99
|
+
Uh oh. After contacting the mailing list, you've found that you've actually
|
100
|
+
discovered a bug. You can file the bug at the
|
101
|
+
{github issues page}[https://github.com/sparklemotion/sqlite3-ruby/issues]
|
102
|
+
which can be found here:
|
103
|
+
|
104
|
+
* https://github.com/sparklemotion/sqlite3-ruby/issues
|
105
|
+
|
106
|
+
== Usage
|
107
|
+
|
108
|
+
For help figuring out the SQLite3/Ruby interface, check out the
|
109
|
+
SYNOPSIS as well as the RDoc. It includes examples of
|
110
|
+
usage. If you have any questions that you feel should be addressed in the
|
111
|
+
FAQ, please send them to {the mailing list}[http://groups.google.com/group/sqlite3-ruby]
|
112
|
+
|
113
|
+
== Source Code
|
114
|
+
|
115
|
+
The source repository is accessible via git:
|
116
|
+
|
117
|
+
git clone git://github.com/sparklemotion/sqlite3-ruby.git
|
19
118
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.0
|
data/lib/treasurer.rb
CHANGED
@@ -110,10 +110,12 @@ end
|
|
110
110
|
$has_put_startup_message_for_code_runner = true
|
111
111
|
require 'date'
|
112
112
|
require 'coderunner'
|
113
|
+
CodeRunner.setup_run_class('budget')
|
113
114
|
require 'treasurer/commands.rb'
|
114
115
|
require 'treasurer/report.rb'
|
115
116
|
require 'treasurer/analysis.rb'
|
116
117
|
require 'treasurer/accounts.rb'
|
118
|
+
require 'treasurer/account_choices.rb'
|
117
119
|
|
118
120
|
|
119
121
|
######################################
|
@@ -0,0 +1,311 @@
|
|
1
|
+
|
2
|
+
require 'sqlite3'
|
3
|
+
class CodeRunner::Budget
|
4
|
+
# Initialize the sqlite database that stores the user
|
5
|
+
# choices for external_account and sub_account
|
6
|
+
def self.init_sqlite(folder)
|
7
|
+
require 'sqlite3'
|
8
|
+
FileUtils.makedirs(folder + '/sqlite')
|
9
|
+
Dir.chdir(folder + '/sqlite') do
|
10
|
+
db = sqlitedb(Dir.pwd)
|
11
|
+
_rows = db.execute <<-SQL
|
12
|
+
create table external_accounts (
|
13
|
+
eid INTEGER primary key,
|
14
|
+
external_account text
|
15
|
+
);
|
16
|
+
SQL
|
17
|
+
_rows = db.execute <<-SQL
|
18
|
+
create table sub_accounts (
|
19
|
+
sid INTEGER primary key,
|
20
|
+
sub_account text,
|
21
|
+
eid INTEGER,
|
22
|
+
foreign key (eid) references external_accounts (eid)
|
23
|
+
);
|
24
|
+
SQL
|
25
|
+
_rows = db.execute <<-SQL
|
26
|
+
create table choices (
|
27
|
+
id INTEGER primary key,
|
28
|
+
signature text,
|
29
|
+
sid INTEGER,
|
30
|
+
foreign key (sid) references sub_accounts (sid)
|
31
|
+
);
|
32
|
+
SQL
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.sqlitedb(folder)
|
38
|
+
SQLite3::Database.new folder + "/treasurer.db"
|
39
|
+
end
|
40
|
+
|
41
|
+
def sqlitedb
|
42
|
+
self.class.sqlitedb(@runner.root_folder + '/sqlite')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get stored choices from the old flat files
|
46
|
+
def get_old_choices
|
47
|
+
chosen = false
|
48
|
+
Hash.phoenix(@runner.root_folder + '/account_choices.rb') do |choices_hash|
|
49
|
+
if choices_hash[signature]
|
50
|
+
chosen = choices_hash[signature]
|
51
|
+
elsif choices_hash[data_line]
|
52
|
+
#choices_hash[data_line][:external_account] =
|
53
|
+
#choices_hash[data_line][:external_account].to_sym #fixes earlier bug
|
54
|
+
#choices_hash[data_line][:sub_account] =
|
55
|
+
#choices_hash[data_line][:sub_account].to_sym #fixes earlier bug
|
56
|
+
chosen = choices_hash[data_line]
|
57
|
+
choices_hash[signature] = choices_hash[data_line]
|
58
|
+
choices_hash.delete(data_line)
|
59
|
+
elsif choices_hash[old_data_line]
|
60
|
+
chosen = choices_hash[old_data_line]
|
61
|
+
choices_hash[signature] = choices_hash[old_data_line]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if chosen
|
65
|
+
puts "ADDING TO DB"
|
66
|
+
add_sqlite_choices(chosen)
|
67
|
+
end
|
68
|
+
chosen||{}
|
69
|
+
end
|
70
|
+
|
71
|
+
def sqlite_eid(account_spec)
|
72
|
+
eid = nil
|
73
|
+
until eid
|
74
|
+
rows = sqlitedb.execute(
|
75
|
+
'SELECT (eid) ' +
|
76
|
+
'FROM external_accounts ' +
|
77
|
+
'WHERE external_account = ? ',
|
78
|
+
account_spec[:external_account].inspect
|
79
|
+
)
|
80
|
+
pp 'ROWSSS', rows
|
81
|
+
if rows.size < 1
|
82
|
+
sqlitedb.execute(
|
83
|
+
'INSERT INTO external_accounts ' +
|
84
|
+
'(external_account) VALUES (?)',
|
85
|
+
account_spec[:external_account].inspect
|
86
|
+
)
|
87
|
+
elsif rows.size > 1
|
88
|
+
raise "Duplicate external_accounts"
|
89
|
+
else
|
90
|
+
eid=rows[0][0]
|
91
|
+
raise TypeError.new("Bad eid: #{eid.inspect}") unless eid.kind_of? Integer
|
92
|
+
end
|
93
|
+
end
|
94
|
+
eid
|
95
|
+
end
|
96
|
+
|
97
|
+
def sqlite_sid(account_spec)
|
98
|
+
eid = sqlite_eid(account_spec)
|
99
|
+
sid = nil
|
100
|
+
until sid
|
101
|
+
rows = sqlitedb.execute(
|
102
|
+
'SELECT (sid) ' +
|
103
|
+
'FROM sub_accounts ' +
|
104
|
+
'WHERE sub_account = ? AND eid= ?',
|
105
|
+
[account_spec[:sub_account].inspect, eid]
|
106
|
+
)
|
107
|
+
pp 'ROWSSS', rows
|
108
|
+
if rows.size < 1
|
109
|
+
sqlitedb.execute(
|
110
|
+
'INSERT INTO sub_accounts ' +
|
111
|
+
'(sub_account, eid) VALUES (?, ?)',
|
112
|
+
[account_spec[:sub_account].inspect, eid]
|
113
|
+
)
|
114
|
+
elsif rows.size > 1
|
115
|
+
raise "Duplicate sub_accounts"
|
116
|
+
else
|
117
|
+
sid=rows[0][0]
|
118
|
+
raise TypeError.new("Bad sid: #{sid.inspect}") unless sid.kind_of? Integer
|
119
|
+
end
|
120
|
+
end
|
121
|
+
sid
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_sqlite_choices(chosen)
|
125
|
+
sid = sqlite_sid(chosen)
|
126
|
+
sqlitedb.execute(
|
127
|
+
'INSERT INTO choices' +
|
128
|
+
'(signature, sid) VALUES (?, ?)',
|
129
|
+
[signature.inspect, sid]
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get stored choices from the sqlite database
|
134
|
+
def get_sqlite_choices
|
135
|
+
rows = sqlitedb.execute(
|
136
|
+
'SELECT external_account, sub_account ' +
|
137
|
+
'FROM choices ' +
|
138
|
+
'LEFT JOIN sub_accounts ON ' +
|
139
|
+
'sub_accounts.sid = choices.sid ' +
|
140
|
+
'LEFT JOIN external_accounts ON ' +
|
141
|
+
'external_accounts.eid = sub_accounts.eid ' +
|
142
|
+
'WHERE signature = ?',
|
143
|
+
signature.inspect
|
144
|
+
)
|
145
|
+
pp "RRRRROOO", rows
|
146
|
+
if rows.size == 1
|
147
|
+
return {
|
148
|
+
external_account: eval(rows[0][0]),
|
149
|
+
sub_account: eval(rows[0][1]),
|
150
|
+
}
|
151
|
+
elsif rows.size > 1
|
152
|
+
raise "Duplicate signatures in sqlitedb"
|
153
|
+
else
|
154
|
+
return {}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Get new choices from the user interactively.
|
159
|
+
def get_new_choices
|
160
|
+
ext_account = nil
|
161
|
+
chosen = false
|
162
|
+
Dir.chdir(@runner.root_folder) do
|
163
|
+
sym = nil
|
164
|
+
while not chosen
|
165
|
+
Hash.phoenix('external_accounts.rb') do |account_hash|
|
166
|
+
#account_hash.each{|k,v| v[:name] = v[:name].to_sym} #Fixes an earlier bug
|
167
|
+
#choices = account_arr.size.times.map{|i| [i,account_arr[i][:name]]}
|
168
|
+
choices = account_hash.map{|k,v| [v[:sym], k]}.to_h
|
169
|
+
puts Terminal.default_colour
|
170
|
+
puts
|
171
|
+
puts "-" * data_line.size
|
172
|
+
puts signature.inspect
|
173
|
+
puts "-" * data_line.size
|
174
|
+
puts
|
175
|
+
puts "Account: " + account
|
176
|
+
puts
|
177
|
+
puts choices.inspect
|
178
|
+
puts
|
179
|
+
puts "Please choose from the above external accounts for this transaction."
|
180
|
+
puts "If you wish to add a new account type 0. To quit type q"
|
181
|
+
puts "To start again for this transaction, type z"
|
182
|
+
while not chosen
|
183
|
+
require 'io/console'
|
184
|
+
choice = STDIN.getch
|
185
|
+
if choice == "q"
|
186
|
+
throw :quit_data_entry
|
187
|
+
elsif choice == "0"
|
188
|
+
puts "Please type the name of the new account"
|
189
|
+
name = STDIN.gets.chomp.to_sym
|
190
|
+
puts "Please enter a symbol to represent this account (e.g. digit, letter, punctuation)."
|
191
|
+
sym = false
|
192
|
+
until sym
|
193
|
+
sym = STDIN.getch
|
194
|
+
if choices.keys.include? sym
|
195
|
+
puts "This symbol is taken"
|
196
|
+
sym = false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
account_hash[name] = {name: name, sym: sym, sub_accounts: {}}
|
200
|
+
#choices_hash[@id] = name
|
201
|
+
chosen = name
|
202
|
+
elsif choice == "z"
|
203
|
+
chosen = false
|
204
|
+
break
|
205
|
+
elsif not choices.keys.include? choice
|
206
|
+
puts "Error: this symbol does not correspond to an account"
|
207
|
+
else
|
208
|
+
chosen = choices[choice] #account_hash[choice][:name]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
#Hash.phoenix('account_choices.rb') do |choices_hash|
|
212
|
+
#choices_hash[data_line] = {external_account: chosen}
|
213
|
+
#end
|
214
|
+
end
|
215
|
+
ext_account = chosen
|
216
|
+
next if not chosen
|
217
|
+
chosen = false
|
218
|
+
Hash.phoenix('external_accounts.rb') do |account_hash|
|
219
|
+
#choices = account_arr.size.times.map{|i| [i,account_arr[i][:name]]}
|
220
|
+
sub_accounts = account_hash[ext_account][:sub_accounts]
|
221
|
+
sub_accounts.each{|k,v| v[:name] = v[:name].to_sym} #Fixes an earlier bug
|
222
|
+
choices = sub_accounts.map{|k,v| [v[:sym], k]}.to_h
|
223
|
+
puts "-" * data_line.size
|
224
|
+
puts
|
225
|
+
puts choices.inspect
|
226
|
+
puts
|
227
|
+
puts "Please choose from the above sub-accounts for this transaction."
|
228
|
+
puts "If you wish to add a new sub account, type 0. To quit, type q"
|
229
|
+
puts "To start again for this transaction, type z"
|
230
|
+
while not chosen
|
231
|
+
require 'io/console'
|
232
|
+
choice = STDIN.getch
|
233
|
+
if choice == "q"
|
234
|
+
throw :quit_data_entry
|
235
|
+
elsif choice == "0"
|
236
|
+
puts "Please type the name of the new sub account"
|
237
|
+
name = STDIN.gets.chomp.to_sym
|
238
|
+
puts "Please enter a symbol to represent this account (e.g. digit, letter, punctuation)."
|
239
|
+
sym = false
|
240
|
+
until sym
|
241
|
+
sym = STDIN.getch
|
242
|
+
if choices.keys.include? sym
|
243
|
+
puts "This symbol is taken"
|
244
|
+
sym = false
|
245
|
+
end
|
246
|
+
end
|
247
|
+
sub_accounts[name] = {name: name, sym: sym}
|
248
|
+
#choices_hash[@id] = name
|
249
|
+
chosen = name
|
250
|
+
elsif choice == "z"
|
251
|
+
chosen = false
|
252
|
+
break
|
253
|
+
elsif not choices.keys.include? choice
|
254
|
+
puts "Error: this symbol does not correspond to a sub-account"
|
255
|
+
else
|
256
|
+
chosen = choices[choice] #sub_accounts[choice][:name]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
next if not chosen
|
261
|
+
#Hash.phoenix('account_choices.rb') do |choices_hash|
|
262
|
+
#choices_hash[signature] = {external_account: ext_account, sub_account: chosen}
|
263
|
+
#end
|
264
|
+
add_sqlite_choices({external_account: ext_account, sub_account: chosen})
|
265
|
+
end #while not chosen
|
266
|
+
|
267
|
+
end
|
268
|
+
{external_account: ext_account, sub_account: chosen}
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
# All transactions occur between two accounts.
|
273
|
+
# One of those accounts is always physical (e.g. bank account, loan, credit card)
|
274
|
+
# and the other can be either physical or a virtual account of the users choice,
|
275
|
+
# e.g. Food or Petrol or Energy, or maybe WeeklyBudget and LongTermBudget etc.
|
276
|
+
def external_account
|
277
|
+
unless @runner
|
278
|
+
raise "No runner for " + data_line
|
279
|
+
end
|
280
|
+
if not @external_account
|
281
|
+
@external_account = (
|
282
|
+
get_sqlite_choices[:external_account] or
|
283
|
+
get_old_choices[:external_account] or
|
284
|
+
get_new_choices[:external_account]
|
285
|
+
)
|
286
|
+
end
|
287
|
+
return @external_account
|
288
|
+
end
|
289
|
+
|
290
|
+
# All transactions have a subaccount. For transactions between
|
291
|
+
# physical accounts this will almost always be just 'Transfer'
|
292
|
+
# or similar, but virtual accounts will have more meaningful
|
293
|
+
# sub_accounts, e.g. Food might have Groceries, EatingOut
|
294
|
+
# or WeeklyBudget might have Transport, Food, Clothes... depending
|
295
|
+
# on the users preferred way of organising things.
|
296
|
+
# The sub_accounts are primarily a labelling exercise, but done
|
297
|
+
# well can be very helpful in showing a breakdown of expenditure.
|
298
|
+
def sub_account
|
299
|
+
return @sub_account if @sub_account
|
300
|
+
puts "SIGNATURE ", signature.inspect
|
301
|
+
Dir.chdir(@runner.root_folder) do
|
302
|
+
external_account until (
|
303
|
+
choices = nil
|
304
|
+
Hash.phoenix('account_choices.rb'){|choices_hash| choices = choices_hash[signature]}
|
305
|
+
#p [choices, data_line]
|
306
|
+
choices
|
307
|
+
) and choices[:sub_account]
|
308
|
+
@sub_account = choices[:sub_account]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
data/lib/treasurer/commands.rb
CHANGED
@@ -24,7 +24,10 @@ class << self
|
|
24
24
|
end
|
25
25
|
def fetch_reporter(copts = {})
|
26
26
|
load_treasurer_folder(copts)
|
27
|
-
Reporter.new(
|
27
|
+
Reporter.new(
|
28
|
+
CodeRunner.fetch_runner(h: :component),
|
29
|
+
days_before: copts[:b]||360, days_ahead: copts[:a]||180,
|
30
|
+
today: copts[:t], report_currency: copts[:r])
|
28
31
|
end
|
29
32
|
def status(copts={})
|
30
33
|
load_treasurer_folder(copts)
|
@@ -33,10 +36,16 @@ class << self
|
|
33
36
|
def init_root_folder(folder, copts={})
|
34
37
|
raise "Folder already exists" if FileTest.exist? folder
|
35
38
|
FileUtils.makedirs(folder)
|
36
|
-
FileUtils.cp(
|
39
|
+
FileUtils.cp(
|
40
|
+
SCRIPT_FOLDER + '/treasurer/local_customisations.rb',
|
41
|
+
folder + '/local_customisations.rb')
|
37
42
|
CodeRunner.fetch_runner(Y: folder, C: 'budget', X: '/dev/null')
|
43
|
+
init_sqlite(folder)
|
38
44
|
eputs "\n\n Your treasurer folder '#{folder}' has been set up. All further treasurer commands should be run from within this folder.\n"
|
39
45
|
end
|
46
|
+
def init_sqlite(folder)
|
47
|
+
CodeRunner::Budget.init_sqlite(folder)
|
48
|
+
end
|
40
49
|
def load_treasurer_folder(copts={})
|
41
50
|
check_is_treasurer_folder
|
42
51
|
Treasurer.send(:remove_const, :LocalCustomisations) if defined? Treasurer::LocalCustomisations
|
@@ -64,3 +73,6 @@ class << self
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
end
|
76
|
+
|
77
|
+
class CodeRunner::Budget
|
78
|
+
end
|
data/lib/treasurer/report.rb
CHANGED
@@ -80,6 +80,7 @@ class Treasurer
|
|
80
80
|
attr_reader :days_before
|
81
81
|
attr_reader :report_currency
|
82
82
|
attr_reader :accounts_hash
|
83
|
+
attr_reader :runner
|
83
84
|
def initialize(runner, options)
|
84
85
|
@runner = runner
|
85
86
|
|
@@ -119,6 +120,7 @@ class Treasurer
|
|
119
120
|
@indateruns = @runs.find_all{|r| r.days_ago(@today) < @days_before}
|
120
121
|
@stable_discretionary_account_factors = {}
|
121
122
|
@in_limit_discretionary_account_factors = {}
|
123
|
+
@runner = runner
|
122
124
|
#p 'accounts256',@runs.size, @runs.map{|r| r.account}.uniq
|
123
125
|
|
124
126
|
end
|
data/test/test_treasurer.rb
CHANGED
@@ -20,17 +20,18 @@ class TestTreaurer < MiniTest::Test
|
|
20
20
|
Treasurer.add_file('../otheraccountstatement.csv', 'SecondBank', {})
|
21
21
|
Treasurer.add_folder_of_files('../multiple')
|
22
22
|
Treasurer.status h: :component
|
23
|
-
RubyProf.start
|
24
|
-
Treasurer.create_report t: Date.parse('2010-09-07'), b: 40, a: 35
|
25
|
-
result = RubyProf.stop
|
26
|
-
result.eliminate_methods!([/Array#map/, /Array#each/])
|
27
|
-
printer = RubyProf::GraphHtmlPrinter.new(result)
|
28
|
-
File.open('timing.html', 'w'){|f| printer.print(f, {})}
|
23
|
+
#RubyProf.start
|
24
|
+
#Treasurer.create_report t: Date.parse('2010-09-07'), b: 40, a: 35
|
25
|
+
#result = RubyProf.stop
|
26
|
+
#result.eliminate_methods!([/Array#map/, /Array#each/])
|
27
|
+
#printer = RubyProf::GraphHtmlPrinter.new(result)
|
28
|
+
#File.open('timing.html', 'w'){|f| printer.print(f, {})}
|
29
29
|
reporter = Treasurer.fetch_reporter(t: Date.parse('2010-09-07'), b: 40, a: 35)
|
30
30
|
reporter.generate_accounts
|
31
31
|
assert_equal(1, reporter.accounts_hash[:FirstBank].runs.find_all{|r| r.description =~ /BLACKW/}.size)
|
32
32
|
assert_equal(1032.08, reporter.equities.values[0].balance.round(2))
|
33
33
|
assert_equal(1825.28, reporter.equities.values[0].projected_balance(Date.parse('2010-10-09')).round(2))
|
34
|
+
p reporter.runner.component_run_list.values[-1].get_sqlite_choices
|
34
35
|
end
|
35
36
|
#FileUtils.rm_r(testfolder) if FileTest.exist? testfolder
|
36
37
|
end
|
data/treasurer.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: treasurer 0.
|
5
|
+
# stub: treasurer 0.10.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "treasurer".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.10.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Edmund Highcock".freeze]
|
14
|
-
s.date = "2018-
|
14
|
+
s.date = "2018-08-01"
|
15
15
|
s.description = "A simple command line tool for managing accounts and finances. Easily import internet banking spreadsheets and generate sophisticated reports and projections.".freeze
|
16
16
|
s.email = "edmundhighcock@users.sourceforge.net".freeze
|
17
17
|
s.executables = ["treasurer".freeze]
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
"VERSION",
|
29
29
|
"bin/treasurer",
|
30
30
|
"lib/treasurer.rb",
|
31
|
+
"lib/treasurer/account_choices.rb",
|
31
32
|
"lib/treasurer/accounts.rb",
|
32
33
|
"lib/treasurer/analysis.rb",
|
33
34
|
"lib/treasurer/commands.rb",
|
@@ -55,8 +56,9 @@ Gem::Specification.new do |s|
|
|
55
56
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
56
57
|
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 5.0.0"])
|
57
58
|
s.add_runtime_dependency(%q<coderunner>.freeze, [">= 0.14.16"])
|
58
|
-
s.add_runtime_dependency(%q<budgetcrmod>.freeze, ["~> 0.
|
59
|
+
s.add_runtime_dependency(%q<budgetcrmod>.freeze, ["~> 0.5.0"])
|
59
60
|
s.add_runtime_dependency(%q<command-line-flunky>.freeze, [">= 1.0.0"])
|
61
|
+
s.add_runtime_dependency(%q<sqlite3>.freeze, ["~> 1.3"])
|
60
62
|
s.add_development_dependency(%q<shoulda>.freeze, [">= 0"])
|
61
63
|
s.add_development_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
62
64
|
s.add_development_dependency(%q<bundler>.freeze, ["~> 1.0"])
|
@@ -66,8 +68,9 @@ Gem::Specification.new do |s|
|
|
66
68
|
else
|
67
69
|
s.add_dependency(%q<activesupport>.freeze, [">= 5.0.0"])
|
68
70
|
s.add_dependency(%q<coderunner>.freeze, [">= 0.14.16"])
|
69
|
-
s.add_dependency(%q<budgetcrmod>.freeze, ["~> 0.
|
71
|
+
s.add_dependency(%q<budgetcrmod>.freeze, ["~> 0.5.0"])
|
70
72
|
s.add_dependency(%q<command-line-flunky>.freeze, [">= 1.0.0"])
|
73
|
+
s.add_dependency(%q<sqlite3>.freeze, ["~> 1.3"])
|
71
74
|
s.add_dependency(%q<shoulda>.freeze, [">= 0"])
|
72
75
|
s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
73
76
|
s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
|
@@ -78,8 +81,9 @@ Gem::Specification.new do |s|
|
|
78
81
|
else
|
79
82
|
s.add_dependency(%q<activesupport>.freeze, [">= 5.0.0"])
|
80
83
|
s.add_dependency(%q<coderunner>.freeze, [">= 0.14.16"])
|
81
|
-
s.add_dependency(%q<budgetcrmod>.freeze, ["~> 0.
|
84
|
+
s.add_dependency(%q<budgetcrmod>.freeze, ["~> 0.5.0"])
|
82
85
|
s.add_dependency(%q<command-line-flunky>.freeze, [">= 1.0.0"])
|
86
|
+
s.add_dependency(%q<sqlite3>.freeze, ["~> 1.3"])
|
83
87
|
s.add_dependency(%q<shoulda>.freeze, [">= 0"])
|
84
88
|
s.add_dependency(%q<rdoc>.freeze, ["~> 3.12"])
|
85
89
|
s.add_dependency(%q<bundler>.freeze, ["~> 1.0"])
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: treasurer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edmund Highcock
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.5.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.5.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: command-line-flunky
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 1.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.3'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.3'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: shoulda
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,6 +182,7 @@ files:
|
|
168
182
|
- VERSION
|
169
183
|
- bin/treasurer
|
170
184
|
- lib/treasurer.rb
|
185
|
+
- lib/treasurer/account_choices.rb
|
171
186
|
- lib/treasurer/accounts.rb
|
172
187
|
- lib/treasurer/analysis.rb
|
173
188
|
- lib/treasurer/commands.rb
|