treasurer 0.6.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92a0a6c8e0a23eecc1d69c1dd14ff399b8b227c4
4
- data.tar.gz: 66e9cab23527f7dd3f843e2601a8d2904dbe6301
3
+ metadata.gz: d2048cb90864a5b22bc6bb26e1d226040caeb731
4
+ data.tar.gz: 340e5a5daf1026576358fc596ce9894566fac808
5
5
  SHA512:
6
- metadata.gz: 9bc7d55859630ea044d03356f113a20edc1a33dbe357d06b3055c7c922b285944b13acce16f7e4c2a825b10baf83f9eeff182f69863387009fc730e223088973
7
- data.tar.gz: 8c5e101af682d340a99b283f0801ed7afd776e4df1185fa90e3921f4003877c489116b450e3fd951d48c5f27b3a6c7eef99981aa2ea302dff47065a8b11ff5b9
6
+ metadata.gz: c0ac2576887308f53d2e3f72f3e73ece698785c4798d0ae2d8a14a1f114670eb7b44f18462742cab5b7b97c634a20ce71a7cc600d4f816d47d75859e44c1b511
7
+ data.tar.gz: cc2da7e7611fc6cf38502565a2b3721e64c45084627e2adb6bb7df043060af09f377a314e24683591284820aaac63eef9d611f018a676c4006db755d927f608f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.7.0
@@ -13,6 +13,8 @@ class Treasurer::Reporter
13
13
  #ep ['sub_accounts333', name, @runs.size, runs.size]
14
14
  end
15
15
  end
16
+ class ReportAccount < Account
17
+ end
16
18
  class Account
17
19
  attr_reader :name, :external, :runs, :currency
18
20
  attr_accessor :projection, :average, :original_currency
@@ -23,21 +25,66 @@ class Treasurer::Reporter
23
25
  @currency = options[:currency]
24
26
  #@projected_accounts_info =Hash[projected_accounts_info.find_all{|k,v| v[:account] == name}]
25
27
  @external = external
26
- @runs = runs.find_all do |r|
27
- #p ['checking11', name, @currency, ACCOUNT_INFO[r.account]] if name == r.external_account and @currency and @external
28
- #@external ? r.external_account : r.account) == name}
29
- if not @external
30
- r.account == name
31
- elsif @currency and info and cur = info[:currencies] and cur.size > 1
32
- #p ['checking11', name, @currency, ACCOUNT_INFO[r.account]] if name == r.external_account and @currency
33
- r.external_account == name and acinfo = ACCOUNT_INFO[r.account] and acinfo[:currencies] == [@currency]
34
- else
35
- r.external_account == name
28
+ unless @runs = options[:input_runs]
29
+ @runs = runs.find_all do |r|
30
+ #p ['checking11', name, @currency, ACCOUNT_INFO[r.account]] if name == r.external_account and @currency and @external
31
+ #@external ? r.external_account : r.account) == name}
32
+ if not @external
33
+ r.account == name
34
+ elsif @currency and info and cur = info[:currencies] and cur.size > 1
35
+ #p ['checking11', name, @currency, ACCOUNT_INFO[r.account]] if name == r.external_account and @currency
36
+ r.external_account == name and acinfo = ACCOUNT_INFO[r.account] and acinfo[:currencies] == [@currency]
37
+ else
38
+ r.external_account == name
39
+ end
36
40
  end
41
+
42
+ if should_report?
43
+ if @external
44
+ @report_runs = runs.find_all do |r|
45
+ r.external_account == name
46
+ end
47
+ else
48
+ @report_runs = @runs
49
+ end
50
+ end
51
+ else
52
+ @report_runs = []
37
53
  end
38
54
  #p ['Accountinf', name, @currency, @runs.size, runs.size]
39
55
  info[:external] = external if info
40
56
  end
