Files
shaguabijia-app-server/docs/api/compare-record-report.md
T
OuYingJun1024 15dcfa604b feat(compare): 比价记录落库 + 战绩里程碑(真发金币)
- comparison_record 表 + 上报(幂等 user+trace)/列表/详情 接口;服务端派生
  best/saved/is_source_best/status + information(done 帧文案/失败具体原因)
- 战绩里程碑:comparison_milestone_claim 表 + 进度/领取接口,按成功比价次数
  解锁,复用 grant_coins 真发金币(RECORD_MILESTONES 120/180/300/500/800/1200)
- 迁移 record/information/milestone 三个,单 head;rewards.py 集中档位配置
- 测试 test_compare_record(8)+test_compare_milestone(7) 全绿;docs/api 12a-12e + 索引

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 19:56:47 +08:00

3.7 KiB
Raw Blame History

POST /api/v1/compare/record — 上报一次比价结果(幂等)

所属:比价记录组(前缀 /api/v1/compare | 鉴权:Bearer | ← 返回 API 索引

比价 done 帧后,客户端用带 JWT 的通道上报一条比价结果,落 comparison_record 表,作为「我的比价记录」数据源 + 用户级行为画像。

⚠️ 与不鉴权的透传端点 /api/v1/price/step 不同:那是转发壳,本接口按用户维度落库,必须鉴权。 本轮只做 server 端;客户端在 done 帧后调本接口的改动另起一轮(见 待办与技术债.md P1)。

入参(JSON body

字段刻意对齐 pricebot 协议(02_api_protocol.mdcalibration + done.params),客户端把 Phase1 的 calibration 和 done 帧 params 零翻译映射上来即可。

字段 类型 必填 默认 说明
trace_id string pricebot 侧 trace_id。幂等键:同用户同 trace_id 重复上报覆盖、返回同一 id
business_type string food food(外卖,当前唯一接通) / ecom(电商) / coupon(领券)
device_id string | null null 设备号
store_name string | null null 店铺名(外卖,来自 calibration.result
source_platform_id string | null null 源平台代号,如 taobao_flash
source_platform_name string | null null 源平台中文名
source_package string | null null 源平台 Android 包名
source_price float | null null 源平台到手价(
items Item[] [] 下单菜品,{name, qty, specs?}
comparison_results Result[] [] 逐平台对比,见下表(price 单位
skipped_dish_count int | null null 目标平台未找到、跳过的菜品数
skipped_dish_names string[] [] 被跳过的菜名
total_dish_count int | null null 原始菜品总数
information string | null null done 帧文案(成功摘要 / 失败具体原因),持久化为列并在列表/详情返回,前端失败时当原因展示
status string | null null success / failed不传则服务端派生

Item{ name: string, qty: int=1, specs: string[]\|null }

Resultcomparison_results 元素){ platform_id, platform_name, package, price(元,float\|null), is_source(bool), rank(int\|null) }

服务端派生(客户端不用算)

comparison_results 派生并落结构化列:

  • best_*:取最便宜的一家(按 rank 升序、再按 price),写 best_platform_id/name/best_price_cents
  • source_price_cents:优先用 source_price,缺失则取 comparison_resultsis_source=true 行的价
  • saved_amount_cents = 源价 最优价(可为 0 / 负:源平台本来就最便宜)
  • is_source_best:最便宜的一家是否为源平台(= 这次没省到)
  • status(未显式传时):存在「非源且有价」的结果 → success,否则 → failed
  • 金额一律 round(元 × 100)

comparison_results / items / skipped_dish_names 原样存 JSON;完整上报 body 另存 raw_payload(详情接口可取回)。

出参

响应 200{ "id": int }(写入或已存在记录的 id

错误

  • 401 未鉴权
  • 422trace_id 或字段类型不符

说明

失败的比价(done 帧只有源/空 comparison_results)也会落一条 status=failed——「越详细越好」,是否在 UI 展示由前端过滤。