From da0a78d2d04c4d7990b16788b4eeb290acf46290 Mon Sep 17 00:00:00 2001 From: Mathias Scheider Date: Fri, 16 Oct 2026 16:47:08 +0200 Subject: [PATCH] yet another refactor --- src/helper/__init__.py | 1 - src/helper/category.py | 22 --------- src/ingest/b4w.py | 2 +- src/models/category.py | 24 +++++++++- tests/test_helper_db.py | 47 ------------------- tests/test_model_category.py | 87 ++++++++++++++++-------------------- 6 files changed, 61 insertions(+), 122 deletions(-) delete mode 100644 src/helper/__init__.py delete mode 100644 src/helper/category.py delete mode 100644 tests/test_helper_db.py diff --git a/src/helper/__init__.py b/src/helper/__init__.py deleted file mode 100644 index b99435e..0000000 --- a/src/helper/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Database helper for application-specific persistence operations.""" diff --git a/src/helper/category.py b/src/helper/category.py deleted file mode 100644 index 208b887..0000000 --- a/src/helper/category.py +++ /dev/null @@ -1,22 +0,0 @@ -from sqlalchemy.orm import Session - -from src.db_utils import upsert -from src.models.category import Category, CategoryDb - - -def upsert_category( - session: Session, category: Category | None, do_commit: bool = True -) -> CategoryDb | None: - if category is None: - return None - - parent = upsert_category(session, category.parent, do_commit=False) - parameters = {"name": category.name, "parent": parent} - return upsert( - session, - CategoryDb, - parameters, - parameters, - do_update=False, - do_commit=do_commit, - ) diff --git a/src/ingest/b4w.py b/src/ingest/b4w.py index 7186c22..98b180c 100644 --- a/src/ingest/b4w.py +++ b/src/ingest/b4w.py @@ -3,10 +3,10 @@ from pathlib import Path from sqlalchemy.orm import Session from src.db_utils import upsert -from src.helper.category import upsert_category from src.ingest.common import _reader_raw from src.ingest.transactions import consolidate_transactions, map_b4w_to_transaction from src.models.b4w import B4wDb, B4wExport +from src.models.category import upsert_category def reader_b4w(path: Path) -> list[B4wExport]: diff --git a/src/models/category.py b/src/models/category.py index 970151c..3dec8a8 100644 --- a/src/models/category.py +++ b/src/models/category.py @@ -1,7 +1,9 @@ from pydantic import Field, computed_field from sqlalchemy import ForeignKey, String, UniqueConstraint -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, Session, mapped_column, relationship +from src.db_utils import upsert +from src.models.category_budget import CategoryBudgetDb from src.models.common import BaseModelDb, ExportBaseModel, hashify @@ -53,4 +55,22 @@ class CategoryDb(BaseModelDb): "CategoryDb", remote_side="CategoryDb.id", back_populates="children" ) children = relationship("CategoryDb", back_populates="parent") - budgets = relationship("CategoryBudgetDb", back_populates="category") + budgets: Mapped[list[CategoryBudgetDb]] = relationship(back_populates="category") + + +def upsert_category( + session: Session, category: Category | None, do_commit: bool = True +) -> CategoryDb | None: + if category is None: + return None + + parent = upsert_category(session, category.parent, do_commit=False) + parameters = {"name": category.name, "parent": parent} + return upsert( + session, + CategoryDb, + parameters, + parameters, + do_update=False, + do_commit=do_commit, + ) diff --git a/tests/test_helper_db.py b/tests/test_helper_db.py deleted file mode 100644 index ea1722e..0000000 --- a/tests/test_helper_db.py +++ /dev/null @@ -1,47 +0,0 @@ -from sqlalchemy import select -from sqlalchemy.orm import Session - -from src.helper.category import upsert_category -from src.models import Category -from src.models.category import CategoryDb - - -def test_upsert_category_returns_orm_object(db_session: Session): - result = upsert_category( - db_session, - Category.from_str("dummy_parent_1:dummy_parent_2:dummy"), - do_commit=False, - ) - assert result - assert isinstance(result, CategoryDb) - assert str(result.name) == "dummy" - assert str(result.parent.name) == "dummy_parent_2" - assert str(result.parent.parent.name) == "dummy_parent_1" - - -def test_upsert_category_writes_new_to_db(db_session: Session): - upsert_category( - db_session, - Category.from_str("grand_father:father:new_category"), - do_commit=True, - ) - result = db_session.execute( - select(CategoryDb).filter_by(name="new_category") - ).scalar_one() - assert result - assert str(result.name) == "new_category" - assert str(result.parent.name) == "father" - assert str(result.parent.parent.name) == "grand_father" - - -def test_upsert_category_skips_existing(db_session: Session): - for _ in range(3): - upsert_category( - db_session, - Category.from_str("grand_father:father:try_again_and_again"), - do_commit=True, - ) - result = db_session.execute( - select(CategoryDb).filter_by(name="try_again_and_again") - ).all() - assert len(result) == 1 diff --git a/tests/test_model_category.py b/tests/test_model_category.py index d6b0c5e..587bd65 100644 --- a/tests/test_model_category.py +++ b/tests/test_model_category.py @@ -1,56 +1,45 @@ -from src.models import Category +from sqlalchemy import select +from sqlalchemy.orm import Session + +from src.models.category import Category, CategoryDb, upsert_category -def test_single_level_category(): - c = Category.from_str("single") - assert c - assert c.name == "single" - assert c.parent is None - - -def test_two_level_category(): - c = Category.from_str("first:second") - assert c - assert c.name == "second" - assert isinstance(c.parent, Category) - assert c.parent.name == "first" - assert c.parent.parent is None - - -def test_three_level_category(): - c = Category.from_str("first:second:third") - assert c - assert c.name == "third" - assert isinstance(c.parent, Category) - assert c.parent.name == "second" - assert isinstance(c.parent.parent, Category) - assert c.parent.parent.name == "first" - assert c.parent.parent.parent is None - - -def test_single_level_category_to_string(): - c = Category.from_str("single") - assert c - assert str(c) == "single" - - -def test_two_level_category_to_string(): - c = Category(name="second", parent=Category(name="first")) - assert c.to_str() == "first:second" - - -def test_three_level_category_to_string(): - c = Category( - name="third", parent=Category(name="second", parent=Category(name="first")) +def test_upsert_category_returns_orm_object(db_session: Session): + result = upsert_category( + db_session, + Category.from_str("dummy_parent_1:dummy_parent_2:dummy"), + do_commit=False, ) - assert c.to_str() == "first:second:third" + assert result + assert isinstance(result, CategoryDb) + assert str(result.name) == "dummy" + assert str(result.parent.name) == "dummy_parent_2" + assert str(result.parent.parent.name) == "dummy_parent_1" -def test_category_str(): - c = Category.from_str("first:second:third") - assert str(c) == "first:second:third" +def test_upsert_category_writes_new_to_db(db_session: Session): + upsert_category( + db_session, + Category.from_str("grand_father:father:new_category"), + do_commit=True, + ) + result = db_session.execute( + select(CategoryDb).filter_by(name="new_category") + ).scalar_one() + assert result + assert str(result.name) == "new_category" + assert str(result.parent.name) == "father" + assert str(result.parent.parent.name) == "grand_father" -def test_category_repr(): - c = Category.from_str("first:second:third") - assert repr(c) == 'Category.from_str("first:second:third")' +def test_upsert_category_skips_existing(db_session: Session): + for _ in range(3): + upsert_category( + db_session, + Category.from_str("grand_father:father:try_again_and_again"), + do_commit=True, + ) + result = db_session.execute( + select(CategoryDb).filter_by(name="try_again_and_again") + ).all() + assert len(result) == 1