value); } /** * Steht fest, dass der gespeicherte Katalog einem ANDEREN Konto gehört? * * Nur dann — nicht schon, wenn die Herkunft unbekannt ist. Das sind zwei * Zustände mit zwei Handlungsanweisungen, und sie zusammenzuwerfen war ein * teurer Fehler: „Herkunft nie festgehalten" entsteht ganz ohne Kontowechsel, * nämlich wenn ein Abgleich mitten im Anlegen abbricht oder wenn eine * Bestellung sich ihren fehlenden Preis selbst holt (CheckoutController → * PlanPrices::ensure(), BookAddon → SyncStripeAddonItems → * AddonPrices::ensure() — keiner der beiden ruft record()). Die Objekte * stammen dann aus genau dem geltenden Konto, und wer in diesem Zustand die * Leeranweisung für einen Kontowechsel liest, löscht einen Katalog, an dem * laufende Verträge abgerechnet werden. * * Unbekannte Herkunft ist trotzdem kein Freibrief: die Bereitschaftsseite * meldet sie weiter blockierend, nur mit dem Satz, der dazu passt („lauf den * Abgleich noch einmal"). Beweisen kann sie die Herkunft nicht. */ public static function belongsToAnotherMode(): bool { $recorded = self::recorded(); return $recorded !== null && $recorded !== OperatingMode::current(); } /** * Liegt überhaupt eine Stripe-Objekt-ID in der Datenbank? * * Alle vier Orte, an denen der Abgleich etwas hinterlässt — auch die zwei * Register, weil PlanPrices::inStep() für den Netto-Preis eines * Reverse-Charge-Kunden ALLEIN das Register fragt: eine geleerte Spalte in * `plan_prices` ohne gelöschte Registerzeile ließe genau diese Hälfte des * Katalogs still auf das alte Konto zeigen. */ public static function hasStoredObjects(): bool { return PlanFamily::query()->whereNotNull('stripe_product_id')->exists() || PlanPrice::query()->whereNotNull('stripe_price_id')->exists() || StripePlanPrice::query()->exists() || StripeAddonPrice::query()->exists(); } }