[FEATURE] Universeller CSV-Parser mit lernbarem Feldmapping #19

Closed
opened 2026-03-23 15:35:50 +01:00 by Lars · 1 comment
Owner

Feature Request: Universeller CSV-Parser

Beschreibung

Ein modul�bergreifendes CSV-Import-System, das Feldmappings abfragt, erlernt und f�r verschiedene Datenquellen wiederverwendet.

Motivation

Aktuell gibt es separate CSV-Import-Endpunkte f�r:

  • Ern�hrung (FDDB)
  • Aktivit�t (Apple Health)
  • Schlaf (Apple Health)
  • Vitalwerte (Omron, Apple Health)

Jeder Import hat hardcodierte Feldnamen. Bei neuen Formaten oder Apps muss der Code angepasst werden.

Ziel

Ein universeller Parser, der:

  1. CSV hochladen ? Spalten erkennen
  2. Nutzer fragt: "Welches Feld ist 'Datum'?" ? Dropdown mit Spalten
  3. Mapping speichert (DB: csv_field_mappings)
  4. Beim n�chsten Import: automatisch erkennen (Fingerprint: Spalten-Hash)
  5. Werte direkt in Zielmodul importieren (weight_log, nutrition_log, activity_log, etc.)

Anforderungen

1. Feldmapping-Assistent (UI)

Flow:

  • CSV hochladen
  • System erkennt Spalten: ["Datum", "Gewicht (kg)", "Notiz"]
  • Falls unbekannt: Mapping-Dialog
    Zielmodul: [Dropdown: Gewicht | Ern�hrung | Aktivit�t | Schlaf | Vitalwerte]
    
    Feldmappings:
    CSV-Spalte "Datum"       ? [Dropdown: date | created_at | timestamp | ---]
    CSV-Spalte "Gewicht"     ? [Dropdown: weight | value | ---]
    CSV-Spalte "Notiz"       ? [Dropdown: note | comment | ---]
    
    [?] Mapping speichern f�r zuk�nftige Importe
    

2. Datenbankschema

Tabelle: csv_field_mappings

CREATE TABLE csv_field_mappings (
  id UUID PRIMARY KEY,
  profile_id UUID REFERENCES profiles(id),  -- NULL = global
  target_module VARCHAR(50),  -- \"weight\", \"nutrition\", \"activity\", etc.
  source_fingerprint VARCHAR(64),  -- SHA256 Hash der Spalten (sortiert)
  source_name VARCHAR(100),  -- z.B. \"Withings Export\", \"MyFitnessPal CSV\"
  field_mappings JSONB,  -- {\"Datum\": \"date\", \"Gewicht (kg)\": \"weight\"}
  created_at TIMESTAMP DEFAULT NOW()
);

Fingerprint-Berechnung:

import hashlib, json
columns = sorted([\"Datum\", \"Gewicht (kg)\", \"Notiz\"])
fingerprint = hashlib.sha256(json.dumps(columns).encode()).hexdigest()

3. API-Endpunkte

POST /api/import/universal

  • Body: multipart/form-data mit CSV-Datei
  • R�ckgabe:
    • Falls bekannt: {\"fingerprint\": \"abc123\", \"mapping_id\": \"uuid\", \"preview\": [...]}
    • Falls unbekannt: {\"fingerprint\": \"abc123\", \"columns\": [\"Datum\", ...], \"needs_mapping\": true}

POST /api/import/universal/map

  • Body: {\"fingerprint\": \"abc123\", \"target_module\": \"weight\", \"mappings\": {...}, \"source_name\": \"...\"}
  • Speichert Mapping in DB
  • F�hrt Import aus

GET /api/import/mappings

  • Zeigt alle gespeicherten Mappings (global + user-spezifisch)

DELETE /api/import/mappings/{id}

  • L�scht Mapping

4. Modul-Integration

Jeder Zielmodul definiert erforderliche Felder:

MODULE_SCHEMAS = {
    \"weight\": {
        \"required\": [\"date\", \"weight\"],
        \"optional\": [\"note\"],
        \"target_table\": \"weight_log\"
    },
    \"nutrition\": {
        \"required\": [\"date\", \"kcal\"],
        \"optional\": [\"protein_g\", \"fat_g\", \"carbs_g\"],
        \"target_table\": \"nutrition_log\"
    },
    # ...
}

5. UI-Komponente

UniversalCsvImport.jsx

  • Drag & Drop Upload
  • Falls Mapping bekannt: "Import starten"
  • Falls unbekannt: Mapping-Dialog
  • History: Liste aller Mappings mit Edit/Delete

Integration in Module:

  • WeightScreen, NutritionPage, ActivityPage, SleepPage, VitalsPage
  • Zus�tzlicher Tab "Universal-Import" neben den spezifischen Imports

Vorteile

? Flexibilit�t: Neue Apps/Formate ohne Code-�nderung
? Lernf�hig: Einmal mappen ? immer verf�gbar
? Nutzerfreundlich: Visuelles Mapping statt manueller Spalten-Umbennung
? Wiederverwendbar: Mappings teilen (global/user-spezifisch)
? Zukunftssicher: Beliebige CSV-Quellen unterst�tzen

Beispiel-Workflow

  1. Nutzer l�dt "withings_export.csv" hoch (noch nie gesehen)
  2. System: "Unbekanntes Format. Spalten: [Date, Weight (kg), Fat Mass (kg)]"
  3. Nutzer mappt:
    • Date ? date
    • Weight (kg) ? weight
    • Fat Mass (kg) ? (ignorieren)
  4. System: "Mapping gespeichert als \"Withings Export\""
  5. Import: 120 Zeilen ? weight_log
  6. N�chstes Mal: Withings CSV ? automatisch erkannt ? 1-Klick-Import

Technische Details

  • Parser: csv Modul (Python stdlib)
  • Encoding-Erkennung: chardet f�r UTF-8/ISO-8859-1
  • Validierung: Pydantic Models pro Zielmodul
  • Duplikat-Erkennung: Wie bei bestehenden Imports (date-basiert)
  • Logging: Fehlerhafte Zeilen �berspringen, in Import-Report auflisten

Phasen

Phase 1: MVP

  • Tabelle csv_field_mappings
  • Fingerprint-Berechnung
  • POST /api/import/universal (Erkennung)
  • POST /api/import/universal/map (Speichern + Import)
  • Modul-Schema f�r weight
  • Basis-UI: Mapping-Dialog

Phase 2: Erweitert

  • Alle Module (nutrition, activity, sleep, vitals, circumference, caliper)
  • GET /api/import/mappings (History)
  • DELETE Mappings
  • Mapping bearbeiten (Update)
  • Global vs. User-spezifisch

Phase 3: Komfort

  • Auto-Suggest ("Spalte \"Gewicht\" ? wahrscheinlich weight")
  • Datentyp-Validierung ("Spalte enth�lt keine Zahlen ? kann nicht \"weight\" sein")
  • Vorschau vor Import (erste 5 Zeilen)
  • Einheiten-Konvertierung (lbs ? kg, etc.)

Priorit�t

Medium � Nice-to-have f�r v9e/v9f

Labels

feature, develop

# Feature Request: Universeller CSV-Parser ## Beschreibung Ein modul�bergreifendes CSV-Import-System, das Feldmappings abfragt, erlernt und f�r verschiedene Datenquellen wiederverwendet. ## Motivation Aktuell gibt es separate CSV-Import-Endpunkte f�r: - Ern�hrung (FDDB) - Aktivit�t (Apple Health) - Schlaf (Apple Health) - Vitalwerte (Omron, Apple Health) Jeder Import hat hardcodierte Feldnamen. Bei neuen Formaten oder Apps muss der Code angepasst werden. ## Ziel Ein **universeller Parser**, der: 1. CSV hochladen ? Spalten erkennen 2. Nutzer fragt: "Welches Feld ist 'Datum'?" ? Dropdown mit Spalten 3. Mapping speichert (DB: `csv_field_mappings`) 4. Beim n�chsten Import: automatisch erkennen (Fingerprint: Spalten-Hash) 5. Werte direkt in Zielmodul importieren (weight_log, nutrition_log, activity_log, etc.) ## Anforderungen ### 1. Feldmapping-Assistent (UI) **Flow:** - CSV hochladen - System erkennt Spalten: `["Datum", "Gewicht (kg)", "Notiz"]` - Falls unbekannt: Mapping-Dialog ``` Zielmodul: [Dropdown: Gewicht | Ern�hrung | Aktivit�t | Schlaf | Vitalwerte] Feldmappings: CSV-Spalte "Datum" ? [Dropdown: date | created_at | timestamp | ---] CSV-Spalte "Gewicht" ? [Dropdown: weight | value | ---] CSV-Spalte "Notiz" ? [Dropdown: note | comment | ---] [?] Mapping speichern f�r zuk�nftige Importe ``` ### 2. Datenbankschema **Tabelle: `csv_field_mappings`** ```sql CREATE TABLE csv_field_mappings ( id UUID PRIMARY KEY, profile_id UUID REFERENCES profiles(id), -- NULL = global target_module VARCHAR(50), -- \"weight\", \"nutrition\", \"activity\", etc. source_fingerprint VARCHAR(64), -- SHA256 Hash der Spalten (sortiert) source_name VARCHAR(100), -- z.B. \"Withings Export\", \"MyFitnessPal CSV\" field_mappings JSONB, -- {\"Datum\": \"date\", \"Gewicht (kg)\": \"weight\"} created_at TIMESTAMP DEFAULT NOW() ); ``` **Fingerprint-Berechnung:** ```python import hashlib, json columns = sorted([\"Datum\", \"Gewicht (kg)\", \"Notiz\"]) fingerprint = hashlib.sha256(json.dumps(columns).encode()).hexdigest() ``` ### 3. API-Endpunkte **POST /api/import/universal** - Body: `multipart/form-data` mit CSV-Datei - R�ckgabe: - Falls bekannt: `{\"fingerprint\": \"abc123\", \"mapping_id\": \"uuid\", \"preview\": [...]}` - Falls unbekannt: `{\"fingerprint\": \"abc123\", \"columns\": [\"Datum\", ...], \"needs_mapping\": true}` **POST /api/import/universal/map** - Body: `{\"fingerprint\": \"abc123\", \"target_module\": \"weight\", \"mappings\": {...}, \"source_name\": \"...\"}` - Speichert Mapping in DB - F�hrt Import aus **GET /api/import/mappings** - Zeigt alle gespeicherten Mappings (global + user-spezifisch) **DELETE /api/import/mappings/{id}** - L�scht Mapping ### 4. Modul-Integration Jeder Zielmodul definiert **erforderliche Felder**: ```python MODULE_SCHEMAS = { \"weight\": { \"required\": [\"date\", \"weight\"], \"optional\": [\"note\"], \"target_table\": \"weight_log\" }, \"nutrition\": { \"required\": [\"date\", \"kcal\"], \"optional\": [\"protein_g\", \"fat_g\", \"carbs_g\"], \"target_table\": \"nutrition_log\" }, # ... } ``` ### 5. UI-Komponente **UniversalCsvImport.jsx** - Drag & Drop Upload - Falls Mapping bekannt: "Import starten" - Falls unbekannt: Mapping-Dialog - History: Liste aller Mappings mit Edit/Delete **Integration in Module:** - WeightScreen, NutritionPage, ActivityPage, SleepPage, VitalsPage - Zus�tzlicher Tab "Universal-Import" neben den spezifischen Imports ## Vorteile ? **Flexibilit�t:** Neue Apps/Formate ohne Code-�nderung ? **Lernf�hig:** Einmal mappen ? immer verf�gbar ? **Nutzerfreundlich:** Visuelles Mapping statt manueller Spalten-Umbennung ? **Wiederverwendbar:** Mappings teilen (global/user-spezifisch) ? **Zukunftssicher:** Beliebige CSV-Quellen unterst�tzen ## Beispiel-Workflow 1. **Nutzer l�dt \"withings_export.csv\" hoch** (noch nie gesehen) 2. **System:** \"Unbekanntes Format. Spalten: [Date, Weight (kg), Fat Mass (kg)]\" 3. **Nutzer mappt:** - Date ? date - Weight (kg) ? weight - Fat Mass (kg) ? (ignorieren) 4. **System:** \"Mapping gespeichert als \\\"Withings Export\\\"\" 5. **Import:** 120 Zeilen ? weight_log 6. **N�chstes Mal:** Withings CSV ? automatisch erkannt ? 1-Klick-Import ## Technische Details - **Parser:** `csv` Modul (Python stdlib) - **Encoding-Erkennung:** `chardet` f�r UTF-8/ISO-8859-1 - **Validierung:** Pydantic Models pro Zielmodul - **Duplikat-Erkennung:** Wie bei bestehenden Imports (date-basiert) - **Logging:** Fehlerhafte Zeilen �berspringen, in Import-Report auflisten ## Phasen ### Phase 1: MVP - [ ] Tabelle `csv_field_mappings` - [ ] Fingerprint-Berechnung - [ ] POST /api/import/universal (Erkennung) - [ ] POST /api/import/universal/map (Speichern + Import) - [ ] Modul-Schema f�r `weight` - [ ] Basis-UI: Mapping-Dialog ### Phase 2: Erweitert - [ ] Alle Module (nutrition, activity, sleep, vitals, circumference, caliper) - [ ] GET /api/import/mappings (History) - [ ] DELETE Mappings - [ ] Mapping bearbeiten (Update) - [ ] Global vs. User-spezifisch ### Phase 3: Komfort - [ ] Auto-Suggest (\"Spalte \\\"Gewicht\\\" ? wahrscheinlich weight\") - [ ] Datentyp-Validierung (\"Spalte enth�lt keine Zahlen ? kann nicht \\\"weight\\\" sein\") - [ ] Vorschau vor Import (erste 5 Zeilen) - [ ] Einheiten-Konvertierung (lbs ? kg, etc.) ## Priorit�t **Medium** � Nice-to-have f�r v9e/v9f ## Labels `feature`, `develop`
Lars added the
feature
develop
labels 2026-03-23 15:35:50 +01:00
Lars closed this issue 2026-03-23 15:37:58 +01:00
Author
Owner

Duplikat von #21

Duplikat von #21
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Lars/mitai-jinkendo#19
No description provided.