- README with project overview - TDD (Technical Design Document) - AI Council Review with critical analysis - User Stories (27 stories, 120 SP) - Architecture documentation Stack: NestJS + React + PostgreSQL + Redis Server: waldseilgarten (85.199.86.188)
460 lines
12 KiB
Markdown
460 lines
12 KiB
Markdown
# Technical Design Document (TDD)
|
|
# Waldseilgarten Herrenberg CRM
|
|
|
|
**Version:** 1.0
|
|
**Datum:** 2026-03-14
|
|
**Autor:** AI-Assistent (Henry)
|
|
**Status:** Entwurf
|
|
|
|
---
|
|
|
|
## 1. Executive Summary
|
|
|
|
### 1.1 Ziel
|
|
Entwicklung eines modernen CRM- und Projektmanagementsystems für den Waldseilgarten Herrenberg mit Fokus auf:
|
|
- Kunden- und Kontaktverwaltung
|
|
- Projekt-Tracking
|
|
- Dokumentenmanagement
|
|
- E-Mail-Integration
|
|
|
|
### 1.2 Tech Stack
|
|
| Schicht | Technologie |
|
|
|---------|-------------|
|
|
| Backend | NestJS (Node.js 22) |
|
|
| Frontend | React 19 + Vite |
|
|
| Datenbank | PostgreSQL 18 |
|
|
| Cache | Redis 7 |
|
|
| Container | Podman |
|
|
| Proxy | Traefik |
|
|
|
|
### 1.3 Architekturprinzipien
|
|
- **Modularität:** Klare Trennung in Feature-Module
|
|
- **Type-Safety:** TypeScript durchgehend
|
|
- **API-First:** REST API als zentrale Schnittstelle
|
|
- **Containerized:** Vollständig containerisiert
|
|
|
|
---
|
|
|
|
## 2. Systemarchitektur
|
|
|
|
### 2.1 High-Level Architektur
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Client │
|
|
│ (React + Vite) │
|
|
└───────────────────────┬─────────────────────────────────────┘
|
|
│ HTTPS
|
|
┌───────────────────────▼─────────────────────────────────────┐
|
|
│ Traefik │
|
|
│ (Reverse Proxy + SSL) │
|
|
└───────────────────────┬─────────────────────────────────────┘
|
|
┌───────────────┼───────────────┐
|
|
▼ ▼ ▼
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│ Frontend │ │ Backend │ │ Worker │
|
|
│ (nginx) │ │ (NestJS) │ │ (IMAP) │
|
|
│ :3000 │ │ :3001 │ │ │
|
|
└──────────────┘ └──────┬───────┘ └──────────────┘
|
|
│
|
|
┌───────────────┼───────────────┐
|
|
▼ ▼ ▼
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│ PostgreSQL │ │ Redis │ │ Local │
|
|
│ (DB) │ │ (Cache) │ │ Storage │
|
|
│ :5432 │ │ :6379 │ │ │
|
|
└──────────────┘ └──────────────┘ └──────────────┘
|
|
```
|
|
|
|
### 2.2 Backend-Module
|
|
|
|
```
|
|
backend/src/
|
|
├── auth/ # Phase 1: Authentifizierung
|
|
├── customers/ # Phase 1: Kundenverwaltung
|
|
├── projects/ # Phase 1: Projektmanagement
|
|
├── dashboard/ # Phase 1: Statistiken
|
|
├── documents/ # Phase 2: Dokumentenverwaltung
|
|
├── tasks/ # Phase 3: Aufgabenmanagement
|
|
├── email/ # Phase 4: E-Mail-Integration
|
|
├── calendar/ # Phase 5: Google Calendar
|
|
└── common/ # Shared Utilities
|
|
```
|
|
|
|
### 2.3 Datenbank-Schema (Phase 1)
|
|
|
|
```sql
|
|
-- Users
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
first_name VARCHAR(100),
|
|
last_name VARCHAR(100),
|
|
role VARCHAR(20) DEFAULT 'user',
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Customers
|
|
CREATE TABLE customers (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
company_name VARCHAR(255) NOT NULL,
|
|
industry VARCHAR(100),
|
|
website VARCHAR(255),
|
|
phone VARCHAR(50),
|
|
email VARCHAR(255),
|
|
address TEXT,
|
|
notes TEXT,
|
|
tags TEXT[],
|
|
created_by UUID REFERENCES users(id),
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Contacts (Ansprechpartner)
|
|
CREATE TABLE contacts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
customer_id UUID REFERENCES customers(id) ON DELETE CASCADE,
|
|
first_name VARCHAR(100) NOT NULL,
|
|
last_name VARCHAR(100) NOT NULL,
|
|
email VARCHAR(255),
|
|
phone VARCHAR(50),
|
|
position VARCHAR(100),
|
|
is_primary BOOLEAN DEFAULT false,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Projects
|
|
CREATE TABLE projects (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
customer_id UUID REFERENCES customers(id) ON DELETE SET NULL,
|
|
status VARCHAR(50) DEFAULT 'new',
|
|
priority VARCHAR(20) DEFAULT 'medium',
|
|
start_date DATE,
|
|
end_date DATE,
|
|
budget DECIMAL(12,2),
|
|
created_by UUID REFERENCES users(id),
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Project Members
|
|
CREATE TABLE project_members (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
|
|
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
role VARCHAR(50) DEFAULT 'member',
|
|
joined_at TIMESTAMP DEFAULT NOW(),
|
|
UNIQUE(project_id, user_id)
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 3. API-Design
|
|
|
|
### 3.1 Authentication
|
|
|
|
```typescript
|
|
// POST /api/auth/login
|
|
interface LoginRequest {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
interface LoginResponse {
|
|
access_token: string;
|
|
user: {
|
|
id: string;
|
|
email: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
role: string;
|
|
};
|
|
}
|
|
|
|
// POST /api/auth/register
|
|
interface RegisterRequest {
|
|
email: string;
|
|
password: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
}
|
|
```
|
|
|
|
### 3.2 Customers
|
|
|
|
```typescript
|
|
// GET /api/customers
|
|
interface ListCustomersQuery {
|
|
page?: number;
|
|
limit?: number;
|
|
search?: string;
|
|
industry?: string;
|
|
tags?: string[];
|
|
}
|
|
|
|
// POST /api/customers
|
|
interface CreateCustomerRequest {
|
|
company_name: string;
|
|
industry?: string;
|
|
website?: string;
|
|
phone?: string;
|
|
email?: string;
|
|
address?: string;
|
|
notes?: string;
|
|
tags?: string[];
|
|
}
|
|
|
|
// GET /api/customers/:id
|
|
interface CustomerResponse {
|
|
id: string;
|
|
company_name: string;
|
|
industry?: string;
|
|
website?: string;
|
|
phone?: string;
|
|
email?: string;
|
|
address?: string;
|
|
notes?: string;
|
|
tags: string[];
|
|
contacts: Contact[];
|
|
projects: ProjectSummary[];
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
```
|
|
|
|
### 3.3 Projects
|
|
|
|
```typescript
|
|
// POST /api/projects
|
|
interface CreateProjectRequest {
|
|
name: string;
|
|
description?: string;
|
|
customer_id?: string;
|
|
status?: 'new' | 'active' | 'on_hold' | 'completed' | 'cancelled';
|
|
priority?: 'low' | 'medium' | 'high' | 'urgent';
|
|
start_date?: string;
|
|
end_date?: string;
|
|
budget?: number;
|
|
}
|
|
|
|
// GET /api/projects/:id
|
|
interface ProjectResponse {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
customer?: CustomerSummary;
|
|
status: string;
|
|
priority: string;
|
|
start_date?: string;
|
|
end_date?: string;
|
|
budget?: number;
|
|
members: ProjectMember[];
|
|
documents_count: number;
|
|
tasks_count: number;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Sicherheit
|
|
|
|
### 4.1 Authentifizierung
|
|
- JWT-based Authentication
|
|
- Access Token: 24h Gültigkeit
|
|
- Refresh Token: 7 Tage Gültigkeit (optional)
|
|
- bcrypt für Passwort-Hashing (10 rounds)
|
|
|
|
### 4.2 Autorisierung
|
|
- Rollenbasierte Zugriffskontrolle (RBAC)
|
|
- Rollen: `admin`, `manager`, `user`
|
|
- Guards auf Controller-Ebene
|
|
|
|
### 4.3 Datenschutz
|
|
- HTTPS enforced
|
|
- SQL Injection Prevention (TypeORM)
|
|
- XSS Prevention (React escaping)
|
|
- CSRF Protection
|
|
|
|
---
|
|
|
|
## 5. Deployment
|
|
|
|
### 5.1 Container-Setup
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:18-alpine
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
POSTGRES_DB: ${POSTGRES_DB}
|
|
volumes:
|
|
- ./data/db:/var/lib/postgresql/data
|
|
networks:
|
|
- crm-network
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
command: redis-server --requirepass ${REDIS_PASSWORD}
|
|
volumes:
|
|
- ./data/redis:/data
|
|
networks:
|
|
- crm-network
|
|
|
|
backend:
|
|
build: ./backend
|
|
environment:
|
|
NODE_ENV: production
|
|
POSTGRES_HOST: postgres
|
|
REDIS_HOST: redis
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.crm-api.rule=Host(`api.crm.waldseilgarten-herrenberg.de`)"
|
|
networks:
|
|
- crm-network
|
|
|
|
frontend:
|
|
build: ./frontend
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.crm-frontend.rule=Host(`crm.waldseilgarten-herrenberg.de`)"
|
|
networks:
|
|
- crm-network
|
|
|
|
networks:
|
|
crm-network:
|
|
driver: bridge
|
|
```
|
|
|
|
### 5.2 Traefik-Konfiguration
|
|
|
|
```yaml
|
|
# traefik/dynamic/crm.yml
|
|
http:
|
|
routers:
|
|
crm-api:
|
|
rule: "Host(`api.waldseilgarten-herrenberg.de`)"
|
|
service: crm-api
|
|
entryPoints:
|
|
- websecure
|
|
tls:
|
|
certResolver: le
|
|
|
|
crm-frontend:
|
|
rule: "Host(`waldseilgarten-herrenberg.de`)"
|
|
service: crm-frontend
|
|
entryPoints:
|
|
- websecure
|
|
tls:
|
|
certResolver: le
|
|
|
|
services:
|
|
crm-api:
|
|
loadBalancer:
|
|
servers:
|
|
- url: "http://waldseilgarten-backend:3001"
|
|
|
|
crm-frontend:
|
|
loadBalancer:
|
|
servers:
|
|
- url: "http://waldseilgarten-frontend:3000"
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Testing
|
|
|
|
### 6.1 Test-Strategie
|
|
- **Unit Tests:** Jest für Services
|
|
- **Integration Tests:** Supertest für API
|
|
- **E2E Tests:** Playwright für Frontend
|
|
|
|
### 6.2 Test-Abdeckung
|
|
- Mindestens 80% für kritische Pfade
|
|
- Auth-Flows vollständig testen
|
|
- API-Endpunkte validieren
|
|
|
|
---
|
|
|
|
## 7. Monitoring & Logging
|
|
|
|
### 7.1 Logging
|
|
- Structured Logging (Winston)
|
|
- Log-Level: ERROR, WARN, INFO, DEBUG
|
|
- Request-Logging via Middleware
|
|
|
|
### 7.2 Health Checks
|
|
```
|
|
GET /api/health
|
|
{
|
|
"status": "healthy",
|
|
"database": "connected",
|
|
"cache": "connected",
|
|
"version": "1.0.0"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Nicht-funktionale Anforderungen
|
|
|
|
| Anforderung | Ziel |
|
|
|-------------|------|
|
|
| Performance | API-Response < 200ms (p95) |
|
|
| Verfügbarkeit | 99.9% Uptime |
|
|
| Skalierung | Horizontal skalierbar |
|
|
| Backup | Tägliche DB-Backups |
|
|
| Wartung | Zero-Downtime Deployments |
|
|
|
|
---
|
|
|
|
## 9. Risiken & Mitigation
|
|
|
|
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|
|
|--------|-------------------|--------|------------|
|
|
| IMAP-Integration komplex | Hoch | Mittel | Frühes Proof-of-Concept |
|
|
| SeaDrive-Kompatibilität | Mittel | Mittel | Fallback zu lokalem Storage |
|
|
| Performance bei vielen Dokumenten | Mittel | Hoch | Pagination, Lazy Loading |
|
|
| Browser-Kompatibilität | Niedrig | Niedrig | Moderne Browser voraussetzen |
|
|
|
|
---
|
|
|
|
## 10. Nächste Schritte
|
|
|
|
1. **Setup** (Tag 1)
|
|
- Repository initialisieren
|
|
- Docker-Compose Setup
|
|
- Datenbank-Migrations
|
|
|
|
2. **Phase 1: Auth** (Tag 2-3)
|
|
- Login/Register API
|
|
- JWT-Implementation
|
|
- Frontend Auth-Flow
|
|
|
|
3. **Phase 1: Kunden** (Tag 4-5)
|
|
- CRUD API
|
|
- Frontend Forms
|
|
- Listen-View
|
|
|
|
4. **Review** (Tag 6)
|
|
- Code Review
|
|
- Testing
|
|
- Deployment auf Staging
|
|
|
|
---
|
|
|
|
**Ende des TDD**
|