# fahrschuldesk — Projektplan

## 1. Überblick

**fahrschuldesk** ist eine SaaS-Plattform zur Verwaltung von Fahrschulen. Plattformbetreiber (Admin-Team) können Fahrschulen als Mandanten anlegen und verwalten. Jede Fahrschule erhält eine modulare Oberfläche mit Kundenverwaltung, Kalender, Messenger und optionaler Lernsoftware.

**Status:** Planungsphase (Initialsetup)

---

## 2. Architektur

### 2.1 Domains

| Domain | Zweck | Pfad |
|---|---|---|
| `fahrschuldesk.de` | WebUI (Frontend) | `www/fahrschuldesk.de/public/` |
| `api.fahrschuldesk.de` | REST API (Backend) | `www/api.fahrschuldesk.de/public/` |

### 2.2 Tech-Stack

- **Frontend:** Vue 3 + Vite (SPA)
- **Backend:** PHP (Laravel oder Slim Framework)
- **Datenbank:** PostgreSQL (fahrschuldesk DB, Host: 10.255.30.11:5433)
- **WebSockets:** Für Messenger (Socket.io oder native WebSockets)
- **Dateien:** Lokaler Storage + S3-kompatibel (für Self-Hosted einfach lokaler Ordner)
- **Auth:** JWT-basiert mit Refresh-Token
- **CI/CD:** GitHub Actions / GitLab CI

### 2.3 Kalender-Integration

Der Kalender wird über die fahrschultermin.de API gesteuert (spätere Integration). Die fahrschuldesk-API dient als Schnittstelle.

---

## 3. Hierarchie & Datenmodell

```
Plattform-Admins (intern)
 └── Fahrschule (Mandant)
      └── Filialen
           └── Benutzer
```

### 3.1 Tabellen

#### Plattform-Admins (interne Verwaltung)
```
platform_admins
  - id (uuid)
  - email (unique)
  - password_hash
  - name
  - role (super_admin | support | sales)
  - created_at
  - updated_at
  - last_login_at
```

#### Fahrschulen (Mandanten)
```
tenants
  - id (uuid)
  - name
  - slug (unique, für Subdomain?)
  - email (Rechnungs-Kontakt)
  - phone
  - address
  - status (pending_approval | active | suspended | trial)
  - trial_ends_at
  - created_at
  - updated_at
  
  # Branding
  - logo_url
  - primary_color
  - secondary_color
  - custom_css (optional)
  
  # Self-Hosted
  - is_self_hosted (bool)
  - self_hosted_license_key
```

#### Filialen
```
branches
  - id (uuid)
  - tenant_id (FK)
  - name
  - address
  - phone
  - email
  - opening_hours (JSON)
  - is_headquarters (bool)
  - created_at
  - updated_at
```

#### Benutzer
```
users
  - id (uuid)
  - tenant_id (FK)
  - branch_id (FK, nullable)
  - email (unique pro Tenant)
  - password_hash
  - first_name
  - last_name
  - user_type (admin | office | instructor | lecturer | student)
  - status (active | inactive | pending)
  - avatar_url
  - phone
  - created_at
  - updated_at
  - last_login_at
```

#### Module (pro Fahrschule zuweisbar)
```
modules
  - id (uuid)
  - key (office | calendar | messenger | learning_blank | learning_premium)
  - name
  - description
  - monthly_price (cent)
  - is_active (Plattform-global)
  - created_at

tenant_modules
  - id (uuid)
  - tenant_id (FK)
  - module_id (FK)
  - status (enabled | disabled)
  - enabled_at
  - expires_at (nullable)
  - trial_ends_at (nullable)
```

#### Pakete (Preismodelle)
```
packages
  - id (uuid)
  - key (starter | professional | enterprise)
  - name
  - description
  - monthly_price (cent)
  - modules_included (JSON array von module_keys)
  - max_users
  - max_branches
  - created_at

tenant_packages
  - id (uuid)
  - tenant_id (FK)
  - package_id (FK)
  - started_at
  - expires_at
```

#### Lerninhalte (Premium-Modul)
```
learning_contents
  - id (uuid)
  - tenant_id (FK, nullable — null = Plattform-global)
  - category
  - title
  - description
  - content_type (video | document | quiz | exercise)
  - content_url
  - thumbnail_url
  - duration_minutes
  - is_premium
  - created_at
  - updated_at
```

#### Fahrschüler-Fortschritt
```
student_progress
  - id (uuid)
  - user_id (FK, student)
  - content_id (FK)
  - status (not_started | in_progress | completed)
  - completed_at
  - notes (Lehrer-Kommentare)
  - created_at
  - updated_at
```

