budget/pfbudget/graph.py
Luís Murta 0f5123d91e
Adds --save option to graph command
By passing the --save option the create graph is saved to a graph.png
file.
Entire argument dictionary passed to graph function.
2021-07-07 22:22:24 +01:00

132 lines
4.1 KiB
Python

from __future__ import annotations
from calendar import monthrange
from dateutil.rrule import rrule, MONTHLY
from typing import TYPE_CHECKING
import datetime as dt
import matplotlib.pyplot as plt
import pfbudget.categories
if TYPE_CHECKING:
from pfbudget.database import DBManager
def monthly(
db: DBManager, args: dict, start: dt.date = dt.date.min, end: dt.date = dt.date.max
):
transactions = db.get_daterange(start, end)
start, end = transactions[0].date, transactions[-1].date
monthly_transactions = tuple(
(
month,
{
group: sum(
transaction.value
for transaction in transactions
if transaction.category in categories
and month
<= transaction.date
<= month
+ dt.timedelta(days=monthrange(month.year, month.month)[1] - 1)
)
for group, categories in pfbudget.categories.groups.items()
},
)
for month in [
month.date()
for month in rrule(
MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1)
)
]
)
plt.figure(figsize=(30, 10))
plt.plot(
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
[groups["income"] for _, groups in monthly_transactions],
)
plt.stackplot(
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
[
[-groups[group] for _, groups in monthly_transactions]
for group in pfbudget.categories.groups
if group != "income" and group != "investment"
],
labels=[
group
for group in pfbudget.categories.groups
if group != "income" and group != "investment"
],
)
plt.legend(loc="upper left")
plt.tight_layout()
if args["save"]:
plt.savefig("graph.png")
else:
plt.show()
def discrete(
db: DBManager, args: dict, start: dt.date = dt.date.min, end: dt.date = dt.date.max
):
transactions = db.get_daterange(start, end)
start, end = transactions[0].date, transactions[-1].date
monthly_transactions = tuple(
(
month,
{
category: sum(
transaction.value
for transaction in transactions
if transaction.category == category
and month
<= transaction.date
<= month
+ dt.timedelta(days=monthrange(month.year, month.month)[1] - 1)
)
for category in pfbudget.categories.categories
},
)
for month in [
month.date()
for month in rrule(
MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1)
)
]
)
plt.figure(figsize=(30, 10))
plt.plot(
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
[
sum(
value
for category, value in categories.items()
if category in pfbudget.categories.groups["income"]
)
for _, categories in monthly_transactions
],
)
plt.stackplot(
list(rrule(MONTHLY, dtstart=start.replace(day=1), until=end.replace(day=1))),
[
[-categories[category] for _, categories in monthly_transactions]
for category in pfbudget.categories.categories
if category not in pfbudget.categories.groups["income"]
and category not in pfbudget.categories.groups["investment"]
],
labels=[
category
for category in pfbudget.categories.categories
if category not in pfbudget.categories.groups["income"]
and category not in pfbudget.categories.groups["investment"]
],
)
plt.legend(loc="upper left")
plt.tight_layout()
if args["save"]:
plt.savefig("graph.png")
else:
plt.show()