Kairo-Jinkendo/docs/reference/design-principles/mitai/UNIVERSAL_IMPORT_DESIGN_PRINCIPLES.md

326 lines
14 KiB
Markdown
Raw Permalink Normal View History

# Universal CSV Import – Designprinzipien (Extraktion)
**Status:** Analyse / Arbeitspapier
**Stand:** 2026-07-04
**Geltungsbereich:** Universal CSV Import (Issue #21) — Ingest/Mapping/Persistenz, keine Auswertungslogik
**Serie:** Designprinzipien für Produktfamilie · Dokument 6 von n
**Vorgänger:** [AUTH_SESSION_DESIGN_PRINCIPLES.md](./AUTH_SESSION_DESIGN_PRINCIPLES.md)
**Kernkomponenten:**
| Bereich | Pfade |
|---------|-------|
| Modul-Kanon | `backend/csv_parser/module_registry.py` |
| Ausführung | `backend/csv_parser/executor.py` |
| Parsing/Typen | `core.py`, `type_converter.py`, `field_units.py` |
| Aggregation | `import_row_processing.py` |
| Validierung | `template_validator.py` |
| Fehler-Hints | `import_errors.py` |
| Mapping-Vorschläge | `mapping_suggest.py` |
| Nutzer-API | `backend/routers/csv_import.py` |
| Admin-Vorlagen | `backend/routers/admin_csv_templates.py` |
| Persistenz-Orchestrator | `data_layer/activity_persistence_orchestrator.py` |
| Leitfaden | `UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md` |
| Import-Grenze | `.claude/rules/ARCHITECTURE.md` §8 |
---
## Modul
**Universal CSV Import**
Konfigurierbare Pipeline: **CSV-Datei → Feld-Mapping → Typkonvertierung → (optional Aggregation) → DB-Upsert** — mit Vorlagen, Audit-Log und row-level Fehlertoleranz.
---
## Fachliche Verantwortung
Das Modul übernimmt:
1. **Modul-Registry** — Welche Zieltabellen/Felder importierbar sind (Typen, Duplikat-Keys, Strategien).
2. **Vorlagen (Mappings)** — System-Templates (Admin) + Nutzer-Kopien (`csv_field_mappings`).
3. **Analyse** — Delimiter-Erkennung, Spalten-Signatur, Mapping-Vorschläge, Diagnose einzelner Zeilen.
4. **Ausführung** — Upsert pro Modul, `source=csv`, Statistik, `affected_ids`.
5. **Fehlertransparenz** — Row-level Errors mit `code`/`hint`; kein Silent-Fail der ganzen Transaktion.
6. **Audit** — `csv_import_log` mit Status, Counts, betroffenen IDs.
7. **Limits** — Dateigröße/Zeilen aus `system_config`; Feature-Entitlements pro Modul.
Es übernimmt **nicht**:
- Fachliche Metriken / Scores (→ Data Layer, siehe [DATA_LAYER_DESIGN_PRINCIPLES.md](./DATA_LAYER_DESIGN_PRINCIPLES.md))
- Prompt-/KI-Logik
- Vollständiger Ersatz aller Legacy-Import-Endpoints (noch parallel)
### Pipeline (Happy Path)
```
Upload CSV
→ decode_raw_bytes + resolve_effective_csv_delimiter
→ Vorlage laden (csv_field_mappings)
→ validate (optional Admin) / feature check
→ run_universal_csv_import(cur, …) // eine Transaktion
→ build_row_after_mapping (type_converter)
→ aggregate_mapped_rows (import_row_processing)
→ UPSERT / activity_persistence_orchestrator
→ csv_import_log UPDATE + increment_feature_usage
```
### Unterstützte Module (Registry)
| Modul | Zieltabelle | Besonderheit |
|-------|-------------|--------------|
| `nutrition` | `nutrition_log` | Tages-Aggregation |
| `weight` | `weight_log` | Duplikat: profile + date |
| `activity` | `activity_log` | SAVEPOINT pro Zeile; EAV via Orchestrator |
| `vitals_baseline` | `vitals_baseline` | Tages-Aggregation |
| `blood_pressure` | `blood_pressure_log` | Composite `measured_at` |
| `sleep` | `sleep_log` | Legacy-Adapter `import_mode: apple_sleep_aggregate` |
---
## Administrierte vs. code-definierte Konfiguration
| Konfiguration | Speicherort | Wer pflegt? |
|---------------|-------------|-------------|
| Zielfelder, Typen, Duplikat-Keys | `MODULE_DEFINITIONS` | Entwickler (Code) |
| System-Vorlagen | `csv_field_mappings` (`is_system=true`) | Admin (+ Migration Seeds) |
| Nutzer-Mappings | `csv_field_mappings` (`profile_id`) | Nutzer (Kopie/Anpassung) |
| `field_mappings`, `type_conversions`, `import_row_processing` | JSONB in Vorlage | Admin/Nutzer |
| Import-Limits | `system_config.csv_import` | Admin |
| Delimiter-Sniffing-Heuristik | `core.py` | Code |
| Header-Aliases (Vorschläge) | `mapping_suggest.py` | Code |
**Bewusst nicht in Routern hardcodiert:** Feldlisten, Duplikat-Logik — nur Registry + Executor.
---
## Designprinzipien
### 1. Module Registry als Single Source of Truth
| | |
|---|---|
| **Prinzip** | Alle erlaubten Zielfelder, Typen und Duplikat-Keys leben in `MODULE_DEFINITIONS` — Router duplizieren nicht. |
| **Begründung** | Admin-UI, Validator, Executor und `/api/csv/modules` bleiben synchron. |
| **Quelle** | `module_registry.py`; Agent-Guide §1 |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Activity erweitert Felder dynamisch aus `training_parameters` (DB). |
### 2. Ingest vs. Interpretation (Import-Grenze)
| | |
|---|---|
| **Prinzip** | Import: Mapping + Typ/Einheit + Duplikat/Upsert. **Keine** fachliche Auswertung beim Insert. |
| **Begründung** | Semantik gehört in Data Layer; Import bleibt austauschbar und testbar. |
| **Quelle** | `ARCHITECTURE.md` §8; [DATA_LAYER_DESIGN_PRINCIPLES.md](./DATA_LAYER_DESIGN_PRINCIPLES.md) |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | `sleep_apple_import.py` ist Legacy-Adapter mit quellenspezifischer Logik. |
### 3. Vorlagen trennen Struktur von Datei
| | |
|---|---|
| **Prinzip** | `csv_field_mappings` speichert Modul, Delimiter, Header-Flag, Mappings, Conversions, Row-Processing — unabhängig vom Upload. |
| **Begründung** | Wiederverwendung (Apple Health, Omron, …); Nutzer wählt Vorlage statt jedes Mal neu zu mappen. |
| **Quelle** | Migration 042; Admin + User APIs |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Nutzer-Kopien nicht immer durch `validate_csv_template` (#71). |
### 4. Effektives Trennzeichen aus Datei, nicht blind aus Vorlage
| | |
|---|---|
| **Prinzip** | `resolve_effective_csv_delimiter` — DE-Export (`;`) vs. EN-Vorlage (`,`) wird aus Header-Feldanzahl erkannt. |
| **Begründung** | Regionale CSV-Exporte brechen sonst das gesamte Mapping (eine Spalte). |
| **Quelle** | `core.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Heuristik, kein 100%-Garant für exotische Formate. |
### 5. Typ- und Einheiten-Konvertierung deklarativ
| | |
|---|---|
| **Prinzip** | `type_conversions` + `source_unit` in Vorlage; Logik in `type_converter` / `field_units`. |
| **Begründung** | kJ→kcal, Datumsformate, Dezimal-Komma ohne Code pro Quelle. |
| **Quelle** | `type_converter.py`, `field_units.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Falsche `source_unit` → DB-Overflow; `enrich_row_error` hilft nachträglich. |
### 6. Zeilen-Aggregation vor Upsert
| | |
|---|---|
| **Prinzip** | `import_row_processing` (group_by + aggregates) fasst mehrere CSV-Zeilen pro logischem Tag/Datensatz zusammen. |
| **Begründung** | Ernährung/Vitals: viele Rohzeilen → ein Tageseintrag. |
| **Quelle** | `import_row_processing.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Modul-Default als Legacy-Fallback wenn Vorlage leer; Admin „Format prüfen“ kann Processing auslassen. |
### 7. Ein Cursor, eine Transaktion, SAVEPOINT pro Zeile
| | |
|---|---|
| **Prinzip** | `run_universal_csv_import(cur, …)` nutzt **bestehenden** Cursor; bei Row-Fehlern SAVEPOINT + ROLLBACK TO, nicht ganze Xact abbrechen. |
| **Begründung** | PostgreSQL „transaction aborted“; partielle Imports mit Fehlerliste. |
| **Quelle** | `executor.py` (activity, vitals); `csv_import.py` SAVEPOINT `csv_import_exec` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Nicht alle Module gleich implementiert; Disziplin pro Modul. |
### 8. Kein verschachteltes get_db im Importpfad
| | |
|---|---|
| **Prinzip** | FK-Auflösung (z. B. Trainingstyp) und Activity-Persistenz mit **demselben** `cur` wie der Import. |
| **Begründung** | Pool-Deadlocks, konsistente Transaktion. |
| **Quelle** | `_resolve_training_type_for_activity`; Agent-Guide §2 |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Lazy-Import aus Router in Executor (Kopplung). |
### 9. Strukturierte Fehler mit Hints
| | |
|---|---|
| **Prinzip** | `enrich_row_error()` mappt DB-/Parse-Fehler auf `code` + menschenlesbaren `hint`. |
| **Begründung** | Nutzer/Admin können Vorlagen korrigieren ohne PostgreSQL-Kenntnis. |
| **Quelle** | `import_errors.py`; Import-Response `error_details` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Heuristische String-Matches, nicht vollständig. |
### 10. Vorlagen-Validierung vor Persistenz (Admin)
| | |
|---|---|
| **Prinzip** | `validate_csv_template` → `{ valid, errors[], warnings[] }`; Admin Create/Update → HTTP 422 bei Fehlern. |
| **Begründung** | Fehler früh, nicht erst beim Nutzer-Import. |
| **Quelle** | `template_validator.py`; `admin_csv_templates.py` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Dry-Run / User-Mappings Lücken (#71). |
### 11. System- vs. User-Mappings (Permissions)
| | |
|---|---|
| **Prinzip** | `is_system=true`: nur Admin editierbar; Nutzer kopiert und passt eigene Zeile an. |
| **Begründung** | Shipped Templates schützen; Individualisierung erlauben. |
| **Quelle** | `permissions.py`; DB CHECK + Unique Indexes |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | — |
### 12. Import-Audit und Rollback-Vorbereitung
| | |
|---|---|
| **Prinzip** | Jeder Lauf schreibt `csv_import_log` mit Counts, `error_details`, `affected_ids` (PKs pro Tabelle). |
| **Begründung** | Nachvollziehbarkeit, spätere Bereinigung/Rollback, Erfolgsrate pro Vorlage. |
| **Quelle** | Migration 042; `csv_import_execute` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Automatischer Rollback-Button nicht überall umgesetzt. |
### 13. Feature-Entitlements an Import gebunden
| | |
|---|---|
| **Prinzip** | `data_import` global + modulspezifisch (`nutrition_entries`, …); Increment nur für **neue** Zeilen. |
| **Begründung** | Konsistent mit Membership-System. |
| **Quelle** | `csv_import.py` `_check_module_feature_access`, `increment_feature_usage` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Bulk-Increment-Schleife ineffizient (wie Feature-Doc). |
### 14. Mapping-Vorschläge (Heuristik, nicht Autorität)
| | |
|---|---|
| **Prinzip** | `mapping_suggest.py` schlägt Spalten-Zuordnung aus Header-Aliases vor — Admin bestätigt. |
| **Begründung** | Schneller Editor-Start; Kanon bleibt menschlich/administrativ freigegeben. |
| **Quelle** | `_MODULE_HEADER_ALIASES` |
| **Tragfähigkeit** | **mittel–hoch** |
| **Einschränkung** | Domänenspezifische Aliases hardcodiert (DE/EN). |
### 15. Persistenz-Orchestrator für komplexe Domänen
| | |
|---|---|
| **Prinzip** | Activity: nach Registry-Mapping → `activity_persistence_orchestrator` (Upsert + EAV + Eval-Hook). |
| **Begründung** | Gleiche Schreiblogik wie REST-API; kein divergierender CSV-Pfad. |
| **Quelle** | `activity_persistence_orchestrator.py`; [DATA_LAYER_DESIGN_PRINCIPLES.md](./DATA_LAYER_DESIGN_PRINCIPLES.md) §9 |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Nur Activity vollständig; andere Module direkt im Executor. |
---
## Nicht übernehmen
1. **Parallele Legacy-Import-Endpoints** — `/api/nutrition/import-csv`, `/api/activity/import-csv` neben Universal-Pfad; neue Quellen nur über Universal + Vorlage (ARCHITECTURE §8.2).
2. **Quellenspezifische Aggregat-Logik im Import** — `sleep_apple_import` als Dauerlösung; Ziel: mapping-nah + Layer 1 (Gitea #69).
3. **Feldlisten in Routern** — jede neue Spalte nur via `module_registry` + Migration.
4. **Verschachtelte DB-Connections im Executor** — Pool-Risiko; immer Caller-`cur` durchreichen.
5. **Transaktion ohne SAVEPOINT bei Multi-Row-Import** — ein Fehler killt gesamten Import + opaque „transaction aborted“.
6. **Blindes Vorlagen-Delimiter** — regionaler Export bricht Mapping.
7. **Nutzer-Mappings ohne Validierung** — #71; Copy-from-System muss durch Validator.
8. **Dry-Run ohne `import_row_processing`** — Admin „Format prüfen“ unvollständig vs. echter Import.
9. **`source`-CHECK in DB vergessen** — Import setzt `csv`, Constraint muss Migration sein.
10. **NUMERIC-Overflow durch falsche Einheit** — Schema + `source_unit` + Migrationbreite gemeinsam planen.
11. **Interpretation/Auswertung beim Import** — Scores, TDEE, Training-Quality nicht in `executor.py`.
12. **Executor-Monolith ohne Modul-Split** — `executor.py` wächst pro Modul; langfristig Executor-Strategie pro Registry-Key.
---
## Modul-Inventar (Ist-Stand)
```
backend/csv_parser/
├── module_registry.py # MODULE_DEFINITIONS
├── executor.py # run_universal_csv_import
├── core.py # decode, delimiter, limits
├── type_converter.py
├── field_units.py
├── import_row_processing.py
├── template_validator.py
├── import_errors.py
├── mapping_suggest.py
├── permissions.py
└── sleep_apple_import.py # Legacy-Adapter
backend/routers/
├── csv_import.py # Nutzer: modules, analyze, import, mappings
└── admin_csv_templates.py # Admin: CRUD + validate
DB:
├── csv_field_mappings
└── csv_import_log
```
---
## Verwandte Dokumentation
- Agent-Guide (normativ): [UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md](../../technical/UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md)
- Registry-Meta: [REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md](./REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md)
- Import-Grenze: [ARCHITECTURE.md](../../../rules/ARCHITECTURE.md) §8
- Feature-Limits: [FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md](./FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md)
- Gitea #71: Dry-Run, User-Mapping-Validierung
---
## Geplante Folgedokumente (Serie)
| # | Modul | Status |
|---|-------|--------|
| 1–5 | … | ✅ |
| 6 | Universal Import | ✅ dieses Dokument |
| 7 | Dashboard Widgets | ✅ `DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md` |
| 8 | Navigation / IA | ✅ |
| 9 | Migration & Deploy | ✅ |