# Plan: Duplicate Product Detection ## Context When importing products via Excel or STEP upload, there's no warning when a product already exists with a different STEP file. This can lead to accidental overwrites or confusion. The feature adds non-blocking warnings (yellow badges, toasts) at import time. ## Detection Scenarios 1. **Excel preview**: Product exists in DB with a different STEP file linked → warning icon 2. **Excel preview**: Same product in two rows with different `name_cad_modell` → conflict badge 3. **STEP upload on product**: Replacing an existing STEP file on a product that has renders → toast warning 4. **All warnings are non-blocking** — user can still proceed ## Affected Files | File | Change | |------|--------| | `backend/app/services/excel_import.py` | Add STEP conflict detection in `preview_excel_rows()` | | `backend/app/api/routers/uploads.py` | Extend preview response with conflict fields | | `backend/app/api/routers/products.py` | Add render-count warning to CAD upload response | | `frontend/src/api/uploads.ts` | Update TypeScript interfaces | | `frontend/src/pages/Upload.tsx` | Display conflict warnings in preview table | | `frontend/src/api/products.ts` | Add warning fields to CAD upload response type | | `frontend/src/pages/ProductDetail.tsx` | Show toast warnings on STEP replacement | ## Tasks ### [ ] Task 1: Backend — STEP conflict detection in Excel preview - **File**: `backend/app/services/excel_import.py` - **What**: In `preview_excel_rows()`, after the product lookup: 1. If product exists and has `cad_file_id`, load the CadFile and compare `original_name` (stem) with the Excel row's `name_cad_modell` 2. If they differ → set `step_conflict=True` with details 3. Track `name_cad_modell` per product key in the `seen` dict 4. If same product appears again with different `name_cad_modell` → set `cad_name_conflict=True` - **Also**: Add `selectinload(Product.cad_file)` to `lookup_product()` in `backend/app/domains/products/service.py` - **Dependencies**: None ### [ ] Task 2: Backend — Extend preview response models - **File**: `backend/app/api/routers/uploads.py` - **What**: Add to the preview row dict and response: - `step_conflict: bool`, `step_conflict_existing_name: str | None`, `step_conflict_excel_name: str | None` - `cad_name_conflict: bool`, `cad_name_conflict_other_name: str | None`, `cad_name_conflict_row: int | None` - Response-level: `step_conflict_count: int`, `cad_name_conflict_count: int` - **Dependencies**: Task 1 ### [ ] Task 3: Backend — Render warning on product STEP replacement - **File**: `backend/app/api/routers/products.py` - **What**: In `upload_product_cad()`, before replacing cad_file_id: 1. Check if product already has a different `cad_file_id` 2. Count existing MediaAssets (renders) for this product 3. Add `warnings: list[str]` and `existing_render_count: int` to response - **Dependencies**: None ### [ ] Task 4: Frontend — Update API types - **File**: `frontend/src/api/uploads.ts` - **What**: Add conflict fields to `ExcelPreviewRow` and `ExcelPreviewResult` interfaces - **Also**: `frontend/src/api/products.ts` — add `warnings?: string[]` and `existing_render_count?: number` to `ProductCadUploadResponse` - **Dependencies**: Tasks 2, 3 ### [ ] Task 5: Frontend — Show conflict warnings in Upload preview - **File**: `frontend/src/pages/Upload.tsx` - **What**: 1. Add StatCards for `step_conflict_count` and `cad_name_conflict_count` (amber color, AlertTriangle icon) 2. In the preview table rows: yellow warning icon with tooltip for `step_conflict` and `cad_name_conflict` - **Dependencies**: Task 4 ### [ ] Task 6: Frontend — Show warnings on STEP replacement - **File**: `frontend/src/pages/ProductDetail.tsx` - **What**: In `cadUploadMut.onSuccess`, check response for `warnings` and show `toast.warning()` for each - **Dependencies**: Task 4 ## Migration Check **No** — all detection is computed from existing data. ## Order 1. Backend Tasks 1+2 (Excel preview conflicts) 2. Backend Task 3 (STEP replacement warning) 3. Frontend Tasks 4+5+6 (types + UI)