budgetcrmod 0.0.0 → 0.1.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: 2f6c65051be0ec3e7d8da43ff822486d8af50573
4
- data.tar.gz: 75f5c0816e48e18fe9b13076a1af87e16826f959
3
+ metadata.gz: cd1d0b4f3a58bce91cd2ad56229fed7e745a73fb
4
+ data.tar.gz: 9e7aa5398882fa4f219eb78fcb6f97e518550b88
5
5
  SHA512:
6
- metadata.gz: 003fe0aab6ef4f244dc6eb8e21346ddec920274077b6cec71d80f40288cdee4d93e7d7104662a75cbc19d6beeba150dcdb37ab7eb62f3ca579662dd7c8764c7c
7
- data.tar.gz: 62b8ccf7c84d2aba282fa22d4711efd7192f5fda2912afdb5172009adef1e186d0ab78f88256cc33294ae62ba834745f0e9b132abb4878acf78c6256125e3047
6
+ metadata.gz: 13cb28562e021786af1945ad3e050dfdb016d3effd719fab216edb58d0330bb400243abf8b303bc71326ea5dcddd60120e49d2897ef109268b8603a3f3ec5313
7
+ data.tar.gz: 4fa8496fb757cdffdba9eaf10a480ed2d2942723c82ce6690eb62b676951fa4bb2ac16947611d5815f9c8b032d2a8c4acfc16d3d0fbfaeb3597cff276b4cfa50
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: budgetcrmod 0.1.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "budgetcrmod"
9
+ s.version = "0.1.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Edmund Highcock"]
14
+ s.date = "2014-06-02"
15
+ s.description = "A CodeRunner module to help you do your budget"
16
+ s.email = "edmundhighcock@users.sourceforge.net"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "budgetcrmod.gemspec",
29
+ "lib/budgetcrmod.rb",
30
+ "lib/budgetcrmod/budget.rb",
31
+ "lib/budgetcrmod/defaults_files/budget_defaults.rb",
32
+ "test/helper.rb",
33
+ "test/test_budgetcrmod.rb"
34
+ ]
35
+ s.homepage = "http://github.com/edmundhighcock/budgetcrmod"
36
+ s.licenses = ["MIT"]
37
+ s.rubygems_version = "2.2.2"
38
+ s.summary = "A CodeRunner module to help you do your budget"
39
+
40
+ if s.respond_to? :specification_version then
41
+ s.specification_version = 4
42
+
43
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<coderunner>, [">= 0.11.0"])
45
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
46
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
47
+ s.add_development_dependency(%q<bundler>, ["> 1.0.0"])
48
+ s.add_development_dependency(%q<jeweler>, [">= 1.8.4"])
49
+ else
50
+ s.add_dependency(%q<coderunner>, [">= 0.11.0"])
51
+ s.add_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
53
+ s.add_dependency(%q<bundler>, ["> 1.0.0"])
54
+ s.add_dependency(%q<jeweler>, [">= 1.8.4"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<coderunner>, [">= 0.11.0"])
58
+ s.add_dependency(%q<shoulda>, [">= 0"])
59
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
60
+ s.add_dependency(%q<bundler>, ["> 1.0.0"])
61
+ s.add_dependency(%q<jeweler>, [">= 1.8.4"])
62
+ end
63
+ end
64
+
@@ -1,3 +1,4 @@
1
+ require 'date'
1
2
  class String
2
3
  def latex_escape
3
4
  self.gsub(/(?<!\\)([%_&^])/, '\\\\\1')
@@ -43,26 +44,48 @@ class CodeRunner
43
44
  # "11.50",
44
45
  # "4506.80"]
45
46
  #
46
- @component_results = [:date, :type, :sc, :ac, :description, :debit, :credit, :balance]
47
- @results = [:data] + @component_results
47
+ @component_results = [:date, :type, :sc, :ac, :description, :deposit, :withdrawal, :balance]
48
+ @results = [:data, :data_line] + @component_results
48
49
  def generate_input_file
49
50
  FileUtils.cp @data_file.sub(/~/, ENV['HOME']), @directory + '/data.cvs'
50
51
  end
52
+ def debit
53
+ case @account_type
54
+ when :Asset, :Expense
55
+ deposit
56
+ else
57
+ withdrawal
58
+ end
59
+ end
60
+ def credit
61
+ case @account_type
62
+ when :Asset, :Expense
63
+ withdrawal
64
+ else
65
+ deposit
66
+ end
67
+ end
51
68
  DOUBLE_STRING=/"(?:\\\\|\\"|[^"\\]|\\[^"\\])*"/
52
69
  def process_directory_code_specific
53
70
  @status=:Complete
54
71
  data = File.read('data.cvs')
55
72
  data = data.split("\n").map do |line|
56
- p matches = line.scan(Regexp.new("((?:#{DOUBLE_STRING}|[^,])*)(?:,|$)"))
73
+ matches = line.scan(Regexp.new("((?:#{DOUBLE_STRING}|[^,])*)(?:,|$)"))
57
74
  matches.flatten
58
75
  end
59
- pp data
76
+ #pp data
60
77
  @data = data
61
- @data.shift
78
+ @first_line = @data.shift.join(',')
79
+ end
80
+ def reversed?
81
+ #case account_type(@account)
82
+ #when :Asset
83
+ @first_line =~ /Debit.*Credit/
84
+ #end
62
85
  end
63
86
  def print_out_line
64
87
  if @is_component
65
- sprintf("%4d. %10s %3s %6s %8s %-60s %8s %8s %8s", id, *rcp.component_results.map{|res| send(res)})
88
+ sprintf("%4d. %10s %10s %3s %-30s %8s %8s %8s %8s %8s", id, account, *rcp.component_results.find_all{|r| r!=:ac and r!=:sc}.map{|res| send(res)}, budget, external_account)
66
89
  else
