# SaveTheMoment Automatisierungs-System ## Übersicht Das vollständig automatisierte Buchungs- und Verwaltungssystem für SaveTheMoment verarbeitet Anfragen von der E-Mail-Eingang bis zur Admin-Bestätigung. ## Workflow-Phasen ### Phase 1: ANFRAGE (Automatisch bei neuer Buchung) **Trigger:** Neue Buchung via E-Mail-Sync oder API **Automatische Aktionen (`lib/booking-automation.ts::runPostBookingActions()`):** 1. ✅ **LexOffice Contact & Quotation erstellen** - Contact aus Kundendaten erstellen - Angebot mit allen Positionen generieren (Fotobox, KM-Pauschale, Extras) - Angebots-PDF von LexOffice herunterladen - Speichert `lexofficeContactId` und `lexofficeOfferId` 2. ✅ **Mietvertrag-PDF generieren** - PDF aus Template (`mietvertrag-vorlage.pdf`) erstellen - Kundendaten, Event-Details, Preis einfügen - Setzt `contractGenerated: true` und `contractGeneratedAt` 3. ✅ **E-Mail mit Angebot + Vertrag versenden** - Beide PDFs als Anhänge - Online-Signatur-Link enthalten - Übersichtliche Buchungsdetails und Gesamtpreis - Setzt `contractSentAt` 4. ✅ **Nextcloud Kalender-Sync** - Event im Buchungskalender erstellen/aktualisieren - Setzt `calendarSynced: true` und `calendarSyncedAt` 5. ✅ **Admin-Benachrichtigung** - Notification mit Typ `NEW_BOOKING` **Dateien:** - `lib/booking-automation.ts` - Hauptlogik - `lib/lexoffice.ts` - LexOffice API (Contact, Quotation, PDF-Download) - `lib/pdf-template-service.ts` - Contract PDF-Generierung - `lib/email-service.ts` - `sendInitialBookingEmail()` - `lib/nextcloud-calendar.ts` - CalDAV-Synchronisation --- ### Phase 2: ONLINE-UNTERSCHRIFT (Kunde) **Endpoint:** `POST /api/bookings/[id]/sign` **Ablauf:** 1. Kunde öffnet Link: `/contract/sign/{token}` 2. Canvas-Signatur zeichnen 3. POST an `/api/bookings/[id]/sign` mit Base64-Signatur 4. PDF mit Signatur neu generieren 5. Datenbank-Update: - `contractSigned: true` - `contractSignedAt: DateTime` - `contractSignedOnline: true` - `contractSignatureData: String` (Base64) - `contractSignedBy: String` (Kundenname) - `contractSignedIp: String` 6. Notification `CONTRACT_SIGNED` für Admin **Dateien:** - `app/api/bookings/[id]/sign/route.ts` --- ### Phase 3: ADMIN-BESTÄTIGUNG **Endpoint:** `POST /api/bookings/[id]/confirm` **Voraussetzungen:** - ✅ `contractSigned === true` - ✅ `status !== 'CONFIRMED'` **Ablauf:** 1. Admin klickt auf "Buchung bestätigen" im Dashboard 2. LexOffice Auftragsbestätigung erstellen - `lexofficeService.createConfirmationFromBooking()` - Speichert `lexofficeConfirmationId` 3. Status-Update: `RESERVED → CONFIRMED` 4. Setzt `confirmationSentAt` 5. Nextcloud Kalender aktualisieren (Status: CONFIRMED) 6. Notification `BOOKING_CONFIRMED` **Dateien:** - `app/api/bookings/[id]/confirm/route.ts` --- ### Phase 4: RECHNUNG (Zeitgesteuert - TODO) **Trigger:** Cron-Job **Regeln:** - **Privatkunde:** 2 Wochen vor Event-Datum - **Geschäftskunde:** Nach Event-Datum **Ablauf:** 1. LexOffice Rechnung erstellen 2. Rechnung finalisieren (freigeben) 3. E-Mail an Kunde mit Rechnungs-PDF 4. Setzt `lexofficeInvoiceId` --- ## API-Endpunkte ### Admin-Endpoints #### `POST/GET /api/admin/test-automation` Testet die automatischen Aktionen für die neueste Buchung. **Response:** ```json { "success": true, "emailSent": true, "calendarSynced": true, "lexofficeCreated": true, "contractGenerated": true, "errors": [] } ``` #### `POST /api/bookings/[id]/confirm` Bestätigt eine Buchung (RESERVED → CONFIRMED) und erstellt LexOffice Auftragsbestätigung. **Auth:** Admin required --- ### Public-Endpoints #### `POST /api/bookings/[id]/sign` Speichert die Online-Signatur des Kunden. **Body:** ```json { "signatureData": "data:image/png;base64,..." } ``` #### `GET /api/bookings/[id]/sign` Ruft Buchungsdetails für Signatur-Seite ab. --- ## E-Mail-Templates ### 1. Initiale Buchungsanfrage (`sendInitialBookingEmail`) **An:** Kunde **Anhänge:** - `Angebot_{bookingNumber}.pdf` - `Mietvertrag_{bookingNumber}.pdf` **Inhalt:** - Buchungsdetails (Nummer, Datum, Location, Fotobox) - Gesamtpreis (Highlight) - Online-Signatur-Button - Nächste Schritte ### 2. Buchungsbestätigung (`sendBookingConfirmationEmail`) **An:** Kunde **Anhänge:** Keine (aktuell - TODO: Auftragsbestätigung anhängen) **Inhalt:** - Bestätigung der verbindlichen Buchung - Buchungsdetails ### 3. Vertragsversand (`sendContractEmail`) **An:** Kunde **Anhänge:** - `Mietvertrag_{bookingNumber}.pdf` **Inhalt:** - Vertrag als PDF - Online-Signatur-Link - Hinweis auf Signatur-Möglichkeiten --- ## Datenbank-Felder (Booking) ### LexOffice-Integration - `lexofficeContactId` - LexOffice Kontakt-ID - `lexofficeOfferId` - LexOffice Angebots-ID - `lexofficeConfirmationId` - LexOffice Auftragsbestätigungs-ID - `lexofficeInvoiceId` - LexOffice Rechnungs-ID (TODO) - `confirmationSentAt` - Zeitpunkt Admin-Bestätigung ### Contract Management - `contractGenerated` - PDF wurde generiert - `contractGeneratedAt` - Zeitpunkt Generierung - `contractSentAt` - Zeitpunkt Versand - `contractSigned` - Vertrag unterschrieben - `contractSignedAt` - Zeitpunkt Unterschrift - `contractSignedOnline` - Online vs. Upload - `contractSignatureData` - Base64 Signatur-Bild - `contractSignedBy` - Name des Unterzeichners - `contractSignedIp` - IP-Adresse bei Online-Signatur - `contractPdfUrl` - URL zum finalen PDF (optional) ### Kalender-Sync - `calendarEventId` - Nextcloud Event-UID - `calendarSynced` - Sync erfolgreich - `calendarSyncedAt` - Zeitpunkt letzter Sync --- ## Konfiguration ### Umgebungsvariablen ```env # LexOffice LEXOFFICE_API_KEY=your_api_key # Nextcloud NEXTCLOUD_URL=https://your-nextcloud.com NEXTCLOUD_USERNAME=username NEXTCLOUD_PASSWORD=app_password # E-Mail Test-Modus TEST_MODE=true TEST_EMAIL_RECIPIENT=test@example.com EMAIL_ENABLED=true # Base URL NEXTAUTH_URL=https://your-domain.com ``` ### LexOffice-Artikel-IDs Artikel-IDs sind in `PriceConfig` hinterlegt: - `lexofficeArticleId` - Fotobox ohne Druckflatrate - `lexofficeArticleIdWithFlat` - Fotobox mit Druckflatrate - `lexofficeKmFlatArticleId` - Kilometerpauschale (optional) - `lexofficeKmExtraArticleId` - Zusatzkilometer (optional) **Setup:** `scripts/setup-lexoffice-mapping.ts` --- ## Testing ### Manuelle Tests 1. **Test Automation:** ```bash curl -X GET http://localhost:3000/api/admin/test-automation \ -H "Cookie: next-auth.session-token=YOUR_TOKEN" ``` 2. **Test Signatur:** ```bash curl -X POST http://localhost:3000/api/bookings/{id}/sign \ -H "Content-Type: application/json" \ -d '{"signatureData": "data:image/png;base64,..."}' ``` 3. **Test Bestätigung:** ```bash curl -X POST http://localhost:3000/api/bookings/{id}/confirm \ -H "Cookie: next-auth.session-token=YOUR_TOKEN" ``` ### E-Mail-Sync Test ```bash npm run sync-emails # oder node scripts/manual-email-sync.ts ``` --- ## Fehlerbehandlung ### Automatisierung (Non-Blocking) Alle Aktionen in `runPostBookingActions()` sind try-catch geschützt: - LexOffice-Fehler → logged, aber kein Abbruch - PDF-Fehler → logged, aber kein Abbruch - E-Mail-Fehler → logged, nur wenn beide PDFs verfügbar - Kalender-Fehler → logged, aber kein Abbruch **Return-Objekt:** ```typescript { emailSent: boolean; calendarSynced: boolean; lexofficeCreated: boolean; contractGenerated: boolean; errors: string[]; } ``` ### Error-Logs Alle Fehler werden in Console geloggt mit Emoji-Präfix: - ✅ Erfolg - ❌ Fehler - ⚠️ Warnung - 🤖 Automation Start - 💼 LexOffice - 📄 PDF - 📧 E-Mail - 📅 Kalender --- ## Nächste Schritte ### Kurzfristig 1. ✅ Frontend für Online-Signatur erstellen (`/contract/sign/{token}`) 2. ✅ Dashboard-Button für Admin-Bestätigung 3. ✅ Testing mit echter Buchung ### Mittelfristig 1. Rechnung-Scheduler implementieren (Cron-Job) 2. E-Mail-Template für Rechnung 3. Zahlungsstatus-Tracking ### Langfristig 1. Webhook-Integration für LexOffice (statt Polling) 2. SMS-Benachrichtigungen 3. Customer-Portal für Buchungsübersicht --- ## Architektur-Entscheidungen ### Warum Custom LineItems statt nur LexOffice-Artikel? **Problem:** Kilometerpreise sind standortabhängig (Lübeck: 60€/15km, Hamburg: 100€/60km) **Lösung:** Hybrid-Ansatz - Fotobox: LexOffice-Artikel (wenn ID vorhanden) - KM-Pauschale: Custom LineItem mit dynamischem Preis - Extras: LexOffice-Artikel oder Custom ### Warum Promise-basiertes Singleton für Nextcloud? **Problem:** Race-Conditions bei parallelen Initialisierungen **Lösung:** `initPromise`-Pattern - Erste Initialisierung erstellt Promise - Alle weiteren Aufrufe warten auf gleiche Promise - Bei Fehler: Reset für erneuten Versuch ### Warum Non-Blocking Automation? **Problem:** Ein Fehler (z.B. LexOffice down) sollte nicht den gesamten Prozess stoppen **Lösung:** Granulare Error-Handling - Jede Aktion in eigenem try-catch - Fehler werden gesammelt, aber nicht propagiert - Partial Success möglich (z.B. E-Mail ja, Kalender nein) --- ## Support Bei Fragen oder Problemen: 1. Logs prüfen (Console-Output mit Emojis) 2. `.env` Konfiguration validieren 3. Nextcloud-Credentials testen: `node test-nextcloud-connection.js` 4. LexOffice-Artikel-IDs prüfen: `node scripts/setup-lexoffice-mapping.ts` --- **Version:** 1.0 **Letzte Aktualisierung:** 2025-11-12 **Entwickler:** Dennis Forte mit KI-Unterstützung