changelog-filename-gate / validate (push) Failing after 2s
新增 30_8597 覆盖两个端点:
- PUT /v3/admin/order/house-console/room-transfers/{id}/deadline
- GET /v3/admin/order/house-console/audit
同时就地订正已交付的 30_8491(4 行 / 3 处):原文写「cancelDays 传 null 时
cancelCutoff / remindDays 一并清空」,与源码相反。HouseRoomTransferManager#doUpdateDeadline
对 cancelDays == null 的分支是「cutoff / remind 沿用行上原值」——两列 NOT NULL,
传 null 会被 Mapper 守卫当失败返 0、进而被误报成并发修改(正是 #8597 的根因)。
30_8491 自己第 1847 行记录的实测读数也是「cancelCutoff 保留」,即该文件内部自相矛盾。
订正不是措辞问题:前端若按原文写 `cancelCutoff === null` 去判「有没有设期限」,
那个判断恒为 false。订正后同时写明正确判据是看 cancelDays 或 risk === "NO_DEADLINE"。
两文件 validate-changelog-frontmatter.mjs --files 全绿(校验 2 个对象,EXIT=0)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1890 行
85 KiB
Markdown
1890 行
85 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "8491"
|
||
title: "房务控制台新增接口:批量认领、改配取消确认、控房表、退团房转房、异常检查、住宿模板、团期转交"
|
||
consumer: "admin"
|
||
author: "wx(GIT)"
|
||
change_type: "新增接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "not_required"
|
||
frontend_status: "pending"
|
||
frontend_owner: ""
|
||
frontend_ref: ""
|
||
target_release: ""
|
||
verified_at: ""
|
||
status_note: ""
|
||
updated_at: "2026-09-30"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 房务控制台: 新增 17 个管理端接口(批量认领 / 改配取消确认 / 控房表 / 退团房转房 / 异常检查 / 住宿模板 / 团期转交)
|
||
|
||
> **存放目录**: 二期 → `changelogs-v2/2026-09/`
|
||
>
|
||
> **服务**: hl-order-service-v3
|
||
> **Issue**: #8491
|
||
> **日期**: 2026-09-29
|
||
> **影响范围**: 管理后台新菜单「房务控制台」(`/housekeeper/console`)及团期抢单池的「团期转交」
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写)
|
||
|
||
- 新增菜单「房务控制台」,路由 `/housekeeper/console`;原菜单「待处理」(`/housekeeper/todos`)已删除。
|
||
- 房务通知里的跳转链接改指控制台:退团房为 `/housekeeper/console?tab=transfer&id={transferId}`,团期为 `/housekeeper/console?groupBatchId={groupBatchId}`。
|
||
- 本文 17 个接口全部为新增,路径前缀 `/v3/admin/order/house-console/**`(16 个)与 `/v3/admin/order/grab-pool/**`(团期转交 1 个)。
|
||
- 房务人员名单取不到时,「团期转交」一律拒绝并返回 **808343**「房务人员名单暂不可用,请稍后重试」,不会像超管「整团接管」那样降级放行。
|
||
- 住宿模板的改 / 删只允许创建人本人或超管,否则返回 **808352**「只能修改或删除自己创建的模板」。
|
||
- 控房表是否可调房量由响应字段 `stockTrackingEnabled` 决定(对应 resource 全局开关 `hotel.stock.enabled`),前端按该字段控制「调房量」入口。
|
||
|
||
---
|
||
|
||
## 一、背景(选填)
|
||
|
||
#8491 把房务的日常操作收拢到一个控制台:批量认领待认领的常规单需求与团期;改配(换酒店 / 减间数)后对原酒店做取消确认;按酒店 × 房型 × 入住夜查看、调整控房总数与价格并导出;处理退团释放出来的房间(设免费取消期限、转给其他订单或团期、或向酒店取消);一屏查看数据不一致与未办完的事项;按「逐晚城市 / 酒店 / 房型」保存住宿模板复用;团期持有人把整团转交给其他房务。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|------|------|------|----------|------|
|
||
| 1 | 改配原订取消确认 | PUT | `/v3/admin/order/house-console/changes/{changeId}/cancel-confirm` | 新增 | 上传原酒店取消凭证,HELD 转 CANCEL_CONFIRMED |
|
||
| 2 | 批量认领 | POST | `/v3/admin/order/house-console/claims/batch` | 新增 | 常规单需求与团期一次最多 50 条,逐条返回结果 |
|
||
| 3 | 控房表查询 | GET | `/v3/admin/order/house-console/room-control` | 新增 | 酒店 × 房型 × 入住夜的总数、已用、剩余、价格与团组用房 |
|
||
| 4 | 控房表调房量 | PUT | `/v3/admin/order/house-console/room-control/stock` | 新增 | 改单格控房总数,带已用间数 CAS |
|
||
| 5 | 控房表调价 | PUT | `/v3/admin/order/house-console/room-control/price` | 新增 | 按日期区间改控房价 / 结算价 |
|
||
| 6 | 控房表导出 | GET | `/v3/admin/order/house-console/room-control/export` | 新增 | xlsx,两个工作表,不含价格 |
|
||
| 7 | 退团房分页 | GET | `/v3/admin/order/house-console/room-transfers` | 新增 | 退团释放房间列表与待处理汇总 |
|
||
| 8 | 设置退团房免费取消期限 | PUT | `/v3/admin/order/house-console/room-transfers/{id}/deadline` | 新增 | 设 / 清免费取消期限与提醒天数 |
|
||
| 9 | 退团房转入候选 | GET | `/v3/admin/order/house-console/room-transfers/{id}/candidates` | 新增 | 同城同晚的订单 / 团期候选及不可转入原因 |
|
||
| 10 | 退团房转房 | POST | `/v3/admin/order/house-console/room-transfers/{id}/transfer` | 新增 | 把房间转给订单需求或团期 |
|
||
| 11 | 退团房向酒店取消 | POST | `/v3/admin/order/house-console/room-transfers/{id}/cancel-hotel` | 新增 | 上传取消凭证,行置为 CANCELLED |
|
||
| 12 | 房务异常检查 | GET | `/v3/admin/order/house-console/audit` | 新增 | issues 数据不一致 + tasks 待办 |
|
||
| 13 | 住宿模板列表 | GET | `/v3/admin/order/house-console/stay-templates` | 新增 | 全部创建人的模板,按创建时间倒序 |
|
||
| 14 | 住宿模板详情 | GET | `/v3/admin/order/house-console/stay-templates/{id}` | 新增 | 逐晚城市 / 酒店 / 房型明细 |
|
||
| 15 | 住宿模板保存 | POST | `/v3/admin/order/house-console/stay-templates` | 新增 | id 为空新建,否则修改 |
|
||
| 16 | 住宿模板删除 | DELETE | `/v3/admin/order/house-console/stay-templates/{id}` | 新增 | 软删,仅创建人或超管 |
|
||
| 17 | 团期转交 | POST | `/v3/admin/order/grab-pool/group-batches/{groupBatchId}/transfer` | 新增 | 团期持有人或超管把整团交给其他房务 |
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
本节示例 JSON 的字段名、类型、错误码与文案逐一取自源码;ID、日期、金额、姓名等取值为说明用的构造值。所有接口统一返回 `Result` 信封(`code` / `message` / `data` / `traceId` / `success`),示例省略 `traceId`;业务失败与入参校验失败均为 HTTP 200,靠 `code` 区分。ID 与金额字段序列化为字符串。
|
||
|
||
### 1. 改配原订取消确认 `PUT /v3/admin/order/house-console/changes/{changeId}/cancel-confirm`
|
||
|
||
**VO**: `HouseAssignmentChangeConfirmReqVO → Result<Void>`
|
||
|
||
#### 使用场景
|
||
|
||
订单房务详情(`GET /admin/house/orders/{orderId}`)的 `changes[]` 里 `oldStatus=HELD` 的改配记录,房务向原酒店取消后,在该记录上点「确认取消」并上传取消凭证。`changeId` 取自 `changes[].changeId`。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| changeId | Path | Long | ✅ | - | 改配记录 ID |
|
||
| cancelProofFileIds | Body | List<Long> | ✅ | 1~9 个,元素非空 | 取消凭证文件 ID |
|
||
| cancelFee | Body | BigDecimal | ❌ | ≥0,最多 2 位小数 | 取消费用(元) |
|
||
| remark | Body | String | ❌ | ≤200 字 | 备注 |
|
||
|
||
#### 出参 `Result<Void>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data | null | 成功无返回体,前端成功后重新拉取订单房务详情 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"cancelProofFileIds": [1930000000000000501],
|
||
"cancelFee": "120.00",
|
||
"remark": "酒店已电话确认取消"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": null,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
本接口无列表数据,成功时 `data` 恒为 `null`。无降级分支:任何失败都返回非 200 的 `code`,记录不变。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808333,
|
||
"message": "原订已确认取消",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
其余错误:
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | 请上传取消凭证 / 取消凭证 1~9 个 / 凭证文件 ID 不能为空 / 取消费用不能为负 / 取消费用最多 2 位小数 / 备注不能超过 200 字 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808332 | 变更记录不存在 | changeId 不存在 |
|
||
| 808116 | 订单未抢单, 请先抢单再配房 | 该需求无人持有 |
|
||
| 808110 | 需求不属于当前用户 | 当前登录人不是需求持有人(超管同样拒绝) |
|
||
| 808333 | 原订已确认取消 | 记录已不是 HELD,或并发确认时落后的一方 |
|
||
| 100503 | 资源被占用,请稍后重试 | 同一 changeId 正在被另一请求处理 |
|
||
|
||
#### 业务边界
|
||
|
||
- 只有该需求的当前持有人能确认;超管**不豁免**,超管要确认须先把需求「指派」或「转单」给自己。
|
||
- 只能从 `HELD` 确认一次,成功后 `oldStatus=CANCEL_CONFIRMED`;重复确认返回 808333。
|
||
- 成功时覆盖写该记录的取消费用、凭证与备注,操作人记为确认人;不改配房行,不发通知。
|
||
- 同一 `changeId` 在服务端串行处理(锁 30 秒),并发请求其一返回 100503 或 808333。
|
||
|
||
### 2. 批量认领 `POST /v3/admin/order/house-console/claims/batch`
|
||
|
||
**VO**: `HouseConsoleBatchClaimReqVO → HouseConsoleBatchClaimRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
控房台待认领列表勾选多条常规单需求和 / 或团期,一次提交认领。结果逐条返回,前端按 `items[]` 标出成功与失败原因。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| requirementIds | Body | List<Long> | ❌ | 元素非空 | 常规单住宿需求 ID 列表 |
|
||
| groupBatchIds | Body | List<Long> | ❌ | 元素非空 | 团期 ID 列表 |
|
||
| (跨字段) | Body | - | ✅ | 两列表各自去重后合计 1~50 条 | 违反时返回 400「请选择 1~50 条待认领记录」 |
|
||
|
||
#### 出参 `Result<HouseConsoleBatchClaimRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| successCount | Integer | 成功条数 |
|
||
| failCount | Integer | 失败条数 |
|
||
| items | List<Item> | 逐项结果,顺序:先需求后团期,各自按提交顺序去重 |
|
||
| items[].targetType | String | REQUIREMENT 常规单住宿需求 / GROUP_BATCH 团期 |
|
||
| items[].targetId | Long(String) | 需求 ID 或团期 ID |
|
||
| items[].orderId | Long(String) | 订单 ID,仅需求项有;团期项为空 |
|
||
| items[].teamNo | String | 团号;无团号为空 |
|
||
| items[].batchNo | String | 团期批次号,仅团期项有 |
|
||
| items[].success | Boolean | 是否认领成功 |
|
||
| items[].errorCode | Integer | 失败错误码;成功为空,系统异常也为空 |
|
||
| items[].errorMessage | String | 失败原因;成功为空 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"requirementIds": [1840000000000000001, 1840000000000000011],
|
||
"groupBatchIds": [1840000000000000002]
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"successCount": 2,
|
||
"failCount": 1,
|
||
"items": [
|
||
{ "targetType": "REQUIREMENT", "targetId": "1840000000000000001", "orderId": "1840000000000000003", "teamNo": "HL20261002A", "batchNo": null, "success": true, "errorCode": null, "errorMessage": null },
|
||
{ "targetType": "REQUIREMENT", "targetId": "1840000000000000011", "orderId": "1840000000000000013", "teamNo": "HL20261003B", "batchNo": null, "success": false, "errorCode": 808001, "errorMessage": "该需求已被其他房务认领或状态已变化,请刷新后重试" },
|
||
{ "targetType": "GROUP_BATCH", "targetId": "1840000000000000002", "orderId": null, "teamNo": null, "batchNo": "GB20261001-01", "success": true, "errorCode": null, "errorMessage": null }
|
||
]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
- 订单号 / 团号 / 批次号等展示字段是一次批量查询补齐的;该查询失败时这些字段为空,认领结果不受影响。
|
||
- 单条出现非业务异常时该条 `success=false`、`errorCode=null`、`errorMessage="系统繁忙,请稍后重试"`,其余条目照常处理。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "请选择 1~50 条待认领记录",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
整体失败:
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | 请选择 1~50 条待认领记录 / 需求 ID 不能为空 / 团期 ID 不能为空 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 100502 | 批量认领处理中,请勿重复提交 | 同一批 3 秒内重复提交 |
|
||
|
||
逐项失败(出现在 `items[].errorCode`)常见值:808001「该需求已被其他房务认领或状态已变化,请刷新后重试」、808002「需求已不存在」、808003「该需求已由您抢到,请勿重复抢单」、808004「需求所在订单已取消」,团期项沿用整团认领的既有错误码。
|
||
|
||
#### 业务边界
|
||
|
||
- 每一条独立认领、独立成败,不整体回滚;HTTP 与 `code` 为 200 只代表批次处理完,逐项看 `items[].success`。
|
||
- 需求项走常规单抢单、团期项走整团认领,校验与单条认领一致。
|
||
- 同一 ID 重复提交只处理一次;`successCount + failCount` 等于去重后的条数。
|
||
|
||
### 3. 控房表查询 `GET /v3/admin/order/house-console/room-control`
|
||
|
||
**VO**: `HouseRoomControlListReqVO → HouseRoomControlRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
控制台「控房表」页签加载:按城市或酒店、入住夜区间列出每个酒店 × 房型 × 入住夜的控房总数、已用、剩余、已分配、价格,以及每格的团组用房明细。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| cityCode | Query | String | ❌ | ≤32 | 城市**编码**(如 `hailar`);与 hotelId 都不传则查全部酒店 |
|
||
| hotelId | Query | Long | ❌ | - | 传了只查这一家,优先于 cityCode |
|
||
| dateFrom | Query | LocalDate | ✅ | yyyy-MM-dd | 入住夜起(含) |
|
||
| dateTo | Query | LocalDate | ✅ | yyyy-MM-dd;跨度 ≤62 天(含首尾) | 入住夜止(含) |
|
||
| onlyWithRemain | Query | Boolean | ❌ | - | true 时只返回剩余为不限或 >0 的行 |
|
||
|
||
#### 出参 `Result<HouseRoomControlRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| stockTrackingEnabled | Boolean | resource 全局库存追踪开关(`hotel.stock.enabled`);false 时行照常返回,但调房量会被拒(808312) |
|
||
| rows | List<HouseRoomControlRowRespVO> | 控房行,按(酒店, 入住夜, 房型)升序 |
|
||
| rows[].hotelId | Long(String) | 酒店 ID |
|
||
| rows[].hotelName | String | 酒店名称 |
|
||
| rows[].cityName | String | 城市中文名 |
|
||
| rows[].roomTypeId | Long(String) | 房型 ID |
|
||
| rows[].roomTypeName | String | 房型名称 |
|
||
| rows[].stayDate | LocalDate | 入住夜 |
|
||
| rows[].totalRooms | Integer | 控房总数 = 剩余 + 已用;null 表示不限量 |
|
||
| rows[].usedRooms | Integer | 已用(resource 当前值) |
|
||
| rows[].remainRooms | Integer | 剩余;null 表示不限量 |
|
||
| rows[].assignedRooms | Integer | 已分配:扣库存的配房行 + 已确认扣库存的团期计划行的间数合计 |
|
||
| rows[].protocolPrice | BigDecimal(String) | 控房价 |
|
||
| rows[].settlementPrice | BigDecimal(String) | 结算价 |
|
||
| rows[].usages | List<Usage> | 团组用房明细 |
|
||
| rows[].usages[].orderId | Long(String) | 订单 ID;团期计划行为 null |
|
||
| rows[].usages[].teamNo | String | 团号;团期计划行或无团号为 null |
|
||
| rows[].usages[].batchNo | String | 团期批次号;散客订单为 null |
|
||
| rows[].usages[].roomCount | Integer | 用房间数 |
|
||
| rows[].usages[].roomSource | String | 恒为 STOCK(本表只列扣库存行) |
|
||
| rows[].usages[].roomSourceLabel | String | 控房 |
|
||
| rows[].usages[].confirmStatusLabel | String | 确认状态标签 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/room-control?cityCode=hailar&dateFrom=2026-10-01&dateTo=2026-10-07&onlyWithRemain=false
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"stockTrackingEnabled": true,
|
||
"rows": [
|
||
{
|
||
"hotelId": "100001",
|
||
"hotelName": "海拉尔草原酒店",
|
||
"cityName": "海拉尔",
|
||
"roomTypeId": "300001",
|
||
"roomTypeName": "豪华双床房",
|
||
"stayDate": "2026-10-01",
|
||
"totalRooms": 12,
|
||
"usedRooms": 5,
|
||
"remainRooms": 7,
|
||
"assignedRooms": 5,
|
||
"protocolPrice": "320.00",
|
||
"settlementPrice": "300.00",
|
||
"usages": [
|
||
{ "orderId": "1930000000000000001", "teamNo": "HL20261001A", "batchNo": null, "roomCount": 3, "roomSource": "STOCK", "roomSourceLabel": "控房", "confirmStatusLabel": "已确认" },
|
||
{ "orderId": null, "teamNo": null, "batchNo": "GB20261001", "roomCount": 2, "roomSource": "STOCK", "roomSourceLabel": "控房", "confirmStatusLabel": "已确认" }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
```json
|
||
{ "code": 200, "message": "成功", "data": { "stockTrackingEnabled": true, "rows": [] }, "success": true }
|
||
```
|
||
|
||
条件内无控房行时 `rows` 为空数组。resource 服务不可用时不降级为空表,返回 808900。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808313,
|
||
"message": "日期跨度不能超过 62 天",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | dateFrom 不能为空 / dateTo 不能为空 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808313 | 日期跨度不能超过 62 天 | dateFrom 晚于 dateTo,或跨度超 62 天 |
|
||
| 808330 | 查询范围过大,请缩小酒店或日期范围 | 结果超过 2000 行 |
|
||
| 808900 | 资源服务暂不可用,请稍后重试 | resource 调用失败 |
|
||
|
||
#### 业务边界
|
||
|
||
- 本接口的 `cityCode` 是城市**编码**;退团房列表(接口 7)的 `cityCode` 是城市**中文名**,两处不要混用。
|
||
- `stockTrackingEnabled=false` 时行照常返回,已用 / 剩余取 resource 当前值,但此时配房不扣减库存,已用 / 剩余不随配房变化;前端应据此隐藏或禁用「调房量」。
|
||
- 纯读接口,无幂等要求,不写任何数据。
|
||
|
||
### 4. 控房表调房量 `PUT /v3/admin/order/house-console/room-control/stock`
|
||
|
||
**VO**: `HouseRoomControlStockSaveReqVO → HouseRoomControlRowRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
控房表某一格(酒店 × 房型 × 入住夜)点「调房量」,修改控房总数。提交时带上页面读到的已用间数做并发校验。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| hotelId | Body | Long | ✅ | - | 酒店 ID |
|
||
| roomTypeId | Body | Long | ✅ | - | 房型 ID |
|
||
| stayDate | Body | LocalDate | ✅ | yyyy-MM-dd | 入住夜 |
|
||
| totalRooms | Body | Integer | ✅ | 0~500 | 新的控房总数 |
|
||
| expectedUsedRooms | Body | Integer | ✅ | ≥0 | 页面读到的已用间数(CAS 期望值) |
|
||
|
||
#### 出参 `Result<HouseRoomControlRowRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| hotelId / hotelName / cityName | Long(String) / String / String | 酒店与城市 |
|
||
| roomTypeId / roomTypeName | Long(String) / String | 房型 |
|
||
| stayDate | LocalDate | 入住夜 |
|
||
| totalRooms | Integer | 调整后的控房总数;null 表示不限量 |
|
||
| usedRooms | Integer | 已用 |
|
||
| remainRooms | Integer | 剩余;null 表示不限量 |
|
||
| assignedRooms | Integer | 已分配间数 |
|
||
| protocolPrice / settlementPrice | BigDecimal(String) | 控房价 / 结算价 |
|
||
| usages | List<Usage> | 团组用房明细,字段同接口 3 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"hotelId": 100001,
|
||
"roomTypeId": 300001,
|
||
"stayDate": "2026-10-01",
|
||
"totalRooms": 15,
|
||
"expectedUsedRooms": 5
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"hotelId": "100001", "hotelName": "海拉尔草原酒店", "cityName": "海拉尔",
|
||
"roomTypeId": "300001", "roomTypeName": "豪华双床房", "stayDate": "2026-10-01",
|
||
"totalRooms": 15, "usedRooms": 5, "remainRooms": 10, "assignedRooms": 5,
|
||
"protocolPrice": "320.00", "settlementPrice": "300.00",
|
||
"usages": [
|
||
{ "orderId": "1930000000000000001", "teamNo": "HL20261001A", "batchNo": null, "roomCount": 3, "roomSource": "STOCK", "roomSourceLabel": "控房", "confirmStatusLabel": "已确认" }
|
||
]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
写入成功后服务端会重读这一行;重读失败时用写入结果拼出返回行,此时 `assignedRooms=0`、`usages=[]`,前端可再调接口 3 刷新整表。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808311,
|
||
"message": "已占用数已变化,请刷新后重试",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | hotelId 不能为空 / roomTypeId 不能为空 / stayDate 不能为空 / totalRooms 不能为空 / totalRooms 不能小于 0 / totalRooms 不能大于 500 / expectedUsedRooms 不能为空 / expectedUsedRooms 不能小于 0 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808312 | 库存追踪未开启,暂不能调整房量 | resource 全局开关关闭 |
|
||
| 808310 | 总房量不能小于已占用 {0} 间 | totalRooms 小于当前已用,{0} 为已用间数 |
|
||
| 808311 | 已占用数已变化,请刷新后重试 | expectedUsedRooms 与服务端当前已用不一致 |
|
||
| 100502 | 调房量处理中,请勿重复提交 | 同一操作人 3 秒内重复提交同一格 |
|
||
| 808900 | 资源服务暂不可用,请稍后重试 | resource 调用失败 |
|
||
|
||
#### 业务边界
|
||
|
||
- 写守卫只要求房务角色,不校验认领人:控房是酒店级资源,不属于任何订单。
|
||
- 失败时控房总数不变。808311 后前端应重新查询该格再提交。
|
||
- 幂等键带操作人,两个房务 3 秒内改同一格不会被互判为重复提交,由 CAS 决定先后。
|
||
|
||
### 5. 控房表调价 `PUT /v3/admin/order/house-console/room-control/price`
|
||
|
||
**VO**: `HouseRoomControlPriceSaveReqVO → Result<Integer>`
|
||
|
||
#### 使用场景
|
||
|
||
控房表选定酒店 × 房型,对一段入住夜批量修改控房价和 / 或结算价。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| hotelId | Body | Long | ✅ | - | 酒店 ID |
|
||
| roomTypeId | Body | Long | ✅ | - | 房型 ID |
|
||
| dateFrom | Body | LocalDate | ✅ | yyyy-MM-dd | 入住夜起(含) |
|
||
| dateTo | Body | LocalDate | ✅ | yyyy-MM-dd;跨度 ≤62 天 | 入住夜止(含) |
|
||
| protocolPrice | Body | BigDecimal | ❌ | >0,最多 2 位小数 | 控房价;不传则不改 |
|
||
| settlementPrice | Body | BigDecimal | ❌ | >0,最多 2 位小数 | 结算价;不传则不改 |
|
||
|
||
#### 出参 `Result<Integer>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data | Integer | 受影响的天数(更新已有价格日历行 + 补建缺失日历行) |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"hotelId": 100001,
|
||
"roomTypeId": 300001,
|
||
"dateFrom": "2026-10-01",
|
||
"dateTo": "2026-10-07",
|
||
"protocolPrice": "320.00",
|
||
"settlementPrice": "300.00"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": 7,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
本接口无列表型数据;区间内缺失的价格日历行会被补建并计入 `data`。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808314,
|
||
"message": "协议价与结算价至少填写一项",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | hotelId 不能为空 / roomTypeId 不能为空 / dateFrom 不能为空 / dateTo 不能为空 / protocolPrice 必须大于 0 / protocolPrice 最多 2 位小数 / settlementPrice 必须大于 0 / settlementPrice 最多 2 位小数 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808313 | 日期跨度不能超过 62 天 | dateFrom 晚于 dateTo 或跨度超 62 天 |
|
||
| 808314 | 协议价与结算价至少填写一项 | 两个价格都没传 |
|
||
| 100502 | 调价处理中,请勿重复提交 | 3 秒内重复提交 |
|
||
| 808900 | 资源服务暂不可用,请稍后重试 | resource 调用失败 |
|
||
|
||
#### 业务边界
|
||
|
||
- 只影响之后新生成的配房;已有配房行保存的是配房当时的价格快照,不回写。
|
||
- 不传的价格字段保持原值,不会被清空。
|
||
- 一次调用按区间整体写入,不需要前端逐日调用。
|
||
|
||
### 6. 控房表导出 `GET /v3/admin/order/house-console/room-control/export`
|
||
|
||
**VO**: `HouseRoomControlListReqVO → xlsx 文件流`
|
||
|
||
#### 使用场景
|
||
|
||
控房表页签点「导出」,按与查询相同的条件下载 Excel。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| cityCode | Query | String | ❌ | ≤32 | 城市编码;与 hotelId 都不传则导出全部酒店 |
|
||
| hotelId | Query | Long | ❌ | - | 只导出这一家,优先于 cityCode |
|
||
| dateFrom | Query | LocalDate | ✅ | yyyy-MM-dd | 入住夜起(含) |
|
||
| dateTo | Query | LocalDate | ✅ | yyyy-MM-dd;跨度 ≤62 天 | 入住夜止(含) |
|
||
| onlyWithRemain | Query | Boolean | ❌ | - | 只导出有剩余的行 |
|
||
|
||
#### 出参 `xlsx 文件流(失败时为 Result JSON)`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| Content-Type | Header | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
|
||
| Content-Disposition | Header | `attachment; filename="<URL 编码文件名>"; filename*=UTF-8''<URL 编码文件名>` |
|
||
| 文件名 | String | `控房表-{dateFrom}~{dateTo}.xlsx` |
|
||
| 工作表「每日房量」 | Sheet | 每个酒店 × 房型 × 入住夜一行;列:酒店 / 入住夜日期 / 房型 / 控房总数 / 已用 / 剩余;不限量时总数与剩余显示「不限」 |
|
||
| 工作表「团组用房」 | Sheet | 一条占用一行;列:酒店 / 入住夜日期 / 房型 / 团号 / 房源 / 用房间数 / 确认状态;团期计划行没有团号,团号列填批次号 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/room-control/export?hotelId=100001&dateFrom=2026-10-01&dateTo=2026-10-07
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||
"Content-Disposition": "attachment; filename=\"%E6%8E%A7%E6%88%BF%E8%A1%A8-2026-10-01~2026-10-07.xlsx\"; filename*=UTF-8''%E6%8E%A7%E6%88%BF%E8%A1%A8-2026-10-01~2026-10-07.xlsx"
|
||
}
|
||
```
|
||
|
||
以上为响应头,响应体是二进制 xlsx。
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
条件内无数据时仍返回 xlsx,两个工作表只有表头。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808330,
|
||
"message": "查询范围过大,请缩小酒店或日期范围",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
失败时响应体是 `Result` JSON 而不是文件,错误码同接口 3(400 / 808090 / 808313 / 808330 / 808900),另有 100502「导出处理中,请勿重复点击」。前端下载前需按 Content-Type 判断是文件还是 JSON。
|
||
|
||
#### 业务边界
|
||
|
||
- 导出内容不含价格列。
|
||
- 与接口 3 同一查询条件与同一 2000 行上限。
|
||
- 同一条件 3 秒内重复点击返回 100502。
|
||
|
||
### 7. 退团房分页 `GET /v3/admin/order/house-console/room-transfers`
|
||
|
||
**VO**: `HouseRoomTransferPageReqVO → HouseRoomTransferPageRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
控制台「退团房」页签(通知链接 `/housekeeper/console?tab=transfer&id={transferId}`):列出退团释放出来、需要转给别人或向酒店取消的房间,并给出待处理的风险汇总。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| page | Query | Integer | ❌ | 默认 1 | 页码 |
|
||
| pageSize | Query | Integer | ❌ | 1~100,默认 20 | 每页条数 |
|
||
| status | Query | String | ❌ | PENDING / TRANSFERRED / CANCELLED,默认 PENDING | 状态 |
|
||
| risk | Query | String | ❌ | OVERDUE / NEAR / NO_DEADLINE / NORMAL | 风险筛选 |
|
||
| cityCode | Query | String | ❌ | ≤64 | 城市**中文名**(如 `海拉尔`) |
|
||
| keyword | Query | String | ❌ | ≤64 | 团号或酒店名 |
|
||
| stayDateFrom | Query | LocalDate | ❌ | yyyy-MM-dd | 入住晚起(含) |
|
||
| stayDateTo | Query | LocalDate | ❌ | yyyy-MM-dd | 入住晚止(含) |
|
||
|
||
#### 出参 `Result<HouseRoomTransferPageRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| records | List<HouseRoomTransferRespVO> | 当前页转房行 |
|
||
| records[].id | Long(String) | 转房行 ID |
|
||
| records[].sourceType | String | 来源类型 ORDER / GROUP_BATCH |
|
||
| records[].sourceOrderId | Long(String) | 源订单 ID(团期来源时为离团子单) |
|
||
| records[].teamNo | String | 源订单团号;空为 null |
|
||
| records[].sourceTeamNo | String | 源团号 / 批次号快照 |
|
||
| records[].sourceGroupBatchId | Long(String) | 源团期 ID |
|
||
| records[].sourceBatchNo | String | 源团期批次号 |
|
||
| records[].stayDate | LocalDate | 入住晚 |
|
||
| records[].cityName | String | 城市名 |
|
||
| records[].hotelId / hotelName | Long(String) / String | 酒店 |
|
||
| records[].roomTypeId / roomTypeName | Long(String) / String | 房型 |
|
||
| records[].roomCount | Integer | 原始间数 |
|
||
| records[].remainingCount | Integer | 剩余待处理间数 |
|
||
| records[].status / statusLabel | String | 状态及中文 |
|
||
| records[].cancelDays | Integer | 入住前几天免费取消;未设为 null |
|
||
| records[].cancelCutoff | String | 截止当天时刻 HH:mm |
|
||
| records[].remindDays | Integer | 提前几天提醒 |
|
||
| records[].deadlineAt | LocalDateTime | 免费取消截止时刻;未设期限为 null |
|
||
| records[].risk / riskLabel | String | 风险及中文;仅 PENDING 行有值 |
|
||
| records[].targetType | String | 最近一次转出的目标类型 ORDER / GROUP_BATCH |
|
||
| records[].targetOrderId / targetTeamNo | Long(String) / String | 目标订单与团号 |
|
||
| records[].targetRequirementId | Long(String) | 目标需求 ID |
|
||
| records[].targetGroupBatchId / targetBatchNo | Long(String) / String | 目标团期与批次号 |
|
||
| records[].hotelConfirmNo | String | 酒店确认号(转出时填写) |
|
||
| records[].proofFileIds | List<String> | 凭证文件 ID |
|
||
| records[].cancelFee | BigDecimal(String) | 取消费用(元) |
|
||
| records[].cancelReason | String | 取消原因 HOTEL_CANCELLED |
|
||
| records[].handlerName / handledAt | String / LocalDateTime | 处理人与处理时间 |
|
||
| records[].remark | String | 备注 |
|
||
| records[].readOnly | Boolean | 对当前登录人是否只读(源单由他人处理) |
|
||
| records[].readOnlyReason | String | 「由 X 处理」;可写为 null |
|
||
| total | long | 总条数 |
|
||
| page / pageSize | int | 当前页 / 每页条数 |
|
||
| summary.pendingRooms | int | 全部 PENDING 行的待处理间数合计 |
|
||
| summary.overdueRooms | int | 其中已过免费取消期的间数 |
|
||
| summary.nearRooms | int | 其中临近免费取消期的间数 |
|
||
| summary.noDeadlineRooms | int | 其中未设免费取消期的间数 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/room-transfers?status=PENDING&cityCode=海拉尔&page=1&pageSize=20
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"records": [
|
||
{
|
||
"id": "1950000000000000001", "sourceType": "ORDER", "sourceOrderId": "1930000000000000001",
|
||
"teamNo": "HL20261001A", "sourceTeamNo": "HL20261001A", "sourceGroupBatchId": null, "sourceBatchNo": null,
|
||
"stayDate": "2026-10-02", "cityName": "海拉尔", "hotelId": "100001", "hotelName": "海拉尔草原酒店",
|
||
"roomTypeId": "300001", "roomTypeName": "豪华双床房", "roomCount": 2, "remainingCount": 2,
|
||
"status": "PENDING", "statusLabel": "待处理", "cancelDays": 3, "cancelCutoff": "18:00", "remindDays": 1,
|
||
"deadlineAt": "2026-09-29 18:00:00", "risk": "NEAR", "riskLabel": "临近免费取消期",
|
||
"targetType": null, "targetOrderId": null, "targetTeamNo": null, "targetRequirementId": null,
|
||
"targetGroupBatchId": null, "targetBatchNo": null, "hotelConfirmNo": null, "proofFileIds": [],
|
||
"cancelFee": null, "cancelReason": null, "handlerName": null, "handledAt": null, "remark": null,
|
||
"readOnly": false, "readOnlyReason": null
|
||
}
|
||
],
|
||
"total": 1,
|
||
"page": 1,
|
||
"pageSize": 20,
|
||
"summary": { "pendingRooms": 2, "overdueRooms": 0, "nearRooms": 2, "noDeadlineRooms": 0 }
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
```json
|
||
{ "code": 200, "message": "成功", "data": { "records": [], "total": 0, "page": 1, "pageSize": 20, "summary": { "pendingRooms": 0, "overdueRooms": 0, "nearRooms": 0, "noDeadlineRooms": 0 } }, "success": true }
|
||
```
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "risk 取值非法",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | status 取值非法 / risk 取值非法 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
|
||
#### 业务边界
|
||
|
||
- `summary` 始终统计全部 PENDING 行,不受本次筛选条件影响;列表按筛选条件分页。
|
||
- `risk` 只对 PENDING 行有意义,其他状态行 `risk` / `riskLabel` 为 null;带 `risk` 筛选时服务端在内存中分页,`total` 仍是筛选后的总数。
|
||
- `readOnly` 判据与写接口 8 / 10 / 11 的守卫一致:源单持有人本人为 false,超管豁免为 false,其余为 true 并给「由 X 处理」(持有人姓名取不到时为「由其他房务处理」)。
|
||
|
||
### 8. 设置退团房免费取消期限 `PUT /v3/admin/order/house-console/room-transfers/{id}/deadline`
|
||
|
||
**VO**: `HouseRoomTransferDeadlineSaveReqVO → HouseRoomTransferRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
退团房列表某一行点「设期限」,录入酒店给的免费取消规则(入住前几天、当天几点前)与提前几天提醒;也可清除期限。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 转房行 ID |
|
||
| cancelDays | Body | Integer | ❌ | 0~60;null 表示清除期限 | 入住前几天免费取消 |
|
||
| cancelCutoff | Body | String | ❌ | HH:mm;cancelDays 非空而本字段空时取 18:00;cancelDays 为 null 时本字段被忽略,**该行原值保留、不置空**(#8597 订正) | 截止当天的时刻 |
|
||
| remindDays | Body | Integer | ❌ | 0~30;cancelDays 非空而本字段空时取 1;cancelDays 为 null 时本字段被忽略,**该行原值保留、不置空**(#8597 订正) | 提前几天提醒 |
|
||
|
||
#### 出参 `Result<HouseRoomTransferRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| (整行) | HouseRoomTransferRespVO | 更新后的该转房行,字段同接口 7 的 `records[]` |
|
||
| cancelDays / cancelCutoff / remindDays | Integer / String / Integer | 更新后的期限参数 |
|
||
| deadlineAt | LocalDateTime | 截止时刻 = 入住晚 − cancelDays 天的 cancelCutoff;清除期限后为 null |
|
||
| risk / riskLabel | String | 按新期限重算的风险 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"cancelDays": 3,
|
||
"cancelCutoff": "18:00",
|
||
"remindDays": 1
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"id": "1950000000000000001", "sourceType": "ORDER", "stayDate": "2026-10-02",
|
||
"hotelName": "海拉尔草原酒店", "roomTypeName": "豪华双床房", "remainingCount": 2,
|
||
"status": "PENDING", "statusLabel": "待处理", "cancelDays": 3, "cancelCutoff": "18:00", "remindDays": 1,
|
||
"deadlineAt": "2026-09-29 18:00:00", "risk": "NEAR", "riskLabel": "临近免费取消期",
|
||
"readOnly": false, "readOnlyReason": null
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
`cancelDays` 传 null 表示清除期限:**只有 `cancelDays` 变成 null**,`cancelCutoff` / `remindDays` 保留该行原值(从未设过期限时是默认的 `"18:00"` / `1`);返回行的 `deadlineAt=null`、`risk=NO_DEADLINE`、`riskLabel="未设免费取消期"`。判「有没有设期限」只看 `cancelDays === null` 或 `risk === "NO_DEADLINE"`,不要看 `cancelCutoff` / `remindDays` 是否为 null(#8597 订正)。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808328,
|
||
"message": "退改期限参数不合法",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808320 | 转房记录不存在 | id 不存在 |
|
||
| 808326 | 只有原单处理人可以处理退团房间 | 非源单持有人且非超管 |
|
||
| 808328 | 退改期限参数不合法 | cancelDays 超 0~60、remindDays 超 0~30、cancelCutoff 不是 HH:mm |
|
||
| 808321 | 该房间已处理 | 行已不是 PENDING |
|
||
| 808932 | 房务状态已被并发修改,请刷新后重试 | 并发写冲突 |
|
||
| 100502 | 修改处理中,请勿重复提交 | 3 秒内重复提交 |
|
||
|
||
#### 业务边界
|
||
|
||
- 本接口的入参不走注解校验,范围与格式错误统一返回 808328(不是 400)。
|
||
- 只有 PENDING 行可改;源单持有人或超管可操作。
|
||
- 校验顺序:808320 → 808326 → 808328 → 808321 → 808932。
|
||
|
||
### 9. 退团房转入候选 `GET /v3/admin/order/house-console/room-transfers/{id}/candidates`
|
||
|
||
**VO**: `Long id → List<HouseRoomTransferCandidateRespVO>`
|
||
|
||
#### 使用场景
|
||
|
||
退团房「转房」弹窗打开时加载:列出与该房间同城、同入住晚、非控房的常规单需求与团期,可转入的排在前面,不合格的带原因列出。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 转房行 ID |
|
||
|
||
#### 出参 `Result<List<HouseRoomTransferCandidateRespVO>>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| targetType | String | ORDER / GROUP_BATCH |
|
||
| orderId | Long(String) | 目标订单 ID;团期目标为 null |
|
||
| teamNo | String | 目标订单团号 |
|
||
| requirementId | Long(String) | 目标需求 ID(targetType=ORDER 时转房入参用) |
|
||
| groupBatchId | Long(String) | 目标团期 ID(targetType=GROUP_BATCH 时转房入参用) |
|
||
| batchNo | String | 目标团期批次号 |
|
||
| guestName | String | 客人姓名 / 团期名称 |
|
||
| stayDate | LocalDate | 入住晚 |
|
||
| cityName | String | 城市名 |
|
||
| needRoomCount | Integer | 该晚还差几间没配 |
|
||
| eligible | Boolean | 是否可转入 |
|
||
| ineligibleReason | String | 不可转入原因 |
|
||
| holderName | String | 目标当前处理人姓名;待认领为 null |
|
||
| readOnly | Boolean | 目标是否由他人处理(仅展示,不影响转入) |
|
||
| readOnlyReason | String | 「由 X 处理」 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/room-transfers/1950000000000000001/candidates
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": [
|
||
{ "targetType": "ORDER", "orderId": "1930000000000000009", "teamNo": "HL20261002C", "requirementId": "1940000000000000009", "groupBatchId": null, "batchNo": null, "guestName": "李女士", "stayDate": "2026-10-02", "cityName": "海拉尔", "needRoomCount": 2, "eligible": true, "ineligibleReason": null, "holderName": "张三", "readOnly": true, "readOnlyReason": "由 张三 处理" },
|
||
{ "targetType": "GROUP_BATCH", "orderId": null, "teamNo": null, "requirementId": null, "groupBatchId": "1960000000000000001", "batchNo": "GB20261001", "guestName": "呼伦贝尔秋季团", "stayDate": "2026-10-02", "cityName": "海拉尔", "needRoomCount": 3, "eligible": false, "ineligibleReason": "团期已确认", "holderName": null, "readOnly": false, "readOnlyReason": null }
|
||
],
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
```json
|
||
{ "code": 200, "message": "成功", "data": [], "success": true }
|
||
```
|
||
|
||
该转房行已不是 PENDING(已转出 / 已取消)时同样返回空数组,不报错。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808320,
|
||
"message": "转房记录不存在",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808320 | 转房记录不存在 | id 不存在 |
|
||
|
||
#### 业务边界
|
||
|
||
- `readOnly` 只用于展示目标由谁处理,不影响能否转入;能否转入只看 `eligible`。
|
||
- `ineligibleReason` 取值见「六.5 枚举」;可转入的候选排在前面。
|
||
- 纯读接口,不写数据。
|
||
|
||
### 10. 退团房转房 `POST /v3/admin/order/house-console/room-transfers/{id}/transfer`
|
||
|
||
**VO**: `HouseRoomTransferSaveReqVO → HouseRoomTransferRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
退团房「转房」弹窗选中一个候选后提交:把若干间房转给订单需求或团期,同时录入酒店确认号与凭证。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 转房行 ID |
|
||
| targetType | Body | String | ✅ | ORDER / GROUP_BATCH | 转入目标类型 |
|
||
| targetRequirementId | Body | Long | 条件 | targetType=ORDER 必填 | 目标需求 ID(取候选的 requirementId) |
|
||
| targetGroupBatchId | Body | Long | 条件 | targetType=GROUP_BATCH 必填 | 目标团期 ID(取候选的 groupBatchId) |
|
||
| roomCount | Body | Integer | ✅ | ≥1,且不超过剩余间数与目标缺口 | 转出间数 |
|
||
| hotelConfirmNo | Body | String | ✅ | 1~64 字 | 酒店确认号 |
|
||
| proofFileIds | Body | List<Long> | ✅ | 1~9 个,元素非空 | 凭证文件 ID |
|
||
| remark | Body | String | ❌ | ≤200 字 | 备注 |
|
||
|
||
#### 出参 `Result<HouseRoomTransferRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| (整行) | HouseRoomTransferRespVO | 转房后的该行,字段同接口 7 的 `records[]` |
|
||
| remainingCount | Integer | 扣减后的剩余待处理间数 |
|
||
| status / statusLabel | String | 剩余为 0 时为 TRANSFERRED / 已转出,否则仍为 PENDING |
|
||
| targetType / targetOrderId / targetTeamNo / targetRequirementId / targetGroupBatchId / targetBatchNo | String / Long(String) / String / Long(String) / Long(String) / String | 最近一次转出的目标 |
|
||
| hotelConfirmNo / proofFileIds / handlerName / handledAt | String / List<String> / String / LocalDateTime | 本次转出录入的信息 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"targetType": "ORDER",
|
||
"targetRequirementId": 1940000000000000009,
|
||
"roomCount": 2,
|
||
"hotelConfirmNo": "HX20261002001",
|
||
"proofFileIds": [1930000000000000601],
|
||
"remark": "酒店已同意换住客"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"id": "1950000000000000001", "sourceType": "ORDER", "stayDate": "2026-10-02",
|
||
"hotelName": "海拉尔草原酒店", "roomTypeName": "豪华双床房", "roomCount": 2, "remainingCount": 0,
|
||
"status": "TRANSFERRED", "statusLabel": "已转出", "risk": null, "riskLabel": null,
|
||
"targetType": "ORDER", "targetOrderId": "1930000000000000009", "targetTeamNo": "HL20261002C",
|
||
"targetRequirementId": "1940000000000000009", "targetGroupBatchId": null, "targetBatchNo": null,
|
||
"hotelConfirmNo": "HX20261002001", "proofFileIds": ["1930000000000000601"],
|
||
"handlerName": "王房务", "handledAt": "2026-09-29 10:00:00", "remark": "酒店已同意换住客",
|
||
"readOnly": false, "readOnlyReason": null
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
本接口无列表数据;任何失败都返回非 200 的 `code`,源行、目标与配房均不变。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808322,
|
||
"message": "目标不可转入:不同城",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | 请选择转入目标类型 / targetType 取值非法 / 请填写转出间数 / 转出间数至少 1 间 / 酒店确认号不能超过 64 字 / 凭证最多 9 个 / 凭证文件 ID 不能为空 / 备注不能超过 200 字 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808320 | 转房记录不存在 | id 不存在 |
|
||
| 808326 | 只有原单处理人可以处理退团房间 | 非源单持有人且非超管 |
|
||
| 808325 | 请填写酒店确认号并上传凭证 | 确认号为空或凭证为空 |
|
||
| 808322 | 目标不可转入:{0} | {0} 为具体原因,见「六.5 枚举」 |
|
||
| 808323 | 目标团期已确认,不能转入 | 目标团期已推进到确认;来源为团期(sourceType=GROUP_BATCH)且源团期已推进到确认时也返回本码,文案仍写「目标团期」 |
|
||
| 808321 | 该房间已处理 | 行已不是 PENDING |
|
||
| 808324 | 转出间数超过剩余 {0} 间 | roomCount 超过源剩余或目标缺口,{0} 为此刻可转间数 |
|
||
| 808608 | 订房计划已被其他操作修改,请刷新后重试 | 团期计划版本冲突 |
|
||
| 599602 | 应付款台账行已锁定 | 来源为 ORDER、源配房行对应的应付款台账行已有在途付款申请 |
|
||
| 808932 | 房务状态已被并发修改,请刷新后重试 | 并发写冲突 |
|
||
| 100502 | 转房处理中,请勿重复提交 | 3 秒内重复提交 |
|
||
| 100503 | 资源被占用,请稍后重试 | 源或目标正被另一写操作锁定 |
|
||
|
||
#### 业务边界
|
||
|
||
- 只有源单持有人或超管可转;超管豁免持有人校验。目标由谁持有不影响转入。
|
||
- `hotelConfirmNo` 与 `proofFileIds` 在 Swagger 标为必填,但不是注解校验:缺失时返回业务码 808325,不是 400。
|
||
- 校验顺序:808320 → 808326 → 808325 → 808322(未指定转入目标)→ 锁内复验(808323 / 808321 / 808324 / 808322 其余原因)→ 808932。
|
||
- 部分转出时该行保持 PENDING,`remainingCount` 减少;剩余为 0 时变为 TRANSFERRED。
|
||
- 来源为 ORDER 时,源配房行的应付款台账行若已有在途付款申请,返回 599602 且整笔不落库。
|
||
- 通知在事务提交后才发出、回滚时一条不发:目标处理人收 `HOUSE_ROOM_TRANSFERRED`(跳转 `/housekeeper/console?tab=transfer&id={transferId}`;目标待认领、没有处理人时不发),源单与目标单的定制师各收一条(同一人只发一次;团期目标只通知源单定制师)。
|
||
|
||
### 11. 退团房向酒店取消 `POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel`
|
||
|
||
**VO**: `HouseRoomTransferCancelReqVO → HouseRoomTransferRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
退团房没有合适的转入对象时,房务向酒店取消该房间,上传取消凭证并录入取消费用。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 转房行 ID |
|
||
| proofFileIds | Body | List<Long> | ✅ | 1~9 个,元素非空 | 取消凭证文件 ID |
|
||
| cancelFee | Body | BigDecimal | ❌ | ≥0,最多 2 位小数 | 取消费用(元) |
|
||
| remark | Body | String | ❌ | ≤200 字 | 备注 |
|
||
|
||
#### 出参 `Result<HouseRoomTransferRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| (整行) | HouseRoomTransferRespVO | 取消后的该行,字段同接口 7 的 `records[]` |
|
||
| status / statusLabel | String | CANCELLED / 已取消 |
|
||
| cancelReason | String | HOTEL_CANCELLED |
|
||
| cancelFee | BigDecimal(String) | 录入的取消费用 |
|
||
| proofFileIds | List<String> | 取消凭证 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"proofFileIds": [1930000000000000701],
|
||
"cancelFee": "0.00",
|
||
"remark": "酒店已免费取消"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"id": "1950000000000000001", "sourceType": "ORDER", "stayDate": "2026-10-02",
|
||
"hotelName": "海拉尔草原酒店", "roomTypeName": "豪华双床房", "roomCount": 2, "remainingCount": 2,
|
||
"status": "CANCELLED", "statusLabel": "已取消", "risk": null, "riskLabel": null,
|
||
"cancelFee": "0.00", "cancelReason": "HOTEL_CANCELLED", "proofFileIds": ["1930000000000000701"],
|
||
"handlerName": "王房务", "handledAt": "2026-09-29 10:00:00", "remark": "酒店已免费取消",
|
||
"readOnly": false, "readOnlyReason": null
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
本接口无列表数据;任何失败都返回非 200 的 `code`,该行不变。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808325,
|
||
"message": "请填写酒店确认号并上传凭证",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | 凭证最多 9 个 / 凭证文件 ID 不能为空 / 取消费用不能为负 / 取消费用最多 2 位小数 / 备注不能超过 200 字 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808320 | 转房记录不存在 | id 不存在 |
|
||
| 808326 | 只有原单处理人可以处理退团房间 | 非源单持有人且非超管 |
|
||
| 808325 | 请填写酒店确认号并上传凭证 | 未上传凭证(本接口不要求确认号,文案沿用同一错误码) |
|
||
| 808321 | 该房间已处理 | 行已不是 PENDING |
|
||
| 808932 | 房务状态已被并发修改,请刷新后重试 | 并发写冲突 |
|
||
| 100502 | 取消处理中,请勿重复提交 | 3 秒内重复提交 |
|
||
|
||
#### 业务边界
|
||
|
||
- 只有源单持有人或超管可操作。
|
||
- 凭证为空时返回 808325(业务码,不是 400)。
|
||
- 成功后该行整行变为 CANCELLED,不再出现在待处理汇总里;已部分转出的行取消的是剩余部分。
|
||
- 校验顺序:808320 → 808326 → 808325 → 808321 → 808932。
|
||
|
||
### 12. 房务异常检查 `GET /v3/admin/order/house-console/audit`
|
||
|
||
**VO**: `HouseConsoleAuditReqVO → HouseConsoleAuditRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
控制台「异常检查」页签:按出发日期区间一次列出数据对不上的问题(issues)和还没办完的事(tasks),每条可按 `orderId` / `groupBatchId` / `refId` 跳转处理。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| scope | Query | String | ❌ | mine / all,默认 mine | 待办范围 |
|
||
| departDateFrom | Query | LocalDate | ❌ | yyyy-MM-dd;默认今天 | 出发日期起(含) |
|
||
| departDateTo | Query | LocalDate | ❌ | yyyy-MM-dd;默认起始日 +30 天;跨度 ≤92 天 | 出发日期止(含) |
|
||
|
||
#### 出参 `Result<HouseConsoleAuditRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| issues | List<Item> | 数据不一致问题 |
|
||
| tasks | List<Item> | 待处理事项 |
|
||
| (Item)code | String | 问题码或待办码,见「六.5 枚举」 |
|
||
| (Item)codeLabel | String | 问题中文,前端直接展示 |
|
||
| (Item)taskCode | String | 待办码,仅 tasks 有值(与 code 相同) |
|
||
| (Item)orderId | Long(String) | 订单 ID |
|
||
| (Item)teamNo | String | 订单团号 |
|
||
| (Item)groupBatchId | Long(String) | 团期 ID |
|
||
| (Item)batchNo | String | 团期批次号 |
|
||
| (Item)stayDate | LocalDate | 入住晚 |
|
||
| (Item)hotelId / hotelName | Long(String) / String | 酒店 |
|
||
| (Item)roomTypeId / roomTypeName | Long(String) / String | 房型 |
|
||
| (Item)refId | Long(String) | 关联单据 ID(转房行 / 改配记录),用于跳转 |
|
||
| (Item)detail | String | 说明文字 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/audit?scope=mine&departDateFrom=2026-10-01&departDateTo=2026-10-31
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"issues": [
|
||
{ "code": "STOCK_LEDGER_MISMATCH", "codeLabel": "库存账不平", "taskCode": null, "orderId": null, "teamNo": null, "groupBatchId": null, "batchNo": null, "stayDate": "2026-10-02", "hotelId": "100001", "hotelName": "海拉尔草原酒店", "roomTypeId": "300001", "roomTypeName": "豪华双床房", "refId": null, "detail": "本地已用 5 间,库存日历已用 3 间" }
|
||
],
|
||
"tasks": [
|
||
{ "code": "TRANSFER_PENDING", "codeLabel": "退团房未结清", "taskCode": "TRANSFER_PENDING", "orderId": "1930000000000000001", "teamNo": "HL20261001A", "groupBatchId": null, "batchNo": null, "stayDate": "2026-10-02", "hotelId": "100001", "hotelName": "海拉尔草原酒店", "roomTypeId": "300001", "roomTypeName": "豪华双床房", "refId": "1950000000000000001", "detail": "剩余 2 间待处理" }
|
||
]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
```json
|
||
{ "code": 200, "message": "成功", "data": { "issues": [], "tasks": [] }, "success": true }
|
||
```
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808313,
|
||
"message": "日期跨度不能超过 92 天",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | scope 取值非法 | scope 不是 mine / all |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808313 | 日期跨度不能超过 92 天 | 出发日期跨度超 92 天 |
|
||
|
||
#### 业务边界
|
||
|
||
- `scope` 只作用于 `tasks`:mine 只列当前登录人持有的订单 / 团期的待办;`issues` 不受 scope 影响,始终是区间内全部。
|
||
- `STOCK_LEDGER_MISMATCH`(库存账不平)只在 resource 全局库存追踪开关打开时检查;开关关闭时不会产出该问题码。
|
||
- 纯读接口,不写数据。
|
||
|
||
### 13. 住宿模板列表 `GET /v3/admin/order/house-console/stay-templates`
|
||
|
||
**VO**: `String keyword → List<HouseStayTemplateSimpleRespVO>`
|
||
|
||
#### 使用场景
|
||
|
||
控制台「住宿模板」页签,以及配房时「从模板带入」的下拉列表。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| keyword | Query | String | ❌ | - | 模板名称模糊匹配 |
|
||
|
||
#### 出参 `Result<List<HouseStayTemplateSimpleRespVO>>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | Long(String) | 模板 ID |
|
||
| name | String | 模板名称 |
|
||
| creatorName | String | 创建人姓名;房务名单里查不到时为 null |
|
||
| nightCount | Integer | 晚数 |
|
||
| createTime | LocalDateTime | 创建时间 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/stay-templates?keyword=海拉尔
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": [
|
||
{ "id": "1839000000000000001", "name": "海拉尔 3 晚标准", "creatorName": "张三", "nightCount": 3, "createTime": "2026-09-28 10:00:00" }
|
||
],
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
```json
|
||
{ "code": 200, "message": "成功", "data": [], "success": true }
|
||
```
|
||
|
||
房务名单取不到时列表照常返回,`creatorName` 为 null。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808090,
|
||
"message": "未登录或非房务角色,无权操作",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 返回全部创建人的模板(不是只看自己的),按创建时间倒序,不分页。
|
||
- 已删除的模板不返回。
|
||
- 纯读接口,不写数据。
|
||
|
||
### 14. 住宿模板详情 `GET /v3/admin/order/house-console/stay-templates/{id}`
|
||
|
||
**VO**: `Long id → HouseStayTemplateRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
打开模板编辑,或配房时选中模板后取出逐晚明细带入。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 模板 ID |
|
||
|
||
#### 出参 `Result<HouseStayTemplateRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | Long(String) | 模板 ID |
|
||
| name | String | 模板名称 |
|
||
| creatorId | Long(String) | 创建人 ID(前端据此判断是否显示改 / 删) |
|
||
| creatorName | String | 创建人姓名 |
|
||
| createTime | LocalDateTime | 创建时间 |
|
||
| nights | List<Night> | 逐晚安排 |
|
||
| nights[].day | Integer | 第几晚,从 1 起 |
|
||
| nights[].cityName | String | 城市名 |
|
||
| nights[].hotelId / hotelName | Long(String) / String | 酒店 |
|
||
| nights[].settleType | String | 结算方式编码(字典 `resource_settle_type`),可空 |
|
||
| nights[].settleTypeLabel | String | 结算方式名称;为空时为「待确认」 |
|
||
| nights[].rooms | List<Room> | 房型明细 |
|
||
| nights[].rooms[].roomTypeId / roomTypeName | Long(String) / String | 房型 |
|
||
| nights[].rooms[].roomCount | Integer | 间数 |
|
||
| nights[].rooms[].price | String | 单价(元) |
|
||
| nights[].rooms[].breakfast | String | INCLUDED / EXCLUDED / PENDING |
|
||
| nights[].rooms[].breakfastLabel | String | 早餐显示名 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/house-console/stay-templates/1839000000000000001
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"id": "1839000000000000001",
|
||
"name": "海拉尔 3 晚标准",
|
||
"creatorId": "30001",
|
||
"creatorName": "张三",
|
||
"createTime": "2026-09-28 10:00:00",
|
||
"nights": [
|
||
{
|
||
"day": 1, "cityName": "海拉尔", "hotelId": "100001", "hotelName": "海拉尔草原酒店",
|
||
"settleType": null, "settleTypeLabel": "待确认",
|
||
"rooms": [
|
||
{ "roomTypeId": "300001", "roomTypeName": "豪华双床房", "roomCount": 5, "price": "320.00", "breakfast": "INCLUDED", "breakfastLabel": "含早餐" }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
模板不存在或已删除时不返回空对象,返回 808351。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808351,
|
||
"message": "模板不存在",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808351 | 模板不存在 | id 不存在或已删除 |
|
||
|
||
#### 业务边界
|
||
|
||
- 任何房务都可查看任何人的模板;改 / 删权限见接口 15 / 16。
|
||
- `settleTypeLabel` 由服务端按字典翻译,字典查不到时回退为原编码。
|
||
|
||
### 15. 住宿模板保存 `POST /v3/admin/order/house-console/stay-templates`
|
||
|
||
**VO**: `HouseStayTemplateSaveReqVO → Result<Long>`
|
||
|
||
#### 使用场景
|
||
|
||
「住宿模板」页签新建或编辑模板后保存。`id` 为空表示新建,有值表示修改该模板。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Body | Long | ❌ | - | 模板 ID;为空表示新建 |
|
||
| name | Body | String | ✅ | 1~50 字,服务端去首尾空格 | 模板名称,未删除模板中唯一 |
|
||
| nights | Body | List<Night> | ✅ | 1~30 晚 | 逐晚安排 |
|
||
| nights[].day | Body | Integer | ✅ | 1~30 | 第几晚 |
|
||
| nights[].cityName | Body | String | ❌ | ≤32 字 | 城市名 |
|
||
| nights[].hotelId | Body | Long | ❌ | - | 酒店 ID |
|
||
| nights[].hotelName | Body | String | ❌ | ≤100 字 | 酒店名 |
|
||
| nights[].settleType | Body | String | ❌ | ≤32 字 | 结算方式编码(字典 `resource_settle_type`),空为待确认 |
|
||
| nights[].rooms | Body | List<Room> | ✅ | 每晚 1~10 行 | 房型明细 |
|
||
| nights[].rooms[].roomTypeId | Body | Long | ❌ | - | 房型 ID |
|
||
| nights[].rooms[].roomTypeName | Body | String | ❌ | ≤100 字 | 房型名 |
|
||
| nights[].rooms[].roomCount | Body | Integer | ✅ | 1~500 | 间数 |
|
||
| nights[].rooms[].price | Body | BigDecimal | ❌ | ≥0,最多 2 位小数 | 单价(元) |
|
||
| nights[].rooms[].breakfast | Body | String | ❌ | INCLUDED / EXCLUDED / PENDING | 早餐 |
|
||
|
||
#### 出参 `Result<Long>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data | Long | 模板 ID(新建时为新 ID,修改时为原 ID) |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"id": null,
|
||
"name": "海拉尔 3 晚标准",
|
||
"nights": [
|
||
{
|
||
"day": 1,
|
||
"cityName": "海拉尔",
|
||
"hotelId": 100001,
|
||
"hotelName": "海拉尔草原酒店",
|
||
"settleType": null,
|
||
"rooms": [
|
||
{ "roomTypeId": 300001, "roomTypeName": "豪华双床房", "roomCount": 5, "price": "320.00", "breakfast": "INCLUDED" }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": "1839000000000000001",
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
本接口无列表数据;失败时模板不变(新建则不产生记录)。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808352,
|
||
"message": "只能修改或删除自己创建的模板",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | name 不能为空 / name 不能超过 50 字 / nights 不能为空 / nights 不能超过 30 晚 / day 不能为空 / day 从 1 起 / day 不能超过 30 / cityName 不能超过 32 字 / hotelName 不能超过 100 字 / settleType 不能超过 32 字 / rooms 不能为空 / 每晚 rooms 不能超过 10 行 / roomTypeName 不能超过 100 字 / roomCount 不能为空 / roomCount 至少 1 / roomCount 不能超过 500 / price 不能小于 0 / price 最多 2 位小数 / breakfast 只能是 INCLUDED / EXCLUDED / PENDING | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808350 | 模板名称已存在 | 与未删除模板重名(去首尾空格后比较) |
|
||
| 808351 | 模板不存在 | 修改时 id 不存在或已删除 |
|
||
| 808352 | 只能修改或删除自己创建的模板 | 修改他人创建的模板且当前登录人不是超管 |
|
||
| 100502 | 模板保存处理中,请勿重复提交 | 3 秒内重复提交 |
|
||
|
||
#### 业务边界
|
||
|
||
- 修改只允许创建人本人或超管。
|
||
- 名称唯一只在未删除模板中判断,已删除模板的名称可以复用。
|
||
- 修改是整份覆盖:`nights` 以本次提交为准。
|
||
|
||
### 16. 住宿模板删除 `DELETE /v3/admin/order/house-console/stay-templates/{id}`
|
||
|
||
**VO**: `Long id → Result<Void>`
|
||
|
||
#### 使用场景
|
||
|
||
「住宿模板」页签删除一个模板。前端可按详情里的 `creatorId` 与当前登录人比对决定是否展示删除按钮,服务端仍会校验。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | ✅ | - | 模板 ID |
|
||
|
||
#### 出参 `Result<Void>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data | null | 成功无返回体 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
DELETE /v3/admin/order/house-console/stay-templates/1839000000000000001
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": null,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
成功时 `data` 恒为 `null`;删除的是软删,列表与详情不再返回该模板。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808352,
|
||
"message": "只能修改或删除自己创建的模板",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 808351 | 模板不存在 | id 不存在或已删除 |
|
||
| 808352 | 只能修改或删除自己创建的模板 | 删除他人创建的模板且当前登录人不是超管 |
|
||
|
||
#### 业务边界
|
||
|
||
- 只允许创建人本人或超管删除。
|
||
- 软删;删除后该名称可被新模板复用。
|
||
- 已删除的模板再次删除返回 808351。
|
||
|
||
### 17. 团期转交 `POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/transfer`
|
||
|
||
**VO**: `HouseGroupTransferReqVO → Result<Void>`
|
||
|
||
#### 使用场景
|
||
|
||
团期持有人(或超管)把已整团认领的团期交给另一名房务,例如持有人休假。控制台团期视图(通知链接 `/housekeeper/console?groupBatchId={groupBatchId}`)上的「转交」按钮调用。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
|
||
| toUserId | Body | Long | ✅ | 须是在职房务 | 接收人 userId |
|
||
| reason | Body | String | ✅ | 1~200 字 | 转交原因,写入团期时间线 |
|
||
|
||
#### 出参 `Result<Void>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data | null | 成功无返回体 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"toUserId": 30002,
|
||
"reason": "本人休假,团期交给同组房务跟进"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": null,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
房务人员名单取不到时**不降级放行**,直接返回 808343,团期持有人不变。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 808343,
|
||
"message": "房务人员名单暂不可用,请稍后重试",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
| code | message | 触发 |
|
||
|------|---------|------|
|
||
| 400 | toUserId 不能为空 / reason 不能为空 / reason 长度不能超过 200 字 | 入参校验 |
|
||
| 808090 | 未登录或非房务角色,无权操作 | 非房务角色 |
|
||
| 589500 | 团期不存在 | groupBatchId 不存在 |
|
||
| 808340 | 只有团期当前处理人可以转交 | 团期未被认领;或当前登录人不是持有人且不是超管;或并发下持有人已变 |
|
||
| 808341 | 不能转交给自己 | toUserId 等于当前持有人或当前登录人 |
|
||
| 808343 | 房务人员名单暂不可用,请稍后重试 | 房务人员名单取不到(异常 / 空) |
|
||
| 808342 | 接收人不是房务 | 名单里没有 toUserId |
|
||
| 808659 | 该团有 {0} 户存在逐户配房(首个订单 {1}),请先删除配房后再操作 | 团内有户存在有效的逐户配房 |
|
||
| 100502 | 团期转交处理中,请勿重复提交 | 5 秒内重复提交 |
|
||
|
||
#### 业务边界
|
||
|
||
- 持有人本人或超管可转交;超管可转交任何已被认领的团期。
|
||
- `reason` 必填,与户级转单(超管 ≥10 字、普通房务可选)规则不同。
|
||
- 名单取不到一律拒绝(808343);只有超管「整团接管」(`POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/takeover`)在名单取不到时仍放行,接收人姓名显示占位 `user-{id}`。
|
||
- 名单里有接收人、但其姓名为空时,时间线里显示 `user-{id}`。
|
||
- 只换持有人:订房计划与分房不变。团期时间线记一条「团期转交:A → B(原因)」,事务提交后通知接收人。
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式(接口类必写)
|
||
|
||
> 本节只写**后端接受/拒绝 payload 的规则**,不写 UI 渲染建议。
|
||
|
||
### ✅ 正确 / ❌ 错误 payload 对照
|
||
|
||
| 场景 | payload |
|
||
|------|---------|
|
||
| ✅ 批量认领只认领需求 | `{ "requirementIds": [1840000000000000001] }` |
|
||
| ❌ 批量认领两个列表都空 | `{ "requirementIds": [], "groupBatchIds": [] }` → 400 请选择 1~50 条待认领记录 |
|
||
| ✅ 转入订单需求 | `{ "targetType": "ORDER", "targetRequirementId": 1940000000000000009, "roomCount": 1, "hotelConfirmNo": "HX1", "proofFileIds": [1] }` |
|
||
| ❌ 转入团期却只给需求 ID | `{ "targetType": "GROUP_BATCH", "targetRequirementId": 1940000000000000009, "roomCount": 1, "hotelConfirmNo": "HX1", "proofFileIds": [1] }` → 808322 目标不可转入:未指定转入目标 |
|
||
| ❌ 转房不带凭证 | `{ "targetType": "ORDER", "targetRequirementId": 1940000000000000009, "roomCount": 1, "hotelConfirmNo": "HX1" }` → 808325 |
|
||
| ✅ 清除退团房期限 | `{ "cancelDays": null }` |
|
||
| ❌ 期限天数越界 | `{ "cancelDays": 61 }` → 808328(不是 400) |
|
||
| ✅ 只改结算价 | `{ "hotelId": 100001, "roomTypeId": 300001, "dateFrom": "2026-10-01", "dateTo": "2026-10-07", "settlementPrice": "300.00" }` |
|
||
| ❌ 调价两个价格都不传 | `{ "hotelId": 100001, "roomTypeId": 300001, "dateFrom": "2026-10-01", "dateTo": "2026-10-07" }` → 808314 |
|
||
| ❌ 调房量不带已用期望值 | `{ "hotelId": 100001, "roomTypeId": 300001, "stayDate": "2026-10-01", "totalRooms": 15 }` → 400 expectedUsedRooms 不能为空 |
|
||
| ❌ 团期转交不写原因 | `{ "toUserId": 30002 }` → 400 reason 不能为空 |
|
||
|
||
### 切换状态时的必要动作
|
||
|
||
- 转房 `targetType` 切换时,把另一个目标 ID 字段置 null;服务端只读与 `targetType` 对应的那个字段。
|
||
- 调房量提交的 `expectedUsedRooms` 必须取自最近一次查询该格的 `usedRooms`;收到 808311 后先重新查询再提交。
|
||
- 控房表查询用城市**编码**,退团房列表用城市**中文名**,两个筛选框的取值来源不同。
|
||
- 下载导出文件前按响应 `Content-Type` 判断:xlsx 为文件,`application/json` 为错误 `Result`。
|
||
|
||
---
|
||
|
||
## 五、数据库行为(涉及写操作时必写)
|
||
|
||
| 前端提交 | 写入位置 | 行为 |
|
||
|----------|----------|------|
|
||
| 改配原订取消确认 | `house_assignment_change` | 该记录 HELD → CANCEL_CONFIRMED,覆盖取消费用 / 凭证 / 备注 / 操作人 |
|
||
| 批量认领 | 需求与团期的认领字段 | 逐条独立写,失败的条目不写 |
|
||
| 调房量 | resource 价格日历的库存列 | 按已用间数 CAS 更新控房总数 |
|
||
| 调价 | resource 价格日历的价格列 | 一次区间写入:已有日历行更新、缺失的补建;未传的价格列不动 |
|
||
| 设置期限 | `house_room_transfer` | 更新 cancel_days / cancel_cutoff / remind_days |
|
||
| 转房 | `house_room_transfer`、目标配房或团期计划、源配房或源团期计划 | 同一事务:父行扣剩余、写目标、扣源、写子行与日志;任一步失败整笔回滚 |
|
||
| 向酒店取消 | `house_room_transfer` | 父行置 CANCELLED、cancel_reason=HOTEL_CANCELLED |
|
||
| 模板保存 / 删除 | `house_stay_template` | 新建 / 整份覆盖;删除为软删 |
|
||
| 团期转交 | 团期认领字段、团期时间线 | CAS 换持有人,写时间线;计划与分房不动 |
|
||
|
||
**显式 SET NULL 说明**: 设置期限时 `cancelDays` 传 null **只把免费退改天数清空**,截止时刻与提醒天数保留该行原值(两列非空),`deadlineAt` 随之为 null(#8597 订正);其余写接口未传的可选字段保持原值,不会被写成 null。
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
- 已登录但不是房务角色(ROOM_MANAGER / SUPER_ADMIN 以外)→ 808090「未登录或非房务角色,无权操作」;原「房务组长」角色已取消,该类账号同样返回 808090。
|
||
- 写接口统一经房务写守卫;只读接口经房务读守卫,两者都只认房务角色。
|
||
- 资源不存在 → 各接口的业务码(808320 / 808332 / 808351 / 589500),HTTP 200。
|
||
- resource 服务不可用 → 控房表相关接口返回 808900「资源服务暂不可用,请稍后重试」,不返回空表冒充无数据。
|
||
- 所有写接口带防重(3 秒,团期转交 5 秒);重复提交返回 100502 与各接口自己的提示文案。
|
||
- 并发写冲突 → 808932「房务状态已被并发修改,请刷新后重试」或 808311 / 808608(见各接口)。
|
||
|
||
---
|
||
|
||
## 六.5、枚举 / 数据字典(接口出现枚举时必写)
|
||
|
||
### oldStatus(HouseAssignmentChangeConstants)
|
||
|
||
**所属字段**: `HouseAssignmentChangeRespVO.oldStatus` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `HELD` | 原酒店待取消 | 改配后原酒店还没取消,可调接口 1 确认 |
|
||
| `CANCEL_CONFIRMED` | 已确认取消 | 已上传取消凭证 |
|
||
|
||
### changeKind(HouseAssignmentChangeConstants)
|
||
|
||
**所属字段**: `HouseAssignmentChangeRespVO.changeKind` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `HOTEL` | 换酒店 | 配房行换了酒店 |
|
||
| `ROOM_COUNT` | 减间数 | 配房行间数减少 |
|
||
|
||
### status(退团房行状态)
|
||
|
||
**所属字段**: `HouseRoomTransferRespVO.status`、`HouseRoomTransferPageReqVO.status` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `PENDING` | 待处理 | 还有剩余间数没转出也没取消 |
|
||
| `TRANSFERRED` | 已转出 | 剩余间数已全部转出 |
|
||
| `CANCELLED` | 已取消 | 已向酒店取消 |
|
||
|
||
### risk(退团房风险)
|
||
|
||
**所属字段**: `HouseRoomTransferRespVO.risk`、`HouseRoomTransferPageReqVO.risk` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `OVERDUE` | 已过免费取消期 | 现在已过截止时刻(入住晚 − cancelDays 天的 cancelCutoff) |
|
||
| `NEAR` | 临近免费取消期 | 今天 ≥ 截止日 − remindDays 天(按日比较) |
|
||
| `NO_DEADLINE` | 未设免费取消期 | cancelDays 为空 |
|
||
| `NORMAL` | 正常 | 其余 |
|
||
|
||
### cancelReason(HouseRoomTransferCancelReason)
|
||
|
||
**所属字段**: `HouseRoomTransferRespVO.cancelReason` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `HOTEL_CANCELLED` | - | 接口 11 写入;该值在代码里没有对应的中文标签,展示时请用行上的 `statusLabel`(已取消) |
|
||
|
||
### sourceType / targetType(退团房来源与目标类型)
|
||
|
||
**所属字段**: `HouseRoomTransferRespVO.sourceType`、`targetType`,`HouseRoomTransferSaveReqVO.targetType`,`HouseRoomTransferCandidateRespVO.targetType` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `ORDER` | 订单 | 常规单或团期户的订单需求 |
|
||
| `GROUP_BATCH` | 团期 | 团期整团 |
|
||
|
||
### ineligibleReason / 808322 参数(转入不可用原因)
|
||
|
||
**所属字段**: `HouseRoomTransferCandidateRespVO.ineligibleReason`、808322 文案 `{0}` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `团期已确认` | 团期已确认 | 候选原因 |
|
||
| `需求已失效` | 需求已失效 | 候选原因 |
|
||
| `需求改版中` | 需求改版中 | 候选原因 |
|
||
| `该晚已配满` | 该晚已配满 | 候选原因 |
|
||
| `无团号` | 无团号 | 候选原因,也是 808322 参数 |
|
||
| `该晚已有同酒店同房型` | 该晚已有同酒店同房型 | 候选原因,也是 808322 参数 |
|
||
| `未指定转入目标` | 未指定转入目标 | 808322 参数 |
|
||
| `目标不存在` | 目标不存在 | 808322 参数 |
|
||
| `团期户请转入所在团期` | 团期户请转入所在团期 | 808322 参数 |
|
||
| `不同城` | 不同城 | 808322 参数 |
|
||
| `目标当晚无住宿` | 目标当晚无住宿 | 808322 参数 |
|
||
| `目标当晚已有控房` | 目标当晚已有控房 | 808322 参数 |
|
||
| `不能转回原团期/原需求` | 不能转回原团期/原需求 | 808322 参数 |
|
||
|
||
### 批量认领 targetType
|
||
|
||
**所属字段**: `HouseConsoleBatchClaimRespVO.items[].targetType` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `REQUIREMENT` | 常规单住宿需求 | 来自 requirementIds |
|
||
| `GROUP_BATCH` | 团期 | 来自 groupBatchIds |
|
||
|
||
### audit code(异常检查问题码与待办码)
|
||
|
||
**所属字段**: `HouseConsoleAuditRespVO.Item.code` / `taskCode` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `STOCK_OVERBOOKED` | 超分配 | issues;已分配超过库存 |
|
||
| `STOCK_LEDGER_MISMATCH` | 库存账不平 | issues;本地已用与库存日历不一致,仅库存追踪开关打开时检查 |
|
||
| `STOCK_ROW_MISSING` | 库存日历缺行 | issues |
|
||
| `TRANSFER_TARGET_GONE` | 转房目标失效 | issues |
|
||
| `PLAN_COUNT_MISMATCH` | 计划数量不符 | issues |
|
||
| `TRANSFER_PENDING` | 退团房未结清 | tasks |
|
||
| `HOTEL_CANCEL_PENDING` | 原酒店待取消 | tasks;对应 HELD 改配记录 |
|
||
| `INQUIRY_PENDING` | 新订/变更待确认 | tasks |
|
||
| `STAY_UNARRANGED` | 住宿待落实 | tasks |
|
||
|
||
### breakfast(HouseBreakfast)
|
||
|
||
**所属字段**: `HouseStayTemplateSaveReqVO.nights[].rooms[].breakfast`、`HouseStayTemplateRespVO.nights[].rooms[].breakfast` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `INCLUDED` | 含早餐 | - |
|
||
| `EXCLUDED` | 不含早餐 | - |
|
||
| `PENDING` | 早餐待确认 | 未填时按此输出 |
|
||
|
||
### roomSource(HouseRoomSource)
|
||
|
||
**所属字段**: `HouseRoomControlRowRespVO.usages[].roomSource` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `STOCK` | 控房 | 控房表只列扣库存的行,本表恒为此值 |
|
||
|
||
### settleType(字典 resource_settle_type)
|
||
|
||
**所属字段**: `HouseStayTemplateRespVO.nights[].settleType` / **类型**: `String`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| 空 | 待确认 | settleTypeLabel 输出「待确认」 |
|
||
| 字典编码 | 字典名称 | 字典查不到时 settleTypeLabel 回退为原编码 |
|
||
|
||
### 错误码段 808300~808399(HouseConsoleErrorCode)
|
||
|
||
**所属字段**: `Result.code` / **类型**: `Integer`
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `808310` | 总房量不能小于已占用 {0} 间 | 调房量;{0} 为已用间数 |
|
||
| `808311` | 已占用数已变化,请刷新后重试 | 调房量 CAS 失败 |
|
||
| `808312` | 库存追踪未开启,暂不能调整房量 | 调房量;resource 全局开关关闭 |
|
||
| `808313` | 日期跨度不能超过 {0} 天 | 控房表 62 天;异常检查 92 天 |
|
||
| `808314` | 协议价与结算价至少填写一项 | 调价 |
|
||
| `808320` | 转房记录不存在 | 退团房 |
|
||
| `808321` | 该房间已处理 | 退团房行已不是 PENDING |
|
||
| `808322` | 目标不可转入:{0} | 转房;{0} 见上表 |
|
||
| `808323` | 目标团期已确认,不能转入 | 转房;源团期已确认时也返回本码 |
|
||
| `808324` | 转出间数超过剩余 {0} 间 | 转房;{0} 为此刻可转间数 |
|
||
| `808325` | 请填写酒店确认号并上传凭证 | 转房 / 向酒店取消 |
|
||
| `808326` | 只有原单处理人可以处理退团房间 | 退团房写操作 |
|
||
| `808328` | 退改期限参数不合法 | 设置期限 |
|
||
| `808330` | 查询范围过大,请缩小酒店或日期范围 | 控房表查询 / 导出 |
|
||
| `808332` | 变更记录不存在 | 改配取消确认 |
|
||
| `808333` | 原订已确认取消 | 改配取消确认 |
|
||
| `808340` | 只有团期当前处理人可以转交 | 团期转交 |
|
||
| `808341` | 不能转交给自己 | 团期转交 |
|
||
| `808342` | 接收人不是房务 | 团期转交 |
|
||
| `808343` | 房务人员名单暂不可用,请稍后重试 | 团期转交、户级转单、超管指派 |
|
||
| `808350` | 模板名称已存在 | 模板保存 |
|
||
| `808351` | 模板不存在 | 模板详情 / 保存 / 删除 |
|
||
| `808352` | 只能修改或删除自己创建的模板 | 模板保存 / 删除 |
|
||
|
||
808327、808331 未使用。
|
||
|
||
### resource 错误码映射(HouseResourceErrorTranslator)
|
||
|
||
**所属字段**: `Result.code` / **类型**: `Integer`
|
||
|
||
控房表接口调用 resource 时,resource 返回的 3104xx 在本服务翻译成 8083xx 后返回,前端只会看到右侧的码。
|
||
|
||
| 值 | 中文 | 说明 |
|
||
|----|------|------|
|
||
| `310421` | 映射为 808313 | 参数固定为 62 |
|
||
| `310422` | 映射为 808330 | - |
|
||
| `310423` | 映射为 808312 | - |
|
||
| `310424` | 映射为 808310 | 参数为已用间数,取不到时为「?」 |
|
||
| `310425` | 映射为 808311 | - |
|
||
| 其他 3104xx | 原样透传 | 例如 310426「房型 {0} 不属于酒店 {1}」 |
|
||
| 返回为空 | 映射为 808900 | 资源服务暂不可用,请稍后重试 |
|
||
|
||
---
|
||
|
||
## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面)
|
||
|
||
- **仅影响**: 管理后台「房务控制台」菜单各页签;团期抢单池新增「转交」动作。
|
||
- **零影响**:
|
||
- 小程序与 H5
|
||
- 已有配房行的价格(调价只作用于之后新生成的配房)
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
所有接口都经测试服网关调用。HTTP 状态恒为 200,下面的 `code` 指响应 body 里的 `code`,带 ✓ 标记。行尾 `@` 后面是当时测试服 order-v3 的部署提交。`bdde64a3a`、`9c7ac9382`、`ff6863754`、`3ecf38797` 四个提交都包含本单合并提交 `7c21cf0e40`。控房表相关接口另依赖 resource 部署提交 `bdde64a3a`,测试服已开 `hotel.stock.enabled=true`。
|
||
|
||
```
|
||
PUT /v3/admin/order/house-console/changes/{changeId}/cancel-confirm HELD 改配记录,带 1 个凭证 + cancelFee=200.00 → code=200,oldStatus HELD→CANCEL_CONFIRMED,cancelFee="200.00" ✓ @bdde64a3a
|
||
PUT /v3/admin/order/house-console/changes/{changeId}/cancel-confirm 同一条再确认一次 → code=808333「原订已确认取消」 ✓ @bdde64a3a
|
||
POST /v3/admin/order/house-console/claims/batch 2 条待认领 + 1 条已被他人认领 → code=200,successCount=2、failCount=1,失败项 errorCode=808001;成功两条的认领人为本人 ✓ @bdde64a3a
|
||
GET /v3/admin/order/house-console/room-control 某晚已有 2 间控房配房 → code=200,usedRooms=2、assignedRooms=2、totalRooms=15、remainRooms=13 ✓ @9c7ac9382
|
||
PUT /v3/admin/order/house-console/room-control/stock totalRooms=1(小于已占用 2) → code=808310 ✓ @9c7ac9382
|
||
PUT /v3/admin/order/house-console/room-control/stock expectedUsedRooms=1(实际已占用 2) → code=808311 ✓ @9c7ac9382
|
||
PUT /v3/admin/order/house-console/room-control/stock totalRooms=5 + expectedUsedRooms=2 → code=200;控房表该行 totalRooms 15→5、remainRooms 13→3 ✓ @9c7ac9382
|
||
PUT /v3/admin/order/house-console/room-control/price protocolPrice / settlementPrice 620.00 / 615.00 → 680.00 / 675.00 → code=200;之后新提交的同酒店同房型同晚配房行快照 680.00 / 675.00,调价前已有的行仍是 620.00 / 615.00 ✓ @9c7ac9382
|
||
GET /v3/admin/order/house-console/room-control/export 导出 → 响应为 xlsx 文件(非 JSON 包装);sheet「每日房量」表头 酒店 / 入住夜日期 / 房型 / 控房总数 / 已用 / 剩余,sheet「团组用房」表头 酒店 / 入住夜日期 / 房型 / 团号 / 房源 / 用房间数 / 确认状态,全文无价格列 ✓ @9c7ac9382
|
||
GET /v3/admin/order/house-console/room-transfers 取消一张已确认常规订单(1 行非控房 2 间 + 1 行控房) → code=200,新增 1 行 PENDING、roomCount=2,控房行不出现 ✓ @bdde64a3a,重建夹具复测同样读数 ✓ @ff6863754
|
||
GET /v3/admin/order/house-console/room-transfers 同一取消命令重放(返回 581017 订单已取消) → 行数仍为 1 ✓ @bdde64a3a
|
||
GET /v3/admin/order/house-console/room-transfers RESOURCE_PREPARING 团期里一户出行前取消 → code=200,新增 1 行 PENDING、sourceType=GROUP_BATCH、roomCount=2 ✓ @3ecf38797
|
||
GET /v3/admin/order/house-console/room-transfers 整行转出后 → 该行 status=TRANSFERRED、remainingCount=0、标签「已转出」 ✓ @3ecf38797
|
||
PUT /v3/admin/order/house-console/room-transfers/{id}/deadline cancelDays=3 → code=200,分页该行 risk=OVERDUE ✓ @9c7ac9382,复测 ✓ @ff6863754
|
||
PUT /v3/admin/order/house-console/room-transfers/{id}/deadline cancelDays=0、remindDays=1 → code=200,risk=NEAR ✓ @9c7ac9382,复测 ✓ @ff6863754
|
||
PUT /v3/admin/order/house-console/room-transfers/{id}/deadline cancelDays=null(清空) → code=200,库里 cancel_days 为 NULL(cancel_cutoff / remind_days 保留原值),risk=NO_DEADLINE ✓ @ff6863754
|
||
GET /v3/admin/order/house-console/room-transfers/{id}/candidates 同城同晚有 RESOURCE_PREPARING 团期 → code=200,该团 eligible=true、needRoomCount=4 ✓ @3ecf38797
|
||
GET /v3/admin/order/house-console/room-transfers/{id}/candidates 同城同晚有房务 B 处理的订单 → 该单 eligible=true,holderName 为房务 B 的姓名 ✓ @ff6863754
|
||
GET /v3/admin/order/house-console/room-transfers/{id}/candidates 团期该晚 needRoomCount=0 → eligible=false,ineligibleReason「该晚已配满」 ✓ @ff6863754
|
||
GET /v3/admin/order/house-console/room-transfers/{id}/candidates 已确认团期 → eligible=false、ineligibleReason「团期已确认」:测试服未单独调用,由 HouseRoomTransferQueryManagerTest#candidates_confirmedGroup_listedLastAsIneligibleWithReason 覆盖
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 转入团期,不带 hotelConfirmNo → code=808325「请填写酒店确认号并上传凭证」 ✓ @3ecf38797
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 转入 RESOURCE_PREPARING 团期,带齐确认号与凭证、整行 2 间 → code=200,源行 TRANSFERRED、remainingCount 2→0;该团该晚新增 1 行 2 间计划行(不扣控房、已确认);源订单该晚配房行被软删 ✓ @3ecf38797
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 转入房务 B 处理的订单 → code=200,目标配房行 confirmStatus=CONFIRMED;房务 B 站内信新增 HOUSE_ROOM_TRANSFERRED「退团房间已转入:<目标团号>」 ✓ @ff6863754
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 非源单处理人(房务 C)调用 → code=808326「只有原单处理人可以处理退团房间」 ✓ @ff6863754
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 部分转入 roomCount=1 → code=200,源行 remainingCount 2→1,仍为 PENDING ✓ @ff6863754
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/transfer 转入已确认团期 → 808323:测试服未单独调用,由 HouseRoomTransferManagerTest#transfer_recheck7GroupNoLongerWritable_throws808323 覆盖
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel 不带凭证 → code=808325 ✓ @9c7ac9382
|
||
POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel 带凭证(真实 OSS 上传) → code=200,该行 PENDING→CANCELLED,cancel_fee=0.00 ✓ @9c7ac9382
|
||
GET /v3/admin/order/house-console/audit 有 HELD 改配记录、尚未确认取消 → code=200,tasks 含 HOTEL_CANCEL_PENDING「原酒店待取消」 ✓ @bdde64a3a
|
||
GET /v3/admin/order/house-console/audit 源订单已取消、退团房行 PENDING,窗口覆盖出发日 → code=200,tasks 含 TRANSFER_PENDING「退团房未结清」 ✓ @ff6863754
|
||
GET /v3/admin/order/house-console/audit issues 各类(超分配 / 账不平)正反例:开关打开时正常流程造不出超分配,测试服未单独造,由 HouseConsoleAuditManagerTest#audit_assignedAboveStockPlusUsed_reportsOverbooked 等逐类覆盖
|
||
GET /v3/admin/order/house-console/stay-templates 新建后按关键字查 → code=200,列表含新模板 ✓ @bdde64a3a,复测 ✓ @9c7ac9382
|
||
GET /v3/admin/order/house-console/stay-templates/{id} 测试服未单独调用,由 HouseStayTemplateServiceTest#get_roundTripNights_withLabelsAndPriceString 覆盖
|
||
POST /v3/admin/order/house-console/stay-templates 新建 → code=200 ✓;同名再建 → code=808350「模板名称已存在」 ✓ @bdde64a3a,复测 ✓ @9c7ac9382
|
||
DELETE /v3/admin/order/house-console/stay-templates/{id} 非创建人(房务 A)删除 → code=808352「只能修改或删除自己创建的模板」 ✓;创建人(超管测试账号)删除 → code=200 ✓ @bdde64a3a,复测 ✓ @9c7ac9382
|
||
POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/transfer 持有人转给另一房务(团里已有 1 行计划) → code=200;团期配房列表 houseClaimerName 变为接收人,计划行数 1→1 ✓ @9c7ac9382
|
||
POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/transfer 非持有人(房务 C)调用 → code=808340「只有团期当前处理人可以转交」 ✓ @9c7ac9382
|
||
```
|
||
|
||
验证身份:房务 A / B / C、测试定制师、超管测试账号,全部是测试专用账号。落库读数来自测试服只读 SQL。
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- 关联 Issue: [wx/HL#8491](https://git.1814.love:8443/wx/HL/issues/8491)
|
||
- 契约文档: `docs/order-v3/api/API-SPEC-HOUSE-V1.1.html` §12 接口、§11.12 错误码
|
||
- 同批变更: 同目录 `30_8491_房务配房接口字段与口径调整-修改接口-管理后台.md`、`30_8491_房务旧列表接口下线-删除接口-管理后台.md`
|
||
|
||
## 关联 / 联系人
|
||
|
||
### 链接
|
||
|
||
- **Issue**: [#8491](https://git.1814.love:8443/wx/HL/issues/8491)
|
||
|
||
### 联系人
|
||
|
||
- **后端负责人**: @wx
|