End-to-End Dokumentation: Friseur 1
Company: Friseur 1 (ID: 1) | Branches: 1 | Services: 3 | Staff: 5
Diese Dokumentation beschreibt den vollständigen E2E-Prozess von Inbound-Calls über Retell.ai, Middleware, Cal.com bis zur Buchungsbestätigung. → Vollständige Spezifikation | 📊 Audit-Report | ⚠️ Gaps
📱 AskPro AI - Produkt-Übersicht
Voice AI Platform für automatische Terminbuchungen
Multi-Tenant SaaS-Lösung mit KI-gestütztem Telefon-Agent für Friseursalons, Arztpraxen, und Service-Unternehmen.
0a. Anbieter-Perspektive AskPro AI
Was bietet AskPro AI als Plattform-Anbieter: Multi-Tenant SaaS, Voice AI Integration, Kalender-Synchronisation, Automatisches Billing.
(Multi-Tenant Core)"] ADMIN["🖥️ Filament Admin
(Company Management)"] BILLING["💳 Stripe Billing
(Usage-Based)"] DB[("🗄️ PostgreSQL
(Shared Database)")] end subgraph "🔌 Externe Integrationen" RETELL["🤖 Retell.ai
(Voice AI Platform)"] CALCOM["📅 Cal.com
(Booking System)"] end subgraph "👥 Endkunden (Mandanten)" FRISEUR["💈 Friseur 1
(2 Filialen, 5 Mitarbeiter)"] ARZT["🏥 Arztpraxis
(Terminbuchung)"] SERVICE["🔧 Service-Betrieb
(Auftragsannahme)"] end PLATFORM --> DB ADMIN --> PLATFORM PLATFORM --> BILLING PLATFORM <--> RETELL PLATFORM <--> CALCOM FRISEUR --> RETELL ARZT --> RETELL SERVICE --> RETELL PLATFORM -.->|"Mandant 1"| FRISEUR PLATFORM -.->|"Mandant 2"| ARZT PLATFORM -.->|"Mandant 3"| SERVICE style PLATFORM fill:#E8F5E9 style ADMIN fill:#E0F2F1 style BILLING fill:#FCE4EC style DB fill:#F1F8E9 style RETELL fill:#FFF3E0 style CALCOM fill:#F3E5F5 style FRISEUR fill:#E3F2FD style ARZT fill:#E3F2FD style SERVICE fill:#E3F2FD
Kernfunktionen: Multi-Tenancy (Company Scoping), Voice AI Integration (Retell.ai), Kalender-Sync (Cal.com), Usage-Based Billing (Stripe), Admin-Portal (Filament).
0b. Endkunden-Perspektive Value Proposition
Was erhält ein Endkunde wie "Friseur 1": 24/7 Telefon-Agent, Automatische Buchungen, Keine manuelle Verwaltung, Integration mit bestehendem Kalender.
+493033081738"] end subgraph "🤖 AskPro AI Service" AGENT["🎙️ KI-Agent
spricht Deutsch
versteht Intent"] BOOK["📅 Automatische
Terminbuchung
24/7 verfügbar"] end subgraph "💈 Friseur 1 (Ihr Unternehmen)" CAL["📆 Ihr Kalender
(Cal.com)
bleibt immer aktuell"] TEAM["👥 Ihr Team
keine manuelle
Eingabe nötig"] CONFIRM["✅ Bestätigung
per E-Mail/SMS
an Kunden"] end CALL --> AGENT AGENT -->|"Termin gefunden"| BOOK BOOK --> CAL CAL --> TEAM BOOK --> CONFIRM style CALL fill:#E3F2FD style AGENT fill:#FFF3E0 style BOOK fill:#C8E6C9 style CAL fill:#F3E5F5 style TEAM fill:#E0F2F1 style CONFIRM fill:#C8E6C9
Vorteile für Friseur 1:
✅ Keine verpassten Anrufe (24/7 Erreichbarkeit)
✅ Automatische Buchung ohne Personal (Kosteneinsparung)
✅ Integration mit bestehendem Kalender (keine Doppelbuchungen)
✅ Natürliche Sprachverarbeitung (Kunden merken kaum einen Unterschied)
✅ Transparente Abrechnung (nutzungsbasiert, keine Fixkosten)
A. C4-Kontextdiagramm System Overview
Zeigt alle beteiligten Systeme und deren Kommunikation: Customer, Retell.ai, Middleware, Cal.com, Frontend, Billing, Database.
Agent: ...b6d56ab07b"] MW["⚙️ Middleware
Laravel API"] CAL["📅 Cal.com
Team: 34209"] FE["🖥️ Frontend
Filament"] BILL["💳 Billing
Stripe"] DB[("🗄️ Database
PostgreSQL")] CUS -->|"Inbound Call
+493033081738"| RAI RAI -->|Webhook| MW MW -->|"Booking API"| CAL MW -->|Read/Write| DB MW -->|UI| FE MW -->|Charges| BILL CAL -->|Webhook| MW style CUS fill:#E3F2FD style RAI fill:#FFF3E0 style MW fill:#E8F5E9 style CAL fill:#F3E5F5 style FE fill:#E0F2F1 style BILL fill:#FCE4EC style DB fill:#F1F8E9
B. E2E Happy Path Main Flow
Erfolgreicher Buchungspfad: Anruf → Intent-Erkennung → Policy-Check → Verfügbarkeitsabfrage → Buchung → Bestätigung → Logging.
Customer?"} D[collect_appointment_info] E[check_availability] end subgraph MW["⚙️ Middleware"] F["PolicyEngine:
canBook?"] G["CalcomService:
getSlots"] H{"Slot
found?"} I[Create Appointment] J[Log Call + Costs] end subgraph CAL["📅 Cal.com"] K["Query Availability
Team 34209"] L["POST /bookings"] M[("Booking DB")] end subgraph FE["🖥️ Frontend"] N["Display in
Call Log"] O["Show Transcript"] end A --> B --> C C -->|"Phone Lookup"| F C -->|Yes| D --> E F -->|"Policy OK"| G G --> K K -->|"Slots Available"| H H -->|Yes| I I --> L --> M M -->|"Webhook Confirm"| I I --> J J --> N --> O H -->|No| D F -->|"Policy Block"| J style A fill:#E3F2FD style B fill:#FFF3E0 style C fill:#FFE0B2 style F fill:#C8E6C9 style H fill:#C8E6C9 style I fill:#C8E6C9 style K fill:#E1BEE7 style M fill:#F1F8E9
C. Alternativpfade Error Handling
Umgang mit Sonderfällen: Umbuchung, Stornierung, Policy-Blockierung, No-Show, Nummernunterdrückung, Eskalation.
D. Conversational Decision Tree Intent Recognition
Intent-Erkennung, Required Slots, Disambiguation, NLU-Fallback-Strategien.
erkannt?"} BOOK["Intent: book_appointment"] CANCEL["Intent: cancel_appointment"] RESC["Intent: reschedule_appointment"] INFO["Intent: get_info"] UNK["Intent: unknown"] START --> INTENT INTENT -->|book| BOOK INTENT -->|cancel| CANCEL INTENT -->|reschedule| RESC INTENT -->|info| INFO INTENT -->|unclear| UNK BOOK --> SLOTS["Required Slots:
service, date, time"] SLOTS --> DISAMB{"All
filled?"} DISAMB -->|No| ASK["Ask missing info"] ASK --> SLOTS DISAMB -->|Yes| CONFIRM["Confirm & Book"] UNK --> FALLBACK["NLU Fallback:
Rephrase question"] FALLBACK --> INTENT style START fill:#E3F2FD style INTENT fill:#FFF3E0 style BOOK fill:#C8E6C9 style CONFIRM fill:#C8E6C9 style UNK fill:#FFCDD2 style FALLBACK fill:#FFE0B2
E. Middleware-Orchestrierung Integration Layer
Webhook-Verarbeitung, Idempotenz, Retry-Logic, Mapping (TeamID↔Filiale, EventID↔Service), Timezone-Handling.
/api/webhooks/retell"] W2["Cal.com Webhook
/api/calcom/webhook"] end subgraph "Idempotenz" ID1["Check:
retell_call_id exists?"] ID2["Check:
calcom_booking_uid exists?"] end subgraph "Verarbeitung" MAP["Mapping:
TeamID↔Branch
EventID↔Service
StaffID↔User"] POL["Policy Check
canBook/canCancel"] RETRY["Retry Logic
Circuit Breaker"] end subgraph "Persistence" DB[("Database
PostgreSQL")] CACHE[("Redis Cache
5min TTL")] end W1 --> ID1 W2 --> ID2 ID1 -->|New| MAP ID2 -->|New| MAP ID1 -->|Duplicate| SKIP["Return cached"] ID2 -->|Duplicate| SKIP MAP --> POL POL --> RETRY RETRY --> DB DB --> CACHE style ID1 fill:#FFF3E0 style ID2 fill:#FFF3E0 style MAP fill:#E1BEE7 style POL fill:#FFE0B2 style SKIP fill:#C8E6C9
F. Cal.com Sequence Booking API
Sequenzdiagramm der Cal.com API-Integration: Availability → Slot Selection → Booking Creation → Webhook Callback.
Team 34209 Note over MW,CAL: Availability Check MW->>CAL: GET /slots/available
eventTypeId=???
startTime=2025-11-04 CAL-->>MW: {slots: [...]} Note over MW,CAL: Booking Creation MW->>CAL: POST /bookings
{eventTypeId, start, attendee} CAL-->>MW: {uid, id, status: "accepted"} MW->>MW: Store calcom_booking_id Note over MW,CAL: Webhook Callback CAL->>MW: POST /api/calcom/webhook
{triggerEvent: "BOOKING_CREATED"} MW-->>CAL: 200 OK Note over MW,CAL: Rescheduling MW->>CAL: PATCH /bookings/{uid}
{start: new_time} CAL-->>MW: {uid, status: "rescheduled"} CAL->>MW: Webhook: BOOKING_RESCHEDULED Note over MW,CAL: Cancellation MW->>CAL: DELETE /bookings/{uid} CAL-->>MW: 204 No Content CAL->>MW: Webhook: BOOKING_CANCELLED
G. Billing Flow Cost Calculation
Sekundengenaue Kostenberechnung: Retell.ai Cost → Platform Markup → Currency Conversion → Rounding → Balance/Invoice.
per_second"] COST["Retell Cost:
seconds × $0.020/60"] MARKUP["Markup:
× 30%"] EXCH["Convert:
USD → EUR"] ROUND["Round:
ceil(cents)"] BAL{"Prepaid
Balance?"} DEDUCT["Deduct from Balance"] TOPUP["Stripe Top-Up
required"] INV["Add to Invoice"] START --> DUR --> COST COST --> MARKUP --> EXCH --> ROUND ROUND --> BAL BAL -->|Sufficient| DEDUCT BAL -->|Low| TOPUP DEDUCT --> INV TOPUP --> INV style START fill:#E3F2FD style COST fill:#FFE0B2 style BAL fill:#FFF3E0 style DEDUCT fill:#C8E6C9 style TOPUP fill:#FFCDD2
H. Telemetrie & Logging Observability
Call-ID-Korrelation, Metriken (Duration, Cost, Sentiment), Transcript-Speicherung, Privacy (PII Redaction).
retell_call_id"] BOOK["Booking ID
calcom_booking_id"] CUS["Customer ID"] end subgraph "Metrics" DUR["Duration
(seconds)"] COST["Cost
(cents)"] SENT["Sentiment
(-1 to 1)"] INTENT["Intent
(book/cancel/...)"] end subgraph "Logs" TRANS["Transcript
(TEXT)"] AUDIO["Audio URL
(30 days)"] META["Metadata JSON"] end subgraph "Privacy" ANON["PII Redaction
after 365d"] DEL["Auto-Delete
after 90d"] end CALL --> BOOK CALL --> CUS CALL --> DUR CALL --> COST CALL --> SENT CALL --> INTENT CALL --> TRANS CALL --> AUDIO CALL --> META TRANS --> ANON --> DEL style CALL fill:#E3F2FD style BOOK fill:#E1BEE7 style TRANS fill:#FFF3E0 style ANON fill:#FFCDD2
I. Zustandsautomat State Machine
Lifecycle eines Leads/Kunden: Unknown → Known → In Gespräch → Slot gesucht → Gebucht → Verschoben/Storniert/Completed/NoShow.
J. ER-Diagramm Data Model
Datenmodell: Company → Branch → Service (+ Components) → Staff → Customer → Appointment → Call → Transcript → Charge.
K. Terminarten Simple vs. Composite
Simple Appointments: Einfache Termine mit einem durchgehenden Zeitraum (z.B. Beratungsgespräch 60min).
Composite Appointments: Mehrteilige Termine mit Arbeitsphasen und optionalen Pausen (z.B. Färben mit Einwirkzeit).
K.1 Taxonomie & Datenmodell
Implementierung: Composite Appointments speichern ihre Segmente als JSON-Array im segments-Feld.
Keine separate Tabelle nötig. starts_at/ends_at umfassen die gesamte Zeitspanne (min/max aller Segmente).
K.2 Zeitachse mit Pausen
Beispiel: Ein Färbe-Termin besteht aus 4 Segmenten (3× WORK, 1× BREAK). Gesamtdauer: 120min. Pausen sind explizit als eigene Segmente modelliert.
K.3 Validierungs-Flow
segments = null] SIMPLE --> VALIDATE_SIMPLE[Start/End validieren] VALIDATE_SIMPLE --> SAVE TYPE -->|Composite| COMPOSITE[is_composite = true] COMPOSITE --> SEGMENTS[Segmente definieren] SEGMENTS --> PAUSE{Pausen benötigt?} PAUSE -->|Ja| ADD_BREAKS[BREAK-Segmente einfügen
type: 'break'] PAUSE -->|Nein| ORDER ADD_BREAKS --> ORDER ORDER[Segmente sortieren
order: 1, 2, 3...] ORDER --> VALIDATE_SEG[Validierung] VALIDATE_SEG --> CHECK1{Überlappungen?} CHECK1 -->|Ja| ERROR1[❌ Fehler] CHECK1 -->|Nein| CHECK2{Lücken?} CHECK2 -->|Ja| WARN[⚠️ Warnung] CHECK2 -->|Nein| CALC WARN --> CALC CALC[starts_at = min Segment start
ends_at = max Segment end] CALC --> SAVE SAVE[(Appointment speichern)] ERROR1 --> END([Ende]) SAVE --> END style SIMPLE fill:#C8E6C9 style COMPOSITE fill:#E1BEE7 style ADD_BREAKS fill:#FFE0B2 style ERROR1 fill:#FFCDD2 style WARN fill:#FFF9C4 style SAVE fill:#C8E6C9
Validierungsregeln:
- ✅ Segmente dürfen sich nicht überlappen
- ⚠️ Lücken zwischen Segmenten sind erlaubt (Warnung)
- ✅
order-Index muss aufsteigend sein - ✅
starts_at/ends_atdes Appointments = min/max der Segmente
K.4 State Machine (Laufzeit)
(bei BREAK-Segment) InProgress --> Completed: finish() InProgress --> Cancelled: cancel() Paused --> InProgress: resume()
(nächstes WORK-Segment) Paused --> Cancelled: cancel() Completed --> [*] Cancelled --> [*] note right of Paused Bei Composite Appointments: Pause = BREAK-Segment aktiv end note note right of InProgress Aktuelles Segment wird verarbeitet (WORK) end note
Hinweis: Bei Composite Appointments steuern pause() und resume()
den Übergang zwischen WORK- und BREAK-Segmenten.
K.5 Datenbank-Schema
Persistenz: Alle Appointment-Daten in einer Tabelle. Segmente als JSON im segments-Feld.
composite_group_uid erlaubt Gruppierung mehrerer Termine (z.B. für komplexe Behandlungen).
segments JSON-Struktur (Beispiel):
[
{
"start": "2025-11-03 10:30:00",
"end": "2025-11-03 11:15:00",
"label": "Färben Phase 1",
"type": "work",
"order": 1,
"duration_minutes": 45
},
{
"start": "2025-11-03 11:15:00",
"end": "2025-11-03 11:45:00",
"label": "Einwirkzeit",
"type": "break",
"order": 2,
"duration_minutes": 30
}
]