Files
moneyfy/backend/app/db/seed_data.py
T
moneyfyandClaude Opus 5 0b06775be3 feat: Projektfundament mit Datenmodell, Migrationen und Seed
- Repo-Struktur für Backend, Frontend, Dokumentation und Gitea-Workflows
- FastAPI-Skeleton mit pydantic-settings und RFC-7807-artigem Fehlerformat
- Vollständiges Datenmodell (15 Tabellen) als SQLAlchemy-2.0-Modelle
- Alembic gegen die Async-Engine inklusive Erstmigration
- Idempotenter Seed für den deutschen Kategoriebaum und Standardregeln
- Endpunkte /api/health und /api/version
- pytest-Infrastruktur mit transaktionsisolierten Fixtures

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
2026-09-09 13:12:08 +02:00

111 lines
3.6 KiB
Python

"""Deutscher Standard-Kategoriebaum für den Erst-Seed."""
from dataclasses import dataclass, field
from app.models.enums import EntryKind
@dataclass(frozen=True)
class SeedCategory:
"""Ein Knoten des Seed-Baums. Unterkategorien erben `kind` vom Elternknoten."""
name: str
icon: str = "circle"
color: str = "#64748b"
is_fixed_cost: bool = False
children: tuple["SeedCategory", ...] = field(default_factory=tuple)
# Ausgaben ----------------------------------------------------------------------
EXPENSE_TREE: tuple[SeedCategory, ...] = (
SeedCategory(
name="Wohnen",
icon="house",
color="#f97316",
is_fixed_cost=True,
children=(
SeedCategory("Miete", "key-round", "#f97316", True),
SeedCategory("Nebenkosten", "droplets", "#fb923c", True),
SeedCategory("Strom", "zap", "#facc15", True),
SeedCategory("Internet", "wifi", "#38bdf8", True),
SeedCategory("Rundfunkbeitrag", "radio", "#a78bfa", True),
),
),
SeedCategory(
name="Versicherungen",
icon="shield",
color="#0ea5e9",
is_fixed_cost=True,
children=(
SeedCategory("Haftpflicht", "shield-check", "#0ea5e9", True),
SeedCategory("Hausrat", "shield-half", "#22d3ee", True),
SeedCategory("Kfz", "car-front", "#38bdf8", True),
SeedCategory("Kranken", "heart-pulse", "#f472b6", True),
SeedCategory("BU", "briefcase-medical", "#818cf8", True),
),
),
SeedCategory(
name="Abos & Medien",
icon="repeat",
color="#a855f7",
is_fixed_cost=True,
children=(
SeedCategory("Streaming", "clapperboard", "#e11d48", True),
SeedCategory("Software", "app-window", "#8b5cf6", True),
SeedCategory("Cloud", "cloud", "#60a5fa", True),
SeedCategory("Zeitungen", "newspaper", "#94a3b8", True),
),
),
SeedCategory(
name="Mobilität",
icon="car",
color="#14b8a6",
children=(
SeedCategory("Kfz-Steuer", "landmark", "#14b8a6", True),
SeedCategory("Sprit", "fuel", "#f59e0b"),
SeedCategory("ÖPNV", "bus", "#10b981", True),
SeedCategory("Werkstatt", "wrench", "#64748b"),
),
),
SeedCategory(
name="Lebenshaltung",
icon="shopping-basket",
color="#84cc16",
children=(
SeedCategory("Lebensmittel", "shopping-cart", "#84cc16"),
SeedCategory("Drogerie", "sparkles", "#22c55e"),
SeedCategory("Restaurant", "utensils", "#f97316"),
),
),
SeedCategory(
name="Finanzen",
icon="banknote",
color="#6366f1",
children=(
SeedCategory("Kredite", "hand-coins", "#ef4444", True),
SeedCategory("Sparen", "piggy-bank", "#10b981", True),
SeedCategory("Gebühren", "receipt", "#94a3b8", True),
),
),
)
# Einkünfte ---------------------------------------------------------------------
INCOME_TREE: tuple[SeedCategory, ...] = (
SeedCategory(
name="Einkünfte",
icon="wallet",
color="#22c55e",
children=(
SeedCategory("Gehalt", "briefcase", "#22c55e"),
SeedCategory("Nebeneinkünfte", "laptop", "#4ade80"),
SeedCategory("Erstattungen", "undo-2", "#34d399"),
SeedCategory("Zinsen", "percent", "#a3e635"),
),
),
)
SEED_TREE: tuple[tuple[EntryKind, tuple[SeedCategory, ...]], ...] = (
(EntryKind.EXPENSE, EXPENSE_TREE),
(EntryKind.INCOME, INCOME_TREE),
)