fix(compare): 「已下单」从店级改按 trace_id 精确对齐 #224
Reference in New Issue
Block a user
Delete Branch "fix/compare-ordered-attribution-by-trace-id"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景 / 问题
比价记录页「已下单」tab 混进大量本不该出现的记录:同一家店比价多次、只下过一单,却把这家店的每一条比价(含失败灰卡、没真正下单的成功比价)都塞进「已下单」。
根因
「已下单」原先是店级判定——下单上报(POST /order/report)不带 trace_id、savings_record 也没有指向具体某次比价的键,服务端只能用 savings_record.shop_name == comparison_record.store_name 做店名匹配 → 同店所有比价一并命中。属"先有省钱记账、后蹭已下单"的历史债(见 docs/database/savings_record.md 的 Join Key 注释)。
方案
把 trace_id 从比价会话打通到下单上报,「已下单」改为按 trace_id 精确对齐到那一条比价:
下单上报带上本次比价 trace_id → 落 savings_record.trace_id;
「已下单」过滤/打标(C 端 + admin)统一改成 savings_record.trace_id == comparison_record.trace_id(comparison 侧 trace_id 本就是 NOT NULL UNIQUE);
不做店名回退、不回填历史:没有 trace_id 的订单(历史/老客户端)对齐不上任何记录 → 不进「已下单」。
行为变化(评审必看)
上线后「已下单」只反映"更新版客户端下的新单":历史订单 + 老客户端过渡期订单没 trace_id,不再进「已下单」,随客户端铺量回血。
失败/终止比价不再进「已下单」(本就没真正下单;trace_id 只会指向有价可点的成功比价)。
后台看板「下单数」会掉:历史 savings_record 全是 trace_id=NULL,period_ordered_count 上线当天明显下跌——是口径变化、非回归,请知会看数据的同学。
必须与客户端一起上:只上服务端 → 订单永远不带 trace_id → 任何订单都对不上 → 「已下单」永远空。见关联 android PR。
🤖 review-pr 深审结论
🟢 看着没问题(置信度 0.88)。服务端把「已下单」从店级(店名匹配)改为按
trace_id精确对齐单次比价:新增savings_record.trace_id列 + 迁移,上报落库,读取端(C 端分页 / admin queries / dashboard 统计)全部切到 trace_id。与 Android #396 契约字段名一致,闭环。契约核对(合并 main 后)
schemas/order.pyOrderReportRequest.trace_id(≤64)↔ Android #396 上报体put("trace_id", ...)字段名一致 ✓ComparisonRecord.trace_id为 非空必填(compare/record无 trace_id 会 422),故dashboard_overview去掉store_name.is_not(None)守卫、改用SavingsRecord.trace_id == ComparisonRecord.trace_id的 EXISTS 是安全的 ✓alembic heads→ 单 headsavings_record_trace_id(down_revision=comparison_updated_at,无兄弟迁移撞车、无多头)✓测试/构建:✅ 已实跑(合并 main 后 worktree,venv Py3.12)
pytest tests/test_compare_record.py tests/test_admin_read.py→ 43 passedpytest tests/test_admin_roles.py tests/test_cps_admin.py→ 21 passedissues:无 high/med。
trace_id=NULL)不再标「已下单」。作者已在迁移 docstring 明确「不做回填」,是本次「店级→单次级」的既定取舍。上线需与 App #396 协同发布——老 App 未更新期间新下单不带 trace_id,「已下单」率会临时下降。正面:契约闭环干净;保留了原「只查本页 trace_id、不全量捞回内存」的性能写法(避免随下单量线性变慢 + SQLite 绑定变量上限);注释把 demo/老客户端/历史三种 NULL 情形都讲清了。
建议:与 App #396 协同上线;product 知悉历史「已下单」会因无回填而消失(如需保留可另做一次性回填脚本,但会牺牲精确性,通常不必)。