mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-25 09:06:40 +02:00
Update INSIGHT-CRM.md with complete Company API documentation, Contact/Deal changes (companyId, position), and frontend integration suggestions. Update Summarize.md with current test results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
138 lines
6.5 KiB
Markdown
138 lines
6.5 KiB
Markdown
# CRM-Service - Zusammenfassung
|
|
|
|
## Stand: 2026-03-10
|
|
|
|
### Was wurde erstellt
|
|
|
|
Der CRM-Service als eigenstaendiges NestJS-Package unter `packages/crm-service/`.
|
|
|
|
### Struktur
|
|
|
|
```
|
|
packages/crm-service/
|
|
package.json — Dependencies (NestJS 10, Prisma, Passport, ioredis)
|
|
tsconfig.json — Strict TypeScript
|
|
nest-cli.json — NestJS CLI Config
|
|
Dockerfile — Multi-Stage (base, deps, development, build, production)
|
|
.dockerignore — Excludes
|
|
prisma/
|
|
crm.schema.prisma — Eigenes Schema (app_crm) mit eigenem Client-Output
|
|
src/
|
|
main.ts — Bootstrap (Port 3100, Prefix: api/v1/crm, Swagger)
|
|
app.module.ts — Root Module mit globalem JwtAuthGuard + ExceptionFilter
|
|
config/ — Umgebungsvariablen-Validierung
|
|
prisma/ — CrmPrismaService (eigener Client)
|
|
redis/ — RedisService (Token-Blocklist, Cache)
|
|
auth/ — JWT Strategy (RS256), JwtAuthGuard, RolesGuard, TenantGuard
|
|
common/ — Decorators (@Public, @Roles, @CurrentUser), Pagination, ExceptionFilter
|
|
companies/ — CRUD: Unternehmen (uebergeordnete Entity)
|
|
contacts/ — CRUD: Kontakte (PERSON, ORGANIZATION) mit Company-Verknuepfung
|
|
activities/ — CRUD: Aktivitaeten (NOTE, CALL, EMAIL, MEETING, TASK)
|
|
pipelines/ — CRUD: Sales-Pipelines mit Stages (inkl. Stage-Update)
|
|
deals/ — CRUD: Vorgaenge mit Pipeline/Stage/Contact/Company-Zuordnung
|
|
```
|
|
|
|
### Datenbank-Modelle (app_crm Schema)
|
|
|
|
- **Company** — Unternehmen mit Branche, Adresse, Tags, Audit-Trail. Eltern-Entity fuer Contacts und Deals.
|
|
- **Contact** — Kontakte (Person/Organisation) mit optionaler Company-Zuordnung (companyId, position)
|
|
- **Activity** — Aktivitaeten verknuepft mit Kontakten
|
|
- **Pipeline** — Konfigurierbare Sales-Pipelines pro Tenant
|
|
- **PipelineStage** — Stufen innerhalb einer Pipeline (Name, Farbe, Reihenfolge editierbar)
|
|
- **Deal** — Vorgaenge mit Wert, Status, Pipeline/Stage/Contact/Company-Zuordnung
|
|
|
|
### Entity-Beziehungen
|
|
|
|
```
|
|
Company (1) --< (n) Contact — companyId (optional, SetNull bei Loeschung)
|
|
Company (1) --< (n) Deal — companyId (optional, SetNull bei Loeschung)
|
|
Contact (1) --< (n) Activity — contactId (Cascade bei Loeschung)
|
|
Contact (1) --< (n) Deal — contactId (optional, SetNull bei Loeschung)
|
|
Pipeline (1) --< (n) PipelineStage — pipelineId (Cascade bei Loeschung)
|
|
Pipeline (1) --< (n) Deal — pipelineId (Cascade bei Loeschung)
|
|
PipelineStage (1) --< (n) Deal — stageId
|
|
```
|
|
|
|
### API-Endpunkte
|
|
|
|
| Methode | Pfad | Beschreibung |
|
|
|---------|------|-------------|
|
|
| GET/POST | /api/v1/crm/companies | Liste / Erstellen |
|
|
| GET/PATCH/DELETE | /api/v1/crm/companies/:id | Detail / Update / Delete |
|
|
| GET/POST | /api/v1/crm/contacts | Liste / Erstellen |
|
|
| GET/PATCH/DELETE | /api/v1/crm/contacts/:id | Detail / Update / Delete |
|
|
| GET/POST | /api/v1/crm/activities | Liste / Erstellen |
|
|
| GET/PATCH/DELETE | /api/v1/crm/activities/:id | Detail / Update / Delete |
|
|
| GET/POST | /api/v1/crm/pipelines | Liste / Erstellen |
|
|
| GET/PATCH/DELETE | /api/v1/crm/pipelines/:id | Detail / Update / Delete |
|
|
| POST/DELETE | /api/v1/crm/pipelines/:id/stages | Stage hinzufuegen/entfernen |
|
|
| PATCH | /api/v1/crm/pipelines/:id/stages/:stageId | Stage bearbeiten (Name, Farbe, Reihenfolge) |
|
|
| GET/POST | /api/v1/crm/deals | Liste / Erstellen |
|
|
| GET/PATCH/DELETE | /api/v1/crm/deals/:id | Detail / Update / Delete |
|
|
| GET | /health | Health-Check (public) |
|
|
|
|
### Docker-Integration
|
|
|
|
- `docker-compose.crm.yml` im Projekt-Root
|
|
- Port: 3100
|
|
- Netzwerke: insight-web, insight-db, insight-cache
|
|
- Traefik HTTP-Route: `Host(172.20.10.59) && PathPrefix(/api/v1/crm)` mit Priority 100
|
|
- Traefik HTTPS-Route: `crm-secure` mit `entrypoints=websecure`, `tls=true`, Priority 100
|
|
- JWT Public Key als Read-Only Volume (.keys/jwt-public.pem)
|
|
- Direkte PostgreSQL-Verbindung (PgBouncer unterstuetzt kein search_path fuer Schema-Auswahl)
|
|
|
|
### Sicherheit
|
|
|
|
- JWT RS256 Validierung mit shared Public Key
|
|
- Token-Revocation via Redis (blocked:{jti})
|
|
- Multi-Tenancy: Alle Queries filtern nach tenantId
|
|
- TenantGuard sichert mandantenbezogenen Zugriff
|
|
- Globaler ValidationPipe (whitelist + forbidNonWhitelisted)
|
|
- Strict TypeScript, kein `any`
|
|
- 401 bei fehlendem/ungueltigem Token
|
|
|
|
### Deployment-Status
|
|
|
|
**Erfolgreich deployed auf insight-dev-01 (172.20.10.59) am 2026-03-10**
|
|
|
|
- Container: insight-crm (Development-Mode)
|
|
- Prisma Migrationen angewendet:
|
|
- `20260310163211_init` — Initiales Schema (Contact, Activity, Pipeline, PipelineStage, Deal)
|
|
- `20260310183117_add_companies` — Company-Entity, Contact.companyId/position, Deal.companyId
|
|
- Alle API-Endpunkte getestet und funktionsfaehig
|
|
- Traefik-Routing aktiv (HTTP + HTTPS): http(s)://172.20.10.59/api/v1/crm/*
|
|
- Swagger-Docs: http://172.20.10.59/api/v1/crm/docs/
|
|
|
|
### Getestete Endpunkte
|
|
|
|
| Test | Ergebnis |
|
|
|------|----------|
|
|
| POST /companies (Erstellen mit allen Feldern) | 200 OK, UUID + _count korrekt |
|
|
| GET /companies (Liste) | 200 OK, pagination + _count korrekt |
|
|
| GET /companies/:id (Detail) | 200 OK, contacts[] + deals[] + _count |
|
|
| PATCH /companies/:id (Update) | 200 OK, updatedBy + tags korrekt |
|
|
| GET /companies?search=Xinion | 200 OK, Suche funktioniert |
|
|
| POST /contacts (mit companyId + position) | 201 Created, Company-Verknuepfung korrekt |
|
|
| GET /contacts/:id (mit Company) | 200 OK, company-Objekt enthalten |
|
|
| POST /activities (Notiz) | 201 Created, contactId verknuepft |
|
|
| POST /pipelines (mit 4 Stages) | 201 Created, Stages korrekt |
|
|
| PATCH /pipelines/:id/stages/:stageId | 200 OK, Stage-Update korrekt |
|
|
| POST /deals (mit companyId + contactId) | 200 OK, Company + Contact verknuepft |
|
|
| GET /deals/:id (mit Company) | 200 OK, company + pipeline.stages enthalten |
|
|
| GET /deals?companyId=... | 200 OK, Filter nach Company funktioniert |
|
|
| PATCH /deals/:id (WON) | 200 OK, closedAt automatisch gesetzt |
|
|
| GET /contacts ohne Token | 401 Unauthorized |
|
|
| Validierung (falsche Felder) | 400 Bad Request, Details korrekt |
|
|
|
|
### Bekannte Einschraenkungen
|
|
|
|
- PgBouncer kann nicht genutzt werden (search_path nicht kompatibel mit transaction pooling)
|
|
|
|
### Naechste Schritte
|
|
|
|
1. Frontend: Company-Modul (Seiten, Formulare, Sidebar-Link)
|
|
2. Frontend: Contact/Deal-Formulare um Company-Selektor erweitern
|
|
3. Activity-Liste komplett laden (UI-Button "Alle anzeigen")
|
|
4. Kanban-Board fuer Vorgaenge (Drag & Drop Stage-Wechsel)
|
|
5. E2E-Tests schreiben
|
|
6. Production-Build testen (multi-stage Dockerfile)
|