Files
shaguabijia-app-server/docs/database/comparison_record.md
T
ouzhou 90c0d65a16 chore(alembic): merge comparison_milestone 和 savings_report_fields 两个 head (#11)
Co-authored-by: OuYingJun1024 <1034284404@qq.com>
Reviewed-on: #11
Co-authored-by: ouzhou <ouzhou@wonderable.ai>
Co-committed-by: ouzhou <ouzhou@wonderable.ai>
2026-06-03 09:48:28 +08:00

48 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# comparison_record — 比价记录(每次比价完整明细)
> 模型 `app/models/comparison.py` | 关联接口 [compare-record-report](../api/compare-record-report.md) / [compare-records](../api/compare-records.md) / [compare-record-detail](../api/compare-record-detail.md) | [← 表索引](./README.md)
每完成一次比价(外卖/电商/领券),客户端 done 帧后用带 JWT 通道上报一条。「我的比价记录」页数据源,也是比价战绩里程碑解锁进度的计数源(`status='success'` 条数)。
> 与 `savings_record` 的区别:本表是「每一次**比价行为**的完整明细」(不省钱、甚至失败也记);`savings_record` 是「真正**下单成交**省了多少」。两表独立、互不喂数据。
## 字段
| 列 | 类型 | 约束 / 默认 | 说明 |
|---|---|---|---|
| `id` | Integer | PK, autoincrement | |
| `user_id` | Integer | FK→user.id, index, NOT NULL | 归属用户 |
| `device_id` | String(64) | nullable | 设备号 |
| `business_type` | String(16) | NOT NULL, default `food`, index | `food`(当前唯一接通)/ `ecom` / `coupon` |
| `trace_id` | String(64) | NOT NULL | pricebot 侧 trace_id(关联调试落盘 + 幂等键) |
| `source_platform_id` | String(32) | nullable | 源平台代号 |
| `source_platform_name` | String(32) | nullable | 源平台中文名 |
| `source_package` | String(128) | nullable | 源平台 Android 包名 |
| `source_price_cents` | Integer | nullable | 源平台到手价(分) |
| `best_platform_id` | String(32) | nullable | 最优平台代号(= rank=1) |
| `best_platform_name` | String(32) | nullable | 最优平台中文名 |
| `best_price_cents` | Integer | nullable | 最优价(分) |
| `saved_amount_cents` | Integer | nullable | 源价 最优价(可 0/负) |
| `is_source_best` | Boolean | nullable | 源平台就是最便宜(= 没省到) |
| `store_name` | String(128) | nullable | 店铺名 |
| `total_dish_count` | Integer | nullable | 菜品总数 |
| `skipped_dish_count` | Integer | nullable | 跳过(没找到)菜品数 |
| `status` | String(16) | NOT NULL, default `success` | `success`(拿到有效对比)/ `failed`(出错/没采到目标价) |
| `information` | String(256) | nullable | done 帧文案;成功=摘要,失败=具体原因(前端失败时当原因展示) |
| `items` | JSON(PG: JSONB) | NOT NULL, default [] | 下单菜品 `[{name, qty, specs?}]` |
| `comparison_results` | JSON(PG: JSONB) | NOT NULL, default [] | 逐平台对比 `[{platform_id,platform_name,package,price(元),is_source,rank,coupon_saved}]`;`coupon_saved`=该平台主优惠额(元,美团红包/淘宝平台红包/京东优惠券·百亿补贴,只取那一笔,不含配送费/共减总额),各平台抠到红包即带值(2026-06 起源平台 Phase1 意图识别也抠,当前仅淘宝源),没用/没抠到为 null,前端展示「已优惠 ¥X」 |
| `skipped_dish_names` | JSON(PG: JSONB) | NOT NULL, default [] | 被跳过的菜名 |
| `raw_payload` | JSON(PG: JSONB) | nullable | 客户端原始上报(calibration + done.params 全量) |
| `created_at` | DateTime(tz) | server_default now(), index | 时间 |
## 索引与约束
- PK: `id`;index: `user_id``business_type``created_at`
- UNIQUE(`user_id`, `trace_id`) = `uq_comparison_user_trace`(同次比价重试/重复上报幂等覆盖)
## 关系
- `user_id``user.id`(多对一)
-`comparison_milestone_claim` 间接依赖:里程碑解锁进度 = 本表 `status='success'` 条数。
## 说明
- `best_*` / `saved_amount_cents` / `is_source_best` / `status``repositories/comparison.py:_derive``comparison_results` 派生,客户端不用自己算。
- 4 个 JSON 列用 `JSON().with_variant(JSONB(),"postgresql")`(SQLite 退化 JSON)。金额结构化列存「分」,`comparison_results.price` 原样存「元」。