Updated apps
This commit is contained in:
@@ -337,6 +337,68 @@ async def ws_subscribe(
|
||||
_forward_update()
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): f"{DOMAIN}/schedule/preview",
|
||||
# A DRAFT schedule in Schedule.to_dict form — validated leniently by
|
||||
# Schedule.from_dict (unknown kinds sanitize to manual → empty result).
|
||||
vol.Required("schedule"): dict,
|
||||
vol.Optional("last_performed"): vol.Any(str, None),
|
||||
vol.Optional("times_performed", default=0): vol.All(int, vol.Range(min=0, max=100000)),
|
||||
vol.Optional("count", default=3): vol.All(int, vol.Range(min=1, max=10)),
|
||||
}
|
||||
)
|
||||
@websocket_api.async_response
|
||||
async def ws_schedule_preview(
|
||||
hass: HomeAssistant,
|
||||
connection: websocket_api.ActiveConnection,
|
||||
msg: dict[str, Any],
|
||||
) -> None:
|
||||
"""Next N occurrences of a draft schedule — computed by the REAL engine.
|
||||
|
||||
Powers the task dialog's live "next dates" preview (#83 roadmap item).
|
||||
Stateless and read-only: instantiates Schedule.from_dict and iterates
|
||||
next_due(), simulating an ON-TIME completion per step (last_performed /
|
||||
last_planned_due advance, times_performed increments) — so completion-
|
||||
anchored intervals, calendar kinds, season windows, business-day rolls,
|
||||
±offsets and finite series all advance exactly as the engine would.
|
||||
Never a frontend reimplementation (the #103 drift lesson).
|
||||
"""
|
||||
from datetime import date as date_cls
|
||||
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from ..helpers.schedule import Schedule, preview_occurrences
|
||||
|
||||
lp: date_cls | None = None
|
||||
raw_lp = msg.get("last_performed")
|
||||
if raw_lp:
|
||||
try:
|
||||
lp = date_cls.fromisoformat(raw_lp)
|
||||
except ValueError:
|
||||
connection.send_error(msg["id"], "invalid_date", "Invalid last_performed (expected YYYY-MM-DD)")
|
||||
return
|
||||
|
||||
today = dt_util.now().date()
|
||||
try:
|
||||
sched = Schedule.from_dict(msg["schedule"])
|
||||
dates, series_ended = preview_occurrences(
|
||||
sched,
|
||||
last_performed=lp,
|
||||
times_performed=int(msg.get("times_performed", 0)),
|
||||
today=today,
|
||||
count=int(msg.get("count", 3)),
|
||||
)
|
||||
except (TypeError, ValueError) as err:
|
||||
connection.send_error(msg["id"], "invalid_input", f"Invalid schedule: {err}")
|
||||
return
|
||||
|
||||
connection.send_result(
|
||||
msg["id"],
|
||||
{"occurrences": [d.isoformat() for d in dates], "series_ended": series_ended},
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command({vol.Required("type"): f"{DOMAIN}/budget_status"})
|
||||
@websocket_api.async_response
|
||||
async def ws_get_budget_status(
|
||||
|
||||
Reference in New Issue
Block a user