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>
This commit is contained in:
Kevin Adametz 2026-09-18 10:41:04 +00:00
parent 72432fdb82
commit 9a88e82baa
15 changed files with 518 additions and 65 deletions

View file

@ -3,6 +3,7 @@
use App\Console\Commands\AggregatePressReleaseViews;
use App\Console\Commands\CheckIndexStatus;
use App\Console\Commands\CheckMailDomains;
use App\Console\Commands\ExpireGrandfathering;
use App\Console\Commands\FetchMailBounces;
use App\Console\Commands\GenerateManualInvoices;
use App\Console\Commands\PublishScheduledPressReleases;
@ -134,6 +135,15 @@ Schedule::command(PurgeConversionEvents::class)
// Manueller Rechnungskreis (MAN-) — Legacy-Zahlungen
// ========================================
// Bestandsschutz mit überschrittenem Legacy-Vertragsende beenden (Audit
// F06) — vor dem Rechnungslauf, damit kein beendeter Vertrag mehr
// abgerechnet wird.
Schedule::command(ExpireGrandfathering::class)
->dailyAt('04:15')
->withoutOverlapping()
->runInBackground()
->onFailure($alertOnFailure('billing:expire-grandfathering'));
// Fällige Rechnungen für laufende Legacy-Zahlungsvereinbarungen ausstellen
// (Periodenende erreicht), wie im Altsystem. Neue Abschlüsse laufen über
// Stripe (STR-Kreis) und werden hier nicht angefasst.