244 lines
11 KiB
Markdown
244 lines
11 KiB
Markdown
# 06 – Feature-Scope (IN / OUT / ANGEPASST)
|
||
|
||
Diese Matrix ist die **fachliche Scope-Grundlage**. **Stand: 2026-04-23 – Entscheidungen vom Auftraggeber bestätigt.**
|
||
|
||
Legende: **IN** = wird migriert · **NEU** = wird neu gebaut (nicht aus Legacy portiert) · **OUT** = entfällt · **ANGEPASST** = kommt rein, aber in veränderter Form · **ARCHIV** = nur lesbar für Nachschau.
|
||
|
||
---
|
||
|
||
## 1. Authentifizierung
|
||
|
||
| Feature | Legacy | Scope | Anmerkung |
|
||
|---|---|---|---|
|
||
| Login/Logout | ✓ | **IN** | Fortify |
|
||
| Registrierung (neue User) | ✓ | **IN** | Fortify-View anpassen; User-Typ bei Anmeldung wählen |
|
||
| Passwort zurücksetzen | ✓ | **IN** | Fortify |
|
||
| E-Mail-Verifizierung | ✓ | **IN** | Fortify |
|
||
| 2FA (TOTP) | – | **IN** (neu) | Fortify 2FA-Spalten liegen bereits in `users` |
|
||
| Remember-me | ✓ | **IN** | Laravel Standard |
|
||
| **Magic-Link Login** (Login per E-Mail-Link) | – | **NEU** ⭐ | Für Companies ohne Passwort + als Alternative für alle; kurzlebige signed URLs |
|
||
| Legacy-Passwort-Hashes weiter gültig | sha1 | **OUT** | Go-Live-Mailing mit Reset-Link + Sicherheitshinweis |
|
||
| Legacy-API-Key-Kompatibilität | ✓ | **OUT** | Sauberer Cut-over auf Sanctum; Kunden werden über neue Tokens informiert |
|
||
| Captcha beim Login | sfCaptchaGDPlugin | **OUT** | Ersetzt durch Rate-Limiting + Honeypot |
|
||
|
||
---
|
||
|
||
## 2. Benutzer / Profile
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| User-CRUD im Admin | ✓ | **IN** |
|
||
| User-Rollen (Groups) | sfGuardGroup | **IN** (Spatie): `admin`, `editor`, `customer`, `api-only` |
|
||
| User-Permissions | sfGuardPermission | **IN** (Spatie) |
|
||
| User-Profile (Adresse, Tel, Tax-ID …) | ✓ | **IN** |
|
||
| Sanctum-Tokens verwalten (Self-Service) | – | **NEU** | Customer verwaltet eigene Tokens unter `/account/tokens` |
|
||
| User-Profile `backlink_url` | ✓ | **IN** |
|
||
| User-Profile `show_stats` | ✓ | **IN** |
|
||
| User-Profile `disable_footer_code` | ✓ | **IN** | Footer-Code bleibt Feature |
|
||
| User-Profile `contract_date` | ✓ | **IN** |
|
||
| ApiUser als eigener Typ | ✓ | **ANGEPASST** | Als Rolle `api-only` (Spatie), keine eigene Tabelle |
|
||
|
||
---
|
||
|
||
## 3. Firmen & Kontakte
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| Company-CRUD | ✓ | **IN** |
|
||
| Agency als Subtyp | Inheritance | **IN** | Als `type`-Enum auf `companies` (entschieden in D-17/Q-10) |
|
||
| Mehrere verantwortliche User pro Company | `ResponsibleCompanyUser` | **IN** | Pivot mit `role` |
|
||
| Company-Login (eigenes Passwort) | ✓ | **OUT** | Stattdessen: User-Zugang pro Ansprechpartner; Company-E-Mail bekommt Magic-Link |
|
||
| **Company-Logo-Upload (verbessert)** | ✓ (minimal) | **ANGEPASST** ⭐ | Mehrere Varianten (sq / wide / darkmode), größere Auflösung, Drag-&-Drop |
|
||
| Footer-Code deaktivieren pro Company | ✓ | **IN** |
|
||
| Contact-CRUD | ✓ | **IN** |
|
||
| Contact-Autocomplete in PM-Formular | ✓ | **IN** |
|
||
|
||
---
|
||
|
||
## 4. Pressemitteilungen
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| CRUD (Admin) | ✓ | **IN** |
|
||
| **CRUD (Customer-Self-Service)** | ✓ | **IN** ⭐ | Customer-Portal: eigene PMs erstellen/bearbeiten |
|
||
| Multi-Kategorie? | Nein (1 Kategorie) | **IN** (1:1, N:M optional später) |
|
||
| Slugging per Titel+Sprache | ✓ | **IN** |
|
||
| Teaser-Range `teaser_begin`/`teaser_end` | ✓ | **IN** |
|
||
| Status (`draft`, `published`, `rejected`, `archived`) | lose Strings | **IN** | Enum |
|
||
| Publish/Reject-Workflow | ✓ | **IN** | Actions + Events |
|
||
| Automatische Blacklist-Prüfung | ✓ | **IN** |
|
||
| **Image-Upload mehrere pro PM (verbessert)** | ✓ | **ANGEPASST** ⭐ | Mehrere Bilder, größere Auflösungen, Varianten; Legacy war sehr minimalistisch |
|
||
| Preview-Bild | ✓ | **IN** |
|
||
| Hits-Zähler | ✓ | **IN** | Atomar `increment` |
|
||
| `no_export`-Flag | ✓ | **IN** |
|
||
| `portal`-Spalte (portal_type) | – | **IN** ⭐ | Pflichtfeld für Portal-Zuordnung (presseecho / businessportal24) |
|
||
| SEO-Felder (Meta Title, Description) | teilw. | **ANGEPASST** | Explizite SEO-Spalten |
|
||
| Kontakte zu PMs zuordnen | ✓ | **IN** |
|
||
| **Öffentlicher Magic-Link zum Teilen / Vorschau** | – | **NEU** | UUID-basierter Share-Link für noch unveröffentlichte PMs |
|
||
|
||
---
|
||
|
||
## 5. Kategorien
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| CRUD mit Slug | ✓ | **IN** |
|
||
| Mehrsprachigkeit (DE + EN) | ✓ | **IN** | `category_translations`, DE + EN direkt initialisiert |
|
||
| Hierarchie (Parent/Child) | ✗ | **IN** (neu, optional) | `parent_id` vorgesehen |
|
||
| Footer-Code pro Kategorie | ✓ | **IN** |
|
||
|
||
---
|
||
|
||
## 6. Newsletter
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| Subscribe mit Double-Opt-In | ✓ | **NEU** | Komplett neu gebaut |
|
||
| Unsubscribe-Link | ✓ | **NEU** |
|
||
| Admin: Subscriber-Liste | ✓ | **NEU** |
|
||
| Admin: Kampagnen (manuell versenden) | ✗ | **NEU** |
|
||
| CSV-Export / -Import | ✗ | **NEU** |
|
||
| Bestandssubscriber (aus Legacy) | ✓ | **IN** (Datenimport) | Nur Subscriber-Daten werden übernommen, kein Workflow-Code |
|
||
|
||
---
|
||
|
||
## 7. Billing / Payment / Invoicing
|
||
|
||
**Großer Umbau** (D-03, D-12, D-13): Komplett neuer Billing-Lauf, nur Stripe, alte Rechnungen → Archiv.
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| **PaymentOption-Verwaltung (neu definiert)** | ✓ | **NEU** | Neue Produkte, Stripe Prices als Quelle |
|
||
| **Grandfathering** (aktive Alt-User behalten Konditionen) | – | **NEU** ⭐ | `grandfathered_until`-Feld, automatische Migration auf neue Produkte bei Ablauf |
|
||
| Recurring via Stripe Subscription | – | **NEU** | Stripe Subscriptions |
|
||
| Onetime / Single-Purchase | ✓ | **NEU** | Stripe Checkout |
|
||
| Coupons | ✓ | **OUT** (vertagt, D-16) | Kein Model in Phase 1; evtl. Stripe-Coupons später. Aktuelle Coupon-Routen/Views gelten nur als UI-Skeleton ohne Priorisierung in P1. |
|
||
| Mehrfach-Buchung pro Company | ✓ | **IN** (neu modelliert) |
|
||
| Zahlungsart: SPK Berlin / Cortal Consors / Bar / Post / PayPal | ✓ | **OUT** |
|
||
| **Zahlungsart: Rechnung** | ✓ | **OUT** ⭐ | Entfällt komplett, nur noch Stripe |
|
||
| Zahlungsart: Stripe (Karte, SEPA, Klarna optional) | ✗ | **NEU** |
|
||
| Invoice-Generation (neu) | ✓ | **NEU** | Trigger: erfolgreicher Stripe-Charge oder periodische Subscription-Invoices |
|
||
| Invoice-PDF | ✓ (TCPDF) | **ANGEPASST** | DomPDF |
|
||
| Mahnwesen | ✓ (3 Stufen) | **NEU** | Vereinfacht, da nur noch Stripe-Zahlungsausfälle abzufangen sind |
|
||
| Abweichende Rechnungs-Adresse | ✓ | **IN** |
|
||
| Tax-Exempt / Reverse-Charge | ✓ | **IN** |
|
||
| VAT-Berechnung | ✓ | **IN** (aktuelle Sätze) |
|
||
| **Legacy-Rechnungen (PDFs)** | ✓ | **ARCHIV** ⭐ | Separate Tabelle `legacy_invoices` mit vollständigem DB-Import inkl. Status/User-Zuordnung; PDF wird read-only bei Abruf aus Legacy-Daten generiert |
|
||
|
||
---
|
||
|
||
## 8. REST-API
|
||
|
||
Details: [`07-API-MIGRATION.md`](./07-API-MIGRATION.md)
|
||
|
||
| Endpoint | Legacy | Scope |
|
||
|---|---|---|
|
||
| POST Pressrelease | ✓ | **IN** (neu implementiert, Sanctum-Auth) |
|
||
| GET Pressrelease-List | ✓ | **IN** |
|
||
| GET/PATCH Pressrelease | ✓ | **IN** |
|
||
| POST Image-Upload | ✓ | **IN** |
|
||
| GET Companies | ✓ | **IN** |
|
||
| GET Categories | ✓ | **IN** |
|
||
| POST Newsletter subscribe | ✓ | **IN** |
|
||
| **Auth: Legacy `api_key`-Query-Param** | ✓ | **OUT** ⭐ | Sanctum-Bearer-Token only; Kunden-Migration per E-Mail |
|
||
| (alles andere Undokumentierte) | ? | ❓ | Legacy-Log analysieren |
|
||
|
||
---
|
||
|
||
## 9. Marketing / Redaktion
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| **Promotion-Links** | ✓ | **OUT** ⭐ | Entfällt komplett (D-14) |
|
||
| Footer-Code pro Kategorie/Sprache | ✓ | **IN** |
|
||
| „page"-Modul (statische Seiten) | ✓ | **OUT** | Static Pages im Frontend-Repo als Blade |
|
||
|
||
---
|
||
|
||
## 10. Cron / Scheduler
|
||
|
||
| Job | Legacy | Scope |
|
||
|---|---|---|
|
||
| `sfp:user-payment-create` | ✓ | **OUT** | Abgelöst durch Stripe Subscriptions |
|
||
| `sfp:invoice-create` | ✓ | **NEU** | Stripe-Webhook-getrieben statt Cron |
|
||
| `sfp:invoice-reminder` | ✓ | **NEU** | Laravel-Scheduler-Job für unbezahlte Stripe-Invoices |
|
||
| `sfp:user-paymentoption-expire` | deaktiviert | **NEU** | Grandfather-Ablauf-Handler |
|
||
| **Magic-Link-Cleanup** | – | **NEU** | Expired tokens löschen |
|
||
| Newsletter-Versand-Queue | – | **NEU** |
|
||
| Log-Rotation / Prune Failed Jobs | – | **NEU** |
|
||
|
||
---
|
||
|
||
## 11. Bilder / Media
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| Thumbnail-Generierung | sfImageTransformPlugin | **ANGEPASST** | Intervention Image, on-upload |
|
||
| Varianten (thumb_200, thumb_500, etc.) | ✓ | **IN** |
|
||
| Storage lokal | ✓ | **IN** (Dev + Prod initial) |
|
||
| Storage S3-kompatibel | ✗ | **IN** (optional später) |
|
||
| Alte Image-URLs (`/thumbnails/...`) | ✓ | **ANGEPASST** | Redirect-Middleware |
|
||
| **Company-Logo größer & mehrere Varianten** | ✓ (minimal) | **NEU** ⭐ |
|
||
| **Press-Release mehrere Bilder** | teils | **NEU** ⭐ |
|
||
|
||
---
|
||
|
||
## 12. Kundenbereich / Customer-Portal ⭐ NEU AUFGEWERTET
|
||
|
||
**Entscheidung D-11:** Das Backend ist **nicht nur Admin-UI**, sondern bedient auch Endkunden.
|
||
|
||
| Feature | Scope | Anmerkung |
|
||
|---|---|---|
|
||
| Customer-Login (Passwort oder Magic-Link) | **NEU** | Eigene Route-Gruppe `customer.*` |
|
||
| Eigenes Dashboard (Übersicht aktive Abos, letzte PMs, Rechnungen) | **NEU** |
|
||
| Eigene Pressemitteilungen: Liste / Erstellen / Bearbeiten | **NEU** |
|
||
| Eigene Rechnungen einsehen + PDF | **NEU** | Inkl. Legacy-Archivrechnungen |
|
||
| API-Tokens verwalten (Sanctum-PATs) | **NEU** |
|
||
| Company-/Contact-Profile pflegen | **NEU** |
|
||
| Zwei-Faktor-Auth aktivieren | **NEU** |
|
||
| Passwort ändern / Mail ändern | **NEU** |
|
||
|
||
---
|
||
|
||
## 13. Frontend-Integration
|
||
|
||
| Feature | Legacy | Scope |
|
||
|---|---|---|
|
||
| Altes Symfony-Frontend (presseecho/businessportal24.com) | ✓ | **OUT** |
|
||
| Neue Frontends (presseecho.test / businessportal24.test) | vorhanden | **IN** | Greifen künftig auf neue Models/API zu |
|
||
|
||
---
|
||
|
||
## 14. Offene Scope-Entscheidungen (Restliste)
|
||
|
||
| ID | Thema | Vorschlag / Status |
|
||
|---|---|---|
|
||
| S-01 | Multi-Kategorie pro PM | Bei 1:1 belassen; N:M-Ausbau nur auf Anfrage |
|
||
| S-02 | Coupons-Wiedereinführung | Vertagt (siehe D-16) |
|
||
| S-03 | E-Mail-Duplikate zwischen Portalen | Merge wenn gleiche E-Mail (siehe 05-DATABASE-MERGE §3.1) |
|
||
| S-04 | S3 für Medien in Prod | Optional, erst wenn Volumen es erfordert |
|
||
| S-05 | Definition der neuen Stripe-Produkte | Preisliste + Laufzeiten vom Auftraggeber noch zu liefern |
|
||
|
||
---
|
||
|
||
## 15. QA-Checkliste (manuell, vor Go-Live)
|
||
|
||
- [ ] Admin-Login (inkl. 2FA) funktioniert
|
||
- [ ] **Customer-Login via Magic-Link** funktioniert
|
||
- [ ] **Customer-Login via Passwort** funktioniert
|
||
- [ ] Passwort-Reset-Flow funktioniert (für Go-Live-Mailing kritisch)
|
||
- [ ] Portal-Scoping: Admin sieht mit Filter Presseecho-only, BP24-only, alle
|
||
- [ ] Press Release: Admin: Create → Save Draft → Publish → Mail → sichtbar im Frontend
|
||
- [ ] Press Release: **Customer**: Create → Save Draft → Submit → Admin sieht zur Prüfung
|
||
- [ ] Pressrelease Image-Upload, mehrere Bilder, Preview-Bild-Flag
|
||
- [ ] Company-Logo-Upload (mehrere Varianten)
|
||
- [ ] Blacklist-Wort blockiert Publish
|
||
- [ ] Newsletter Double-Opt-In End-to-End (**neu**)
|
||
- [ ] Stripe-Checkout End-to-End inkl. Webhook, Invoice-PDF wird erzeugt
|
||
- [ ] Grandfather-User: aktives Alt-Abo wird korrekt weiterberechnet/angezeigt
|
||
- [ ] Legacy-Rechnungen im Archiv sichtbar (Admin + Customer)
|
||
- [ ] API: `POST /v1/press-releases` mit Sanctum-Token
|
||
- [ ] API: Alter `api_key`-Parameter wird abgewiesen (Error-Hinweis mit Migrationslink)
|
||
- [ ] Alter `/thumbnails/...`-Link redirectet korrekt
|
||
- [ ] Scheduler-Jobs greifen (Runbook: `php artisan schedule:run` und `queue:work`)
|
||
- [ ] **Import-Rehearsal**: aktuelles Runbook aus `MIGRATION-STEPS.md` läuft auf frischer Ziel-DB gegen produktiven DB-Snapshot erfolgreich durch
|