67
90
  #pr = component_runs.sort_by{|r| r.id}
68
91
  "#{sprintf("%3d", @id)}. #{sprintf("%-20s", @account)} Start: #{start_date} End: #{end_date} Final Balance: #{final_balance} "
@@ -72,39 +95,50 @@ class CodeRunner
72
95
  @date_sorted_component ||= component_runs.sort_by{|r| r.id}
73
96
  end
74
97
  def end_date
75
- date_sorted_component[-1].date
98
+ date_sorted_component[-1].date rescue nil
76
99
  end
77
100
  def start_date
78
- date_sorted_component[0].date
101
+ date_sorted_component[0].date rescue nil
79
102
  end
80
103
  def final_balance
81
- date_sorted_component[-1].balance
104
+ date_sorted_component[-1].balance rescue nil
82
105
  end
83
106
  def parameter_transition(run)
84
107
  end
85
108
  def parameter_string
86
109
  ""
87
110
  end
111
+
112
+ #def external_account
113
+ #(sub_account.to_s + '_' + budget.to_s).to_sum
114
+ #end
88
115
 
89
116
  def generate_component_runs
90
117
  @runner.cache[:data] ||= []
118
+ reslts = rcp.component_results
119
+ if reversed?
120
+ reslts[5] = :withdrawal
121
+ reslts[6] = :deposit
122
+ end
91
123
  @data.each do |dataset|
92
124
  next if @runner.cache[:data].include? dataset and Date.parse(dataset[0]) > Date.parse("1/1/2013")
93
125
  component = create_component
94
- rcp.component_results.each_with_index do |res,index|
126
+ reslts.each_with_index do |res,index|
95
127
  value = dataset[index]
96
128
  # ep value
97
129
  value = Date.parse value if res == :date
98
- value = value.to_f if [:credit, :debit, :balance].include? res
130
+ value = value.to_f if [:deposit, :withdrawal, :balance].include? res
99
131
  component.set(res, value)
132
+ component.set(:data_line, reslts.map{|r| component.send(r).to_s}.join(','))
100
133
  end
101
134
  @runner.cache[:data].push dataset
102
135
  #component.account = @account
103
136
  end
104
137
  end
105
- def days_ago
138
+ def days_ago(today = Date.today)
139
+ #ep ['today', today, date]
106
140
  # sprintf("%04d%02d%02d", date.year, date.month, date.day).to_i
107
- - ((date.to_datetime.to_time.to_i - Time.now.to_i) / 24 / 3600).to_i
141
+ - ((date.to_datetime.to_time.to_i - today.to_datetime.to_time.to_i) / 24 / 3600).to_i
108
142
  end
109
143
  def idate
110
144
  date.to_datetime.to_time.to_i
@@ -114,157 +148,157 @@ class CodeRunner
114
148
  end
115
149
 
116
150
 
117
- def self.sum_future(future_items, end_date)
118
- sum = future_items.inject(0) do |sum, (name, item)|
119
- item = [item] unless item.kind_of? Array
120
- value = item.inject(0) do |value,info|
121
- value += info[:size] unless (Date.today > info[:date]) or (info[:date] > end_date) # add unless we have already passed that date
122
- value
123
- end
124
- rcp.excluding.include?(name) ? sum : sum + value
125
- end
126
- sum
127
- end
128
-
129
- def self.budget_expenditure(runner, budget, budget_info, start_date)
130
- dates = []
131
- expenditures = []
132
- budget_items = []
133
- date = budget_info[:end]||Date.today
134
- start_date = [(budget_info[:start]||start_date), start_date].max
135
- expenditure = 0
136
- items_temp = []
137
- items = runner.component_run_list.values.find_all{|r| r.budget == budget and r.in_date(budget_info)}
138
- #ep ['items', items]
139
- #ep ['budget', budget]
140
- counter = 0
141
- if not budget_info[:period]
142
- dates.push date
143
- budget_items.push items
144
- expenditures.push (items.map{|r| r.debit - r.credit}+[0]).sum
145
- else
146
-
147
- case budget_info[:period][1]
148
- when :month
149
- while date > start_date
150
- items_temp += items.find_all{|r| r.date == date}
151
- if date.mday == (budget_info[:monthday] or 1)
152
- counter +=1
153
- if counter % budget_info[:period][0] == 0
154
- expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
155
- dates.push date
156
- expenditures.push expenditure
157
- budget_items.push items_temp
158
- items_temp = []
159
- expenditure = 0
160
- end
161
- end
162
- date-=1
163
- end
164
- when :day
165
- while date > start_date
166
- items_temp += items.find_all{|r| r.date == date}
167
- #expenditure += (budget_items[-1].map{|r| r.debit}+[0]).sum
168
- counter +=1
169
- if counter % budget_info[:period][0] == 0
170
- expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
171
- dates.push date
172
- expenditures.push expenditure
173
- budget_items.push items_temp
174
- items_temp = []
175
- expenditure = 0
176
- end
177
- date-=1
178
- end
179
- end
180
- end
181
-
182
- [dates, expenditures, budget_items]
183
-
184
- end
185
-
186
- def self.sum_regular(regular_items, end_date)
187
- today = Date.today
188
- sum = regular_items.inject(0) do |sum, (name, item)|
189
- item = [item] unless item.kind_of? Array
190
- # ep item
191
- value = item.inject(0) do |value,info|
192
- finish = (info[:end] and info[:end] < end_date) ? info[:end] : end_date
193
- #today = (Time.now.to_i / (24.0*3600.0)).round
151
+ #def self.sum_future(future_items, end_date, options={})
152
+ #sum = future_items.inject(0) do |sum, (name, item)|
153
+ #item = [item] unless item.kind_of? Array
154
+ #value = item.inject(0) do |value,info|
155
+ #value += info[:size] unless (options[:today]||Date.today > info[:date]) or (info[:date] > end_date) # add unless we have already passed that date
156
+ #value
157
+ #end
158
+ #rcp.excluding.include?(name) ? sum : sum + value
159
+ #end
160
+ #sum
161
+ #end
162
+
163
+ #def self.budget_expenditure(runner, budget, budget_info, start_date, options={})
164
+ #dates = []
165
+ #expenditures = []
166
+ #budget_items = []
167
+ #date = budget_info[:end]||options[:today]||Date.today
168
+ #start_date = [(budget_info[:start]||start_date), start_date].max
169
+ #expenditure = 0
170
+ #items_temp = []
171
+ #items = runner.component_run_list.values.find_all{|r| r.budget == budget and r.in_date(budget_info)}
172
+ ##ep ['items', items]
173
+ ##ep ['budget', budget]
174
+ #counter = 0
175
+ #if not budget_info[:period]
176
+ #dates.push date
177
+ #budget_items.push items
178
+ #expenditures.push (items.map{|r| r.debit - r.credit}+[0]).sum
179
+ #else
180
+
181
+ #case budget_info[:period][1]
182
+ #when :month
183
+ #while date > start_date
184
+ #items_temp += items.find_all{|r| r.date == date}
185
+ #if date.mday == (budget_info[:monthday] or 1)
186
+ #counter +=1
187
+ #if counter % budget_info[:period][0] == 0
188
+ #expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
189
+ #dates.push date
190
+ #expenditures.push expenditure
191
+ #budget_items.push items_temp
192
+ #items_temp = []
193
+ #expenditure = 0
194
+ #end
195
+ #end
196
+ #date-=1
197
+ #end
198
+ #when :day
199
+ #while date > start_date
200
+ #items_temp += items.find_all{|r| r.date == date}
201
+ ##expenditure += (budget_items[-1].map{|r| r.debit}+[0]).sum
202
+ #counter +=1
203
+ #if counter % budget_info[:period][0] == 0
204
+ #expenditure = (items_temp.map{|r| r.debit - r.credit}+[0]).sum
205
+ #dates.push date
206
+ #expenditures.push expenditure
207
+ #budget_items.push items_temp
208
+ #items_temp = []
209
+ #expenditure = 0
210
+ #end
211
+ #date-=1
212
+ #end
213
+ #end
214
+ #end
215
+
216
+ #[dates, expenditures, budget_items]
217
+
218
+ #end
219
+
220
+ #def self.sum_regular(regular_items, end_date, options={})
221
+ #today = options[:today]||Date.today
222
+ #sum = regular_items.inject(0) do |sum, (name, item)|
223
+ #item = [item] unless item.kind_of? Array
224
+ ## ep item
225
+ #value = item.inject(0) do |value,info|
226
+ #finish = (info[:end] and info[:end] < end_date) ? info[:end] : end_date
227
+ ##today = (Time.now.to_i / (24.0*3600.0)).round
194
228
 