#### Audit-Log
```
audit_logs
  - id (uuid)
  - tenant_id (FK, nullable — null für Plattform-Admin-Aktionen)
  - user_id (FK, nullable)
  - action (created | updated | deleted | login | logout | etc.)
  - entity_type (tenant | user | branch | module | etc.)
  - entity_id (UUID des betroffenen Datensatzes)
  - old_values (JSON, nullable)
  - new_values (JSON, nullable)
  - ip_address
  - user_agent
  - created_at
  
  # Index auf tenant_id + created_at für schnelle Abfragen
  # Index auf entity_type + entity_id
```

#### Rechnungen
```
invoices
  - id (uuid)
  - tenant_id (FK)
  - invoice_number (unique)
  - amount (cent)
  - vat_amount (cent)
  - total_amount (cent)
  - currency (EUR)
  - status (draft | pending | paid | overdue | cancelled)
  - billing_period_start
  - billing_period_end
  - due_date
  - paid_at (nullable)
  - created_at
  - updated_at

invoice_items
  - id (uuid)
  - invoice_id (FK)
  - description
  - quantity
  - unit_price (cent)
  - total_price (cent)
```

#### E-Mail / Notifications
```
notification_templates
  - id (uuid)
  - key (welcome | password_reset | invoice | trial_expiring | etc.)
  - subject
  - body_html
  - body_text
  - variables (JSON)
  - created_at
  - updated_at

notifications
  - id (uuid)
  - user_id (FK)
  - tenant_id (FK, nullable)
  - template_key
  - subject
  - body
  - status (pending | sent | failed)
  - sent_at
  - created_at
```

#### Dateien / Uploads / DKS (Dokumenten-Klasse-System)
```
files
  - id (uuid)
  - tenant_id (FK)
  - user_id (FK, nullable — wer hochgeladen hat)
  - entity_type (vehicle | student | instructor | branch | etc.)
  - entity_id (UUID)
  - file_type (insurance | tuv | logo | avatar | document | etc.)
  - original_filename
  - storage_path
  - mime_type
  - size_bytes
  - created_at
  
  # Dateien werden im Storage abgelegt:
  # SaaS: /storage/tenants/{tenant_id}/files/
  # Self-Hosted: /var/www/fahrschuldesk/storage/files/
```

#### Messenger (DSGVO-konform)
```
conversations
  - id (uuid)
  - tenant_id (FK)
  - type (direct | group)
  - name (nullable, nur für groups)
  - created_at
  - updated_at

conversation_participants
  - id (uuid)
  - conversation_id (FK)
  - user_id (FK)
  - joined_at
  - last_read_at

messages
  - id (uuid)
  - conversation_id (FK)
  - user_id (FK)
  - body (Verschlüsselt auf DB-Ebene)
  - is_edited (bool)
  - is_deleted (bool)
  - created_at
  - updated_at
  
  # Keine Ende-zu-Ende Verschlüsselung (Plattform hat Zugriff für Support/Audit)
  # DSGVO: Keine externen Dienste, alles auf eigenen Servern
  # Nachrichten können auf Anfrage exportiert/gelöscht werden (DSGVO-Compliance)
```

---

## 4. API-Struktur

### 4.1 Auth
```
POST   /api/auth/login                    (JWT Token)
POST   /api/auth/logout
POST   /api/auth/refresh                 (Refresh Token)
GET    /api/auth/me

POST   /api/auth/forgot-password
POST   /api/auth/reset-password
```

### 4.2 Registration (Self-Service)
```
POST   /api/auth/register                (Fahrschule registrieren)
GET    /api/auth/register/verify/:token  (E-Mail verifizieren)
```

### 4.3 Plattform-Admin (nur Admins)
```
GET    /api/admin/tenants
POST   /api/admin/tenants
GET    /api/admin/tenants/:id
PUT    /api/admin/tenants/:id
DELETE /api/admin/tenants/:id

POST   /api/admin/tenants/:id/approve     (Freigabe nach Registration)
POST   /api/admin/tenants/:id/suspend

GET    /api/admin/tenants/:id/modules
POST   /api/admin/tenants/:id/modules
DELETE /api/admin/tenants/:id/modules/:moduleId

GET    /api/admin/platform-modules
GET    /api/admin/platform-modules/:id

GET    /api/admin/invoices
GET    /api/admin/invoices/:id
PUT    /api/admin/invoices/:id/mark-paid

GET    /api/admin/audit-logs             (Plattform-weit)
GET    /api/admin/audit-logs/:id

GET    /api/admin/platform-admins
POST   /api/admin/platform-admins
PUT    /api/admin/platform-admins/:id
DELETE /api/admin/platform-admins/:id
```

