文件
hl-api-changelog/changelogs-v2/2026-09/30_8491_房务控制台接口-新增接口-管理后台.md
T
API Changelog Bot和Claude Opus 5 c2f04d7b32
changelog-filename-gate / validate (push) Failing after 2s
docs(changelog): 补 #8597 退团房期限清空与退团房待办交接件,并订正 #8491 里「三列一并置空」的错述
新增 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>
2026-09-30 07:46:23 +08:00

85 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 8491 房务控制台新增接口:批量认领、改配取消确认、控房表、退团房转房、异常检查、住宿模板、团期转交 admin wx(GIT) 新增接口 deployed not_required pending 2026-09-30 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 ✅ 1~9 个,元素非空 取消凭证文件 ID
cancelFee Body BigDecimal ❌ ≥0,最多 2 位小数 取消费用(元)
remark Body String ❌ ≤200 字 备注

出参 Result<Void>

字段 类型 说明
data null 成功无返回体,前端成功后重新拉取订单房务详情

请求示例

{
  "cancelProofFileIds": [1930000000000000501],
  "cancelFee": "120.00",
  "remark": "酒店已电话确认取消"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null,
  "success": true
}

空数据 / 降级响应

本接口无列表数据,成功时 data 恒为 null。无降级分支:任何失败都返回非 200 的 code,记录不变。

错误响应

