presseportale/app/Mail/GrandfatheringExpired.php
Kevin Adametz 9a88e82baa billing/dev: Vertragsende in der MAN-Abrechnung, Rechnungslauf ohne Tageskappe, Qualitätsgates (Audit Block 5+6, Deploy E)
Block 5 — MAN-Abrechnung

F06 (E6): Ein explizites Legacy-Vertragsende (grandfathered_until) deckelt
jetzt Auswahl und Sperr-Nachprüfung: Beginnt die nächste Periode nach dem
Vertragsende, gibt es keine Rechnung mehr. Neuer täglicher Befehl
billing:expire-grandfathering (04:15, vor dem Rechnungslauf) setzt
abgelaufene Posten auf gekündigt und schickt je Kunde eine Mail
(GrandfatheringExpired). Auf der Dev-Kopie trägt kein Posten ein
Vertragsende; der Fehler war latent.

F16: Nicht abrechenbare Vereinbarungen bekommen einen Sperrvermerk
(billing_hold_reason/-at), sichtbar auf der Admin-Zahlungsseite, und
stehen im Rechnungslauf hinten an. Der Lauf arbeitet den fälligen Bestand
in Seiten ab; --limit deckelt die erstellten Rechnungen (500), nicht die
betrachteten Fälle. Vorher blockierten 50 unvollständige Fälle die 51.
dauerhaft, und der Durchsatz war auf 50 am Tag begrenzt.

Block 6 — Entwicklung

F24: Lint-Workflow prüft mit pint --test statt zu formatieren; keine
Schreibrechte mehr.
F27: composer run dev startet beide Vite-Server (npm run dev:all).
F28: docs/README.md als historischer Stand markiert, toter Link auf das
Hub-Flux-Archiv korrigiert, aktueller Einstieg dev/README.md.
F26: Login-Modal übernimmt den Fokus, hält Tab im Dialog und gibt den
Fokus beim Schließen an den Auslöser zurück – ohne neue Abhängigkeit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 10:41:04 +00:00

48 lines
1.3 KiB
PHP

<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon;
/**
* Information an den Kunden, dass sein Bestandsschutz zum vertraglich
* vereinbarten Ende ausgelaufen ist (Audit F06) — keine Mahnung, keine
* Stornierung, nur der Hinweis, wie es weitergeht.
*
* Transaktionsmail: bewusst ohne Opt-out.
*/
class GrandfatheringExpired extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public string $bookingUrl;
public function __construct(
public readonly User $user,
public readonly ?Carbon $endedOn,
) {
$this->bookingUrl = route('me.bookings.index');
}
public function envelope(): Envelope
{
$bcc = (string) config('legal.contact_email');
return new Envelope(
subject: 'Ihr Bestandsschutz auf pressekonto ist zum Vertragsende ausgelaufen',
bcc: $bcc !== '' ? [$bcc] : [],
);
}
public function content(): Content
{
return new Content(view: 'emails.billing.grandfathering-expired');
}
}