### 4.4 Tenant-Admin (Fahrschule)
```
GET    /api/branches
POST   /api/branches
PUT    /api/branches/:id
DELETE /api/branches/:id

GET    /api/users
POST   /api/users
GET    /api/users/:id
PUT    /api/users/:id
DELETE /api/users/:id

GET    /api/my-modules
GET    /api/my-profile
PUT    /api/my-profile

GET    /api/audit-logs                   (Tenant-spezifisch)
GET    /api/audit-logs/:id

# Branding
PUT    /api/tenant/branding
GET    /api/tenant/branding

# Pakete
GET    /api/my-package
PUT    /api/tenant/logo
```

### 4.5 Kalender (Integration fahrschultermin.de)
```
GET    /api/calendar/events              (weiterleiten an fahrschultermin.de API)
POST   /api/calendar/events
PUT    /api/calendar/events/:id
DELETE /api/calendar/events/:id
GET    /api/calendar/availability        (Abfrage freier Slots)
```

### 4.6 Messenger
```
GET    /api/messenger/conversations
POST   /api/messenger/conversations
GET    /api/messenger/conversations/:id
POST   /api/messenger/conversations/:id/messages
GET    /api/messenger/conversations/:id/messages
PUT    /api/messenger/messages/:id       (editieren)
DELETE /api/messenger/messages/:id       (soft delete)
```

### 4.7 Lernsoftware
```
GET    /api/learning/contents
GET    /api/learning/contents/:id
GET    /api/learning/my-progress
POST   /api/learning/my-progress
PUT    /api/learning/my-progress/:contentId

# Nur für Admin / Dozenten
POST   /api/learning/contents           (Blanko: eigene Inhalte erstellen)
PUT    /api/learning/contents/:id
DELETE /api/learning/contents/:id
```

### 4.8 Dateien / DKS
```
GET    /api/files                        (Liste, gefiltert nach entity)
POST   /api/files                        (Upload)
GET    /api/files/:id
DELETE /api/files/:id
GET    /api/files/:id/download
```

### 4.9 Rechnungen (Tenant)
```
GET    /api/billing/invoices
GET    /api/billing/invoices/:id
GET    /api/billing/current-package
```

---

## 5. Rollen & Rechte

### Plattform-Admins (intern)
| Rolle | Rechte |
|---|---|
| super_admin | Alles: Tenants, Admins, Module, Settings, Invoices, Audit |
| support | Tenants einsehen/verwalten, keine Admins ändern, keine Settings |
| sales | Tenants anlegen, keine Settings, keine Admin-Verwaltung |

### Fahrschul-Benutzer
| Typ | Beschreibung |
|---|---|
| admin | Voller Zugriff auf eigene Fahrschule |
| office | Büromitarbeiter: Kunden, Kalender, Berichte |
| instructor | Fahrlehrer: Kalender, eigene Fahrschüler, DKS |
| lecturer | Dozent: Kalender, eigene Unterrichtseinheiten |
| student | Fahrschüler: Lernsoftware, eigener Fortschritt, Messenger |

### Rechte-Matrix (pro Modul)
```
user_types:
  admin:     [office:rw, calendar:rw, messenger:rw, learning:rw, files:rw]
  office:    [office:rw, calendar:r, messenger:rw, learning:r, files:r]
  instructor:[office:r, calendar:rw, messenger:rw, learning:r, files:rw]
  lecturer:  [calendar:rw, messenger:rw, learning:rw, files:r]
  student:   [calendar:r, messenger:rw, learning:rw, files:r]
```

---

## 6. Modul-System

### 6.1 Verfügbare Module

| Key | Name | Beschreibung |
|---|---|---|
| `office` | Office | Kundenverwaltung, Fahrzeugverwaltung, Berichte |
| `calendar` | Kalender | Terminplanung (Integration fahrschultermin.de) |
| `messenger` | Messenger | WhatsApp-ähnlich, DSGVO-konform |
| `learning_blank` | Lernsoftware (Blanko) | Eigene Inhalte erstellen |
| `learning_premium` | Lernsoftware (Premium) | Inkl. vorgefertigter Lerninhalte |

### 6.2 Modul-Zuordnung

- Jede Fahrschule kann Module einzeln aktivieren/deaktivieren
- Preise werden pro Modul hinterlegt
- `learning_blank` und `learning_premium` schließen sich gegenseitig aus

---

## 7. Billing & Pakete

