diff --git a/finance/.gitignore b/finance/.gitignore new file mode 100644 index 0000000..e3d2a42 --- /dev/null +++ b/finance/.gitignore @@ -0,0 +1,5 @@ +.env +__pycache__/ +*.sqlite +tests/fixtures/*.pdf +.venv/ diff --git a/finance/app/__init__.py b/finance/app/__init__.py new file mode 100644 index 0000000..473a0f4 diff --git a/finance/app/config.py b/finance/app/config.py new file mode 100644 index 0000000..12fdc74 --- /dev/null +++ b/finance/app/config.py @@ -0,0 +1,34 @@ +import os +from dataclasses import dataclass +from decimal import Decimal +from functools import lru_cache +from pathlib import Path + + +@dataclass(frozen=True) +class Settings: + database_url: str + api_key: str + gui_user: str + gui_password_hash: str + session_secret: str + inbox_dir: Path + uploads_dir: Path + warn_threshold: Decimal + horizon_days: int + + +@lru_cache +def get_settings() -> Settings: + e = os.environ.get + return Settings( + database_url=e("FB_DATABASE_URL", "sqlite:///./fb.sqlite"), + api_key=e("FB_API_KEY", ""), + gui_user=e("FB_GUI_USER", "admin"), + gui_password_hash=e("FB_GUI_PASSWORD_HASH", ""), + session_secret=e("FB_SESSION_SECRET", "dev-secret"), + inbox_dir=Path(e("FB_INBOX_DIR", "./inbox")), + uploads_dir=Path(e("FB_UPLOADS_DIR", "./uploads")), + warn_threshold=Decimal(e("FB_WARN_THRESHOLD", "0")), + horizon_days=int(e("FB_HORIZON_DAYS", "548")), + ) diff --git a/finance/pytest.ini b/finance/pytest.ini new file mode 100644 index 0000000..c898d22 --- /dev/null +++ b/finance/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests diff --git a/finance/requirements-dev.txt b/finance/requirements-dev.txt new file mode 100644 index 0000000..03fd52f --- /dev/null +++ b/finance/requirements-dev.txt @@ -0,0 +1,3 @@ +-r requirements.txt +pytest==8.4.1 +httpx==0.28.1 diff --git a/finance/requirements.txt b/finance/requirements.txt new file mode 100644 index 0000000..4b56046 --- /dev/null +++ b/finance/requirements.txt @@ -0,0 +1,9 @@ +fastapi==0.116.1 +uvicorn==0.35.0 +sqlalchemy==2.0.41 +alembic==1.16.2 +psycopg[binary]==3.2.9 +jinja2==3.1.6 +python-multipart==0.0.20 +itsdangerous==2.2.0 +pdfplumber==0.11.7 diff --git a/finance/tests/__init__.py b/finance/tests/__init__.py new file mode 100644 index 0000000..473a0f4 diff --git a/finance/tests/test_config.py b/finance/tests/test_config.py new file mode 100644 index 0000000..07ac514 --- /dev/null +++ b/finance/tests/test_config.py @@ -0,0 +1,7 @@ +from app.config import get_settings + + +def test_defaults(): + s = get_settings() + assert s.horizon_days == 548 + assert s.gui_user == "admin"