{
  "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 ❌ 元素非空 常规单住宿需求 ID 列表
groupBatchIds Body List ❌ 元素非空 团期 ID 列表
(跨字段) Body - ✅ 两列表各自去重后合计 1~50 条 违反时返回 400「请选择 1~50 条待认领记录」

出参 Result<HouseConsoleBatchClaimRespVO>

字段 类型 说明
successCount Integer 成功条数
failCount Integer 失败条数
items List 逐项结果,顺序:先需求后团期,各自按提交顺序去重
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 失败原因;成功为空

请求示例

{
  "requirementIds": [1840000000000000001, 1840000000000000011],
  "groupBatchIds": [1840000000000000002]
}

响应示例

{
  "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="系统繁忙,请稍后重试",其余条目照常处理。

错误响应

{
  "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 控房行,按(酒店, 入住夜, 房型)升序
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 团组用房明细
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 确认状态标签

请求示例

GET /v3/admin/order/house-console/room-control?cityCode=hailar&dateFrom=2026-10-01&dateTo=2026-10-07&onlyWithRemain=false

响应示例

{
  "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
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": { "stockTrackingEnabled": true, "rows": [] }, "success": true }

条件内无控房行时 rows 为空数组。resource 服务不可用时不降级为空表,返回 808900。

错误响应

{
  "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 团组用房明细,字段同接口 3

请求示例

{
  "hotelId": 100001,
  "roomTypeId": 300001,
  "stayDate": "2026-10-01",
  "totalRooms": 15,
  "expectedUsedRooms": 5
}

响应示例

{
  "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 刷新整表。

错误响应

{
  "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 受影响的天数(更新已有价格日历行 + 补建缺失日历行)

请求示例

{
  "hotelId": 100001,
  "roomTypeId": 300001,
  "dateFrom": "2026-10-01",
  "dateTo": "2026-10-07",
  "protocolPrice": "320.00",
  "settlementPrice": "300.00"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": 7,
  "success": true
}

空数据 / 降级响应

本接口无列表型数据;区间内缺失的价格日历行会被补建并计入 data。

错误响应

{
  "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 一条占用一行;列:酒店 / 入住夜日期 / 房型 / 团号 / 房源 / 用房间数 / 确认状态;团期计划行没有团号,团号列填批次号

请求示例

GET /v3/admin/order/house-console/room-control/export?hotelId=100001&dateFrom=2026-10-01&dateTo=2026-10-07

响应示例

{
  "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,两个工作表只有表头。

错误响应

{
  "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 当前页转房行
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 凭证文件 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 其中未设免费取消期的间数

请求示例

GET /v3/admin/order/house-console/room-transfers?status=PENDING&cityCode=海拉尔&page=1&pageSize=20

响应示例

{
  "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
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": { "records": [], "total": 0, "page": 1, "pageSize": 20, "summary": { "pendingRooms": 0, "overdueRooms": 0, "nearRooms": 0, "noDeadlineRooms": 0 } }, "success": true }

错误响应

{
  "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 按新期限重算的风险

请求示例

{
  "cancelDays": 3,
  "cancelCutoff": "18:00",
  "remindDays": 1
}

响应示例

{
  "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 订正)。

错误响应

{
  "code": 808328,
  "message": "退改期限参数不合法",
  "data": null,
  "success": false
}
code message 触发
808090 未登录或非房务角色,无权操作 非房务角色
808320 转房记录不存在 id 不存在
808326 只有原单处理人可以处理退团房间 非源单持有人且非超管
808328 退改期限参数不合法 cancelDays 超 060、remindDays 超 030、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 处理」

请求示例

GET /v3/admin/order/house-console/room-transfers/1950000000000000001/candidates

响应示例

{
  "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
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": [], "success": true }

该转房行已不是 PENDING(已转出 / 已取消)时同样返回空数组,不报错。

错误响应

{
  "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 ✅ 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 / LocalDateTime 本次转出录入的信息

请求示例

{
  "targetType": "ORDER",
  "targetRequirementId": 1940000000000000009,
  "roomCount": 2,
  "hotelConfirmNo": "HX20261002001",
  "proofFileIds": [1930000000000000601],
  "remark": "酒店已同意换住客"
}

响应示例

{
  "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,源行、目标与配房均不变。

错误响应

{
  "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 ✅ 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 取消凭证

请求示例

{
  "proofFileIds": [1930000000000000701],
  "cancelFee": "0.00",
  "remark": "酒店已免费取消"
}

响应示例

{
  "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,该行不变。

错误响应

{
  "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 数据不一致问题
tasks List 待处理事项
(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 说明文字

请求示例

GET /v3/admin/order/house-console/audit?scope=mine&departDateFrom=2026-10-01&departDateTo=2026-10-31

响应示例

{
  "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
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": { "issues": [], "tasks": [] }, "success": true }

错误响应

{
  "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 创建时间

请求示例

GET /v3/admin/order/house-console/stay-templates?keyword=海拉尔

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    { "id": "1839000000000000001", "name": "海拉尔 3 晚标准", "creatorName": "张三", "nightCount": 3, "createTime": "2026-09-28 10:00:00" }
  ],
  "success": true
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": [], "success": true }

房务名单取不到时列表照常返回,creatorName 为 null。

错误响应

{
  "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 逐晚安排
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 房型明细
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 早餐显示名

请求示例

GET /v3/admin/order/house-console/stay-templates/1839000000000000001

响应示例

{
  "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。

错误响应

{
  "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 ✅ 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 ✅ 每晚 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)

请求示例

{
  "id": null,
  "name": "海拉尔 3 晚标准",
  "nights": [
    {
      "day": 1,
      "cityName": "海拉尔",
      "hotelId": 100001,
      "hotelName": "海拉尔草原酒店",
      "settleType": null,
      "rooms": [
        { "roomTypeId": 300001, "roomTypeName": "豪华双床房", "roomCount": 5, "price": "320.00", "breakfast": "INCLUDED" }
      ]
    }
  ]
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": "1839000000000000001",
  "success": true
}

空数据 / 降级响应

本接口无列表数据;失败时模板不变(新建则不产生记录)。

错误响应

{
  "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 成功无返回体

请求示例

DELETE /v3/admin/order/house-console/stay-templates/1839000000000000001

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null,
  "success": true
}

空数据 / 降级响应

成功时 data 恒为 null;删除的是软删,列表与详情不再返回该模板。

错误响应

{
  "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 成功无返回体

请求示例

{
  "toUserId": 30002,
  "reason": "本人休假,团期交给同组房务跟进"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null,
  "success": true
}

空数据 / 降级响应

房务人员名单取不到时不降级放行,直接返回 808343,团期持有人不变。

错误响应

{
  "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
  • 契约文档: docs/order-v3/api/API-SPEC-HOUSE-V1.1.html §12 接口、§11.12 错误码
  • 同批变更: 同目录 30_8491_房务配房接口字段与口径调整-修改接口-管理后台.md、30_8491_房务旧列表接口下线-删除接口-管理后台.md

关联 / 联系人

链接

联系人

  • 后端负责人: @wx