docs(crm): Phase 2.2-2.4 Frontend-TODOs abgehakt + Summarize.md aktualisiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas Reitz 2026-03-12 21:09:16 +01:00
parent 27507f1372
commit a55643a0dd
2 changed files with 301 additions and 0 deletions

View file

@ -2,6 +2,46 @@
## Stand: 2026-03-12
### Aktueller Sprint: CRM Phase 2 (Feature-Branch: feature/crm-service)
---
### Aenderungen 2026-03-12: CRM Phase 2 — Forecast, Import, Enrichment (Frontend komplett)
#### Phase 2.3: Forecasting
- `crm/forecast/ForecastPage.tsx` — Prognose-Dashboard unter `/crm/forecast`
- Pipeline-Filter (Dropdown) + Zeitraum-Toggle (Monat/Quartal/Jahr)
- Summary-Cards: Offene Vorgaenge, Gesamtwert, Gewichteter Wert, Zeitraum
- Tabelle: Stage | Wahrscheinlichkeit | Vorgaenge | Gesamtwert | Gewichteter Wert
- `crm/pipelines/PipelinesPage.tsx` — Probability-Feld (0100%) pro Pipeline-Stage
#### Phase 2.2: CSV/Excel Import
- `crm/import/ImportPage.tsx` — 3-Schritt-Wizard in CRM-Einstellungen → Tab "Import"
- Schritt 1: Typ-Auswahl (Kontakte/Unternehmen/Vorgaenge) + Datei-Upload (CSV, XLSX, max 10MB)
- Schritt 2: Spalten-Mapping (Auto-Match + manuell), Duplikat-Strategie, Kopfzeilen-Option
- Schritt 3: Ergebnis (created/updated/skipped/errors + Fehlerdetails)
- API-Konvertierungen: `PERSON→contact`, mapping `Record→Array [{sourceColumn,targetField}]`
#### Phase 2.4: Datenanreicherung
- `crm/companies/CompanyDetailPage.tsx` — "Anreichern"-Button im Header
- POST /companies/:id/enrich → Suggestions-Modal
- Tabelle: Feld | Aktuell | Vorschlag | Quelle + "Uebernehmen"-Button (PATCH)
- suggestions-Konvertierung: Backend-Record → UI-Array
- `crm/settings/CrmSettingsPage.tsx` — North Data API-Key in Tab "Integrationen"
#### Kontakt-Entity UI/UX Redesign (aus dieser Sprint-Session)
- `components/Drawer.tsx` + `Drawer.module.css` — Wiederverwendbarer Right-Side-Drawer
- `crm/contacts/ContactFormModal.tsx` — Modal → Drawer, Zwei-Tab-Struktur (Allgemein/Details)
- `crm/contacts/ContactDetailPage.tsx`:
- Header: Name (Unternehmen) in Klammern, Aktiv/Inaktiv-Badge (Pill mit farbigem Dot)
- Kontaktdaten-Card: immer alle Allgemein-Felder (leere Felder = "—"), 2 Sub-Spalten
- Lexware-Section entfernt (Kontakte werden nicht separat in Lexware gepflegt)
#### TypeScript
- `npx tsc --noEmit` in packages/frontend: 0 Fehler (alle Commits)
---
### Aktueller Sprint: Sprint 1 (Alpha)
---

View file

