b4780e256e
- 重写 15 张已有表文档:每张补「用在 App 哪/增删改查时机/字段取值/join key 指向」 - 新建 4 张缺失表文档:wechat_transfer_authorization / ad_watch_log / price_report / app_config - 新增 OVERVIEW.md:功能↔表映射 + 写入路径 + 表间关系(含语义 join key)+ ER + 资金模型 - README 索引补齐到 19 表 + 置顶 OVERVIEW + 通用约定补全 - 纠正过时:withdraw_order(reviewing/rejected/user_name)、savings_record(/order/report 真实写入)、coin_transaction(biz_type) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
43 lines
3.8 KiB
Markdown
43 lines
3.8 KiB
Markdown
# price_report — 上报更低价(众包纠偏)
|
|
|
|
> 模型 `app/models/price_report.py` · 仓库 `app/repositories/report.py` · 接口 `POST /api/v1/report`(提交,multipart)/ `GET /api/v1/report/records`(列表)· [← 索引](./README.md) · [总览](./OVERVIEW.md)
|
|
|
|
用户在「我的比价记录」里选一条,举报「某平台比我们算出的最低价更便宜」,带 1~4 张截图证明,人工审核通过后发金币奖励。与 `feedback`(自由文本)不同:本表**结构化**——关联具体比价记录、原最低价 vs 上报价、审核状态、奖励。是「省钱护城河」的众包纠偏入口。
|
|
|
|
## 用在哪 / 增删改查
|
|
- **C(插入)**:`POST /api/v1/report`(multipart:`comparison_record_id` + `reported_platform_id` + `reported_price`(元) + `images`)。后端 `create_report`:① 反查 `comparison_record`(须属本人)取 `best_price_cents` 作"原最低价";② **校验上报价 < 原最低价**(否则 400);③ 截图经 `core.media` 落 `/media/price_report/`;④ 写一行 `status='pending'`。**原最低价快照由后端反查,不信客户端传值**。
|
|
- **U(更新,审核)**:人工审核后台改 `status`(approved/rejected)+ `reject_reason` / `reward_coins` / `reviewed_at`(当前审核动作在 admin 侧,提交一律 pending)。
|
|
- **D**:无。关联的 `comparison_record` 若被删,本行 `comparison_record_id` 置空(可空 FK),上报历史保留。
|
|
- **R**:`GET /api/v1/report/records`(用户上报列表,可按 `status` 筛,带各状态计数)。
|
|
|
|
## 字段
|
|
| 列 | 类型 | 约束 / 默认 | 说明(取值 / join) |
|
|
|---|---|---|---|
|
|
| `id` | Integer | PK, autoincrement | |
|
|
| `user_id` | Integer | FK→user.id, index, NOT NULL | 上报用户 |
|
|
| `comparison_record_id` | Integer | FK→comparison_record.id, index, nullable | 选中的那条比价记录(删后置空保留历史) |
|
|
| `store_name` | String(128) | nullable | 门店名快照(反查 comparison_record 冗余存,防关联记录改/删) |
|
|
| `dish_summary` | String(256) | nullable | 菜品摘要(由比价记录 items 的菜名拼成) |
|
|
| `original_platform_id` / `_name` | String(32) | nullable | 原最低价平台快照(= 比价记录 best_platform_*) |
|
|
| `original_price_cents` | Integer | nullable | 原最低价(分,后端反查 `comparison_record.best_price_cents`) |
|
|
| `reported_platform_id` | String(32) | NOT NULL | 用户上报的更低价平台,取值 `meituan-waimai`/`jd-waimai`/`taobao-shanguang`(canonical id) |
|
|
| `reported_platform_name` | String(32) | NOT NULL | 上报平台展示名(美团外卖/京东外卖/淘宝闪购) |
|
|
| `reported_price_cents` | Integer | NOT NULL | 用户上报的更低价(分);**校验必须 < `original_price_cents`** |
|
|
| `images` | JSON | NOT NULL, default [] | 截图相对 URL 列表 `/media/price_report/...`(1~4 张) |
|
|
| `status` | String(16) | NOT NULL, default `pending`, index | 取值:`pending`(审核中)/ `approved`(通过)/ `rejected`(未通过) |
|
|
| `reject_reason` | String(256) | nullable | 驳回原因(审核填) |
|
|
| `reward_coins` | Integer | nullable | 通过后发的金币(人工审核后台动作,提交时为 null) |
|
|
| `reviewed_at` | DateTime(tz) | nullable | 审核时间 |
|
|
| `created_at` | DateTime(tz) | server_default now(), index | 提交时间 |
|
|
|
|
## 关系 / Join Key
|
|
- `user_id` → `user.id`(多对一)。
|
|
- `comparison_record_id` → `comparison_record.id`(多对一,可空)。提交时**读** `comparison_record` 的 `best_price_cents`(校验)/ `best_platform_*` / `store_name` / `items`(冗余快照),之后即使原记录变动也对得上。
|
|
|
|
## 索引与约束
|
|
- PK `id`;index `user_id`、`comparison_record_id`、`status`、`created_at`。
|
|
|
|
## 注意
|
|
- 奖励发放(approved → 钱包 +`reward_coins`)是人工审核后台动作,提交一律 `pending`,本表只留字段。
|
|
- 截图复用 `core.media`(魔数嗅探 + 随机文件名),与头像/反馈同一套上传。
|