diff --git a/docs/superpowers/plans/2026-08-04-admin-comparison-outcome-display.md b/docs/superpowers/plans/2026-08-04-admin-comparison-outcome-display.md index cc2a29b..543491d 100644 --- a/docs/superpowers/plans/2026-08-04-admin-comparison-outcome-display.md +++ b/docs/superpowers/plans/2026-08-04-admin-comparison-outcome-display.md @@ -736,7 +736,134 @@ Co-Authored-By: Claude Opus 4.8 (1M context) " --- -## Task 5: 前端类型 `types.ts`(admin-web) +## Task 5: 列表 / 概览「状态」筛选对齐 admin 口径(后端) + +**Files:** +- Modify: `app/admin/repositories/queries.py`(`_comparison_status_condition` 改 admin 口径;删除不再引用的 #209 常量) +- Test: `tests/test_comparison_admin_summary.py`(新增筛选用例) + +- [ ] **Step 1: 写失败测试** + +追加到 `tests/test_comparison_admin_summary.py` 末尾: + +```python +def test_list_status_filter_uses_admin_outcome() -> None: + """列表「状态」筛选走 admin 口径:筛成功含 6 类,筛失败仅纯技术故障。""" + db = SessionLocal() + try: + rows = [ + ("flt-success", "success", "success"), + ("flt-below-min", "success", "below_minimum"), + ("flt-store-not-found", "failed", "store_not_found"), + ("flt-failed", "failed", "failed"), + ("flt-cancelled", "cancelled", None), + ] + for trace_id, status, record_status in rows: + db.add(ComparisonRecord( + trace_id=trace_id, + status=status, + raw_payload={"record_status": record_status} if record_status else None, + created_at=datetime(2039, 3, 10, 12, tzinfo=UTC), + )) + db.flush() + + succ, _c1, succ_total = queries.list_comparison_records( + db, status="success", date_from=date(2039, 3, 10), date_to=date(2039, 3, 10) + ) + assert succ_total == 3 + assert {it.trace_id for it in succ} == { + "flt-success", "flt-below-min", "flt-store-not-found", + } + + fail, _c2, fail_total = queries.list_comparison_records( + db, status="failed", date_from=date(2039, 3, 10), date_to=date(2039, 3, 10) + ) + assert fail_total == 1 + assert {it.trace_id for it in fail} == {"flt-failed"} + + _canc, _c3, canc_total = queries.list_comparison_records( + db, status="cancelled", date_from=date(2039, 3, 10), date_to=date(2039, 3, 10) + ) + assert canc_total == 1 + finally: + db.rollback() + db.close() +``` + +- [ ] **Step 2: 运行确认失败** + +Run: `cd e:/project/shaguabijia-app-server && ./.venv/Scripts/python.exe -m pytest tests/test_comparison_admin_summary.py::test_list_status_filter_uses_admin_outcome -q` +Expected: FAIL — 筛 success 仍按 status 列别名(漏掉 store_not_found),`succ_total == 3` 不符。 + +- [ ] **Step 3a: 改 `_comparison_status_condition`** + +`queries.py`(现为,约 66-68 行): + +```python +def _comparison_status_condition(status: str): + values = _COMPARISON_STATUS_ALIASES.get(status, (status,)) + return ComparisonRecord.status.in_(values) +``` + +改为(此时 `admin_success_sql` 已在 Task 3 import 到 `queries.py`): + +```python +def _comparison_status_condition(status: str): + """列表/概览「状态」筛选:success/failed 按 admin 口径(与显示/统计一致); + cancelled/running 按 status 列生命周期。""" + if status == "success": + return admin_success_sql() + if status == "failed": + return ~admin_success_sql() & ComparisonRecord.status.notin_(("cancelled", "running")) + return ComparisonRecord.status == status +``` + +- [ ] **Step 3b: 删除不再引用的 #209 常量** + +Task 3(概览 case 改 `admin_success_sql`)+ 本 Task(`_comparison_status_condition` 改 admin 口径)后,下列 #209 常量已无任何引用(`_comparison_status_condition` 耗时调用在 Task 3 已改走 `status_filter`)。删除 `queries.py` 里这整段(`_COMPARISON_STATUS_ALIASES` 定义起,至 `_COMPARISON_COMPLETED_STATUSES` 定义结束,约 45-62 行): + +```python +_COMPARISON_STATUS_ALIASES = { + "success": ("success", "below_minimum"), + "failed": ( + "failed", + "store_closed", + "store_not_found", + "items_not_found", + "no_delivery", + "unsupported", + ), + "cancelled": ("cancelled",), + "running": ("running",), +} +_COMPARISON_SUCCESS_STATUSES = _COMPARISON_STATUS_ALIASES["success"] +_COMPARISON_FAILED_STATUSES = _COMPARISON_STATUS_ALIASES["failed"] +_COMPARISON_COMPLETED_STATUSES = ( + *_COMPARISON_SUCCESS_STATUSES, + *_COMPARISON_FAILED_STATUSES, +) +``` + +> 删除前用 `grep -rn "_COMPARISON_SUCCESS_STATUSES\|_COMPARISON_COMPLETED_STATUSES\|_COMPARISON_STATUS_ALIASES\|_COMPARISON_FAILED_STATUSES" app/` 复核确无残留引用(应仅剩本段自身)。 + +- [ ] **Step 4: 运行确认通过 + 概览回归** + +Run: `cd e:/project/shaguabijia-app-server && ./.venv/Scripts/python.exe -m pytest tests/test_comparison_admin_summary.py -q` +Expected: PASS(3 passed) + +- [ ] **Step 5: 提交** + +```bash +cd e:/project/shaguabijia-app-server +git add app/admin/repositories/queries.py tests/test_comparison_admin_summary.py +git commit -m "feat(admin): 比价记录「状态」筛选对齐 admin 口径 + 清理 #209 死常量 + +Co-Authored-By: Claude Opus 4.8 (1M context) " +``` + +--- + +## Task 6: 前端类型 `types.ts`(admin-web) > 前端无测试框架(见 CLAUDE.md),用 `npx tsc --noEmit` 类型校验 + 手动核对。 @@ -770,7 +897,7 @@ Co-Authored-By: Claude Opus 4.8 (1M context) " --- -## Task 6: 前端状态列 + 详情 + 标签映射(admin-web) +## Task 7: 前端状态列 + 详情 + 标签映射(admin-web) **Files:** - Modify: `src/app/(main)/comparison-records/page.tsx`(`STATUS_LABEL`/`STATUS_COLOR` 精简、状态列 render、详情状态、import) @@ -866,7 +993,7 @@ Co-Authored-By: Claude Opus 4.8 (1M context) " --- -## Task 7: 状态口径文档补 admin 说明(后端,收尾) +## Task 8: 状态口径文档补 admin 说明(后端,收尾) **Files:** - Modify: `docs/guides/比价结果卡片-状态口径与交互参考.md`(app-server)