From 9d47c4ef84bb206ab7125d4a0605bdf1bd88d342 Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 15 Apr 2026 10:28:13 +0200 Subject: [PATCH] feat: Update session metrics handling for CSV-mapped values - Enhanced the docstring for `upsert_session_metrics_from_csv_mapped` to clarify the handling of schema parameters and EAV logic. - Modified the condition for skipping updates based on `source_field` to ensure only patchable columns are processed, improving data integrity during session metrics upsert operations. --- .../data_layer/activity_session_metrics.py | 14 ++++++-- ..._per_km_trigger_no_overwrite_on_update.sql | 35 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 backend/migrations/056_activity_kcal_per_km_trigger_no_overwrite_on_update.sql diff --git a/backend/data_layer/activity_session_metrics.py b/backend/data_layer/activity_session_metrics.py index 6e3de0e..69109e7 100644 --- a/backend/data_layer/activity_session_metrics.py +++ b/backend/data_layer/activity_session_metrics.py @@ -313,7 +313,17 @@ def upsert_session_metrics_from_csv_mapped( training_category: Optional[str], training_type_id: Optional[int], ) -> None: - """EAV nur für Schema-Parameter ohne source_field (reine Session-Metriken).""" + """ + EAV für Schema-Parameter aus CSV-mapped Werten. + + Spalten-gestützte Parameter (source_field ∈ ACTIVITY_LOG_PATCHABLE_COLUMNS) werden + ausschließlich über resolve_activity_log_column_patch_from_csv → activity_log + geschrieben — hier kein EAV. + + Wenn source_field gesetzt ist, aber **kein** patchbarer Spaltenname (z. B. eigener + Key „stola“ wie der Parametername), wäre früher weder Spalten-Update noch EAV erfolgt; + dann EAV wie bei reinen Metriken. + """ cur.execute( "SELECT profile_id FROM activity_log WHERE id = %s", (activity_log_id,), @@ -330,7 +340,7 @@ def upsert_session_metrics_from_csv_mapped( if raw is None or raw == "": continue src_col = (spec.get("source_field") or "").strip() - if src_col: + if src_col and src_col in ACTIVITY_LOG_PATCHABLE_COLUMNS: continue tid = spec["training_parameter_id"] dt = spec["data_type"] diff --git a/backend/migrations/056_activity_kcal_per_km_trigger_no_overwrite_on_update.sql b/backend/migrations/056_activity_kcal_per_km_trigger_no_overwrite_on_update.sql new file mode 100644 index 0000000..b129f86 --- /dev/null +++ b/backend/migrations/056_activity_kcal_per_km_trigger_no_overwrite_on_update.sql @@ -0,0 +1,35 @@ +-- Migration 056: kcal_per_km Trigger — manuelles Leeren bei UPDATE erlauben +-- Problem: calculate_avg_hr_percent (014) setzte bei jedem UPDATE kcal_per_km aus +-- kcal_active/distance_km, sobald beide gesetzt waren — ein bewusst geleertes Feld +-- erschien sofort wieder. +-- Lösung: automatische Ableitung nur noch bei INSERT (wenn kcal_per_km noch NULL ist). + +CREATE OR REPLACE FUNCTION calculate_avg_hr_percent() +RETURNS TRIGGER AS $$ +DECLARE + user_max_hr INTEGER; +BEGIN + SELECT hf_max INTO user_max_hr + FROM profiles + WHERE id = NEW.profile_id; + + IF NEW.hr_avg IS NOT NULL AND user_max_hr IS NOT NULL AND user_max_hr > 0 THEN + NEW.avg_hr_percent := (NEW.hr_avg::float / user_max_hr::float) * 100; + END IF; + + IF TG_OP = 'INSERT' THEN + IF NEW.kcal_active IS NOT NULL AND NEW.distance_km IS NOT NULL AND NEW.distance_km > 0 THEN + IF NEW.kcal_per_km IS NULL THEN + NEW.kcal_per_km := NEW.kcal_active::float / NEW.distance_km; + END IF; + END IF; + END IF; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +DO $$ +BEGIN + RAISE NOTICE '✓ Migration 056: kcal_per_km nur noch bei INSERT auto-abgeleitet'; +END $$;