From ce5bac10e61e44a555ad5992811ad6f4da9268d8 Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Sat, 18 Jul 2026 16:53:16 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=A0=B8=E5=8D=95Step1?= =?UTF-8?q?=E4=BD=8F=E5=AE=BF=E5=AD=97=E6=AE=B5=E5=89=8D=E7=AB=AF=E5=8F=98?= =?UTF-8?q?=E6=9B=B4=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...核单Step1住宿成本字段-修改接口-管理后台.md | 359 ++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 changelogs-v2/2026-07/18_5043_核单Step1住宿成本字段-修改接口-管理后台.md diff --git a/changelogs-v2/2026-07/18_5043_核单Step1住宿成本字段-修改接口-管理后台.md b/changelogs-v2/2026-07/18_5043_核单Step1住宿成本字段-修改接口-管理后台.md new file mode 100644 index 0000000..140351f --- /dev/null +++ b/changelogs-v2/2026-07/18_5043_核单Step1住宿成本字段-修改接口-管理后台.md @@ -0,0 +1,359 @@ +# 【修改接口·管理后台】核单 Step1 住宿成本字段 (#5043) + +> **PR**: #5047 | **服务**: hl-order-service-v3 | **更新时间**: 2026-07-18 16:50 + +## 1. 接口背景 + +核单 Step1 住宿成本明细需要对齐原型里的酒店资源、房型资源、核算单价、来源和确认状态展示。现有接口保留原路径,在 `GET/PUT /v3/admin/order/{orderId}/settlement/step1` 上做兼容增强。 + +## 2. 变更清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 查询住宿核算明细 | GET | `/v3/admin/order/{orderId}/settlement/step1` | 修改接口 | `HotelItemVO` 出参新增 10 个字段 | +| 2 | 保存住宿核算明细 | PUT | `/v3/admin/order/{orderId}/settlement/step1` | 修改接口 | `HotelItemVO` 入参支持保存酒店/房型资源、单价、来源和确认状态字段 | + +## 3. 接口详情 + +### 3.1 查询住宿核算明细 + +- **使用场景**:进入核单 Step1 住宿页签时查询住宿成本明细。 +- **认证**:需要管理后台 JWT。 +- **幂等性**:幂等,只读查询。 +- **响应结构**:`data` 为 `HotelItemVO[]` 数组。 + +### 3.2 保存住宿核算明细 + +- **使用场景**:保存核单 Step1 住宿成本明细。 +- **认证**:需要管理后台 JWT。 +- **幂等性**:全量替换保存;同一份 `items` 重复提交后,以最后一次提交为准。 +- **请求体兼容**:推荐使用 `{ "items": [...] }`;历史数组 body `[...]` 仍兼容。 + +## 4. 接口入参 + +### 4.1 路径参数 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `orderId` | string | 是 | 订单 ID,长整型字符串 | + +### 4.2 PUT 请求体字段 + +| 字段 | 类型 | 必填 | 说明 | 校验规则 | +|------|------|------|------|----------| +| `items` | array | 是 | 住宿成本明细行数组,全量替换保存 | 不允许为 `null` | +| `items[].id` | string | 否 | 已存在行 ID;全量替换保存时可不传 | 长整型字符串 | +| `items[].hotelAssignmentId` | string/null | 否 | 配房 assignment ID;手工行可为 `null` | 长整型字符串或 `null` | +| `items[].hotelId` | string/null | 否 | 酒店资源 ID;本次新增 | 长整型字符串或 `null` | +| `items[].roomTypeId` | string/null | 否 | 房型资源 ID;本次新增 | 长整型字符串或 `null` | +| `items[].stayDate` | string | 是 | 入住日期 | `yyyy-MM-dd`,不能早于订单出发日 | +| `items[].hotelName` | string | 是 | 酒店名称 | 1-200 字符 | +| `items[].roomType` | string/null | 否 | 房型分类或旧展示字段 | 最大 64 字符 | +| `items[].roomTypeName` | string/null | 否 | 房型/规格名称;本次新增 | 最大 64 字符 | +| `items[].roomCount` | integer | 是 | 总间数 | 正整数 | +| `items[].unitPrice` | number/null | 否 | 核算单价,单位元/间夜;本次新增;不传时按 `actualCost / roomCount` 降级计算 | `>= 0` | +| `items[].plannedCost` | number | 是 | 计划成本,单位元 | `>= 0` | +| `items[].actualCost` | number | 是 | 实际成本,单位元 | `>= 0` | +| `items[].paymentMethod` | string | 否 | 付款方式;与 `settleType` 二选一 | `SIGNED` / `COMPANY_PAID` / `CASH_PAID` | +| `items[].paymentMethodName` | string | 否 | 付款方式中文名,仅展示字段;保存时可不传;本次新增 | 最大 32 字符 | +| `items[].settleType` | string | 否 | 配房结算类型;与 `paymentMethod` 二选一 | `cash` / `sign` / `company` | +| `items[].sourceType` | string | 否 | 来源类型;本次新增;不传时按是否有 `hotelAssignmentId` 派生 | `HOUSE_ASSIGNMENT` / `MANUAL` / `TEMPLATE` | +| `items[].sourceTypeName` | string | 否 | 来源类型中文名,仅展示字段;保存时可不传;本次新增 | 最大 32 字符 | +| `items[].sourceId` | string/null | 否 | 来源业务 ID;本次新增;配房来源默认等于 `hotelAssignmentId` | 长整型字符串或 `null` | +| `items[].settlementConfirmStatus` | string | 否 | 核单确认状态;本次新增;不传默认 `CONFIRMED` | `UNCONFIRMED` / `CONFIRMED` | +| `items[].settlementConfirmStatusName` | string | 否 | 核单确认状态中文名,仅展示字段;保存时可不传;本次新增 | 最大 32 字符 | +| `items[].remark` | string/null | 否 | 备注 | 最大 500 字符 | +| `items[].voucherUrls` | array | 否 | 凭证图片 URL 数组 | 字符串数组 | + +## 5. 出参 + +### 5.1 GET 响应字段:`HotelItemVO` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `id` | string/null | 核单住宿明细行 ID;首次派生未保存的行可为 `null` | +| `hotelAssignmentId` | string/null | 配房 assignment ID;手工行可为 `null` | +| `hotelId` | string/null | 酒店资源 ID;本次新增 | +| `roomTypeId` | string/null | 房型资源 ID;本次新增 | +| `stayDate` | string | 入住日期,`yyyy-MM-dd` | +| `hotelName` | string | 酒店名称 | +| `roomType` | string/null | 房型分类或旧展示字段 | +| `roomTypeName` | string/null | 房型/规格名称;本次新增 | +| `roomCount` | integer | 总间数 | +| `unitPrice` | number/null | 核算单价,单位元/间夜;本次新增 | +| `plannedCost` | number | 计划成本,单位元 | +| `actualCost` | number | 实际成本,单位元 | +| `paymentMethod` | string | 付款方式 | +| `paymentMethodName` | string/null | 付款方式中文名;本次新增 | +| `settleType` | string/null | 配房结算类型;保存草稿后可能为空 | +| `sourceType` | string | 来源类型;本次新增 | +| `sourceTypeName` | string/null | 来源类型中文名;本次新增 | +| `sourceId` | string/null | 来源业务 ID;本次新增 | +| `settlementConfirmStatus` | string | 核单确认状态;本次新增 | +| `settlementConfirmStatusName` | string/null | 核单确认状态中文名;本次新增 | +| `remark` | string/null | 备注 | +| `voucherUrls` | array | 凭证图片 URL 数组 | + +### 5.2 PUT 响应字段:`SettlementHotelSaveRespVO` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `addedIds` | string[] | 本次保存新增的核单住宿明细行 ID 列表 | +| `updatedIds` | string[] | 本次保存更新的核单住宿明细行 ID 列表;当前全量替换语义下通常为空数组 | +| `deletedIds` | string[] | 本次保存删除的核单住宿明细行 ID 列表;当前返回通常为空数组 | +| `totalActualCost` | string | 保存后 Step1 实际成本合计,单位元 | + +## 6. 枚举 / 数据字典 + +### 6.1 `paymentMethod` + +**所属字段**:`items[].paymentMethod`、`data[].paymentMethod` | **类型**:String | **必填**:否 + +| 值 | 中文 | 说明 | +|----|------|------| +| `SIGNED` | 签单 | 现场签单 | +| `COMPANY_PAID` | 公司付款 | 公司统一付款 | +| `CASH_PAID` | 现付 | 现场现金或线下现付 | + +### 6.2 `settleType` + +**所属字段**:`items[].settleType`、`data[].settleType` | **类型**:String | **必填**:否 + +| 值 | 中文 | 映射后的 `paymentMethod` | +|----|------|--------------------------| +| `cash` | 现付 | `CASH_PAID` | +| `sign` | 签单 | `SIGNED` | +| `company` | 公司付款 | `COMPANY_PAID` | + +### 6.3 `sourceType` + +**所属字段**:`items[].sourceType`、`data[].sourceType` | **类型**:String | **必填**:否 + +| 值 | 中文 | 说明 | +|----|------|------| +| `HOUSE_ASSIGNMENT` | 配房结果 | 来自房务配房结果 | +| `MANUAL` | 手工 | 核单手工补充住宿行 | +| `TEMPLATE` | 模板 | 模板来源住宿行,当前预留 | + +### 6.4 `settlementConfirmStatus` + +**所属字段**:`items[].settlementConfirmStatus`、`data[].settlementConfirmStatus` | **类型**:String | **必填**:否 + +| 值 | 中文 | 说明 | +|----|------|------| +| `UNCONFIRMED` | 未确认 | 核单住宿明细未确认 | +| `CONFIRMED` | 已确认 | 核单住宿明细已确认;不传时默认该值 | + +## 7. 错误码 + +| code | 含义 | 触发场景 | +|------|------|----------| +| `584002` | 当前核单状态不允许录住宿核单 | PUT 保存时,订单不是「待核单」或「核单中」 | +| `584008` | 订单缺出发日期,无法派生 dayNumber | PUT 保存时订单出发日期为空 | +| `584009` | `stayDate` 早于订单出发日期 | PUT 保存时日期越界 | +| `584062` | 临时行必须指定付款方式 | `paymentMethod` 和 `settleType` 都为空 | +| `584064` | 配房记录 `settleType` 字典值非法 | `settleType` 不是 `cash/sign/company` | +| `100001` | 参数非法 | 字段格式不符合校验,例如枚举值不在允许范围内、金额小于 0 | + +## 8. 示例 + +### 8.1 典型成功:GET 查询 + +**请求** + +```http +GET /v3/admin/order/2077233855281971202/settlement/step1 +Authorization: Bearer {token} +``` + +**响应** + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": [ + { + "id": "2077328317421187001", + "hotelAssignmentId": "2077233886282088401", + "hotelId": "50001", + "roomTypeId": "51001", + "stayDate": "2026-07-18", + "hotelName": "海拉尔海棠酒店", + "roomType": "STANDARD", + "roomTypeName": "精品标间", + "roomCount": 2, + "unitPrice": 440.00, + "plannedCost": 880.00, + "actualCost": 880.00, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现付", + "settleType": "cash", + "sourceType": "HOUSE_ASSIGNMENT", + "sourceTypeName": "配房结果", + "sourceId": "2077233886282088401", + "settlementConfirmStatus": "CONFIRMED", + "settlementConfirmStatusName": "已确认", + "remark": "已核对", + "voucherUrls": [] + } + ] +} +``` + +### 8.2 边界成功:PUT 保存手工住宿行 + +**请求** + +```http +PUT /v3/admin/order/2077233855281971202/settlement/step1 +Authorization: Bearer {token} +Content-Type: application/json +``` + +```json +{ + "items": [ + { + "hotelAssignmentId": null, + "hotelId": null, + "roomTypeId": null, + "stayDate": "2026-07-18", + "hotelName": "临时补充酒店", + "roomType": "STANDARD", + "roomTypeName": "标准间", + "roomCount": 1, + "unitPrice": 300.00, + "plannedCost": 300.00, + "actualCost": 300.00, + "paymentMethod": "COMPANY_PAID", + "sourceType": "MANUAL", + "sourceId": null, + "settlementConfirmStatus": "UNCONFIRMED", + "voucherUrls": [], + "remark": "核单临时补充" + } + ] +} +``` + +**响应** + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "addedIds": ["2078398065684692001"], + "updatedIds": [], + "deletedIds": [], + "totalActualCost": "300.00" + } +} +``` + +### 8.3 业务失败:缺付款方式 + +**请求** + +```http +PUT /v3/admin/order/2077233855281971202/settlement/step1 +Authorization: Bearer {token} +Content-Type: application/json +``` + +```json +{ + "items": [ + { + "hotelAssignmentId": null, + "stayDate": "2026-07-18", + "hotelName": "临时补充酒店", + "roomType": "STANDARD", + "roomCount": 1, + "plannedCost": 300.00, + "actualCost": 300.00 + } + ] +} +``` + +**响应** + +```json +{ + "code": 584062, + "message": "临时行(无配房关联)必须指定 paymentMethod", + "data": null, + "success": false +} +``` + +## 9. 业务边界 + +- `PUT` 是全量替换保存;前端保存时应提交页面当前完整明细列表。 +- `hotelAssignmentId` 有值时通常表示配房来源;`hotelAssignmentId` 为空时通常表示手工补充行。 +- `sourceType` 不传时,`hotelAssignmentId` 有值默认 `HOUSE_ASSIGNMENT`,否则默认 `MANUAL`。 +- `sourceId` 不传且 `sourceType=HOUSE_ASSIGNMENT` 时,默认使用 `hotelAssignmentId`;其他来源可为 `null`。 +- `unitPrice` 不传且 `roomCount > 0`、`actualCost` 有值时,返回时会按 `actualCost / roomCount` 保留 2 位小数。 +- `settlementConfirmStatus` 不传时默认 `CONFIRMED`。 +- `paymentMethod` 与 `settleType` 二选一;`paymentMethod` 优先,`settleType` 会映射成 `paymentMethod`。 +- 订单核单状态必须是「待核单」或「核单中」才允许保存 Step1。 + +## 10. 修改前后对比 + +### 10.1 字段级对比 + +| 字段 | 修改前 | 修改后 | +|------|--------|--------| +| `hotelId` | 无 | 新增,酒店资源 ID | +| `roomTypeId` | 无 | 新增,房型资源 ID | +| `roomTypeName` | 无 | 新增,房型/规格名称 | +| `unitPrice` | 无 | 新增,核算单价 | +| `paymentMethodName` | 无 | 新增,付款方式中文名 | +| `sourceType` | 无 | 新增,来源类型 | +| `sourceTypeName` | 无 | 新增,来源类型中文名 | +| `sourceId` | 无 | 新增,来源业务 ID | +| `settlementConfirmStatus` | 无 | 新增,核单确认状态 | +| `settlementConfirmStatusName` | 无 | 新增,核单确认状态中文名 | + +### 10.2 行为级对比 + +| 行为 | 修改前 | 修改后 | +|------|--------|--------| +| 住宿来源展示 | 只能通过 `hotelAssignmentId` 粗略判断 | 返回 `sourceType/sourceTypeName/sourceId` | +| 单价展示 | 前端只能根据总价和间数自行推算 | 返回 `unitPrice`,缺失时后端按实际成本和间数降级计算 | +| 确认状态展示 | 无独立字段 | 返回 `settlementConfirmStatus/settlementConfirmStatusName` | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:否。新增字段为兼容性新增,旧字段保留。 +- **前端是否必须同步上线**:否。旧页面可继续按原字段展示;需要原型新增列时读取新增字段。 +- **影响已有数据**:历史行新增字段可能为 `null`,前端需要保留空值展示逻辑。 + +### 11.2 回滚方案 + +- 回滚接口代码后,前端不要再依赖本次新增字段。 +- 如果页面已使用新增列,回滚期间新增列需要降级为空态展示。 + +## 12. 注意事项 + +- `paymentMethodName`、`sourceTypeName`、`settlementConfirmStatusName` 都是展示字段,保存时可不传。 +- `roomType` 是旧字段,`roomTypeName` 是本次新增的房型/规格名称;两者可能同时存在。 +- `settlementConfirmStatus` 是核单明细确认状态,与房务配房确认状态不是同一个字段。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#5043](https://git.1814.love:8443/wx/HL/issues/5043) +- **PR**: [#5047](https://git.1814.love:8443/wx/HL/pulls/5047) +- **Merge commit**: [0a9e83b39](https://git.1814.love:8443/wx/HL/commit/0a9e83b390d135c05b43bc18afe1b190329bf85c) + +### 13.2 联系人 + +- **后端负责人**: @yaosutu