### 7.1 Pakete (Beispiel)
| Paket | Preis/Monat | Module | Max Users | Max Filialen |
|---|---|---|---|---|
| Starter | 49€ | Office + Kalender + Messenger | 5 | 1 |
| Professional | 99€ | Alle Module (Blanko) | 20 | 3 |
| Premium | 149€ | Alle Module (Premium) | Unlimited | Unlimited |

### 7.2 Trial
- 14 Tage kostenlos testen
- Danach: Admin-Freigabe nötig
- Trial-End: E-Mail-Erinnerung 3 Tage vorher

### 7.3 Bezahlung
- PayPal (monatlich/jährlich)
- Rechnung (auf Anfrage für Enterprise)
- Automatische Mahnung bei Überfälligkeit

### 7.4 Self-Hosted
- License-Key nötig
- Keine weiteren Mandanten anlegbar (nur Filialen)
- Update-Management via License-Key

---

## 8. Registration & Freigabe

### 8.1 Self-Service Flow
```
1. Fahrschule registriert sich (Name, E-Mail, Password)
2. E-Mail-Verifizierung (Token)
3. Status: "pending_approval"
4. Admin erhält E-Mail: "Neue Registrierung"
5. Admin prüft und genehmigt (oder ablehnen)
6. Status: "active" → Fahrschule kann Login
```

### 8.2 Multi-Admin pro Fahrschule
- Erster Admin = der Registrierer
- Weitere Admin-Accounts können durch den ersten Admin angelegt werden

---

## 9. Branding & Design

### 9.1 Plattform-Defaults
- Logo, Farben, Fonts werden durch Plattform vorgegeben
- Template: Default-Theme für alle neuen Fahrschulen

### 9.2 Tenant-Branding
Jede Fahrschule kann anpassen:
- Logo (Header, E-Mails, Rechnungen)
- Primärfarbe (Buttons, Links, Akzente)
- Sekundärfarbe
- Custom CSS (optional, für fortgeschrittene Nutzer)

### 9.3 E-Mail-Branding
- Rechnungs-E-Mails mit Logo der Fahrschule
- E-Mail-Templates pro Tenant individuell

---

## 10. Audit-Log

### 10.1 Plattform-Admin Audit
- Alle Aktionen aller Tenants einsehbar
- Filterbar nach Tenant, Aktionstyp, Zeitraum

### 10.2 Tenant-Admin Audit
- Nur eigene Fahrschule
- Alle User-Aktionen geloggt
- Erfüllt DSGVO-Anforderungen

### 10.3 Was geloggt wird
- Login / Logout
- CRUD-Operationen auf alle Entitäten
- Änderungen an Benutzern, Modulen, Rechten

---

## 11. Messenger (WhatsApp-like)

### 11.1 Features
- 1:1 Chat
- Gruppen-Chat
- Nachrichten editieren/löschen
- Timestamps, Read-Receipts
- Online-Status

### 11.2 DSGVO
- Alle Daten auf eigenen Servern
- Keine externen Dienste (kein Twilio, keine Cloud-Dienste)
- Export aller Daten möglich (DSGVO-Art. 15)
- Löschen auf Anfrage (DSGVO-Art. 17)

### 11.3 Technisch
- WebSockets für Echtzeit
- Polling-Fallback wenn WebSockets nicht verfügbar
- Messages in DB verschlüsselt (für Backend-Zugriff)

---

## 12. DKS (Dokumenten-Klasse-System)

### 12.1 Dateitypen
- Fahrzeug: Versicherungsunterlagen, TÜV-Berichte, Kennzeichen
- Fahrschüler: Personalausweis, Sehtest, Erste-Hilfe-Nachweis
- Fahrlehrer: Führerschein, Lehrberechtigung
- Filiale: Mietverträge, Gewerbeanmeldung

### 12.2 Features
- Upload mit Drag & Drop
- Dateityp-Kategorisierung
- Ablage nach Entity (Fahrzeug, Student, etc.)
- Download
- Versionierung (neue Datei ersetzt alte, alte bleibt)
- Ablaufdatum-Erinnerungen (z.B. TÜV)

---

## 13. Self-Hosted Option

### 13.1 Anforderungen
- PHP 8.2+
- PostgreSQL 15+
- 4GB RAM minimum
- Ubuntu/Debian/CentOS

### 13.2 Einschränkungen
- **Keine Mandanten** anlegbar (nur die eigene Fahrschule)
- Filialen: Ja (unbegrenzt)
- User: Ja (gemäß Paket)
- Updates: Manuell via License-Key

### 13.3 Installation
- Docker-Compose für einfache Installation
- Oder klassisch via Composer + Migration

---

## 14. Frontend-Struktur (fahrschuldesk.de)

