Commit graph

204 commits

Author SHA1 Message Date
7494f19b4a Plan: R2.4 SEO-Basics erledigt (Sitemap, robots, Meta)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:34:43 +00:00
b855cbf7c0 Plan: Kuendigungsbutton (R3.0b) + Erloeschens-Checkbox (R3.0c) erledigt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 11:42:17 +00:00
239ec571bc Plan: Rechtstexte-Architektur referenziert + Hub-Geruest-Vorarbeit notiert
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:48:07 +00:00
8001280185 Plan: Online-Widerruf (R3.0) erledigt + Follow-ups notiert
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:04:05 +00:00
38d7cca086 Plan: R2.2/R2.3 erledigt (Hub-Ueberarbeitung + Plan-Katalog-Pipeline verifiziert)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:24:39 +00:00
5226f5de2b Plan: R2.1 erledigt + naechste Schritte notiert
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:15:25 +00:00
1e9c2f96ed Plan: R0 komplett + R1.1/R1.3 erledigt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:08:45 +00:00
cb2fe97609 Plan: Release-Entwicklungsplan (R0-R6) aus Vier-Achsen-Analyse konsolidiert
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:50:37 +00:00
90f3245e41 Plan: Phase 5 vollstaendig abgeschlossen (5.2/5.3/5.5 auf erledigt)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 10:44:15 +00:00
0e08d8acc4 5.5: Auth-Components abgeschlossen (funktional gegengetestet) + Plan-Stand
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 10:11:23 +00:00
6b1d84fc01 Doku: 5.4 abgeschlossen + 5.5 Teil-Stand im Entwicklungsplan
5.4 als erledigt markiert (page-header/empty-state/table-pagination; table-
panel + searchable-select bewusst nicht gebaut). 5.5 Teil-erledigt (alert +
session-status); password-input + rate-limit-trait mit Begruendung zurueck-
gestellt. Wiedereinstieg-Abschnitt + Datum aktualisiert, Perf-Fix vermerkt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 08:44:44 +00:00
c16b0b77e2 Doku: portalBadgeColor()-Klaerung im Plan vermerkt (toter Code entfernt)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 10:57:19 +00:00
63071a0a3e Doku: Stand & Wiedereinstieg-Abschnitt im Entwicklungsplan
Klarer Status (Phasen 0-4 + 5.1 fertig, 5.2/5.3 teilweise) und konkrete
Reihenfolge fuer den Wiedereinstieg in die verbleibende Blade-Component-Arbeit
(visuelle QA noetig, eine Component pro Commit). Hinweise zu ausgeschlossenen
User-Dateien (sidebar, web/**) festgehalten.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:25:22 +00:00
dc68404891 Doku: Phase-5.3-Fortschritt (displayName/localizedName erledigt, Rest UI-lastig)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:20:33 +00:00
89842ac37f Optimierung 5.2 (Teil 1): ProvidesUserFormRules-Concern
Die zwischen Benutzer-Anlegen und -Bearbeiten identischen Validierungsbloecke
liegen jetzt in ProvidesUserFormRules: userIdentityRules(?int $ignore) (E-Mail-
Unique ignoriert beim Bearbeiten den eigenen Datensatz), userRolesAndCompaniesRules()
und userBillingRules(). Beide Formulare nutzen die Array-Spreads; die nur im
Bearbeiten genutzten Profil-/Kontakt-Regeln bleiben dort inline. Ungenutzten
Rule-Import aus dem Anlegen-Formular entfernt.

Offen (mit User abzustimmen, UI-/Divergenz-lastig): gemeinsamer Save-Service und
die Blade-Feld-Components.

31 User-Tests gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:41:57 +00:00
a8958c176e Optimierung 5.1: Tabellen-Concerns (Sortierung, Volltext-Heuristik, Stats)
- HasSortableTable::sort() ersetzt 5 byte-identische sort()-Kopien in den
  Admin-Listen (Benutzer, Firmen, Kategorien, Kontakte, Pressemitteilungen).
  $sortBy/$sortDir-Defaults bleiben je Komponente, da sie divergieren.
- HasFullTextSearch::supportsFullTextSearch() ersetzt 9 byte-identische Kopien
  (4 Index-Listen + 5 Firmen-Comboboxen); ungenutzte DB-Imports entfernt.
- AdminPerformanceCache::activeInactiveStats(Builder) buendelt den identischen
  SUM(CASE WHEN is_active)-Block der Benutzer- und Firmenliste.

Zurueckgestellt (real divergent): HasResettableFilters (updatedXxxFilter
normalisieren teils zusaetzlich) und eine gemeinsame hydrateRelationCounts().

Tests: erweiterte AdminPerformanceCacheTest; 99 Admin-Tests bleiben gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:36:48 +00:00
8e0aedaf95 Doku: Phase 4 im Entwicklungsplan abgeschlossen markiert (4.1-4.4)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:16:13 +00:00
e5a63bcedd Optimierung 4.1: Web-Portal-/Domain-Kontext extrahiert
- WebPortalContext::fromRequest() buendelt die zuvor ~6x je Route-Closure
  wiederholte Host->Portal-Ableitung (portal, language, portalValues,
  domainConfig).
- DomainAssetContext::applyWebDomainConfig() ist die Single Source of Truth fuer
  die Domain-/Theme-Anwendung (config + View::share + Vite); die fruehere
  $applyWebDomainConfig-Closure in routes/web.php ist nur noch ein duenner
  Delegations-Wrapper, damit Bare-Root- und Edition-Home-Route unveraendert
  per Closure aufrufen koennen.
- Die 6 Portal-Seiten-Closures (Kategorie, Detail, Veroeffentlichen, Suche,
  Newsrooms, Newsroom-Detail) sowie Preise nutzen jetzt den zentralen Kontext.

Abgesichert durch die 92 Web/-Tests (jede Seite laeuft ueber den neuen Kontext).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:42:00 +00:00
987a5a2c42 Optimierung 4.2: Published-Release-Query ueber PressRelease-Scopes zentralisiert
Vier komponierbare Scopes auf PressRelease:
- published()         Status freigegeben + published_at gesetzt (ohne Zeitschranke,
                      damit Statistik-Fenster frei einschraenken koennen)
- visibleInArchive()  published() + published_at <= jetzt (oeffentlich sichtbar)
- forPortalValues()   whereIn portal
- forLanguage()       where language

~19 duplizierte Query-Bloecke in routes/web.php (Home, Kategorie, Detail,
Veroeffentlichen, Suche, Newsrooms, Newsroom-Detail, Legacy-Redirect) nutzen
jetzt diese Scopes. Jedes withoutGlobalScope(PortalScope) bleibt an seiner
Stelle erhalten; die Klausel-Reihenfolge ist fuers Ergebnis irrelevant (reine
AND-Verknuepfung), daher verhaltensgleich.

Test: Web/PublishedReleaseScopeTest; die 89 bestehenden Web/-Tests bleiben gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:35:55 +00:00
4c80b934ab Doku: Phase 3 im Entwicklungsplan abgeschlossen markiert (3.1-3.3 nachgezogen)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:21:22 +00:00
31e01e46b6 Optimierung 3.6: Zugriffs-Gates und getrennte Impersonation-Sperre
- Gate::define('access-admin'|'access-customer') als Single Source of Truth im
  AppServiceProvider (auch via @can/Policies nutzbar). EnsureUserIsAdmin und
  EnsureUserIsCustomer pruefen jetzt ueber diese Gates.
- Impersonation-Redirect aus EnsureUserIsAdmin in die eigene Middleware
  BlockAdminDuringImpersonation ausgelagert (Sitzungs-Bedingung statt
  Rollenfrage); laeuft vor der Zugriffspruefung und ist zusaetzlich als
  persistente Livewire-Middleware registriert.
- Routen-Alias 'can:' bewusst NICHT verwendet: die Admin-Middleware ist
  persistente Livewire-Middleware und braucht eine konkrete Klasse; der
  parametrisierte Alias kann dort nicht stehen. EnsureApiUserIsActive bleibt
  eigenstaendig (is_active-Pruefung mit getesteter JSON-Antwort, kein Gate).
- Tests: Auth/AccessGatesTest; UserImpersonationTest bleibt gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:20:28 +00:00
b255d90721 Optimierung 3.5: Kleinere Zentralisierungen (VAT, findByEmail, Waehrung, Provisioning)
- VatResolver::normalizeCountryCode()/isEuCountry() als Single Source of Truth;
  resolve(), VatIdValidationService und StripeCheckoutService nutzen jetzt die
  zentrale EU-Pruefung statt eigener config-Lookups.
- User::findByEmail() buendelt die LOWER(email)-Lookups (ContactAccessService,
  SocialAuthService). Bleibt bewusst case-insensitiv, da E-Mails nicht
  normalisiert gespeichert werden; der indexfreundliche Direktvergleich
  braucht erst eine Schreib-Normalisierung (offen, dokumentiert).
- config('billing.default_currency') ersetzt 8 verstreute 'EUR'/'eur'-Literale
  (Stripe-Calls via strtolower). Vereinheitlicht nebenbei die zuvor uneinheitlich
  gespeicherte SinglePurchase.currency.
- Neuer CustomerAccountProvisioner::provisionVerifiedCustomer() ist die
  gemeinsame Provisioning-Methode (verifiziert + aktiv + customer-Rolle) fuer
  ContactAccessService und SocialAuthService.
- Tests: UserFindByEmailTest, erweiterte VatResolverTest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:14:05 +00:00
31d407d3ad Optimierung 3.4: Performance (Logging terminable, Single-Purchase memoisiert)
- LogApiUsage als terminable Middleware: der ApiUsageLog-INSERT laeuft nach
  gesendeter Antwort und verlaengert nicht mehr die Request-Dauer. Startzeit
  wird ueber ein Request-Attribut uebergeben (terminate() laeuft auf frischer
  Instanz).
- User::openSinglePurchaseCount() memoisiert die offenen Einmalkaeufe pro
  Request. Vorher wurde derselbe grantingSubmission-Count im Status-Widget
  mehrfach (Quota-Total, Quota-Remaining, openSinglePurchases) plus ein
  exists() in hasActiveBooking abgesetzt -> jetzt eine Query.
- CustomerCompanyContext::selectedCompany() nutzt eine einzige first()-Query
  statt exists()+first(); das Verwerfen nicht (mehr) erreichbarer Auswahlen
  bleibt erhalten.
- LegacySubscriptionService::cancelBundleFor() ist ein einziges Bulk-Update
  statt Update-pro-Iteration (UserPaymentOption hat keine Observer/Events).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:05:07 +00:00
6a1240bdfb Doku: Phase 2 im Entwicklungsplan als abgeschlossen markiert
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:17:28 +00:00
554a731a24 Optimierung Phase 1: Aufraeumen / toter Code
1.1 Prototyp admin/users/table entfernt: Route (war durch admin/users/{id}
    ohnehin unerreichbar) + Volt-Komponente table.blade.php geloescht,
    ADMIN_ROUTES.md aktualisiert; Regressions-Test in PanelConsolidationTest.
1.2 16 tote Legacy-Wrapper-Views unter resources/views/admin/* geloescht
    (nutzten alte Route-Parameter, nirgends via view/@include/@livewire
    gerendert); admin.dashboard + .md-Doku behalten.
1.3 Tote Helfer entfernt: EnsureUserIsAdmin redundantes loadMissing('roles'),
    ungenutzter statusColor-Key aus with() in admin PR edit/show,
    LegacyInvoicePdfController Laufzeit-Schema::hasColumn (Spalte existiert
    seit Migration) inkl. Schema-Import.

Volle Suite gruen (794 passed, 1 skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 08:27:12 +00:00
c7bd940f28 Optimierung Phase 0: Korrektheit & Security
Konsolidierter Entwicklungsplan aus den zwei Analyse-Dokumenten plus
Umsetzung der Phase-0-Massnahmen (Korrektheit/Security, je mit Tests):

0.1 BasicAuth: timing-sicherer Vergleich (hash_equals, beide Felder ohne
    Short-Circuit); Enabled-Check zur Laufzeit via config('auth.basic.*')
    statt env() im Bootstrap-Closure (greift jetzt unter config:cache);
    Config-Block + .env.example. Fund: auth.basic.* war nie als Config
    definiert, Gate war faktisch unkonfigurierbar.
0.2 Legacy-Invoice-"latest"-Abfrage zentralisiert (LegacyInvoice::
    scopeLatestFirst + User::latestLegacyInvoice); beide Consumer N+1-frei
    umgestellt; unterschiedliches null-Verhalten bewusst erhalten.
0.3 Payment-Option-Eligibility vereinheitlicht (period-aware, strikt):
    UserPaymentOption::scopeActiveNow/grandfatheredNow + User::
    hasActivePaymentOption; hasActiveBooking/hasUnlimitedPressReleaseQuota
    und ApiAccessEligibilityService darauf umgestellt; $hasGrandfathered-
    Mislabel behoben.
0.4 Theme->Portal-Vokabular: totes, projektfremdes ThemeMiddleware
    geloescht; Mapping in Portal::fromTheme() zentralisiert; fremden
    b2in-Default im ThemeServiceProvider auf Portal-Default korrigiert.
0.5 InvoiceNumberGenerator: Erst-Insert race-sicher via insertOrIgnore
    (Unique-Index auf circle existiert bereits). CreditWalletService war
    bereits abgesichert (Unique-Index + createOrFirst).

Tests: 4 neue Dateien, 5 bestehende auf gueltiges grandfathered_until
angepasst. Volle Suite gruen (793 passed, 1 skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 08:09:02 +00:00
97d69a1a3a Migration: PM-Datum korrekt übernehmen, UUID stabil, Zwei-Phasen-Runbook
- published_at = Legacy-created_at (Publikationsdatum, Frontend-Sortier-
  schlüssel) statt updated_at, das bei Alt-Daten oft den Massen-/Migrations-
  stempel trägt und ein falsches "frisches" Datum erzeugte.
- created_at/updated_at per forceFill direkt im Import gesetzt (waren nicht
  fillable, wurden still verworfen) – Import allein ist jetzt datumssauber.
- legacy:fix-timestamps korrigiert zusätzlich published_at (status=published).
- PM-UUID bleibt beim Re-Import/Delta-Lauf erhalten (kein Neu-Würfeln).
- MIGRATION-STEPS auf Zwei-Phasen-Strategie umgestellt: migrate, Phase 1 mit
  --force, Phase 2 (Delta) ohne --force, Grandfather-Re-Run, Idempotenz-Tabelle.
- Tests: LegacyPressReleaseDateImportTest (published_at-Quelle, Entwurf,
  Force-Re-Import erhält UUID + Datum).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:32:48 +00:00
3a1d2e6751 Frontend: Editorial-Relaunch der öffentlichen Strecke + Ausgaben-Routing
Öffentliche Seiten auf gemeinsames Editorial-Design (x-web.site-header/-footer,
Design-Tokens) und Ausgaben-Präfix /{edition}/ (de|en) umgestellt.

- Routing: neue Middleware SetEdition (Locale + URL::defaults), /{edition}-Gruppe
  in routes/web.php, Root-Redirect auf /de, 301 für Legacy-.html-URLs,
  Baseline-Default in AppServiceProvider.
- Neue URL-Schemata: /{edition}/press-release/{slug}, /{edition}/category/{slug}.
- Ausgabe = Sprache: DE/EN-Umschalter (Region/CH/AT entfernt); EditorialClock
  und Livewire-Komponenten sprachdynamisch.
- Detail-, Kategorie- und Veröffentlichen-Seite mit echten Daten neu aufgebaut.
- Suche aktiviert: Volt-Komponente livewire/web/search (Titel/Text/Keywords +
  Firma + Rubrik, Filter, Sortierung, Pagination, URL-Parameter q/category/sort).
- Rubriken-Navigation statt Übersichtsseite: Helper CategoryNavigation;
  web/kategorien.blade.php + Route entfernt (Legacy-301).
- Tests: Edition-Routing, Kategorie-Seite/-Navigation, Detail, Veröffentlichen,
  Suche, EditorialClock. Doku in "Echte öffentliche Unterseiten.md" aktualisiert.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:39:28 +00:00
55d974f9e8 Doku: Sicherheits- & Deployment-Hinweise (Auth, Rollen, Verifizierung)
Dokumentiert die deployment-kritischen und sicherheitsrelevanten Punkte der
Auth-Phase: Reihenfolge der Migrationen (Verifizierungs-Backfill gegen Lockout,
Legacy-editor→customer-Downgrade), der Sicherheits-Fix der Editor-Über-
berechtigung (65.950 Legacy-User hatten Admin-Zugriff), die Firmen-Scope-
Verhaltensänderung bei PMs und der Magic-Link-Kontaktzugang. PROGRESS-Log-
Eintrag (16.06.) und README-Index ergänzt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 08:35:04 +00:00
234772be9f Doku-Abschluss 12.06.: README-Stand, weiteres/-Index, Next Steps (Phase-2/Magic-Link, Duplicate-Content)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 16:24:28 +00:00
ced39dd371 KI-generierte Bilder: eigener Lizenztyp, Anbieter-Bestätigung, Kennzeichnung
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 16:04:12 +00:00
a193097e7d Titelbild-Upload: Bildrechte in 5 Schritten + große Bildvorschau
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:34:40 +00:00
1f31e108d0 Verlinkung & Backlinks: systemseitige rel-Auszeichnung (Decision-Update 11.06.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:24:20 +00:00
ad75886929 PM-Vorschau: Workflow oben + farbig, Metadaten, saubere Inhalts-Typografie
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:16:52 +00:00
6ba260e2d6 Profil-Feinschliff: Pflicht-Badges, Fokus-Fix, Submit-Modal auf Switches
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:02:11 +00:00
d07b13810c User-Panel-Restarbeiten: PM-Guard, Profil-Rework, USt-ID-Prüfung, Buchungspflicht-Adresse
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:36:18 +00:00
b126254d53 Responsive-Härtung: Seiten-Header, Kontextleiste, Stat-Cards
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:08:08 +00:00
c5907dacda Admin-Zahlungsmodul: Zahlungs-Übersicht + Tarif-Verwaltung mit Stripe-Sync
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:54:53 +00:00
5555be4f4d Buchungs-Seite: Feinschliff nach Review
- Aktueller-Tarif-Card erscheint erst mit vorhandener Buchung; die
  Kontingent-Kachel zeigt nur noch echte Zahlen (kein irreführendes
  "Unbegrenzt" vor dem Launch-Schalter)
- Tarif-Cards plakativer: Icon je Tarif, größerer Preis, Trennlinie vor
  den Leistungen, mehr Abstand zum größeren Buchen-Button
- "Prüfung und Veröffentlichung inklusive" statt "KI-Prüfung"
- "Aktive Buchungen"-Panel entfernt (redundant zum Tarif-Panel);
  Verlauf als eigene, durch Trennlinie abgegrenzte Sektion
- Tests angepasst; Suite 519 passed / 4 skipped

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:30:06 +00:00
7818c57e35 Phase 9F: Tarif-Seite mit Stripe-Checkout und Billing Portal
- Buchungs-Seite zeigt das echte 4-Tier-Raster aus plans (Monat/Jahr-
  Toggle, Jahrespreis als "2 Monate gratis") mit Checkout-Buttons,
  Einzel-PM als separaten No-Abo-Block und Enterprise-Hinweis;
  Credit-Konzept-Mock entfernt (Credits folgen mit 9I bzw. Phase 2)
- Aktueller-Tarif-Panel real: Abo (Preis, Kontingent, Kündigungsstatus),
  Bestandstarif (unbegrenzt, nächste MAN-Rechnung), offene Einzelkäufe;
  Kontingent-Kachel zeigt "Unbegrenzt" bei Bestandsschutz
- "Abo verwalten" über das Stripe Billing Portal
  (me.checkout.billing-portal; Zahlungsmethode, Rechnungen, Kündigung)
- Aktive Buchungen + Verlauf aus echten Daten (Abo, Legacy-Vereinbarung,
  offene/eingelöste Einzelkäufe mit PM-Verknüpfung)
- Tests: BookingsPageTest (9 Tests), PanelConsolidationTest angepasst;
  Suite 519 passed / 4 skipped
- Doku: PHASE-9-Plan 9F ✅, Billing-Doku (Routen, Stripe Tax aktiviert),
  STATUS-ABGLEICH, Checkliste, PROGRESS

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 12:39:39 +00:00
ed99ee29fb Phase 9E (Abschluss): Checkout-Flows und Plan-Kontingent statt Quota-Stub
- Checkout-Backend: me.checkout.subscription (Tarif-Abo monatlich/jährlich)
  und me.checkout.single-pm (Einzel-PM 19 € netto, pending-Kauf mit
  Webhook-Erfüllung); StripeCheckoutService als mockbarer Stripe-Wrapper;
  Stripe Tax via Cashier::calculateTaxes() (Netto-Preise, USt-ID-Abfrage)
- Slot-Logik: Kontingent aus dem Tarif (plans.press_release_quota) plus
  bezahlte Einmalkäufe; Verbrauch bei Veröffentlichung zuerst aus dem
  Plan-Zähler, danach Einlösung des ältesten Einmalkaufs (consumed +
  PM-Verknüpfung); Grandfathered = unbegrenzt (Entscheidung 12.06.2026,
  Bestandsschutz); Stub-Spalte users.press_release_quota entfernt
- billing:sync-stripe-plans legt zusätzlich das Einzel-PM-Produkt an
  (STRIPE_PRICE_SINGLE_PM); Test-Mode-Sync gelaufen
- Buchungs-Seite: Rückmeldung nach Checkout (erfolg/abbruch/Guard-Hinweis)
- Tests: PressReleaseQuotaTest auf Plan-Semantik neu geschrieben,
  CheckoutFlowTest (8 Tests), Modal-/API-Tests angepasst; Suite 510 passed
- Doku: Billing-und-Rechnungskreise (Kontingent-Tabelle, Checkout-Routen,
  Webhook-Events, Stripe-CLI-Hinweis), PHASE-9-Plan 9E ✅, Checkliste,
  STATUS-ABGLEICH, PROGRESS

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 12:10:32 +00:00
a9dd565f6c Doku: zentrale Billing-Referenz und Status-Sync Phase 9D
- Neues Dokument docs/user-admin/Billing-und-Rechnungskreise.md:
  hybride Rechnungskreise (STR-/MAN-/Archiv), Tarif-Datenmodell,
  MAN-Faelligkeitslauf, USt-Regeln, Befehle/Scheduler, Konfiguration
  (billing.php + Cashier-ENV) und offene Punkte
- README-Index + STATUS-ABGLEICH (Finanzen-Sektion) aktualisiert
- PROGRESS-Eintrag Phase 9D (Datenmodell, Rechnungskreise,
  Grandfather-Migration, USt)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:02:45 +00:00
808d94f29f USt-Behandlung: Netto-Preise, VatResolver und Steuer-Ausweis im MAN-Kreis
Einwand/Entscheidung 12.06.2026: Legacy fakturierte brutto (Steuer
inkludiert, z. B. 199 Euro; steuerbefreite Kunden mit Netto-Ausweis
167,23). Alle neuen Preise sind netto; die Steuer wird zur
Rechnungsstellung sauber validiert und ausgewiesen.

- VatResolver + VatTreatment: DE grundsaetzlich immer mit Steuer, EU nur
  mit (formal plausibler) USt-ID befreit (Reverse Charge inkl.
  Pflichthinweis), Drittlaender grundsaetzlich befreit;
  EU-Laenderliste + vat_rate in config/billing.php
- Schema: billing_addresses.vat_id + invoice_billing_addresses.vat_id
  (Snapshot pro Rechnung), invoices.tax_note; Profil-Formular schreibt
  die vorhandene USt-ID jetzt auch an die Rechnungsadresse
- ManualInvoiceService: rechnet auf Netto-Vertragsbasis
  (legacy_conditions.net_cents bzw. Netto-Katalogpreis) und bestimmt
  Steuer/is_netto/tax_note pro Rechnung ueber den VatResolver
- legacy:grandfather-subscriptions: leitet net_cents aus der letzten
  Legacy-Rechnung ab (brutto / 1,19 bzw. is_netto-Betrag direkt);
  fuer DE-Bestandskunden bleibt der Bruttobetrag unveraendert
  (199 brutto -> 167,23 netto + 31,77 USt = 199,00)
- Doku: Decision-Update 2.1 (Netto-Klarstellung), Phase-9-Plan,
  Checkliste, 05-DATABASE-MERGE 5.6; offen: VIES-Validierung der USt-ID

Tests: VatResolverTest (Datasets fuer alle Faelle), Reverse-Charge/
EU-/Drittland-Rechnungen, Netto-Ableitung; Suite 490 passed, 4 skipped.
Pint clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:58:43 +00:00
9f610f42d9 P6.6: legacy:grandfather-subscriptions — aktive Legacy-Abos aus dem Rechnungsarchiv migrieren
Kriterien vom Auftraggeber (12.06.2026): Quelle der Aktiv-Erkennung ist
ausschliesslich das read-only Rechnungsarchiv legacy_invoices (D-12).
Legacy-Rechnungen bleiben Archiv; neue manuelle Rechnungen entstehen im
MAN-Rechnungskreis.

- Aktiv-Regel: juengste Rechnung pro (Portal, Legacy-Vereinbarung) mit
  payment_option.type=recurring und user_payment_option.status=active;
  next_due_date max. --grace-months (Default 12) ueberfaellig, sonst
  stale -> bleibt reines Archiv. Einmal-Kaeufe werden nie uebernommen.
- Uebernahme als grandfathered in user_payment_options:
  current_period_end = next_due_date, Betraege/Intervall der letzten
  Legacy-Rechnung in legacy_conditions -> der taegliche MAN-Lauf
  (billing:generate-manual-invoices) fakturiert zum gewohnten
  jaehrlichen Rhythmus weiter. Versteckte Katalog-Platzhalter
  LEGACY-{PE|BP}-{Artikel} in payment_options.
- Replay-faehig (D-18): Re-Runs aktualisieren anhand der Legacy-IDs in
  legacy_conditions statt zu duplizieren — die Kern-Migration laeuft
  kurz vor dem Relaunch erneut.
- Optionen: --dry-run, --as-of, --grace-months, --no-report; JSON-Report
  nach storage/app/migration/. Dry-Run gegen Test-Snapshot: 22 aktive
  jaehrliche Vereinbarungen, davon 4 sofort faellig, 0 stale.
- Doku: MIGRATION-STEPS.md (Runbook-Reihenfolge nach archive-invoices),
  05-DATABASE-MERGE §5.6, 12-NAECHSTE-SCHRITTE 6.6, 08-PROGRESS,
  PHASE-9-Plan + Checkliste.

Tests: GrandfatherLegacySubscriptionsTest (7, inkl. End-to-End
Migration -> MAN-Rechnung mit Legacy-Betraegen). Suite: 475 passed,
4 skipped. Pint clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:35:48 +00:00
6b0ca3f2e0 Phase 9 Block 1: Gelb-Routing Direkt-Live, Slot-Verbrauch bei Veroeffentlichung, Submit-Gate
9A — Gelb geht direkt live (Entscheidung 12.06.2026):
- routeByClassification(): Gelb durchlaeuft denselben Auto-Publish-Pfad
  wie Gruen (autoPublishApproved); nur Rot wird abgelehnt
- Scheduler publiziert faellige gelbe + gruene PMs; unklassifizierte
  bleiben als Fallback in der manuellen Queue

9B — Slot-Verbrauch bei Veroeffentlichung (Decision-Update 3.2):
- Increment aus submitForReview() entfernt; publish() und
  changeStatusFromAdmin() zaehlen idempotent beim ersten
  published-Uebergang (Pruefung ueber Status-Logs); Rot kostet nichts
- Submit-Guard: Einreichen erfordert freien Slot
  (QuotaExceededException, API 422)

9C — Submit-Gate vorbereitet (Decision-Update 5.1):
- User::hasActiveBooking()-Stub hinter config/billing.php
  (enforce_booking, Default aus); Tarif-Modul ersetzt nur den Rumpf
- Einreichungs-Modal zeigt ohne Buchung einen Buchungs-Hinweis;
  Server-Guard (BookingRequiredException), API antwortet 402
- Fix: Customer-Create legte PMs bei "Zur Pruefung senden" direkt mit
  Status review an (vorbei an Blacklist/Quota/KI/Status-Log) — laeuft
  jetzt immer ueber submitForReview()

Suite: 451 passed, 4 skipped (9 neue Tests). Pint clean.
Plan: docs/PHASE-9-FLOW-UND-TARIFE-PLAN.md (Block 2 nach Review-Stopp).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:47:06 +00:00
b2b5ff06c2 Doku: Status-Sync 11./12.06., Decision-Update Preisstruktur und Phase-9-Plan
- Decision-Update Preisstruktur & Veroeffentlichungs-Flow aufgenommen
  (Launch-Tarife, Slot-Verbrauch bei Veroeffentlichung, Submit-Gate,
  Launch-Credits) inkl. Klarstellung 12.06.: Gelb geht direkt live,
  keine manuelle Pruef-Queue, nur Rot wird abgelehnt
- Alle Status-Dokumente auf den Code-Stand gezogen: README-Index,
  STATUS-ABGLEICH (KI-Pipeline, Bilder/Lizenzen, Pricing), Checkliste
  (KI- und Titelbild-Bloecke, Launch-To-dos), Admin-User,
  user-zusammenhaenge (Datenmodell-Delta), Entwicklungsplan KI-Pruefung
  (Phase 0 abgehakt, Decision-Abgleich)
- Ueberschriebene Tarif-Abschnitte in Konzept-Update 1/2 und
  Relaunch-Konzept mit Superseded-/IST-Hinweisen markiert
- Neues Plan-Dokument PHASE-9-FLOW-UND-TARIFE-PLAN.md (9A-9J)
- Phase-8-Roadmap-Doku (20-PHASE-8-USER-PANEL.md) + PROGRESS-Eintraege

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:20:22 +00:00
a8d12283bf 29-05-2026 Optimierungen Fixes am Code 2026-05-29 12:42:05 +00:00
fd1f6bd401 22-05-2026 Optimierung der User und Admin Panels 2026-05-22 11:18:59 +02:00
36c6499770 create PM v0.5 2026-05-20 19:14:39 +02:00
9844b41535 Rebrand Hub+Flux 2026-05-20 15:44:15 +02:00