4.2 KiB
4.2 KiB
产品编辑 订金设置 固定金额/比例 严格互斥
服务: hl-product-service-v2 (端口 8083) PR: #819 Issue: #816 日期: 2026-04-18 影响范围: 产品编辑 Step1 基础信息 → 订金设置
一、变更说明
此前后端未对订金"固定金额"和"比例"做互斥校验,允许两字段同时有值写入数据库;下单报价时按「固定额 > 0 优先」的逻辑处理,导致比例字段在同时有值时永远不生效,产生脏数据。
现在后端强制两字段任意时刻最多只有一个有值:
- 同时提交两个字段(都 > 0)→ 后端 400 拒绝,返回提示"订金固定金额与比例互斥,只能填写其中一个"
- 保存时若
depositAmount有值 → 数据库deposit_ratio显式置 NULL - 保存时若
depositRatio有值 → 数据库deposit_amount显式置 NULL - 两者都为 null(或 0)→ 合法(视为全款模式 PaymentType=FULL)
二、前端必须配合
切换 tab 时清空对方字段再提交,否则后端直接拒绝:
| 前端场景 | 必须提交的 payload |
|---|---|
| 用户选"固定金额"填 500 | { "depositAmount": 500, "depositRatio": null } |
| 用户从"固定金额"切到"比例"填 10% | { "depositAmount": null, "depositRatio": 10 } |
| 用户选"全款支付"(无订金) | { "paymentType": "FULL", "depositAmount": null, "depositRatio": null } |
| ❌ 错误示例(会被 400) | { "depositAmount": 500, "depositRatio": 10 } |
关键点:切换 tab 时必须把对方字段在提交前 reset 成 null,不要只是隐藏输入框。前端 state 里残留另一方的历史值会让后端拒绝。
三、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 保存产品基础信息 | POST | /admin/product-basic/save |
请求体新增校验 | depositAmount/depositRatio 不得同时 > 0 |
四、接口详情
1. 保存产品基础信息 POST /admin/product-basic/save
VO: ProductBasicSaveReqVO
相关字段(字段本身没改,校验行为改了):
| 字段 | 类型 | 必填 | 说明 | 变化 |
|---|---|---|---|---|
paymentType |
String | 是 | 支付方式:FULL=全款, DEPOSIT=订金+尾款 |
无 |
depositAmount |
BigDecimal | 否 | 订金固定金额(元/人),与 depositRatio 互斥 |
互斥校验 |
depositRatio |
Integer | 否 | 订金比例(%),与 depositAmount 互斥 |
互斥校验 |
互斥规则:
depositAmount和depositRatio任意时刻最多只有一个 > 0- 两者都 null / 都 0 → 合法
- 其中一个有值,另一个必须为 null 或 0
违反互斥的错误响应:
{
"code": 400,
"message": "depositMutex: 订金固定金额与比例互斥,只能填写其中一个",
"success": false,
"data": null
}
五、数据库行为
保存成功后数据库 product_basic 表:
| 前端提交 | deposit_amount 列 |
deposit_ratio 列 |
|---|---|---|
depositAmount=500, depositRatio=null |
500.00 |
NULL |
depositAmount=null, depositRatio=10 |
NULL |
10 |
| 都为 null | NULL |
NULL |
即使前端不传"对方字段",后端也会显式 SET NULL,不会保留数据库里的历史残留值。
六、下单/报价逻辑未变
下单报价(InternalProductService.fillPaymentInfo)规则保持不变:
paymentType = 'DEPOSIT' 时:
if depositAmount > 0: 使用固定金额
else if depositRatio > 0: depositAmount = totalPrice × depositRatio / 100
else: depositAmount = 0
因为现在产品保存阶段已经保证了两字段互斥,下单阶段永远走其中一条分支,不会再出现"两个都有值但比例被忽略"的脏数据场景。
七、影响范围
- 仅影响管理后台产品编辑的订金设置表单
- 小程序端 C 端算价、订单创建、订单详情等接口零影响
- 历史数据(已经同时有两字段值的产品):后端读取逻辑不变,仍按固定额优先,不会异常。下次编辑保存时才会触发互斥校验