文件
hl-api-changelog/changelogs-v2/2026-09/30_8615_转房记录作废原因与退房给酒店口径调整-修改接口-管理后台.md
T
API Changelog Bot和Claude Opus 5.5 d1ab03e7c0
changelog-filename-gate / validate (push) Failing after 2s
docs(changelog): #8615 转房记录作废原因与退房给酒店口径调整
- 转房列表 cancelReason 新增三个系统作废取值(本团已再分配 / 本团已撤销该晚计划 / 团期已解散)
- 退房给酒店(I-21)对团期来源行补批次门禁与超量码 808324
- 附测试环境实测结论

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 11:05:20 +08:00

20 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 8615 退团转房:作废原因新增三个系统取值,向酒店取消追加团期栅栏与联动缩减 admin wx(GIT) 修改接口 deployed not_required pending 2026-09-30 dev-v3

退团转房:作废原因新增三个系统取值,向酒店取消追加团期栅栏与联动缩减

⚠️ 关键变化

  • 退团转房池列表(#8491 I-17)的 records[].cancelReason 由原来只有一个取值 HOTEL_CANCELLED,扩展为四个取值,新增 GROUP_REALLOCATED / GROUP_PLAN_REMOVED / GROUP_DISBANDED 三个由团期写口在同一事务内系统作废时写入的取值;这三种情况下 handlerName 恒为 null(无人工处理人),handledAt 仍会写入系统作废发生的时刻。前端按 cancelReason 分支展示原因文案的地方需要扩展这三个分支,否则会落到未知分支的兜底展示。
  • 退团房向酒店取消(#8491 I-21,POST .../room-transfers/{id}/cancel-hotel)新增两个错误码:团期来源行在源团期已不在「资源准备中」阶段时返回 808323(此前 I-21 对团期来源行不做团期状态校验,任何状态都能直接取消,改动后与转房接口 I-20 同口径);团期来源行的源计划空余不足以覆盖本行待转间数时返回 808324。这两个码此前只出现在 I-20 的错误表里,I-21 的错误表新增了它们。
  • 退团房向酒店取消成功后,若该行是团期来源行,会在同一事务内按取消的间数同步缩减源团期计划行的 roomCount(联动 shrinkForTransfer);这一步不改变本接口的响应结构,只影响该房间此后是否还会被团期自动分配算进可用余量。
  • 转房接口(#8491 I-20)不在本次变更接口清单内——其错误表已发布过 808324,本次只是把此前一个应报 808324(源计划空余不足)却会先报到 808932(并发冲突)的边界情况改为直接报 808324,错误码本身与文案都没有新增,属于既有契约内的分支修正,前端已有的 808324/808932 处理分支不需要改动。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 退团转房池分页 GET /v3/admin/order/house-console/room-transfers 响应字段取值扩展 cancelReason 新增三个系统作废取值,系统作废行 handlerName 为空
2 退团房向酒店取消 POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel 新增错误码 + 联动行为 团期来源行新增 808323/808324 校验;取消成功后同步缩减源团期计划间数

三、接口详情

1. 退团转房池分页 GET /v3/admin/order/house-console/room-transfers

VO: HouseRoomTransferPageReqVO → HouseRoomTransferPageRespVO

使用场景

房务控制台「退团房」页签展示当前待处理 / 已转出 / 已取消的转房行列表。本次改动只涉及列表行里 cancelReason 取值集合的扩展,请求参数与响应结构均未变化。

入参

字段 位置 类型 必填 约束 说明
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 风险筛选,仅对 PENDING 行有意义
cityCode Query String ❌ ≤64 城市中文名
keyword Query String ❌ ≤64 团号或酒店名关键词
stayDateFrom Query LocalDate ❌ yyyy-MM-dd 入住晚起(含)
stayDateTo Query LocalDate ❌ yyyy-MM-dd 入住晚止(含)

出参

字段 类型 说明
records List 当前页转房行
records[].id Long(String) 转房行 ID
records[].sourceType String 来源类型 ORDER / GROUP_BATCH
records[].sourceGroupBatchId / sourceBatchNo Long(String) / String 团期来源行的源团期 ID 与批次号
records[].stayDate LocalDate 入住晚
records[].hotelName / roomTypeName String 酒店名 / 房型名
records[].roomCount Integer 原始间数
records[].remainingCount Integer 剩余待处理间数;部分被系统收敛时会减少,行仍保持 PENDING
records[].status / statusLabel String PENDING / TRANSFERRED / CANCELLED 及中文
records[].cancelReason 【改动】String 仅 CANCELLED 行有值。HOTEL_CANCELLED=房务人工向酒店取消(不变);新增 GROUP_REALLOCATED=本团已再分配、GROUP_PLAN_REMOVED=本团已撤销该晚计划、GROUP_DISBANDED=团期已解散,三者都是团期写口系统作废,见「六.5」
records[].handlerName 【改动】String 处理人姓名;cancelReason 为三个新增取值之一时恒为 null(无人工处理人)
records[].handledAt LocalDateTime 处理时间;系统作废时同样写入作废发生的时刻,不为 null
records[].readOnly / readOnlyReason Boolean / String 对当前登录人是否只读及理由
total / page / pageSize long / int / int 分页信息
summary.pendingRooms 等 4 项 int 全部 PENDING 行的风险汇总,恒不受本次筛选条件影响

请求示例

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

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "id": "9100234", "sourceType": "GROUP_BATCH", "sourceOrderId": null, "teamNo": null,
        "sourceTeamNo": "HLT-20261012-003", "sourceGroupBatchId": "500321", "sourceBatchNo": "HLT-20261012-003",
        "stayDate": "2026-10-12", "cityName": "海拉尔", "hotelId": "60088", "hotelName": "海拉尔国际大酒店",
        "roomTypeId": "70012", "roomTypeName": "高级大床房", "roomCount": 2, "remainingCount": 2,
        "status": "CANCELLED", "statusLabel": "已取消", "cancelDays": 3, "cancelCutoff": "18:00", "remindDays": 1,
        "deadlineAt": "2026-10-09T18:00:00", "risk": "NORMAL", "riskLabel": "正常",
        "targetType": null, "targetOrderId": null, "targetTeamNo": null, "targetRequirementId": null,
        "targetGroupBatchId": null, "targetBatchNo": null, "hotelConfirmNo": null, "proofFileIds": [],
        "cancelFee": null, "cancelReason": "GROUP_REALLOCATED", "handlerName": null,
        "handledAt": "2026-09-30T10:02:11", "remark": null, "readOnly": false, "readOnlyReason": null
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20,
    "summary": { "pendingRooms": 6, "overdueRooms": 0, "nearRooms": 1, "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": "status 取值非法",
  "data": null,
  "success": false
}
code message 触发
400 status 取值非法 / risk 取值非法 入参校验,未变
808090 未登录或非房务角色,无权操作 非房务角色,未变

业务边界

  • 团期写口(分房重算、加入团期自动分房、改计划间数、删计划、团期解散)触发系统收敛时:某计划行下全部 PENDING 转房行都被覆盖,则行整体变为 CANCELLED 并写入对应 cancelReason;只覆盖了一部分,则行仍是 PENDING,仅 remainingCount 减少,cancelReason/handlerName/handledAt 均不变。
  • 系统作废(cancelReason 为 GROUP_REALLOCATED/GROUP_PLAN_REMOVED/GROUP_DISBANDED)的行没有人工处理人:handlerName 为 null;触发它的管理员记在操作日志里,不在本接口暴露。
  • summary 恒统计全部 PENDING 行,不受本次筛选条件影响。

2. 退团房向酒店取消 POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel

VO: HouseRoomTransferCancelReqVO → HouseRoomTransferRespVO

使用场景

退团房没有合适的转入对象时,房务直接向酒店办理取消,上传凭证并可录入取消费用。本次改动只影响团期来源行(sourceType=GROUP_BATCH):新增源团期状态与源计划余量两道校验,取消成功后联动缩减源团期计划间数;常规单来源行(sourceType=ORDER)的路径与校验顺序不变。

入参

字段 位置 类型 必填 约束 说明
id Path Long ✅ - 转房行 ID
proofFileIds Body List ✅ 1~9 个,元素非空 取消凭证文件 ID
cancelFee Body BigDecimal ❌ ≥0,最多 2 位小数 取消费用(元)
remark Body String ❌ ≤200 字 备注

出参

字段 类型 说明
(整行) HouseRoomTransferRespVO 取消后的该行,字段同接口 1 的 records[]
status / statusLabel String CANCELLED / 已取消
cancelReason String 恒为 HOTEL_CANCELLED;本接口触发的取消不会写入三个系统作废取值,那三个只由团期写口的系统收敛写入
hotelConfirmNo String 本接口不接收确认号,恒为 null(未变)
cancelFee / proofFileIds BigDecimal(String) / List 录入的取消费与凭证

请求示例

{
  "proofFileIds": [88031, 88032],
  "cancelFee": 0,
  "remark": "酒店已免费取消"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "id": "9100235", "sourceType": "GROUP_BATCH", "sourceOrderId": null, "teamNo": null,
    "sourceTeamNo": "HLT-20261012-004", "sourceGroupBatchId": "500322", "sourceBatchNo": "HLT-20261012-004",
    "stayDate": "2026-10-15", "cityName": "满洲里", "hotelId": "60090", "hotelName": "满洲里丽景大酒店",
    "roomTypeId": "70020", "roomTypeName": "行政大床房", "roomCount": 3, "remainingCount": 3,
    "status": "CANCELLED", "statusLabel": "已取消", "risk": null, "riskLabel": null,
    "hotelConfirmNo": null, "proofFileIds": ["88031", "88032"], "cancelFee": "0.00",
    "cancelReason": "HOTEL_CANCELLED", "handlerName": "王芳", "handledAt": "2026-09-30T10:15:32",
    "remark": "酒店已免费取消", "readOnly": false, "readOnlyReason": null
  },
  "success": true
}

空数据 / 降级响应

本接口无列表数据;任何失败都返回非 200 的 code,该行状态不变。

错误响应

{
  "code": 808324,
  "message": "转出间数超过剩余 1 间",
  "data": null,
  "success": false
}
code message 触发
400 凭证最多 9 个 / 凭证文件 ID 不能为空 / 取消费用不能为负 / 取消费用最多 2 位小数 / 备注不能超过 200 字 入参校验,未变
808090 未登录或非房务角色,无权操作 非房务角色,未变
808320 转房记录不存在 id 不存在(未变;锁前锁后各判一次,同一个码)
808326 只有原单处理人可以处理退团房间 非源单持有人且非超管,未变
808325 请填写酒店确认号并上传凭证 未上传凭证(本接口不要求确认号,文案沿用同一错误码),未变
808323 目标团期已确认,不能转入 【新增,仅团期来源行】源团期已不在「资源准备中」阶段。文案沿用 I-20 已发布的措辞,这里没有「目标」,实际含义是「源团期已不可再改动,不能取消这一行」
808321 该房间已处理 行已不是 PENDING,未变
808932 房务状态已被并发修改,请刷新后重试 【团期来源行新增触发场景】源团期或源计划行在读取时已不存在(并发被删/改);以及原有的 CAS 并发冲突
808324 转出间数超过剩余 {0} 间 【新增,仅团期来源行】源计划行已分配间数 > roomCount − 本行剩余间数,即空余不足以覆盖本行待取消间数;{0} = max(roomCount − 已分配间数, 0)
100502 取消处理中,请勿重复提交 3 秒内重复提交,未变

业务边界

  • 只有源单持有人或超管可操作;凭证为空返回 808325(业务码,不是 400)。
  • 校验顺序(团期来源行):808320(不锁定读)→ 808326 → 808325 → 808323(源团期栅栏)→ 808320(锁定读复验,同一个码)→ 808321 → 808932(源团期/源计划缺失)→ 808324(源计划空余不足)→ 808932(CAS 并发冲突)。常规单来源行没有 808323/808324 两步,其余顺序不变。
  • 团期来源行取消成功后,源团期计划行的 roomCount 会在同一事务内按取消间数同步缩减;这一步对本接口响应体不可见,影响的是该房间此后是否还计入团期自动分配的可用余量。
  • 成功后该行整行变为 CANCELLED,不再出现在待处理汇总里;已部分转出的行取消的是剩余部分。

四、契约约束与正确调用方式

  • 接口 2 的团期来源行取消前,前端应先确认该行所属团期仍处于允许改动的阶段;若已收到 808323,不应重试,应提示房务该团期已不可再取消这一行。
  • 接口 2 收到 808324 时,message 里的数字是此刻可取消的上限间数(可能为 0),不代表本行 remainingCount;不要直接拿 remainingCount 去重试提交。
  • 接口 1 展示已取消行的原因文案时必须按 cancelReason 四个取值分支处理,不要假设该字段只有一个可能值;系统作废三种取值下 handlerName 为 null 是正常状态,不是数据缺失。

五、数据库行为

场景 团期计划行 room_count 转房行 status / remaining_count
常规单来源行(ORDER)取消 不涉及团期计划 CANCELLED,其余字段照旧写入
团期来源行取消,源计划空余充足 按本次取消间数同步减少(shrinkForTransfer) CANCELLED
团期来源行取消,源计划空余不足(命中 808324) 不变 不变,整体事务回滚
团期写口触发系统收敛(分房重算 / 自动分房 / 改计划间数 / 删计划 / 团期解散) 视触发写口而定 全部覆盖:CANCELLED + 对应 cancel_reason;部分覆盖:仍 PENDING,remaining_count 减少

六、边界行为

  • 转房行不存在或已被删除 → 808320(接口 2,未变)。
  • 团期整团解散时,其下全部 PENDING 转房行在同一事务内作废(cancelReason=GROUP_DISBANDED),此后对这些行调用接口 2 会先命中 808321(已非 PENDING)。
  • 源团期推进出「资源准备中」阶段后,其团期来源的 PENDING 行调用接口 2 会命中 808323;同一场景下调用 I-20(转房)此前已经是 808323,两个接口现在口径一致。
  • 本单上线前已存在、且所属计划行已被删除但转房行仍是 PENDING 的存量脏数据,不会被本次新增的系统收敛机制回溯处理,仍会出现在接口 1 的列表里;对这类行调用接口 2,源团期已不在「资源准备中」时返回 808323,否则因源计划不存在返回 808932。

六.5、枚举

cancelReason(house_room_transfer.cancel_reason,仅 status=CANCELLED 时有值)

取值 中文 说明 是否本次新增
HOTEL_CANCELLED 房务人工向酒店取消 房务通过接口 2 主动办理 否
GROUP_REALLOCATED 本团已再分配 计划行还在,但空余已不足以覆盖待转间数——本团别的户分到了这批房,或计划间数被调少 是
GROUP_PLAN_REMOVED 本团已撤销该晚计划 待转房挂的计划行已不在活跃计划里:被删除、被替换成不同房型/酒店的新行,或缩减到 0 被整行删除 是
GROUP_DISBANDED 团期已解散 流团/解散时该团全部待转房一并作废 是

六.6、修改前后对比

字段取值

字段 改前 改后
接口 1 records[].cancelReason 仅 HOTEL_CANCELLED 一个取值 新增 GROUP_REALLOCATED / GROUP_PLAN_REMOVED / GROUP_DISBANDED 三个取值
接口 2 错误码集合 808320 / 808321 / 808325 / 808326 / 808932(另有 400 / 808090 / 100502) 团期来源行新增 808323、808324

行为

行为 改前 改后
本团某户分到已释放的团期房 原 PENDING 转房行照常留在池里,房务仍可在接口 2 / I-20 继续处理,存在一房两卖风险 团期写口在同一事务内收敛该计划行下的 PENDING 转房行,全部覆盖则整行作废并写入对应 cancelReason,部分覆盖则 remaining_count 减少
接口 2 对团期来源行的源团期状态 不做校验,源团期任意状态都能直接取消 源团期不在「资源准备中」时返回 808323
接口 2 取消团期来源行后源计划间数 不变 按取消间数同步缩减
接口 2 团期来源行空余不足 无此校验 返回 808324,行与源计划均不写入

六.7、影响评估

  • 是否破坏向后兼容:否。cancelReason 是新增取值,不是重命名或语义变更;两个错误码是接口 2 的新增分支,不是复用/覆盖已有码的语义。
  • 前端是否必须同步上线:是。不同步的话,系统作废行在列表上会落入未处理的 cancelReason 分支;团期来源行取消撞上 808323/808324 时若没有对应分支,会呈现为未识别错误。
  • 前端 workaround 清理点:若此前把「cancelReason 非 HOTEL_CANCELLED」当异常兜底处理,需要改为按四个取值分别展示;否则无需清理,只需新增分支。

七、不影响范围

  • 常规单来源行(sourceType=ORDER)在接口 2 的校验顺序、错误码与响应结构均未变化。
  • 接口 1 的入参、分页结构、summary 汇总口径未变化。
  • 转房接口 I-20 的请求/响应结构、错误码集合未新增,本单不改变其契约,仅修正一处原本应报 808324 却先报到 808932 的边界分支,不在本次变更接口清单内。
  • 房务分房重建(H11)等团期写口自身的请求/响应契约未变化,只是这些写口在检测到需要收敛的 PENDING 转房行时会按本单的规则写入新的 cancelReason。

八、测试环境已验证

测试环境已验证(部署提交 405fc8db0,验证时刻 2026-09-30 10:22~10:41):

  1. 转出间数超过计划剩余:POST /v3/admin/order/house-console/room-transfers/{id}/cancel-hotel,body code=808324("转出间数超过剩余 0 间"),转房行与计划行均无变化。
  2. 团内户取消离团后另一户经重算分到房:POST /v3/admin/order/{id}/cancel/pre-trip + POST /v3/admin/house/group-batches/{id}/allocations/rebuild,转房行由 PENDING 变为 CANCELLED,cancelReason=GROUP_REALLOCATED,处理人为空,有对应操作日志。
  3. 计划仍有空余时人工办理转出:POST .../cancel-hotel,body code=200,转房行变 CANCELLED/HOTEL_CANCELLED,计划 roomCount 由 2 减为 0 并软删(预期)。

十、相关文档

  • 工单 #8615
  • 参考发布契约:changelogs-v2/2026-09/30_8491_房务控制台接口-新增接口-管理后台.md(I-17 / I-20 / I-21 的既有字段与错误码定义)

关联 / 联系人

  • 关联工单:#8615
  • 关联历史 changelog:#8491