feat(gamification): flag cascade-completed parents as auto_completed
complete_subtask_and_check_parent now sets auto_completed = 1 on the parent when it closes via the cascade. The subtask UPDATE itself remains at the default 0, so explicit user taps still count toward the Phase 8 daily total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -451,7 +451,13 @@ pub async fn complete_subtask_and_check_parent(pool: &SqlitePool, subtask_id: &s
|
||||
})?;
|
||||
|
||||
if pending == 0 {
|
||||
sqlx::query("UPDATE tasks SET done = 1, done_at = datetime('now') WHERE id = ?")
|
||||
// Phase 8: flag the cascade so the daily-count query can exclude
|
||||
// it. The subtask UPDATE (above) stays at auto_completed = 0 — the
|
||||
// user explicitly ticked it, so it counts.
|
||||
sqlx::query(
|
||||
"UPDATE tasks SET done = 1, done_at = datetime('now'), auto_completed = 1 \
|
||||
WHERE id = ?",
|
||||
)
|
||||
.bind(&pid)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
@@ -2016,4 +2022,59 @@ mod tests {
|
||||
let missing = get_setting(&pool, "nonexistent").await.unwrap();
|
||||
assert!(missing.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn cascade_sets_auto_completed_on_parent_only() {
|
||||
let pool = test_pool().await;
|
||||
|
||||
// Parent + two subtasks.
|
||||
insert_task(
|
||||
&pool,
|
||||
"parent",
|
||||
"Parent task",
|
||||
"inbox",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
insert_subtask(&pool, "s1", "Step 1", "parent")
|
||||
.await
|
||||
.unwrap();
|
||||
insert_subtask(&pool, "s2", "Step 2", "parent")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
complete_subtask_and_check_parent(&pool, "s1")
|
||||
.await
|
||||
.unwrap();
|
||||
complete_subtask_and_check_parent(&pool, "s2")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Parent auto-closed.
|
||||
let parent_auto: i64 =
|
||||
sqlx::query_scalar("SELECT auto_completed FROM tasks WHERE id = 'parent'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
parent_auto, 1,
|
||||
"parent closed by cascade must be auto_completed = 1"
|
||||
);
|
||||
|
||||
// Subtasks themselves are manual.
|
||||
let s1_auto: i64 = sqlx::query_scalar("SELECT auto_completed FROM tasks WHERE id = 's1'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
let s2_auto: i64 = sqlx::query_scalar("SELECT auto_completed FROM tasks WHERE id = 's2'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(s1_auto, 0, "subtask completion is manual");
|
||||
assert_eq!(s2_auto, 0, "subtask completion is manual");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user