diff --git a/changelogs-v2/2026-10/04_8786_团期核单alloc-preview试算teamNo订正-修改接口-管理后台.md b/changelogs-v2/2026-10/04_8786_团期核单alloc-preview试算teamNo订正-修改接口-管理后台.md new file mode 100644 index 00000000..f13468aa --- /dev/null +++ b/changelogs-v2/2026-10/04_8786_团期核单alloc-preview试算teamNo订正-修改接口-管理后台.md @@ -0,0 +1,277 @@ +--- +schema: "hl-changelog/v2" +ticket: "8786" +title: "团期核单 alloc-preview 试算回执 splits.teamNo 由恒 null 订正为已填充真实团号" +consumer: "admin" +author: "yst" +change_type: "修改接口" +backend_status: "merged" +gateway_status: "not_required" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "订正 04_8714 §5.5 中「alloc-preview 试算回执的 splits.teamNo 本期恒 null 未填充」的标注:#8787 已给拆账试算接口出参补 teamNo 填充,与 tab splits / panel households / sub-orders 三处同源同口径;试算仍不落库。已合 dev-v3 未部署测试服。" +updated_at: "2026-10-04" +base: "dev-v3" +--- + +# order-v3 groupbatch:alloc-preview 拆账试算回执 splits.teamNo 订正为已填充(管理后台)—— 订正 04_8714 + +> ⚠️ **本文是订正 changelog**,修订《04_8714_团期核单重做8类tab明细+公摊拆账-修改接口-管理后台.md》§5.5 与 §12.6 中「alloc-preview 试算回执的 splits[].teamNo 本期恒 null」的描述。原文件保留不改动;两处描述不一致时**以本文为准**。接口路径、入参结构、出参字段清单均无变化,唯一变化是**试算回执 splits[].teamNo 从恒 null 变为已填充真实团号**。 + +## 1. 接口背景 + +04_8714 团期核单重做落地时,拆账试算接口 `POST …/settlement/alloc-preview` 的出参 `lines[].splits[].teamNo` 未填充(试算不查团号,恒 null),changelog 据此标注「本期恒 null,不要用它做展示」。 + +#8786(PR #8787)补上该缺口:试算回执现在与正式读端点一样填充真实团号,前端试算预览可直接展示 teamNo,与暂存回执、tab 读端点体验一致,无需再对试算场景做 teamNo 空值特判。 + +## 2. 变更清单 + +| # | 接口 | 变更点 | 类型 | +|---|------|--------|------| +| 1 | `POST /v3/admin/order/group-batch/{groupBatchId}/settlement/alloc-preview` | 出参 `lines[].splits[].teamNo` 由**恒 null** 改为**填充真实团号**(order_main.team_no,订金支付成功后生成;未付订金的订单仍为 null)。与 tab splits / panel households / sub-orders 三处**同源同口径** | ✨ 出参字段值变化 | + +路径前缀统一为 `/v3/admin/order/group-batch/{groupBatchId}/settlement`,下文用 `…` 代指。接口签名(路径 / 入参字段 / 出参字段清单)零变化,仅一个字段的值从 null 变为有值。 + +## 3. 接口详情 + +| 项 | 说明 | +|---|---| +| 服务 | hl-order-service-v3(端口 8086) | +| 路径 | `POST /v3/admin/order/group-batch/{groupBatchId}/settlement/alloc-preview` | +| 使用场景 | 管理后台 → 团期详情 → 核单 Tab:录入期拆账试算预览(不落库,前端编辑时实时预览分摊结果) | +| 认证 | 管理后台登录态(JWT);网关既有路由 `/v3/admin/**`,无新增网关配置 | +| 权限码 | `group-batch:audit:view`;缺码一律 589507 | +| 幂等性 | 纯查询型试算,**不写库**,天然幂等;无 expectedVersion | +| 限流 | 无特殊限流 | + +## 4. 接口入参 + +入参不变(GroupSettleAllocPreviewReqVO): + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| category | string | ✅ | 费用类别 8 值之一(HOTEL / TICKET / MEAL / VEHICLE / GUIDE / PHOTOGRAPHER / OTHER_INCOME / OTHER_EXPENSE) | +| lines | array | ✅ | 待试算明细行数组(≤500 行,结构同 04_8714 §4.2 `lines[]`);**无 expectedVersion**(纯试算不写库) | + +路径参数 `groupBatchId`(Path,Long)必填,团期 ID。 + +## 5. 出参字段 + +出参结构(GroupSettleAllocPreviewRespVO)不变: + +| 字段 | 类型 | 说明 | +|------|------|------| +| lines | array | 试算后的明细行(结构同 04_8714 §5.2 LineVO;confirmStatus 恒 UNCONFIRMED、lineId 原样回显或 null、sourceType 恒 MANUAL;splits 为重算预览)。**无任何写库** | + +`lines[].splits[]`(SplitVO)中本次变化的字段: + +| 字段 | 类型 | 说明 | +|------|------|------| +| orderId | string | 子订单 ID(不变) | +| **teamNo** | string 或 null | **团号**(order_main.team_no,订金支付成功后生成;未付订金的订单为 null)。⚠️ **本次订正点**:由原来恒 null 改为**已填充真实团号**,与 tab splits / panel households / sub-orders 三处**同源同口径**(服务端同一处批量取数:OrderService.selectTeamNoMapByIds,防 N+1) | +| householdName | string | 户名(客户姓名快照,不变) | +| ratio | string | 拆账比例(6 位小数,不变) | +| peopleCount | int 或 null | 该户参与人数快照(不变) | +| amount | string | 拆账金额(不变) | +| roundingBearer | boolean | 尾差承担户标记(不变) | +| note | string 或 null | 备注(不变) | + +## 6. 枚举 / 数据字典 + +本次无枚举 / 字典变化。 + +## 7. 错误码 + +本次无错误码变化。alloc-preview 相关错误码与 04_8714 §7 一致:589507(无权限)/ 589572(所选订单不属本团)/ 589750(拆账合计与行总额不一致)/ 589751(指定报名须至少选一户)/ 589753(入参非法,含负金额,见 04_8783 订正)。 + +## 8. 示例 + +### 8.1 典型:已付订金订单,试算回执 splits.teamNo 有值 + +请求: + + POST /v3/admin/order/group-batch/1934567890123456789/settlement/alloc-preview + Content-Type: application/json + +```json +{ + "category": "HOTEL", + "lines": [ + { + "lineId": null, + "allocMode": "SHARED", + "allocRule": "PER_HEAD_AVG", + "actualAmount": 4600.00, + "hotelName": "图嘎营地", + "roomTypeName": "蒙古包", + "roomCount": 5, + "unitPrice": 380.00 + } + ] +} +``` + +响应 200(张三、李四家均已付订金,teamNo 有值): + +```json +{ + "code": 0, + "data": { + "lines": [ + { + "lineId": null, + "confirmStatus": "UNCONFIRMED", + "allocMode": "SHARED", + "allocRule": "PER_HEAD_AVG", + "actualAmount": "4600.00", + "sourceType": "MANUAL", + "hotelName": "图嘎营地", + "roomTypeName": "蒙古包", + "roomCount": 5, + "unitPrice": "380.00", + "splits": [ + { "orderId": "1934567890123450001", "teamNo": "26-0001", "householdName": "张三", + "ratio": "0.300000", "peopleCount": 3, "amount": "1380.00", "roundingBearer": true, "note": null }, + { "orderId": "1934567890123450002", "teamNo": "26-0002", "householdName": "李四", + "ratio": "0.700000", "peopleCount": 7, "amount": "3220.00", "roundingBearer": false, "note": null } + ] + } + ] + } +} +``` + +**订正前**:同样请求 splits 里两处 teamNo 均为 `null`;**订正后**:填充真实团号,与 `GET …/settlement/hotels` 读端点返回的 splits.teamNo 完全一致。 + +### 8.2 边界:未付订金订单,splits.teamNo 仍为 null + +请求同上(团内王五家订单 1934567890123450003 未付订金): + +```json +{ + "category": "HOTEL", + "lines": [ + { + "lineId": null, + "allocMode": "SHARED", + "allocRule": "PER_HEAD_AVG", + "actualAmount": 1500.00, + "hotelName": "图嘎营地" + } + ] +} +``` + +响应 200: + +```json +{ + "code": 0, + "data": { + "lines": [ + { + "lineId": null, + "confirmStatus": "UNCONFIRMED", + "allocMode": "SHARED", + "allocRule": "PER_HEAD_AVG", + "actualAmount": "1500.00", + "sourceType": "MANUAL", + "hotelName": "图嘎营地", + "splits": [ + { "orderId": "1934567890123450001", "teamNo": "26-0001", "householdName": "张三", + "ratio": "0.300000", "peopleCount": 3, "amount": "450.00", "roundingBearer": true, "note": null }, + { "orderId": "1934567890123450003", "teamNo": null, "householdName": "王五", + "ratio": "0.700000", "peopleCount": 7, "amount": "1050.00", "roundingBearer": false, "note": null } + ] + } + ] + } +} +``` + +读法:**teamNo 可空语义不变**——团号在订金支付成功后才生成,未付订金的订单(王五家)teamNo 仍为 null,前端列表渲染的空值兜底**必须保留**。订正只影响「有团号但试算不回填」的场景,不影响「本来就没团号」的场景。 + +### 8.3 业务失败:拆账合计与行总额不一致(589750,既有行为不变,供对照) + +请求: + + POST /v3/admin/order/group-batch/1934567890123456789/settlement/alloc-preview + +```json +{ + "category": "HOTEL", + "lines": [ + { + "lineId": null, + "allocMode": "DESIGNATED", + "actualAmount": 3800.00, + "hotelName": "图嘎营地", + "splits": [ { "orderId": "1934567890123450001", "amount": 3000.00 } ] + } + ] +} +``` + +响应: + +```json +{ + "code": 589750, + "message": "拆账合计与明细行总额不一致(图嘎营地拆账合计 3000.00 / 明细总额 3800.00,差额 800.00),请核对后再提交" +} +``` + +试算与正式提交同一套拆账校验,错误码行为不变。 + +## 9. 业务边界 + +**适用**: +- 核单录入期的拆账试算预览(公摊 / 指定报名两种口径),试算回执可直接渲染含 teamNo 的拆账明细列表,与暂存回执、tab 读端点同一渲染组件。 + +**不适用**: +- 试算不落库——alloc-preview 的结果仅供前端预览,刷新页面 / 重新 GET tab 后不会保留;要持久化仍走 `PUT …/settlement/{tab}` 整 tab 暂存。 + +**特殊边界**: +- **teamNo 可空不变**:未付订金订单恒无团号,teamNo=null 是正常业务状态,不是数据缺失;前端空值兜底逻辑必须保留。 +- **同源同口径**:试算回执的 teamNo 与 tab splits / panel households / sub-orders 三处取自同一服务端批量查询(selectTeamNoMapByIds),任何场景下同一订单的 teamNo 展示一致,不会出现「试算有值、正式读出 null」或反之的口径分裂。 + +## 10. 修改前后对比 + +### 字段级对比 + +| 项 | 原来(04_8714 描述 / #8787 前实现) | 现在(#8787 订正后) | +|----|--------------------------------------|----------------------| +| alloc-preview 回执 `lines[].splits[].teamNo` | **恒 null**(试算不查团号) | **填充真实团号**(order_main.team_no);未付订金订单仍为 null | + +### 行为级对比 + +| 行为 | 原来 | 现在 | +|------|------|------| +| 试算预览渲染团号列 | 前端只能显示空 / 占位,或需自行调 sub-orders 接口补 teamNo | 直接用回执里的 teamNo 渲染,与正式读端点一致 | +| 试算落库 | 不落库(不变) | 不落库(不变) | +| 其余出参字段 | 不变 | 不变 | + +## 11. 影响评估 / 回滚 + +- **破坏兼容**:否。字段从 null 变有值,属纯增量信息;前端若按 04_8714 的建议「不要用试算回执 teamNo 做展示」而未消费该字段,则**零改动**。 +- **前端必须同步上线**:否(后端已合 dev-v3 未部署测试服)。 +- **workaround 清理点**:若前端此前为在试算预览里展示团号而自行调 `GET …/settlement/sub-orders` 或 panel 接口补 teamNo 的变通逻辑,现在可以删掉——试算回执自带 teamNo,直接渲染即可。 +- **回滚方案**:后端回滚 = revert PR #8787 即可(纯代码改动,无 DDL / 无数据迁移)。 + +## 12. 注意事项 + +1. **本文优先于 04_8714**:两份 changelog 对 alloc-preview 回执 splits[].teamNo 的描述不一致时,以本文为准(04_8714 §5.5「本期恒 null」与 §12.6「不要用它做展示」两条作废)。04_8714 的其余内容(接口清单 / 出入参结构 / 枚举字典 / 拆账规则)继续有效。 +2. **teamNo 空值兜底保留**:未付订金订单 teamNo 仍为 null,列表渲染的空值处理不能因为本次填充而删除。 +3. **三处同源**:tab splits / panel households / sub-orders / alloc-preview 四处的 teamNo 现在完全同源同口径,前端不需要对试算场景做任何特判。 +4. **试算仍不落库**:alloc-preview 是纯预览,任何试算结果都不会写入核单数据;持久化走 PUT 整 tab 暂存。 + +## 13. 关联 / 联系人 + +- Issue:https://git.1814.love/wx/HL/issues/8786 +- PR:https://git.1814.love/wx/HL/pulls/8787 +- Commit(squash merge):https://git.1814.love/wx/HL/commit/d20e6432128f +- 被订正的原 changelog:`changelogs-v2/2026-10/04_8714_团期核单重做8类tab明细+公摊拆账-修改接口-管理后台.md`(同仓同目录) +- 后端负责人:@yst