# 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 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