文件
hl-api-changelog/changelogs-v2/2026-09/26_8388_房务最终确认回执上传加认领校验列表加读门-修改接口-管理后台.md
T
API Changelog Bot和Claude Opus 5.5 88caa74d34
changelog-filename-gate / validate (push) Failing after 3s
docs(changelog): 房务接口审计批次 #8385~#8390 交接件
- #8385 团期订房计划建守卫(未认领团 808612)与 808660 释放文案
- #8386 住宿 supplier-reject 加角色门与认领校验,车务 supplier-reject 下线
- #8387 下线订单侧房间分配三口 /v3/admin/order/{id}/room
- #8388 最终确认回执上传加认领校验、列表加读门、808184 带具体原因
- #8389 下线 POST /v3/admin/order/assignments/{assignmentId}/rooms
- #8390 房务 16 个只读端点加角色读门,ADMIN 房务菜单撤授

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 23:52:47 +08:00

15 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 8388 回执接口守卫:上传加认领人校验(808110/808186,超管不豁免)、列表加房务读门(808090)、缺分片改 808184 admin wx(GIT) 修改接口 deployed verified pending 房务回执上传新增认领人校验(超管不豁免)与可选分片处理;列表新增房务读权限门(不受灰度开关控制,常开);错误码 808184 消息补五种原因的具体文案。测试环境网关已实测各分支,含缺分片 808184 新文案。 2026-09-26 dev-v3

order-v3:房务最终确认回执接口守卫加固(管理后台)

服务: hl-order-service-v3
PR: #8394(原始改动) + #8399(808184 补 {0} 占位追加)
Issue: #8388


⚠️ 关键变化

  1. 上传回执 POST /admin/house/assignments/requirements/{requirementId}/receipts:

    • 新增认领人校验:需求必须被当前操作人认领,否则返回 808110(非本人);SUPER_ADMIN 在本端点不豁免,与 #8386 驳回需求口径相反。
    • 需求处于 PENDING_CLAIM(未认领)时先被状态闸口拦下,返回 808186;错误码 808116 仅作理论防御(正常调用路径不可达)。
    • 缺 file 分片 / 0 字节 file 分片改返 808184「回执上传失败:上传文件为空或缺少 file 分片」(改前返 HTTP 500),共 5 种原因文案。
    • 顺序:角色门(808090/808091)→ 需求存在(808100)→ 状态闸口(808186)→ 认领人校验(808110)→ 文件校验(808184)。
  2. 回执列表 GET /admin/house/assignments/requirements/{requirementId}/receipts:

    • 新增房务读权限门:非房务角色(定制师、车控等)返回 808090。房务全角色(含组长)可见;超管可见。
    • 无认领限制(组长可看全部、他人接手前查历史回执)。

一、背景

回执两个端点(上传、列表)无任何权限校验,导致:

  1. 非认领人房务可为他人上传回执,破坏追责链。
  2. 定制师、车控等非房务角色可读回执列表含 OSS 直链与酒店联系信息。

同一配房模块的 10 个写操作都带认领人校验;回执缺失属遗漏。缺 file 分片时返回 500 属参数处理缺陷(hl-common-log 共性坑,本单仅止血)。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 上传最终确认回执 POST /admin/house/assignments/requirements/{requirementId}/receipts 修改接口 加认领人校验、缺分片改 808184
2 回执列表 GET /admin/house/assignments/requirements/{requirementId}/receipts 修改接口 加房务读权限门(808090)

三、接口详情

1. 上传最终确认回执 POST /admin/house/assignments/requirements/{requirementId}/receipts

VO: multipart/form-data: file → Result<HouseFinalizeReceiptRespVO>

使用场景

房务在配房面板「最终确认」区上传回执照片/PDF,证明已与酒店确认房间。仅该需求的认领人本人可上传;非房务角色、房务组长、非认领人(含 SUPER_ADMIN)均返回权限错误——超管在本端点不豁免认领归属校验,这一点与 #8386(驳回需求超管豁免)口径不同。

入参字段表

字段 位置 类型 必填 约束 说明
requirementId Path Long 是 — 酒店需求 ID
file Form MultipartFile 是(业务校验) ≤50MB,类型自动识别 回执文件;缺失返 808184

出参字段表

字段 类型 说明
receiptId String 回执 ID(雪花 ID,序列化为字符串)
requirementId String 需求 ID(雪花 ID,序列化为字符串)
orderId String 订单 ID(雪花 ID,序列化为字符串)
fileName String 原始文件名
ossUrl String OSS 公网 URL,domain + "/" + ossKey 拼接,不签名
ossKey String OSS Object Key
fileSize Long 文件大小(字节)
fileType String 附件类型:PDF / IMAGE / OTHER(按扩展名识别)
createTime LocalDateTime 上传时间,序列化格式 yyyy-MM-dd HH:mm:ss

请求示例

