feat(collect): support soft deletion of one task
This commit is contained in:
@@ -161,6 +161,8 @@ class Task:
|
||||
generated_at: Optional[str]
|
||||
applied_at: Optional[str]
|
||||
updated_at: str
|
||||
deleted_at: Optional[str]
|
||||
deleted_reason: Optional[str]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -261,6 +263,8 @@ CREATE TABLE IF NOT EXISTS tasks (
|
||||
generated_at TEXT,
|
||||
applied_at TEXT,
|
||||
updated_at TEXT NOT NULL,
|
||||
deleted_at TEXT,
|
||||
deleted_reason TEXT,
|
||||
UNIQUE(batch_id, source_file_abs, source_sheet, source_row)
|
||||
);
|
||||
|
||||
@@ -495,6 +499,7 @@ def init_db(path=None, conn=None) -> None:
|
||||
_ensure_task_image_task_columns(database)
|
||||
_ensure_task_cover_reset_columns(database)
|
||||
_ensure_task_product_status_columns(database)
|
||||
_ensure_task_delete_columns(database)
|
||||
_migrate_legacy_product_status_defaults(database)
|
||||
_ensure_image_studio_project_suite_columns(database)
|
||||
_ensure_image_studio_project_draft_columns(database)
|
||||
@@ -537,6 +542,15 @@ def _ensure_task_product_status_columns(database):
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN product_status_at TEXT")
|
||||
|
||||
|
||||
def _ensure_task_delete_columns(database):
|
||||
columns = {row["name"] for row in database.execute("PRAGMA table_info(tasks)").fetchall()}
|
||||
if "deleted_at" not in columns:
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN deleted_at TEXT")
|
||||
if "deleted_reason" not in columns:
|
||||
database.execute("ALTER TABLE tasks ADD COLUMN deleted_reason TEXT")
|
||||
database.execute("CREATE INDEX IF NOT EXISTS idx_tasks_deleted_at ON tasks(deleted_at)")
|
||||
|
||||
|
||||
def _migrate_legacy_product_status_defaults(database):
|
||||
"""Treat pre-status-feature active batches as historically on-shelf once."""
|
||||
|
||||
@@ -548,6 +562,7 @@ def _migrate_legacy_product_status_defaults(database):
|
||||
product_status_at = NULL,
|
||||
updated_at = ?
|
||||
WHERE (product_status IS NULL OR TRIM(product_status) = '')
|
||||
AND deleted_at IS NULL
|
||||
AND batch_id IN (
|
||||
SELECT id
|
||||
FROM batches
|
||||
@@ -880,6 +895,7 @@ def list_tasks(
|
||||
params.append(value)
|
||||
if not include_deleted:
|
||||
clauses.append("b.deleted_at IS NULL")
|
||||
clauses.append("t.deleted_at IS NULL")
|
||||
sql = "SELECT t.* FROM tasks t JOIN batches b ON b.id = t.batch_id"
|
||||
if clauses:
|
||||
sql += " WHERE " + " AND ".join(clauses)
|
||||
@@ -920,11 +936,44 @@ def delete_batch(batch_id, reason=None, path=None, conn=None) -> dict:
|
||||
"image_paths": image_paths,
|
||||
}
|
||||
|
||||
|
||||
def delete_task(task_id, reason=None, path=None, conn=None) -> dict:
|
||||
"""Soft delete one inactive task without touching its source files or images."""
|
||||
|
||||
task_id = int(task_id)
|
||||
with _connection(conn, path) as database:
|
||||
task = get_task(task_id, conn=database)
|
||||
if task is None:
|
||||
raise DbError(f"任务不存在或已删除: {task_id}")
|
||||
if task.status == "running":
|
||||
raise DbError("任务正在处理,不能删除")
|
||||
now = _now()
|
||||
with database:
|
||||
cursor = database.execute(
|
||||
"""
|
||||
UPDATE tasks
|
||||
SET deleted_at = ?, deleted_reason = ?, updated_at = ?
|
||||
WHERE id = ? AND deleted_at IS NULL AND status <> 'running'
|
||||
""",
|
||||
(now, str(reason or ""), now, task_id),
|
||||
)
|
||||
if cursor.rowcount != 1:
|
||||
raise DbError("任务已删除或正在处理,不能删除")
|
||||
return {
|
||||
"task_id": task_id,
|
||||
"batch_id": task.batch_id,
|
||||
"item_id": task.item_id,
|
||||
"committed": int(task.committed or 0),
|
||||
"deleted_at": now,
|
||||
}
|
||||
|
||||
|
||||
def get_task(task_id, path=None, conn=None, include_deleted=False):
|
||||
clauses = ["t.id = ?"]
|
||||
params = [int(task_id)]
|
||||
if not include_deleted:
|
||||
clauses.append("b.deleted_at IS NULL")
|
||||
clauses.append("t.deleted_at IS NULL")
|
||||
sql = "SELECT t.* FROM tasks t JOIN batches b ON b.id = t.batch_id"
|
||||
sql += " WHERE " + " AND ".join(clauses)
|
||||
with _connection(conn, path) as database:
|
||||
|
||||
Reference in New Issue
Block a user