updated apps

This commit is contained in:
2026-07-14 23:57:03 -04:00
parent 6cc7212cef
commit 010e828e9c
797 changed files with 45153 additions and 4246 deletions
@@ -105,6 +105,18 @@ class MaintenanceStore:
del state[key]
clean[tid] = state
data["tasks"] = clean
# Spare-part stock counts ({part_id: {"stock": int}}) — same shape
# discipline as tasks: a malformed section degrades to "untracked".
parts = data.get("parts")
if parts is not None and not isinstance(parts, dict):
_LOGGER.warning("Store 'parts' is %s, expected dict — resetting stock state", type(parts).__name__)
data["parts"] = {}
elif isinstance(parts, dict):
data["parts"] = {
pid: dict(state)
for pid, state in parts.items()
if isinstance(state, dict)
}
return data
def async_delay_save(self) -> None:
@@ -168,6 +180,43 @@ class MaintenanceStore:
del tasks[tid]
return len(orphaned)
# --- spare-part stock (mutable count; static part defs live in entry.data) ---
def get_part_stock(self, part_id: str) -> int | None:
"""On-hand count for a part, or None when inventory isn't tracked."""
state = self._data.get("parts", {}).get(part_id, {})
stock = state.get("stock")
return int(stock) if isinstance(stock, int) else None
def all_part_stocks(self) -> dict[str, int | None]:
"""{part_id: stock} for every tracked part."""
return {pid: self.get_part_stock(pid) for pid in self._data.get("parts", {})}
def set_part_stock(self, part_id: str, stock: int | None) -> None:
"""Set (or untrack with None) a part's on-hand count, clamped to
[0, MAX_PART_STOCK]. The WS schemas cap each INPUT at MAX_PART_STOCK,
but additive paths (restock delta / buy-task completion) could push
the SUM past it — this chokepoint clamp keeps every writer honest."""
from .helpers.parts import MAX_PART_STOCK
parts: dict[str, Any] = self._data.setdefault("parts", {})
if stock is None:
parts.pop(part_id, None)
else:
parts.setdefault(part_id, {})["stock"] = min(max(0, int(stock)), MAX_PART_STOCK)
def remove_part(self, part_id: str) -> None:
"""Drop a deleted part's stock state."""
self._data.get("parts", {}).pop(part_id, None)
def prune_part_orphans(self, valid_part_ids: set[str]) -> int:
"""Drop stock states whose part ids no longer exist (journey-I1 twin)."""
parts = self._data.get("parts", {})
orphaned = [pid for pid in parts if pid not in valid_part_ids]
for pid in orphaned:
del parts[pid]
return len(orphaned)
# --- last_performed ---
def get_last_performed(self, task_id: str) -> str | None: