fix: vitals_baseline dynamic query parameter mismatch
**Bug:** POST /api/vitals/baseline threw UndefinedParameter **Cause:** Dynamic SQL generation had desynchronized column names and placeholders **Fix:** Rewrote to use synchronized insert_cols, insert_placeholders, update_fields arrays - Track param_idx correctly (start at 3 after pid and date) - Build INSERT columns and placeholders in parallel - Cleaner, more maintainable code - Fixes Ruhepuls entry error
This commit is contained in:
parent
378bf434fc
commit
37ea1f8537
|
|
@ -99,52 +99,83 @@ def create_or_update_baseline(
|
|||
"""Create or update baseline entry (upsert on date)."""
|
||||
pid = get_pid(x_profile_id)
|
||||
|
||||
# Build dynamic update columns (only non-None fields)
|
||||
fields = []
|
||||
# Build dynamic INSERT columns and UPDATE fields
|
||||
insert_cols = []
|
||||
insert_placeholders = []
|
||||
update_fields = []
|
||||
values = [pid, entry.date]
|
||||
param_idx = 3 # Start after $1 (pid) and $2 (date)
|
||||
|
||||
if entry.resting_hr is not None:
|
||||
fields.append("resting_hr = COALESCE(EXCLUDED.resting_hr, vitals_baseline.resting_hr)")
|
||||
insert_cols.append("resting_hr")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"resting_hr = COALESCE(EXCLUDED.resting_hr, vitals_baseline.resting_hr)")
|
||||
values.append(entry.resting_hr)
|
||||
param_idx += 1
|
||||
|
||||
if entry.hrv is not None:
|
||||
fields.append("hrv = COALESCE(EXCLUDED.hrv, vitals_baseline.hrv)")
|
||||
insert_cols.append("hrv")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"hrv = COALESCE(EXCLUDED.hrv, vitals_baseline.hrv)")
|
||||
values.append(entry.hrv)
|
||||
param_idx += 1
|
||||
|
||||
if entry.vo2_max is not None:
|
||||
fields.append("vo2_max = COALESCE(EXCLUDED.vo2_max, vitals_baseline.vo2_max)")
|
||||
insert_cols.append("vo2_max")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"vo2_max = COALESCE(EXCLUDED.vo2_max, vitals_baseline.vo2_max)")
|
||||
values.append(entry.vo2_max)
|
||||
param_idx += 1
|
||||
|
||||
if entry.spo2 is not None:
|
||||
fields.append("spo2 = COALESCE(EXCLUDED.spo2, vitals_baseline.spo2)")
|
||||
insert_cols.append("spo2")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"spo2 = COALESCE(EXCLUDED.spo2, vitals_baseline.spo2)")
|
||||
values.append(entry.spo2)
|
||||
param_idx += 1
|
||||
|
||||
if entry.respiratory_rate is not None:
|
||||
fields.append("respiratory_rate = COALESCE(EXCLUDED.respiratory_rate, vitals_baseline.respiratory_rate)")
|
||||
insert_cols.append("respiratory_rate")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"respiratory_rate = COALESCE(EXCLUDED.respiratory_rate, vitals_baseline.respiratory_rate)")
|
||||
values.append(entry.respiratory_rate)
|
||||
param_idx += 1
|
||||
|
||||
if entry.body_temperature is not None:
|
||||
fields.append("body_temperature = COALESCE(EXCLUDED.body_temperature, vitals_baseline.body_temperature)")
|
||||
insert_cols.append("body_temperature")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"body_temperature = COALESCE(EXCLUDED.body_temperature, vitals_baseline.body_temperature)")
|
||||
values.append(entry.body_temperature)
|
||||
param_idx += 1
|
||||
|
||||
if entry.resting_metabolic_rate is not None:
|
||||
fields.append("resting_metabolic_rate = COALESCE(EXCLUDED.resting_metabolic_rate, vitals_baseline.resting_metabolic_rate)")
|
||||
insert_cols.append("resting_metabolic_rate")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"resting_metabolic_rate = COALESCE(EXCLUDED.resting_metabolic_rate, vitals_baseline.resting_metabolic_rate)")
|
||||
values.append(entry.resting_metabolic_rate)
|
||||
param_idx += 1
|
||||
|
||||
if entry.note:
|
||||
fields.append("note = COALESCE(EXCLUDED.note, vitals_baseline.note)")
|
||||
insert_cols.append("note")
|
||||
insert_placeholders.append(f"${param_idx}")
|
||||
update_fields.append(f"note = COALESCE(EXCLUDED.note, vitals_baseline.note)")
|
||||
values.append(entry.note)
|
||||
param_idx += 1
|
||||
|
||||
# At least one field must be provided
|
||||
if not fields:
|
||||
if not insert_cols:
|
||||
raise HTTPException(400, "At least one baseline vital must be provided")
|
||||
|
||||
# Build value placeholders
|
||||
placeholders = ", ".join([f"${i}" for i in range(1, len(values) + 1)])
|
||||
|
||||
with get_db() as conn:
|
||||
cur = get_cursor(conn)
|
||||
query = f"""
|
||||
INSERT INTO vitals_baseline (profile_id, date, {', '.join([f.split('=')[0].strip() for f in fields])})
|
||||
VALUES ($1, $2, {', '.join([f'${i}' for i in range(3, len(values) + 1)])})
|
||||
INSERT INTO vitals_baseline (profile_id, date, {', '.join(insert_cols)})
|
||||
VALUES ($1, $2, {', '.join(insert_placeholders)})
|
||||
ON CONFLICT (profile_id, date)
|
||||
DO UPDATE SET {', '.join(fields)}, updated_at = NOW()
|
||||
DO UPDATE SET {', '.join(update_fields)}, updated_at = NOW()
|
||||
RETURNING *
|
||||
"""
|
||||
cur.execute(query, values)
|
||||
cur.execute(query, tuple(values))
|
||||
return r2d(cur.fetchone())
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user