393 files
This commit is contained in:
@@ -22,7 +22,7 @@ from .const import (
|
||||
from .helpers.aggregate import merged_tasks
|
||||
from .helpers.dates import interval_span_days, parse_hhmm
|
||||
from .helpers.global_options import is_schedule_time_enabled
|
||||
from .helpers.i18n import normalize_language
|
||||
from .helpers.i18n import format_text, normalize_language
|
||||
from .models.maintenance_task import MaintenanceTask
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -442,12 +442,8 @@ _CAL_STRINGS: dict[str, dict[str, str]] = {
|
||||
|
||||
|
||||
def _cal_t(key: str, lang: str, **kwargs: str) -> str:
|
||||
"""Get calendar translation string."""
|
||||
strings = _CAL_STRINGS.get(lang, _CAL_STRINGS["en"])
|
||||
text = strings.get(key, _CAL_STRINGS["en"].get(key, key))
|
||||
if kwargs:
|
||||
text = text.format(**kwargs)
|
||||
return text
|
||||
"""Get calendar translation string (the shared i18n.format_text)."""
|
||||
return format_text(_CAL_STRINGS, lang, key, **kwargs)
|
||||
|
||||
|
||||
# babel's get_day_names lazily reads locale data files from disk on first use
|
||||
@@ -570,10 +566,17 @@ async def async_setup_entry(
|
||||
|
||||
|
||||
|
||||
def _task_label(task: MaintenanceTask) -> str:
|
||||
"""Task name, with the due cycle phase appended for phased tasks (#139)."""
|
||||
phase = task.current_phase_name
|
||||
return f"{task.name} · {phase}" if phase else task.name
|
||||
def _task_label(task: MaintenanceTask, hass: HomeAssistant | None = None) -> str:
|
||||
"""Task name, with the due cycle phase appended for phased tasks (#139)
|
||||
and, for a calendar-driven task, the next events' titles (#189)."""
|
||||
from .helpers.calendar_source import next_event_titles
|
||||
from .helpers.phases import task_label
|
||||
|
||||
titles = next_event_titles(hass, task._schedule(), task.next_due) if hass is not None else None
|
||||
return task_label(
|
||||
{"name": task.name, "phases": task.phases, "phase_sequence": task.phase_sequence, "phase_cursor": task.phase_cursor},
|
||||
titles,
|
||||
)
|
||||
|
||||
class MaintenanceCalendar(CalendarEntity):
|
||||
"""Calendar entity aggregating all maintenance tasks."""
|
||||
@@ -678,9 +681,16 @@ class MaintenanceCalendar(CalendarEntity):
|
||||
|
||||
# Merge static (ConfigEntry) + dynamic (Store) task data
|
||||
tasks_data = merged_tasks(entry)
|
||||
schedule_time_enabled = self._is_schedule_time_feature_enabled()
|
||||
|
||||
for task_id, task_dict in tasks_data.items():
|
||||
task = MaintenanceTask.from_dict(task_dict)
|
||||
# The coordinator's feature-flag gate: with time-of-day
|
||||
# scheduling switched off a stored schedule_time must not
|
||||
# count (the fallback status below would read OVERDUE after
|
||||
# HH:MM on the due day while the sensor says due soon).
|
||||
if not schedule_time_enabled:
|
||||
task.schedule_time = None
|
||||
|
||||
if not task.enabled:
|
||||
continue
|
||||
@@ -695,7 +705,7 @@ class MaintenanceCalendar(CalendarEntity):
|
||||
if live.get("_trigger_current_value") is not None:
|
||||
task._trigger_current_value = live["_trigger_current_value"]
|
||||
|
||||
event = self._create_event_for_task(task, obj_name, start_d, end_d)
|
||||
event = self._create_event_for_task(task, obj_name, start_d, end_d, live_status=live.get("_status"))
|
||||
if event:
|
||||
events.append(event)
|
||||
|
||||
@@ -712,8 +722,17 @@ class MaintenanceCalendar(CalendarEntity):
|
||||
object_name: str,
|
||||
start_d: date,
|
||||
end_d: date,
|
||||
*,
|
||||
live_status: str | None = None,
|
||||
) -> CalendarEvent | None:
|
||||
"""Create a calendar event for a task if within range."""
|
||||
"""Create a calendar event for a task if within range.
|
||||
|
||||
``live_status`` is the coordinator's computed status; the calendar
|
||||
recomputed its own, without the schedule_time feature gate, and its
|
||||
prefix disagreed with the task sensor (bug audit 2026-09-26, DRY
|
||||
BR-A9). The model's status is only the fallback before the first
|
||||
refresh.
|
||||
"""
|
||||
lang = self._lang
|
||||
|
||||
if task.schedule_type == ScheduleType.MANUAL:
|
||||
@@ -750,7 +769,7 @@ class MaintenanceCalendar(CalendarEntity):
|
||||
if next_due < start_d or next_due > end_d:
|
||||
return None
|
||||
|
||||
status = task.status
|
||||
status = live_status or task.status
|
||||
prefix = STATUS_PREFIX.get(status, "")
|
||||
|
||||
# Build translated description
|
||||
@@ -775,7 +794,7 @@ class MaintenanceCalendar(CalendarEntity):
|
||||
end = start_dt + timedelta(minutes=30)
|
||||
|
||||
return CalendarEvent(
|
||||
summary=f"{prefix} {_task_label(task)} ({object_name})",
|
||||
summary=f"{prefix} {_task_label(task, self.hass)} ({object_name})",
|
||||
start=start,
|
||||
end=end,
|
||||
description=(
|
||||
|
||||
Reference in New Issue
Block a user