- Vintage Modell hinzugefuegt - Equipment Multi-Select (Neue Buchung + Bearbeitung) - Kundenadresse in Formularen - Bearbeiten-Seite fuer Buchungen - Abbau-Zeiten in Formularen und Uebersicht - Vertrag PDF nur bei Privatkunden - LexOffice Kontakt-Erstellung Fix (BUSINESS) - Zurueck-Pfeil auf Touren-Seite
9.3 KiB
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()):
-
✅ LexOffice Contact & Quotation erstellen
- Contact aus Kundendaten erstellen
- Angebot mit allen Positionen generieren (Fotobox, KM-Pauschale, Extras)
- Angebots-PDF von LexOffice herunterladen
- Speichert
lexofficeContactIdundlexofficeOfferId
-
✅ Mietvertrag-PDF generieren
- PDF aus Template (
mietvertrag-vorlage.pdf) erstellen - Kundendaten, Event-Details, Preis einfügen
- Setzt
contractGenerated: trueundcontractGeneratedAt
- PDF aus Template (
-
✅ E-Mail mit Angebot + Vertrag versenden
- Beide PDFs als Anhänge
- Online-Signatur-Link enthalten
- Übersichtliche Buchungsdetails und Gesamtpreis
- Setzt
contractSentAt
-
✅ Nextcloud Kalender-Sync
- Event im Buchungskalender erstellen/aktualisieren
- Setzt
calendarSynced: trueundcalendarSyncedAt
-
✅ Admin-Benachrichtigung
- Notification mit Typ
NEW_BOOKING
- Notification mit Typ
Dateien:
lib/booking-automation.ts- Hauptlogiklib/lexoffice.ts- LexOffice API (Contact, Quotation, PDF-Download)lib/pdf-template-service.ts- Contract PDF-Generierunglib/email-service.ts-sendInitialBookingEmail()lib/nextcloud-calendar.ts- CalDAV-Synchronisation
Phase 2: ONLINE-UNTERSCHRIFT (Kunde)
Endpoint: POST /api/bookings/[id]/sign
Ablauf:
- Kunde öffnet Link:
/contract/sign/{token} - Canvas-Signatur zeichnen
- POST an
/api/bookings/[id]/signmit Base64-Signatur - PDF mit Signatur neu generieren
- Datenbank-Update:
contractSigned: truecontractSignedAt: DateTimecontractSignedOnline: truecontractSignatureData: String(Base64)contractSignedBy: String(Kundenname)contractSignedIp: String
- Notification
CONTRACT_SIGNEDfü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:
- Admin klickt auf "Buchung bestätigen" im Dashboard
- LexOffice Auftragsbestätigung erstellen
lexofficeService.createConfirmationFromBooking()- Speichert
lexofficeConfirmationId
- Status-Update:
RESERVED → CONFIRMED - Setzt
confirmationSentAt - Nextcloud Kalender aktualisieren (Status: CONFIRMED)
- 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:
- LexOffice Rechnung erstellen
- Rechnung finalisieren (freigeben)
- E-Mail an Kunde mit Rechnungs-PDF
- Setzt
lexofficeInvoiceId
API-Endpunkte
Admin-Endpoints
POST/GET /api/admin/test-automation
Testet die automatischen Aktionen für die neueste Buchung.
Response:
{
"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:
{
"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}.pdfMietvertrag_{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-IDlexofficeOfferId- LexOffice Angebots-IDlexofficeConfirmationId- LexOffice Auftragsbestätigungs-IDlexofficeInvoiceId- LexOffice Rechnungs-ID (TODO)confirmationSentAt- Zeitpunkt Admin-Bestätigung
Contract Management
contractGenerated- PDF wurde generiertcontractGeneratedAt- Zeitpunkt GenerierungcontractSentAt- Zeitpunkt VersandcontractSigned- Vertrag unterschriebencontractSignedAt- Zeitpunkt UnterschriftcontractSignedOnline- Online vs. UploadcontractSignatureData- Base64 Signatur-BildcontractSignedBy- Name des UnterzeichnerscontractSignedIp- IP-Adresse bei Online-SignaturcontractPdfUrl- URL zum finalen PDF (optional)
Kalender-Sync
calendarEventId- Nextcloud Event-UIDcalendarSynced- Sync erfolgreichcalendarSyncedAt- Zeitpunkt letzter Sync
Konfiguration
Umgebungsvariablen
# 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 DruckflatratelexofficeArticleIdWithFlat- Fotobox mit DruckflatratelexofficeKmFlatArticleId- Kilometerpauschale (optional)lexofficeKmExtraArticleId- Zusatzkilometer (optional)
Setup: scripts/setup-lexoffice-mapping.ts
Testing
Manuelle Tests
-
Test Automation:
curl -X GET http://localhost:3000/api/admin/test-automation \ -H "Cookie: next-auth.session-token=YOUR_TOKEN" -
Test Signatur:
curl -X POST http://localhost:3000/api/bookings/{id}/sign \ -H "Content-Type: application/json" \ -d '{"signatureData": "data:image/png;base64,..."}' -
Test Bestätigung:
curl -X POST http://localhost:3000/api/bookings/{id}/confirm \ -H "Cookie: next-auth.session-token=YOUR_TOKEN"
E-Mail-Sync Test
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:
{
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
- 📅 Kalender
Nächste Schritte
Kurzfristig
- ✅ Frontend für Online-Signatur erstellen (
/contract/sign/{token}) - ✅ Dashboard-Button für Admin-Bestätigung
- ✅ Testing mit echter Buchung
Mittelfristig
- Rechnung-Scheduler implementieren (Cron-Job)
- E-Mail-Template für Rechnung
- Zahlungsstatus-Tracking
Langfristig
- Webhook-Integration für LexOffice (statt Polling)
- SMS-Benachrichtigungen
- 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:
- Logs prüfen (Console-Output mit Emojis)
.envKonfiguration validieren- Nextcloud-Credentials testen:
node test-nextcloud-connection.js - 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