@ -2858,3 +2858,264 @@ Sie werden **NICHT** vom Enrich-Endpoint aktualisiert. Stattdessen setzt das Fro
4. **Tests:** Import-Edge-Cases besonders gruendlich testen (leere Zeilen, Sonderzeichen, fehlende Pflichtfelder, doppelte E-Mails)
5. **DSGVO:** Import-Temp-Dateien MUESSEN nach Verarbeitung geloescht werden
6. **Completion-Report:** Nach jeder Phase einen Eintrag in dieser Datei ergaenzen (wie bei Phase 2.1)
---
## Phase 2.3 Backend — Forecast (DONE)
**Implementiert am:** 2026-03-12
### Schema-Aenderung
- `PipelineStage.probability` — Decimal(3,2), Default 0, Bereich 0.001.00
- Migration: `prisma/migrations/20260312_phase23_forecast/migration.sql`
### Neue Endpoints
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | /api/v1/crm/deals/forecast?pipelineId=&period= | Umsatz-Forecast (gewichtete Pipeline) |
### Forecast Response
```json
{
"success": true,
"data": {
"period": "quarter",
"periodStart": "2026-01-01T00:00:00.000Z",
"periodEnd": "2026-03-31T23:59:59.999Z",
"currency": "EUR",
"stages": [
{
"stageId": "uuid",
"stageName": "Qualifiziert",
"stageColor": "#3B82F6",
"probability": 0.25,
"sortOrder": 1,
"pipelineId": "uuid",
"pipelineName": "Sales",
"dealCount": 5,
"totalValue": 50000,
"weightedValue": 12500
}
],
"totals": {
"dealCount": 15,
"totalValue": 150000,
"weightedValue": 67500
}
}
}
```
### Query-Parameter
- `pipelineId` (optional, UUID) — Filter nach Pipeline
- `period` (optional, enum: month|quarter|year, default: quarter)
### DTO-Updates
- `CreatePipelineStageDto.probability` — Optional, @IsNumber, @Min(0), @Max(1)
- `UpdateStageDto.probability` — Optional, gleiche Validierung
### Geaenderte Dateien
- `prisma/crm.schema.prisma` — probability auf PipelineStage
- `src/pipelines/dto/create-pipeline.dto.ts` — probability-Feld
- `src/pipelines/dto/update-stage.dto.ts` — probability-Feld
- `src/pipelines/pipelines.service.ts` — probability in create/addStage/updateStage
- `src/pipelines/pipelines.controller.ts` — probability durchreichen
- `src/deals/dto/forecast-query.dto.ts` — NEU: ForecastQueryDto + ForecastPeriod Enum
- `src/deals/deals.service.ts` — NEU: forecast() + getPeriodBounds()
- `src/deals/deals.controller.ts` — NEU: GET /deals/forecast (vor :id Route)
### TODO Frontend
- [x] Forecast-Seite (`/crm/forecast`) — Pipeline-Filter, Zeitraum-Toggle (Monat/Quartal/Jahr), Tabelle mit gewichteten Werten + Summary-Cards
- [x] probability-Feld in Pipeline-Stage-Editor (0100% Input in PipelinesPage)
---
## Phase 2.2 Backend — CSV/Excel Import (DONE)
**Implementiert am:** 2026-03-12
### Neue Dependencies
- `csv-parser: ^3.0.0` — CSV-Parser mit Stream-Support
- `xlsx: ^0.18.5` — Excel-Parser (XLSX/XLS)
- `@types/multer: ^1.4.12` (devDep)
### Neue Endpoints
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| POST | /api/v1/crm/import/preview | Datei-Vorschau (Multipart, CSV/XLSX) |
| POST | /api/v1/crm/import/execute | Import ausfuehren |
### Preview (Multipart POST)
- **File-Upload**: `file` Feld, max 10MB, MIME: text/csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
- **Query-Params**: `entityType` (contact|company), `delimiter` (optional)
- **Max Rows**: 5000
- **Preview Rows**: Erste 10
```json
{
"success": true,
"data": {
"importId": "uuid",
"format": "csv",
"columns": ["Vorname", "Nachname", "E-Mail", "Telefon"],
"rows": [{"Vorname": "Max", "Nachname": "Muster", ...}],
"totalRows": 250,
"availableTargetFields": ["firstName", "lastName", "email", ...]
}
}
```
### Execute (JSON POST)
```json
{
"importId": "uuid-from-preview",
"entityType": "contact",
"mapping": [
{"sourceColumn": "Vorname", "targetField": "firstName"},
{"sourceColumn": "E-Mail", "targetField": "email"}
],
"duplicateStrategy": "SKIP"
}
```
**Duplikat-Strategien** (E-Mail-Abgleich, case-insensitive):
- `SKIP` — Zeile ueberspringen
- `UPDATE` — Bestehenden Datensatz aktualisieren
- `MARK` — Neuen Datensatz mit Tag "DUPLIKAT" erstellen
**Response:**
```json
{
"success": true,
"data": {
"created": 230,
"updated": 0,
"skipped": 15,
"errors": 5,
"totalProcessed": 250,
"errorDetails": [{"row": 42, "field": "", "value": "", "message": "..."}]
}
}
```
### Target Fields
- **Contact**: firstName, lastName, email, phone, mobile, companyName, position, department, website, street, zip, city, state, country, notes, tags, source, linkedinUrl
- **Company**: name, email, phone, website, industry, street, zip, city, state, country, vatId, taxId, tradeRegisterNumber, registerCourt, notes, tags
### GDPR
- Temp-Dateien werden unter `/tmp/crm-import-{uuid}{ext}` gespeichert
- Nach Execute werden Temp-Dateien IMMER geloescht (finally-Block)
- Owner wird automatisch auf den importierenden User gesetzt
### Neue Dateien
- `src/import/import.module.ts`
- `src/import/import.controller.ts`
- `src/import/import.service.ts`
- `src/import/dto/import-preview.dto.ts`
- `src/import/dto/import-execute.dto.ts`
### TODO Frontend
- [x] Import-Wizard (3 Schritte: Upload → Spalten-Mapping → Ergebnis) in CRM-Einstellungen → Tab "Import"
- [x] Import-Ergebnis-Anzeige (created/updated/skipped/errors mit Fehlerdetails)
- [x] entityType-Konvertierung: PERSON→contact, COMPANY→company
- [x] mapping-Konvertierung: Record→Array [{sourceColumn, targetField}]
---
## Phase 2.4 Backend — Datenanreicherung / Enrichment (DONE)
**Implementiert am:** 2026-03-12
### Neue Endpoints
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| 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 |
### Datenquellen
1. **Unternehmensregister.de** (kostenfrei) — Handelsregister-Daten: registerNumber, registerCourt, Adresse
2. **North Data API** (kostenpflichtig, optional) — Erweiterte Daten: name, vatId, website, phone, Adresse, industry
Beide Quellen werden **parallel** abgefragt (`Promise.allSettled`). Graceful Degradation: Wenn eine Quelle fehlschlaegt, werden Ergebnisse der anderen zurueckgegeben.
### Enrich Response (Suggestion-Only, KEIN Auto-Write)
```json
{
"success": true,
"data": {
"companyId": "uuid",
"companyName": "Muster GmbH",
"sources": ["unternehmensregister.de", "northdata.de"],
"suggestions": {
"tradeRegisterNumber": {
"current": null,
"suggested": "HRB 12345",
"source": "unternehmensregister.de"
},
"vatId": {
"current": null,
"suggested": "DE123456789",
"source": "northdata.de"
}
},
"enrichedAt": "2026-03-12T14:30:00.000Z",
"warnings": []
}
}
```
### North Data Settings
- Gespeichert in Redis: `crm:{tenantId}:integrations:north_data`
- Fallback: Env-Variable `NORTH_DATA_API_KEY`
- API-Key wird in GET-Response maskiert: `****xxxx`
### Env-Variablen (optional)
- `NORTH_DATA_API_KEY` — Globaler API-Key
- `NORTH_DATA_API_URL` — Base-URL (Default: https://www.northdata.de/_api)
### Health-Check
- `/health` Response enthaelt neuen Service: `enrichment: 'up' | 'down' | 'unconfigured'`
- Version auf `0.3.0` erhoeht
### Neue Dateien
- `src/enrichment/enrichment.module.ts`
- `src/enrichment/enrichment.controller.ts`
- `src/enrichment/enrichment.service.ts`
- `src/enrichment/dto/enrich-response.dto.ts`
- `src/enrichment/dto/enrichment-settings.dto.ts`
### Geaenderte Dateien
- `src/app.module.ts` — EnrichmentModule registriert
- `src/config/env.validation.ts` — NORTH_DATA_API_KEY + _URL
- `src/health/health.module.ts` — EnrichmentModule importiert
- `src/health/health.controller.ts` — enrichment Health-Check
### TODO Frontend
- [x] "Anreichern"-Button auf Company-Detail — POST /enrich, Suggestions-Modal (Tabelle mit Feld/Aktuell/Vorschlag/Quelle), "Uebernehmen" per PATCH
- [x] suggestions-Konvertierung: Record<field,{current,suggested,source}> → Array fuer UI
- [x] North Data API-Key in CRM-Einstellungen → Tab "Integrationen"