To improve the code organization, additional subfolders were added into the pfbudget module. The barebones of renewing the token and downloading transactions directly from the banks through the Nordigen API were also added. Issues #13, #15
139 lines
4.7 KiB
Python
139 lines
4.7 KiB
Python
from __future__ import annotations
|
|
from dateutil.rrule import rrule, YEARLY
|
|
from typing import TYPE_CHECKING
|
|
import datetime as dt
|
|
|
|
import pfbudget.core.categories
|
|
|
|
if TYPE_CHECKING:
|
|
from pfbudget.db.manager import DBManager
|
|
|
|
|
|
def net(db: DBManager, 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
|
|
|
|
yearly_transactions = tuple(
|
|
(
|
|
year,
|
|
{
|
|
group: sum(
|
|
transaction.value
|
|
for transaction in transactions
|
|
if transaction.category in categories
|
|
and year <= transaction.date <= year.replace(month=12, day=31)
|
|
)
|
|
for group, categories in pfbudget.core.categories.groups.items()
|
|
},
|
|
)
|
|
for year in [
|
|
year.date()
|
|
for year in rrule(
|
|
YEARLY, dtstart=start.replace(day=1), until=end.replace(day=1)
|
|
)
|
|
]
|
|
)
|
|
|
|
for year, groups in yearly_transactions:
|
|
print(f"\n{year.year}\n")
|
|
|
|
income = groups.pop("income-fixed") + groups.pop("income-extra")
|
|
print(f"Income: {income:.2f} €\n")
|
|
|
|
investments = -groups.pop("investment")
|
|
|
|
expenses = 0
|
|
for group, value in groups.items():
|
|
expenses -= value
|
|
if income != 0:
|
|
print(
|
|
f"{group.capitalize()} expenses: {-value:.2f} € ({-value/income*100:.1f}%)"
|
|
)
|
|
else:
|
|
print(f"{group.capitalize()} expenses: {-value:.2f} €")
|
|
|
|
print(f"\nNet total: {income-expenses:.2f} €")
|
|
if income != 0:
|
|
print(
|
|
f"Total expenses are {expenses:.2f} € ({expenses/income*100:.1f}% of income)\n"
|
|
)
|
|
else:
|
|
print(f"Total expenses are {expenses:.2f} €. No income this year!\n")
|
|
|
|
print(f"Invested: {investments:.2f}€\n")
|
|
|
|
|
|
def detailed(db: DBManager, 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
|
|
|
|
yearly_transactions: tuple[int, dict[str, float]] = tuple(
|
|
(
|
|
year.year,
|
|
{
|
|
category: sum(
|
|
transaction.value
|
|
for transaction in transactions
|
|
if transaction.category == category
|
|
and year <= transaction.date <= year.replace(month=12, day=31)
|
|
)
|
|
for category in pfbudget.core.categories.categories
|
|
},
|
|
)
|
|
for year in [
|
|
year.date()
|
|
for year in rrule(
|
|
YEARLY, dtstart=start.replace(day=1), until=end.replace(day=1)
|
|
)
|
|
]
|
|
)
|
|
|
|
for year, categories in yearly_transactions:
|
|
print(f"\n{year}\n")
|
|
|
|
income = sum(
|
|
sum
|
|
for category, sum in categories.items()
|
|
if category in pfbudget.core.categories.groups["income-fixed"]
|
|
or category in pfbudget.core.categories.groups["income-extra"]
|
|
)
|
|
print(f"Income: {income:.2f}€\n")
|
|
|
|
investments = -sum(
|
|
sum
|
|
for category, sum in categories.items()
|
|
if category in pfbudget.core.categories.groups["investment"]
|
|
)
|
|
|
|
expenses = 0
|
|
for category, value in categories.items():
|
|
if (
|
|
category not in pfbudget.core.categories.groups["income-fixed"]
|
|
and category not in pfbudget.core.categories.groups["income-extra"]
|
|
and category not in pfbudget.core.categories.groups["investment"]
|
|
):
|
|
if category == "Null":
|
|
if value != 0:
|
|
print(f"Null: {value} != 0€")
|
|
continue
|
|
expenses -= value
|
|
|
|
if income != 0:
|
|
print(
|
|
f"{category.capitalize()} expenses: {-value:.2f} € ({-value/income*100:.1f}%)"
|
|
)
|
|
else:
|
|
print(f"{category.capitalize()} expenses: {-value:.2f} €")
|
|
if income != 0:
|
|
print(
|
|
f"\nNet total: {income-expenses:.2f} € ({(income-expenses)/income*100:.1f}% of income)"
|
|
)
|
|
print(
|
|
f"Total expenses are {expenses:.2f} € ({expenses/income*100:.1f}% of income)\n"
|
|
)
|
|
else:
|
|
print(f"\nNet total: {income-expenses:.2f} €")
|
|
print(f"Total expenses are {expenses:.2f} €. No income this year!\n")
|
|
|
|
print(f"Invested: {investments:.2f}€\n")
|