From 8f884f7a69845f68c3859a49f7b43f5db767b2b8 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Thu, 13 Jul 2017 21:38:30 -0400 Subject: [PATCH] Add more sample reports Also switch tabs to spaces in existing sample reports --- reports/asset_allocation.lua | 42 ++++++++++++++++ reports/monthly_cash_flow.lua | 38 +++++++------- reports/monthly_expenses.lua | 74 ++++++++++++++-------------- reports/monthly_net_worth.lua | 60 ++++++++++++++++++++++ reports/monthly_net_worth_change.lua | 61 +++++++++++++++++++++++ reports/quarterly_net_worth.lua | 60 ++++++++++++++++++++++ reports/years_income.lua | 70 +++++++++++++------------- 7 files changed, 314 insertions(+), 91 deletions(-) create mode 100644 reports/asset_allocation.lua create mode 100644 reports/monthly_net_worth.lua create mode 100644 reports/monthly_net_worth_change.lua create mode 100644 reports/quarterly_net_worth.lua diff --git a/reports/asset_allocation.lua b/reports/asset_allocation.lua new file mode 100644 index 0000000..6229fee --- /dev/null +++ b/reports/asset_allocation.lua @@ -0,0 +1,42 @@ +function generate() + accounts = get_accounts() + securities = get_securities() + default_currency = get_default_currency() + series_map = {} + totals_map = {} + + t = tabulation.new(1) + t:title("Current Asset Allocation") + + t:label(1, "Assets") + + for id, security in pairs(securities) do + totals_map[id] = 0 + series_map[id] = t:series(tostring(security)) + end + + for id, acct in pairs(accounts) do + if acct.type == account.Asset or acct.type == account.Investment or acct.type == account.Bank or acct.type == account.Cash then + balance = acct:balance() + multiplier = 1 + if acct.security ~= default_currency and balance.amount ~= 0 then + price = acct.security:closestprice(default_currency, date.now()) + if price == nil then + --[[ + -- This should contain code to warn the user that their report is missing some information + --]] + multiplier = 0 + else + multiplier = price.value + end + end + totals_map[acct.security.SecurityId] = balance.amount * multiplier + totals_map[acct.security.SecurityId] + end + end + + for id, series in pairs(series_map) do + series:value(1, totals_map[id]) + end + + return t +end diff --git a/reports/monthly_cash_flow.lua b/reports/monthly_cash_flow.lua index 08697a7..de44628 100644 --- a/reports/monthly_cash_flow.lua +++ b/reports/monthly_cash_flow.lua @@ -1,26 +1,26 @@ function generate() - year = date.now().year + year = date.now().year - accounts = get_accounts() - t = tabulation.new(12) - t:title(year .. " Monthly Cash Flow") - series = t:series("Income minus expenses") + accounts = get_accounts() + t = tabulation.new(12) + t:title(year .. " Monthly Cash Flow") + series = t:series("Income minus expenses") - for month=1,12 do - begin_date = date.new(year, month, 1) - end_date = date.new(year, month+1, 1) + for month=1,12 do + begin_date = date.new(year, month, 1) + end_date = date.new(year, month+1, 1) - t:label(month, tostring(begin_date)) - cash_flow = 0 + t:label(month, tostring(begin_date)) + cash_flow = 0 - for id, acct in pairs(accounts) do - if acct.type == account.Expense or acct.type == account.Income then - balance = acct:balance(begin_date, end_date) - cash_flow = cash_flow - balance.amount - end - end - series:value(month, cash_flow) - end + for id, acct in pairs(accounts) do + if acct.type == account.Expense or acct.type == account.Income then + balance = acct:balance(begin_date, end_date) + cash_flow = cash_flow - balance.amount + end + end + series:value(month, cash_flow) + end - return t + return t end diff --git a/reports/monthly_expenses.lua b/reports/monthly_expenses.lua index b523deb..cf00c94 100644 --- a/reports/monthly_expenses.lua +++ b/reports/monthly_expenses.lua @@ -1,49 +1,49 @@ function account_series_map(accounts, tabulation) - map = {} + map = {} - for i=1,100 do -- we're not messing with accounts more than 100 levels deep - all_handled = true - for id, acct in pairs(accounts) do - if not map[id] then - all_handled = false - if not acct.parent then - map[id] = tabulation:series(acct.name) - elseif map[acct.parent.accountid] then - map[id] = map[acct.parent.accountid]:series(acct.name) - end - end - end - if all_handled then - return map - end - end + for i=1,100 do -- we're not messing with accounts more than 100 levels deep + all_handled = true + for id, acct in pairs(accounts) do + if not map[id] then + all_handled = false + if not acct.parent then + map[id] = tabulation:series(acct.name) + elseif map[acct.parent.accountid] then + map[id] = map[acct.parent.accountid]:series(acct.name) + end + end + end + if all_handled then + return map + end + end - error("Accounts nested (at least) 100 levels deep") + error("Accounts nested (at least) 100 levels deep") end function generate() - year = date.now().year - account_type = account.Expense + year = date.now().year + account_type = account.Expense - accounts = get_accounts() - t = tabulation.new(12) - t:title(year .. " Monthly Expenses") - series_map = account_series_map(accounts, t) + accounts = get_accounts() + t = tabulation.new(12) + t:title(year .. " Monthly Expenses") + series_map = account_series_map(accounts, t) - for month=1,12 do - begin_date = date.new(year, month, 1) - end_date = date.new(year, month+1, 1) + for month=1,12 do + begin_date = date.new(year, month, 1) + end_date = date.new(year, month+1, 1) - t:label(month, tostring(begin_date)) + t:label(month, tostring(begin_date)) - for id, acct in pairs(accounts) do - series = series_map[id] - if acct.type == account_type then - balance = acct:balance(begin_date, end_date) - series:value(month, balance.amount) - end - end - end + for id, acct in pairs(accounts) do + series = series_map[id] + if acct.type == account_type then + balance = acct:balance(begin_date, end_date) + series:value(month, balance.amount) + end + end + end - return t + return t end diff --git a/reports/monthly_net_worth.lua b/reports/monthly_net_worth.lua new file mode 100644 index 0000000..55beb90 --- /dev/null +++ b/reports/monthly_net_worth.lua @@ -0,0 +1,60 @@ +function account_series_map(accounts, tabulation) + map = {} + + for i=1,100 do -- we're not messing with accounts more than 100 levels deep + all_handled = true + for id, acct in pairs(accounts) do + if not map[id] then + all_handled = false + if not acct.parent then + map[id] = tabulation:series(acct.name) + elseif map[acct.parent.accountid] then + map[id] = map[acct.parent.accountid]:series(acct.name) + end + end + end + if all_handled then + return map + end + end + + error("Accounts nested (at least) 100 levels deep") +end + +function generate() + year = date.now().year + + accounts = get_accounts() + t = tabulation.new(12) + t:title(year .. " Monthly Net Worth") + series_map = account_series_map(accounts, t) + default_currency = get_default_currency() + + for month=1,12 do + end_date = date.new(year, month+1, 1) + + t:label(month, tostring(end_date)) + + for id, acct in pairs(accounts) do + series = series_map[id] + if acct.type ~= account.Expense and acct.type ~= account.Income and acct.type ~= account.Trading then + balance = acct:balance(end_date) + multiplier = 1 + if acct.security ~= default_currency and balance.amount ~= 0 then + price = acct.security:closestprice(default_currency, end_date) + if price == nil then + --[[ + -- This should contain code to warn the user that their report is missing some information + --]] + multiplier = 0 + else + multiplier = price.value + end + end + series:value(month, balance.amount * multiplier) + end + end + end + + return t +end diff --git a/reports/monthly_net_worth_change.lua b/reports/monthly_net_worth_change.lua new file mode 100644 index 0000000..95b9ed5 --- /dev/null +++ b/reports/monthly_net_worth_change.lua @@ -0,0 +1,61 @@ +function account_series_map(accounts, tabulation) + map = {} + + for i=1,100 do -- we're not messing with accounts more than 100 levels deep + all_handled = true + for id, acct in pairs(accounts) do + if not map[id] then + all_handled = false + if not acct.parent then + map[id] = tabulation:series(acct.name) + elseif map[acct.parent.accountid] then + map[id] = map[acct.parent.accountid]:series(acct.name) + end + end + end + if all_handled then + return map + end + end + + error("Accounts nested (at least) 100 levels deep") +end + +function generate() + year = date.now().year + + accounts = get_accounts() + t = tabulation.new(12) + t:title(year .. " Monthly Net Worth") + series_map = account_series_map(accounts, t) + default_currency = get_default_currency() + + for month=1,12 do + begin_date = date.new(year, month, 1) + end_date = date.new(year, month+1, 1) + + t:label(month, tostring(begin_date)) + + for id, acct in pairs(accounts) do + series = series_map[id] + if acct.type ~= account.Expense and acct.type ~= account.Income and acct.type ~= account.Trading then + balance = acct:balance(begin_date, end_date) + multiplier = 1 + if acct.security ~= default_currency then + price = acct.security:closestprice(default_currency, end_date) + if price == nil then + --[[ + -- This should contain code to warn the user that their report is missing some information + --]] + multiplier = 0 + else + multiplier = price.value + end + end + series:value(month, balance.amount * multiplier) + end + end + end + + return t +end diff --git a/reports/quarterly_net_worth.lua b/reports/quarterly_net_worth.lua new file mode 100644 index 0000000..eb98386 --- /dev/null +++ b/reports/quarterly_net_worth.lua @@ -0,0 +1,60 @@ +function account_series_map(accounts, tabulation) + map = {} + + for i=1,100 do -- we're not messing with accounts more than 100 levels deep + all_handled = true + for id, acct in pairs(accounts) do + if not map[id] then + all_handled = false + if not acct.parent then + map[id] = tabulation:series(acct.name) + elseif map[acct.parent.accountid] then + map[id] = map[acct.parent.accountid]:series(acct.name) + end + end + end + if all_handled then + return map + end + end + + error("Accounts nested (at least) 100 levels deep") +end + +function generate() + year = date.now().year-4 + + accounts = get_accounts() + t = tabulation.new(20) + t:title(year .. "-" .. date.now().year .. " Quarterly Net Worth") + series_map = account_series_map(accounts, t:series("Net Worth")) + default_currency = get_default_currency() + + for month=1,20 do + end_date = date.new(year, month*3-2, 1) + + t:label(month, tostring(end_date)) + + for id, acct in pairs(accounts) do + series = series_map[id] + if acct.type ~= account.Expense and acct.type ~= account.Income and acct.type ~= account.Trading then + balance = acct:balance(end_date) + multiplier = 1 + if acct.security ~= default_currency then + price = acct.security:closestprice(default_currency, end_date) + if price == nil then + --[[ + -- This should contain code to warn the user that their report is missing some information + --]] + multiplier = 0 + else + multiplier = price.value + end + end + series:value(month, balance.amount * multiplier) + end + end + end + + return t +end diff --git a/reports/years_income.lua b/reports/years_income.lua index 4e9c20d..7ae19d0 100644 --- a/reports/years_income.lua +++ b/reports/years_income.lua @@ -1,47 +1,47 @@ function account_series_map(accounts, tabulation) - map = {} + map = {} - for i=1,100 do -- we're not messing with accounts more than 100 levels deep - all_handled = true - for id, acct in pairs(accounts) do - if not map[id] then - all_handled = false - if not acct.parent then - map[id] = tabulation:series(acct.name) - elseif map[acct.parent.accountid] then - map[id] = map[acct.parent.accountid]:series(acct.name) - end - end - end - if all_handled then - return map - end - end + for i=1,100 do -- we're not messing with accounts more than 100 levels deep + all_handled = true + for id, acct in pairs(accounts) do + if not map[id] then + all_handled = false + if not acct.parent then + map[id] = tabulation:series(acct.name) + elseif map[acct.parent.accountid] then + map[id] = map[acct.parent.accountid]:series(acct.name) + end + end + end + if all_handled then + return map + end + end - error("Accounts nested (at least) 100 levels deep") + error("Accounts nested (at least) 100 levels deep") end function generate() - year = date.now().year - account_type = account.Income + year = date.now().year + account_type = account.Income - accounts = get_accounts() - t = tabulation.new(1) - t:title(year .. " Income") - series_map = account_series_map(accounts, t) + accounts = get_accounts() + t = tabulation.new(1) + t:title(year .. " Income") + series_map = account_series_map(accounts, t) - begin_date = date.new(year, 1, 1) - end_date = date.new(year+1, 1, 1) + begin_date = date.new(year, 1, 1) + end_date = date.new(year+1, 1, 1) - t:label(1, year .. " Income") + t:label(1, year .. " Income") - for id, acct in pairs(accounts) do - series = series_map[id] - if acct.type == account_type then - balance = acct:balance(begin_date, end_date) - series:value(1, balance.amount) - end - end + for id, acct in pairs(accounts) do + series = series_map[id] + if acct.type == account_type then + balance = acct:balance(begin_date, end_date) + series:value(1, balance.amount) + end + end - return t + return t end