195
- nunits = 0
196
- counter = info[:period][0] == 1 ? 0 : nil
197
- unless counter
198
- date = today
199
- counter = 0
200
- case info[:period][1]
201
- when :month
202
- while date >= (info[:start] or Date.today)
203
- counter +=1 if date.mday == (info[:monthday] or 1)
204
- date -= 1
205
- end
206
- when :year
207
- while date >= (info[:start] or Date.today)
208
- counter +=1 if date.yday == (info[:yearday] or 1)
209
- date -= 1
210
- end
211
- when :day
212
- while date > (info[:start] or Date.today)
213
- counter +=1
214
- date -= 1
215
- end
216
- end
217
- end
218
- date = today
219
- case info[:period][1]
220
- when :month
221
- #p date, info
222
- while date <= finish
223
- if date.mday == (info[:monthday] or 1)
224
- nunits += 1 if counter % info[:period][0] == 0
225
- counter +=1
226
- end
227
- date += 1
228
- end
229
- when :year
230
- while date <= finish
231
- if date.yday == (info[:yearday] or 1)
232
- nunits += 1 if counter % info[:period][0] == 0
233
- counter +=1
234
- end
235
- date += 1
236
- end
237
- when :day
238
- while date <= finish
239
- nunits += 1 if counter % info[:period][0] == 0
240
- counter +=1
241
- date += 1
242
- end
243
- end
244
-
245
-
246
-
247
-
248
-
249
- #nyears = (finish.year - today.year)
250
- #nmonths = nyears * 12 + (finish.month - today.month)
251
- #(puts "Number of Months: #{nmonths}"; @pnmonths=true) unless @pnmonths
252
- #ndays = nyears * 12 + (finish.yday - today.yday)
253
- #number = case info[:period][1]
254
- #when :month
255
- #(nmonths / info[:period][0]).ceil
256
- #when :day
257
- #(ndays / info[:period][0]).ceil
258
- #end
259
- #value + number * info[:size]
260
- #eputs "Regular Expenditure Item: #{sprintf("%10s", name)} -- #{nunits} payments, total #{nunits * info[:size]}"
261
- value + nunits * info[:size]
262
-
263
- end
264
- (rcp.excluding? and rcp.excluding.include?(name)) ? sum : sum + value
265
- end
266
- sum
267
- end
229
+ #nunits = 0
230
+ #counter = info[:period][0] == 1 ? 0 : nil
231
+ #####################unless counter
232
+ #####################date = today
233
+ #####################counter = 0
234
+ #####################case info[:period][1]
235
+ #####################when :month
236
+ #####################while date >= (info[:start] or Date.today)
237
+ #####################counter +=1 if date.mday == (info[:monthday] or 1)
238
+ #####################date -= 1
239
+ #####################end
240
+ #####################when :year
241
+ #####################while date >= (info[:start] or Date.today)
242
+ #####################counter +=1 if date.yday == (info[:yearday] or 1)
243
+ #####################date -= 1
244
+ #####################end
245
+ #####################when :day
246
+ #####################while date > (info[:start] or Date.today)
247
+ #####################counter +=1
248
+ #####################date -= 1
249
+ #####################end
250
+ #####################end
251
+ #####################end
252
+ #date = today
253
+ #########################case info[:period][1]
254
+ #########################when :month
255
+ ##########################p date, info
256
+ #########################while date <= finish
257
+ #########################if date.mday == (info[:monthday] or 1)
258
+ #########################nunits += 1 if counter % info[:period][0] == 0
259
+ #########################counter +=1
260
+ #########################end
261
+ #########################date += 1
262
+ #########################end
263
+ #########################when :year
264
+ #########################while date <= finish
265
+ #########################if date.yday == (info[:yearday] or 1)
266
+ #########################nunits += 1 if counter % info[:period][0] == 0
267
+ #########################counter +=1
268
+ #########################end
269
+ #########################date += 1
270
+ #########################end
271
+ #########################when :day
272
+ #########################while date <= finish
273
+ #########################nunits += 1 if counter % info[:period][0] == 0
274
+ #########################counter +=1
275
+ #########################date += 1
276
+ #########################end
277
+ #########################end
278
+
279
+
280
+
281
+
282
+
283
+ ##nyears = (finish.year - today.year)
284
+ ##nmonths = nyears * 12 + (finish.month - today.month)
285
+ ##(puts "Number of Months: #{nmonths}"; @pnmonths=true) unless @pnmonths
286
+ ##ndays = nyears * 12 + (finish.yday - today.yday)
287
+ ##number = case info[:period][1]
288
+ ##when :month
289
+ ##(nmonths / info[:period][0]).ceil
290
+ ##when :day
291
+ ##(ndays / info[:period][0]).ceil
292
+ ##end
293
+ ##value + number * info[:size]
294
+ ##eputs "Regular Expenditure Item: #{sprintf("%10s", name)} -- #{nunits} payments, total #{nunits * info[:size]}"
295
+ #value + nunits * info[:size]
296
+
297
+ #end
298
+ #(rcp.excluding? and rcp.excluding.include?(name)) ? sum : sum + value
299
+ #end
300
+ #sum
301
+ #end
268
302
  def self.predictable_component_ids(runner)
