Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions custom_components/taskmate/coord_chores.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,10 @@ async def async_complete_chore(
return await self._async_join_team_chore(chore, child, now, as_parent=as_parent, photo_url=photo_url)
# Open-ended completions always go to a parent: the child suggested the
# point value, so self-awarding it would let them set their own pay.
auto_approve = as_parent or (not chore.requires_approval and not requires_photo and not is_open_ended)
# A grown-up's own completion never waits for approval (#1061).
auto_approve = (
as_parent or child.is_adult or (not chore.requires_approval and not requires_photo and not is_open_ended)
)
# Won at auction (#982): the winner is paid their winning bid for this
# occurrence instead of the chore's own points — exactly what they bid.
auction_price = self.auction_price_for(chore, child_id, today)
Expand Down Expand Up @@ -1401,12 +1404,14 @@ async def async_complete_bonus_subtask(
if already_done:
raise ValueError(f"Bonus sub-task '{subtask.name}' already completed today.")

# A grown-up's own sub-task never waits for approval (#1061).
needs_approval = chore.requires_approval and not child.is_adult
completion = ChoreCompletion(
chore_id=chore_id,
child_id=child_id,
completed_at=now,
approved=not chore.requires_approval,
points_awarded=subtask.points if not chore.requires_approval else 0,
approved=not needs_approval,
points_awarded=subtask.points if not needs_approval else 0,
submitted_points=subtask.points,
bonus_subtask_id=bonus_subtask_id,
child_undo_allowed=by_child and undo_window_seconds(self.storage) > 0,
Expand All @@ -1417,15 +1422,15 @@ async def async_complete_bonus_subtask(
# awarding can suspend.
self.storage.add_completion(completion)

if not chore.requires_approval:
if not needs_approval:
total_awarded = await self._award_points(child, subtask.points, skip_streak=True)
completion.approved = True
completion.approved_at = dt_util.now()
completion.points_awarded = total_awarded
self.storage.update_completion(completion)
await self.storage.async_save()

if chore.requires_approval:
if needs_approval:
await self._async_notify_pending_approval(
child.name, f"{chore.name} › {subtask.name}", subtask.points, completion_id=completion.id
)
Expand Down
17 changes: 10 additions & 7 deletions custom_components/taskmate/coord_timed.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,21 @@ async def async_stop_timed_task(self, chore_id: str, child_id: str) -> None:
rate_seconds = chore.timed_rate_minutes * 60
pts = (total_seconds // rate_seconds) * chore.timed_rate_points if rate_seconds > 0 else 0

# A grown-up's own session never waits for approval (#1061).
needs_approval = chore.requires_approval and not child.is_adult
completion = ChoreCompletion(
chore_id=chore_id,
child_id=child_id,
completed_at=now,
approved=not chore.requires_approval,
points_awarded=pts if not chore.requires_approval else 0,
approved=not needs_approval,
points_awarded=pts if not needs_approval else 0,
submitted_points=pts,
timed_duration_seconds=total_seconds,
# The child's own stopped session: theirs to undo in the window (#918).
child_undo_allowed=undo_window_seconds(self.storage) > 0,
)

if not chore.requires_approval:
if not needs_approval:
total_awarded = await self._award_points(child, pts)
completion.approved = True
completion.approved_at = dt_util.now()
Expand All @@ -147,7 +149,7 @@ async def async_stop_timed_task(self, chore_id: str, child_id: str) -> None:

await self.storage.async_save()

if chore.requires_approval:
if needs_approval:
await self._async_notify_pending_approval(
child.name,
chore.name,
Expand Down Expand Up @@ -252,17 +254,18 @@ async def _async_stop_stale_timed_sessions(self) -> None:
rate_seconds = chore.timed_rate_minutes * 60
pts = (total_seconds // rate_seconds) * chore.timed_rate_points if rate_seconds > 0 else 0

needs_approval = chore.requires_approval and not child.is_adult
if total_seconds > 0:
completion = ChoreCompletion(
chore_id=session.chore_id,
child_id=session.child_id,
completed_at=dt_util.now(),
approved=not chore.requires_approval,
points_awarded=pts if not chore.requires_approval else 0,
approved=not needs_approval,
points_awarded=pts if not needs_approval else 0,
submitted_points=pts,
timed_duration_seconds=total_seconds,
)
if not chore.requires_approval:
if not needs_approval:
total_awarded = await self._award_points(child, pts)
completion.approved = True
completion.approved_at = dt_util.now()
Expand Down
2 changes: 2 additions & 0 deletions custom_components/taskmate/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ async def async_add_child(
birthday: str = "",
presence_entity: str = "",
age_group: str = "",
is_adult: bool = False,
refresh: bool = True,
) -> Child:
"""Add a new child.
Expand All @@ -1009,6 +1010,7 @@ async def async_add_child(
birthday=birthday,
presence_entity=presence_entity,
age_group=age_group,
is_adult=is_adult,
)
self.storage.add_child(child)
await self.storage.async_save()
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@ class Child:
# Setup wizard age group (#980): one of AGE_GROUPS, or "" when none was
# picked (every child that predates the wizard). Only steers suggestions.
age_group: str = ""
# A grown-up's profile (#1061): their own completions never wait for
# approval, and cards leave them out unless a card opts in (show_adults).
is_adult: bool = False
id: str = field(default_factory=generate_id)

@classmethod
Expand All @@ -280,6 +283,7 @@ def from_dict(cls, data: dict[str, Any]) -> Child:
guest_expires_on=str(data.get("guest_expires_on", "") or ""),
birthday=str(data.get("birthday", "") or ""),
age_group=normalize_age_group(data.get("age_group")),
is_adult=bool(data.get("is_adult", False)),
availability_entity=data.get("availability_entity", ""),
availability_inverted=data.get("availability_inverted", False),
unavailability_entity=data.get("unavailability_entity", ""),
Expand Down Expand Up @@ -319,6 +323,7 @@ def to_dict(self) -> dict[str, Any]:
"guest_expires_on": self.guest_expires_on,
"birthday": self.birthday,
"age_group": self.age_group,
"is_adult": self.is_adult,
"availability_entity": self.availability_entity,
"availability_inverted": self.availability_inverted,
"unavailability_entity": self.unavailability_entity,
Expand Down
2 changes: 2 additions & 0 deletions custom_components/taskmate/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ def _build_children_summary(coordinator: TaskMateCoordinator, common: dict) -> l
if getattr(c, "is_guest", False)
else {}
),
# Grown-ups (#1061): cards leave these out unless show_adults is set.
**({"is_adult": True} if getattr(c, "is_adult", False) else {}),
# Chore roulette (#677): today's pick + spins left, so the card can
# show the result and disable the button once the allowance is used.
**(
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ async def _ws_get_state(hass, connection, msg, coordinator):
vol.Optional("birthday", default=""): vol.All(str, vol.Length(max=10)),
vol.Optional("presence_entity", default=""): _validate_presence_entity,
vol.Optional("age_group", default=""): vol.In(("", *AGE_GROUPS)),
vol.Optional("is_adult", default=False): bool,
}
)
@websocket_api.async_response
Expand All @@ -517,6 +518,7 @@ async def _ws_add_child(hass, connection, msg, coordinator):
birthday=birthday,
presence_entity=msg.get("presence_entity", ""),
age_group=msg.get("age_group", ""),
is_adult=bool(msg.get("is_adult", False)),
)
connection.send_result(msg["id"], {"id": child.id})

Expand All @@ -538,6 +540,7 @@ async def _ws_add_child(hass, connection, msg, coordinator):
vol.Optional("guest_expires_on"): str,
vol.Optional("birthday"): vol.All(str, vol.Length(max=10)),
vol.Optional("age_group"): vol.In(("", *AGE_GROUPS)),
vol.Optional("is_adult"): bool,
}
)
@websocket_api.async_response
Expand Down Expand Up @@ -573,6 +576,8 @@ async def _ws_update_child(hass, connection, msg, coordinator):
existing.presence_entity = msg["presence_entity"]
if "age_group" in msg:
existing.age_group = msg["age_group"]
if "is_adult" in msg:
existing.is_adult = bool(msg["is_adult"])
if "is_guest" in msg or "guest_expires_on" in msg:
# Routed through the coordinator so the expiry is validated and an
# archived guest is un-archived when promoted to a family member.
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
"common.editor.filter_by_child_all": "Alle børn",
"common.editor.header_colour": "Overskriftsfarve",
"common.editor.header_colour_helper": "Baggrundsfarve på kortets overskrift",
"common.editor.show_adults": "Vis voksne",
"common.editor.show_adults_helper": "Medtag voksenprofiler på dette kort",
"common.editor.overview_entity": "Oversigtsentitet",
"common.editor.overview_entity_helper": "TaskMates oversigtssensor",
"common.editor.show_parent_actions": "Vis forældrehandlinger",
Expand Down Expand Up @@ -941,6 +943,9 @@
"panel.child_age_group_label": "Aldersgruppe",
"panel.child_age_group_none": "Ikke valgt",
"panel.child_age_group_hint": "Bestemmer, hvilke pligter opsætningsguiden foreslår. Ændrer ikke andet.",
"panel.child_adult_label": "Voksenprofil",
"panel.child_adult_hint": "Til en forælder eller anden voksen. Pligter, de markerer som udført, tæller med det samme uden godkendelse, og kort viser dem kun, når kortets indstilling \"Vis voksne\" er slået til.",
"panel.child_adult_pill": "Voksen",
"wizard.title": "Opsætningsguide",
"wizard.run_btn": "Kør opsætningsguiden",
"wizard.open_btn": "Åbn guiden",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@
"common.editor.filter_by_child_all": "Alle Kinder",
"common.editor.header_colour": "Kopfzeilenfarbe",
"common.editor.header_colour_helper": "Hintergrundfarbe der Kartenkopfzeile",
"common.editor.show_adults": "Erwachsene anzeigen",
"common.editor.show_adults_helper": "Erwachsenenprofile auf dieser Karte anzeigen",
"common.editor.overview_entity": "Übersichtseinheit",
"common.editor.overview_entity_helper": "Die TaskMate-Übersichtssensoreinheit",
"common.editor.show_parent_actions": "Elternaktionen anzeigen",
Expand Down Expand Up @@ -889,6 +891,9 @@
"panel.child_age_group_label": "Altersgruppe",
"panel.child_age_group_none": "Nicht festgelegt",
"panel.child_age_group_hint": "Bestimmt, welche Aufgaben der Einrichtungsassistent vorschlägt. Ändert sonst nichts.",
"panel.child_adult_label": "Erwachsenenprofil",
"panel.child_adult_hint": "Für ein Elternteil oder einen anderen Erwachsenen. Aufgaben, die sie als erledigt markieren, zählen sofort ohne Genehmigung, und Karten zeigen sie nur, wenn die Kartenoption „Erwachsene anzeigen“ aktiviert ist.",
"panel.child_adult_pill": "Erwachsen",
"wizard.title": "Einrichtungsassistent",
"wizard.run_btn": "Einrichtungsassistent starten",
"wizard.open_btn": "Assistent öffnen",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
"common.editor.filter_by_child_all": "All Children",
"common.editor.header_colour": "Header Colour",
"common.editor.header_colour_helper": "Card header background colour",
"common.editor.show_adults": "Show adults",
"common.editor.show_adults_helper": "Include adult profiles on this card",
"common.editor.overview_entity": "Overview Entity",
"common.editor.overview_entity_helper": "The TaskMate overview sensor entity",
"common.editor.show_parent_actions": "Show parent actions",
Expand Down Expand Up @@ -941,6 +943,9 @@
"panel.child_age_group_label": "Age group",
"panel.child_age_group_none": "Not set",
"panel.child_age_group_hint": "Decides which chores the setup wizard suggests. Changes nothing else.",
"panel.child_adult_label": "Adult profile",
"panel.child_adult_hint": "For a parent or other grown-up. Chores they mark done count straight away with no approval, and cards leave them out unless the card's \"Show adults\" option is on.",
"panel.child_adult_pill": "Adult",
"wizard.title": "Setup wizard",
"wizard.run_btn": "Run setup wizard",
"wizard.open_btn": "Open wizard",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
"common.editor.filter_by_child_all": "All Children",
"common.editor.header_colour": "Header Colour",
"common.editor.header_colour_helper": "Card header background colour",
"common.editor.show_adults": "Show adults",
"common.editor.show_adults_helper": "Include adult profiles on this card",
"common.editor.overview_entity": "Overview Entity",
"common.editor.overview_entity_helper": "The TaskMate overview sensor entity",
"common.editor.show_parent_actions": "Show parent actions",
Expand Down Expand Up @@ -941,6 +943,9 @@
"panel.child_age_group_label": "Age group",
"panel.child_age_group_none": "Not set",
"panel.child_age_group_hint": "Decides which chores the setup wizard suggests. Changes nothing else.",
"panel.child_adult_label": "Adult profile",
"panel.child_adult_hint": "For a parent or other grown-up. Chores they mark done count straight away with no approval, and cards leave them out unless the card's \"Show adults\" option is on.",
"panel.child_adult_pill": "Adult",
"wizard.title": "Setup wizard",
"wizard.run_btn": "Run setup wizard",
"wizard.open_btn": "Open wizard",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@
"common.editor.filter_by_child_all": "Tous les enfants",
"common.editor.header_colour": "Couleur de l'en-tête",
"common.editor.header_colour_helper": "Couleur d'arrière-plan de l'en-tête de la carte",
"common.editor.show_adults": "Afficher les adultes",
"common.editor.show_adults_helper": "Inclure les profils adultes sur cette carte",
"common.editor.overview_entity": "Entité de vue d'ensemble",
"common.editor.overview_entity_helper": "L'entité du capteur de vue d'ensemble TaskMate",
"common.editor.show_parent_actions": "Afficher les actions parentales",
Expand Down Expand Up @@ -889,6 +891,9 @@
"panel.child_age_group_label": "Tranche d'âge",
"panel.child_age_group_none": "Non définie",
"panel.child_age_group_hint": "Détermine les tâches suggérées par l'assistant de configuration. Ne change rien d'autre.",
"panel.child_adult_label": "Profil adulte",
"panel.child_adult_hint": "Pour un parent ou un autre adulte. Les tâches qu'il marque comme faites comptent tout de suite, sans validation, et les cartes ne l'affichent que si l'option « Afficher les adultes » de la carte est activée.",
"panel.child_adult_pill": "Adulte",
"wizard.title": "Assistant de configuration",
"wizard.run_btn": "Lancer l'assistant de configuration",
"wizard.open_btn": "Ouvrir l'assistant",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@
"common.editor.filter_by_child_all": "Alle barn",
"common.editor.header_colour": "Toppfarge",
"common.editor.header_colour_helper": "Bakgrunnsfarge for korttoppen",
"common.editor.show_adults": "Vis voksne",
"common.editor.show_adults_helper": "Ta med voksenprofiler på dette kortet",
"common.editor.overview_entity": "Oversiktsentitet",
"common.editor.overview_entity_helper": "TaskMate oversiktssensor-entiteten",
"common.editor.show_parent_actions": "Vis foreldrehandlinger",
Expand Down Expand Up @@ -889,6 +891,9 @@
"panel.child_age_group_label": "Aldersgruppe",
"panel.child_age_group_none": "Ikke valgt",
"panel.child_age_group_hint": "Bestemmer hvilke oppgaver oppsettveiviseren foreslår. Endrer ikke noe annet.",
"panel.child_adult_label": "Voksenprofil",
"panel.child_adult_hint": "For en forelder eller en annen voksen. Oppgaver de markerer som gjort, teller med en gang uten godkjenning, og kort viser dem bare når kortets valg «Vis voksne» er slått på.",
"panel.child_adult_pill": "Voksen",
"wizard.title": "Oppsettveiviser",
"wizard.run_btn": "Kjør oppsettveiviseren",
"wizard.open_btn": "Åpne veiviseren",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/nn.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@
"common.editor.filter_by_child_all": "Alle born",
"common.editor.header_colour": "Toppfarge",
"common.editor.header_colour_helper": "Bakgrunnsfarge for korttoppen",
"common.editor.show_adults": "Vis vaksne",
"common.editor.show_adults_helper": "Ta med vaksenprofilar på dette kortet",
"common.editor.overview_entity": "Oversiktsentitet",
"common.editor.overview_entity_helper": "TaskMate oversiktssensor-entiteten",
"common.editor.show_parent_actions": "Vis foreldrehandlingar",
Expand Down Expand Up @@ -889,6 +891,9 @@
"panel.child_age_group_label": "Aldersgruppe",
"panel.child_age_group_none": "Ikkje vald",
"panel.child_age_group_hint": "Avgjer kva oppgåver oppsettsvegvisaren føreslår. Endrar ikkje noko anna.",
"panel.child_adult_label": "Vaksenprofil",
"panel.child_adult_hint": "For ein forelder eller ein annan vaksen. Oppgåver dei markerer som gjort, tel med ein gong utan godkjenning, og kort viser dei berre når kortet sitt val «Vis vaksne» er slått på.",
"panel.child_adult_pill": "Vaksen",
"wizard.title": "Oppsettsvegvisar",
"wizard.run_btn": "Køyr oppsettsvegvisaren",
"wizard.open_btn": "Opne vegvisaren",
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/www/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
"common.editor.filter_by_child_all": "Wszystkie dzieci",
"common.editor.header_colour": "Kolor nagłówka",
"common.editor.header_colour_helper": "Kolor tła nagłówka karty",
"common.editor.show_adults": "Pokaż dorosłych",
"common.editor.show_adults_helper": "Uwzględnij profile dorosłych na tej karcie",
"common.editor.overview_entity": "Encja przeglądu",
"common.editor.overview_entity_helper": "Encja sensora przeglądu TaskMate",
"common.editor.show_parent_actions": "Pokaż działania rodzica",
Expand Down Expand Up @@ -941,6 +943,9 @@
"panel.child_age_group_label": "Grupa wiekowa",
"panel.child_age_group_none": "Nie ustawiono",
"panel.child_age_group_hint": "Decyduje, jakie obowiązki proponuje kreator. Nie zmienia niczego innego.",
"panel.child_adult_label": "Profil dorosłego",
"panel.child_adult_hint": "Dla rodzica lub innej dorosłej osoby. Obowiązki, które oznaczy jako wykonane, liczą się od razu bez zatwierdzania, a karty pokazują tę osobę tylko wtedy, gdy w karcie włączona jest opcja „Pokaż dorosłych”.",
"panel.child_adult_pill": "Dorosły",
"wizard.title": "Kreator konfiguracji",
"wizard.run_btn": "Uruchom kreator konfiguracji",
"wizard.open_btn": "Otwórz kreator",
Expand Down
Loading
Loading