INSIGHT-MVP/packages/crm-service/Summarize.md
Thomas Reitz a13cca054b docs(crm): document Company entity for frontend developer
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>
2026-03-10 19:47:39 +01:00

6.5 KiB

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)