```
src/
├── views/
│   ├── auth/
│   │   ├── Login.vue
│   │   ├── Register.vue
│   │   ├── ForgotPassword.vue
│   │   └── VerifyEmail.vue
│   ├── admin/                    (Plattform-Admin)
│   │   ├── Dashboard.vue
│   │   ├── Tenants.vue
│   │   ├── TenantEdit.vue
│   │   ├── Modules.vue
│   │   ├── Invoices.vue
│   │   ├── AuditLog.vue
│   │   └── PlatformAdmins.vue
│   ├── tenant/                   (Fahrschule)
│   │   ├── Dashboard.vue
│   │   ├── Users.vue
│   │   ├── Branches.vue
│   │   ├── Office.vue           (Kunden, Fahrzeuge)
│   │   ├── Calendar.vue         (→ fahrschultermin.de)
│   │   ├── Messenger.vue
│   │   ├── Learning.vue
│   │   ├── Files.vue            (DKS)
│   │   ├── Branding.vue
│   │   └── Billing.vue
│   └── student/                  (Fahrschüler)
│       ├── Dashboard.vue
│       ├── Learning.vue
│       └── Messenger.vue
├── components/
│   ├── common/
│   │   ├── AppHeader.vue
│   │   ├── AppSidebar.vue
│   │   └── ModuleCard.vue
│   ├── messenger/
│   │   ├── ChatWindow.vue
│   │   ├── ConversationList.vue
│   │   └── MessageBubble.vue
│   ├── files/
│   │   ├── FileUploader.vue
│   │   └── FileList.vue
│   └── branding/
│       └── ColorPicker.vue
├── stores/                       (Pinia)
│   ├── auth.js
│   ├── tenant.js
│   ├── modules.js
│   └── messenger.js
├── router/
│   └── index.js
├── api/                          (Axios Client)
│   ├── client.js
│   ├── auth.js
│   ├── admin.js
│   └── tenant.js
└── styles/
    ├── variables.css
    └── theme.css
```

---

## 15. CI/CD Pipeline

```yaml
# .github/workflows/deploy.yml

name: Deploy

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: PHP Setup
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: pgsql, curl
      - name: Run Tests
        run: composer test

  deploy-api:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Sync to Server
        uses: appleboy/scp-action@master
        with:
          host: fahrschuldesk.de
          port: 2225
          username: fahrschuldesk
          key: ${{ secrets.SSH_KEY }}
          source: "api/*"
          target: "/srv/web/fahrschuldesk/domains/api.fahrschuldesk.de/public/"

  deploy-frontend:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Build Vue
        run: |
          npm ci
          npm run build
      - name: Sync to Server
        uses: appleboy/scp-action@master
        with:
          host: fahrschuldesk.de
          port: 2225
          username: fahrschuldesk
          key: ${{ secrets.SSH_KEY }}
          source: "dist/*"
          target: "/srv/web/fahrschuldesk/domains/fahrschuldesk.de/public/"
```

---

## 16. Offene Fragen / Next Steps

- [ ] Tech-Stack final abstimmen (Laravel vs. Slim vs. anderes?)
- [ ] PayPal Integration: API Keys besorgen
- [ ] Design-System erstellen (Default-Theme)
- [ ] OpenAPI Spec schreiben
- [ ] Erste Migration: Alle Tabellen
- [ ] Auth-Flow: Login + Registration + E-Mail-Verifizierung
- [ ] Messenger: WebSocket-Integration planen
- [ ] Self-Hosted: Docker-Compose vorbereiten

---

## 17. Phase 1 — Erste Schritte

### Ziel: Grundgerüst stehen

1. **DB-Schema:** Migrationen schreiben für alle Tabellen
2. **API-Skelett:** Auth + Tenant-Registration + Admin-CRUD + Module-CRUD
3. **Frontend-Skelett:** Vue 3 + Vite + Router + Pinia + TailwindCSS
4. **Login-Seite:** Plattform-Admin Login
5. **Registration:** Self-Service + Admin-Freigabe
6. **Admin-Dashboard:** Tenants auflisten, anlegen, Module zuweisen
7. **Branding:** Logo-Upload, Farben wählen
8. **Audit-Log:** Basis-Implementierung

---

## 18. Datei-Ablage (Storage)

### SaaS
```
/srv/web/fahrschuldesk/storage/
├── tenants/{tenant_id}/
│   ├── files/
│   │   ├── vehicles/
│   │   ├── students/
│   │   └── ...
│   ├── avatars/
│   └── logos/
└── backups/
```

### Self-Hosted
```
/var/www/fahrschuldesk/storage/
├── files/
├── avatars/
├── logos/
└── backups/
```