7 OptionParser.new do |opts|
8 opts.banner = "Usage: fin [options]"
10 options[:transactions_file] = "#{File.expand_path('~')}/.fin/transactions"
11 opts.on("", "--transactions-file FILE",
12 "Use transactions file FILE") do |filename|
13 options[:transactions_file] = File.expand_path(filename)
16 options[:totals_filter] = 'true'
17 opts.on("", "--filter FILTER",
18 "Use Ruby predicate FILTER as filter on input.",
19 "Assume availability of Transaction object",
20 "parameter named \"transaction\"") do |filter|
21 options[:totals_filter] = filter
26 ledger = Ledger.new(options[:transactions_file])
28 STDERR.puts "Error: Couldn't open file #{options[:transactions_file]}"
32 STDERR.puts "#{ledger.length} transactions read."
34 def totals(ledger, options = {})
35 options = {:format => :humane }.merge options
36 # set up a few handy names for filtering by the --filter command-line option
37 yesterday, today, tomorrow = Date.today - 1, Date.today, Date.today + 1
38 last_month, this_month, next_month = today << 1, today, today >> 1
39 last_year, this_year, next_year = today << 12, today, today >> 12
40 last_month_start = Date.new(last_month.year, last_month.month, 1)
41 last_month_end = Date.new(last_month.year, last_month.month, -1)
42 this_month_start = Date.new(this_month.year, this_month.month, 1)
43 this_month_end = Date.new(this_month.year, this_month.month, -1)
44 next_month_start = Date.new(next_month.year, next_month.month, 1)
45 next_month_end = Date.new(next_month.year, next_month.month, -1)
46 last_year_start = Date.new(last_year.year, 1, 1)
47 last_year_end = Date.new(last_year.year, -1, -1)
48 this_year_start = Date.new(this_year.year, 1, 1)
49 this_year_end = Date.new(this_year.year, -1, -1)
50 next_year_start = Date.new(next_year.year, 1, 1)
51 next_year_end = Date.new(next_year.year, -1, -1)
52 # get filtered totals.
53 account_totals = ledger.accumulate do |transaction|
54 from, to = transaction.from, transaction.to
55 amount = transaction.amount
56 date = transaction.date
57 notes = transaction.description
58 eval(options[:totals_filter])
61 account_totals.sort! do |account1, account2|
62 account1.to_s <=> account2.to_s
66 STDERR.puts "#{account_totals.length} accounts defined.", "\n"
67 account_totals.each_index do |index|
68 if options[:format] == :humane
69 account_name = ' ' * (account_totals[index].depth) + account_totals[index].name
71 print(("%.2f" % account_totals[index].balance).rjust(40 - account_name.length, '.'))
74 print("\t", ("%.2f" % account_totals[index]))
80 totals ledger, options.merge({:format => :humane})