-
Notifications
You must be signed in to change notification settings - Fork 0
/
reader.rb
executable file
·74 lines (66 loc) · 2.31 KB
/
reader.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env ruby
require_relative 'monkey_patches'
require 'awesome_print'
require 'gnucash'
require 'spreadsheet_architect'
require 'active_support/all'
class ReportGenerator
def initialize(file, options)
puts "Reading book..."
@book = Gnucash.open(file)
@accounts = Hash.recursive
@book.accounts.each do |account|
add_account(account)
end
@options = options
expenses = @book.accounts.select{ |account| account.full_name.start_with?("Expenses") }
summary = summary_by_month(expenses)
all_months = summary.values.map(&:keys).flatten.uniq.sort
rows = []
summary.each do |account, months|
monthly_sums = all_months.map{ |month| months[month] || 0.0 }
# Chop off the current month for the purpose of averages
prev_months = monthly_sums.slice(0..-2)
if prev_months.any?
monthly_average = (prev_months.reduce(&:+) / prev_months.size).round(2)
else
monthly_average = monthly_sums.first
end
ytd = monthly_sums.reduce(&:+)
rows << [account] + monthly_sums + [monthly_average, ytd]
end
# Sort by the monthly average, descending
#rows.sort_by!(&:last).reverse!
puts("Writing spreadsheet")
data = SpreadsheetArchitect.to_ods(data: rows, headers: ["Account"] + all_months + ["Monthly Avg", "YTD"])
File.open("monthly.ods", "w") { |f| f.write(data) }
end
def summary_by_month(accounts)
results = {}
puts "Reading accounts..."
accounts.each do |account|
#attr_names = %i(type id placeholder full_name transactions)
by_month = account.transactions.group_by { |t| [t.date.year, t.date.month] }
totals = by_month.map do |(year, month), transactions|
value = transactions
.map(&:value)
.map(&:val)
.reduce(&:+) || 0
if value == 0 && @options[:omit_zero]
nil
else
value = value / 100.0
[Date.civil(year, month, 1).strftime("%Y-%m"), value]
end
end.compact.to_h
results[account.full_name] = totals if totals.any?
end
results
end
def add_account(account)
name = account.full_name
*parent_path, account_name = name.split(":")
@accounts.get(parent_path)[account_name] = account
end
end
gen = ReportGenerator.new("/Users/aj/budget/accounts-2019.gnucash", omit_zero: true)