INSIGHT-MVP/packages/crm-service/Summarize.md
Thomas Reitz 9d496d2e53 feat(crm): integrate Lexware Office for vouchers and contact sync
Adds complete Lexware Office integration to CRM service:
- Rate-limited HTTP client (Token Bucket, 2 req/s)
- Bidirectional contact sync (manual import + ERP-push)
- Voucher caching (quotes, orders, invoices, credit notes)
- Deal-voucher linking (m:n join table with audit)
- Cron jobs: voucher refresh (4h), ERP push (30min)
- Distributed locks via Redis for job deduplication
- Health check extended with Lexware status
- Prisma schema: LexwareVoucher, DealVoucher, VoucherType enum
- Companies/Contacts/Deals services extended with Lexware data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:28:41 +01:00

154 lines
7.9 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, @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
companies/ — CRUD: Unternehmen (mit Lexware ERP-Push bei Update)
contacts/ — CRUD: Kontakte (mit Lexware ERP-Push bei Update)
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 + DealVouchers
health/ — Health-Check (DB, Redis, Lexware)
lexware/ — Lexware Office Integration (NEU)
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 Lexware-Verknuepfung (lexwareContactId, lexwareContactVersion, lexwareSyncedAt)
- **Contact** — Kontakte mit optionaler Lexware-Verknuepfung
- **Activity** — Aktivitaeten verknuepft mit Kontakten
- **Pipeline** — Konfigurierbare Sales-Pipelines pro Tenant
- **PipelineStage** — Stufen innerhalb einer Pipeline
- **Deal** — Vorgaenge mit dealVouchers-Relation zu Lexware-Belegen
- **LexwareVoucher** (NEU) — Gecachte Belege aus Lexware Office (Angebote, Auftraege, Rechnungen, Gutschriften)
- **DealVoucher** (NEU) — 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) LexwareVoucher — companyId (optional, SetNull)
Contact (1) --< (n) Activity — contactId (Cascade)
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)
```
### 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 |
| 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:
- `20260310163211_init` — Initiales Schema
- `20260310183117_add_companies` — Company-Entity
- `20260310_add_lexware_integration` — Lexware Office Integration (AUSSTEHEND)
### Naechste Schritte
1. Migration `20260310_add_lexware_integration` auf Server anwenden
2. `LEXWARE_API_KEY` in `.env` auf Server setzen
3. Container neu bauen und deployen
4. Lexware-Endpunkte auf Server testen
5. Frontend: Lexware-Integration in Company/Contact/Deal-Detail-Seiten
6. Activity-Liste komplett laden (UI-Button "Alle anzeigen")
7. Kanban-Board fuer Vorgaenge