budgetcrmod 0.2.2 → 0.2.3
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/budgetcrmod.gemspec +3 -3
- data/lib/budgetcrmod/budget.rb +646 -651
- 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: 690a66a464147f4818488e427d9556a46a2f5352
|
4
|
+
data.tar.gz: 90406cb37a7885adf871b362c44e52049747fc66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c12a9b4c4a0b764f3f3c003970dcb6a6bcb358fcfdb4d5c6da95c96aef192b00fe8539c259463ef9e74df93d50bcac6759ed0f85a8a25f8a29ae5a57cd74ddd7
|
7
|
+
data.tar.gz: 5c0b29941d7ae468b5eb6ccf51dcc89baeb8e6e0c454c4c1608a4e55144ffd635294c2c8f73ff7b6d95700eb9604e2c9112dd0fd462858226c109833d7af81ba
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/budgetcrmod.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: budgetcrmod 0.2.
|
5
|
+
# stub: budgetcrmod 0.2.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "budgetcrmod".freeze
|
9
|
-
s.version = "0.2.
|
9
|
+
s.version = "0.2.3"
|
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-04-09"
|
15
15
|
s.description = "A CodeRunner module to help you do your budget".freeze
|
16
16
|
s.email = "edmundhighcock@users.sourceforge.net".freeze
|
17
17
|
s.extra_rdoc_files = [
|
data/lib/budgetcrmod/budget.rb
CHANGED
@@ -1,86 +1,78 @@
|
|
1
|
-
class Float
|
2
|
-
def to_str
|
3
|
-
sprintf("%.2f", self)
|
4
|
-
end
|
5
|
-
def to_s
|
6
|
-
sprintf("%.2f", self)
|
7
|
-
end
|
8
|
-
end
|
9
1
|
require 'date'
|
10
2
|
class String
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
def latex_escape
|
4
|
+
self.gsub(/(?<!\\)([$%_&^])/, '\\\\\1')
|
5
|
+
end
|
6
|
+
#alias :old_to_f :to_f
|
7
|
+
#def to_f
|
8
|
+
#gsub(/,/, '').old_to_f
|
9
|
+
#end
|
18
10
|
end
|
19
11
|
|
20
12
|
class Date
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
13
|
+
attr_accessor :sortsign
|
14
|
+
def -@
|
15
|
+
#@sortsign ? @sortsign *= -1 : (@sortsign=-1)
|
16
|
+
newdate = dup
|
17
|
+
newdate.sortsign = -1
|
18
|
+
newdate
|
19
|
+
end
|
20
|
+
alias :oldcompare :<=>
|
29
21
|
def <=>(other)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
oldres = oldcompare(other)
|
23
|
+
oldres *= -1 if @sortsign==-1 and other.sortsign == -1
|
24
|
+
oldres
|
25
|
+
end
|
34
26
|
end
|
35
27
|
|
36
28
|
require 'date'
|
37
29
|
class CodeRunner
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# ["05/07/2010",
|
51
|
-
# "DEB",
|
52
|
-
# "308760",
|
53
|
-
# "25387560",
|
54
|
-
# "ANGELSCD 0655",
|
55
|
-
# "",
|
56
|
-
# "11.50",
|
57
|
-
# "4506.80"]
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
30
|
+
class Budget < Run
|
31
|
+
@code_long = "Budget Calculator"
|
32
|
+
@uses_mpi = false
|
33
|
+
@naming_pars = []
|
34
|
+
@run_info = []
|
35
|
+
@variables = [:data_file, :account]
|
36
|
+
@excluded_sub_folders = []
|
37
|
+
@modlet_required = false
|
38
|
+
@defaults_file_name = "budget_defaults.rb"
|
39
|
+
|
40
|
+
@code_module_folder = File.dirname(File.expand_path(__FILE__)) # i.e. the directory this file is in
|
41
|
+
|
42
|
+
# ["05/07/2010",
|
43
|
+
# "DEB",
|
44
|
+
# "308760",
|
45
|
+
# "25387560",
|
46
|
+
# "ANGELSCD 0655",
|
47
|
+
# "",
|
48
|
+
# "11.50",
|
49
|
+
# "4506.80"]
|
50
|
+
#
|
51
|
+
@component_results = [:date, :type, :sc, :ac, :description, :deposit, :withdrawal, :balance]
|
52
|
+
@results = [:date_i, :data, :data_line, :dataset] + @component_results
|
53
|
+
def generate_input_file
|
54
|
+
FileUtils.cp @data_file.sub(/~/, ENV['HOME']), @directory + '/data.cvs'
|
55
|
+
end
|
56
|
+
def debit
|
57
|
+
case @account_type
|
58
|
+
when :Asset, :Expense
|
59
|
+
deposit
|
60
|
+
else
|
61
|
+
withdrawal
|
62
|
+
end
|
63
|
+
end
|
64
|
+
def credit
|
65
|
+
case @account_type
|
66
|
+
when :Asset, :Expense
|
67
|
+
withdrawal
|
68
|
+
else
|
69
|
+
deposit
|
70
|
+
end
|
71
|
+
end
|
72
|
+
DOUBLE_STRING=/"(?:\\\\|\\"|[^"\\]|\\[^"\\])*"/
|
73
|
+
def process_directory_code_specific
|
74
|
+
@status=:Complete
|
75
|
+
data = File.read('data.cvs')
|
84
76
|
#p ['encoding', data.encoding]
|
85
77
|
#data.encode(Encoding::UTF_8)
|
86
78
|
tries = 1
|
@@ -98,128 +90,132 @@ class CodeRunner
|
|
98
90
|
retry
|
99
91
|
end
|
100
92
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
93
|
+
if data[0] =~ /^\d{2} \w{3} \d\d,/ # BarclayCard format
|
94
|
+
data.unshift 'date,description,type,user,expensetype,withdrawal,withdrawal'
|
95
|
+
end
|
104
96
|
|
105
|
-
|
106
|
-
|
107
|
-
|
97
|
+
@first_line_string = data[0].dup
|
98
|
+
data = data.map do |line|
|
99
|
+
matches = line.scan(Regexp.new("((?:#{DOUBLE_STRING}|[^,])*)(?:,|$)"))
|
108
100
|
pp matches
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
101
|
+
matches.flatten
|
102
|
+
end
|
103
|
+
#pp data
|
104
|
+
@data = data
|
105
|
+
@first_line = @data.shift.join(',')
|
114
106
|
generate_component_runs
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
107
|
+
end
|
108
|
+
#def reversed?
|
109
|
+
#case account_type(@account)
|
110
|
+
#when :Asset
|
111
|
+
#@first_line =~ /Debit.*Credit/
|
112
|
+
#end
|
113
|
+
#end
|
114
|
+
def print_out_line
|
115
|
+
if @is_component
|
116
|
+
sprintf("%4d. %10s %10s %3s %-40s %8s %8s %8s %8s %8s", id, account, *rcp.component_results.find_all{|r| r!=:ac and r!=:sc}.map{|res| send(res).to_s.gsub(/\s+/, ' ')}, external_account, sub_account)
|
117
|
+
else
|
118
|
+
#pr = component_runs.sort_by{|r| r.id}
|
119
|
+
"#{sprintf("%3d", @id)}. #{sprintf("%-20s", @account)} Start: #{start_date} End: #{end_date} Final Balance: #{final_balance} "
|
120
|
+
end
|
121
|
+
end
|
122
|
+
def date_sorted_component
|
123
|
+
@date_sorted_component ||= component_runs.sort_by{|r| r.id}
|
124
|
+
end
|
125
|
+
def end_date
|
126
|
+
date_sorted_component[-1].date rescue nil
|
127
|
+
end
|
128
|
+
def start_date
|
129
|
+
date_sorted_component[0].date rescue nil
|
130
|
+
end
|
131
|
+
def final_balance
|
132
|
+
date_sorted_component[-1].balance rescue nil
|
133
|
+
end
|
134
|
+
def parameter_transition(run)
|
135
|
+
end
|
136
|
+
def parameter_string
|
137
|
+
""
|
138
|
+
end
|
147
139
|
#def external_account
|
148
|
-
|
149
|
-
|
140
|
+
#name = super
|
141
|
+
#if ACCOUNT_INFO[name] and ACCOUNT_INFO[name][:currencies].size > 2
|
150
142
|
#end
|
151
143
|
#def sub_account
|
152
144
|
#end
|
153
145
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
146
|
+
def sub_account
|
147
|
+
cache[:sub_account] ||= super
|
148
|
+
end
|
149
|
+
def external_account
|
150
|
+
cache[:external_account] ||= super
|
151
|
+
end
|
152
|
+
|
153
|
+
#def external_account
|
154
|
+
#(budget.to_s + '_' + sub_account.to_s).to_sym
|
155
|
+
#end
|
156
|
+
|
157
|
+
def csv_data_fields
|
158
|
+
case @first_line_string
|
159
|
+
when /Date,Type,Sort Code,Account Number,Description,In,Out,Balance/ # Old Lloyds Bank Format
|
160
|
+
[:date, :type, :sc, :ac, :description, :deposit, :withdrawal, :balance]
|
161
|
+
when /Transaction Date,Transaction Type,Sort Code,Account Number,Transaction Description,Debit Amount,Credit Amount,Balance/ # 2013 Lloyds Bank Format, NB they are using debit and credit as if the account is an equity account (when of course a bank account is really an asset)
|
162
|
+
[:date, :type, :sc, :ac, :description, :withdrawal, :deposit, :balance]
|
163
|
+
when /Date,Date entered,Reference,Description,Amount/ # Lloyds Credit Card statement
|
164
|
+
[:date, :dummy, :dummy, :description, :withdrawal]
|
165
|
+
when /date,description,type,user,expensetype,withdrawal,withdrawal/
|
166
|
+
[:date,:description,:type,:dummy,:dummy, :withdrawal, :withdrawal]
|
175
167
|
when /Datum,Transaktion,Kategori,Belopp,Saldo/ # Nordea.se privat, Belopp is positive when the asset increases
|
176
168
|
[:date,:description,:dummy,:deposit,:balance]
|
177
169
|
when /Bokföringsdatum,Transaktionsreferens,Mottagare,Belopp,Valuta/ # Forex.se privat, Belopp is positive when the asset increases
|
178
170
|
[:date,:description,:dummy,:deposit,:dummy]
|
179
171
|
when /Datum,Text,Belopp/ #Ecster Credit Card
|
180
|
-
[:date,:description,:
|
172
|
+
[:date,:description,:deposit]
|
181
173
|
when /Effective Date,Entered Date,Transaction Description,Amount/ #QudosBank, the first field is blank
|
182
174
|
[:dummy,:date,:description,:deposit]
|
183
|
-
|
184
|
-
|
175
|
+
when /Date,Amount,Currency,Description,"Payment Reference","Running Balance","Exchange Rate","Payer Name","Payee Name","Payee Account Number",Merchant/ #TransferWise
|
176
|
+
[:date,:deposit,:dummy,:description,:dummy,:balance,:dummy,:dummy,:dummy,:dummy,:dummy]
|
177
|
+
end
|
178
|
+
end
|
185
179
|
|
186
|
-
|
187
|
-
|
188
|
-
|
180
|
+
#def withdrawn
|
181
|
+
#@withdrawn||0.0
|
182
|
+
#end
|
189
183
|
|
190
|
-
|
191
|
-
|
192
|
-
|
184
|
+
def has_balance?
|
185
|
+
@has_balance ||= csv_data_fields.include? :balance
|
186
|
+
end
|
193
187
|
|
194
|
-
|
188
|
+
attr_accessor :dummy
|
195
189
|
|
196
190
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
191
|
+
def set_zeroes
|
192
|
+
@withdrawal||=0.0
|
193
|
+
@deposit||=0.0
|
194
|
+
end
|
195
|
+
def generate_component_runs
|
202
196
|
#puts Kernel.caller
|
203
197
|
#p ['generate_component_runs', @component_runs.class, (@component_runs.size rescue nil), @runner.component_run_list.size, @directory]
|
204
198
|
return if @component_runs and @component_runs.size > 0
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
next if @runner.component_run_list.map{|k,v| v.instance_variable_get(:@dataset)}.include? dataset # and Date.parse(dataset[0]) > Date.parse("1/1/2013")
|
199
|
+
@runner.cache[:data] ||= []
|
200
|
+
#reslts = rcp.component_results
|
201
|
+
#if reversed?
|
202
|
+
#reslts[5] = :withdrawal
|
203
|
+
#reslts[6] = :deposit
|
204
|
+
#end
|
205
|
+
@data.each do |dataset|
|
206
|
+
#next if @runner.cache[:data].include? dataset and Date.parse(dataset[0]) > Date.parse("1/1/2013")
|
207
|
+
#next if @runner.component_run_list.map{|k,v| v.instance_variable_get(:@dataset)}.include? dataset # and Date.parse(dataset[0]) > Date.parse("1/1/2013")
|
208
|
+
next if @runner.component_run_list.find{|k,v| v.dataset == dataset} # and Date.parse(dataset[0]) > Date.parse("1/1/2013")
|
214
209
|
next if @first_line_string =~ /^Datum/ and dataset[1] =~ /Reservation/
|
215
|
-
|
210
|
+
component = create_component
|
211
|
+
component.set_zeroes
|
216
212
|
ep 'Generating Component', @component_runs.size
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
213
|
+
reslts = csv_data_fields
|
214
|
+
reslts.each_with_index do |res,index|
|
215
|
+
value = dataset[index]
|
216
|
+
#ep value
|
217
|
+
value = Date.parse value if res == :date
|
218
|
+
if [:deposit, :withdrawal, :balance].include? res
|
223
219
|
case @first_line_string
|
224
220
|
when /^Datum/i # we are dealing with European numbers
|
225
221
|
value = value.gsub(/[." ]/, '')
|
@@ -227,494 +223,493 @@ class CodeRunner
|
|
227
223
|
else
|
228
224
|
value = value.gsub(/[",]/, '')
|
229
225
|
end
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
component.
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
end
|
226
|
+
next unless value =~ /\d/
|
227
|
+
value = value.to_f
|
228
|
+
end
|
229
|
+
component.set(res, value)
|
230
|
+
end
|
231
|
+
component.set(:data_line, reslts.map{|r| component.send(r).to_s}.join(','))
|
232
|
+
component.set(:dataset, dataset)
|
238
233
|
component.date_i = component.date.to_datetime.to_time.to_i
|
239
234
|
if component.deposit < 0.0 and component.withdrawal == 0.0
|
240
235
|
component.withdrawal = -component.deposit
|
241
236
|
component.deposit = 0.0
|
242
237
|
end
|
243
|
-
|
238
|
+
@runner.cache[:data].push dataset
|
244
239
|
component.external_account; component.sub_account # Triggers interactive account choices
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
# sprintf("%04d%02d%02d", date.year, date.month, date.day).to_i
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
## ep item
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
#"#{budgets.map{|budget, budget_info|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
#}.join("\n\n")
|
495
|
-
#}"
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
#\\documentclass{article}
|
525
|
-
#\\usepackage[cm]{fullpage}
|
526
|
-
#\\usepackage{tabulary}
|
527
|
-
#\\usepackage{graphicx}
|
528
|
-
#%\\usepackage{hyperlink}
|
529
|
-
#\\newcommand\\Tstrut{\\rule{0pt}{2.8ex}}
|
530
|
-
#\\begin{document}
|
531
|
-
#\\title{#{numdays}-day Budget Report}
|
532
|
-
#\\maketitle
|
533
|
-
#\\tableofcontents
|
534
|
-
|
535
|
-
#\\section{Summary of Accounts}
|
536
|
-
##{accounts.map{|acc|
|
537
|
-
#"\\subsection{#{acc}}
|
538
|
-
#\\begin{tabulary}{0.8\\textwidth}{ r l}
|
539
|
-
###Balance & #{runs.find_all{|r| r.account==acc}.sort_by{|r|
|
540
|
-
|
541
|
-
###}[-1].balance} \\\\
|
542
|
-
#####Expenditure & #{runs.find_all{|r| r.account==acc &&
|
543
|
-
|
544
|
-
#####}.map{|r|
|
545
|
-
|
546
|
-
#####}.sum} \\\\
|
547
|
-
###Income & #{runs.find_all{|r| r.account==acc &&
|
548
|
-
|
549
|
-
###}.map{|r| r.credit}.sum} \\\\
|
550
|
-
#\\end{tabulary}"}.join("\n\n")
|
551
|
-
#}
|
552
|
-
|
553
|
-
#\\section{Graphs of Recent Balances}
|
554
|
-
##{accounts.map{|acc|
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
#}.join("\n\n")
|
595
|
-
#}
|
596
|
-
|
597
|
-
|
598
|
-
#\\section{Budget Expenditure}
|
599
|
-
##{latex_budget_transfers(runner,actual_budgets, options)}
|
600
|
-
|
601
|
-
#\\section{Transfers}
|
602
|
-
##{latex_budget_transfers(runner, TRANSFERS, options.dup.absorb({transfers: true}))}
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
#\\section{Budget Resolutions}
|
607
|
-
|
608
|
-
#This section sums items from budgets drawn from an alternate account, i.e. it determines how much should be transferred from one account to another as a result of expenditure from a given budget.
|
609
|
-
|
610
|
-
##{actual_budgets.map{|budget, budget_info|
|
611
|
-
|
612
|
-
########################################"\\subsection{#{budget} }
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
240
|
+
#component.account = @account
|
241
|
+
end
|
242
|
+
end
|
243
|
+
def days_ago(today = Date.today)
|
244
|
+
#ep ['today', today, date]
|
245
|
+
# sprintf("%04d%02d%02d", date.year, date.month, date.day).to_i
|
246
|
+
#cache[:days_ago] ||= {}
|
247
|
+
#cache[:days_ago][today.to_s] ||=
|
248
|
+
- ((date.to_datetime.to_time.to_i - today.to_datetime.to_time.to_i) / 24 / 3600).to_i
|
249
|
+
end
|
250
|
+
def idate
|
251
|
+
date.to_datetime.to_time.to_i
|
252
|
+
end
|
253
|
+
def ds
|
254
|
+
description
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
#def self.sum_future(future_items, end_date, options={})
|
259
|
+
#sum = future_items.inject(0) do |sum, (name, item)|
|
260
|
+
#item = [item] unless item.kind_of? Array
|
261
|
+
#value = item.inject(0) do |value,info|
|
262
|
+
#value += info[:size] unless (options[:today]||Date.today > info[:date]) or (info[:date] > end_date) # add unless we have already passed that date
|
263
|
+
#value
|
264
|
+
#end
|
265
|
+
#rcp.excluding.include?(name) ? sum : sum + value
|
266
|
+
#end
|
267
|
+
#sum
|
268
|
+
#end
|
269
|
+
|
270
|
+
#def self.budget_expenditure(runner, budget, budget_info, start_date, options={})
|
271
|
+
#dates = []
|
272
|
+
#expenditures = []
|
273
|
+
#budget_items = []
|
274
|
+
#date = budget_info[:end]||options[:today]||Date.today
|
275
|
+
#start_date = [(budget_info[:start]||start_date), start_date].max
|
276
|
+
#expenditure = 0
|
277
|
+
#items_temp = []
|
278
|
+
#items = runner.component_run_list.values.find_all{|r| r.budget == budget and r.in_date(budget_info)}
|
279
|
+
##ep ['items', items]
|
280
|
+
##ep ['budget', budget]
|
281
|
+
#counter = 0
|
282
|
+
#if not budget_info[:period]
|
283
|
+
#dates.push date
|
284
|
+
#budget_items.push items
|
285
|
+
#expenditures.push (items.map{|r| r.debit - r.credit}+[0]).sum
|
286
|
+
#else
|
287
|
+
|
288
|
+
#case budget_info[:period][1]
|
289
|
+
#when :month
|
290
|
+
#while date > start_date
|
291
|
+
#items_temp += items.find_all{|r| r.date == date}
|
292
|
+
#if date.mday == (budget_info[:monthday] or 1)
|
293
|
+
#counter +=1
|
294
|
+
#if counter % budget_info[:period][0] == 0
|
295
|
+
#expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
|
296
|
+
#dates.push date
|
297
|
+
#expenditures.push expenditure
|
298
|
+
#budget_items.push items_temp
|
299
|
+
#items_temp = []
|
300
|
+
#expenditure = 0
|
301
|
+
#end
|
302
|
+
#end
|
303
|
+
#date-=1
|
304
|
+
#end
|
305
|
+
#when :day
|
306
|
+
#while date > start_date
|
307
|
+
#items_temp += items.find_all{|r| r.date == date}
|
308
|
+
##expenditure += (budget_items[-1].map{|r| r.debit}+[0]).sum
|
309
|
+
#counter +=1
|
310
|
+
#if counter % budget_info[:period][0] == 0
|
311
|
+
#expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
|
312
|
+
#dates.push date
|
313
|
+
#expenditures.push expenditure
|
314
|
+
#budget_items.push items_temp
|
315
|
+
#items_temp = []
|
316
|
+
#expenditure = 0
|
317
|
+
#end
|
318
|
+
#date-=1
|
319
|
+
#end
|
320
|
+
#end
|
321
|
+
#end
|
322
|
+
|
323
|
+
#[dates, expenditures, budget_items]
|
324
|
+
|
325
|
+
#end
|
326
|
+
|
327
|
+
#def self.sum_regular(regular_items, end_date, options={})
|
328
|
+
#today = options[:today]||Date.today
|
329
|
+
#sum = regular_items.inject(0) do |sum, (name, item)|
|
330
|
+
#item = [item] unless item.kind_of? Array
|
331
|
+
## ep item
|
332
|
+
#value = item.inject(0) do |value,info|
|
333
|
+
#finish = (info[:end] and info[:end] < end_date) ? info[:end] : end_date
|
334
|
+
##today = (Time.now.to_i / (24.0*3600.0)).round
|
335
|
+
|
336
|
+
#nunits = 0
|
337
|
+
#counter = info[:period][0] == 1 ? 0 : nil
|
338
|
+
#####################unless counter
|
339
|
+
#####################date = today
|
340
|
+
#####################counter = 0
|
341
|
+
#####################case info[:period][1]
|
342
|
+
#####################when :month
|
343
|
+
#####################while date >= (info[:start] or Date.today)
|
344
|
+
#####################counter +=1 if date.mday == (info[:monthday] or 1)
|
345
|
+
#####################date -= 1
|
346
|
+
#####################end
|
347
|
+
#####################when :year
|
348
|
+
#####################while date >= (info[:start] or Date.today)
|
349
|
+
#####################counter +=1 if date.yday == (info[:yearday] or 1)
|
350
|
+
#####################date -= 1
|
351
|
+
#####################end
|
352
|
+
#####################when :day
|
353
|
+
#####################while date > (info[:start] or Date.today)
|
354
|
+
#####################counter +=1
|
355
|
+
#####################date -= 1
|
356
|
+
#####################end
|
357
|
+
#####################end
|
358
|
+
#####################end
|
359
|
+
#date = today
|
360
|
+
#########################case info[:period][1]
|
361
|
+
#########################when :month
|
362
|
+
##########################p date, info
|
363
|
+
#########################while date <= finish
|
364
|
+
#########################if date.mday == (info[:monthday] or 1)
|
365
|
+
#########################nunits += 1 if counter % info[:period][0] == 0
|
366
|
+
#########################counter +=1
|
367
|
+
#########################end
|
368
|
+
#########################date += 1
|
369
|
+
#########################end
|
370
|
+
#########################when :year
|
371
|
+
#########################while date <= finish
|
372
|
+
#########################if date.yday == (info[:yearday] or 1)
|
373
|
+
#########################nunits += 1 if counter % info[:period][0] == 0
|
374
|
+
#########################counter +=1
|
375
|
+
#########################end
|
376
|
+
#########################date += 1
|
377
|
+
#########################end
|
378
|
+
#########################when :day
|
379
|
+
#########################while date <= finish
|
380
|
+
#########################nunits += 1 if counter % info[:period][0] == 0
|
381
|
+
#########################counter +=1
|
382
|
+
#########################date += 1
|
383
|
+
#########################end
|
384
|
+
#########################end
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
##nyears = (finish.year - today.year)
|
391
|
+
##nmonths = nyears * 12 + (finish.month - today.month)
|
392
|
+
##(puts "Number of Months: #{nmonths}"; @pnmonths=true) unless @pnmonths
|
393
|
+
##ndays = nyears * 12 + (finish.yday - today.yday)
|
394
|
+
##number = case info[:period][1]
|
395
|
+
##when :month
|
396
|
+
##(nmonths / info[:period][0]).ceil
|
397
|
+
##when :day
|
398
|
+
##(ndays / info[:period][0]).ceil
|
399
|
+
##end
|
400
|
+
##value + number * info[:size]
|
401
|
+
##eputs "Regular Expenditure Item: #{sprintf("%10s", name)} -- #{nunits} payments, total #{nunits * info[:size]}"
|
402
|
+
#value + nunits * info[:size]
|
403
|
+
|
404
|
+
#end
|
405
|
+
#(rcp.excluding? and rcp.excluding.include?(name)) ? sum : sum + value
|
406
|
+
#end
|
407
|
+
#sum
|
408
|
+
#end
|
409
|
+
def self.predictable_component_ids(runner)
|
410
|
+
#runner.instance_variable_set(:@component_run_list, {})
|
411
|
+
#runner.instance_variable_set(:@component_ids, [])
|
412
|
+
#runner.instance_variable_set(:@component_id, -1)
|
413
|
+
#runner.run_list.each{|r| r.instance_variable_set(:@component_runs, [])}
|
414
|
+
#runner.run_list.values.sort_by{|r| r.id}.each{|r| r.generate_component_runs}
|
415
|
+
#runner.save_large_cache
|
416
|
+
end
|
417
|
+
def self.kit_time_format_x(kit)
|
418
|
+
kit.gp.timefmt = %["%s"]
|
419
|
+
kit.data.each{|dk| dk.gp.using = "1:2"}
|
420
|
+
kit.gp.xdata = "time"
|
421
|
+
kit.gp.format = %[x "%d %B %Y"]
|
422
|
+
kit.gp.format = [%[x "%b %Y"]]
|
423
|
+
kit.gp.mxtics = "30"
|
424
|
+
kit.gp.xtics = "rotate by 340 offset 0,-0.5 #{24*3600*14}"
|
425
|
+
kit.gp.xtics = "rotate by 340 offset 0,-0.5 2629746"
|
426
|
+
end
|
427
|
+
|
428
|
+
def self.print_budget(options={})
|
429
|
+
@excluding = (options[:excluding] or [])
|
430
|
+
runner = CodeRunner.fetch_runner(Y: Dir.pwd)
|
431
|
+
puts "------------------------------"
|
432
|
+
puts " Budget Report"
|
433
|
+
puts "------------------------------"
|
434
|
+
balance = runner.component_run_list.values.sort_by{|r| [r.date, r.id]}.map{|r| r.balance}[-1]
|
435
|
+
puts "Balance: #{balance}"
|
436
|
+
end_date = Date.parse("01/10/2011")
|
437
|
+
puts "Regular Expenditure: #{total_regular = sum_regular(REGULAR_EXPENDITURE, end_date)}"
|
438
|
+
puts "Future Expenditure: #{total_future = sum_future(FUTURE_EXPENDITURE, end_date)}"
|
439
|
+
puts "Total Expenditure: #{total_expenditure = total_future + total_regular}"
|
440
|
+
puts "Total Income: #{total_incoming = sum_future(FUTURE_INCOME, end_date)}"
|
441
|
+
total = balance + total_incoming - total_expenditure
|
442
|
+
puts "Weekly Budget: #{total/((end_date.to_datetime.to_time.to_i - Time.now.to_i) / 3600 / 24 / 7)}"
|
443
|
+
end
|
444
|
+
|
445
|
+
#def self.budgets_with_averages(runner, budgets, start_date, options={})
|
446
|
+
#projected_budgets = budgets.dup
|
447
|
+
#projected_budgets.each{|key,v| projected_budgets[key]=projected_budgets[key].dup}
|
448
|
+
#projected_budgets.each do |budget, budget_info|
|
449
|
+
##budget_info = budgets[budget]
|
450
|
+
#dates, expenditures, items = budget_expenditure(runner, budget, budget_info, start_date, today: options[:today])
|
451
|
+
#budget_info[:size] = expenditures.mean rescue 0.0
|
452
|
+
#end
|
453
|
+
#projected_budgets
|
454
|
+
#end
|
455
|
+
|
456
|
+
#def self.latex_budget_transfers(runner, budgets, options)
|
457
|
+
#numdays = options[:days]
|
458
|
+
#today = options[:today]||Date.today
|
459
|
+
#"#{budgets.map{|budget, budget_info|
|
460
|
+
#dates, expenditures, items = budget_expenditure(runner, budget, budget_info, today - numdays, today: options[:today])
|
461
|
+
##ep ['budget', budget, dates, expenditures]
|
462
|
+
#kit = GraphKit.quick_create([dates.map{|d| d.to_time.to_i}, expenditures])
|
463
|
+
#kit.data.each{|dk| dk.gp.with="boxes"}
|
464
|
+
#kit.gp.style = "fill solid"
|
465
|
+
#kit.xlabel = nil
|
466
|
+
#kit.ylabel = "Expenditure"
|
467
|
+
#unless options[:transfers]
|
468
|
+
#kits = budgets_with_averages(runner, {budget => budget_info}, today - numdays, today: today).map{|budget, budget_info|
|
469
|
+
##ep 'Budget is ', budget
|
470
|
+
#kit2 = GraphKit.quick_create([
|
471
|
+
#[dates[0], dates[-1]].map{|d| d.to_time.to_i},
|
472
|
+
#[budget_info[:size], budget_info[:size]]
|
473
|
+
#])
|
474
|
+
#kit2.data[0].gp.with = 'lp lw 4'
|
475
|
+
#kit2
|
476
|
+
#}
|
477
|
+
##$debug_gnuplot = true
|
478
|
+
##kits.sum.gnuplot
|
479
|
+
#kit += kits.sum
|
480
|
+
|
481
|
+
#else
|
482
|
+
#kit.data[0].y.data.map!{|expen| expen*-1.0}
|
483
|
+
#end
|
484
|
+
#kit.title = "#{budget} Expenditure with average (Total = #{kit.data[0].y.data.sum})"
|
485
|
+
#kit_time_format_x(kit)
|
486
|
+
##kit.gnuplot
|
487
|
+
#kit.gnuplot_write("#{budget}.eps")
|
488
|
+
#"\\begin{center}\\includegraphics[width=4.0in]{#{budget}.eps}\\vspace{1em}\\end{center}"
|
489
|
+
#}.join("\n\n")
|
490
|
+
#}"
|
491
|
+
#end
|
492
|
+
|
493
|
+
#def self.latex_report(options={})
|
494
|
+
#runner = CodeRunner.fetch_runner(Y: Dir.pwd, h: :component)
|
495
|
+
#numdays = options[:days]
|
496
|
+
#today = options[:today] || Date.today
|
497
|
+
## Delete budgets that contain no items
|
498
|
+
#actual_budgets = BUDGETS.dup
|
499
|
+
#BUDGETS.keys.each do |budget|
|
500
|
+
#actual_budgets.delete(budget) if budget_expenditure(runner, budget, BUDGETS[budget], today - numdays, today: today)[0].size == 0
|
501
|
+
#end
|
502
|
+
##predictable_component_ids(runner)
|
503
|
+
#days_ahead = options[:days_ahead]
|
504
|
+
#runs = runner.component_run_list.values
|
505
|
+
#indateruns = runs.find_all{|r| r.days_ago < numdays}
|
506
|
+
#accounts = runs.map{|r| r.account}.uniq
|
507
|
+
#ep 'Accounts', accounts
|
508
|
+
#projected_budgets = Hash[actual_budgets.dup.find_all{|k,v| v[:discretionary]}]
|
509
|
+
#projected_budgets = budgets_with_averages(runner,projected_budgets, today - numdays, today: today)
|
510
|
+
##projected_budgets.each{|key,v| projected_budgets[key]=projected_budgets[key].dup}
|
511
|
+
##projected_budgets.each do |budget, budget_info|
|
512
|
+
###budget_info = budgets[budget]
|
513
|
+
##dates, expenditures, items = budget_expenditure(runner, budget, budget_info, today - numdays)
|
514
|
+
##budget_info[:size] = expenditures.mean
|
515
|
+
##end
|
516
|
+
#ep 'projected_budgets', projected_budgets
|
517
|
+
#File.open('report.tex', 'w') do |file|
|
518
|
+
#file.puts <<EOF
|
519
|
+
#\\documentclass{article}
|
520
|
+
#\\usepackage[cm]{fullpage}
|
521
|
+
#\\usepackage{tabulary}
|
522
|
+
#\\usepackage{graphicx}
|
523
|
+
#%\\usepackage{hyperlink}
|
524
|
+
#\\newcommand\\Tstrut{\\rule{0pt}{2.8ex}}
|
525
|
+
#\\begin{document}
|
526
|
+
#\\title{#{numdays}-day Budget Report}
|
527
|
+
#\\maketitle
|
528
|
+
#\\tableofcontents
|
529
|
+
|
530
|
+
#\\section{Summary of Accounts}
|
531
|
+
##{accounts.map{|acc|
|
532
|
+
#"\\subsection{#{acc}}
|
533
|
+
#\\begin{tabulary}{0.8\\textwidth}{ r l}
|
534
|
+
###Balance & #{runs.find_all{|r| r.account==acc}.sort_by{|r|
|
535
|
+
###r.date
|
536
|
+
###}[-1].balance} \\\\
|
537
|
+
#####Expenditure & #{runs.find_all{|r| r.account==acc &&
|
538
|
+
#####r.days_ago < numdays
|
539
|
+
#####}.map{|r|
|
540
|
+
#####r.debit
|
541
|
+
#####}.sum} \\\\
|
542
|
+
###Income & #{runs.find_all{|r| r.account==acc &&
|
543
|
+
###r.days_ago < numdays
|
544
|
+
###}.map{|r| r.credit}.sum} \\\\
|
545
|
+
#\\end{tabulary}"}.join("\n\n")
|
546
|
+
#}
|
547
|
+
|
548
|
+
#\\section{Graphs of Recent Balances}
|
549
|
+
##{accounts.map{|acc|
|
550
|
+
#balance = runs.find_all{|r| r.account==acc}.sort_by{|r| r.date }[-1].balance
|
551
|
+
#accshort = acc.gsub(/\s/, '')
|
552
|
+
#kit = runner.graphkit(['date.to_time.to_i', 'balance'], {conditions: "account == #{acc.inspect} and days_ago < #{numdays}", sort: 'date'})
|
553
|
+
#futuredates = (today..today+days_ahead).to_a
|
554
|
+
##p ["Regtrans", REGULAR_TRANSFERS.values_at(*REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc})]
|
555
|
+
|
556
|
+
#budgets = Hash[projected_budgets.find_all{|k,v| v[:account] == acc}]
|
557
|
+
#ep ['budgets', budgets]
|
558
|
+
#projection = futuredates.map{|date| balance -
|
559
|
+
#sum_regular(REGULAR_EXPENDITURE[acc], date, today: today) +
|
560
|
+
#sum_regular(REGULAR_INCOME[acc], date, today: today) -
|
561
|
+
#sum_regular(budgets, date, today: today) -
|
562
|
+
#sum_future(FUTURE_EXPENDITURE[acc], date, today: today) +
|
563
|
+
#sum_future(FUTURE_INCOME[acc], date, today: today) +
|
564
|
+
#(REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc}.map{|key|
|
565
|
+
##p [acc, 'to', "key", key]
|
566
|
+
#sum_regular( REGULAR_TRANSFERS[key], date, today: today)
|
567
|
+
#}.sum||0) -
|
568
|
+
#(REGULAR_TRANSFERS.keys.find_all{|from,to| from == acc}.map{|key|
|
569
|
+
##p [acc, 'from',"key", key]
|
570
|
+
#sum_regular( REGULAR_TRANSFERS[key], date, today: today)
|
571
|
+
#}.sum||0)
|
572
|
+
#}
|
573
|
+
#kit2 = GraphKit.quick_create([futuredates.map{|d| d.to_time.to_i}, projection])
|
574
|
+
#kit += kit2
|
575
|
+
#kit.title = "Balance for #{acc}"
|
576
|
+
#kit.xlabel = %['Date' offset 0,-2]
|
577
|
+
#kit.xlabel = nil
|
578
|
+
#kit.ylabel = "Balance"
|
579
|
+
|
580
|
+
#kit.data[0].gp.title = 'Previous'
|
581
|
+
#kit.data[1].gp.title = '0 GBP Discretionary'
|
582
|
+
#kit.data[1].gp.title = 'Projection'
|
583
|
+
#kit.data.each{|dk| dk.gp.with = "lp"}
|
584
|
+
|
585
|
+
#kit_time_format_x(kit)
|
586
|
+
|
587
|
+
#(kit).gnuplot_write("#{accshort}_balance.eps", size: "4.0in,3.0in")
|
588
|
+
#"\\begin{center}\\includegraphics[width=4.0in]{#{accshort}_balance.eps}\\end{center}"
|
589
|
+
#}.join("\n\n")
|
590
|
+
#}
|
591
|
+
|
592
|
+
|
593
|
+
#\\section{Budget Expenditure}
|
594
|
+
##{latex_budget_transfers(runner,actual_budgets, options)}
|
595
|
+
|
596
|
+
#\\section{Transfers}
|
597
|
+
##{latex_budget_transfers(runner, TRANSFERS, options.dup.absorb({transfers: true}))}
|
598
|
+
|
599
|
+
|
600
|
+
|
601
|
+
#\\section{Budget Resolutions}
|
602
|
+
|
603
|
+
#This section sums items from budgets drawn from an alternate account, i.e. it determines how much should be transferred from one account to another as a result of expenditure from a given budget.
|
604
|
+
|
605
|
+
##{actual_budgets.map{|budget, budget_info|
|
606
|
+
|
607
|
+
########################################"\\subsection{#{budget} }
|
608
|
+
########################################\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{r l}
|
609
|
+
########################################%\\hline
|
610
|
+
########################################Account Owed & Amount \\\\
|
611
|
+
########################################\\hline
|
612
|
+
########################################\\Tstrut
|
613
|
+
#########################################{budget_items = indateruns.find_all{|r| r.budget == budget}
|
619
614
|
########################################alternate_accounts = budget_items.map{|r| r.account}.uniq - [budget_info[:account]]
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
#########################################{ alternate_accounts.map{|acc|
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
########################################"
|
652
|
-
#}.join("\n\n")
|
653
|
-
#}
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
#\\section{Budget and Transfer Breakdown}
|
658
|
-
##{(TRANSFERS + actual_budgets).map{|budget, budget_info|
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
#}.join("\n\n")
|
687
|
-
#}
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
#\\section{Recent Transactions}
|
692
|
-
##{accounts.map{|acc|
|
693
|
-
|
694
|
-
#\\footnotesize
|
695
|
-
##{all = runs.find_all{|r| r.account == acc and r.days_ago < numdays}.sort_by{|r| [r.date, r.id]}.reverse
|
696
|
-
#ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
|
697
|
-
########all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
|
698
|
-
########"\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 + "l"}}
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
########}.join("\\\\\n")}
|
704
|
-
########\\end{tabulary}"}.join("\n\n")}"
|
705
|
-
#}.join("\n\n")}
|
706
|
-
#\\end{document}
|
707
|
-
#EOF
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
615
|
+
########################################alternate_accounts.map{|acc|
|
616
|
+
########################################alternate_items = budget_items.find_all{|r| r.account == acc}
|
617
|
+
########################################total = alternate_items.map{|r| r.debit - r.credit}.sum
|
618
|
+
########################################"#{acc} & #{total} \\\\"
|
619
|
+
########################################}.join("\n\n")
|
620
|
+
########################################}
|
621
|
+
|
622
|
+
########################################\\\\
|
623
|
+
########################################\\hline
|
624
|
+
########################################\\end{tabulary}
|
625
|
+
########################################\\normalsize
|
626
|
+
########################################\\vspace{1em}\n\n
|
627
|
+
|
628
|
+
#########################################{ alternate_accounts.map{|acc|
|
629
|
+
########################################alternate_items = budget_items.find_all{|r| r.account == acc}
|
630
|
+
########################################alternate_items.pieces((alternate_items.size.to_f/50.to_f).ceil).map{|piece|
|
631
|
+
########################################"\\footnotesize\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 }}
|
632
|
+
#########################################{budget}: & #{budget_info[:account]} & owes & #{acc} &&&&\\\\
|
633
|
+
########################################\\hline
|
634
|
+
|
635
|
+
########################################\\Tstrut
|
636
|
+
|
637
|
+
#########################################{piece.map{|r|
|
638
|
+
########################################([:id] + rcp.component_results - [:sc]).map{|res|
|
639
|
+
########################################r.send(res).to_s.latex_escape
|
640
|
+
#########################################rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
|
641
|
+
########################################}.join(" & ")
|
642
|
+
########################################}.join("\\\\\n")
|
643
|
+
########################################}
|
644
|
+
########################################\\end{tabulary}\\normalsize"}.join("\n\n")
|
645
|
+
########################################}.join("\n\n")}
|
646
|
+
########################################"
|
647
|
+
#}.join("\n\n")
|
648
|
+
#}
|
649
|
+
|
650
|
+
|
651
|
+
|
652
|
+
#\\section{Budget and Transfer Breakdown}
|
653
|
+
##{(TRANSFERS + actual_budgets).map{|budget, budget_info|
|
654
|
+
#dates, expenditures, budget_items = budget_expenditure(runner, budget, budget_info, today - numdays, today: today)
|
655
|
+
#pp budget, budget_items.map{|items| items.map{|i| i.date.to_s}}
|
656
|
+
#"\\subsection{#{budget}}" +
|
657
|
+
########################budget_items.zip(dates, expenditures).map{|items, date, expenditure|
|
658
|
+
########################if items.size > 0
|
659
|
+
########################"
|
660
|
+
########################\\footnotesize
|
661
|
+
########################\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 2 }}
|
662
|
+
########################%\\hline
|
663
|
+
########################& #{date.to_s.latex_escape} & & & Total & #{expenditure} & \\\\
|
664
|
+
########################\\hline
|
665
|
+
########################\\Tstrut
|
666
|
+
#########################{items.map{|r|
|
667
|
+
########################([:id] + rcp.component_results - [:sc, :balance]).map{|res|
|
668
|
+
########################r.send(res).to_s.latex_escape
|
669
|
+
########################}.join(" & ")
|
670
|
+
########################}.join("\\\\\n")
|
671
|
+
########################}
|
672
|
+
########################\\\\
|
673
|
+
########################\\hline
|
674
|
+
########################\\end{tabulary}
|
675
|
+
########################\\normalsize
|
676
|
+
########################\\vspace{1em}\n\n"
|
677
|
+
########################else
|
678
|
+
########################""
|
679
|
+
########################end
|
680
|
+
########################}.join("\n\n")
|
681
|
+
#}.join("\n\n")
|
682
|
+
#}
|
683
|
+
|
684
|
+
|
685
|
+
|
686
|
+
#\\section{Recent Transactions}
|
687
|
+
##{accounts.map{|acc|
|
688
|
+
#"\\subsection{#{acc}}
|
689
|
+
#\\footnotesize
|
690
|
+
##{all = runs.find_all{|r| r.account == acc and r.days_ago < numdays}.sort_by{|r| [r.date, r.id]}.reverse
|
691
|
+
#ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
|
692
|
+
########all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
|
693
|
+
########"\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 + "l"}}
|
694
|
+
#########{piece.map{|r|
|
695
|
+
########([:id] + rcp.component_results - [:sc] + [:budget]).map{|res| r.send(res).to_s.latex_escape
|
696
|
+
#########rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
|
697
|
+
########}.join(" & ")
|
698
|
+
########}.join("\\\\\n")}
|
699
|
+
########\\end{tabulary}"}.join("\n\n")}"
|
700
|
+
#}.join("\n\n")}
|
701
|
+
#\\end{document}
|
702
|
+
#EOF
|
703
|
+
|
704
|
+
|
705
|
+
#end
|
706
|
+
#system "latex report.tex && latex report.tex"
|
707
|
+
#end
|
708
|
+
#require 'treasurer'
|
709
|
+
#require 'local_customisations.rb'
|
710
|
+
#include Treasurer::LocalCustomisations
|
711
|
+
|
712
|
+
end # class Budget
|
718
713
|
end #class CodeRunner
|
719
714
|
|
720
715
|
p Dir.pwd
|