POST /admin/house/assignments/requirements/2103126783048245250/receipts HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <room_manager token>
Content-Type: multipart/form-data; boundary=----Boundary

------Boundary
Content-Disposition: form-data; name="file"; filename="receipt.jpg"
Content-Type: image/jpeg

[binary jpeg data]
------Boundary--

响应示例

成功:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "receiptId": "2103801203844689921",
    "requirementId": "2103126783048245250",
    "orderId": "2100542287908892650",
    "fileName": "receipt.jpg",
    "ossUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/house/finalize-receipt/...",
    "ossKey": "house/finalize-receipt/2026-09/2103126783048245250_receipt.jpg",
    "fileSize": 512000,
    "fileType": "IMAGE",
    "createTime": "2026-09-26 14:30:00"
  }
}

失败(非认领人):

{
  "code": 808110,
  "message": "需求不属于当前用户",
  "success": false,
  "data": null
}

失败(缺分片,实测):

{
  "code": 808184,
  "message": "回执上传失败:上传文件为空或缺少 file 分片",
  "success": false,
  "data": null
}

空数据 / 降级响应

  • 文件为空或缺 file 分片:code=808184,message「回执上传失败:上传文件为空或缺少 file 分片」(改前返 HTTP 500)。

错误响应

{
  "code": 808110,
  "message": "需求不属于当前用户",
  "success": false,
  "data": null
}

其他错误码:

  • 808090:未登录或非房务角色,无权操作。
  • 808091:房务组长为只读监督角色,无权执行该操作。
  • 808100:需求不存在。
  • 808186:当前状态不允许上传回执(仅 CLAIMING/PENDING_FINALIZE 可传;PENDING_CLAIM 等其他状态走这个码,不是 808116)。
  • 808116:订单未抢单, 请先抢单再配房(状态闸口之后理论不可达,作纵深防护保留)。
  • 808184:回执上传失败:{0},{0} 按触发原因取以下固定文案之一——「上传文件为空或缺少 file 分片」/「文件大小超过 50MB」/「OSS 未配置」/「读取上传文件失败」/「文件存储服务暂不可用,请稍后重试」;异常原文只进服务端日志,不回显给客户端。

业务边界

  • 认领校验:需求 claimer_id 必须等于当前操作人;超管不豁免,对他人认领的需求上传同样返回 808110。与 #8386(驳回需求,超管豁免)口径不同,前端不要套同一套按钮逻辑。
  • 校验顺序:写门(808090/808091)→ 需求存在(808100)→ 状态闸口(808186)→ 认领归属(808116/808110)→ 文件校验(808184)。
  • 文件分片:file 分片改为可选(required=false),缺失走 Service 内已有的空文件分支报业务码 808184(改前是 HTML form 漏填触发 MissingServletRequestPartException,落到兜底 Exception 处理器返 HTTP 200+code 500「系统繁忙」并打 ERROR 日志)。
  • 状态限制:仅 CLAIMING(配房中)与 PENDING_FINALIZE(待确认)两个阶段可上传;PENDING_CLAIM(未抢单)等其他状态返 808186,不是 808116。
  • 无事务:upload() 不加 @Transactional;OSS putObject 成功后才 insert,insert 失败可能残留孤儿 OSS 对象(由清理 job 兜底);OSS 失败(putObject 抛异常)返 808184 且不落库。

2. 回执列表 GET /admin/house/assignments/requirements/{requirementId}/receipts

VO: → Result<List<HouseFinalizeReceiptRespVO>>

使用场景

房务或超管查看某需求的全部回执列表(谁上传的、何时、文件链接)。非房务角色返回 808090;房务全角色可见无限制。

入参字段表

字段 位置 类型 必填 约束 说明
requirementId Path Long 是 — 酒店需求 ID

出参字段表

字段 类型 说明
receiptId String 回执 ID(雪花 ID,序列化为字符串)
requirementId String 需求 ID(雪花 ID,序列化为字符串)
orderId String 订单 ID(雪花 ID,序列化为字符串)
fileName String 原始文件名
ossUrl String OSS 公网 URL,不签名
ossKey String OSS Object Key
fileSize Long 文件大小(字节)
fileType String 附件类型:PDF / IMAGE / OTHER
createTime LocalDateTime 上传时间,序列化格式 yyyy-MM-dd HH:mm:ss

请求示例

GET /admin/house/assignments/requirements/2103126783048245250/receipts HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <room_manager token>

响应示例

成功(房务):

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": [
    {
      "receiptId": "2103801203844689921",
      "requirementId": "2103126783048245250",
      "orderId": "2100542287908892650",
      "fileName": "receipt_1.jpg",
      "ossUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/house/finalize-receipt/...",
      "ossKey": "house/finalize-receipt/2026-09/2103126783048245250_receipt_1.jpg",
      "fileSize": 512000,
      "fileType": "IMAGE",
      "createTime": "2026-09-26 14:30:00"
    }
  ]
}

失败(定制师):

