"""Apply parsed BLS 4.0 data: upsert attributes and foods, never delete official rows.""" from __future__ import annotations from typing import Any def upsert_attributes(cur, attributes: list[dict[str, Any]]) -> dict[str, int]: inserted = updated = 0 for a in attributes: cur.execute( """ INSERT INTO food_attributes (attr_key, name_de, name_en, unit, category, data_type, origin, sort_order, updated_at) VALUES (%s, %s, %s, %s, %s, %s, 'official_bls', %s, NOW()) ON CONFLICT (attr_key) DO UPDATE SET name_de = EXCLUDED.name_de, name_en = COALESCE(EXCLUDED.name_en, food_attributes.name_en), unit = COALESCE(EXCLUDED.unit, food_attributes.unit), category = COALESCE(EXCLUDED.category, food_attributes.category), sort_order = EXCLUDED.sort_order, updated_at = NOW() WHERE food_attributes.origin = 'official_bls' RETURNING (xmax = 0) AS inserted """, ( a["attr_key"], a["name_de"], a.get("name_en"), a.get("unit"), a.get("category"), a.get("data_type") or "num_per_100g", a.get("sort_order") or 0, ), ) row = cur.fetchone() if row and row.get("inserted"): inserted += 1 else: updated += 1 return {"inserted": inserted, "updated": updated, "total": len(attributes)} def upsert_foods(cur, foods: list[dict[str, Any]], bls_version: str = "4.0") -> dict[str, int]: cur.execute("SELECT attr_key, id FROM food_attributes") attr_ids = {r["attr_key"]: r["id"] for r in cur.fetchall()} inserted = updated = values_written = 0 for f in foods: code = f["bls_code"] cur.execute("SELECT id FROM food_catalog WHERE bls_code = %s", (code,)) existing = cur.fetchone() if existing: food_id = existing["id"] cur.execute( """ UPDATE food_catalog SET name_de=%s, name_en=%s, food_group=%s, bls_version=%s, catalog_kind='official_bls', source='bls_4.0', is_active=true, updated_at=NOW() WHERE id=%s AND catalog_kind='official_bls' """, (f["name_de"], f.get("name_en"), f.get("food_group"), bls_version, food_id), ) updated += 1 else: cur.execute( """ INSERT INTO food_catalog (bls_code, name_de, name_en, food_group, catalog_kind, bls_version, source) VALUES (%s, %s, %s, %s, 'official_bls', %s, 'bls_4.0') RETURNING id """, (code, f["name_de"], f.get("name_en"), f.get("food_group"), bls_version), ) food_id = cur.fetchone()["id"] inserted += 1 for val in f.get("values") or []: aid = attr_ids.get(val["attr_key"]) if not aid: continue if val.get("is_trace"): cur.execute( """ INSERT INTO food_attribute_values (food_id, attribute_id, value_num, is_trace, origin_code, reference_text, updated_at) VALUES (%s, %s, NULL, true, %s, %s, NOW()) ON CONFLICT (food_id, attribute_id) DO UPDATE SET value_num = NULL, is_trace = true, origin_code = EXCLUDED.origin_code, reference_text = EXCLUDED.reference_text, updated_at = NOW() """, (food_id, aid, val.get("origin_code"), val.get("reference_text")), ) elif val.get("value_num") is None: cur.execute( """ INSERT INTO food_attribute_values (food_id, attribute_id, value_num, is_trace, origin_code, reference_text, updated_at) VALUES (%s, %s, NULL, false, %s, %s, NOW()) ON CONFLICT (food_id, attribute_id) DO UPDATE SET value_num = NULL, is_trace = false, origin_code = EXCLUDED.origin_code, reference_text = EXCLUDED.reference_text, updated_at = NOW() """, (food_id, aid, val.get("origin_code"), val.get("reference_text")), ) else: cur.execute( """ INSERT INTO food_attribute_values (food_id, attribute_id, value_num, is_trace, origin_code, reference_text, updated_at) VALUES (%s, %s, %s, false, %s, %s, NOW()) ON CONFLICT (food_id, attribute_id) DO UPDATE SET value_num = EXCLUDED.value_num, is_trace = false, origin_code = EXCLUDED.origin_code, reference_text = EXCLUDED.reference_text, updated_at = NOW() """, ( food_id, aid, val["value_num"], val.get("origin_code"), val.get("reference_text"), ), ) values_written += 1 return { "foods_inserted": inserted, "foods_updated": updated, "values_written": values_written, "foods_total": len(foods), }