diff --git a/changelogs-v2/2026-06/22_4205_订单增减项改造-新增接口-管理后台.md b/changelogs-v2/2026-06/22_4205_订单增减项改造-新增接口-管理后台.md new file mode 100644 index 0000000..90e6f23 --- /dev/null +++ b/changelogs-v2/2026-06/22_4205_订单增减项改造-新增接口-管理后台.md @@ -0,0 +1,313 @@ +# 订单增减项改造 — 新增统一端点 + 出参增 itemCode/itemName + +- **日期**: 2026-06-22 +- **端类型**: 管理后台 +- **服务**: hl-order-service-v3(端口 8086) +- **接口路径前缀**: /v3/admin/order +- **PR**: [#4207](https://git.1814.love:8443/wx/HL/pulls/4207) +- **Issue**: [#4205](https://git.1814.love:8443/wx/HL/issues/4205) +- **Commit**: [3a3577aa9](https://git.1814.love:8443/wx/HL/commit/3a3577aa9de39857d66c3e1811420ce175956f0a) +- **后端负责人**: 腰苏图(yaosutu) + +--- + +## 1. 接口背景 + +订单详情页原「添加优惠」按鈕,升级为「订单增减项」:**既能加优惠(减项)又能加费用(增项)**。改造前项目名是自由文本输入;改造后改为**数据字典选项**,前端渲染 chip 单选。 + +本次变更要点: + +- **新增** 统一端点 POST /v3/admin/order/{orderId}/adjustment,direction 字段区分减项/增项,前端只维护一套提交逻辑 +- **新建** 两个数据字典 type(order_discount_item / order_surcharge_item),前端动态拉取渲染 +- **增强** 优惠/附加费清单接口出参,discounts[]/surcharges[] 各新增 itemCode + itemName 字段 +- 旧端点 POST /v3/admin/order/{orderId}/discounts 和 /surcharges 已标为 @Deprecated,前端改调 /adjustment;**撤销端点不变** + +--- + +## 2. 变更清单 + +| # | 变更类型 | 接口 / 字段 | 影响 | +|---|----------|------------|------| +| 1 | ✨ 新增接口 | POST /v3/admin/order/{orderId}/adjustment | 统一增减项写入,替代旧两端点 | +| 2 | ✨ 新增字典 | order_discount_item(8 项) | 减项/优惠选项,前端动态拉取 | +| 3 | ✨ 新增字典 | order_surcharge_item(6 项) | 增项/费用选项,前端动态拉取 | +| 4 | ✨ 出参新增字段 | discounts[].itemCode / discounts[].itemName | 优惠/附加费清单接口 | +| 5 | ✨ 出参新增字段 | surcharges[].itemCode / surcharges[].itemName | 同上 | +| 6 | 🔧 旧端点废弃 | POST /v3/admin/order/{orderId}/discounts | @Deprecated,Swagger 隐藏,前端不再调用 | +| 7 | 🔧 旧端点废弃 | POST /v3/admin/order/{orderId}/surcharges | @Deprecated,Swagger 隐藏,前端不再调用 | + +--- + +## 3. 接口详情 + +### 3.1 新增统一增减项端点 + +| 项 | 值 | +|---|---| +| 方法 | POST | +| 路径 | /v3/admin/order/{orderId}/adjustment | +| 接口名 | 订单增减项(统一端点,按 direction 分流) | +| 认证 | Bearer JWT(管理后台 token) | +| 幂等性 | 有(@Idempotent,同用户同订单重复提交返回首次结果) | +| 并发锁 | 有(@Lock4j,同订单并发请求串行执行) | +| Content-Type | application/json | + +### 3.2 字典查询接口(走 user-service,路径与现有字典接口相同) + +| 方法 | 路径 | 说明 | +|---|---|---| +| GET | /admin/dict/data/order_discount_item | 获取减项选项列表 | +| GET | /admin/dict/data/order_surcharge_item | 获取增项选项列表 | + +返回格式示例: + +前端渲染 chip 单选,提交时传 value(即 itemCode)。 + +--- + +## 4. 接口入参 + +### 4.1 路径参数 + +| 参数 | 类型 | 必填 | 说明 | +|---|---|---|---| +| orderId | Long | 是 | 订单 ID | + +### 4.2 请求体字段(OrderAdjustmentReqVO) + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---|---|---| +| direction | String | 是 | 增减方向:REDUCE=减项/优惠,ADD=增项/附加费 | "REDUCE" | +| itemCode | String | 是 | 项目代码:REDUCE 时取 order_discount_item 的 value,ADD 时取 order_surcharge_item 的 value | "OLD_CUSTOMER" | +| amount | String | 是 | 金额(元),必须 > 0,传字符串防 JS 精度丢失 | "200.00" | +| remark | String | 否 | 备注,最多 500 字 | "春节活动老客户优惠" | + +--- + +## 5. 出参字段 + +### 5.1 统一端点出参 + +direction=REDUCE 时返回优惠记录(OrderDiscountRespVO),direction=ADD 时返回附加费记录(OrderSurchargeRespVO)。 + +**direction=REDUCE 出参(优惠记录)** + +| 字段 | 类型 | 说明 | 示例 | +|---|---|---|---| +| id | String | 优惠记录主键 | "8800001234567" | +| orderId | String | 订单 ID | "12345678901234" | +| discountType | String | 优惠类型(统一端点写入时存 itemCode 值) | "OLD_CUSTOMER" | +| itemCode | String | **新增** 优惠项目 itemCode(字典 order_discount_item value) | "OLD_CUSTOMER" | +| itemName | String | **新增** 优惠项目中文名(字典 label 快照) | "老客户回访" | +| discountName | String | 优惠描述(与 itemName 相同,为字典中文名快照) | "老客户回访" | +| discountAmount | String | 优惠金额(元) | "200.00" | +| sourceType | String | 来源类型(统一端点固定 MANUAL) | "MANUAL" | +| sourceRefId | String/null | 来源关联 ID | null | +| status | String | 记录状态(写入后固定 ACTIVE) | "ACTIVE" | +| operatorId | String | 操作人 ID(JWT 派生) | "30001" | +| operatorName | String | 操作人姓名快照 | "李定制师" | +| createdAt | String | 写入时间(ISO 8601) | "2026-06-22T16:08:32" | +| orderDiscountAmountAfter | String | 写入后订单优惠总额镜像(本订单所有 ACTIVE 优惠合计) | "200.00" | + +**direction=ADD 出参(附加费记录)** + +| 字段 | 类型 | 说明 | 示例 | +|---|---|---|---| +| id | String | 附加费记录主键 | "8800009876543" | +| orderId | String | 订单 ID | "12345678901234" | +| itemCode | String | **新增** 增项项目 itemCode(字典 order_surcharge_item value) | "ROOM_UPGRADE" | +| itemName | String | **新增** 增项项目中文名(字典 label 快照) | "升级房型" | +| surchargeName | String | 附加费描述(与 itemName 相同) | "升级房型" | +| surchargeAmount | String | 附加费金额(元) | "300.00" | +| sourceType | String | 来源类型(统一端点固定 MANUAL) | "MANUAL" | +| sourceRefId | String/null | 来源关联 ID | null | +| status | String | 记录状态(写入后固定 ACTIVE) | "ACTIVE" | +| operatorId | String | 操作人 ID | "30001" | +| operatorName | String | 操作人姓名快照 | "李定制师" | +| createdAt | String | 写入时间(ISO 8601) | "2026-06-22T16:12:00" | +| orderSurchargeAmountAfter | String | 写入后订单附加费总额镜像(本订单所有 ACTIVE 附加费合计) | "300.00" | + +### 5.2 优惠/附加费清单接口新增字段 + +接口:GET /v3/admin/order/{orderId}/discounts-surcharges(路径不变) + +**discounts[] 新增字段** + +| 字段 | 类型 | 说明 | 历史数据 | +|---|---|---|---| +| itemCode | String/null | 优惠项目 itemCode | null(早鸟、行程编辑等历史写入行) | +| itemName | String/null | 优惠项目中文名 | null(历史行兼容) | + +**surcharges[] 新增字段** + +| 字段 | 类型 | 说明 | 历史数据 | +|---|---|---|---| +| itemCode | String/null | 增项项目 itemCode | null(历史行兼容) | +| itemName | String/null | 增项项目中文名 | null(历史行兼容) | + +历史行(早鸟自动写入、行程编辑产生的记录)itemCode/itemName 返回 null,前端渲染时降级显示 discountName/surchargeName 字段。 + +--- + +## 6. 枚举 / 数据字典 + +### 6.1 AdjustmentDirection 枚举(入参 direction 字段) + +| 值 | 含义 | 落库位置 | +|---|---|---| +| REDUCE | 减项/优惠,订单总额减少 | order_discount 表 | +| ADD | 增项/附加费,订单总额增加 | order_surcharge 表 | + +### 6.2 order_discount_item 字典(dictType=order_discount_item) + +减项/优惠选项,前端调 GET /admin/dict/data/order_discount_item 动态渲染。 + +| value(itemCode,提交时传此值) | label(展示中文) | sort | +|---|---|---| +| OLD_CUSTOMER | 老客户回访 | 1 | +| DISTRIBUTION | 分销返点 | 2 | +| PEER_PRICE | 同行价 | 3 | +| FAMILY_PRICE | 亲友价 | 4 | +| COMPLAINT_COMP | 投诉补偿 | 5 | +| FESTIVAL | 生日节日 | 6 | +| GROUPON | 团购优惠 | 7 | +| OTHER | 其他 | 8 | + +### 6.3 order_surcharge_item 字典(dictType=order_surcharge_item) + +增项/费用选项,前端调 GET /admin/dict/data/order_surcharge_item 动态渲染。 + +| value(itemCode,提交时传此值) | label(展示中文) | sort | +|---|---|---| +| ROOM_UPGRADE | 升级房型 | 1 | +| ADD_ENTERTAINMENT | 加购娱乐项目 | 2 | +| ADD_VEHICLE | 增加用车 | 3 | +| EXTRA_PERSON | 超员补位 | 4 | +| ADD_ITINERARY | 行程加点 | 5 | +| OTHER | 其他 | 6 | + +--- + +## 7. 错误码 + +| 错误码 | 含义 | 触发场景 | +|---|---|---| +| 200 | 成功 | — | +| 581306 | ADJUSTMENT_ITEM_INVALID:itemCode 不在对应字典范围内 | direction=REDUCE 时 itemCode 不在 order_discount_item;direction=ADD 时 itemCode 不在 order_surcharge_item;或字典服务不可用 | +| 400 | 参数校验失败 | direction/itemCode 为空,amount 为空或 ≤ 0,remark 超 500 字 | +| 404(内部业务码) | 订单不存在 | orderId 无对应订单 | + +> 字典服务(user-service)不可用时,后端降级返回空选项集,任何 itemCode 均触发 581306 拒绝(保守策略)。 + +--- + +## 8. 示例 + +### 8.1 典型成功——减项(老客户优惠 200 元) + +请求: + + + +响应: + + + +### 8.2 典型成功——增项(升级房型 300 元) + +请求: + + + +响应: + + + +### 8.3 业务失败——itemCode 不合法(错误码 581306) + +请求: + + + +响应: + + + +> "VIP" 是旧端点历史枚举值,不在 order_discount_item 字典,统一端点拒绝。 + +--- + +## 9. 业务边界 + +**适用**: +- 订单处于任何状态均可操作(无订单状态限制) +- 一笔订单可叠加多条优惠/附加费记录,每条独立成行 + +**不适用**: +- 旧端点(/discounts、/surcharges)已废弃,前端不应再调用 + +**特殊边界**: +- 减项/增项金额均无上限校验,业务人员自行把握 +- 历史行(早鸟写入、行程编辑产生)itemCode/itemName 返回 null,前端渲染时降级显示 discountName/surchargeName +- 同一请求遭并发时(@Lock4j),后到的排队等待,不会重复写入 + +--- + +## 10. 修改前后对比 + +### 10.1 写入端点 + +| 场景 | 改造前 | 改造后 | +|---|---|---| +| 加优惠 | POST /{orderId}/discounts,discountName 自由文本 | POST /{orderId}/adjustment,direction=REDUCE + itemCode 字典选项 | +| 加附加费 | POST /{orderId}/surcharges,surchargeName 自由文本 | POST /{orderId}/adjustment,direction=ADD + itemCode 字典选项 | + +### 10.2 出参字段变化(清单接口) + +| 位置 | 改造前 | 改造后 | +|---|---|---| +| discounts[n] | 无 itemCode / itemName 字段 | 新增 itemCode、itemName(统一端点写入时有值,历史行 null) | +| surcharges[n] | 无 itemCode / itemName 字段 | 新增 itemCode、itemName(同上) | + +### 10.3 项目名来源变化 + +| 改造前 | 改造后 | +|---|---| +| discountName/surchargeName 由用户自由输入文本 | 由 itemCode 查字典 label 后端回填,存入 discountName/surchargeName 快照列 | + +--- + +## 11. 影响评估 / 回滚 + +**前端需同步操作**: + +1. 订单增减项弹窗的原因/项目 chips 改为动态调字典接口渲染(/admin/dict/data/order_discount_item 和 order_surcharge_item),不再硬编码 +2. 提交时调 /adjustment,传 direction + itemCode + amount + remark +3. 清单接口(discounts/surcharges 列表)新增 itemCode/itemName 字段,建议优先显示 itemName,null 时降级显示 discountName/surchargeName + +**破坏兼容性**:旧端点仍保留可调(非破坏性),但 Swagger 已隐藏,前端代码应切换。 + +**上线顺序建议**:user-service 须先于或同时于 order-v3 部署(字典须先存在);建议先上线后端,再上线前端。 + +**回滚方案**: +- 后端:重新部署旧版 hl-order-service-v3 + hl-user-service(旧端点仍在) +- 前端:切回调旧两端点即可 + +--- + +## 12. 注意事项 + +1. **user-service 先行**:order-v3 /adjustment 端点运行时调 user-service 拉字典,若字典不存在,任何 itemCode 均触发 581306 拒绝。两服务须同批或 user-service 先上。 +2. **itemCode 大小写敏感**:传 "OLD_CUSTOMER" 不能传 "old_customer"。 +3. **amount 传字符串**:防 JS 数值精度丢失,传 "200.00" 而非数字 200.00。 +4. **字典 value 不可随意修改**:value 已写入历史快照字段,运营改 value 会导致历史数据 itemCode 无法回查中文名(itemName 返回 null,discountName 仍有值可降级)。 +5. **多条叠加**:多次调 /adjustment 每次写一条新记录,清单接口可见全部明细,镜像值为当前全部 ACTIVE 之和。 + +--- + +## 13. 关联 / 联系人 + +- **Issue**: https://git.1814.love:8443/wx/HL/issues/4205 +- **PR**: https://git.1814.love:8443/wx/HL/pulls/4207 +- **Commit**: https://git.1814.love:8443/wx/HL/commit/3a3577aa9de39857d66c3e1811420ce175956f0a +- **后端负责人**: 腰苏图(yaosutu)