treasurer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/treasurer/commands.rb +7 -7
- data/lib/treasurer/local_customisations.rb +2 -0
- data/lib/treasurer/report.rb +26 -16
- data/lib/treasurer.rb +4 -0
- data/test/test_treasurer.rb +3 -3
- data/treasurer.gemspec +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6aa2a2dc0c5bcd8c4cc5bc4bc905e4c99e317497
|
4
|
+
data.tar.gz: 0208ef5153cfb46947fce5ca8079ead628180fb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 891b64d30e9cc11a6fe2793b88751e20bfb84630a14c39370f35bea6d485b47621be03ee06ee9db3d5ab77f159c7bf5458e9dd6af76396e06b4b63d9192cd6cb
|
7
|
+
data.tar.gz: 3694e108f72e3f72b90f2e21660f5939a52b4c931e5b0f4d196f3a2e358ad58e5e5d3b297a4e17dbf1f485e20d211ac66320e5748946f7c0ba63266536b0438f
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/treasurer/commands.rb
CHANGED
@@ -6,7 +6,7 @@ class << self
|
|
6
6
|
ep 'entries', Dir.entries
|
7
7
|
CodeRunner.submit(p: "{data_file: '#{File.expand_path(file)}', account: :#{account}}")
|
8
8
|
end
|
9
|
-
def
|
9
|
+
def add_folder_of_files(folder, copts={})
|
10
10
|
#Dir.chdir(folder) do
|
11
11
|
files = Dir.entries(folder).grep(/\.csv$/)
|
12
12
|
accounts = files.map{|f| f.sub(/\.csv/, '')}
|
@@ -18,6 +18,11 @@ class << self
|
|
18
18
|
def check_is_treasurer_folder
|
19
19
|
raise "This folder has not been set up to use with Treasurer; please initialise a folder with treasurer init" unless FileTest.exist? '.code_runner_script_defaults.rb' and eval(File.read('.code_runner_script_defaults.rb'))[:code] == 'budget'
|
20
20
|
end
|
21
|
+
def create_report(copts = {})
|
22
|
+
load_treasurer_folder
|
23
|
+
reporter = Reporter.new(CodeRunner.fetch_runner(h: :component), days_before: copts[:b]||360, days_ahead: copts[:a]||180, today: copts[:t])
|
24
|
+
reporter.report()
|
25
|
+
end
|
21
26
|
def init_root_folder(folder, copts={})
|
22
27
|
raise "Folder already exists" if FileTest.exist? folder
|
23
28
|
FileUtils.makedirs(folder)
|
@@ -32,13 +37,8 @@ class << self
|
|
32
37
|
Treasurer::Reporter.send(:include, Treasurer::LocalCustomisations)
|
33
38
|
Treasurer::Reporter::Account.send(:include, Treasurer::LocalCustomisations)
|
34
39
|
Treasurer::Reporter::Analysis.send(:include, Treasurer::LocalCustomisations)
|
35
|
-
CodeRunner::Budget.send(:include, Treasurer::LocalCustomisations)
|
36
40
|
runner = CodeRunner.fetch_runner
|
37
|
-
|
38
|
-
def report(copts = {})
|
39
|
-
load_treasurer_folder
|
40
|
-
reporter = Reporter.new(CodeRunner.fetch_runner(h: :component), days_before: copts[:b]||360, days_ahead: copts[:a]||180, today: copts[:t])
|
41
|
-
reporter.report()
|
41
|
+
CodeRunner::Budget.send(:include, Treasurer::LocalCustomisations)
|
42
42
|
end
|
43
43
|
|
44
44
|
def method_missing(meth, *args)
|
data/lib/treasurer/report.rb
CHANGED
@@ -66,8 +66,9 @@ class Reporter
|
|
66
66
|
def report
|
67
67
|
get_actual_budgets
|
68
68
|
get_projected_budgets
|
69
|
-
|
70
|
-
|
69
|
+
accounts = @runs.map{|r| r.account}.uniq.map{|acc| Account.new(acc, self, @runner, @runs, @projected_budgets, false)}
|
70
|
+
external_accounts = (@runs.map{|r| r.external_account}.uniq - accounts.map{|acc| acc.name}).map{|acc| Account.new(acc, self, @runner, @runs, @projected_budgets, true)}
|
71
|
+
@accounts = accounts + external_accounts
|
71
72
|
@accounts.unshift (@equity = Equity.new(self, @runner, @accounts))
|
72
73
|
get_in_limit_discretionary_budget_factor
|
73
74
|
get_stable_discretionary_budget_factor
|
@@ -80,7 +81,7 @@ class Reporter
|
|
80
81
|
report << expense_account_summary
|
81
82
|
report << budget_expenditure_graphs
|
82
83
|
report << '\end{multicols}'
|
83
|
-
report << budget_resolutions
|
84
|
+
#report << budget_resolutions
|
84
85
|
report << budget_breakdown
|
85
86
|
report << transactions_by_account
|
86
87
|
report << footer
|
@@ -112,12 +113,17 @@ class Reporter
|
|
112
113
|
#if !date
|
113
114
|
#@runs.sort_by{|r| r.date}[-1].balance
|
114
115
|
if @external
|
115
|
-
|
116
|
+
#p ['name is ', name, type]
|
117
|
+
#
|
118
|
+
#@runs.find_all{|r| r.date < date}.map{|r| (r.deposit - r.withdrawal) * (@external ? -1 : 1)}.sum || 0.0
|
119
|
+
# Temporary....
|
120
|
+
0.0
|
116
121
|
else
|
117
122
|
@runs.sort_by{|r| (r.date.to_datetime.to_time.to_i - date.to_datetime.to_time.to_i).to_f.abs}[0].balance
|
118
123
|
end
|
119
124
|
end
|
120
125
|
def expenditure(today, days_before, &block)
|
126
|
+
p ['name22 is ', name, type]
|
121
127
|
@runs.find_all{|r| r.days_ago(today) < days_before and (!block or yield(r)) }.map{|r| @external ? r.withdrawal : r.deposit }.sum || 0
|
122
128
|
end
|
123
129
|
def income(today, days_before)
|
@@ -143,6 +149,7 @@ EOF
|
|
143
149
|
end
|
144
150
|
end
|
145
151
|
def projected_balance(date)
|
152
|
+
return 0.0 if @external # Temporary Hack
|
146
153
|
non_discretionary_projected_balance(date) -
|
147
154
|
@reporter.sum_regular(@projected_budgets, date)
|
148
155
|
end
|
@@ -194,7 +201,7 @@ EOF
|
|
194
201
|
stable = futuredates.map{|date| projected_balance(date)}
|
195
202
|
kit5 = GraphKit.quick_create([futuredates.map{|d| d.to_time.to_i}, stable])
|
196
203
|
#exit
|
197
|
-
@projected_budget_factor = nil
|
204
|
+
@reporter.projected_budget_factor = nil
|
198
205
|
kit += (kit2 + kit4 + kit5)
|
199
206
|
kit = kit3 + kit
|
200
207
|
kit.title = "Balance for #{name}"
|
@@ -287,19 +294,19 @@ EOF
|
|
287
294
|
\\subsection{Equity}
|
288
295
|
#{@accounts.find{|acc| acc.type == :Equity }.summary_table(@today, @days_before)}
|
289
296
|
\\subsection{Assets}
|
290
|
-
#{@accounts.find_all{|acc|
|
297
|
+
#{@accounts.find_all{|acc| acc.type == :Asset }.map{|acc| acc.summary_table(@today, @days_before)}.join("\n\n") }
|
291
298
|
\\subsection{Liabilities}
|
292
|
-
#{@accounts.find_all{|acc|
|
299
|
+
#{@accounts.find_all{|acc| acc.type == :Liability }.map{|acc| acc.summary_table(@today, @days_before)}.join("\n\n") }
|
293
300
|
\\subsection{Income}
|
294
|
-
#{@accounts.find_all{|acc|
|
301
|
+
#{@accounts.find_all{|acc| acc.type == :Income }.map{|acc| acc.summary_table(@today, @days_before)}.join("\n\n") }
|
295
302
|
\\subsection{Expenses}
|
296
|
-
#{@accounts.find_all{|acc|
|
303
|
+
#{@accounts.find_all{|acc| acc.type == :Expense }.map{|acc| acc.summary_table(@today, @days_before)}.join("\n\n") }
|
297
304
|
EOF
|
298
305
|
end
|
299
306
|
def account_balance_graphs
|
300
307
|
<<EOF
|
301
308
|
\\section{Graphs of Recent Balances}
|
302
|
-
#{@accounts.find_all{|acc|
|
309
|
+
#{@accounts.find_all{|acc| acc.type != :Expense}.map{|acc|
|
303
310
|
acc.write_balance_graph(@today, @days_before, @days_ahead)
|
304
311
|
acc.balance_graph_string
|
305
312
|
}.join("\n\n")
|
@@ -326,9 +333,12 @@ EOF
|
|
326
333
|
EOF
|
327
334
|
end
|
328
335
|
def expense_pie_chart(name, &block)
|
329
|
-
expaccs = @accounts.find_all{|acc|
|
336
|
+
expaccs = @accounts.find_all{|acc| acc.type == :Expense}
|
330
337
|
labels = expaccs.map{|acc| acc.name}
|
331
338
|
exps = expaccs.map{|acc| acc.expenditure(@today, 50000, &block)}
|
339
|
+
labels, exps = [labels, exps].transpose.find_all{|l, e| e != 0.0}.transpose
|
340
|
+
return "No expenditure in budget period." if labels == nil
|
341
|
+
ep ['labels22539', labels, exps]
|
332
342
|
kit = GraphKit.quick_create([exps])
|
333
343
|
kit.data[0].gp.with = 'boxes'
|
334
344
|
kit.gp.style = "fill solid"
|
@@ -500,13 +510,13 @@ EOF
|
|
500
510
|
if items.size > 0
|
501
511
|
"
|
502
512
|
\\footnotesize
|
503
|
-
\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " *
|
513
|
+
\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 3 + " L " + " r " * 2 + " c " }}
|
504
514
|
%\\hline
|
505
|
-
|
515
|
+
#{date.to_s.latex_escape} & & & Total & #{expenditure} & \\\\
|
506
516
|
\\hline
|
507
517
|
\\Tstrut
|
508
518
|
#{items.map{|r|
|
509
|
-
(
|
519
|
+
( CodeRunner::Budget.rcp.component_results + [:external_account] - [:sc, :balance ]).map{|res|
|
510
520
|
r.send(res).to_s.latex_escape
|
511
521
|
}.join(" & ")
|
512
522
|
}.join("\\\\\n")
|
@@ -534,9 +544,9 @@ EOF
|
|
534
544
|
#{all = acc.runs.find_all{|r| r.days_ago(@today) < @days_before}.sort_by{|r| [r.date, r.id]}.reverse
|
535
545
|
#ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
|
536
546
|
all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
|
537
|
-
"\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " *
|
547
|
+
"\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 3 + " L " + " r " * 3 + "l"}}
|
538
548
|
#{piece.map{|r|
|
539
|
-
(
|
549
|
+
(CodeRunner::Budget.rcp.component_results - [:sc] + [:budget]).map{|res| r.send(res).to_s.latex_escape
|
540
550
|
#rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
|
541
551
|
}.join(" & ")
|
542
552
|
}.join("\\\\\n")}
|
data/lib/treasurer.rb
CHANGED
@@ -91,6 +91,9 @@ class Treasurer
|
|
91
91
|
# options (copts) hash
|
92
92
|
def setup(copts)
|
93
93
|
# None neededed
|
94
|
+
copts[:b] = copts[:b].to_i
|
95
|
+
copts[:a] = copts[:a].to_i
|
96
|
+
copts[:t] = Date.parse(copts[:t]) if copts[:t]
|
94
97
|
end
|
95
98
|
def verbosity
|
96
99
|
2
|
@@ -100,6 +103,7 @@ class Treasurer
|
|
100
103
|
end
|
101
104
|
|
102
105
|
$has_put_startup_message_for_code_runner = true
|
106
|
+
require 'date'
|
103
107
|
require 'coderunner'
|
104
108
|
require 'treasurer/commands.rb'
|
105
109
|
require 'treasurer/report.rb'
|
data/test/test_treasurer.rb
CHANGED
@@ -11,10 +11,10 @@ class TestTreasurer < Test::Unit::TestCase
|
|
11
11
|
Treasurer.add_file('../bankaccountstatement.csv', 'FirstBank', {})
|
12
12
|
Treasurer.status
|
13
13
|
Treasurer.add_file('../otheraccountstatement.csv', 'SecondBank', {})
|
14
|
-
Treasurer.
|
14
|
+
Treasurer.add_folder_of_files('../multiple')
|
15
15
|
Treasurer.status h: :component
|
16
|
-
Treasurer.
|
16
|
+
Treasurer.create_report t: Date.parse('2010-09-07'), b: 40, a: 35
|
17
17
|
end
|
18
|
-
FileUtils.rm_r(testfolder) if FileTest.exist? testfolder
|
18
|
+
#FileUtils.rm_r(testfolder) if FileTest.exist? testfolder
|
19
19
|
end
|
20
20
|
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.2.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "treasurer"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.2.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Edmund Highcock"]
|
14
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-06-02"
|
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."
|
16
16
|
s.email = "edmundhighcock@users.sourceforge.net"
|
17
17
|
s.executables = ["treasurer"]
|
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.2.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: 2014-
|
11
|
+
date: 2014-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coderunner
|