# 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