269
303
  #runner.instance_variable_set(:@component_run_list, {})
270
304
  #runner.instance_variable_set(:@component_ids, [])
@@ -299,270 +333,275 @@ class CodeRunner
299
333
  puts "Weekly Budget: #{total / ((end_date.to_datetime.to_time.to_i - Time.now.to_i) / 3600 / 24 /7)}"
300
334
  end
301
335
 
302
- def self.budgets_with_averages(runner, budgets, start_date)
303
- projected_budgets = budgets.dup
304
- projected_budgets.each{|key,v| projected_budgets[key]=projected_budgets[key].dup}
305
- projected_budgets.each do |budget, budget_info|
306
- #budget_info = budgets[budget]
307
- dates, expenditures, items = budget_expenditure(runner, budget, budget_info, start_date)
308
- budget_info[:size] = expenditures.mean rescue 0.0
309
- end
310
- projected_budgets
311
- end
312
-
313
- def self.latex_budget_transfers(runner, budgets, options)
314
- numdays = options[:days]
315
- "#{budgets.map{|budget, budget_info|
316
- dates, expenditures, items = budget_expenditure(runner, budget, budget_info, Date.today - numdays)
317
- #ep ['budget', budget, dates, expenditures]
318
- kit = GraphKit.quick_create([dates.map{|d| d.to_time.to_i}, expenditures])
319
- kit.data.each{|dk| dk.gp.with="boxes"}
320
- kit.gp.style = "fill solid"
321
- kit.xlabel = nil
322
- kit.ylabel = "Expenditure"
323
- unless options[:transfers]
324
- kits = budgets_with_averages(runner, {budget => budget_info}, Date.today - numdays).map{|budget, budget_info|
325
- #ep 'Budget is ', budget
326
- kit2 = GraphKit.quick_create([
327
- [dates[0], dates[-1]].map{|d| d.to_time.to_i},
328
- [budget_info[:size], budget_info[:size]]
329
- ])
330
- kit2.data[0].gp.with = 'lp lw 4'
331
- kit2
332
- }
333
- #$debug_gnuplot = true
334
- #kits.sum.gnuplot
335
- kit += kits.sum
336
-
337
- else
338
- kit.data[0].y.data.map!{|expen| expen*-1.0}
339
- end
340
- kit.title = "#{budget} Expenditure with average (Total = #{kit.data[0].y.data.sum})"
341
- kit_time_format_x(kit)
342
- #kit.gnuplot
343
- kit.gnuplot_write("#{budget}.eps")
344
- "\\begin{center}\\includegraphics[width=4.0in]{#{budget}.eps}\\vspace{1em}\\end{center}"
345
- }.join("\n\n")
346
- }"
347
- end
348
-
349
- def self.latex_report(options={})
350
- runner = CodeRunner.fetch_runner(Y: Dir.pwd, h: :component)
351
- numdays = options[:days]
352
- # Delete budgets that contain no items
353
- actual_budgets = BUDGETS.dup
354
- BUDGETS.keys.each do |budget|
355
- actual_budgets.delete(budget) if budget_expenditure(runner, budget, BUDGETS[budget], Date.today - numdays)[0].size == 0
356
- end
357
- #predictable_component_ids(runner)
358
- days_ahead = options[:days_ahead]
359
- runs = runner.component_run_list.values
360
- indateruns = runs.find_all{|r| r.days_ago < numdays}
361
- accounts = runs.map{|r| r.account}.uniq
362
- ep 'Accounts', accounts
363
- projected_budgets = Hash[actual_budgets.dup.find_all{|k,v| v[:discretionary]}]
364
- projected_budgets = budgets_with_averages(runner,projected_budgets, Date.today - numdays)
336
+ #def self.budgets_with_averages(runner, budgets, start_date, options={})
337
+ #projected_budgets = budgets.dup
365
338
  #projected_budgets.each{|key,v| projected_budgets[key]=projected_budgets[key].dup}
