updated apps
This commit is contained in:
@@ -28,8 +28,9 @@ def _export_documents(doc_store: Any, object_id: str) -> list[dict[str, Any]]:
|
||||
File binaries are NOT in the JSON export (they live under /config and travel
|
||||
via the HA backup). An import without a matching backup therefore recreates
|
||||
file metadata pointing at a missing blob — the storage-hygiene repair issue
|
||||
catches those as dangling. Web-links round-trip fully. task_ids are dropped:
|
||||
tasks get fresh ids on import, so the links wouldn't resolve.
|
||||
catches those as dangling. Web-links round-trip fully. ``task_ids`` are
|
||||
carried too (as the OLD task ids); the importer remaps them onto the fresh
|
||||
task ids so a doc's task links survive a backup/restore.
|
||||
"""
|
||||
out: list[dict[str, Any]] = []
|
||||
for d in doc_store.for_object(object_id):
|
||||
@@ -40,6 +41,8 @@ def _export_documents(doc_store: Any, object_id: str) -> list[dict[str, Any]]:
|
||||
"url": d.get("url"),
|
||||
"title": d.get("title"),
|
||||
"tags": d.get("tags") or [],
|
||||
"task_ids": d.get("task_ids") or [],
|
||||
"part_ids": d.get("part_ids") or [],
|
||||
}
|
||||
)
|
||||
else:
|
||||
@@ -52,6 +55,8 @@ def _export_documents(doc_store: Any, object_id: str) -> list[dict[str, Any]]:
|
||||
"mime": d.get("mime"),
|
||||
"size": d.get("size"),
|
||||
"tags": d.get("tags") or [],
|
||||
"task_ids": d.get("task_ids") or [],
|
||||
"part_ids": d.get("part_ids") or [],
|
||||
}
|
||||
)
|
||||
return out
|
||||
@@ -81,6 +86,14 @@ def _build_export_object(
|
||||
"name": tdata.get("name", ""),
|
||||
"type": tdata.get("type", "custom"),
|
||||
"enabled": tdata.get("enabled", True),
|
||||
# Provenance + lifecycle a backup must preserve: created_at is the
|
||||
# next_due fallback anchor when last_performed is None (dropping it
|
||||
# silently shifts due dates on restore), and the archived_* pair
|
||||
# keeps a retired task retired — without them an archived task comes
|
||||
# back ACTIVE after a restore.
|
||||
"created_at": tdata.get("created_at"),
|
||||
"archived_at": tdata.get("archived_at"),
|
||||
"archived_reason": tdata.get("archived_reason"),
|
||||
"schedule_type": sched["schedule_type"],
|
||||
"interval_days": sched["interval_days"],
|
||||
"interval_unit": sched["interval_unit"],
|
||||
@@ -115,6 +128,9 @@ def _build_export_object(
|
||||
"assignee_pool": tdata.get("assignee_pool") or [],
|
||||
"rotation_strategy": tdata.get("rotation_strategy"),
|
||||
"reading_unit": tdata.get("reading_unit"),
|
||||
# Spare parts: consumption links + the auto-buy-task marker.
|
||||
"consumes_parts": tdata.get("consumes_parts"),
|
||||
"part_ref": tdata.get("part_ref"),
|
||||
"status": ct.get("_status", "ok"),
|
||||
"days_until_due": ct.get("_days_until_due"),
|
||||
"next_due": ct.get("_next_due"),
|
||||
@@ -168,20 +184,39 @@ def _build_export_object(
|
||||
},
|
||||
"tasks": tasks,
|
||||
"documents": documents,
|
||||
# Spare parts: full static definition + the tracked stock (dynamic,
|
||||
# read from the Store) so a backup/restore keeps the shelf state.
|
||||
"parts": [
|
||||
{**part, "stock": store.get_part_stock(part["id"]) if store is not None else None}
|
||||
for part in (entry.data.get("parts") or {}).values()
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def object_entries(hass: HomeAssistant, entry_ids: set[str] | None = None) -> list[ConfigEntry]:
|
||||
"""The maintenance OBJECT entries (never the global hub), optionally
|
||||
narrowed to a selection. Shared by every exporter so JSON/YAML/CSV apply
|
||||
the same selective-export filter. ``entry_ids=None`` means all objects."""
|
||||
return [
|
||||
entry
|
||||
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||
if entry.unique_id != GLOBAL_UNIQUE_ID and (entry_ids is None or entry.entry_id in entry_ids)
|
||||
]
|
||||
|
||||
|
||||
def build_export_data(
|
||||
hass: HomeAssistant,
|
||||
include_history: bool = True,
|
||||
entry_ids: set[str] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Gather all maintenance data into a plain dict.
|
||||
|
||||
This must be called from the event loop (accesses HA APIs).
|
||||
The returned dict contains no HA objects and is safe to
|
||||
serialize in an executor thread.
|
||||
serialize in an executor thread. ``entry_ids`` narrows the export to a
|
||||
selection of objects (None = all).
|
||||
"""
|
||||
entries = [entry for entry in hass.config_entries.async_entries(DOMAIN) if entry.unique_id != GLOBAL_UNIQUE_ID]
|
||||
entries = object_entries(hass, entry_ids)
|
||||
|
||||
objects = []
|
||||
for entry in entries:
|
||||
|
||||
Reference in New Issue
Block a user