fix: 采购价格上限按数量计算总价 (#181)
This commit is contained in:
@@ -375,7 +375,7 @@ Admin 本地时区,付款状态只是 Client 核单上报时的快照,Admin
|
||||
2. 当前 PDD 商品已采集成功(`skus_json` 非空);
|
||||
3. 该顺运宝规格非空,且已有当前 PDD 商品的规格映射;
|
||||
4. 数量大于 0;
|
||||
5. **价格上限已填且大于 0** —— 默认从当前映射的 PDD 规格价格带出,操作员可改,但不允许为空;
|
||||
5. **人民币单价上限已填且大于 0** —— 默认从当前映射的 PDD 规格价格带出,操作员可改但不允许为空;页面显示 `单价 × 数量` 的订单总价上限,后端按最新数量重新计算并把总价写入 `max_price_cent`;
|
||||
6. 已选择分配的客户端;
|
||||
7. 所选客户端存在且在当前账号可见范围内;其在线状态和 `purchase_mode` 只影响何时领取,不阻止提前指派;
|
||||
8. 同一顺运宝明细没有 `pending` / `assigned` / `claimed` 的采购任务;
|
||||
@@ -454,10 +454,10 @@ Admin 新建采购任务固定使用不可变的 `execution_mode=live`,不向
|
||||
| 场景 | 币种 | 字段示例 |
|
||||
|---|---|---|
|
||||
| 蝦皮售价 | 台币 | `price_twd_cent` |
|
||||
| PDD 采购价、价格上限 | 人民币 | `max_price_cent` |
|
||||
| PDD 采购单价、订单总价上限 | 人民币 | SKU `price_cent`、任务 `max_price_cent` |
|
||||
|
||||
`[必须]` **两种币种不得混用,不得互相换算后覆盖原值。**
|
||||
采购任务里的价格上限是**人民币**,默认来源是采集回来的 PDD 价格,并由采购员逐行确认,
|
||||
采购任务里的单价及订单总价上限是**人民币**:单价默认来源是采集回来的 PDD SKU 价格并由采购员逐行确认,订单总价上限由后端按 `单价上限 × 数量` 计算,
|
||||
和蝦皮的台币售价没有换算关系。
|
||||
|
||||
`[待定]` 是否需要展示汇率或利润,待业务确认。MVP 不做。
|
||||
|
||||
@@ -371,7 +371,7 @@ UPDATE pdd_products
|
||||
| 字段 | Admin 拿它干什么 | 不给会怎样 |
|
||||
|---|---|---|
|
||||
| `skus[].options` | 匹配弹窗列出规格供人选 | 没东西可选,匹配做不了 |
|
||||
| `skus[].price_cent` | 建采购任务时带出 `max_price_cent` | 价格保护填不了,Client 会拒绝执行 |
|
||||
| `skus[].price_cent` | 建采购任务时带出单价上限,再乘采购数量生成 `max_price_cent` | 订单总价保护填不了,Client 会拒绝执行 |
|
||||
| `skus[].available` | 不给缺货规格建任务 | 白跑一趟,Client 到手机上才发现卖光 |
|
||||
| `goods_id` / `title` | 核对"采的是不是要的那个商品" | 链接跳转、采错商品时静默存错 |
|
||||
| `shop_name` | 核对是否来自目标店铺 | 同标题商品无法区分来源;采不到时允许为空 |
|
||||
@@ -429,7 +429,7 @@ CREATE INDEX idx_syb_orders_list ON syb_orders(updated_at DESC, syb_id DESC);
|
||||
```
|
||||
|
||||
- `price_twd_cent` 是**台币分**,是蝦皮那边的售价,
|
||||
和采购任务的人民币价格上限**没有换算关系**,不要互相赋值。
|
||||
和采购任务的人民币订单总价上限**没有换算关系**,不要互相赋值。
|
||||
- `image_url` 存 URL。`[必须]` 不要把图片二进制存进数据库。
|
||||
- `shop_name` 是顺运宝货运单级事实,同一货运单下的多条商品明细会重复保存同一值;
|
||||
独立列用于列表展示和检索,完整上游值仍保留在 `syb_data.stock.shopName`。
|
||||
@@ -705,7 +705,7 @@ CREATE INDEX idx_tasks_order ON tasks(order_no);
|
||||
2. **采购任务的 `quantity` 和 `max_price_cent` 都必须有值**,
|
||||
这是价格保护,没有它 Client 会拒绝执行。
|
||||
|
||||
`max_price_cent` 是**人民币分**,默认从 `pdd_data` 里对应 SKU 的价格带出,操作员可改但不能清空。
|
||||
`max_price_cent` 是**人民币订单总价上限(整数分)**。页面默认从 `pdd_data` 对应 SKU 带出单价上限,操作员可改但不能清空;后端在事务内按顺运宝最新数量计算 `单价上限 × quantity` 后写入本字段,并检查整数溢出。历史任务不回写。
|
||||
|
||||
状态含义见 [01 需求](01-requirements.md) §6.2。
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ X-Client-Id: client-001
|
||||
—— **指定给本机的优先**;
|
||||
|
||||
网页创建的采购任务固定走第一种:创建前已经校验当前账号对客户端的可见范围,
|
||||
并写入 `pdd_options`、`quantity` 和人民币 `max_price_cent`。这不改变 Client 接口字段。
|
||||
并写入 `pdd_options`、`quantity` 和人民币订单总价上限 `max_price_cent`。总价上限由采购员确认的 SKU 单价上限乘以顺运宝最新数量得到;这不改变 Client 接口字段。
|
||||
3. 没有就返回 `204 No Content`;
|
||||
4. 有就把 `status` 改成 `claimed`、记 `claimed_at`,返回任务。
|
||||
|
||||
@@ -120,7 +120,7 @@ Client 上报的 `capabilities.purchase_mode` 过滤:`dry_run` Client 只能
|
||||
Admin Web 可以把 live 任务预先指派给当前账号可见的任意 Client,不在创建时按该字段
|
||||
拒绝;尚未就绪的指定 Client 不会领取,待其设备与真实采购执行器就绪并自动上报 live 后领取。
|
||||
|
||||
`[必须]` `payload.goods_url` 必须有值;采购任务的 `quantity` 和 `max_price_cent` 必须有值。
|
||||
`[必须]` `payload.goods_url` 必须有值;采购任务的 `quantity` 和 `max_price_cent` 必须有值。`max_price_cent` 固定表示人民币订单总价上限,不得下发单价。
|
||||
这些在建任务时就该校验住(见 [01 需求](01-requirements.md) §5),
|
||||
不要等到这里才发现发不出去。
|
||||
|
||||
@@ -315,7 +315,7 @@ Client 契约里散落的 Admin 侧硬要求,汇总在这里,**可以直接
|
||||
- [ ] `claim` 无任务时返回 `204`,不是 `200` 加空对象
|
||||
- [ ] 响应不含租约、不含 Admin 侧状态
|
||||
- [ ] `payload.goods_url` 必有值
|
||||
- [ ] 采购任务的 `quantity`、`max_price_cent` 必有值,且是人民币分整数
|
||||
- [ ] 采购任务的 `quantity`、`max_price_cent` 必有值,后者是人民币订单总价上限的分整数
|
||||
- [ ] 可以预先指派 live 任务给可见 Client,但领取时不向只声明 `dry_run` 的客户端返回 live 任务
|
||||
- [ ] `result` / `failure` 幂等:同键同内容返回同结果
|
||||
- [ ] 同键不同内容返回 `409`
|
||||
|
||||
@@ -599,7 +599,7 @@ PDD 采集中(超时)行可用于
|
||||
### 6.4 创建采购任务
|
||||
|
||||
只有“可创建采购任务”的行能参与采购批量动作。勾选后打开服务端渲染的确认弹窗:选择当前账号
|
||||
可见的任意客户端,并逐行确认人民币价格上限。离线或尚未就绪的 Client 也可提前
|
||||
可见的任意客户端,并逐行确认人民币单价上限和自动计算的订单总价上限。离线或尚未就绪的 Client 也可提前
|
||||
指派,待其就绪后领取;选项继续显示在线状态但不因能力状态禁用。默认价格来自映射规格
|
||||
的 PDD 采集价;没有价格时留空强制填写。新任务固定为真实下单(不支付),不显示执行
|
||||
模式选择,也不再要求额外风险复选框、确认短语或浏览器二次确认。
|
||||
@@ -616,7 +616,7 @@ grid 样式不得覆盖 `hidden`,关闭后改变勾选再打开也不得残留
|
||||
- 同一明细已有 `pending`、`assigned`、`claimed`、`succeeded` 或 `manual_review` 的采购任务时
|
||||
拒绝重复创建;成功任务是采购终态,待人工核对任务可能已经下单。`failed/cancelled` 的现有
|
||||
人工判断后重新创建策略不变。
|
||||
- 顺运宝列表继续显示台币售价,但绝不把它带入人民币价格上限。
|
||||
- 顺运宝列表继续显示台币售价,但绝不把它带入人民币单价或订单总价上限。
|
||||
|
||||
```text
|
||||
成功创建 3 个任务。以下 2 条未创建:
|
||||
@@ -624,8 +624,8 @@ grid 样式不得覆盖 `hidden`,关闭后改变勾选再打开也不得残留
|
||||
· SO-...-009 规格未匹配
|
||||
```
|
||||
|
||||
`[必须]` 创建前弹出确认框,让操作员选**分配给哪个当前账号可见的 Client**,并确认价格上限。
|
||||
价格上限默认从当前映射的 PDD 规格采集价带出,可改,**不允许为空**。
|
||||
`[必须]` 创建前弹出确认框,让操作员选**分配给哪个当前账号可见的 Client**,并确认人民币单价上限。
|
||||
单价上限默认从当前映射的 PDD 规格采集价带出,可改,**不允许为空**。每行必须同时显示固定数量和即时计算的 `订单总价上限 = 单价上限 × 数量`;总价使用只读 `output` 和 `aria-live` 提供反馈。JavaScript 只负责展示,后端必须用数据库中的最新数量重新计算。
|
||||
|
||||
可采购行的“下一步”显示“创建采购任务”。点击后复用同一个确认弹窗并只带入当前明细,
|
||||
不改变表格复选框状态;顶部批量入口仍按已勾选明细打开。客户端选项显示名称和 Client
|
||||
@@ -634,7 +634,7 @@ ID 和在线状态;所有可见 Client 都可选择且只有一个时自动选
|
||||
“采集采购”页,不得再次创建;采购完成行显示
|
||||
“查看采购结果”,待人工核对行显示“查看采购任务”,两者同样进入按订单号筛选的采集采购页。
|
||||
服务端仍必须重新
|
||||
校验映射、数量、人民币价格上限、客户端权限、固定 live 模式、创建审计和重复任务,不能
|
||||
校验映射、数量、人民币单价与订单总价上限、客户端权限、固定 live 模式、创建审计和重复任务,不能
|
||||
信任列表页的旧状态。
|
||||
|
||||
|
||||
@@ -677,9 +677,9 @@ placeholder 写「任务编号 / 订单号 / 商品 ID」,**不要写全「PDD
|
||||
不能只靠前缀或颜色区分。
|
||||
|
||||
- `[必须]` **目标列**:采集显示 `PDD <pdd_goods_id>`(能 join 到未删除商品
|
||||
的标题时追加显示);采购显示 `<order_no> · <颜色/尺码> · <数量>件 · ≤<价格上限>`。
|
||||
的标题时追加显示);采购显示 `<order_no> · <颜色/尺码> · <数量>件 · ≤<订单总价上限>`。
|
||||
拼接逻辑在 service 层组装成一个字符串,模板只负责显示。
|
||||
- `[必须]` 价格上限显示成 `¥42.00`(分转元),底层存的是整数分。
|
||||
- `[必须]` 订单总价上限显示成 `¥42.00`(分转元),底层存的是整数分。
|
||||
- `[必须]` **PDD 店铺列**:按任务的 `pdd_goods_id` 关联当前未删除
|
||||
`pdd_products.shop_name`;没有商品、尚未采集、店铺为空或商品已软删除时显示 `—`。
|
||||
- `[必须]` **客户端列**:优先显示当前 `clients.name`;名称为空或客户端记录不存在时
|
||||
@@ -711,7 +711,7 @@ placeholder 写「任务编号 / 订单号 / 商品 ID」,**不要写全「PDD
|
||||
│ PDD 店铺 某某店铺 │
|
||||
│ 目标规格 黑色 / M (采购任务才有) │
|
||||
│ 数量 2 (采购任务才有) │
|
||||
│ 价格上限 ¥42.00 (采购任务才有) │
|
||||
│ 订单总价上限 ¥42.00 (采购任务才有) │
|
||||
├──────────────────────────────────────────────┤
|
||||
│ PDD 核单结果 (采购任务才有) │
|
||||
│ PDD 订单编号 PDD-20260810-001 │
|
||||
@@ -727,7 +727,7 @@ placeholder 写「任务编号 / 订单号 / 商品 ID」,**不要写全「PDD
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- `[必须]` 采购专有字段(数量、价格上限、目标规格)在采集任务的弹窗里
|
||||
- `[必须]` 采购专有字段(数量、订单总价上限、目标规格)在采集任务的弹窗里
|
||||
**整段隐藏**,不显示空行。
|
||||
- PDD 核单结果只在采购任务显示,订单编号使用可选择复制的普通文本;付款状态标签
|
||||
必须包含“上报时”,不能暗示为实时状态。
|
||||
|
||||
Reference in New Issue
Block a user