Luís Murta c6cfd52b8b
Adds new Manager that will handle components
Move from a direct access to DB by the parsers/categorizers to a middle
layer, which will bring an easier way to have two input alternatives.
This patch starts by instantiating the manager on the cli runnable and
using it for the parser function.

This patch also moves the queries to a different file, so that
introducing new functions on the DB client becomes more manageable and
clearer.

Finally, the new manager will need converters to move from the code type
Transaction to the DB types. This will eventually simplify the code data
model by removing more of its method and leaving it a simple dataclass.

Issue #14
2022-10-06 22:22:54 +01:00

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.client import DatabaseClient
def net(db: DatabaseClient, 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: DatabaseClient, 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")