187 files

This commit is contained in:
Home Assistant Version Control
2026-10-09 11:57:31 +00:00
parent 28fa34d78a
commit 1e1b12d52b
187 changed files with 40899 additions and 32654 deletions
+32 -6
View File
@@ -16,7 +16,7 @@ from homeassistant.helpers.event import async_track_time_change
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.util import dt as dt_util
from . import photos
from . import notify_strings, photos
from .const import DOMAIN
from .coord_assignments import AssignmentsMixin
from .coord_auctions import AuctionsMixin
@@ -136,6 +136,7 @@ class TaskMateCoordinator(
self.external_state_version: int = 0
self._unsub_surprise: Callable[[], None] | None = None
self._unsub_weekly: Callable[[], None] | None = None
self._unsub_language: Callable[[], None] | None = None
self._unsub_mandatory: list[Callable[[], None]] = []
# Per-build memo for the availability matrix (PERF-1). Non-None only
# inside `availability_build_scope()`; see coord_chores/coord_assignments.
@@ -392,6 +393,10 @@ class TaskMateCoordinator(
"""Initialize the coordinator."""
await self.storage.async_load()
self.notifications.coordinator = self
# Notification wording follows HA's language (#1037): load it now, and
# again whenever the language is changed.
await notify_strings.async_load(self.hass)
self._unsub_language = notify_strings.async_watch_language(self.hass)
# Wire existing parent recipients to default-on parent-audience types
# that have no routes yet (e.g. a parent added after the one-time seed),
# so pending-approval notifications actually reach a parent.
@@ -470,6 +475,7 @@ class TaskMateCoordinator(
async def _async_send_weekly_digest(self) -> None:
"""Build and send the weekly digest to parents (opt-in)."""
await notify_strings.async_load(self.hass)
summary = self._build_weekly_digest()
if not summary:
return
@@ -492,7 +498,14 @@ class TaskMateCoordinator(
done[comp.child_id] = done.get(comp.child_id, 0) + 1
earned[comp.child_id] = earned.get(comp.child_id, 0) + (comp.points_awarded or 0)
pts = self.storage.get_points_name()
lines = [f"• {c.name}: {done.get(c.id, 0)} chores, {earned.get(c.id, 0)} {pts} earned" for c in children]
lines = [
notify_strings.render(
self.hass,
"weekly_digest_line",
{"child_name": c.name, "chores": done.get(c.id, 0), "points": earned.get(c.id, 0), "points_name": pts},
)
for c in children
]
return "\n".join(lines)
async def _async_send_monthly_report(self) -> None:
@@ -500,6 +513,7 @@ class TaskMateCoordinator(
today = dt_util.now().date()
month_end = today.replace(day=1) - timedelta(days=1)
month_start = month_end.replace(day=1)
await notify_strings.async_load(self.hass)
summary = self._build_monthly_report(month_start, month_end)
if not summary:
return
@@ -507,7 +521,7 @@ class TaskMateCoordinator(
"monthly_report",
{
"summary": summary,
"month": month_start.strftime("%B %Y"),
"month": notify_strings.month_year(self.hass, month_start),
},
)
@@ -528,8 +542,18 @@ class TaskMateCoordinator(
earned[comp.child_id] = earned.get(comp.child_id, 0) + (comp.points_awarded or 0)
pts = self.storage.get_points_name()
lines = [
f"• {c.name}: {done.get(c.id, 0)} chores, {earned.get(c.id, 0)} {pts}, "
f"level {getattr(c, 'level', 1)}, best streak {getattr(c, 'best_streak', 0)}"
notify_strings.render(
self.hass,
"monthly_report_line",
{
"child_name": c.name,
"chores": done.get(c.id, 0),
"points": earned.get(c.id, 0),
"points_name": pts,
"level": getattr(c, "level", 1),
"streak": getattr(c, "best_streak", 0),
},
)
for c in children
]
return "\n".join(lines)
@@ -688,7 +712,7 @@ class TaskMateCoordinator(
{
"child_name": top["name"],
"points": top["points"],
"month": prev_end.strftime("%B %Y"),
"month": notify_strings.month_year(self.hass, prev_end),
"points_name": self.storage.get_points_name(),
},
)
@@ -809,6 +833,7 @@ class TaskMateCoordinator(
"_unsub_tag_scanned",
"_unsub_surprise",
"_unsub_weekly",
"_unsub_language",
"_unsub_auction_timer",
):
if unsub := getattr(self, attr, None):
@@ -1011,6 +1036,7 @@ class TaskMateCoordinator(
self.storage.remove_daily_progress_for_child(child_id)
self.storage.remove_quest_progress_for_child(child_id)
self.storage.remove_challenge_progress_for_child(child_id)
self.storage.remove_weekly_target_bonuses(child_id=child_id)
# Drop pending swap requests either side of this child (#785) — a
# handover to or from a deleted child can never complete, and the
# approval queue would render them as "?".