From f506a55d7b73acb24c1bed932207086fb9e5e114 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 23 Mar 2026 16:40:49 +0100 Subject: [PATCH] fix: support German column names in CSV imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Import expected English column names, but German Apple Health/Omron exports use German names with units. Fixed: - Apple Health: Support both English and German column names - "Start" OR "Datum/Uhrzeit" - "Resting Heart Rate" OR "Ruhepuls (count/min)" - "Heart Rate Variability" OR "Herzfrequenzvariabilität (ms)" - "VO2 Max" OR "VO2 max (ml/(kg·min))" - "Oxygen Saturation" OR "Blutsauerstoffsättigung (%)" - "Respiratory Rate" OR "Atemfrequenz (count/min)" - Omron: Support column names with/without units - "Systolisch (mmHg)" OR "Systolisch" - "Diastolisch (mmHg)" OR "Diastolisch" - "Puls (bpm)" OR "Puls" - "Unregelmäßiger Herzschlag festgestellt" OR "Unregelmäßiger Herzschlag" - "Mögliches AFib" OR "Vorhofflimmern" Added debug logging for both imports to show detected columns. Co-Authored-By: Claude Opus 4.6 --- backend/routers/blood_pressure.py | 30 +++++++++++++++++++++++------- backend/routers/vitals_baseline.py | 18 ++++++++++-------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/backend/routers/blood_pressure.py b/backend/routers/blood_pressure.py index b613d3b..e22c790 100644 --- a/backend/routers/blood_pressure.py +++ b/backend/routers/blood_pressure.py @@ -310,8 +310,15 @@ async def import_omron_csv( with get_db() as conn: cur = get_cursor(conn) + # Log available columns for debugging + first_row = True + for row in reader: try: + if first_row: + logger.info(f"Omron CSV Columns: {list(row.keys())}") + first_row = False + # Parse Omron German date format date_str = row.get('Datum', row.get('Date')) time_str = row.get('Zeit', row.get('Time', '08:00')) @@ -325,18 +332,27 @@ async def import_omron_csv( errors += 1 continue - # Extract measurements - systolic = row.get('Systolisch', row.get('Systolic')) - diastolic = row.get('Diastolisch', row.get('Diastolic')) - pulse = row.get('Puls', row.get('Pulse')) + # Extract measurements (support column names with/without units) + systolic = (row.get('Systolisch (mmHg)') or row.get('Systolisch') or + row.get('Systolic (mmHg)') or row.get('Systolic')) + diastolic = (row.get('Diastolisch (mmHg)') or row.get('Diastolisch') or + row.get('Diastolic (mmHg)') or row.get('Diastolic')) + pulse = (row.get('Puls (bpm)') or row.get('Puls') or + row.get('Pulse (bpm)') or row.get('Pulse')) if not systolic or not diastolic: + logger.warning(f"Skipped row {date_str} {time_str}: Missing BP values (sys={systolic}, dia={diastolic})") skipped += 1 continue - # Parse warning flags - irregular = row.get('Unregelmäßiger Herzschlag', row.get('Irregular Heartbeat', '')) - afib = row.get('Vorhofflimmern', row.get('AFib', '')) + # Parse warning flags (support various column names) + irregular = (row.get('Unregelmäßiger Herzschlag festgestellt') or + row.get('Unregelmäßiger Herzschlag') or + row.get('Irregular Heartbeat') or '') + afib = (row.get('Mögliches AFib') or + row.get('Vorhofflimmern') or + row.get('Possible AFib') or + row.get('AFib') or '') irregular_heartbeat = irregular.lower() in ['ja', 'yes', 'true', '1'] possible_afib = afib.lower() in ['ja', 'yes', 'true', '1'] diff --git a/backend/routers/vitals_baseline.py b/backend/routers/vitals_baseline.py index 8815e64..affa695 100644 --- a/backend/routers/vitals_baseline.py +++ b/backend/routers/vitals_baseline.py @@ -320,18 +320,20 @@ async def import_apple_health_baseline( logger.info(f"CSV Columns: {list(row.keys())}") first_row = False - date = row.get('Start')[:10] if row.get('Start') else None + # Support both English and German column names + date_raw = row.get('Start') or row.get('Datum/Uhrzeit') + date = date_raw[:10] if date_raw else None if not date: - logger.warning(f"Skipped row (no date): Start='{row.get('Start')}'") + logger.warning(f"Skipped row (no date): Start='{row.get('Start')}', Datum/Uhrzeit='{row.get('Datum/Uhrzeit')}'") skipped += 1 continue - # Extract baseline vitals from Apple Health export - rhr = row.get('Resting Heart Rate') - hrv = row.get('Heart Rate Variability') - vo2 = row.get('VO2 Max') - spo2 = row.get('Oxygen Saturation') - resp_rate = row.get('Respiratory Rate') + # Extract baseline vitals (support English + German column names) + rhr = row.get('Resting Heart Rate') or row.get('Ruhepuls (count/min)') + hrv = row.get('Heart Rate Variability') or row.get('Herzfrequenzvariabilität (ms)') + vo2 = row.get('VO2 Max') or row.get('VO2 max (ml/(kg·min))') + spo2 = row.get('Oxygen Saturation') or row.get('Blutsauerstoffsättigung (%)') + resp_rate = row.get('Respiratory Rate') or row.get('Atemfrequenz (count/min)') # Skip if no baseline vitals if not any([rhr, hrv, vo2, spo2, resp_rate]):