{
  "code": 808090,
  "message": "未登录或非房务角色,无权操作",
  "success": false,
  "data": null
}

空数据 / 降级响应

  • 无回执:code=200,data=[]。

错误响应

{
  "code": 808090,
  "message": "未登录或非房务角色,无权操作",
  "success": false,
  "data": null
}

说明:

  • 808090(新增):非房务角色返回;该读门调 HouseReadGuard.assertHouseReadPermission(),不受 #8390 引入的灰度开关 group-batch.acl.enforce.house-read-role 控制,是常开的角色门。

业务边界

  • 角色放行:ROOM_MANAGER / house_keeper_lead / SUPER_ADMIN 均可读;零角色(#7609 G-2 保留项)亦放行。
  • 无认领限制:组长可看全部需求回执(监督权),他人接手后也可查历史。
  • 直链有效期:测试桶直链公共可读(无签名);生产桶读策略未定,前端不得缓存直链。

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

场景 调用方法 说明
✅ 认领人上传 POST /admin/house/assignments/requirements/{id}/receipts,multipart: file=@... 该需求的当前认领人上传,返回 200
✅ 房务查列表 GET /admin/house/assignments/requirements/{id}/receipts 返回 200 + 全部回执
✅ 组长查列表 同上(house_keeper_lead 身份) 无限制,200 返回
❌ 非认领人上传(含 SUPER_ADMIN) — 返回 808110,不落库;超管在本端点不豁免认领归属校验
❌ 未认领需求(PENDING_CLAIM)上传 — 返回 808186(先过状态闸口)
❌ 定制师查列表 — 返回 808090
❌ 缺 file 分片 空 multipart 或无 file 字段 返回 808184

五、数据库行为

无变更、无 Flyway。house_finalize_receipt 表与逻辑保留;认领人校验在内存判断,无新增存储。


六、边界行为

场景 行为
认领人上传 返回 200,回执入库入 OSS
非认领人上传(含 SUPER_ADMIN) 返回 808110,无新行
转单后原人上传 返回 808110(新人成认领人,原人失去权限)
PENDING_CLAIM 需求上传 返回 808186(状态闸口先于认领校验)
组长列表查询 返回 200,全列表
定制师列表查询 返回 808090,无数据
缺 file 分片 / 0 字节 file 分片 返回 808184(HTTP 200、code 业务码,5 种原因文案)

六.6、修改前后对比

维度 改前 改后
非认领人上传(含超管) 返回 200,入库 返回 808110
缺 file 分片 HTTP 500、ERROR 日志 HTTP 200、code 808184,仅 WARN 日志
定制师查列表 返回 200 + 列表 返回 808090

六.7、影响评估

  • 兼容性:hl-ui 回执上传与列表操作收新错误码(808090/808091/808110/808186/808184);需处理新文案提示。
  • 前端要动的:
    • 上传失败按错误码区分:「权限不足」(808090/808091)、「非本人(含超管)」(808110)、「需求未认领」(808186)、「文件」(808184,5 种原因文案,需在 message 里判断具体原因而非只判 code)。
    • 定制师等非房务角色不再能查回执列表,改改导航或隐藏入口。
  • 数据影响:无;仅加校验,不改历史回执。
  • 其它服务:hl-mp-service、fleet 无直接调用。

七、不影响范围

  • 房务订单详情页回执展示逻辑(虽然定制师不再能查全列表,已登录进详情页的现有回执链接仍有效)。
  • 回执删除接口(无,但实体带 @TableLogic 支持软删)。
  • 其他配房写操作(转单、释放、分房等),无改动。

八、测试环境已验证

部署:测试环境 order-v3 1f65d7894(含 e2313790b)。网关 api.test.1814.love:9443。

# 场景 实测结果
1 认领人上传 code 200,新行 uploader_id = 认领人;已软删清理
2 非认领人上传 code 808110,无新行
3 PENDING_CLAIM 需求上传 code 808186
4 SUPER_ADMIN 对他人认领的需求上传 code 808110(不豁免)
5 缺 file 分片(multipart 只带无关字段)×2 HTTP 200 + {"code":808184,"message":"回执上传失败:上传文件为空或缺少 file 分片"}
6 0 字节 file 分片 同 #5,同码同文案
7 房务(认领人本人)查列表 code 200,全部回执
8 定制师 / VEHICLE_MANAGER 查列表 code 808090,无数据
9 house_keeper_lead / 非认领 ROOM_MANAGER / SUPER_ADMIN 查列表 code 200,全部回执

#5、#6 场景 order-v3 日志对应 3 条 WARN Business error [order.808184],无 Unexpected error ERROR 行。


十、相关文档

  • Issue:wx/HL#8388
  • PR:wx/HL#8399(808184 补 {0} 占位追加)
  • 相关单号:#8386(认领人校验,超管在该单有豁免,口径与本单相反)、#8390(读权限门同配方)

关联 / 联系人

联系人

  • 后端负责人: @wx