mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-24 23:56:40 +02:00
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:
parent
27507f1372
commit
a55643a0dd
2 changed files with 301 additions and 0 deletions
40
Summarize.md
40
Summarize.md
|
|
@ -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 (0–100%) 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)
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -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.00–1.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 (0–100% 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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue