- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family. - Updated README files to include references to the new design principles documentation. - Enhanced the overall documentation structure to improve navigation and accessibility of design resources. - Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
14 KiB
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
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:
- Modul-Registry — Welche Zieltabellen/Felder importierbar sind (Typen, Duplikat-Keys, Strategien).
- Vorlagen (Mappings) — System-Templates (Admin) + Nutzer-Kopien (
csv_field_mappings). - Analyse — Delimiter-Erkennung, Spalten-Signatur, Mapping-Vorschläge, Diagnose einzelner Zeilen.
- Ausführung — Upsert pro Modul,
source=csv, Statistik,affected_ids. - Fehlertransparenz — Row-level Errors mit
code/hint; kein Silent-Fail der ganzen Transaktion. - Audit —
csv_import_logmit Status, Counts, betroffenen IDs. - 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)
- 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 |
| 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 §9 |
| Tragfähigkeit | hoch |
| Einschränkung | Nur Activity vollständig; andere Module direkt im Executor. |
Nicht übernehmen
-
Parallele Legacy-Import-Endpoints —
/api/nutrition/import-csv,/api/activity/import-csvneben Universal-Pfad; neue Quellen nur über Universal + Vorlage (ARCHITECTURE §8.2). -
Quellenspezifische Aggregat-Logik im Import —
sleep_apple_importals Dauerlösung; Ziel: mapping-nah + Layer 1 (Gitea #69). -
Feldlisten in Routern — jede neue Spalte nur via
module_registry+ Migration. -
Verschachtelte DB-Connections im Executor — Pool-Risiko; immer Caller-
curdurchreichen. -
Transaktion ohne SAVEPOINT bei Multi-Row-Import — ein Fehler killt gesamten Import + opaque „transaction aborted“.
-
Blindes Vorlagen-Delimiter — regionaler Export bricht Mapping.
-
Nutzer-Mappings ohne Validierung — #71; Copy-from-System muss durch Validator.
-
Dry-Run ohne
import_row_processing— Admin „Format prüfen“ unvollständig vs. echter Import. -
source-CHECK in DB vergessen — Import setztcsv, Constraint muss Migration sein. -
NUMERIC-Overflow durch falsche Einheit — Schema +
source_unit+ Migrationbreite gemeinsam planen. -
Interpretation/Auswertung beim Import — Scores, TDEE, Training-Quality nicht in
executor.py. -
Executor-Monolith ohne Modul-Split —
executor.pywä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
- Registry-Meta: REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md
- Import-Grenze: ARCHITECTURE.md §8
- Feature-Limits: 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 | ✅ |