Preserve sub-component hierarchy in export/import

This commit is contained in:
2026-06-10 12:27:05 -05:00
parent d1fc80164f
commit d41fe7f4ab
2 changed files with 98 additions and 9 deletions
+28 -9
View File
@@ -1193,11 +1193,13 @@ def create_app(config_object="config"):
buf = io.StringIO()
w = csv.writer(buf)
w.writerow(["id", "name", "battery_slots", "installed_count",
"device_type", "battery_size", "location", "ha_entity_id", "notes"])
"device_type", "battery_size", "location", "ha_entity_id", "notes",
"parent_id", "parent_name"])
for d in rows:
w.writerow([d.id, d.name, d.battery_slots, d.installed_count(),
d.device_type or "", d.battery_size or "",
d.location or "", d.ha_entity_id or "", d.notes or ""])
d.location or "", d.ha_entity_id or "", d.notes or "",
d.parent_id or "", d.parent.name if d.parent else ""])
return buf.getvalue()
def _charge_logs_csv():
@@ -1296,7 +1298,9 @@ def create_app(config_object="config"):
{"id": d.id, "name": d.name, "battery_slots": d.battery_slots,
"installed_count": d.installed_count(), "device_type": d.device_type,
"battery_size": d.battery_size, "location": d.location,
"ha_entity_id": d.ha_entity_id, "notes": d.notes}
"ha_entity_id": d.ha_entity_id, "notes": d.notes,
"parent_id": d.parent_id,
"parent_name": d.parent.name if d.parent else None}
for d in devices
],
"charge_logs": [
@@ -1366,29 +1370,33 @@ def create_app(config_object="config"):
try:
# --- devices ---
for d in data.get("devices", []):
def _import_device(d, new_parent_id):
nonlocal devices_created, devices_skipped
old_id = d.get("id")
name = (d.get("name") or "").strip()
if not name:
devices_skipped += 1
continue
return
parent_key = new_parent_id if new_parent_id is not None else -1
existing = db.query(Device).filter(
Device.parent_key == -1, Device.name == name
Device.parent_key == parent_key, Device.name == name
).first()
if existing:
if old_id is not None:
device_id_map[old_id] = existing.id
devices_skipped += 1
else:
slots = d.get("battery_slots")
new_dev = Device(
name = name,
battery_slots = d.get("battery_slots") or 1,
battery_slots = slots if slots is not None else 1,
device_type = d.get("device_type") or None,
battery_size = d.get("battery_size") or "",
battery_size = d.get("battery_size") or None,
location = d.get("location") or None,
ha_entity_id = d.get("ha_entity_id") or None,
notes = d.get("notes") or None,
parent_key = -1,
parent_id = new_parent_id,
parent_key = parent_key,
)
db.add(new_dev)
db.flush()
@@ -1396,6 +1404,17 @@ def create_app(config_object="config"):
device_id_map[old_id] = new_dev.id
devices_created += 1
# Two passes so sub-components can resolve their parent's new id
# regardless of ordering in the payload. A sub whose parent is
# missing from the payload is imported as top-level.
device_rows = data.get("devices", [])
for d in device_rows:
if d.get("parent_id") is None:
_import_device(d, None)
for d in device_rows:
if d.get("parent_id") is not None:
_import_device(d, device_id_map.get(d.get("parent_id")))
# --- batteries ---
for b in data.get("batteries", []):
old_id = b.get("id")