Persist skip_on_away on quest definitions

Add a skip_on_away flag to quest_definitions (migration 8, additive
column defaulting to 1 so existing rows keep today's behaviour). The
admin create/edit routes accept it as an optional boolean (create
defaults true, an omitted edit field keeps the stored value) and the
definition payload returns it. Materialisation generates instances on
absent dates when the flag is false.

Task: ded75ab8-0219-4d52-aefa-82c09e0b5e6b

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 20:31:05 -04:00
co-authored by Claude Opus 5.5
parent 67f333c98e
commit ab0a320f3f
11 changed files with 424 additions and 20 deletions
+10 -3
View File
@@ -363,6 +363,7 @@ class AdminQuestDefinitionResponse(BaseModel):
description: str | None
icon: str | None
is_active: bool
skip_on_away: bool
rule: AdminRuleResponse
assignees: list[AdminAssigneeResponse]
windows: list[AdminDefinitionWindowResponse]
@@ -450,8 +451,9 @@ class AdminQuestDefinitionCreateRequest(BaseModel):
``title``, ``rule``, ``assignee_child_ids`` and ``windows`` are
required (the core rejects an empty title, a non-list or empty
assignee/window list, and unknown window names); ``description``
and ``icon`` are optional and default to NULL through the core.
``windows`` entries are a window name (``morning``) or a two-item
and ``icon`` are optional and default to NULL through the core, and
``skip_on_away`` is optional and defaults to true (no instance on a
date the child is absent). ``windows`` entries are a window name (``morning``) or a two-item
``[window, due_time]`` pair whose due time is a strict 24-hour
HH:MM (or ``null`` for none) — both forms the core normalizes.
"""
@@ -462,6 +464,7 @@ class AdminQuestDefinitionCreateRequest(BaseModel):
windows: list[str | tuple[str, str | None]]
description: str | None = None
icon: str | None = None
skip_on_away: bool = True
class AdminQuestDefinitionEditRequest(BaseModel):
@@ -476,7 +479,8 @@ class AdminQuestDefinitionEditRequest(BaseModel):
``rule`` or ``windows`` is passed and rejected by the core. A
supplied ``windows`` list REPLACES the whole window set, and
``assignees`` are deliberately absent — assignment is not settable
through this route.
through this route. An omitted (or ``null``) ``skip_on_away``
keeps the stored value.
"""
title: str | None = None
@@ -484,6 +488,7 @@ class AdminQuestDefinitionEditRequest(BaseModel):
icon: str | None = None
rule: AdminRuleRequest | None = None
windows: list[str | tuple[str, str | None]] | None = None
skip_on_away: bool | None = None
class AdminQuestDefinitionActiveRequest(BaseModel):
@@ -963,6 +968,7 @@ def _quest_definition_response(
description=bundle.definition.description,
icon=bundle.definition.icon,
is_active=bundle.definition.is_active,
skip_on_away=bundle.definition.skip_on_away,
rule=_rule_response(bundle.rule),
assignees=[
AdminAssigneeResponse(id=child.id, display_name=child.display_name)
@@ -1234,6 +1240,7 @@ async def admin_create_quest_definition(
body.windows,
description=body.description,
icon=body.icon,
skip_on_away=body.skip_on_away,
)
except ValueError as error:
_raise_quest_definition_error(error)