fix: reset subtasks for recurring tasks
This commit is contained in:
@@ -640,6 +640,7 @@ async def update_task(
|
|||||||
data = payload.model_dump(exclude_unset=True)
|
data = payload.model_dump(exclude_unset=True)
|
||||||
expected_version = data.pop("version")
|
expected_version = data.pop("version")
|
||||||
recurrence = None
|
recurrence = None
|
||||||
|
reset_subtasks = False
|
||||||
if data.get("completed") is True:
|
if data.get("completed") is True:
|
||||||
recurrence = await db.scalar(select(RecurrenceTemplate).where(
|
recurrence = await db.scalar(select(RecurrenceTemplate).where(
|
||||||
RecurrenceTemplate.task_id == task_id, RecurrenceTemplate.user_id == user.id
|
RecurrenceTemplate.task_id == task_id, RecurrenceTemplate.user_id == user.id
|
||||||
@@ -656,6 +657,7 @@ async def update_task(
|
|||||||
data["completed"] = False
|
data["completed"] = False
|
||||||
data["due_at"] = next_items[0]
|
data["due_at"] = next_items[0]
|
||||||
recurrence.starts_at = next_items[0]
|
recurrence.starts_at = next_items[0]
|
||||||
|
reset_subtasks = True
|
||||||
if "list_id" in data:
|
if "list_id" in data:
|
||||||
await _owned_list(db, user.id, data["list_id"])
|
await _owned_list(db, user.id, data["list_id"])
|
||||||
if task.parent_id:
|
if task.parent_id:
|
||||||
@@ -685,6 +687,18 @@ async def update_task(
|
|||||||
if exists_id:
|
if exists_id:
|
||||||
raise HTTPException(status_code=409, detail="任务已被更新,请刷新后重试")
|
raise HTTPException(status_code=409, detail="任务已被更新,请刷新后重试")
|
||||||
raise HTTPException(status_code=404, detail="任务不存在")
|
raise HTTPException(status_code=404, detail="任务不存在")
|
||||||
|
if reset_subtasks:
|
||||||
|
reset_at = utcnow()
|
||||||
|
await db.execute(
|
||||||
|
update(Task)
|
||||||
|
.where(
|
||||||
|
Task.parent_id == task.id,
|
||||||
|
Task.user_id == user.id,
|
||||||
|
Task.deleted_at.is_(None),
|
||||||
|
Task.completed.is_(True),
|
||||||
|
)
|
||||||
|
.values(completed=False, version=Task.version + 1, updated_at=reset_at)
|
||||||
|
)
|
||||||
if "list_id" in data and task.parent_id is None:
|
if "list_id" in data and task.parent_id is None:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
update(Task)
|
update(Task)
|
||||||
|
|||||||
@@ -134,6 +134,47 @@ def test_completing_repeating_task_advances_due_date_instead_of_closing_it(clien
|
|||||||
assert recurrence["starts_at"].replace("Z", "") == "2026-09-08T09:00:00"
|
assert recurrence["starts_at"].replace("Z", "") == "2026-09-08T09:00:00"
|
||||||
|
|
||||||
|
|
||||||
|
def test_completing_repeating_task_resets_completed_subtasks_for_next_occurrence(client):
|
||||||
|
inbox = boot(client)
|
||||||
|
parent = client.post(
|
||||||
|
"/api/v1/tasks",
|
||||||
|
json={
|
||||||
|
"title": "每日清理",
|
||||||
|
"list_id": inbox["id"],
|
||||||
|
"due_at": "2026-09-07T09:00:00Z",
|
||||||
|
"rrule": "FREQ=DAILY",
|
||||||
|
},
|
||||||
|
).json()
|
||||||
|
first = client.post(
|
||||||
|
"/api/v1/tasks",
|
||||||
|
json={"title": "清理下载", "list_id": inbox["id"], "parent_id": parent["id"]},
|
||||||
|
).json()
|
||||||
|
second = client.post(
|
||||||
|
"/api/v1/tasks",
|
||||||
|
json={"title": "清理缓存", "list_id": inbox["id"], "parent_id": parent["id"]},
|
||||||
|
).json()
|
||||||
|
for child in (first, second):
|
||||||
|
response = client.patch(
|
||||||
|
f"/api/v1/tasks/{child['id']}",
|
||||||
|
json={"completed": True, "version": child["version"]},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
completed = client.patch(
|
||||||
|
f"/api/v1/tasks/{parent['id']}",
|
||||||
|
json={"completed": True, "version": parent["version"]},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert completed.status_code == 200
|
||||||
|
assert completed.json()["completed"] is False
|
||||||
|
assert completed.json()["due_at"].replace("Z", "") == "2026-09-08T09:00:00"
|
||||||
|
assert [child["completed"] for child in completed.json()["subtasks"]] == [False, False]
|
||||||
|
listed = client.get("/api/v1/tasks", params={"list_id": inbox["id"], "page": 1}).json()["items"]
|
||||||
|
repeated = next(task for task in listed if task["id"] == parent["id"])
|
||||||
|
assert [child["completed"] for child in repeated["subtasks"]] == [False, False]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_recurrence_mutations_keep_exact_timestamp_validation(client):
|
def test_recurrence_mutations_keep_exact_timestamp_validation(client):
|
||||||
inbox = boot(client)
|
inbox = boot(client)
|
||||||
task = client.post(
|
task = client.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user