57
+
58
+ # Make the account object that does the reporting. This only
59
+ # gets called if we are doing a currency conversion and
60
+ # this account is in the reeport currency.
61
+ def generate_report_account
62
+ p [name_c, @report_runs.class, @runs.class]
63
+ @report_account = ReportAccount.new(@name, @reporter, @runner, nil, @external, {currency: @currency, input_runs: @report_runs})
64
+ @report_account.instance_variable_set(:@currency, @reporter.report_currency)
65
+ @report_account.instance_variable_set(:@original_currency, currency)
66
+ end
67
+
68
+ # The object that actually does the reporting. If there is no
69
+ # currency conversion this is just self.
70
+ # A separate report object is needed as just lumping all the
71
+ # different currencies together across the board results
72
+ # in double counting.
73
+ #
74
+ # The report account is used for reporting information
75
+ # regarding a particular account. The main accoun is
76
+ # used for calculations e.g. Equity
77
+ def report_account
78
+ @report_account || self
79
+ end
80
+
81
+ # Should I report? If there is no currency conversion
82
+ # all accounts report. If there is currency conversion
83
+ # only non-external accounts and accounts in the
84
+ # right currency report.
85
+ def should_report?
86
+ !@reporter.report_currency or !@external or (@original_currency||currency) == @reporter.report_currency
87
+ end
41
88
  def sub_accounts
42
89
  @sub_accounts ||= @runs.map{|r| r.sub_account}.uniq.compact.map{|acc| SubAccount.new(acc, @reporter, @runner, @runs, @external, currency: @currency)}
43
90
  end
@@ -137,7 +184,7 @@ EOF
137
184
  def summary_line(today, days_before)
138
185
 
139
186
  <<EOF
140
- #{name_c} & #{balance} & #{deposited(today, days_before)} & #{withdrawn(today, days_before)}
187
+ #{name_c} & #{balance.to_tex} & #{deposited(today, days_before).to_tex} & #{withdrawn(today, days_before).to_tex}
141
188
  EOF
142
189
  end
143
190
  def money_in_sign
@@ -237,13 +284,15 @@ EOF
237
284
  #exit
238
285
  @reporter.projected_account_factor = nil
239
286
  kit += ( kit4 + kit5 + kit2)
240
- kit.yrange = [kit.data.map{|dk| dk.y.data.min}.min, kit.data.map{|dk| dk.y.data.max}.max]
287
+ kit.yrange = [(m = kit.data.map{|dk| dk.y.data.min}.min; m-m.abs*0.1), (m=kit.data.map{|dk| dk.y.data.max}.max; m+m.abs*0.1)]
241
288
  #kit += (kit2)
242
289
  kit = kit3 + kit
243
290
  kit.title = "Balance for #{name_c}"
244
291
  kit.xlabel = %['Date' offset 0,-2]
245
292
  kit.xlabel = nil
246
293
  kit.ylabel = "Balance"
294
+ kit.gp.mytics= "5"
295
+ kit.gp.grid = "ytics mytics lw 2,lw 1"
247
296
 
248
297
 
249
298
  kit.data[0].gp.title = 'Limit'
@@ -255,14 +304,20 @@ EOF
255
304
  kit.data.each{|dk| dk.gp.with = "l lw 5"}
256
305
  kit.data[4].gp.with = "l lw 5 dt 2 lc rgb 'black' "
257
306
  kit.gp.key = ' bottom left '
258
- kit.gp.key = ' rmargin '
307
+ kit.gp.key = ' rmargin samplen 2'
259
308
 
260
309
  #(p kit; STDIN.gets) if name == :LloydsCreditCard
261
310
  CodeRunner::Budget.kit_time_format_x(kit)
311
+ size = case type
312
+ when :Equity
313
+ "4.0in,4.0in"
314
+ else
315
+ "4.0in,2.5in"
316
+ end
262
317
 
263
318
  fork do
