fix(db): migrate processed tasks with missing product status
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
@@ -259,6 +260,168 @@ class DbTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_init_db_defaults_processed_missing_status_and_creates_one_backup(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
db_path = os.path.join(temp_dir, "cmshopee.db")
|
||||
db.init_db(db_path)
|
||||
batch_id = db.create_batch(["processed.xlsx"], path=db_path)
|
||||
deleted_batch_id = db.create_batch(["deleted.xlsx"], path=db_path)
|
||||
item_ids = {
|
||||
"stage": "51100639801",
|
||||
"timestamp": "51100639802",
|
||||
"content": "51100639803",
|
||||
"unprocessed": "51100639804",
|
||||
"unknown": "51100639805",
|
||||
"deleted_task": "51100639806",
|
||||
"deleted_batch": "51100639807",
|
||||
}
|
||||
rows = []
|
||||
for source_row, item_id in enumerate(item_ids.values(), start=2):
|
||||
rows.append(
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, f"{item_id}.xlsx"),
|
||||
"source_sheet": "Sheet1",
|
||||
"source_row": source_row,
|
||||
"account_name": "店铺",
|
||||
"alias": "alias",
|
||||
"item_id": item_id,
|
||||
}
|
||||
)
|
||||
db.insert_tasks(batch_id, rows[:-1], path=db_path)
|
||||
db.insert_tasks(deleted_batch_id, rows[-1:], path=db_path)
|
||||
|
||||
conn = db.connect(db_path)
|
||||
try:
|
||||
tasks = {
|
||||
task.item_id: task
|
||||
for task in db.list_tasks(batch_id=batch_id, conn=conn)
|
||||
}
|
||||
deleted_batch_task = db.list_tasks(
|
||||
batch_id=deleted_batch_id,
|
||||
conn=conn,
|
||||
)[0]
|
||||
with conn:
|
||||
conn.execute(
|
||||
"UPDATE batches SET created_at = ? WHERE id IN (?, ?)",
|
||||
("2026-07-27T12:00:00", batch_id, deleted_batch_id),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE tasks SET stage = 'generated', new_cover_path = ? WHERE id = ?",
|
||||
(
|
||||
os.path.join(temp_dir, "stage.jpg"),
|
||||
tasks[item_ids["stage"]].id,
|
||||
),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE tasks SET generated_at = ?, new_cover_path = ? WHERE id = ?",
|
||||
(
|
||||
"2026-07-27T12:01:00",
|
||||
os.path.join(temp_dir, "timestamp.jpg"),
|
||||
tasks[item_ids["timestamp"]].id,
|
||||
),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE tasks SET new_title = ? WHERE id = ?",
|
||||
("历史生成标题", tasks[item_ids["content"]].id),
|
||||
)
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE tasks
|
||||
SET product_status = 'unknown',
|
||||
product_status_note = '已有未知状态',
|
||||
new_title = '不应覆盖'
|
||||
WHERE id = ?
|
||||
""",
|
||||
(tasks[item_ids["unknown"]].id,),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE tasks SET stage = 'generated', deleted_at = ? WHERE id = ?",
|
||||
("2026-07-27T12:02:00", tasks[item_ids["deleted_task"]].id),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE tasks SET stage = 'generated' WHERE id = ?",
|
||||
(deleted_batch_task.id,),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE batches SET deleted_at = ? WHERE id = ?",
|
||||
("2026-07-27T12:03:00", deleted_batch_id),
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
db.init_db(db_path)
|
||||
|
||||
migrated = {
|
||||
task.item_id: task
|
||||
for task in db.list_tasks(
|
||||
batch_id=batch_id,
|
||||
path=db_path,
|
||||
include_deleted=True,
|
||||
)
|
||||
}
|
||||
for key in ("stage", "timestamp", "content"):
|
||||
task = migrated[item_ids[key]]
|
||||
self.assertEqual("normal", task.product_status)
|
||||
self.assertEqual(
|
||||
db.LEGACY_PRODUCT_STATUS_DEFAULT_NOTE,
|
||||
task.product_status_note,
|
||||
)
|
||||
self.assertIsNone(task.product_status_at)
|
||||
self.assertIsNone(migrated[item_ids["unprocessed"]].product_status)
|
||||
self.assertEqual("unknown", migrated[item_ids["unknown"]].product_status)
|
||||
self.assertEqual(
|
||||
"已有未知状态",
|
||||
migrated[item_ids["unknown"]].product_status_note,
|
||||
)
|
||||
self.assertIsNone(migrated[item_ids["deleted_task"]].product_status)
|
||||
deleted_batch_task = db.list_tasks(
|
||||
batch_id=deleted_batch_id,
|
||||
path=db_path,
|
||||
include_deleted=True,
|
||||
)[0]
|
||||
self.assertIsNone(deleted_batch_task.product_status)
|
||||
|
||||
backup_dir = os.path.join(temp_dir, "backups")
|
||||
backups = [
|
||||
os.path.join(backup_dir, name)
|
||||
for name in os.listdir(backup_dir)
|
||||
if f"before-{db.LEGACY_STATUS_BACKUP_TASK_ID}" in name
|
||||
]
|
||||
self.assertEqual(1, len(backups))
|
||||
backup_conn = sqlite3.connect(backups[0])
|
||||
try:
|
||||
row = backup_conn.execute(
|
||||
"SELECT product_status FROM tasks WHERE item_id = ?",
|
||||
(item_ids["stage"],),
|
||||
).fetchone()
|
||||
self.assertIsNone(row[0])
|
||||
finally:
|
||||
backup_conn.close()
|
||||
|
||||
content_task = migrated[item_ids["content"]]
|
||||
plan = product_status.build_apply_plan([content_task], "title")
|
||||
self.assertEqual([content_task.id], [task.id for task in plan["executable"]])
|
||||
first_updated_at = content_task.updated_at
|
||||
|
||||
db.init_db(db_path)
|
||||
|
||||
self.assertEqual(
|
||||
first_updated_at,
|
||||
db.get_task(content_task.id, path=db_path).updated_at,
|
||||
)
|
||||
self.assertEqual(
|
||||
1,
|
||||
len(
|
||||
[
|
||||
name
|
||||
for name in os.listdir(backup_dir)
|
||||
if f"before-{db.LEGACY_STATUS_BACKUP_TASK_ID}" in name
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_init_db_repairs_only_legacy_promotion_status_misclassification(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
db_path = os.path.join(temp_dir, "cmshopee.db")
|
||||
|
||||
+3
-2
@@ -7644,7 +7644,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
statuses = ["unlisted", "reviewing", None]
|
||||
statuses = ["unlisted", "reviewing", "unknown"]
|
||||
for task, status in zip(
|
||||
db.list_tasks(batch_id=batch_id, path=cfg["db_path"]),
|
||||
statuses,
|
||||
@@ -8566,6 +8566,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
db.mark_failed(tasks_b[0].id, "generate", "生成失败", path=cfg["db_path"])
|
||||
db.set_product_status(tasks_a[0].id, "normal", path=cfg["db_path"])
|
||||
db.set_product_status(tasks_a[1].id, "unlisted", path=cfg["db_path"])
|
||||
db.set_product_status(tasks_a[2].id, "reviewing", path=cfg["db_path"])
|
||||
db.set_product_status(tasks_b[0].id, "unknown", path=cfg["db_path"])
|
||||
|
||||
tab = GenerateTab(config=cfg)
|
||||
@@ -8628,7 +8629,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual([], unlisted_plan["execution_tasks"])
|
||||
tab.status_filter.setCurrentIndex(tab.status_filter.findData("all"))
|
||||
tab.product_status_filter.setCurrentIndex(
|
||||
tab.product_status_filter.findData("unchecked")
|
||||
tab.product_status_filter.findData("reviewing")
|
||||
)
|
||||
self.assertEqual(1, tab.model.rowCount())
|
||||
self.assertEqual("51100639512", tab.model.index(0, 1).data())
|
||||
|
||||
Reference in New Issue
Block a user