feat(task): 批量改状态与看板数据接口
- POST /items/batch-status:逐条成败,不做全回滚;拖 10 条里 1 条冲突不该让另 9 条白干
- GET /items/board:四列一次取全,收件箱不进看板
- 修:/items/board 被 /{item_id} 抢先匹配导致 422
- 新增向量库配置项(M3 用,独立实例,不动 fnsvr-01)
- 3 个新测试,全量 46 passed
This commit is contained in:
@@ -270,3 +270,90 @@ async def test_cursor_pagination_does_not_repeat_rows(client: AsyncClient) -> No
|
||||
assert ids_first.isdisjoint(ids_second)
|
||||
assert len(ids_second) == 1
|
||||
assert second["has_more"] is False
|
||||
|
||||
|
||||
async def test_batch_status_partial_success(client: AsyncClient) -> None:
|
||||
"""拖 3 条进去:2 条该成功,1 条因为版本过期该失败,且失败不影响另外两条。"""
|
||||
user = await login(client)
|
||||
ws = await create_workspace(client, user, "个人")
|
||||
a = await _new_item(client, user, ws["id"], title="A", status="todo")
|
||||
b = await _new_item(client, user, ws["id"], title="B", status="todo")
|
||||
stale = await _new_item(client, user, ws["id"], title="C", status="todo")
|
||||
|
||||
# 让 C 的版本先过期:另一个人(同一用户)改了一次
|
||||
unwrap(
|
||||
await client.patch(
|
||||
f"{items_url(ws['id'])}/{stale['id']}",
|
||||
json={"title": "C 改过", "version": stale["version"]},
|
||||
headers=user["headers"],
|
||||
)
|
||||
)
|
||||
|
||||
body = unwrap(
|
||||
await client.post(
|
||||
f"{items_url(ws['id'])}/batch-status",
|
||||
json={
|
||||
"status": "done",
|
||||
"items": [
|
||||
{"id": a["id"], "version": a["version"]},
|
||||
{"id": b["id"], "version": b["version"]},
|
||||
{"id": stale["id"], "version": stale["version"]},
|
||||
],
|
||||
},
|
||||
headers=user["headers"],
|
||||
)
|
||||
)
|
||||
assert len(body["updated"]) == 2
|
||||
assert len(body["failed"]) == 1
|
||||
assert body["failed"][0]["id"] == stale["id"]
|
||||
assert body["failed"][0]["code"] == 4009
|
||||
assert body["failed"][0]["current_version"] == stale["version"] + 1
|
||||
|
||||
detail_a = unwrap(await client.get(f"{items_url(ws['id'])}/{a['id']}", headers=user["headers"]))
|
||||
assert detail_a["status"] == "done"
|
||||
assert detail_a["completed_at"] is not None
|
||||
|
||||
|
||||
async def test_batch_status_reports_illegal_transition(client: AsyncClient) -> None:
|
||||
user = await login(client)
|
||||
ws = await create_workspace(client, user, "个人")
|
||||
inbox = await _new_item(client, user, ws["id"], title="还在收件箱")
|
||||
|
||||
body = unwrap(
|
||||
await client.post(
|
||||
f"{items_url(ws['id'])}/batch-status",
|
||||
json={"status": "done", "items": [{"id": inbox["id"], "version": inbox["version"]}]},
|
||||
headers=user["headers"],
|
||||
)
|
||||
)
|
||||
assert body["updated"] == []
|
||||
assert body["failed"][0]["code"] == 5002
|
||||
assert "todo" in body["failed"][0]["allowed"]
|
||||
|
||||
|
||||
async def test_board_groups_by_status_and_hides_others(client: AsyncClient) -> None:
|
||||
user = await login(client)
|
||||
ws = await create_workspace(client, user, "个人")
|
||||
await _new_item(client, user, ws["id"], title="待办1", status="todo")
|
||||
await _new_item(client, user, ws["id"], title="在做1", status="doing")
|
||||
await _new_item(client, user, ws["id"], title="卡住1", status="blocked")
|
||||
await _new_item(client, user, ws["id"], title="收件箱的", status="inbox")
|
||||
|
||||
board = unwrap(await client.get(f"{items_url(ws['id'])}/board", headers=user["headers"]))
|
||||
columns = board["columns"]
|
||||
assert board["order"] == ["todo", "doing", "blocked", "done"]
|
||||
assert [i["title"] for i in columns["todo"]] == ["待办1"]
|
||||
assert [i["title"] for i in columns["doing"]] == ["在做1"]
|
||||
assert [i["title"] for i in columns["blocked"]] == ["卡住1"]
|
||||
assert columns["done"] == []
|
||||
# 收件箱不属于看板任何一列
|
||||
all_titles = [i["title"] for col in columns.values() for i in col]
|
||||
assert "收件箱的" not in all_titles
|
||||
|
||||
# 别人的工作区看板为空
|
||||
other_user = await login(client)
|
||||
other_ws = await create_workspace(client, other_user, "别人")
|
||||
empty = unwrap(
|
||||
await client.get(f"{items_url(other_ws['id'])}/board", headers=other_user["headers"])
|
||||
)
|
||||
assert all(len(col) == 0 for col in empty["columns"].values())
|
||||
|
||||
Reference in New Issue
Block a user