264
- (kit).gnuplot_write("#{name_c_file}_balance.eps", size: "4.0in,1.5in") #, latex: true)
265
- %x[epspdf #{name_c_file}_balance.eps]
319
+ (kit).gnuplot_write("#{name_c_file}_balance.eps", size: size) #, latex: true)
320
+ %x[epspdf -b #{name_c_file}_balance.eps]
266
321
  end
267
322
  #%x[epspdf #{name}_balance.eps]
268
323
  end
@@ -281,6 +336,9 @@ EOF
281
336
  @accounts = accounts #.find_all{|acc| not acc.external}
282
337
  @currency = options[:currency]
283
338
  end
339
+ def should_report?
340
+ true
341
+ end
284
342
  def type
285
343
  :Equity
286
344
  end
@@ -336,7 +394,7 @@ Balance & #{balance} \\\\
336
394
  EOF
337
395
  end
338
396
  def summary_line(today, days_before)
339
- "#{name_c} & #{balance(today)} & & "
397
+ "#{name_c} & #{balance(today).to_tex} & & "
340
398
  end
341
399
  end
342
400
  end
@@ -22,7 +22,8 @@ module Analysis
22
22
  #start_date = [(account.info[:start]||@start_date), @start_date].max
23
23
  expenditure = 0
24
24
  items_temp = []
25
- items = @runner.component_run_list.values.find_all{|r| r.external_account == account.name and r.in_date(account.info) and @accounts_hash[r.account].original_currency == account.original_currency}
25
+ #items = @runner.component_run_list.values.find_all{|r| r.external_account == account.name and r.in_date(account.info) and @accounts_hash[r.account].original_currency == account.original_currency}
26
+ items = account.runs.find_all{|r| r.in_date(account.info)}
26
27
  #ep ['items', items.map{|i| i.date}]
27
28
  #ep ['account', account.name_c]
28
29
  counter = 0
@@ -142,7 +143,7 @@ module Analysis
142
143
  sum_out = regular_items.inject(0) do |sum, (account, item)|
143
144
  item = [item] unless item.kind_of? Array
144
145
  # ep item
145
- value = item.inject(0) do |value,info|
146
+ value_out = item.inject(0) do |value,info|
146
147
  finish = (info[:end] and info[:end] < end_date) ? info[:end] : end_date
147
148
  #today = (Time.now.to_i / (24.0*3600.0)).round
148
149
 
@@ -212,7 +213,7 @@ module Analysis
212
213
  value + nunits * (info[:size]||account.projection*(@projected_account_factor||1.0))
213
214
 
214
215
  end
215
- sum + value
216
+ sum + value_out
216
217
  #(rcp.excluding? and rcp.excluding.include?(name)) ? sum : sum + value
217
218
  end
218
219
  sum_out
@@ -11,39 +11,44 @@ class Float
11
11
  sprintf("%.2f", self)
12
12
  end
13
13
  end
14
+ class Numeric
15
+ def to_tex
16
+ sprintf("%.2f", self).reverse.gsub(/(\d{3})(?=\d)/){"#$1,\\"}.reverse
17
+ end
18
+ end
14
19
  class Date
15
20
  def inspect
16
21
  "Date.parse('#{to_s}')"
17
22
  end
18
23
  end
19
- # Some thoughts on double entry accounting:
24
+ # Some thoughts on double entry accounting:
20
25
  #
21
26
  # assets - liabilities = equity
22
27
  # where equity = equity_at_start + income - expenses
23
28
  #
24
- # so
29
+ # so
25
30
  #
26
31
  # assets - liabilities = equity_at_start + income - expenses
27
32
  #
28
- # or alternatively
33
+ # or alternatively
29
34
  #
30
35
  # assets + expenses = equity_at_start + income + liabilities (1)
31
36
  #
32
37
  # Good things:
33
38
  # Positive equity_at_start, positive assets, positive income, negative liabilities, negative expenses
34
39
  #
35
- # A debit on the left of (1) must be matched by a credit on the right of (1) and
36
- # vice versa.
40
+ # A debit on the left of (1) must be matched by a credit on the right of (1) and
41
+ # vice versa.
37
42
  #
38
43
  #
39
44
  # A debit to an asset account increases the value of the asset. This means buying some land
40
- # or supplies or depositing some cash in a bank account. You can think of it as a debit because
45
+ # or supplies or depositing some cash in a bank account. You can think of it as a debit because
41
46
  # you are locking up your equity in a way that may not be realisable. A credit to the asset account
42
47
  # means drawing down on the asset, for example selling a bit of land or taking money out of a
43
48
  # bank account.
44
49
  #
45
50
  # Similarly, a debit to an expense account, effectively, spending money on that expense,
46
- # increases the value of that account. Debits here are clearly negative things from
51
+ # increases the value of that account. Debits here are clearly negative things from
47
52
  # the point of view of your wealth! (Credits to expense accounts would be something like
48
53
  # travel reimbursements).
49
54
  #
@@ -52,16 +57,16 @@ end
52
57
  # example a bank account, i.e. you must effectively spend it by buying an asset: remember
53
58
  # a bank may fail... a bank account is an asset with risk just as much as a painting).
54
59
  #
55
- # A credit to liabilities increases the value of the liability, for example taking out a
60
+ # A credit to liabilities increases the value of the liability, for example taking out a
56
61
  # loan. Once you credit a liability you have to either buy (debit) an asset, or buy (debit)
57
62
  # an expense directly (for example a loan to pay some fees).
58
- #
63
+ #
59
64
  # In any accounting period, the sum of all debits and credits should be 0. Also, at the end
60
65
  # of the accounting period,
61
66
  #
62
67
  # equity_at_end = assets - liabilities = equity_at_start + income - expenses
63
68
  #
64
- # This seems obvious to me!!
69
+ # This seems obvious to me!!
65
70
  class Treasurer
66
71
  class Reporter
67
72
  #include LocalCustomisations
@@ -72,7 +77,7 @@ class Treasurer
72
77
  attr_reader :accounts
73
78
  attr_reader :equity
74
79
  attr_reader :projected_accounts_info
75
- attr_reader :days_before
80
+ attr_reader :days_before
76
81
  attr_reader :report_currency
77
82
  attr_reader :accounts_hash
78
83
  def initialize(runner, options)
@@ -87,30 +92,30 @@ class Treasurer
87
92
  @report_currency = options[:report_currency]
88
93
 
89
94
  if run = @runs.find{|r| not r.external_account}
90
- raise "External_account not specified for #{run.data_line}"
95
+ raise "External_account not specified for #{run.data_line}"
91
96
  end
92
97
  @indateruns = @runs.find_all{|r| r.days_ago(@today) < @days_before}
93
98
  @stable_discretionary_account_factors = {}
94
99
  @in_limit_discretionary_account_factors = {}
95
- #p 'accounts256',@runs.size, @runs.map{|r| r.account}.uniq
100
+ #p 'accounts256',@runs.size, @runs.map{|r| r.account}.uniq
96
101
 
97
102
  end
98
103
  def generate_accounts
99
- accounts = @runs.map{|r| r.account}.uniq.map{|acc| Account.new(acc, self, @runner, @runs, false)}
100
- external_accounts = (@runs.map{|r| r.external_account}.uniq - accounts.map{|acc| acc.name}).map{|acc| Account.new(acc, self, @runner, @runs, true)}
104
+ accounts = @runs.map{|r| r.account}.uniq.map{|acc| Account.new(acc, self, @runner, @runs, false)}
105
+ external_accounts = (@runs.map{|r| r.external_account}.uniq - accounts.map{|acc| acc.name}).map{|acc| Account.new(acc, self, @runner, @runs, true)}
101
106
  #if not @report_currency
102
- external_accounts = external_accounts.map do |acc|
103
- if acc_inf = ACCOUNT_INFO[acc.name] and currencies = acc_inf[:currencies] and currencies.size > 1
104
- raise "Only expense accounts can have multiple currencies: #{acc.name} has type #{acc.type}" unless acc.type == :Expense
105
- new_accounts = currencies.map do |curr|
106
- Account.new(acc.name, self, @runner, @runs, true, currency: curr)
107
- end
108
- new_accounts.delete_if{|a| a.runs.size == 0}
109
- new_accounts
110
- else
111
- acc
107
+ external_accounts = external_accounts.map do |acc|
108
+ if acc_inf = ACCOUNT_INFO[acc.name] and currencies = acc_inf[:currencies] and currencies.size > 1
109
+ raise "Only expense accounts can have multiple currencies: #{acc.name} has type #{acc.type}" unless acc.type == :Expense
110
+ new_accounts = currencies.map do |curr|
111
+ Account.new(acc.name, self, @runner, @runs, true, currency: curr)
112
112
  end
113
+ new_accounts.delete_if{|a| a.runs.size == 0}
114
+ new_accounts
115
+ else
116
+ acc
113
117
  end
118
+ end
114
119
  #end
115
120
  external_accounts = external_accounts.flatten
116
121
  @accounts = accounts + external_accounts
@@ -148,6 +153,10 @@ class Treasurer
148
153
  acc.info[:opening_balance] *= EXCHANGE_RATES[[acc.currency, @report_currency]]
149
154
  end
150
155
  end
156
+ if acc.should_report?
157
+ #p acc.name_c
158
+ acc.generate_report_account
159
+ end
151
160
  acc.instance_variable_set(:@original_currency, acc.currency)
152
161
  acc.instance_variable_set(:@currency, @report_currency)
153
162
  acc.info[:currencies] = [@report_currency]
@@ -164,7 +173,7 @@ class Treasurer
164
173
  end
165
174
  @equities = @equities.to_h
166
175
  end
167
-
176
+
168
177
  def report
169
178
  generate_accounts
170
179
  #get_actual_accounts
@@ -199,18 +208,18 @@ class Treasurer
199
208
  <<EOF
200
209
  \\section{Summary of Accounts}
201
210
  #{[:Equity, :Asset, :Liability, :Income, :Expense].map{|type|
202
- accs = @accounts.find_all{|acc| acc.type == type }
211
+ accs = @accounts.find_all{|acc| acc.type == type and acc.should_report?}
203
212
  "\\subsection{#{type}}
204
- \\begin{tabulary}{0.9\\textwidth}{ R | c | c | c}
213
+ \\begin{tabulary}{0.9\\textwidth}{ R | r | r | r}
205
214
  Account & Balance & Deposited & Withdrawn \\\\
206
215
  \\hline
207
216
  \\Tstrut
208
- #{(accs.map{|acc| acc.summary_line(@today, @days_before)} +
209
- (type == :Asset ? ASSETS.map{|n,details| "#{n} (#{details[:currency]}) & #{details[:size]} & & "} : [])).join("\\\\\n")}
217
+ #{(accs.map{|acc| acc.report_account.summary_line(@today, @days_before)} +
218
+ (type == :Asset ? ASSETS.map{|n,details| "#{n} (#{details[:currency]}) & #{details[:size].to_tex} & & "} : [])).join("\\\\\n")}
210
219
  #{type!=:Equity&&false ? "
