Files
finanz-cockpit/tests/factories.py
T
mathias2784 6babc560c7
Tests / test (push) Successful in 16s
Tests / lint (push) Successful in 16s
Category overhaul (#20)
Reviewed-on: #20
Co-authored-by: Mathias <mathias2784@web.de>
2026-10-27 18:08:10 +00:00

142 lines
3.5 KiB
Python

from decimal import Decimal
from pathlib import Path
from typing import Any
from faker import Faker
from polyfactory.factories.pydantic_factory import ModelFactory
from polyfactory.fields import Use
from src.models.b4w import B4wExport
from src.models.category import Category
from src.models.comdirect import ComdirectCreditCard, ComdirectDepot, ComdirectGiro
from src.models.transactions import Transaction
CATEGORY_PATHS = tuple(
line.strip()
for line in (
Path(__file__).resolve().parents[1]
/ "scripts/initial_load/categories/categories.txt"
)
.read_text(encoding="utf-8")
.splitlines()
if line.strip()
)
def _category_from_path(path: str) -> Category:
category = Category.from_str(path)
if category is None:
raise ValueError("Category list contains an empty path")
return category
class CategoryFactory:
__faker__ = Faker("de_DE")
@classmethod
def build(cls) -> Category:
return _category_from_path(cls.__faker__.random_element(CATEGORY_PATHS))
@staticmethod
def build_all() -> list[Category]:
return [_category_from_path(path) for path in CATEGORY_PATHS]
def _faker_or_none(faker: Faker, non_default: Any, default: Any = None, p_value=0.5):
if faker.pyfloat(min_value=0.0, max_value=1.0) < p_value:
return default
return non_default
def _amount() -> Decimal:
return B4wExportFactory.__faker__.pydecimal(
left_digits=6,
right_digits=2,
positive=True,
min_value=Decimal("0.01"),
)
def _amount_eur() -> str:
"""Generate German-formatted decimal string (e.g., '32,43')."""
val = Faker().pydecimal(
right_digits=2, min_value=Decimal("-4000.00"), max_value=Decimal("4000.00")
)
# Format as German string with comma decimal separator
return f"{val:.2f}".replace(".", ",").strip()
def _german_date() -> str:
return Faker().date("%d.%m.%Y")
def _sentence() -> str:
return B4wExportFactory.__faker__.sentence(
nb_words=8,
variable_nb_words=False,
)
def _names() -> str:
return B4wExportFactory.__faker__.company()
def _iban() -> str:
return B4wExportFactory.__faker__.iban()
def _iban_or_none() -> str:
return _faker_or_none(Faker(), Faker().iban(), default="")
class B4wExportFactory(ModelFactory[B4wExport]):
__faker__ = Faker("de_DE")
__use_examples__ = True
Amt = Use(_amount)
RmtInf = Use(_sentence)
Notes = Use(_sentence)
RmtdNm = Use(_names)
OwnrAcctIBAN = Use(_iban)
RmtdAcctIBAN = Use(_iban_or_none)
class ComdirectGiroFactory(ModelFactory[ComdirectGiro]):
__faker__ = Faker("de_DE")
__use_examples__ = True
text = Use(_sentence)
amount_eur = Use(_amount_eur)
date_val = Use(_german_date)
date_book = Use(_german_date)
class ComdirectCreditCardFactory(ModelFactory[ComdirectCreditCard]):
__faker__ = Faker("de_DE")
__use_examples__ = True
text = Use(_sentence)
amount_eur = Use(_amount_eur)
date_val = Use(_german_date)
date_book = Use(_german_date)
class ComdirectDepotFactory(ModelFactory[ComdirectDepot]):
__faker__ = Faker("de_DE")
__use_examples__ = True
amount_eur = Use(_amount_eur)
date_val = Use(_german_date)
num = Use(_amount_eur)
spot_price = Use(_amount_eur)
class TransactionFactory(ModelFactory[Transaction]):
__faker__ = Faker("de_DE")
__use_examples__ = True
account_iban = Use(_iban)
text = Use(_sentence)
other_name = Use(_names)
other_iban = Use(_iban_or_none)