INSIGHT-MVP/packages/crm-service/Summarize.md
Thomas Reitz 63cb05d4d8 feat(crm): Phase 2.2-2.4 backend + contract files — vollständige CRM-Service Implementierung
- Phase 2.3 Forecast: probability-Feld in PipelineStage, GET /crm/deals/forecast Endpoint
- Phase 2.2 Import: ImportModule mit preview/execute/history Endpoints (CSV, XLSX, vCard)
- Phase 2.4 Enrichment: EnrichmentModule mit /enrich + /settings/integrations/north-data
- Contracts: ContractsModule mit CRUD + File-Upload Endpoints (Multer, max 25MB)
- Migrations: 20260312_contract_files, 20260312_phase23_forecast
- docker-compose.crm.yml: uploads Volume für Vertragsdokumente

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 22:06:58 +01:00

14 KiB

CRM-Service - Zusammenfassung

Stand: 2026-03-12

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, @nestjs/axios, @nestjs/schedule)
  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
    migrations/         — SQL-Migrationen
  src/
    main.ts             — Bootstrap (Port 3100, Prefix: api/v1/crm, Swagger)
    app.module.ts       — Root Module mit globalem JwtAuthGuard + ExceptionFilter + ScheduleModule
    config/             — Umgebungsvariablen-Validierung (inkl. LEXWARE_*, NORTH_DATA_*)
    prisma/             — CrmPrismaService (eigener Client)
    redis/              — RedisService (Token-Blocklist, Cache, Distributed Locks)
    auth/               — JWT Strategy (RS256), JwtAuthGuard, RolesGuard, TenantGuard
    common/             — Decorators (@Public, @Roles, @CurrentUser), Pagination, ExceptionFilter, Shared DTOs (contact-info, owner)
    custom-fields/      — Custom Fields System (Phase 2.1): Definitionen + Werte CRUD, Entity-Integration
    companies/          — CRUD: Unternehmen (Multi-Value emails/phones, Owner m:n, Status, Lexware ERP-Push, Custom Fields)
    contacts/           — CRUD: Kontakte (Multi-Value emails/phones, Owner m:n, Status, Events, Custom Fields)
    activities/         — CRUD: Aktivitaeten (NOTE, CALL, EMAIL, MEETING, TASK, FOLLOWUP; contactId+companyId optional)
    pipelines/          — CRUD: Sales-Pipelines mit Stages (inkl. Stage-Update, probability)
    deals/              — CRUD: Vorgaenge mit Pipeline/Stage/Contact/Company + DealVouchers + LostReason + Owner m:n + Events + Custom Fields + Forecast
    import/             — CSV/Excel Import (Phase 2.2): Preview + Execute, Duplikat-Erkennung, GDPR Temp-File-Loesung
    enrichment/         — Datenanreicherung (Phase 2.4): Unternehmensregister.de + North Data API, Suggestion-Only
    contracts/          — CRUD: Vertraege (nested unter /companies/:id/contracts, Status DRAFT/ACTIVE/EXPIRED/CANCELLED) + Datei-Upload (PDF/Word/Excel, max 25MB, max 10 pro Vertrag)
    owners/             — Shared Owner-Service (Contact/Company/Deal Owners, Upsert, Rollen)
    events/             — CRM Event Publisher (Redis Pub/Sub) + Activity Due-Soon Scheduler
    industries/         — CRUD: Branchen (admin-konfigurierbar, mit Farbe)
    account-types/      — CRUD: Kontotypen (admin-konfigurierbar)
    relationship-types/ — CRUD: Beziehungstypen (admin-konfigurierbar)
    company-relationships/ — Company-zu-Company Beziehungen (N:M, bidirektional)
    health/             — Health-Check (DB, Redis, Lexware, Enrichment)
    lexware/            — Lexware Office Integration
      lexware.module.ts              — Feature Module (HttpModule + ScheduleModule)
      lexware-client.service.ts      — Rate-limitierter HTTP Client (Token Bucket, 2 req/s)
      lexware-contacts.service.ts    — Kontakt-Suche, Link, Import, Push, Sync
      lexware-vouchers.service.ts    — Beleg-Abruf, Cache, Deal-Verknuepfung
      lexware-sync.service.ts        — Cron-Jobs (Beleg-Sync 4h, ERP-Push 30min)
      lexware-contacts.controller.ts — REST Endpoints Kontakt-Operationen
      lexware-vouchers.controller.ts — REST Endpoints Beleg-Operationen
      dto/                           — Validierungs-DTOs
      interfaces/                    — TypeScript Interfaces fuer Lexware API
      utils/
        rate-limiter.ts              — Token Bucket (max 2, 2/s Refill)
        lexware-mapper.ts            — Bidirektionales Mapping CRM <-> Lexware

Datenbank-Modelle (app_crm Schema)

  • Company — Unternehmen mit industryId, accountTypeId, Multi-Value emails/phones, Owner m:n, EntityStatus, vatId/taxId/tradeRegisterNumber/companySize, Lexware-Verknuepfung
  • Contact — Kontakte mit Multi-Value emails/phones, Owner m:n, EntityStatus, linkedinUrl/birthday/source/department, Lexware-Verknuepfung
  • Activity — Aktivitaeten verknuepft mit Kontakten UND/ODER Companies (contactId + companyId beide optional, min. 1) + FOLLOWUP-Typ
  • Pipeline — Konfigurierbare Sales-Pipelines pro Tenant
  • PipelineStage — Stufen innerhalb einer Pipeline (+ probability Decimal(3,2) fuer Forecast)
  • Deal — Vorgaenge mit dealVouchers-Relation, Owner m:n, LostReason/LostReasonText, Events
  • ContactEmail — Multi-Value E-Mail-Adressen (Contact/Company, Typ: WORK/PERSONAL/OTHER)
  • ContactPhone — Multi-Value Telefonnummern (Contact/Company, Typ: OFFICE/MOBILE/FAX)
  • ContactOwner — Owner m:n fuer Contacts (Rollen: OWNER/MEMBER/WATCHER)
  • CompanyOwner — Owner m:n fuer Companies
  • DealOwner — Owner m:n fuer Deals
  • Industry — Admin-konfigurierbare Branchen mit Farbe (unique pro Tenant)
  • AccountType — Admin-konfigurierbare Kontotypen (unique pro Tenant)
  • RelationshipType — Admin-konfigurierbare Beziehungstypen (unique pro Tenant)
  • CompanyRelationship — N:M Company-zu-Company Beziehungen mit Typ und Notizen
  • Contract — Vertraege mit title, status (DRAFT/ACTIVE/EXPIRED/CANCELLED), startDate, endDate, value (Decimal 15,2), currency, notes; Company-Relation (Cascade)
  • ContractFile — Vertragsdokumente (PDF/Word/Excel), originalName, storagePath, mimeType, size; Contract-Relation (Cascade)
  • LexwareVoucher — Gecachte Belege aus Lexware Office
  • DealVoucher — Join-Table Deal <-> Beleg (m:n mit Audit-Trail)
  • CustomFieldDef — Benutzerdefinierte Feld-Definitionen (Phase 2.1): entityType, name (Slug), label, fieldType, options (JSONB), isRequired, position. Unique: [tenantId, entityType, name]
  • CustomFieldValue — Gespeicherte Werte (Phase 2.1): fieldDefId, entityId (generisch), valueText/valueNumber/valueDate/valueBoolean/valueJson. Unique: [fieldDefId, entityId]. CASCADE Delete bei Definition-Loeschung

Entity-Beziehungen

