Files
Atlas/AUTOMATION-SYSTEM.md
Julia Wehden a2c95c70e7 feat: Equipment-System, Buchungsbearbeitung, Kundenadresse, LexOffice-Fix
- 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
2026-03-19 16:21:55 +01:00

380 lines
9.3 KiB
Markdown

# 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