fix(crm): align Phase 2.2–2.4 frontend to actual backend contracts

- Import: convert mapping Record→Array, entityType PERSON→contact
- Enrichment: handle suggestions as Record<field,{current,suggested,source}>
- Types: add availableTargetFields to ImportPreviewResponse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas Reitz 2026-03-12 20:55:47 +01:00
parent 219863d538
commit dda672d41e
3 changed files with 35 additions and 9 deletions

View file

@ -613,11 +613,15 @@ export const customFieldsApi = {
// --- Import ---
/** Backend erwartet lowercase entity-type-Bezeichner */
const toImportEntityType = (t: ImportEntityType): string =>
t === 'PERSON' ? 'contact' : t === 'COMPANY' ? 'company' : 'deal';
export const importApi = {
preview: (file: File, entityType: ImportEntityType) => {
const form = new FormData();
form.append('file', file);
form.append('entityType', entityType);
form.append('entityType', toImportEntityType(entityType));
return api
.post<{ success: boolean; data: ImportPreviewResponse; meta: { timestamp: string } }>(
'/crm/import/preview',
@ -627,13 +631,22 @@ export const importApi = {
.then((r) => r.data);
},
execute: (data: ImportExecuteRequest) =>
api
execute: (data: ImportExecuteRequest) => {
// Backend erwartet mapping als Array [{sourceColumn, targetField}]
const mappingArray = Object.entries(data.mapping)
.filter(([, target]) => target)
.map(([sourceColumn, targetField]) => ({ sourceColumn, targetField }));
return api
.post<{ success: boolean; data: ImportExecuteResponse; meta: { timestamp: string } }>(
'/crm/import/execute',
data,
{
...data,
entityType: toImportEntityType(data.entityType),
mapping: mappingArray,
},
)
.then((r) => r.data),
.then((r) => r.data);
},
};
// --- Enrichment ---

View file

@ -197,7 +197,11 @@ export function CompanyDetailPage() {
onClick={() => {
enrichCompany.mutate(company.id, {
onSuccess: (res) => {
setEnrichSuggestions(res.data.suggestions);
// Backend gibt suggestions als Record<field, {current, suggested, source}> zurück
const suggestions = Object.entries(res.data.suggestions).map(
([field, s]) => ({ field, ...s }),
);
setEnrichSuggestions(suggestions);
setEnrichOpen(true);
},
});

View file

@ -860,6 +860,7 @@ export interface ImportPreviewResponse {
rows: Record<string, string>[];
totalRows: number;
format: string;
availableTargetFields?: string[];
}
export interface ImportExecuteRequest {
@ -888,6 +889,7 @@ export interface ImportExecuteResponse {
// --- Enrichment ---
/** Einzelner Vorschlag (normalisiert für die UI) */
export interface EnrichmentSuggestion {
field: string;
current: string | null;
@ -895,12 +897,19 @@ export interface EnrichmentSuggestion {
source: string;
}
export interface EnrichmentResponse {
source: string;
suggestions: EnrichmentSuggestion[];
/** Backend-Antwort: suggestions als Record<field, {...}> */
export interface EnrichmentResponseRaw {
companyId?: string;
companyName?: string;
sources?: string[];
suggestions: Record<string, { current: string | null; suggested: string | null; source: string }>;
enrichedAt: string;
warnings?: string[];
}
/** Normalisierte Variante für die UI (backward-compat alias) */
export type EnrichmentResponse = EnrichmentResponseRaw;
export interface EnrichmentConfig {
apiKey: string;
configured: boolean;