Company (1) --< (n) Contact              — companyId (optional, SetNull)
Company (1) --< (n) Deal                 — companyId (optional, SetNull)
Company (1) --< (n) Activity             — companyId (optional, SetNull)
Company (1) --< (n) LexwareVoucher       — companyId (optional, SetNull)
Company (n) >--< (n) Company             — via CompanyRelationship (bidirektional)
Company (1) --< (n) Contract             — companyId (Cascade)
Company (n) -->  (1) Industry            — industryId (optional, SetNull)
Company (n) -->  (1) AccountType         — accountTypeId (optional, SetNull)
Contact (1) --< (n) Activity             — contactId (optional, SetNull)
Contact (1) --< (n) Deal                 — contactId (optional, SetNull)
Contact (1) --< (n) LexwareVoucher       — contactId (optional, SetNull)
Pipeline (1) --< (n) PipelineStage       — pipelineId (Cascade)
Pipeline (1) --< (n) Deal                — pipelineId (Cascade)
PipelineStage (1) --< (n) Deal           — stageId
Deal (1) --< (n) DealVoucher             — dealId (Cascade)
LexwareVoucher (1) --< (n) DealVoucher   — voucherId (Cascade)
RelationshipType (1) --< (n) CompanyRelationship — relationshipTypeId
CustomFieldDef (1) --< (n) CustomFieldValue     — fieldDefId (Cascade)

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
POST /api/v1/crm/contacts/:id/owners Owner hinzufuegen
DELETE /api/v1/crm/contacts/:id/owners/:userId Owner entfernen
POST /api/v1/crm/companies/:id/owners Owner hinzufuegen
DELETE /api/v1/crm/companies/:id/owners/:userId Owner entfernen
POST /api/v1/crm/deals/:id/owners Owner hinzufuegen
DELETE /api/v1/crm/deals/:id/owners/:userId Owner entfernen
GET/POST /api/v1/crm/activities Liste / Erstellen (companyId+includeContacts fuer aggregierten Feed)
GET/PATCH/DELETE /api/v1/crm/activities/:id Detail / Update / Delete
GET/POST /api/v1/crm/industries Branchen verwalten
PATCH/DELETE /api/v1/crm/industries/:id Branche bearbeiten / loeschen
GET/POST /api/v1/crm/account-types Kontotypen verwalten
PATCH/DELETE /api/v1/crm/account-types/:id Kontotyp bearbeiten / loeschen
GET/POST /api/v1/crm/relationship-types Beziehungstypen verwalten
PATCH/DELETE /api/v1/crm/relationship-types/:id Beziehungstyp bearbeiten / loeschen
GET/POST /api/v1/crm/companies/:id/relationships Beziehungen verwalten
DELETE /api/v1/crm/companies/:id/relationships/:relId Beziehung loeschen
GET /api/v1/crm/users Tenant-User fuer Owner-Dropdown
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
GET/POST /api/v1/crm/deals Liste / Erstellen
GET /api/v1/crm/deals/forecast Umsatz-Forecast (gewichtete Pipeline, Phase 2.3)
GET/PATCH/DELETE /api/v1/crm/deals/:id Detail / Update / Delete
Import (Phase 2.2)
POST /api/v1/crm/import/preview Datei-Vorschau (CSV/XLSX, Multipart)
POST /api/v1/crm/import/execute Import ausfuehren (mit Mapping + Duplikat-Strategie)
Contracts (Vertraege)
GET/POST /api/v1/crm/companies/:id/contracts Liste / Erstellen
GET/PATCH/DELETE /api/v1/crm/companies/:id/contracts/:cid Detail / Update / Delete
POST /api/v1/crm/companies/:id/contracts/:cid/files Datei hochladen (Multipart, max 25MB)
GET /api/v1/crm/companies/:id/contracts/:cid/files Datei-Liste
GET /api/v1/crm/companies/:id/contracts/:cid/files/:fid/download Datei herunterladen (?inline=true)
DELETE /api/v1/crm/companies/:id/contracts/:cid/files/:fid Datei loeschen
Enrichment (Phase 2.4)
POST /api/v1/crm/companies/:id/enrich Unternehmensdaten anreichern (Suggestion-Only)
GET /api/v1/crm/settings/integrations/north-data North Data Einstellungen abrufen
PUT /api/v1/crm/settings/integrations/north-data North Data Einstellungen aktualisieren
GET /health Health-Check (DB, Redis, Lexware, Enrichment)
Custom Fields
POST /api/v1/crm/custom-fields Feld-Definition erstellen
GET /api/v1/crm/custom-fields?entityType=PERSON Definitionen auflisten (nach Entity-Typ)
GET /api/v1/crm/custom-fields/:id Definition abrufen
PATCH /api/v1/crm/custom-fields/:id Definition aktualisieren
DELETE /api/v1/crm/custom-fields/:id Definition loeschen (CASCADE)
PUT /api/v1/crm/custom-fields/:entityId/values Werte setzen (Bulk-Upsert)
GET /api/v1/crm/custom-fields/:entityId/values Werte lesen
Lexware Kontakte
GET /api/v1/crm/lexware/contacts/search Lexware-Kontakte suchen
POST /api/v1/crm/lexware/contacts/link-company Company verknuepfen
POST /api/v1/crm/lexware/contacts/link-contact Contact verknuepfen
DELETE /api/v1/crm/lexware/contacts/unlink-company/:id Verknuepfung loesen
DELETE /api/v1/crm/lexware/contacts/unlink-contact/:id Verknuepfung loesen
POST /api/v1/crm/lexware/contacts/import-company Company aus Lexware importieren
POST /api/v1/crm/lexware/contacts/import-contact Contact aus Lexware importieren
POST /api/v1/crm/lexware/contacts/push/:type/:id CRM -> Lexware pushen
POST /api/v1/crm/lexware/contacts/sync/:type/:id Lexware -> CRM synchronisieren
Lexware Belege
GET /api/v1/crm/lexware/vouchers/company/:id Belege fuer Unternehmen
GET /api/v1/crm/lexware/vouchers/contact/:id Belege fuer Kontakt
GET /api/v1/crm/lexware/vouchers/deal/:id Belege fuer Vorgang
POST /api/v1/crm/lexware/vouchers/deal/:id/link Beleg mit Vorgang verknuepfen
DELETE /api/v1/crm/lexware/vouchers/deal/:id/unlink/:vid Verknuepfung loesen
POST /api/v1/crm/lexware/vouchers/refresh/company/:id Cache aktualisieren
POST /api/v1/crm/lexware/vouchers/refresh/contact/:id Cache aktualisieren

