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
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""Aufzählungstypen des Datenmodells (werden als native PostgreSQL-Enums angelegt)."""
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
from sqlalchemy import Enum as SAEnum
|
||||
|
||||
|
||||
class AccountType(StrEnum):
|
||||
CHECKING = "checking"
|
||||
CREDIT_CARD = "credit_card"
|
||||
SAVINGS = "savings"
|
||||
CASH = "cash"
|
||||
|
||||
|
||||
class EntryKind(StrEnum):
|
||||
"""Richtung eines Postens: Ausgabe oder Einnahme."""
|
||||
|
||||
EXPENSE = "expense"
|
||||
INCOME = "income"
|
||||
|
||||
|
||||
class BusinessDayShift(StrEnum):
|
||||
"""Verschiebung, wenn ein Fälligkeitstag auf Wochenende/Feiertag fällt."""
|
||||
|
||||
NONE = "none"
|
||||
NEXT = "next"
|
||||
PREVIOUS = "previous"
|
||||
|
||||
|
||||
class OccurrenceStatus(StrEnum):
|
||||
PLANNED = "planned"
|
||||
CONFIRMED = "confirmed"
|
||||
SKIPPED = "skipped"
|
||||
|
||||
|
||||
class LogoSource(StrEnum):
|
||||
SIMPLE_ICONS = "simple-icons"
|
||||
LOGODEV = "logodev"
|
||||
BRANDFETCH = "brandfetch"
|
||||
FAVICON = "favicon"
|
||||
UPLOAD = "upload"
|
||||
GENERATED = "generated"
|
||||
|
||||
|
||||
class LogoStatus(StrEnum):
|
||||
PENDING = "pending"
|
||||
RESOLVED = "resolved"
|
||||
FAILED = "failed"
|
||||
MANUAL = "manual"
|
||||
|
||||
|
||||
class NotificationType(StrEnum):
|
||||
DUE_SOON = "due_soon"
|
||||
NOTICE_DEADLINE = "notice_deadline"
|
||||
BUDGET_EXCEEDED = "budget_exceeded"
|
||||
CONTRACT_RENEWAL = "contract_renewal"
|
||||
|
||||
|
||||
class NotificationChannel(StrEnum):
|
||||
SMTP = "smtp"
|
||||
APPRISE = "apprise"
|
||||
|
||||
|
||||
class NotificationStatus(StrEnum):
|
||||
SENT = "sent"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
def pg_enum(enum_cls: type[StrEnum], name: str) -> SAEnum:
|
||||
"""Erzeugt einen nativen PostgreSQL-Enum-Typ mit den String-Werten der Enum-Klasse."""
|
||||
return SAEnum(
|
||||
enum_cls,
|
||||
name=name,
|
||||
native_enum=True,
|
||||
values_callable=lambda cls: [member.value for member in cls],
|
||||
validate_strings=True,
|
||||
)
|
||||
Reference in New Issue
Block a user