# 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