presseportale/dev/migration 2026/00-OVERVIEW.md
Kevin Adametz 0a3e52d603 19-05-2026 Rebrand Pressekonto, Hub-Flux UI und Legacy-Media-Migration
Umbenennung presseportale → pressekonto in Domains, Themes und Dokumentation.
Design-Tokens, Portal-Shell, Customer-Dashboard, Auth- und Admin-PM-Views.
Artisan-Befehl migrate:legacy-media mit Tests und Hub-Flux-Entwicklungsdocs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 16:36:13 +00:00

163 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 00 Overview
## 1. Ausgangslage
### 1.1 Zwei Legacy-Portale (technisch identisch, organisatorisch getrennt)
| Eigenschaft | `presseecho` | `businessportal24` |
|---|---|---|
| Technologie | Symfony 1.4, Doctrine 1.2, PHP 5.6 | Symfony 1.4, Doctrine 1.2, PHP 5.6 |
| Server | Server A | Server B |
| Datenbank | `db_presseecho` (MySQL) | `db_businessportal` (MySQL) |
| Frontend-Domain | presseecho.de | businessportal24.com |
| Code-Base | identisch (nur `app.yml` + Templates abweichend) | identisch |
Code-Referenz im Repo: `/_businessportal24.com/` (exemplarisch; `presseecho` ist inhaltsgleich).
### 1.2 Neue Frontends (bereits in diesem Repo)
- `resources/views/web/` Landingpages für `presseecho.test` und `businessportal24.test`
- Domain-basiertes Theme-System (`config/domains.php` + `ThemeServiceProvider`)
- Zwei Tailwind-/Vite-Configs (Portal vs. Web)
Diese Frontends sollen künftig **gegen das neue Backend arbeiten** via direkter DB-Lesezugriffe (same-DB) oder API.
### 1.3 Neues Backend (Aufgabe dieses Projekts)
- Läuft unter `pressekonto.test` / `pressekonto.de`
- Stack: **Laravel 12, PHP 8.4, Livewire 4, Volt, Flux UI 2, MySQL 8, Tailwind 4**
- **Vorarbeiten bereits vorhanden**: Admin-UI-Gerüst, Routes, Auth-Stack
- **Noch zu tun**: Eloquent-Models, Migrations, Services, Daten-Migration, API, Payment (Stripe), Cron-Jobs
---
## 2. Ziele der Migration
### 2.1 Fachliche Ziele
1. **Ein Backend für beide Portale** Schluss mit dupliziertem Code und doppeltem Betrieb.
2. **Ein Datenbestand** beide Legacy-DBs in eine Ziel-DB konsolidiert, disambiguiert durch `portal` (`presseecho` | `businessportal24`).
3. **Moderne Admin-UX** Livewire + Flux UI statt generierter Symfony-Admin-Tabellen.
4. **Saubere REST-API** mit Sanctum-Auth und Laravel-API-Resources. Harter Cut-over auf Sanctum PATs ohne Legacy-Key-Kompatibilität; Legacy-Keys liefern 410 mit Migrationshinweis.
5. **Automatisierbarer Betrieb** Laravel Scheduler + Queues statt Bash-Scripts.
### 2.2 Nicht-Ziele
- Kein Umbau der neuen Frontends (`presseecho.test`, `businessportal24.test`) die laufen bereits.
- Kein 1:1-Port der alten Backend-Symfony-Templates wir bauen das Admin neu (UI-Gerüst steht schon).
- **Keine Migration der Legacy-Payments/Invoices** als operative Daten nur Archiv.
- **Keine Übernahme alter API-Keys** Cut-over auf Sanctum-Tokens.
- **Keine Übernahme alter Passwörter** User werden zum Reset aufgefordert.
- **Keine Promotion-Links** (Legacy-Feature entfällt).
- Keine Übernahme von PayPal Express, SPK-Berlin, Cortal Consors, Post/Bar, Rechnungszahlung **einzig Stripe**.
- Kein CMS-Modul für redaktionelle Seiten (`page`-Modul im Legacy) wird über Blade-Views im Frontend abgebildet.
---
## 3. Erfolgskriterien
| Kriterium | Messbar an |
|---|---|
| Backend unter `pressekonto.test` erreichbar | HTTP 200 auf Login-Seite |
| Admin-Login (Fortify + 2FA) funktioniert | Feature-Test `AuthTest` |
| Customer-Portal via Magic-Link erreichbar | Feature-Test `MagicLinkLoginTest` |
| Pressemitteilungen CRUD (Admin + Customer) | Livewire-Tests `PressReleaseIndex/Create/Edit/Show` |
| Firmen & Kontakte CRUD | Livewire-Tests |
| Sauberes Migrations-Skript (wiederholbar) | `artisan legacy:import` idempotent, läuft gegen die konfigurierten Legacy-DB-Verbindungen |
| Daten beider Portale importiert | `portal`-Verteilung plausibel, Counts Delta ≤ 1 % |
| Rechnungslauf (neu, Stripe) | Stripe-Webhook-Tests, `invoices:generate` Command |
| Legacy-Rechnungen im Archiv einsehbar | `legacy_invoices`-Table vollständig importiert; PDF wird bei Abruf aus Legacy-Daten generiert |
| API v1 mit Sanctum | API-Feature-Tests |
| Coverage ≥ 70 % auf Domain-Code | `./vendor/bin/pest --coverage` |
---
## 4. Phasen (High-Level)
Ausführlicher Plan in [`03-MIGRATION-PLAN.md`](./03-MIGRATION-PLAN.md).
| Phase | Titel | Ergebnis |
|---|---|---|
| P1 | Fundament | DB-Schema (Migrations), Models, Factories, Seeders, Config (countries/salutations) |
| P2 | Auth & Tenancy | Fortify-Profile, **Magic-Link Auth**, Rollen/Rechte (Spatie), `portal`-Scope auf Models |
| P3 | Admin-UI füllen | Volt-Komponenten an echte Models/Services anbinden (UI existiert) |
| P4 | **Customer-Portal** | Self-Service für Companies (PM erstellen, Rechnungen, Tokens, Profil) |
| P5 | Services & Domain-Logic | PressRelease-, Company-, Newsletter-Services; Slugging; Blacklist-Check |
| P6 | **Daten-Migration** ⭐ | Import-Commands aus beiden Legacy-DBs (**wiederholbar**), Bilder-Transfer, Legacy-Invoice-Archiv |
| P7 | API v1 | Sanctum, API-Resources, **Cut-over** (keine Legacy-Key-Kompatibilität) |
| P8 | Payment & Invoicing (Stripe, **neu**) | Neue Produkte, Checkout, Webhooks, PDF, Mahnwesen, Grandfathering |
| P9 | Scheduler & Queues | Laravel Scheduler + Queues |
| P10 | Testing & Härtung | Pest-Tests, Pint, statische Analyse |
| P11 | Deployment | Staging, Produktiv-Import-Rehearsal, DNS-Cutover, Produktivstart |
---
## 5. Entscheidungen (ehemals offene Fragen, 2026-04-23 geklärt)
| ID | Thema | Entscheidung |
|---|---|---|
| **Q-01** | Produktiv-DB-Dumps beider Legacy-Systeme | ✅ **Liegen vor** unter `dev/migration 2026/sql/` (`businessportal24_2026-04-23.sql` 578 MB, `presseecho_2026-04-23.sql` 369 MB). **Wichtig:** Die Migration muss als *sauberes, wiederholbares Skript* gebaut werden, sodass am Go-Live-Tag der **aktuelle Produktivstand** beider DBs in die neue Live-DB überführt werden kann. Auf dem Test-Server stehen Dumps **und direkter Read-Only-Zugriff** auf die Legacy-DBs zur Verfügung. |
| **Q-02** | Alte User-Passwörter | ❌ **Werden NICHT übernommen.** Beim Go-Live geht eine E-Mail an alle User mit Sicherheitshinweis und Passwort-Reset-Link. **Zusätzlich** wird ein **„Login per E-Mail-Link" (Magic Link / Einmal-Passwort)** eingebaut insbesondere für Companies, die aktuell gar keinen Login haben, aber über die API Pressemitteilungen veröffentlichen. Über diese E-Mail können sie künftig auch auf ihre Pressemappe, Pressemitteilungen, Rechnungen und API-Tokens zugreifen. |
| **Q-03** | Legacy-API-Keys | ❌ **Werden NICHT übernommen.** Neue Token-Technik (Sanctum PATs). Tokens sind pro User im Backend abrufbar und verwaltbar. Alte API-Clients müssen einmalig auf den neuen Token umgestellt werden. |
| **Q-04a** | Alte Rechnungen (PDFs) | ✅ **Kommen ins Archiv** nur lesbare Ansicht, kein aktiver Workflow. Separate `legacy_invoices`-Tabelle mit vollständigem DB-Import inkl. Status/User-Zuordnung; PDF wird für Legacy-Rechnungen bei Abruf aus diesen Daten generiert, nicht als neuer Stripe-Rechnungslauf. |
| **Q-04b** | Rechnungslauf | ✅ **Komplett neu entwickelt.** Keine Rechnungs-Zahlungsweise mehr. **Einzige Zahlungsart: Stripe.** |
| **Q-04c** | PaymentOptions | ✅ **Neue Produkte**, direkt über Stripe bezahlt. **Grandfathering:** Aktive User behalten ihre alten Konditionen bis Laufzeit-Ende, werden dann auf neue Produkte migriert. |
| **Q-05** | Media/Bilder | ✅ **Lokal** (Storage-Disk `public`, später `s3`). Funktionen werden **erweitert**: Pressemitteilungen dürfen künftig mehrere/größere Bilder enthalten, Companies bekommen ordentliche Logo-Varianten (Legacy war sehr minimalistisch). |
| **Q-06** | Pflicht-Datenfelder neu | ✅ `deleted_at` **überall** (Soft-Deletes). `portal`-Spalte auf allen mandantenfähigen Entitäten. Weitere sinnvolle Erweiterungen pro Entität: `uuid` (öffentliche Links), `gdpr_consent_at`, `last_seen_at` (User), `published_at` (PressRelease). |
| **Q-07** | Mehrsprachigkeit | ✅ **Deutsch + Englisch** werden direkt initialisiert (Admin-UI DE, Content zweisprachig DE/EN). |
| **Q-08a** | Promotion Links | ❌ **RAUS.** |
| **Q-08b** | Footer Code | ✅ Bleibt (deaktivierbar pro Company). |
| **Q-08c** | Newsletter | 🔁 **Neu aufgebaut**, nicht migriert. Nur die bestehenden Subscriber-Daten werden importiert. |
| **Q-08d** | **Kundenbereich / Customer-Portal** | ✅ **WICHTIG** (erweitert den Scope): Das Backend ist **NICHT nur Admin**. Drei Nutzer-Bereiche:<br>**Admin** interne Mitarbeiter, volle Verwaltung<br>**Customer** Company-User, eingeloggt *oder* via Magic-Link. Eigene Pressemitteilungen erstellen/bearbeiten, Rechnungen einsehen, API-Tokens verwalten, Company-/Contact-Daten pflegen<br>**API-Only** reine Token-Nutzung für automatisiertes Publishing |
| **Q-09** | Coupons | ⏸️ **Vertagt.** Kein Model/Feld in Phase 1. Kommt später separat dazu. |
| **Q-10** | Agency vs. Company | ✅ **Unterscheidung bleibt** (per `type`-Enum auf `companies`, kein Table-Inheritance). |
**Kernaussage:** Fokus dieser Migration liegt auf **Pressemitteilungen + Companies + Contacts** aus beiden Portalen sauber in eine neue DB zu überführen. **Zahlungen, Abwicklungen und Newsletter werden neu entwickelt** (nicht migriert). Das Backend dient **Admin-UND-Kunden** (Customer-Portal mit Magic-Link).
---
## 6. Stack-Vergleich
| Domäne | Legacy | Ziel |
|---|---|---|
| Framework | Symfony 1.4 | Laravel 12 |
| ORM | Doctrine 1.2 (YAML-Schema) | Eloquent |
| PHP | 5.6 | 8.4 |
| Auth | sfDoctrineGuardPlugin (sha1 + salt) | Fortify + bcrypt + **Magic-Link** |
| API-Auth | statischer `api_key`-String | **Sanctum PAT** (Cut-over, keine Legacy-Kompatibilität) |
| Rollen | `sfGuardGroup` / `sfGuardPermission` | Spatie/Permission |
| Admin-UI | Generator (auto-admin) | Livewire Volt + Flux UI |
| Forms | sfForm / sfFormDoctrine | Livewire + FormRequest + Flux |
| i18n | Doctrine `I18n` behavior | Spatie/Laravel-Translatable oder `*_translations`-Tabelle |
| Slugs | Doctrine `Sluggable` | `spatie/laravel-sluggable` |
| Images | `sfImageTransformPlugin` | `intervention/image` + Image Driver GD/Imagick |
| PDF | TCPDF (via sfpInvoicePdf) | `barryvdh/laravel-dompdf` |
| Cron | Bash-Scripts + Symfony-Tasks | Laravel Scheduler + Jobs/Queues |
| Mail | Swift Mailer | Laravel Mail (symfony/mailer) |
| Templates | PHP `.php` | Blade |
| Testing | kaum | Pest 3 |
| Assets | symlinks in `web/` | Vite 5 (Portal + Web getrennt) |
---
## 7. Risikopunkte
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|---|---|---|---|
| Inkonsistente Daten zwischen beiden Legacy-DBs (gleiche IDs, unterschiedliche Inhalte) | hoch | hoch | Import mit ID-Offset/Re-Mapping; `legacy_id` + `portal` als Unique-Key |
| Abhängigkeiten zwischen Frontends (presseecho.test) und neuem DB-Schema | mittel | hoch | Eloquent-Models können beide Frontends bedienen; Übergangsweise read-only Views |
| Differenz zwischen Test-Dump und Produktiv-Stand am Go-Live-Tag | hoch | hoch | **Wiederholbares Import-Skript**; Delta-Modus; Rehearsal-Import am Staging 1 Tag vor Cutover |
| API-Clients brechen nach Token-Umstellung | hoch | hoch | Frühe Kommunikation an alle API-User; Tokens im Backend self-service abrufbar; Übergangs-Banner |
| User können sich nicht einloggen (weil alte PW weg) | mittel | mittel | Magic-Link + Reset-Mail-Kampagne + gut sichtbare Hilfe |
| Grandfather-Abos falsch abgerechnet | mittel | hoch | Explizite `grandfathered_until`-Spalte, Tests, manuelle Liste |
| Bilder-Pfade ändern (Slug-basierte Thumbnails) | hoch | mittel | Redirect-Rules für alte `/thumbnails/...`-URLs; Import + URL-Map |
---
## 8. Nächste Schritte (konkret)
1. ✅ Entscheidungen geklärt (siehe §5, Stand 2026-04-23)
2. ✅ DB-Dumps liegen in `dev/migration 2026/sql/`
3. **Aktuell:** Phase 1 starten Migrations, Models, Factories, Seeders (siehe [`03-MIGRATION-PLAN.md`](./03-MIGRATION-PLAN.md))
4. Parallel: Staging-DB-Verbindung zu Legacy-Systemen konfigurieren (Read-Only)
5. Phase 2: Magic-Link Auth + Customer-Bereich skizzieren