opencrm/README.md

369 lines
11 KiB
Markdown

# OpenCRM
Web-basiertes CRM-System für Kundenverwaltung mit Verträgen (Energie, Telekommunikation, KFZ-Versicherung).
## Features
- **Kundenverwaltung**: Privat- und Geschäftskunden mit Stammdaten
- **Adressen**: Mehrere Liefer-/Melde- und Rechnungsadressen pro Kunde
- **Bankkarten**: Mit Ablaufdatum, Aktiv-Status und Dokument-Upload (PDF)
- **Ausweise**: Personalausweis, Reisepass, etc. mit Ablaufdatum und Dokument-Upload (PDF)
- **Zähler**: Strom-/Gaszähler mit Zählerstandhistorie
- **Verträge**:
- Energie (Strom, Gas)
- Telekommunikation (DSL, Glasfaser, Mobilfunk, TV)
- KFZ-Versicherung
- **Folgeverträge**: Automatische Datenübernahme bei Anbieterwechsel
- **Vertriebsplattformen**: Verwaltbar über WebUI
- **Email-Provisionierung**: Automatische E-Mail-Weiterleitung bei Plesk/cPanel/DirectAdmin
- **Berechtigungssystem**: Admin, Mitarbeiter, Nur-Lesen, Kundenportal
- **Verschlüsselte Zugangsdaten**: Portal-Passwörter AES-256-GCM verschlüsselt
- **Developer-Tools**: Datenbank-Browser und interaktives ER-Diagramm
## Tech Stack
- **Frontend**: React 18, TypeScript, Tailwind CSS, React Query
- **Backend**: Node.js, Express 4.x, TypeScript
- **Datenbank**: MariaDB
- **ORM**: Prisma
- **Auth**: JWT mit Rollen-basierter Zugriffskontrolle
> **Hinweis zu Express 5:** Das Projekt verwendet bewusst Express 4.x (nicht 5.x). Express 5 ist seit Jahren in der Beta-Phase und noch nicht offiziell stable. Bei der Installation darauf achten, dass `@types/express` zur Express-Version passt:
> - Express 4.x → `@types/express@^4.17.x`
> - Express 5.x → `@types/express@^5.x` (erst bei offiziellem Release empfohlen)
## Voraussetzungen
- Node.js 18+ (empfohlen: 20+)
- Docker & Docker Compose
- npm
## Installation
### 1. Repository klonen
```bash
git clone <repository-url>
cd opencrm
```
### 2. MariaDB-Datenbank starten
```bash
docker-compose up -d
```
Dies startet einen MariaDB-Container mit:
- **Port:** 3306
- **Datenbank:** opencrm
- **Root-Passwort:** rootpassword
- **Benutzer:** opencrm / opencrm123
Warte ca. 10 Sekunden bis die Datenbank bereit ist.
### 3. Backend einrichten
```bash
cd backend
# Dependencies installieren
npm install
# .env-Datei erstellen (falls noch nicht vorhanden)
cp .env.example .env
```
Die `.env`-Datei sollte folgende Werte enthalten:
```env
# Database
DATABASE_URL="mysql://root:rootpassword@localhost:3306/opencrm"
# JWT
JWT_SECRET="change-this-to-a-very-long-random-secret-in-production"
JWT_EXPIRES_IN="7d"
# Encryption (for portal credentials) - generate with: openssl rand -hex 32
ENCRYPTION_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
# Server
PORT=3001
NODE_ENV=development
```
### 4. Datenbank initialisieren
```bash
# Prisma Client generieren und Migrationen ausführen
npx prisma migrate dev
# Seed-Daten einspielen (Admin-User, Rollen, Berechtigungen)
npm run db:seed
```
### 5. Frontend einrichten
```bash
cd ../frontend
# Dependencies installieren
npm install
```
## Anwendung starten
### Backend starten (Terminal 1)
```bash
cd backend
npm run dev
```
Das Backend läuft auf `http://localhost:3001`
### Frontend starten (Terminal 2)
```bash
cd frontend
npm run dev
```
Das Frontend läuft auf `http://localhost:5173`
## Erster Login
Nach dem Seed sind folgende Zugangsdaten verfügbar:
- **E-Mail:** admin@admin.com
- **Passwort:** admin
## Developer-Tools aktivieren
Die Developer-Tools (Datenbankstruktur, ER-Diagramm) sind standardmäßig für Admins verfügbar. Falls der Menüpunkt nicht erscheint:
1. Einmalig im Browser-Console ausführen:
```javascript
fetch('/api/developer/setup', { method: 'POST' })
```
2. Ausloggen und neu einloggen
Alternativ können Developer-Rechte pro Benutzer vergeben werden:
- Benutzer bearbeiten > "Entwicklerzugriff" aktivieren
## Email-Provisionierung
Das System unterstützt die automatische Erstellung von E-Mail-Weiterleitungen auf Hosting-Servern für Stressfrei-Wechseln Adressen.
### Unterstützte Provider
- **Plesk** (implementiert)
- **cPanel** (vorbereitet)
- **DirectAdmin** (vorbereitet)
### Konfiguration
1. **Einstellungen****Email-Provisionierung** öffnen
2. Neuen Provider hinzufügen:
- **Name**: Bezeichnung (z.B. "Plesk Hauptserver")
- **Typ**: Plesk/cPanel/DirectAdmin
- **API-URL**: Server-URL (z.B. `https://server.de:8443`)
- **Benutzername/Passwort**: API-Zugangsdaten
- **Domain**: E-Mail-Domain (z.B. `stressfrei-wechseln.de`)
- **Standard-Weiterleitung**: Zusätzliche Weiterleitungsadresse (optional)
3. Provider als "Standard" und "Aktiv" markieren
4. Verbindung testen
### Verwendung
Beim Anlegen einer Stressfrei-Wechseln Adresse im Kundenbereich erscheint die Checkbox **"Beim E-Mail-Provider anlegen"**, wenn:
- Ein aktiver Standard-Provider konfiguriert ist
- Der Kunde eine E-Mail-Adresse hat
Bei aktivierter Checkbox wird automatisch:
1. Geprüft, ob die E-Mail-Adresse bereits existiert
2. Falls nicht: E-Mail-Adresse beim Provider angelegt mit Weiterleitung an:
- Kunden-E-Mail-Adresse
- Standard-Weiterleitungsadresse (falls konfiguriert)
## Befehle
### Backend
```bash
npm run dev # Entwicklungsserver starten
npm run build # Produktions-Build erstellen
npm run db:studio # Prisma Studio (Datenbank-GUI)
npm run db:migrate # Neue Migration erstellen
npm run db:seed # Seed erneut ausführen
```
### Frontend
```bash
npm run dev # Entwicklungsserver starten
npm run build # Produktions-Build erstellen
npm run preview # Build-Vorschau
```
### Docker
```bash
docker-compose up -d # Container starten
docker-compose down # Container stoppen
docker-compose down -v # Container stoppen + Daten löschen
docker-compose logs -f # Logs anzeigen
```
## Projektstruktur
```
opencrm/
├── backend/
│ ├── src/
│ │ ├── controllers/ # Request-Handler
│ │ ├── middleware/ # Auth, Validation
│ │ ├── routes/ # API-Endpunkte
│ │ ├── services/ # Business-Logik
│ │ ├── types/ # TypeScript-Typen
│ │ └── index.ts # Server-Einstiegspunkt
│ ├── prisma/
│ │ ├── schema.prisma # Datenbank-Schema
│ │ └── seed.ts # Seed-Daten
│ ├── uploads/ # Hochgeladene Dokumente
│ │ ├── bank-cards/ # Bankkarten-Dokumente
│ │ ├── documents/ # Ausweis-Scans
│ │ ├── business-registrations/ # Gewerbeanmeldungen
│ │ ├── commercial-registers/ # Handelsregisterauszüge
│ │ ├── privacy-policies/ # Datenschutzerklärungen
│ │ ├── cancellation-letters/ # Kündigungsschreiben
│ │ ├── cancellation-confirmations/ # Kündigungsbestätigungen
│ │ └── cancellation-*-options/ # Kündigungsdokumente Optionen
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/ # UI-Komponenten
│ │ ├── pages/ # Seiten
│ │ ├── hooks/ # Custom Hooks
│ │ ├── services/ # API-Client
│ │ ├── types/ # TypeScript-Typen
│ │ └── App.tsx # Haupt-Komponente
│ └── package.json
├── docker-compose.yml # MariaDB-Container
└── README.md
```
## Berechtigungen
| Rolle | Kunden | Verträge | Benutzer | Plattformen | Developer |
|-------|--------|----------|----------|-------------|-----------|
| Admin | CRUD | CRUD | CRUD | CRUD | Optional |
| Mitarbeiter | CRUD | CRUD | - | Lesen | - |
| Mitarbeiter (Lesen) | Lesen | Lesen | - | Lesen | - |
| Kunde | Eigene | Eigene | - | - | - |
## Troubleshooting
### Datenbank-Verbindungsfehler
1. Prüfe ob Container läuft: `docker ps`
2. Prüfe die DATABASE_URL in `.env`
3. Warte nach Container-Start ca. 10 Sekunden
### Prisma-Fehler
```bash
# Prisma Client neu generieren
npx prisma generate
# Schema zur Datenbank pushen (ohne Migration)
npx prisma db push
```
### Port bereits belegt
- Backend: `PORT` in `.env` ändern
- Frontend: In `vite.config.ts` anpassen
### Developer-Menü fehlt
```bash
# In der Browser-Console:
fetch('/api/developer/setup', { method: 'POST' }).then(r => r.json()).then(console.log)
# Danach ausloggen und neu einloggen
```
## Geplante Features
### E-Mail-Client Integration
Ein integrierter E-Mail-Client pro Kunde mit den folgenden Funktionen:
#### Konzept
- **E-Mail-Tab in Kundenansicht**: Zeigt alle E-Mails des Kunden via IMAP an
- **Mehrere E-Mail-Konten**: Dropdown zur Auswahl zwischen verschiedenen `@stressfrei-wechseln.de` Adressen des Kunden
- **E-Mails schreiben**: Neue E-Mails verfassen und Antworten auf bestehende E-Mails
- **Versand vom ausgewählten Konto**: SMTP-Versand über die gewählte Stressfrei-Wechseln Adresse
- **Zuordnung zu Verträgen**: Manuelles Zuordnen von E-Mails zu Verträgen
- **E-Mail-Tab in Vertragsansicht**: Zeigt nur dem Vertrag zugeordnete E-Mails (Postfach-Ansicht), mit Antworten/Schreiben-Funktion
#### Technische Umsetzung
1. **IMAP/SMTP-Zugangsdaten speichern**
- Beim Erstellen einer StressfreiEmail werden die Zugangsdaten vom Email-Provider (Plesk) zurückgegeben
- Diese werden verschlüsselt in der Datenbank gespeichert (wie bereits bei Portal-Zugangsdaten)
- StressfreiEmail-Tabelle erweitern um: `imapServer`, `imapPort`, `smtpServer`, `smtpPort`, `emailPassword` (verschlüsselt)
2. **Backend: IMAP-Service**
- IMAP-Client zum Abrufen von E-Mails (z.B. `imap-simple` oder `imapflow`)
- Endpunkte:
- `GET /api/customers/:id/emails` - E-Mails für Kunde abrufen
- `GET /api/emails/:id` - Einzelne E-Mail mit Body
- `POST /api/emails/send` - E-Mail senden (SMTP)
- `PUT /api/emails/:id/assign` - E-Mail einem Vertrag zuordnen
3. **Frontend: E-Mail-Tab (Kundenansicht)**
- Neuer Tab in CustomerDetail: "E-Mails"
- Dropdown oben: Auswahl der StressfreiEmail-Adresse
- Liste der E-Mails (Betreff, Absender, Datum)
- Detail-Ansicht beim Klick
- "Neue E-Mail" und "Antworten" Buttons
- "Vertrag zuordnen" Dropdown in E-Mail-Detail
4. **Frontend: E-Mail-Tab (Vertragsansicht)**
- Neuer Tab in ContractDetail: "E-Mails"
- Zeigt nur E-Mails die diesem Vertrag zugeordnet sind
- Gleiche Funktionalität wie in Kundenansicht:
- Liste der zugeordneten E-Mails
- Detail-Ansicht beim Klick
- "Neue E-Mail" und "Antworten" Buttons
- Versand erfolgt über die StressfreiEmail-Adresse des Kunden
5. **Datenbank**
```prisma
model CustomerEmail {
id Int @id @default(autoincrement())
customerId Int
customer Customer @relation(...)
stressfreiEmailId Int
stressfreiEmail StressfreiEmail @relation(...)
contractId Int? // Optionale Zuordnung zu Vertrag
contract Contract? @relation(...)
messageId String @unique // IMAP Message-ID
subject String
fromAddress String
toAddress String
date DateTime
isRead Boolean @default(false)
folder String // INBOX, Sent, etc.
createdAt DateTime @default(now())
}
```
#### Status
- [ ] Noch nicht implementiert - Plan für zukünftige Version
## Lizenz
MIT