subscription?->customer; $address = $customer?->email; if (blank($address)) { return; } $gebuehren = $this->feesSoFar($case); $this->send($address, new DunningNoticeMail( name: (string) ($customer->name ?? ''), level: $level, amountCents: (int) ($case->subscription->price_cents ?? 0), feeCents: DunningSchedule::feeCents($level), feeTotalCents: $gebuehren, currency: 'EUR', billingUrl: route('billing'), // Das Datum, an dem abgeschaltet wird — aber nur, solange es noch // bevorsteht. Eine Drohung ohne Termin ist keine Auskunft, und ein // Termin in der Vergangenheit wäre schlimmer als keiner. suspendOn: $level < DunningSchedule::SUSPENDED ? $case->opened_at->copy() ->addDays(DunningSchedule::dayOfLevel(DunningSchedule::SUSPENDED)) ->local()->isoFormat('D. MMMM YYYY') : null, )); } public function suspended(DunningCase $case): void { $customer = $case->subscription?->customer; if (blank($customer?->email)) { return; } $this->send($customer->email, new CloudSuspendedMail( name: (string) ($customer->name ?? ''), amountCents: (int) ($case->subscription->price_cents ?? 0), feeTotalCents: $this->feesSoFar($case), currency: 'EUR', billingUrl: route('billing'), )); } public function resumed(DunningCase $case): void { $customer = $case->subscription?->customer; if (blank($customer?->email)) { return; } $this->send($customer->email, new CloudResumedMail( name: (string) ($customer->name ?? ''), // Beglichen ist beglichen: keine Zahl mehr, die nach Restschuld // aussieht. amountCents: 0, feeTotalCents: 0, currency: 'EUR', billingUrl: route('cloud'), )); } /** Alle bisher angefallenen Mahnspesen dieses Falls. */ private function feesSoFar(DunningCase $case): int { return collect(array_keys($case->fee_invoice_ids ?? [])) ->sum(fn ($level) => DunningSchedule::feeCents((int) $level)); } private function send(string $address, object $mailable): void { try { Mail::to($address)->queue($mailable); } catch (Throwable $e) { // Siehe Kopfkommentar: laut, aber nicht kippend. Log::error('Eine Mahnungs-Mail liess sich nicht einreihen', [ 'mailable' => $mailable::class, 'exception' => $e->getMessage(), ]); } } }