mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-25 09:06:40 +02:00
Backend (CRM-Expert Phase 1): - New enums: ContactSource, EntityStatus, CompanySize, OwnerRole, LostReason, EmailType, PhoneType - Contact: add linkedinUrl, birthday, source, department, status - Company: add vatId, taxId, tradeRegisterNumber, registerCourt, companySize, deliveryAddress, dataEnrichedAt/Source, status - Deal: add lostReason + lostReasonText (required when status=LOST) - Multi-value emails/phones tables (contact_emails, contact_phones) - Owner m:n model (contact_owners, company_owners, deal_owners) - Redis Pub/Sub CRM events (crm.contact.created, crm.deal.won, etc.) - Activity due_soon scheduler (cron every 15 min) - SQL migration with data migration for existing records Frontend integration: - types.ts: all new enums, interfaces, label maps - api.ts: owner CRUD endpoints (add/remove for contacts/companies/deals) - hooks.ts: 6 new owner mutation hooks - ContactFormModal: LinkedIn, birthday, source, department, status fields - ContactDetailPage: display new fields (LinkedIn, department, birthday, source, status badge) - CompanyDetailPage: display vatId, taxId, trade register, company size, delivery address, data enrichment info - DealFormModal: lost reason dropdown + text (shown when status=LOST) - DealDetailPage: display lost reason with label - CompaniesPage: EntityStatus-aware status dots (ACTIVE/INACTIVE/BLOCKED) - ActivityType: add FOLLOWUP to all label maps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
198 lines
11 KiB
Markdown
198 lines
11 KiB
Markdown
# 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_*)
|
|
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)
|
|
companies/ — CRUD: Unternehmen (Multi-Value emails/phones, Owner m:n, Status, Lexware ERP-Push)
|
|
contacts/ — CRUD: Kontakte (Multi-Value emails/phones, Owner m:n, Status, Events)
|
|
activities/ — CRUD: Aktivitaeten (NOTE, CALL, EMAIL, MEETING, TASK, FOLLOWUP; contactId+companyId optional)
|
|
pipelines/ — CRUD: Sales-Pipelines mit Stages (inkl. Stage-Update)
|
|
deals/ — CRUD: Vorgaenge mit Pipeline/Stage/Contact/Company + DealVouchers + LostReason + Owner m:n + Events
|
|
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)
|
|
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
|
|
- **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 (DB-Modell vorhanden, UI-Platzhalter)
|
|
- **LexwareVoucher** — Gecachte Belege aus Lexware Office
|
|
- **DealVoucher** — Join-Table Deal <-> Beleg (m:n mit Audit-Trail)
|
|
|
|
### 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
|
|
```
|
|
|
|
### 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/PATCH/DELETE | /api/v1/crm/deals/:id | Detail / Update / Delete |
|
|
| GET | /health | Health-Check (DB, Redis, Lexware) |
|
|
| **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
|
|
|
|
### Naechste Schritte
|
|
|
|
1. Migration `20260312_phase1_schema_expansion` auf Server anwenden
|
|
2. Container neu bauen und deployen
|
|
3. Frontend: Multi-Value Email/Phone UI implementieren
|
|
4. Frontend: Owner-Management UI
|
|
5. Frontend: EntityStatus statt isActive verwenden
|
|
6. Frontend: LostReason bei Deal-Verlust einblenden
|
|
7. Phase 2: Office 365 E-Mail Integration (Planer-Briefing vorhanden)
|
|
8. Phase 3: Kontakt-Zusammenfuehrung (Merge)
|
|
9. Phase 4: Aktivitaets-Erweiterung + Dashboard Widgets
|