feat(admin): 比价记录改「技术成功/失败」口径,外部缺失记为成功 #217

Merged
guke merged 9 commits from feat/admin-comparison-outcome-display into main 2026-08-04 18:49:31 +08:00
Member

背景
admin 比价记录页 / 概览 / 大盘此前把「未找到店、未找到菜、门店打烊、单点不配送、平台不支持、未满起送」统统显示/统计为失败——根因是 #209 把这些业务结局归一化成记录级 status='failed' 落库。但它们其实是比价流程正常跑完、只是外部原因导致结果缺失;与「系统技术故障」混为一谈后,管理员排查时无法区分「是我们系统的锅」还是「目标平台本来就没这家店/这些菜」。

方案
admin 后台改用技术完成率口径:流程跑完(非 running)且非纯技术故障 → 记为成功,有外部缺失的前端标绿「成功」+ ⚠(hover 看具体原因);只有真正的技术故障 failed 才是失败。

口径收敛到新模块 app/admin/repositories/comparison_outcome.py,被列表下发 / 概览 / 大盘 / 状态筛选共同消费(单一真相源)。
原始业务结局取自 raw_payload.record_status(3 级 coalesce 兜底,兼容历史残留;Python 派生与 SQL 判定 bit 一致)。
仅 admin,不碰 C 端 / #209 落库 / 奖励逻辑——admin 关心「系统跑没跑成」,C 端关心「省没省到钱」,刻意分层。

口径映射

原始 record_status admin 状态 hover 提示
success 🟢 成功
below_minimum 🟢 成功 ⚠ 未满起送
store_closed 🟢 成功 ⚠ 门店打烊
store_not_found 🟢 成功 ⚠ 未找到店
items_not_found 🟢 成功 ⚠ 未找到菜
no_delivery 🟢 成功 ⚠ 单点不配送
unsupported 🟢 成功 ⚠ 平台·场景不支持
failed(纯技术故障) 🔴 失败
cancelled / running 中途退出 / 🔵 进行中

