Datenbankfreie Kernberechnung auf Basis schlanker Protokolle, sodass sowohl ORM-Objekte als auch Testdatenklassen verarbeitet werden. - expand() mit voller RFC-5545-Unterstützung, Fensterbegrenzung und Overlays - expand_by_due_date() für Sichten, die nach dem tatsächlichen Zahltag gruppieren - Werktagsverschiebung über den NRW-Feiertagskalender, nominales Datum als Schlüssel - Preishistorie, Ratenzahlungen, Vertragsfristen und Rücklagenberechnung - validate_rrule() und next_dates() für Eingabeprüfung und Terminvorschau - 81 Unit-Tests, davon alle in Abschnitt 2 geforderten Fälle Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
64 lines
1.8 KiB
Python
64 lines
1.8 KiB
Python
"""Leichtgewichtige Testobjekte für die Recurrence-Engine – bewusst ohne Datenbank."""
|
||
|
||
from dataclasses import dataclass, field
|
||
from datetime import date
|
||
from decimal import Decimal
|
||
|
||
from app.models.enums import BusinessDayShift, EntryKind, OccurrenceStatus
|
||
|
||
|
||
@dataclass
|
||
class FakeAmountVersion:
|
||
"""Preisversion, gültig ab `valid_from`."""
|
||
|
||
amount: Decimal
|
||
valid_from: date
|
||
note: str | None = None
|
||
|
||
|
||
@dataclass
|
||
class FakeOccurrence:
|
||
"""Materialisierte Fälligkeit, die das virtuelle Ergebnis überlagert."""
|
||
|
||
occurrence_date: date
|
||
status: OccurrenceStatus = OccurrenceStatus.PLANNED
|
||
actual_amount: Decimal | None = None
|
||
actual_date: date | None = None
|
||
account_id: int | None = None
|
||
note: str | None = None
|
||
id: int | None = 1
|
||
|
||
|
||
@dataclass
|
||
class FakeRecurrence:
|
||
"""Erfüllt `RecurrenceLike` mit denselben Vorgabewerten wie das ORM-Modell."""
|
||
|
||
rrule: str
|
||
dtstart: date
|
||
amount: Decimal = Decimal("100.00")
|
||
kind: EntryKind = EntryKind.EXPENSE
|
||
id: int | None = 1
|
||
is_variable: bool = False
|
||
until: date | None = None
|
||
business_day_shift: BusinessDayShift = BusinessDayShift.NONE
|
||
holiday_region: str = "DE-NW"
|
||
installments_total: int | None = None
|
||
principal_amount: Decimal | None = None
|
||
contract_start: date | None = None
|
||
contract_min_term_months: int | None = None
|
||
contract_notice_period_days: int | None = None
|
||
contract_auto_renew_months: int | None = None
|
||
contract_cancelled_at: date | None = None
|
||
reserve_enabled: bool = False
|
||
account_id: int | None = 1
|
||
amount_versions: list[FakeAmountVersion] = field(default_factory=list)
|
||
|
||
|
||
def d(value: str) -> date:
|
||
"""Kurzschreibweise für ISO-Datumsangaben in Tests."""
|
||
return date.fromisoformat(value)
|
||
|
||
|
||
def euro(value: str) -> Decimal:
|
||
return Decimal(value)
|