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>
163 lines
11 KiB
Markdown
163 lines
11 KiB
Markdown
# 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
|