draft: category tree building
This commit is contained in:
+41
-8
@@ -84,6 +84,7 @@ class Category(ExportBaseModel):
|
|||||||
# TODO (maybe)
|
# TODO (maybe)
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
class CategoryDb(BaseModelDb):
|
class CategoryDb(BaseModelDb):
|
||||||
__tablename__ = "category"
|
__tablename__ = "category"
|
||||||
__table_args__ = (
|
__table_args__ = (
|
||||||
@@ -240,10 +241,10 @@ class CategoryBudgetDb(BaseModelDb):
|
|||||||
|
|
||||||
class CategoryTree(BaseModel):
|
class CategoryTree(BaseModel):
|
||||||
category: Category
|
category: Category
|
||||||
total_amount: float
|
total_amount: float | None = None
|
||||||
total_budget: float
|
total_budget: float | None = None
|
||||||
sub_categories: list[ CategoryTree ] | None
|
sub_categories: list[CategoryTree] | None = None
|
||||||
transactions: list[Transaction] | None
|
transactions: list[Transaction] | None = None
|
||||||
|
|
||||||
def get_total_amount(self) -> float:
|
def get_total_amount(self) -> float:
|
||||||
result = 0.0
|
result = 0.0
|
||||||
@@ -257,14 +258,46 @@ class CategoryTree(BaseModel):
|
|||||||
result = 0.0
|
result = 0.0
|
||||||
result += self.category.get_budget(date_valid)
|
result += self.category.get_budget(date_valid)
|
||||||
if self.sub_categories:
|
if self.sub_categories:
|
||||||
result += sum(category.category.get_budget(date_valid) for category in self.sub_categories)
|
result += sum(
|
||||||
|
category.category.get_budget(date_valid)
|
||||||
|
for category in self.sub_categories
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other: CategoryTree):
|
||||||
...
|
if self.category != other.category:
|
||||||
|
return
|
||||||
|
sub_categories = []
|
||||||
|
for category1 in self.sub_categories or []:
|
||||||
|
for category2 in other.sub_categories or []:
|
||||||
|
if category1.category == category2.category:
|
||||||
|
sub_categories.append(category1 + category2)
|
||||||
|
else:
|
||||||
|
sub_categories.append(category1)
|
||||||
|
sub_categories.append(category2)
|
||||||
|
|
||||||
|
return CategoryTree(
|
||||||
|
category=self.category,
|
||||||
|
total_amount=(self.total_amount or 0.0) + (other.total_amount or 0.0),
|
||||||
|
total_budget=(self.total_budget or 0.0) + (other.total_budget or 0.0),
|
||||||
|
sub_categories=sub_categories,
|
||||||
|
transactions=self.transactions + other.transactions,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_category_tree(transactions: list[Transaction]) -> list[CategoryTree]:
|
def build_category_tree(transactions: list[Transaction]) -> list[CategoryTree]:
|
||||||
# TODO: loop through flat list a build a category tree
|
# TODO: loop through flat list a build a category tree
|
||||||
result = []
|
result = []
|
||||||
for transaction in transactions:
|
for transaction in transactions:
|
||||||
pass
|
bla = _transaction_to_tree(transaction)
|
||||||
|
|
||||||
|
|
||||||
|
def _transaction_to_tree(transaction: Transaction) -> CategoryTree | None:
|
||||||
|
category = transaction.category
|
||||||
|
if not category:
|
||||||
|
return
|
||||||
|
result = CategoryTree(category=category, transactions=[transaction])
|
||||||
|
while category.parent is not None:
|
||||||
|
category = category.parent
|
||||||
|
result = CategoryTree(category=category, sub_categories=[result])
|
||||||
|
return result
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from pydantic import Field, computed_field
|
|||||||
from sqlalchemy import Date, ForeignKey, Index, Integer, String, UniqueConstraint
|
from sqlalchemy import Date, ForeignKey, Index, Integer, String, UniqueConstraint
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||||
|
|
||||||
|
from src.models.category import Category
|
||||||
from src.models.common import Amount, ExportBaseModel, IngestdbBase, date2str, hashify
|
from src.models.common import Amount, ExportBaseModel, IngestdbBase, date2str, hashify
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +30,8 @@ class Transaction(ExportBaseModel):
|
|||||||
other_name: str | None = None
|
other_name: str | None = None
|
||||||
other_iban: str | None = None
|
other_iban: str | None = None
|
||||||
# TODO: The Pydantic model should hold a category object, NOT the category id which is owned by the DB
|
# TODO: The Pydantic model should hold a category object, NOT the category id which is owned by the DB
|
||||||
category_id: int | None = None
|
category: Category | None
|
||||||
|
category_id: int | None = None # remove!
|
||||||
|
|
||||||
@computed_field # type: ignore[prop-decorator]
|
@computed_field # type: ignore[prop-decorator]
|
||||||
@property
|
@property
|
||||||
|
|||||||
Reference in New Issue
Block a user