改动清单
新增 comparison_outcome.py:derive_admin_outcome(列表 Python 派生) + admin_success_sql(聚合/筛选 SQL 判定)。
列表/详情 下发 admin_status + outcome_hint(瞬态挂载,零额外查询)。
概览 comparison_records_summary:success / completed / 耗时分位改 admin 口径。
大盘 dashboard_overview:比价成功率改 admin 口径(顺带补齐 #209 未同步大盘的 below_minimum)。
状态筛选 _comparison_status_condition:筛「成功」含 6 类、筛「失败」仅纯技术故障;清理 #209 遗留死常量。
文档 补 admin 口径说明。

背景 admin 比价记录页 / 概览 / 大盘此前把「未找到店、未找到菜、门店打烊、单点不配送、平台不支持、未满起送」统统显示/统计为失败——根因是 #209 把这些业务结局归一化成记录级 status='failed' 落库。但它们其实是比价流程正常跑完、只是外部原因导致结果缺失;与「系统技术故障」混为一谈后,管理员排查时无法区分「是我们系统的锅」还是「目标平台本来就没这家店/这些菜」。 方案 admin 后台改用技术完成率口径:流程跑完(非 running)且非纯技术故障 → 记为成功,有外部缺失的前端标绿「成功」+ ⚠(hover 看具体原因);只有真正的技术故障 failed 才是失败。 口径收敛到新模块 app/admin/repositories/comparison_outcome.py,被列表下发 / 概览 / 大盘 / 状态筛选共同消费(单一真相源)。 原始业务结局取自 raw_payload.record_status(3 级 coalesce 兜底,兼容历史残留;Python 派生与 SQL 判定 bit 一致)。 仅 admin,不碰 C 端 / #209 落库 / 奖励逻辑——admin 关心「系统跑没跑成」,C 端关心「省没省到钱」,刻意分层。 口径映射 原始 record_status | admin 状态 | hover 提示 -- | -- | -- success | 🟢 成功 | — below_minimum | 🟢 成功 ⚠ | 未满起送 store_closed | 🟢 成功 ⚠ | 门店打烊 store_not_found | 🟢 成功 ⚠ | 未找到店 items_not_found | 🟢 成功 ⚠ | 未找到菜 no_delivery | 🟢 成功 ⚠ | 单点不配送 unsupported | 🟢 成功 ⚠ | 平台·场景不支持 failed(纯技术故障) | 🔴 失败 | — cancelled / running | ⚪ 中途退出 / 🔵 进行中 | — 改动清单 新增 comparison_outcome.py:derive_admin_outcome(列表 Python 派生) + admin_success_sql(聚合/筛选 SQL 判定)。 列表/详情 下发 admin_status + outcome_hint(瞬态挂载,零额外查询)。 概览 comparison_records_summary:success / completed / 耗时分位改 admin 口径。 大盘 dashboard_overview:比价成功率改 admin 口径(顺带补齐 #209 未同步大盘的 below_minimum)。 状态筛选 _comparison_status_condition:筛「成功」含 6 类、筛「失败」仅纯技术故障;清理 #209 遗留死常量。 文档 补 admin 口径说明。
guke added 8 commits 2026-08-04 17:38:20 +08:00
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
admin 比价页/概览/大盘把外部缺失(店/菜/打烊/不配送/不支持/未满起送)记为成功、
仅纯技术故障算失败,刻意宽于 C 端;故 admin 成功率≠C端口径,非 bug。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Member

🤖 review-pr 深审结论

🟢 可合并 — admin 展示口径重构(外部缺失记为成功、纯技术故障才失败),Python/SQL 双实现口径严格对齐;实跑测试全绿。置信度 0.9。

契约(供前端配套 admin-web#104)

AdminComparisonListItem 新增 admin_status: str(success/failed,admin 口径) + outcome_hint: str|null(非空=有缺失,前端标感叹号);原 status 保留。

核对要点

  • Python↔SQL 口径一致derive_admin_outcome(列表逐行) 与 admin_success_sql(概览/大盘统计) 判定一致——SQL coalesce(nullif(record_status,''), nullif(status,''), status列) 精确对齐 Python record_status or status or status列 的短路+空串跳过;cancelled/running 两侧都不计入 success。
  • success_rate 口径正确started=count(id)(总数含 cancelled/running),分母=started-cancelled(非取消数),success 现含外部缺失 → 「技术完成率」上升,符合本 PR 意图;既有分母逻辑未变,无重复扣减。
  • 隔离干净:仅 admin 读取时 Python/SQL 层派生,不碰 C 端 / #209 落库(注释明确,改动全在 app/admin/)。
  • 兼容老记录:coalesce 兜底 status 列,细分值残留在 status 列的历史记录仍正确归类。
  • 顺带一批 timezone.utcUTC(Py3.11 别名)纯风格重构,无语义变化。

构建/测试(已实跑, .venv py3.12.7)

合并最新 main(clean)后 pytest tests/test_admin_comparison_outcome.py tests/test_admin_read.py tests/test_comparison_admin_summary.py46 passed in 12.81s(隔离临时 sqlite)。

观察(非阻断)

success_rate 分母含 running(还在跑的),会让实时成功率略偏低——属既有口径、本 PR 未改,running 瞬态占比小,可接受。

正面

口径 Python/SQL 双实现且严格对齐、隔离不碰落库、兼容老记录、测试覆盖充分(专门的 outcome 用例),附状态口径设计文档。

🤖 自动深审 · 结论仅供参考,请以人工判断为准

## 🤖 review-pr 深审结论 🟢 **可合并** — admin 展示口径重构(外部缺失记为成功、纯技术故障才失败),Python/SQL 双实现口径严格对齐;实跑测试全绿。置信度 0.9。 ### 契约(供前端配套 admin-web#104) `AdminComparisonListItem` 新增 `admin_status: str`(success/failed,admin 口径) + `outcome_hint: str|null`(非空=有缺失,前端标感叹号);原 `status` 保留。 ### 核对要点 - **Python↔SQL 口径一致**:`derive_admin_outcome`(列表逐行) 与 `admin_success_sql`(概览/大盘统计) 判定一致——SQL `coalesce(nullif(record_status,''), nullif(status,''), status列)` 精确对齐 Python `record_status or status or status列` 的短路+空串跳过;cancelled/running 两侧都不计入 success。 - **success_rate 口径正确**:`started=count(id)`(总数含 cancelled/running),`分母=started-cancelled`(非取消数),`success` 现含外部缺失 → 「技术完成率」上升,符合本 PR 意图;既有分母逻辑未变,无重复扣减。 - **隔离干净**:仅 admin 读取时 Python/SQL 层派生,**不碰 C 端 / #209 落库**(注释明确,改动全在 `app/admin/`)。 - **兼容老记录**:coalesce 兜底 `status` 列,细分值残留在 status 列的历史记录仍正确归类。 - 顺带一批 `timezone.utc`→`UTC`(Py3.11 别名)纯风格重构,无语义变化。 ### 构建/测试(已实跑, .venv py3.12.7) 合并最新 `main`(clean)后 `pytest tests/test_admin_comparison_outcome.py tests/test_admin_read.py tests/test_comparison_admin_summary.py` → **46 passed in 12.81s**(隔离临时 sqlite)。 ### 观察(非阻断) `success_rate` 分母含 `running`(还在跑的),会让实时成功率略偏低——属既有口径、本 PR 未改,running 瞬态占比小,可接受。 ### 正面 口径 Python/SQL 双实现且严格对齐、隔离不碰落库、兼容老记录、测试覆盖充分(专门的 outcome 用例),附状态口径设计文档。 <sub>🤖 自动深审 · 结论仅供参考,请以人工判断为准</sub>
guke added 1 commit 2026-08-04 18:45:33 +08:00
guke merged commit 03129e059f into main 2026-08-04 18:49:31 +08:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WonderableAI/shaguabijia-app-server#217