Adds graph date options and report option
Also checks for transactions before loop incase of months without transactions.
This commit is contained in:
parent
ff324ca0a6
commit
647af8be5b
36
main.py
36
main.py
@ -4,6 +4,7 @@ import datetime as dt
|
|||||||
|
|
||||||
from pfbudget.graph import average, discrete, monthly
|
from pfbudget.graph import average, discrete, monthly
|
||||||
from pfbudget.transactions import load_transactions, save_transactions
|
from pfbudget.transactions import load_transactions, save_transactions
|
||||||
|
import pfbudget.report as report
|
||||||
import pfbudget.tools as tools
|
import pfbudget.tools as tools
|
||||||
|
|
||||||
|
|
||||||
@ -143,10 +144,31 @@ def status(state, args):
|
|||||||
|
|
||||||
|
|
||||||
def graph(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":
|
if args.option == "monthly":
|
||||||
monthly(state, args.start, args.end)
|
monthly(state, start, end)
|
||||||
elif args.option == "discrete":
|
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__":
|
if __name__ == "__main__":
|
||||||
@ -205,8 +227,13 @@ if __name__ == "__main__":
|
|||||||
default="monthly",
|
default="monthly",
|
||||||
help="graph option help",
|
help="graph option help",
|
||||||
)
|
)
|
||||||
p_graph.add_argument("start", type=str, nargs="?", help="graph start date")
|
p_graph_interval = p_graph.add_mutually_exclusive_group()
|
||||||
p_graph.add_argument("end", type=str, nargs="?", help="graph end date")
|
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_init.set_defaults(func=init)
|
||||||
p_restart.set_defaults(func=restart)
|
p_restart.set_defaults(func=restart)
|
||||||
@ -215,6 +242,7 @@ if __name__ == "__main__":
|
|||||||
p_vacation.set_defaults(func=vacation)
|
p_vacation.set_defaults(func=vacation)
|
||||||
p_status.set_defaults(func=status)
|
p_status.set_defaults(func=status)
|
||||||
p_graph.set_defaults(func=graph)
|
p_graph.set_defaults(func=graph)
|
||||||
|
p_report.set_defaults(func=f_report)
|
||||||
|
|
||||||
state = tools.pfstate(p)
|
state = tools.pfstate(p)
|
||||||
state.filename = p
|
state.filename = p
|
||||||
|
|||||||
@ -148,6 +148,7 @@ def discrete(state, start, end):
|
|||||||
labels=["Fixed", "Required", "Health", *get_discretionary_expenses()],
|
labels=["Fixed", "Required", "Health", *get_discretionary_expenses()],
|
||||||
)
|
)
|
||||||
plt.legend(loc="upper left")
|
plt.legend(loc="upper left")
|
||||||
|
plt.grid()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
85
pfbudget/report.py
Normal file
85
pfbudget/report.py
Normal 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],
|
||||||
|
)
|
||||||
|
)
|
||||||
@ -153,15 +153,27 @@ def by_month(transactions, start=None, end=None) -> dict:
|
|||||||
|
|
||||||
def by_category(transactions) -> dict:
|
def by_category(transactions) -> dict:
|
||||||
transactions_by_category = dict.fromkeys(get_categories(), None)
|
transactions_by_category = dict.fromkeys(get_categories(), None)
|
||||||
for transaction in transactions:
|
|
||||||
try:
|
if transactions:
|
||||||
transactions_by_category[transaction.category].append(transaction)
|
for transaction in transactions:
|
||||||
except AttributeError:
|
try:
|
||||||
transactions_by_category[transaction.category] = [transaction]
|
transactions_by_category[transaction.category].append(transaction)
|
||||||
|
except AttributeError:
|
||||||
|
transactions_by_category[transaction.category] = [transaction]
|
||||||
|
|
||||||
return transactions_by_category
|
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:
|
def by_month_and_category(transactions, start, end) -> dict:
|
||||||
monthly_transactions_by_categories = {}
|
monthly_transactions_by_categories = {}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user