# Newsletter-Modul Dokumentation ## Übersicht Das Newsletter-Modul ermöglicht die zentrale Verwaltung von Newsletter-Kontakten aus beiden Buchungssystemen (Kulturreisen und Ferienwohnungen). Es synchronisiert automatisch Kundendaten aus Buchungen und bietet Export-Funktionen für Newsletter-Kampagnen. ## Features - ✅ Zentrale Kontaktverwaltung für beide Newsletter-Gruppen - ✅ Automatische Synchronisation aus Buchungssystemen - ✅ Duplikat-Erkennung über E-Mail-Adressen - ✅ Tracking von Buchungsstatistiken - ✅ Status-Verwaltung (Aktiv, Inaktiv, Abgemeldet, Bounced) - ✅ Herkunfts-Tracking (Buchung, Newsletter-Anmeldung, etc.) - ✅ Export-Funktion (CSV) - ✅ Aktivitäts-Log für jeden Kontakt - ✅ Filter- und Suchfunktionen ## Installation ### 1. Migrationen ausführen ```bash ./vendor/bin/sail artisan migrate ``` Dies erstellt folgende Tabellen: - `newsletter_contacts` - Haupt-Kontakte-Tabelle - `newsletter_logs` - Aktivitäts-Log ### 2. Berechtigung hinzufügen In der Datenbank muss die Berechtigung `cms-newsletter` für Benutzer aktiviert werden, die Zugriff auf das Newsletter-Modul haben sollen. ```sql -- Beispiel: Berechtigung für einen User aktivieren -- Dies muss über das bestehende Berechtigungssystem erfolgen ``` ### 3. Erste Synchronisation Nach der Installation sollte eine vollständige Synchronisation durchgeführt werden: ```bash # Alle Buchungen synchronisieren ./vendor/bin/sail artisan newsletter:sync-kulturreisen --force ./vendor/bin/sail artisan newsletter:sync-ferienwohnungen --force ``` ## Verwendung ### Admin-Panel Das Newsletter-Modul ist im Admin-Panel unter **CMS > Inhalte > Newsletter** erreichbar. #### Hauptfunktionen: 1. **Kontaktliste** - Übersicht aller Newsletter-Kontakte - Filter nach Gruppe, Status, Herkunft - Suchfunktion nach E-Mail und Name - DataTables mit Sortierung und Pagination 2. **Kontakt-Detail** - Vollständige Kontaktinformationen - Buchungsstatistiken - Aktivitäts-Log - Verlinkung zu Original-Kundendaten 3. **Kontakt bearbeiten** - Manuelles Erstellen von Kontakten - Bearbeiten von Kontaktdaten - Status-Änderung - Gruppen-Zuweisung 4. **Synchronisation** - Manuelle Synchronisation über UI - Incremental Sync (letzte 30 Tage) - Full Sync (alle Buchungen) 5. **Export** - Export nach Gruppe - Export nach Status - CSV-Format - Vorkonfigurierte Export-Optionen ### Artisan-Befehle #### Synchronisation Kulturreisen ```bash # Incremental Sync (letzte 30 Tage) ./vendor/bin/sail artisan newsletter:sync-kulturreisen # Full Sync (alle Buchungen) ./vendor/bin/sail artisan newsletter:sync-kulturreisen --force ``` Dieser Befehl: - Liest alle Buchungen aus der `booking` Tabelle - Verknüpft mit `customer` Daten - Erstellt oder aktualisiert Newsletter-Kontakte - Zählt Buchungen pro Kunde - Trackt letzte Buchung #### Synchronisation Ferienwohnungen ```bash # Incremental Sync (letzte 30 Tage) ./vendor/bin/sail artisan newsletter:sync-ferienwohnungen # Full Sync (alle Buchungen) ./vendor/bin/sail artisan newsletter:sync-ferienwohnungen --force ``` Dieser Befehl: - Liest Buchungen aus `travel_user_booking_fewos` mit `invoice_number` - Nur Buchungen mit reiner Nummer (keine Storno etc.) - Verknüpft mit `travel_users` Daten - Erstellt oder aktualisiert Newsletter-Kontakte - Zählt Buchungen pro Kunde ### Automatische Synchronisation Für regelmäßige Synchronisation empfiehlt sich ein Cron-Job: ```bash # In der crontab # Täglich um 2 Uhr morgens 0 2 * * * cd /var/www/html && ./vendor/bin/sail artisan newsletter:sync-kulturreisen 0 2 * * * cd /var/www/html && ./vendor/bin/sail artisan newsletter:sync-ferienwohnungen ``` Oder im Laravel Scheduler (`app/Console/Kernel.php`): ```php protected function schedule(Schedule $schedule) { // Täglich um 2 Uhr $schedule->command('newsletter:sync-kulturreisen')->dailyAt('02:00'); $schedule->command('newsletter:sync-ferienwohnungen')->dailyAt('02:15'); } ``` ## Datenmodell ### Newsletter Contact | Feld | Typ | Beschreibung | |------|-----|--------------| | `id` | bigint | Primary Key | | `email` | string | E-Mail-Adresse (unique) | | `firstname` | string | Vorname | | `lastname` | string | Nachname | | `group_kulturreisen` | boolean | Zugehörigkeit zur Gruppe Kulturreisen | | `group_ferienwohnungen` | boolean | Zugehörigkeit zur Gruppe Ferienwohnungen | | `source` | enum | Herkunft des Kontakts | | `status` | enum | Status (active, inactive, unsubscribed, bounced) | | `subscribed_at` | timestamp | Zeitpunkt der Anmeldung | | `unsubscribed_at` | timestamp | Zeitpunkt der Abmeldung | | `last_booking_at` | timestamp | Zeitpunkt der letzten Buchung | | `total_bookings_kulturreisen` | int | Anzahl Buchungen Kulturreisen | | `total_bookings_ferienwohnungen` | int | Anzahl Buchungen Ferienwohnungen | | `customer_id` | int | Referenz zu `customer` (Kulturreisen) | | `travel_user_id` | int | Referenz zu `travel_users` (Ferienwohnungen) | | `last_synced_at` | timestamp | Letzte Synchronisation | | `sync_hash` | string | Hash für Duplikat-Erkennung | | `notes` | text | Notizen | ### Newsletter Log | Feld | Typ | Beschreibung | |------|-----|--------------| | `id` | bigint | Primary Key | | `newsletter_contact_id` | bigint | Foreign Key zu newsletter_contacts | | `action` | enum | Aktion (subscribed, unsubscribed, etc.) | | `description` | string | Beschreibung der Aktion | | `metadata` | json | Zusätzliche Daten | | `user_id` | int | Admin-User der die Aktion ausgeführt hat | ## Status-Typen - **active**: Aktiver Newsletter-Empfänger - **inactive**: Inaktiv (z.B. temporär deaktiviert) - **unsubscribed**: Abgemeldet vom Newsletter - **bounced**: E-Mail nicht zustellbar (Bounced) ## Herkunfts-Typen - **booking_kulturreisen**: Aus Kulturreisen-Buchung - **booking_ferienwohnungen**: Aus Ferienwohnungs-Buchung - **newsletter_signup**: Newsletter-Anmeldung über Formular - **manual**: Manuell erstellt - **import**: Über Import hinzugefügt ## Export-Formate ### CSV-Export Der CSV-Export enthält folgende Spalten: 1. ID 2. E-Mail 3. Vorname 4. Nachname 5. Gruppe Kulturreisen (Ja/Nein) 6. Gruppe Ferienwohnungen (Ja/Nein) 7. Status 8. Herkunft 9. Buchungen Kulturreisen 10. Buchungen Ferienwohnungen 11. Letzte Buchung 12. Angemeldet am 13. Abgemeldet am 14. Erstellt am ## Best Practices ### Duplikat-Vermeidung Das System verwendet einen Hash basierend auf E-Mail und Quelle zur Duplikat-Erkennung. Kontakte werden automatisch zusammengeführt, wenn: - Dieselbe E-Mail-Adresse in beiden Systemen vorkommt - Der neuere Datensatz wird bevorzugt - Gruppenzugehörigkeiten werden kombiniert ### Datenschutz - Soft-Delete: Gelöschte Kontakte werden nicht permanent entfernt - Log-Tracking: Alle Änderungen werden protokolliert - Abmelde-Funktion: Kontakte können sich jederzeit abmelden - Export-Kontrolle: Nur autorisierte Benutzer können exportieren ### Performance - Incremental Sync: Standardmäßig werden nur die letzten 30 Tage synchronisiert - Indexierung: E-Mail, Status und Gruppen sind indexiert - DataTables: Server-Side Processing für große Datenmengen - Batch-Processing: Synchronisation verarbeitet Datensätze effizient ## Troubleshooting ### Problem: Synchronisation schlägt fehl **Lösung:** 1. Prüfe Datenbankverbindungen (beide Datenbanken müssen erreichbar sein) 2. Prüfe Logs: `storage/logs/laravel.log` 3. Führe Sync mit `--force` aus für vollständige Synchronisation ### Problem: Duplikate in der Liste **Lösung:** 1. Prüfe `sync_hash` Spalte 2. Führe manuelle Bereinigung durch 3. Kontakte können manuell zusammengeführt werden ### Problem: Export enthält keine Daten **Lösung:** 1. Prüfe Filter-Einstellungen 2. Prüfe Status der Kontakte 3. Prüfe Berechtigungen ## API-Endpunkte Alle Routen sind unter dem Middleware-Schutz `['admin', '2fa', 'auth.permission:cms-newsletter']`. | Methode | Route | Beschreibung | |---------|-------|--------------| | GET | `/newsletter` | Liste aller Kontakte | | GET | `/newsletter/datatable` | DataTables AJAX | | GET | `/newsletter/{id}` | Detail eines Kontakts | | GET | `/newsletter/{id}/edit` | Bearbeitungsformular | | POST | `/newsletter/{id}/store` | Speichern | | DELETE | `/newsletter/{id}` | Löschen (soft delete) | | POST | `/newsletter/{id}/unsubscribe` | Abmelden | | POST | `/newsletter/{id}/resubscribe` | Wieder aktivieren | | POST | `/newsletter/sync` | Synchronisation starten | | GET | `/newsletter/export` | Export | ## Erweiterungen ### Integration mit Newsletter-Diensten Das Modul kann einfach mit externen Newsletter-Diensten (Mailchimp, SendGrid, etc.) integriert werden: ```php // Beispiel: Export für Mailchimp $contacts = NewsletterContact::active()->kulturreisen()->get(); foreach ($contacts as $contact) { // Mailchimp API Call } ``` ### Webhook für Abmeldungen Eine öffentliche Abmelde-Route kann hinzugefügt werden: ```php // routes/web.php Route::get('/newsletter/unsubscribe/{token}', 'NewsletterPublicController@unsubscribe'); ``` ### Double-Opt-In Für Newsletter-Anmeldungen kann ein Double-Opt-In Prozess implementiert werden. ## Support Bei Fragen oder Problemen: 1. Prüfe diese Dokumentation 2. Prüfe Laravel Logs 3. Prüfe Artisan Command Output 4. Kontaktiere das Entwickler-Team ## Changelog ### Version 1.0.0 (2025-11-07) - ✅ Initiales Release - ✅ Kontaktverwaltung - ✅ Synchronisation Kulturreisen - ✅ Synchronisation Ferienwohnungen - ✅ Export-Funktion - ✅ Admin-Panel Integration