Lexware Office Integration — Details

  • Rate Limiter: In-Memory Token Bucket, 2 Requests/Sekunde (Lexware API Limit)
  • Beleg-Caching: PostgreSQL-Tabelle lexware_vouchers, alle 4h Cron-Refresh + manueller Refresh
  • ERP-Push: Companies/Contacts mit Tag "ERP" werden automatisch (30min Cron) + bei Update nach Lexware gepusht
  • Distributed Locks: Redis SET NX EX verhindert Doppelausfuehrung von Cron-Jobs
  • Optimistic Locking: lexwareContactVersion fuer sichere Updates
  • Graceful Degradation: Ohne LEXWARE_API_KEY → Modul deaktiviert, Health = "unconfigured"

Docker-Integration

  • docker-compose.crm.yml im Projekt-Root
  • Port: 3100
  • Neue Env-Variablen: LEXWARE_API_KEY, LEXWARE_API_URL
  • Traefik HTTP + HTTPS Routing: /api/v1/crm/*

Sicherheit

  • JWT RS256 Validierung mit shared Public Key
  • Token-Revocation via Redis
  • Multi-Tenancy: Alle Queries filtern nach tenantId
  • Globaler ValidationPipe (whitelist + forbidNonWhitelisted)
  • Strict TypeScript, kein any

Deployment-Status

Erfolgreich deployed auf insight-dev-01 (172.20.10.59) am 2026-03-10

  • Prisma Migrationen: siehe Abschnitt "Migrationen" oben

Migrationen

  • 20260310163211_init — Initiales Schema
  • 20260310183117_add_companies — Company-Entity
  • 20260310_add_lexware_integration — Lexware Office Integration
  • 20260311_add_company_detail_overhaul — Company Detail Overhaul
  • 20260312_phase1_schema_expansion — Phase 1: Enums, Multi-Value, Owner, LostReason
  • 20260312_phase2_custom_fields — Phase 2.1: Custom Fields (Definitionen + Werte)
  • 20260312_phase23_forecast — Phase 2.3: probability-Spalte auf pipeline_stages
  • 20260312_contract_files — ContractFile-Tabelle (Vertragsdokumente)

Naechste Schritte

  1. Migrationen auf Server anwenden (phase2_custom_fields + phase23_forecast)
  2. Container neu bauen und deployen
  3. Frontend: Forecast-Widget, Import-UI, Enrichment-UI
  4. Phase 2.5: Berechtigungsmodell (Sichtbarkeitsfilter)