211
220
  \\\\ \\hline
212
221
  \\Tstrut
213
- Totals & #{accs.map{|a| a.balance}.sum} & #{accs.map{|a| a.deposited(@today, @days_before)}.sum} & #{accs.map{|a| a.withdrawn(@today, @days_before)}.sum} \\\\ " : "\\\\"}
222
+ Totals & #{accs.map{|a| a.balance}.sum.to_tex} & #{accs.map{|a| a.deposited(@today, @days_before)}.sum.to_tex} & #{accs.map{|a| a.withdrawn(@today, @days_before)}.sum.to_tex} \\\\ " : "\\\\"}
214
223
  \\end{tabulary}"
215
224
  }.join("\n\n")}
216
225
  EOF
@@ -219,7 +228,7 @@ EOF
219
228
  <<EOF
220
229
  \\section{Graphs of Recent Balances}
221
230
  #{[:Equity, :Asset, :Liability].map{|typ|
222
- "\\subsection{#{typ}}\\vspace{3em}" +
231
+ "\\subsection{#{typ}}\\vspace{3em}" +
223
232
  @accounts.find_all{|acc| acc.type == typ}.map{|acc|
224
233
  acc.write_balance_graph(@today, @days_before, @days_ahead)
225
234
  acc.balance_graph_string
@@ -234,9 +243,10 @@ EOF
234
243
  \\subsection{Totals for #@days_before-day Budget Period}
235
244
  #{expense_pie_charts_by_currency('accountperiod', @expense_accounts){|r| r.days_ago(@today) < @days_before}}
236
245
  \\subsection{Expense Account Breakdown}
237
- #{@expense_accounts.map{|account|
238
- #ep ['sub_accounts2124', account.sub_accounts.map{|sa| sa.name}]
239
- "\\subsection{#{account.name_c}}
246
+ #{@expense_accounts.find_all{|exaccount| exaccount.should_report?}.map{|exaccount|
247
+ account = exaccount.report_account
248
+ "
249
+ \\subsection{#{account.name_c}}
240
250
  #{expense_pie_chart(account.name_c_file + 'breakdown', account.sub_accounts, account){|r|r.days_ago(@today) < @days_before }}"
241
251
  }.join("\n\n")}
242
252
  EOF
@@ -258,7 +268,7 @@ EOF
258
268
  currencies.map do |curr|
259
269
  str = ""
260
270
  str << "\\subsubsection{#{curr}}\n" if curr
261
- str << expense_pie_chart(name + curr.to_s, accounts.find_all{|acc| acc.currency == curr}, &block)
271
+ str << expense_pie_chart(name + curr.to_s, accounts.find_all{|acc| acc.currency == curr and acc.should_report?}.map{|acc| acc.report_account}, &block)
262
272
  str
263
273
  end
264
274
  ).join("\n\n")
