Adds graph date options and report option

Also checks for transactions before loop incase of months without
transactions.
This commit is contained in:
Luís Murta 2021-02-03 21:57:57 +00:00
parent ff324ca0a6
commit 647af8be5b
Signed by: satprog
GPG Key ID: DDF2EFC6179009DC
4 changed files with 135 additions and 9 deletions

36
main.py
View File

@ -4,6 +4,7 @@ import datetime as dt
from pfbudget.graph import average, discrete, monthly
from pfbudget.transactions import load_transactions, save_transactions
import pfbudget.report as report
import pfbudget.tools as tools
@ -143,10 +144,31 @@ def status(state, args):
def graph(state, args):
start, end = None, None
if args.start or args.interval:
start = dt.datetime.strptime(args.start[0], "%Y/%m/%d").date()
if args.end or args.interval:
end = dt.datetime.strptime(args.end[0], "%Y/%m/%d").date()
if args.interval:
start = dt.datetime.strptime(args.interval[0], "%Y/%m/%d").date()
end = dt.datetime.strptime(args.interval[1], "%Y/%m/%d").date()
if args.year:
start = dt.datetime.strptime(args.year[0], "%Y").date()
end = dt.datetime.strptime(
str(int(args.year[0]) + 1), "%Y"
).date() - dt.timedelta(days=1)
if args.option == "monthly":
monthly(state, args.start, args.end)
monthly(state, start, end)
elif args.option == "discrete":
discrete(state, args.start, args.end)
discrete(state, start, end)
def f_report(state, args):
report.net(state)
if __name__ == "__main__":
@ -205,8 +227,13 @@ if __name__ == "__main__":
default="monthly",
help="graph option help",
)
p_graph.add_argument("start", type=str, nargs="?", help="graph start date")
p_graph.add_argument("end", type=str, nargs="?", help="graph end date")
p_graph_interval = p_graph.add_mutually_exclusive_group()
p_graph_interval.add_argument(
"--interval", type=str, nargs=2, help="graph interval", metavar=("START", "END")
)
p_graph_interval.add_argument("--start", type=str, nargs=1, help="graph start date")
p_graph_interval.add_argument("--end", type=str, nargs=1, help="graph end date")
p_graph_interval.add_argument("--year", type=str, nargs=1, help="graph year")
p_init.set_defaults(func=init)
p_restart.set_defaults(func=restart)
@ -215,6 +242,7 @@ if __name__ == "__main__":
p_vacation.set_defaults(func=vacation)
p_status.set_defaults(func=status)
p_graph.set_defaults(func=graph)
p_report.set_defaults(func=f_report)
state = tools.pfstate(p)
state.filename = p

View File

@ -148,6 +148,7 @@ def discrete(state, start, end):
labels=["Fixed", "Required", "Health", *get_discretionary_expenses()],
)
plt.legend(loc="upper left")
plt.grid()
plt.show()

85
pfbudget/report.py Normal file
View File

@ -0,0 +1,85 @@
from .categories import (
get_income_categories,
get_fixed_expenses,
get_required_expenses,
get_health_expenses,
get_discretionary_expenses,
)
from .transactions import (
load_transactions,
daterange,
by_category,
by_month,
by_month_and_category,
by_year_and_category,
)
def net(state, start=None, end=None):
transactions = load_transactions(state.data_dir)
if not start:
start = transactions[0].date
if not end:
end = transactions[-1].date
income, fixed, required, health, discretionary = [], [], [], [], []
yearly_transactions_by_categories = by_year_and_category(transactions, start, end)
for _, transactions_by_category in yearly_transactions_by_categories.items():
income.append(
sum(
float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_income_categories()
for t in transactions
)
)
fixed.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_fixed_expenses()
for t in transactions
)
)
required.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_required_expenses()
for t in transactions
)
)
health.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_health_expenses()
for t in transactions
)
)
discretionary.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_discretionary_expenses()
for t in transactions
)
)
for i, year in enumerate(yearly_transactions_by_categories.keys()):
print(year)
print(
"Income: {:.2f}, Expenses: {:.2f}, Net: {:.2f}\n"
"Fixed Expenses: {:.2f}\n"
"Required Expenses: {:.2f}\n"
"Health Expenses: {:.2f}\n"
"Discretionary Expenses: {:.2f}\n".format(
income[i],
fixed[i] + required[i] + health[i] + discretionary[i],
income[i] - (fixed[i] + required[i] + health[i] + discretionary[i]),
fixed[i],
required[i],
health[i],
discretionary[i],
)
)

View File

@ -153,6 +153,8 @@ def by_month(transactions, start=None, end=None) -> dict:
def by_category(transactions) -> dict:
transactions_by_category = dict.fromkeys(get_categories(), None)
if transactions:
for transaction in transactions:
try:
transactions_by_category[transaction.category].append(transaction)
@ -162,6 +164,16 @@ def by_category(transactions) -> dict:
return transactions_by_category
def by_year_and_category(transactions, start, end) -> dict:
yearly_transactions_by_category = {}
yearly_transactions = by_year(transactions, start, end)
for year, transactions in yearly_transactions.items():
yearly_transactions_by_category[year] = by_category(transactions)
return yearly_transactions_by_category
def by_month_and_category(transactions, start, end) -> dict:
monthly_transactions_by_categories = {}