366
339
  #projected_budgets.each do |budget, budget_info|
367
340
  ##budget_info = budgets[budget]
368
- #dates, expenditures, items = budget_expenditure(runner, budget, budget_info, Date.today - numdays)
369
- #budget_info[:size] = expenditures.mean
341
+ #dates, expenditures, items = budget_expenditure(runner, budget, budget_info, start_date, today: options[:today])
342
+ #budget_info[:size] = expenditures.mean rescue 0.0
370
343
  #end
371
- ep 'projected_budgets', projected_budgets
372
- File.open('report.tex', 'w') do |file|
373
- file.puts <<EOF
374
- \\documentclass{article}
375
- \\usepackage[cm]{fullpage}
376
- \\usepackage{tabulary}
377
- \\usepackage{graphicx}
378
- %\\usepackage{hyperlink}
379
- \\newcommand\\Tstrut{\\rule{0pt}{2.8ex}}
380
- \\begin{document}
381
- \\title{#{numdays}-day Budget Report}
382
- \\maketitle
383
- \\tableofcontents
384
-
385
- \\section{Summary of Accounts}
386
- #{accounts.map{|acc|
387
- "\\subsection{#{acc}}
388
- \\begin{tabulary}{0.8\\textwidth}{ r l}
389
- Balance & #{runs.find_all{|r| r.account==acc}.sort_by{|r|
390
- r.date
391
- }[-1].balance} \\\\
392
- Expenditure & #{runs.find_all{|r| r.account==acc &&
393
- r.days_ago < numdays
394
- }.map{|r|
395
- r.debit
396
- }.sum} \\\\
397
- Income & #{runs.find_all{|r| r.account==acc &&
398
- r.days_ago < numdays
399
- }.map{|r| r.credit}.sum} \\\\
400
- \\end{tabulary}"}.join("\n\n")
401
- }
402
-
403
- \\section{Graphs of Recent Balances}
404
- #{accounts.map{|acc|
405
- balance = runs.find_all{|r| r.account==acc}.sort_by{|r| r.date }[-1].balance
406
- accshort = acc.gsub(/\s/, '')
407
- kit = runner.graphkit(['date.to_time.to_i', 'balance'], {conditions: "account == #{acc.inspect} and days_ago < #{numdays}", sort: 'date'})
408
- futuredates = (Date.today..Date.today+days_ahead).to_a
409
- #p ["Regtrans", REGULAR_TRANSFERS.values_at(*REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc})]
410
-
411
- budgets = Hash[projected_budgets.find_all{|k,v| v[:account] == acc}]
412
- ep ['budgets', budgets]
413
- projection = futuredates.map{|date| balance -
414
- sum_regular(REGULAR_EXPENDITURE[acc], date) +
415
- sum_regular(REGULAR_INCOME[acc], date) -
416
- sum_regular(budgets, date) -
417
- sum_future(FUTURE_EXPENDITURE[acc], date) +
418
- sum_future(FUTURE_INCOME[acc], date) +
419
- (REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc}.map{|key|
420
- #p [acc, 'to', "key", key]
421
- sum_regular( REGULAR_TRANSFERS[key], date)
422
- }.sum||0) -
423
- (REGULAR_TRANSFERS.keys.find_all{|from,to| from == acc}.map{|key|
424
- #p [acc, 'from',"key", key]
425
- sum_regular( REGULAR_TRANSFERS[key], date)
426
- }.sum||0)
427
- }
428
- kit2 = GraphKit.quick_create([futuredates.map{|d| d.to_time.to_i}, projection])
429
- kit += kit2
430
- kit.title = "Balance for #{acc}"
431
- kit.xlabel = %['Date' offset 0,-2]
432
- kit.xlabel = nil
433
- kit.ylabel = "Balance"
434
-
435
- kit.data[0].gp.title = 'Previous'
436
- kit.data[1].gp.title = '0 GBP Discretionary'
437
- kit.data[1].gp.title = 'Projection'
438
- kit.data.each{|dk| dk.gp.with = "lp"}
439
-
440
- kit_time_format_x(kit)
441
-
442
- (kit).gnuplot_write("#{accshort}_balance.eps", size: "4.0in,3.0in")
443
- "\\begin{center}\\includegraphics[width=4.0in]{#{accshort}_balance.eps}\\end{center}"
444
- }.join("\n\n")
445
- }
446
-
447
-
448
- \\section{Budget Expenditure}
449
- #{latex_budget_transfers(runner,actual_budgets, options)}
450
-
451
- \\section{Transfers}
452
- #{latex_budget_transfers(runner, TRANSFERS, options.dup.absorb({transfers: true}))}
453
-
454
-
455
-
456
- \\section{Budget Resolutions}
457
-
458
- 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.
459
-
460
- #{actual_budgets.map{|budget, budget_info|
461
-
462
- "\\subsection{#{budget} }
463
- \\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{r l}
464
- %\\hline
465
- Account Owed & Amount \\\\
466
- \\hline
467
- \\Tstrut
468
- #{budget_items = indateruns.find_all{|r| r.budget == budget}
469
- alternate_accounts = budget_items.map{|r| r.account}.uniq - [budget_info[:account]]
470
- alternate_accounts.map{|acc|
471
- alternate_items = budget_items.find_all{|r| r.account == acc}
472
- total = alternate_items.map{|r| r.debit - r.credit}.sum
473
- "#{acc} & #{total} \\\\"
474
- }.join("\n\n")
475
- }
476
-
477
- \\\\
478
- \\hline
479
- \\end{tabulary}
480
- \\normalsize
481
- \\vspace{1em}\n\n
482
-
483
- #{ alternate_accounts.map{|acc|
484
- alternate_items = budget_items.find_all{|r| r.account == acc}
485
- alternate_items.pieces((alternate_items.size.to_f/50.to_f).ceil).map{|piece|
486
- "\\footnotesize\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 }}
487
- #{budget}: & #{budget_info[:account]} & owes & #{acc} &&&&\\\\
488
- \\hline
489
-
490
- \\Tstrut
491
-
492
- #{piece.map{|r|
493
- ([:id] + rcp.component_results - [:sc]).map{|res|
494
- r.send(res).to_s.latex_escape
495
- #rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
496
- }.join(" & ")
497
- }.join("\\\\\n")
498
- }
499
- \\end{tabulary}\\normalsize"}.join("\n\n")
500
- }.join("\n\n")}
501
- "
502
- }.join("\n\n")
503
- }
504
-
505
-
506
-
507
- \\section{Budget and Transfer Breakdown}
508
- #{(TRANSFERS + actual_budgets).map{|budget, budget_info|
509
- dates, expenditures, budget_items = budget_expenditure(runner, budget, budget_info, Date.today - numdays)
510
- pp budget, budget_items.map{|items| items.map{|i| i.date.to_s}}
511
- "\\subsection{#{budget}}" +
512
- budget_items.zip(dates, expenditures).map{|items, date, expenditure|
513
- if items.size > 0
514
- "
515
- \\footnotesize
516
- \\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 2 }}
517
- %\\hline
518
- & #{date.to_s.latex_escape} & & & Total & #{expenditure} & \\\\
519
- \\hline
520
- \\Tstrut
521
- #{items.map{|r|
522
- ([:id] + rcp.component_results - [:sc, :balance]).map{|res|
523
- r.send(res).to_s.latex_escape
524
- }.join(" & ")
525
- }.join("\\\\\n")
526
- }
527
- \\\\
528
- \\hline
529
- \\end{tabulary}
530
- \\normalsize
531
- \\vspace{1em}\n\n"
532
- else
533
- ""
534
- end
535
- }.join("\n\n")
536
- }.join("\n\n")
537
- }
538
-
539
-
540
-
541
- \\section{Recent Transactions}
542
- #{accounts.map{|acc|
543
- "\\subsection{#{acc}}
544
- \\footnotesize
545
- #{all = runs.find_all{|r| r.account == acc and r.days_ago < numdays}.sort_by{|r| [r.date, r.id]}.reverse
546
- ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
547
- all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
548
- "\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 + "l"}}
549
- #{piece.map{|r|
550
- ([:id] + rcp.component_results - [:sc] + [:budget]).map{|res| r.send(res).to_s.latex_escape
551
- #rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
552
- }.join(" & ")
553
- }.join("\\\\\n")}
554
- \\end{tabulary}"}.join("\n\n")}"
555
- }.join("\n\n")}
556
- \\end{document}
557
- EOF
558
-
559
-
560
- end
561
- system "latex report.tex && latex report.tex"
562
- end
344
+ #projected_budgets
345
+ #end
346
+
347
+ #def self.latex_budget_transfers(runner, budgets, options)
348
+ #numdays = options[:days]
349
+ #today = options[:today]||Date.today
350
+ #"#{budgets.map{|budget, budget_info|
351
+ #dates, expenditures, items = budget_expenditure(runner, budget, budget_info, today - numdays, today: options[:today])
352
+ ##ep ['budget', budget, dates, expenditures]
353
+ #kit = GraphKit.quick_create([dates.map{|d| d.to_time.to_i}, expenditures])
354
+ #kit.data.each{|dk| dk.gp.with="boxes"}
355
+ #kit.gp.style = "fill solid"
356
+ #kit.xlabel = nil
357
+ #kit.ylabel = "Expenditure"
358
+ #unless options[:transfers]
359
+ #kits = budgets_with_averages(runner, {budget => budget_info}, today - numdays, today: today).map{|budget, budget_info|
360
+ ##ep 'Budget is ', budget
361
+ #kit2 = GraphKit.quick_create([
362
+ #[dates[0], dates[-1]].map{|d| d.to_time.to_i},
363
+ #[budget_info[:size], budget_info[:size]]
364
+ #])
365
+ #kit2.data[0].gp.with = 'lp lw 4'
366
+ #kit2
367
+ #}
368
+ ##$debug_gnuplot = true
369
+ ##kits.sum.gnuplot
370
+ #kit += kits.sum
371
+
372
+ #else
373
+ #kit.data[0].y.data.map!{|expen| expen*-1.0}
374
+ #end
375
+ #kit.title = "#{budget} Expenditure with average (Total = #{kit.data[0].y.data.sum})"
376
+ #kit_time_format_x(kit)
377
+ ##kit.gnuplot
378
+ #kit.gnuplot_write("#{budget}.eps")
379
+ #"\\begin{center}\\includegraphics[width=4.0in]{#{budget}.eps}\\vspace{1em}\\end{center}"
380
+ #}.join("\n\n")
381
+ #}"
382
+ #end
383
+
384
+ #def self.latex_report(options={})
385
+ #runner = CodeRunner.fetch_runner(Y: Dir.pwd, h: :component)
386
+ #numdays = options[:days]
387
+ #today = options[:today] || Date.today
388
+ ## Delete budgets that contain no items
389
+ #actual_budgets = BUDGETS.dup
390
+ #BUDGETS.keys.each do |budget|
391
+ #actual_budgets.delete(budget) if budget_expenditure(runner, budget, BUDGETS[budget], today - numdays, today: today)[0].size == 0
392
+ #end
393
+ ##predictable_component_ids(runner)
394
+ #days_ahead = options[:days_ahead]
395
+ #runs = runner.component_run_list.values
396
+ #indateruns = runs.find_all{|r| r.days_ago < numdays}
397
+ #accounts = runs.map{|r| r.account}.uniq
398
+ #ep 'Accounts', accounts
399
+ #projected_budgets = Hash[actual_budgets.dup.find_all{|k,v| v[:discretionary]}]
400
+ #projected_budgets = budgets_with_averages(runner,projected_budgets, today - numdays, today: today)
401
+ ##projected_budgets.each{|key,v| projected_budgets[key]=projected_budgets[key].dup}
402
+ ##projected_budgets.each do |budget, budget_info|
403
+ ###budget_info = budgets[budget]
404
+ ##dates, expenditures, items = budget_expenditure(runner, budget, budget_info, today - numdays)
405
+ ##budget_info[:size] = expenditures.mean
406
+ ##end
407
+ #ep 'projected_budgets', projected_budgets
408
+ #File.open('report.tex', 'w') do |file|
409
+ #file.puts <<EOF
410
+ #\\documentclass{article}
411
+ #\\usepackage[cm]{fullpage}
412
+ #\\usepackage{tabulary}
413
+ #\\usepackage{graphicx}
414
+ #%\\usepackage{hyperlink}
415
+ #\\newcommand\\Tstrut{\\rule{0pt}{2.8ex}}
416
+ #\\begin{document}
417
+ #\\title{#{numdays}-day Budget Report}
418
+ #\\maketitle
419
+ #\\tableofcontents
420
+
421
+ #\\section{Summary of Accounts}
422
+ ##{accounts.map{|acc|
423
+ #"\\subsection{#{acc}}
424
+ #\\begin{tabulary}{0.8\\textwidth}{ r l}
425
+ ###Balance & #{runs.find_all{|r| r.account==acc}.sort_by{|r|
426
+ ###r.date
427
+ ###}[-1].balance} \\\\
428
+ #####Expenditure & #{runs.find_all{|r| r.account==acc &&
429
+ #####r.days_ago < numdays
430
+ #####}.map{|r|
431
+ #####r.debit
432
+ #####}.sum} \\\\
433
+ ###Income & #{runs.find_all{|r| r.account==acc &&
434
+ ###r.days_ago < numdays
435
+ ###}.map{|r| r.credit}.sum} \\\\
436
+ #\\end{tabulary}"}.join("\n\n")
437
+ #}
438
+
439
+ #\\section{Graphs of Recent Balances}
440
+ ##{accounts.map{|acc|
441
+ #balance = runs.find_all{|r| r.account==acc}.sort_by{|r| r.date }[-1].balance
442
+ #accshort = acc.gsub(/\s/, '')
443
+ #kit = runner.graphkit(['date.to_time.to_i', 'balance'], {conditions: "account == #{acc.inspect} and days_ago < #{numdays}", sort: 'date'})
444
+ #futuredates = (today..today+days_ahead).to_a
445
+ ##p ["Regtrans", REGULAR_TRANSFERS.values_at(*REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc})]
446
+
447
+ #budgets = Hash[projected_budgets.find_all{|k,v| v[:account] == acc}]
448
+ #ep ['budgets', budgets]
449
+ #projection = futuredates.map{|date| balance -
450
+ #sum_regular(REGULAR_EXPENDITURE[acc], date, today: today) +
451
+ #sum_regular(REGULAR_INCOME[acc], date, today: today) -
452
+ #sum_regular(budgets, date, today: today) -
453
+ #sum_future(FUTURE_EXPENDITURE[acc], date, today: today) +
454
+ #sum_future(FUTURE_INCOME[acc], date, today: today) +
455
+ #(REGULAR_TRANSFERS.keys.find_all{|from,to| to == acc}.map{|key|
456
+ ##p [acc, 'to', "key", key]
457
+ #sum_regular( REGULAR_TRANSFERS[key], date, today: today)
458
+ #}.sum||0) -
459
+ #(REGULAR_TRANSFERS.keys.find_all{|from,to| from == acc}.map{|key|
460
+ ##p [acc, 'from',"key", key]
461
+ #sum_regular( REGULAR_TRANSFERS[key], date, today: today)
462
+ #}.sum||0)
463
+ #}
464
+ #kit2 = GraphKit.quick_create([futuredates.map{|d| d.to_time.to_i}, projection])
465
+ #kit += kit2
466
+ #kit.title = "Balance for #{acc}"
467
+ #kit.xlabel = %['Date' offset 0,-2]
468
+ #kit.xlabel = nil
469
+ #kit.ylabel = "Balance"
470
+
471
+ #kit.data[0].gp.title = 'Previous'
472
+ #kit.data[1].gp.title = '0 GBP Discretionary'
473
+ #kit.data[1].gp.title = 'Projection'
474
+ #kit.data.each{|dk| dk.gp.with = "lp"}
475
+
476
+ #kit_time_format_x(kit)
477
+
478
+ #(kit).gnuplot_write("#{accshort}_balance.eps", size: "4.0in,3.0in")
479
+ #"\\begin{center}\\includegraphics[width=4.0in]{#{accshort}_balance.eps}\\end{center}"
480
+ #}.join("\n\n")
481
+ #}
482
+
483
+
484
+ #\\section{Budget Expenditure}
485
+ ##{latex_budget_transfers(runner,actual_budgets, options)}
486
+
487
+ #\\section{Transfers}
488
+ ##{latex_budget_transfers(runner, TRANSFERS, options.dup.absorb({transfers: true}))}
489
+
490
+
491
+
492
+ #\\section{Budget Resolutions}
493
+
494
+ #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.
495
+
496
+ ##{actual_budgets.map{|budget, budget_info|
497
+
498
+ ########################################"\\subsection{#{budget} }
499
+ ########################################\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{r l}
500
+ ########################################%\\hline
501
+ ########################################Account Owed & Amount \\\\
502
+ ########################################\\hline
503
+ ########################################\\Tstrut
504
+ #########################################{budget_items = indateruns.find_all{|r| r.budget == budget}
505
+ ########################################alternate_accounts = budget_items.map{|r| r.account}.uniq - [budget_info[:account]]
506
+ ########################################alternate_accounts.map{|acc|
507
+ ########################################alternate_items = budget_items.find_all{|r| r.account == acc}
508
+ ########################################total = alternate_items.map{|r| r.debit - r.credit}.sum
509
+ ########################################"#{acc} & #{total} \\\\"
510
+ ########################################}.join("\n\n")
511
+ ########################################}
512
+
513
+ ########################################\\\\
514
+ ########################################\\hline
515
+ ########################################\\end{tabulary}
516
+ ########################################\\normalsize
517
+ ########################################\\vspace{1em}\n\n
518
+
519
+ #########################################{ alternate_accounts.map{|acc|
520
+ ########################################alternate_items = budget_items.find_all{|r| r.account == acc}
521
+ ########################################alternate_items.pieces((alternate_items.size.to_f/50.to_f).ceil).map{|piece|
522
+ ########################################"\\footnotesize\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 }}
523
+ #########################################{budget}: & #{budget_info[:account]} & owes & #{acc} &&&&\\\\
524
+ ########################################\\hline
525
+
526
+ ########################################\\Tstrut
527
+
528
+ #########################################{piece.map{|r|
529
+ ########################################([:id] + rcp.component_results - [:sc]).map{|res|
530
+ ########################################r.send(res).to_s.latex_escape
531
+ #########################################rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
532
+ ########################################}.join(" & ")
533
+ ########################################}.join("\\\\\n")
534
+ ########################################}
535
+ ########################################\\end{tabulary}\\normalsize"}.join("\n\n")
536
+ ########################################}.join("\n\n")}
537
+ ########################################"
538
+ #}.join("\n\n")
539
+ #}
540
+
541
+
542
+
543
+ #\\section{Budget and Transfer Breakdown}
544
+ ##{(TRANSFERS + actual_budgets).map{|budget, budget_info|
545
+ #dates, expenditures, budget_items = budget_expenditure(runner, budget, budget_info, today - numdays, today: today)
546
+ #pp budget, budget_items.map{|items| items.map{|i| i.date.to_s}}
547
+ #"\\subsection{#{budget}}" +
548
+ ########################budget_items.zip(dates, expenditures).map{|items, date, expenditure|
549
+ ########################if items.size > 0
550
+ ########################"
551
+ ########################\\footnotesize
552
+ ########################\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 2 }}
553
+ ########################%\\hline
554
+ ########################& #{date.to_s.latex_escape} & & & Total & #{expenditure} & \\\\
555
+ ########################\\hline
556
+ ########################\\Tstrut
557
+ #########################{items.map{|r|
558
+ ########################([:id] + rcp.component_results - [:sc, :balance]).map{|res|
559
+ ########################r.send(res).to_s.latex_escape
560
+ ########################}.join(" & ")
561
+ ########################}.join("\\\\\n")
562
+ ########################}
563
+ ########################\\\\
564
+ ########################\\hline
565
+ ########################\\end{tabulary}
566
+ ########################\\normalsize
567
+ ########################\\vspace{1em}\n\n"
568
+ ########################else
569
+ ########################""
570
+ ########################end
571
+ ########################}.join("\n\n")
572
+ #}.join("\n\n")
573
+ #}
574
+
575
+
576
+
577
+ #\\section{Recent Transactions}
578
+ ##{accounts.map{|acc|
579
+ #"\\subsection{#{acc}}
580
+ #\\footnotesize
581
+ ##{all = runs.find_all{|r| r.account == acc and r.days_ago < numdays}.sort_by{|r| [r.date, r.id]}.reverse
582
+ #ep ['acc', acc, 'ids', all.map{|r| r.id}, 'size', all.size]
583
+ ########all.pieces((all.size.to_f/50.to_f).ceil).map{|piece|
584
+ ########"\\setlength{\\parindent}{0cm}\n\n\\begin{tabulary}{0.99\\textwidth}{ #{"c " * 4 + " L " + " r " * 3 + "l"}}
585
+ #########{piece.map{|r|
586
+ ########([:id] + rcp.component_results - [:sc] + [:budget]).map{|res| r.send(res).to_s.latex_escape
587
+ #########rcp.component_results.map{|res| r.send(res).to_s.gsub(/(.{20})/, '\1\\\\\\\\').latex_escape
588
+ ########}.join(" & ")
589
+ ########}.join("\\\\\n")}
590
+ ########\\end{tabulary}"}.join("\n\n")}"
591
+ #}.join("\n\n")}
592
+ #\\end{document}
593
+ #EOF
594
+
595
+
596
+ #end
597
+ #system "latex report.tex && latex report.tex"
598
+ #end
599
+ #require 'treasurer'
600
+ #require 'local_customisations.rb'
601
+ #include Treasurer::LocalCustomisations
563
602
 
564
603
  end # class Budget
565
604
  end #class CodeRunner
566
605
 
567
606
  p Dir.pwd
568
- require Dir.pwd + '/local_customisations.rb'
607
+ #require Dir.pwd + '/local_customisations.rb'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: budgetcrmod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.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-05-26 00:00:00.000000000 Z
11
+ date: 2014-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coderunner
@@ -94,6 +94,7 @@ files:
94
94
  - README.rdoc
95
95
  - Rakefile
96
96
  - VERSION
97
+ - budgetcrmod.gemspec
97
98
  - lib/budgetcrmod.rb
98
99
  - lib/budgetcrmod/budget.rb
99
100
  - lib/budgetcrmod/defaults_files/budget_defaults.rb