@@ -269,27 +279,27 @@ EOF
269
279
  #ep ['labels22539', name, labels, exps]
270
280
 
271
281
  kit = if subacc
272
- start_dates, end_dates, _exps, _items = account_expenditure(subacc)
273
- end_dates = end_dates.reverse #Now from earliest to latest
274
- start_dates = start_dates.reverse
275
- pp ['DATES', start_dates, end_dates, subacc.name]
276
- return "No expenditure in account period." if end_dates.size==0
277
- k = (
278
- end_dates.size.times.map do |i|
279
- exps = accounts.map{|acc| acc.deposited(end_dates[i], end_dates[i] - start_dates[i], &block)}
280
- kt = GraphKit.quick_create([labels.size.times.to_a.map{|l| l.to_f + i.to_f/end_dates.size.to_f}, exps])
281
- kt.data[0].gp.title = "Ending #{end_dates[i].strftime("#{end_dates[i].mday.ordinalize} %B")}; total = #{exps.sum}"
282
- kt.gp.key = "tmargin"
283
- kt
284
- end
285
- ).sum
286
- k
287
- else
288
- exps = accounts.map{|acc| acc.deposited(@today, 50000, &block)}
289
- labels, exps = [labels, exps].transpose.find_all{|l, e| e != 0.0}.transpose
290
- return "No expenditure in account period." if not labels #<F8> labels.size==0
291
- GraphKit.quick_create([labels.size.times.to_a, exps])
292
- end
282
+ start_dates, end_dates, _exps, _items = account_expenditure(subacc)
283
+ end_dates = end_dates.reverse #Now from earliest to latest
284
+ start_dates = start_dates.reverse
285
+ pp ['DATES', start_dates, end_dates, subacc.name]
286
+ return "No expenditure in account period." if end_dates.size==0
287
+ k = (
288
+ end_dates.size.times.map do |i|
289
+ exps = accounts.map{|acc| acc.deposited(end_dates[i], end_dates[i] - start_dates[i], &block)}
290
+ kt = GraphKit.quick_create([labels.size.times.to_a.map{|l| l.to_f + i.to_f/end_dates.size.to_f}, exps])
291
+ kt.data[0].gp.title = "Ending #{end_dates[i].strftime("#{end_dates[i].mday.ordinalize} %B")}; total = #{exps.sum}"
292
+ kt.gp.key = "tmargin"
293
+ kt
294
+ end
295
+ ).sum
296
+ k
297
+ else
298
+ exps = accounts.map{|acc| acc.deposited(@today, 50000, &block)}
299
+ labels, exps = [labels, exps].transpose.find_all{|l, e| e != 0.0}.transpose
300
+ return "No expenditure in account period." if not labels #<F8> labels.size==0
301
+ GraphKit.quick_create([labels.size.times.to_a, exps])
302
+ end
293
303
 
