feat(api): Core-API mit Authentifizierung, CRUD und Monatsreport
- Anmeldung über Argon2id und JWT in httpOnly-Cookies, Refresh mit echter Rotation über die neue Tabelle refresh_token - AuthProvider-Protokoll als Vorbereitung für OIDC, Administrator-Anlage beim Erststart mit erzwungenem Passwortwechsel - CRUD für Konten, Kategorien (zweistufiger Baum), Firmen, Recurrences, Preisversionen, Buchungen, Budgets, Vorlagen und Sparziele - Fälligkeiten mit Overlay-Logik: abrufen, bestätigen, auslassen, zurücksetzen - Kontosalden zum Stichtag, Monatsübersicht mit Plan-Ist-Vergleich - SECRET_KEY jetzt mindestens 32 Zeichen; Platzhalter in Produktion abgelehnt - 61 neue Integrationstests, insgesamt 148 grün 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,64 @@
|
||||
"""Schemata für einzelne Fälligkeiten."""
|
||||
|
||||
from datetime import date
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from app.models.enums import EntryKind, OccurrenceStatus
|
||||
from app.schemas.common import ApiModel, InputModel, Money, PositiveMoney
|
||||
|
||||
|
||||
class OccurrenceOut(ApiModel):
|
||||
"""Eine berechnete Fälligkeit, ggf. überlagert von einer materialisierten Zeile."""
|
||||
|
||||
recurrence_id: int
|
||||
recurrence_title: str
|
||||
kind: EntryKind
|
||||
category_id: int
|
||||
merchant_id: int | None
|
||||
account_id: int | None
|
||||
nominal_date: date = Field(
|
||||
description="Von der Wiederholungsregel geliefertes Datum. Schlüssel für "
|
||||
"`confirm` und `skip`, auch wenn der Zahltag verschoben ist."
|
||||
)
|
||||
due_date: date = Field(description="Zahltag nach Wochenend- und Feiertagsverschiebung.")
|
||||
effective_date: date = Field(description="Ist-Datum, sonst der Zahltag.")
|
||||
amount: Money = Field(description="Sollbetrag laut Preishistorie.")
|
||||
actual_amount: Money | None = None
|
||||
effective_amount: Money = Field(description="Ist-Betrag, sonst Soll. Ausgelassene zählen 0.")
|
||||
status: OccurrenceStatus
|
||||
is_variable: bool
|
||||
occurrence_id: int | None = None
|
||||
note: str | None = None
|
||||
installment_number: int | None = None
|
||||
installments_total: int | None = None
|
||||
|
||||
|
||||
class OccurrenceConfirm(InputModel):
|
||||
"""Bestätigt eine Fälligkeit, wahlweise mit abweichendem Betrag oder Datum."""
|
||||
|
||||
recurrence_id: int
|
||||
occurrence_date: date = Field(description="Das nominale Datum aus `OccurrenceOut`.")
|
||||
actual_amount: PositiveMoney | None = Field(
|
||||
default=None, description="Ohne Angabe gilt der Sollbetrag."
|
||||
)
|
||||
actual_date: date | None = Field(
|
||||
default=None, description="Ohne Angabe gilt der berechnete Zahltag."
|
||||
)
|
||||
account_id: int | None = Field(default=None, description="Abweichendes Konto.")
|
||||
note: str | None = None
|
||||
|
||||
|
||||
class OccurrenceSkip(InputModel):
|
||||
"""Markiert eine Fälligkeit als ausgefallen; sie zählt danach nirgends mehr mit."""
|
||||
|
||||
recurrence_id: int
|
||||
occurrence_date: date
|
||||
note: str | None = None
|
||||
|
||||
|
||||
class OccurrenceReset(InputModel):
|
||||
"""Nimmt eine Bestätigung oder Auslassung zurück."""
|
||||
|
||||
recurrence_id: int
|
||||
occurrence_date: date
|
||||
Reference in New Issue
Block a user