294
304
 
295
305
  #sum = exps.sum
@@ -311,7 +321,7 @@ EOF
311
321
  i = -1
312
322
  kit.gp.xtics = "(#{labels.map{|l| %["#{l}" #{i+=1}]}.join(', ')}) rotate by 315"
313
323
  pp ['kit222', kit, labels]
314
- fork do
324
+ fork do
315
325
  kit.gnuplot_write("#{name}.eps", size: "4.0in,2.0in")
316
326
  %x[epspdf #{name}.eps]
317
327
  end
@@ -362,16 +372,18 @@ EOF
362
372
  #exit
363
373
  end
364
374
  def discretionary_account_table(currency)
365
- discretionary_accounts = accounts_with_averages(@projected_accounts_info.find_all{|acc,inf| acc.currency == currency}.to_h)
375
+ discretionary_accounts = accounts_with_averages(
376
+ @projected_accounts_info.find_all{|acc,inf| acc.currency == currency and acc.should_report?}.map{|acc,inf| [acc.report_account,inf]}.to_h)
377
+ accounts_with_projections(discretionary_accounts.keys)
366
378
 
367
379
  <<EOF
368
380
  \\section{Discretionary Budget Summary (#{currency})}
369
- \\begin{tabulary}{0.9\\textwidth}{ R | c c c c }
381
+ \\begin{tabulary}{0.9\\textwidth}{ R | r r r r }
370
382
  Budget & Average & Projection & Limit & Stable \\\\
371
383
  #{discretionary_accounts.map{|account, info|
372
384
  #ep info
373
385
  "#{account.name_c} & #{account.average} & #{account.projection} & #{
374
- (account.projection * @in_limit_discretionary_account_factors[currency]).round(2)} &
386
+ (account.projection * @in_limit_discretionary_account_factors[currency]).round(2)} &
375
387
  #{(account.projection * @stable_discretionary_account_factors[currency]).round(2)} \\\\"
376
388
  }.join("\n\n")
377
389
  }
@@ -381,15 +393,15 @@ EOF
381
393
  def account_expenditure_graphs
382
394
  <<EOF
383
395
  \\section{Expenditure by Account Period}
384
- #{currency_list.map{|curr|
385
- account_and_transfer_graphs(@expense_accounts.find_all{|acc|
386
- acc.info and acc.info[:period] and acc.currency == curr
387
- })
396
+ #{currency_list.map{|curr|
397
+ account_and_transfer_graphs(@expense_accounts.find_all{|acc|
398
+ acc.info and acc.info[:period] and acc.currency == curr and acc.should_report?
399
+ }.map{|acc| acc.report_account})
388
400
  }.join("\n")}
389
401
  EOF
390
402
  end
391
403
  def account_and_transfer_graphs(accounts, options={})
392
- "#{accounts.map{|account|
404
+ "#{accounts.map{|account|
393
405
  account_info = account.info
394
406
  #ep ['accountbadf', account, account_info]
395
407
  start_dates, dates, expenditures, _items = account_expenditure(account)
@@ -416,11 +428,11 @@ EOF
416
428
  kit.xlabel = nil
417
429
  kit.ylabel = nil
418
430
  unless options[:transfers]
419
- kits = accounts_with_averages({account => account_info}).map{|account, account_info|
431
+ kits = accounts_with_averages({account => account_info}).map{|acco, acco_info|
420
432
  #ep 'Budget is ', account
421
433
  kit2 = GraphKit.quick_create([
422
- [dates[0], dates[-1]].map{|d| d.to_time.to_i - barsize},
423
- [account.average, account.average]
434
+ [dates[0], dates[-1]].map{|d| d.to_time.to_i - barsize},
435
+ [acco.average, acco.average]
424
436
  ])
425
437
  kit2.data[0].gp.with = 'l lw 5'
426
438
  kit2
@@ -436,7 +448,7 @@ EOF
436
448
  CodeRunner::Budget.kit_time_format_x(kit)
437
449
  #kit.gnuplot
438
450
  #ep ['kit1122', account, kit]
439
- fork do
451
+ fork do
440
452
  kit.gnuplot_write("#{account.name_c_file}.eps", size: "4.0in,2.0in")
441
453
  exec "epspdf #{account.name_c_file}.eps"
442
454
  end
@@ -487,8 +499,8 @@ This section sums items from accounts drawn from an alternate account, i.e. it d
487
499
 
488
500
  \\Tstrut
489
501
 
490
- #{piece.map{|r|
491
- ([:id] + CodeRunner::Budget.rcp.component_results - [:sc]).map{|res|
502
+ #{piece.map{|r|
503
+ ([:id] + CodeRunner::Budget.rcp.component_results - [:sc]).map{|res|
492
504
  r.send(res).to_s.latex_escape
493
505
  #rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
494
506
  }.join(" & ")
@@ -517,12 +529,12 @@ EOF
517
529
  def account_breakdown
518
530
  <<EOF
519
531
  \\section{SubAccount Breakdown}
520
- #{(@actual_accounts).map{|account, account_info|
532
+ #{(@actual_accounts).map{|account, account_info|
521
533
  _start_dates, dates, expenditures, account_items = account_expenditure(account, account_info)
522
534
  #pp account, account_items.map{|items| items.map{|i| i.date.to_s}}
523
- "\\subsection{#{account}}" +
535
+ "\\subsection{#{account}}" +
524
536
  account_items.zip(dates, expenditures).map{|items, date, expenditure|
525
- if items.size > 0
537
+ if items.size > 0
526
538
  "
527
539
  \\small
528
540
  \\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 3 + " L " + " r " * 2 + " c " }}
@@ -530,8 +542,8 @@ EOF
530
542
  #{date.to_s.latex_escape} & & & Total & #{expenditure} & \\\\
531
543
  \\hline
532
544
  \\Tstrut
533
- #{items.map{|r|
534
- ( CodeRunner::Budget.rcp.component_results + [:external_account] - [:sc, :balance ]).map{|res|
545
+ #{items.map{|r|
546
+ ( CodeRunner::Budget.rcp.component_results + [:external_account] - [:sc, :balance ]).map{|res|
535
547
  r.send(res).to_s.latex_escape
536
548
  }.join(" & ")
537
549
  }.join("\\\\\n")
@@ -541,7 +553,7 @@ EOF
541
553
  \\end{tabulary}
542
554
  \\normalsize
543
555
  \\vspace{1em}\n\n"
544
- else
556
+ else
545
557
  ""
546
558
  end
547
559
  }.join("\n\n")
@@ -553,7 +565,7 @@ EOF
553
565
  def transactions_by_account
554
566
  <<EOF
555
567
  \\section{Recent Transactions}
556
- #{@accounts.find_all{|acc| not acc.type == :Equity}.sort_by{|acc| acc.external ? 0 : 1}.map{|acc|
568
+ #{@accounts.find_all{|acc| not acc.type == :Equity}.sort_by{|acc| acc.external ? 0 : 1}.map{|acc|
557
569
  "\\subsection{#{acc.name_c}}
558
570
  \\tiny
559
571
  #{all = acc.runs.find_all{|r| r.days_ago(@today) < @days_before}
@@ -566,10 +578,10 @@ EOF
566
578
  #ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
567
579
  all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
568
580
  "\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 3 + " l " + " r " * 3 + "l"}}
569
- #{piece.map{|r|
570
- (CodeRunner::Budget.rcp.component_results - [:sc] + [:sub_account]).map{|res|
581
+ #{piece.map{|r|
582
+ (CodeRunner::Budget.rcp.component_results - [:sc] + [:sub_account]).map{|res|
571
583
  entry = r.send(res).to_s.latex_escape
572
- #if
584
+ #if
573
585
  entry = entry[0...25] if entry.length > 25
574
586
  #if entry.length > 40
575
587
  #entry = entry.split(/.{40}/).join(" \\newline ")
@@ -596,9 +608,9 @@ EOF
596
608
  \\usepackage{libertine}
597
609
  \\usepackage{xcolor,listings}
598
610
  \\newcommand\\Tstrut{\\rule{0pt}{2.8ex}}
599
- \\newcommand\\myfigure[1]{\\vspace*{0em}\\begin{center}
611
+ \\newcommand\\myfigure[1]{\\vspace*{1em}\\begin{center}
600
612
 
601
- \\includegraphics[width=0.9\\textwidth]{#1}
613
+ \\includegraphics[width=0.99\\textwidth]{#1}
602
614
 
603
615
  \\end{center}\\vspace*{0em}
604
616
 
@@ -636,10 +648,10 @@ EOF
636
648
  end
637
649
  end
638
650
  #\\subsection{Last Week}
639
- ##{expense_pie_charts_by_currency('lastweekexpenses', @expense_accounts){|r|
640
- ##p ['r.daysago', r.days_ago(@today)];
641
- #r.days_ago(@today) < 7}}
651
+ ##{expense_pie_charts_by_currency('lastweekexpenses', @expense_accounts){|r|
652
+ ##p ['r.daysago', r.days_ago(@today)];
653
+ #r.days_ago(@today) < 7}}
642
654
  #\\subsection{Last Month}
643
- ##{expense_pie_charts_by_currency('lastmonthexpenses', @expense_accounts){|r| r.days_ago(@today) < 30}}
655
+ ##{expense_pie_charts_by_currency('lastmonthexpenses', @expense_accounts){|r| r.days_ago(@today) < 30}}
644
656
  #\\subsection{Last Year}
645
- ##{expense_pie_charts_by_currency('lastyearexpenses', @expense_accounts){|r| r.days_ago(@today) < 365}}
657
+ ##{expense_pie_charts_by_currency('lastyearexpenses', @expense_accounts){|r| r.days_ago(@today) < 365}}
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.6.0 ruby lib
5
+ # stub: treasurer 0.7.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "treasurer".freeze
9
- s.version = "0.6.0"
9
+ s.version = "0.7.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-04-05"
14
+ s.date = "2018-04-06"
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]
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.6.0
4
+ version: 0.7.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-04-05 00:00:00.000000000 Z
11
+ date: 2018-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport