changelog-filename-gate / validate (push) Failing after 1s
88caa74 房务接口审计批次:#8385 订房计划守卫/#8386 住宿驳回加门+删车务口/#8387 旧房间分配三口下线/#8388 回执认领校验+读门/#8389 家庭维度写口下线/#8390 16 读端点补门+菜单撤授。前端按钮后端字段驱动+错误码拦截器透 message+被删端点零调用/入口仅房务角色页,6 条均 not_required;#8387/#8389 后端已标,余 4 条翻 not_required,owner/ref 留空,status_note 引号内追充实证。
332 行
12 KiB
Markdown
332 行
12 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "8386"
|
||
title: "住宿需求驳回:加房务角色门与认领人校验;车务驳回接口下线"
|
||
consumer: "admin"
|
||
author: "wx(GIT)"
|
||
change_type: "删除接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "not_required"
|
||
frontend_owner: ""
|
||
frontend_ref: ""
|
||
target_release: ""
|
||
verified_at: ""
|
||
status_note: "住宿需求供应方驳回新增房务角色门(808090/808091)与认领人校验(808110/808116,超管豁免);车务驳回接口删除,调用返回 HTTP 200 + code 404。已在测试环境网关实测各角色分支与已删除端点响应。前端实证(mmg 2026-09-27):车务驳回口零调用;住宿驳回按钮 enabled/disabledReason 由后端 canRejectRequirement 驱动,新码拦截器透 message,零改动 not_required。"
|
||
updated_at: "2026-09-26"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# order-v3:住宿需求驳回守卫加固与车务驳回下线(管理后台)
|
||
|
||
**服务**: hl-order-service-v3
|
||
**PR**: #8397
|
||
**Issue**: #8386
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化
|
||
|
||
1. **住宿需求供应方驳回** `POST /v3/admin/order/{id}/hotel-requirement/supplier-reject`:
|
||
- 新增房务角色门:`@HouseWriteGuarded`,非房务角色返回 **808090**,房务组长返回 **808091**。
|
||
- 新增认领人校验:需求必须被当前操作人认领,否则返回 **808110**(非本人)/ **808116**(未认领,仅超管可驳)。
|
||
- 超管可绕过认领限制(跳过本人限制,但仍受角色门约束)。
|
||
|
||
2. **车务需求供应方驳回** `POST /v3/admin/order/{id}/vehicle-requirement/supplier-reject` **已下线**:
|
||
- 端点删除,调用返回 404。
|
||
- hl-ui 全部远程 ref 零调用,车务侧无此功能。
|
||
|
||
---
|
||
|
||
## 一、背景
|
||
|
||
### 住宿驳回
|
||
|
||
API-SPEC §2.8 与 CHANGELOG v6.3.8 均明文「新增房务/超管可用的住宿需求驳回端点」,但实现漏了角色门和认领人校验:
|
||
- 任意 ADMIN token 的后台账号(包括车控、定制师)都能驳回任意订单的需求。
|
||
- 测试服已实证车控账号(VEHICLE_MANAGER)成功打回住宿需求两次。
|
||
- 同类操作(转单、释放、提交配房)都带认领人校验,驳回不带属于遗漏。
|
||
- 打回副作用重:需求行终态失活、flow 回退、定制师开返工待办 + 站内信。
|
||
|
||
### 车务驳回
|
||
|
||
车务从无"抢单 → 认领"的流程,用车需求也从不写入抢单人:整个车务侧"我的接单"接口(#8373)因此下线。供应方驳回同样是"假接口"——没有实际用途、hl-ui 零调用。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|------|------|------|----------|------|
|
||
| 1 | 住宿需求供应方驳回 | POST | `/v3/admin/order/{id}/hotel-requirement/supplier-reject` | 修改接口 | 新增角色门(808090/808091)与认领人校验(808110/808116) |
|
||
| 2 | 车务需求供应方驳回 | POST | `/v3/admin/order/{id}/vehicle-requirement/supplier-reject` | 删除接口 | 端点已删除,调用返回 404 |
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
### 1. 住宿需求供应方驳回 `POST /v3/admin/order/{id}/hotel-requirement/supplier-reject`
|
||
|
||
**VO**: `RejectReqVO → Result<Void>`
|
||
|
||
#### 使用场景
|
||
|
||
房务(ROOM_MANAGER)或超管在配房面板「驳回需求」,把已认领的住宿需求打回给定制师,触发返工。仅认领人或超管可操作;非房务角色返回权限错误。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| id | Path | Long | 是 | — | 订单 ID |
|
||
| returnRemark | Body | String | 是 | `@NotBlank`,≤500 字 | 驳回原因,不能为空 |
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| — | null | 成功返回 null |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
POST /v3/admin/order/770145/hotel-requirement/supplier-reject HTTP/1.1
|
||
Host: api.test.1814.love:9443
|
||
Authorization: Bearer <room_manager token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"returnRemark": "房型不符,请调整"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
**成功**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
**失败(非认领人)**:
|
||
|
||
```json
|
||
{
|
||
"code": 808110,
|
||
"message": "需求不属于当前用户",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
**失败(无房务权限)**:
|
||
|
||
```json
|
||
{
|
||
"code": 808090,
|
||
"message": "未登录或非房务角色,无权操作",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
- `returnRemark` 缺失或为空白:`@Valid` 校验不通过,HTTP 200 + `code: 400` + 具体字段错误信息(不进入业务逻辑)。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "打回/驳回备注不能为空",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
**校验顺序**(前一道不过不会走到后一道):写门(808090/808091)→ 参数校验(400)→ 582031(无生效需求行)→ 582083(需求状态不允许此操作)→ 认领人校验(808116/808110,超管豁免)→ 582086(已有生效配房不可驳回)→ 582083(并发 CAS 失败)。
|
||
|
||
**其他错误码**:
|
||
- **808090**:未登录或非房务角色,无权操作。
|
||
- **808091**:房务组长为只读监督角色,无权执行该操作。
|
||
- **582031**:订单无有效需求行。
|
||
- **582083**:需求状态不允许此操作,请检查当前状态(团期订单只放行 PENDING/PROCESSING;非团期订单放行 PENDING/PROCESSING/PENDING_REVIEW;并发 CAS 失败同样报此码)。
|
||
- **808116**:订单未抢单, 请先抢单再配房(需求未被认领,非超管不可驳)。
|
||
- **808110**:需求不属于当前用户(已被他人认领,非超管不可驳)。
|
||
- **582086**:该需求已有配房记录, 不能驳回, 请走替换/修改配房。
|
||
|
||
#### 业务边界
|
||
|
||
- **认领限制**:需求 `claimer_id` 必须等于当前操作人,或当前角色为 SUPER_ADMIN。房务组长(house_keeper_lead)无法驳回,返回 808091。
|
||
- **超管豁免**:SUPER_ADMIN 绕过认领人限制(不受 808110/808116 约束),但仍受角色门约束(必须先过 `@HouseWriteGuarded`)。
|
||
- **副作用**:驳回目标状态按订单类型区分——核心/定制订单需求驳回后进 `REJECTED_TO_CONSULTANT`,团期订单进 `REJECTED_TO_ADMIN`;触发返工待办与站内信。
|
||
- **转单后生效**:若需求在驳回前被转单给其他房务,原持有人的驳回请求返回 808110(当前 `claimer_id` 已是新认领人)。
|
||
- **已有配房记录不可驳回**:需求已生成生效配房(`hasActiveHotelAssignmentsByOrder` 为真)时返回 582086,须走替换/修改配房而非驳回。
|
||
|
||
---
|
||
|
||
### 2. 车务需求供应方驳回 `POST /v3/admin/order/{id}/vehicle-requirement/supplier-reject`
|
||
|
||
**VO**: `已删除`
|
||
|
||
**状态:已删除**
|
||
|
||
#### 使用场景
|
||
|
||
该接口已删除,不可用。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| — | — | — | — | — | 已删除 |
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| — | — | 已删除 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
POST /v3/admin/order/770145/vehicle-requirement/supplier-reject HTTP/1.1
|
||
Host: api.test.1814.love:9443
|
||
Authorization: Bearer <admin token>
|
||
Content-Type: application/json
|
||
|
||
{}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
HTTP 状态码 **200**(非 404),业务错误码 404:
|
||
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "接口不存在: POST /v3/admin/order/770145/vehicle-requirement/supplier-reject",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
不适用(路由已删)。前端应只判 `code`,不依赖 HTTP 状态码。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "接口不存在: POST /v3/admin/order/770145/vehicle-requirement/supplier-reject",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 接口已删除,路由不存在;调用返回 HTTP 200 + `code: 404`(不是 HTTP 404),前端只判 `code`。
|
||
- hl-ui 全部远程 ref 零调用;测试网关 nginx 日志 2026-09-12~09-26 窗口内该路径 19 次调用全部来自脚本(Python-urllib / curl / 空 UA),零浏览器 UA。
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式
|
||
|
||
| 场景 | 调用方法 | 说明 |
|
||
|------|---------|------|
|
||
| ✅ 认领人驳回 | `POST /v3/admin/order/{orderId}/hotel-requirement/supplier-reject` | 该订单的认领房务直接调,返回 200;定制师开返工待办 |
|
||
| ✅ 超管代驳 | 同上(SUPER_ADMIN 身份)| 超管跳过认领限制,但仍需房务角色权限 |
|
||
| ✅ 订单详情按钮 | 查看 `actions.canRejectRequirement` | enabled 取决于 write 权限 + 认领人判定;false 时显示 disabledReason |
|
||
| ❌ 非认领人驳回 | — | 返回 808110,需求 status 不变 |
|
||
| ❌ 车务驳回 | — | 端点已删除,返回 HTTP 200 + code 404 |
|
||
| ❌ 定制师驳回 | — | 返回 808090 |
|
||
|
||
---
|
||
|
||
## 五、数据库行为
|
||
|
||
无表结构变更、无 Flyway。
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
| 场景 | 行为 |
|
||
|---|---|
|
||
| 认领人驳回 | 返回 200,需求进 REJECTED_TO_CONSULTANT 或 REJECTED_TO_ADMIN |
|
||
| 非认领人驳回 | 返回 808110,需求 status 不变 |
|
||
| 未认领需求 + 房务驳回 | 返回 808116,非超管不可驳 |
|
||
| 超管驳回未认领 | 返回 200,驳回处理 |
|
||
| 转单中驳回(原认领人) | 返回 808110(新认领人接管后视为他人所有) |
|
||
| 车务驳回 | 返回 HTTP 200 + code 404,无新增副作用 |
|
||
|
||
## 六.6、修改前后对比
|
||
|
||
| 维度 | 改前 | 改后 |
|
||
|---|---|---|
|
||
| 车控账号调住宿驳回 | 返回 200,需求打回 | 返回 808090,需求 status 不变 |
|
||
| 非认领人驳回 | 返回 200,需求打回 | 返回 808110,status 不变 |
|
||
| 未认领需求 | 任意房务可驳 | 仅超管可驳,返回 808116 |
|
||
| 车务驳回 | 路由存在,可调用 | 路由删除,返回 HTTP 200 + code 404 |
|
||
|
||
## 六.7、影响评估
|
||
|
||
- **兼容性**:hl-ui 房务驳回按钮的 `enabled` 判定由 `canRejectRequirement` 决定(已包含写权限与认领人两个维度),驳回失败收 808090/808091/808110/808116 四个新码。
|
||
- **前端要动的**:
|
||
- 驳回按钮的 disabled 文案区分「无房务权限」(808090/808091)与「非本人认领」(808110)。
|
||
- 处理 808116「未认领,仅超管可驳」的提示(普通房务不应遇到,因为按钮本身 disabled)。
|
||
- 车务不再有驳回端点,移除 vehicle-requirement/supplier-reject 调用。
|
||
- **数据影响**:无;仅加守卫,不改历史。
|
||
- **其它服务**:fleet 的 `rejectVehicleRequirementFromFleet` 独立存在,本单不动。
|
||
|
||
---
|
||
|
||
## 七、不影响范围
|
||
|
||
- 团期管理员的 dispatch/reject(走独立 `GroupBatchPermissionGuard`),无改动。
|
||
- 转单、释放、提交配房等其他配房写操作,无改动。
|
||
- 车务用车需求的其他接口(提交、放行、派单),无改动。
|
||
- 整团认领释放等认领链路,无改动。
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
部署:测试环境 order-v3 `1f65d7894`(含 e2313790b)。网关 `api.test.1814.love:9443`。
|
||
|
||
| # | 场景 | 实测结果 |
|
||
|---|---|---|
|
||
| 1 | VEHICLE_MANAGER 调住宿 supplier-reject | code 808090,需求状态不变 |
|
||
| 2 | house_keeper_lead 调住宿 supplier-reject | code 808091,需求状态不变 |
|
||
| 3 | 非认领 ROOM_MANAGER(需求已被他人认领)驳回 | code 808110,需求状态不变 |
|
||
| 4 | ROOM_MANAGER 对未认领需求驳回 | code 808116,需求状态不变 |
|
||
| 5 | 超管打回 / 认领人打回自己认领的需求 | 成功,核心订单需求进 REJECTED_TO_CONSULTANT |
|
||
| 6 | 车务 `POST /v3/admin/order/{id}/vehicle-requirement/supplier-reject` | HTTP 200 + code 404「接口不存在: POST <URL>」 |
|
||
|
||
调用来源:测试网关 nginx 日志 2026-09-12~09-26 窗口内车务 supplier-reject 共 19 次,全部是脚本(Python-urllib / curl / 空 UA),零浏览器 UA;hl-ui 全部远程 ref 零调用。
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- Issue:https://git.1814.love/wx/HL/issues/8386
|
||
- PR:https://git.1814.love/wx/HL/pulls/8397
|
||
- 相关单号:#8373(车务我的接单下线)、#8388(回执认领人校验同口径)
|
||
- API-SPEC:`docs/order-v3/api/API-SPEC-HOUSE-V1.1.html` §2.8
|
||
|
||
---
|
||
|
||
## 关联 / 联系人
|
||
|
||
### 联系人
|
||
|
||
- **后端负责人**: @wx
|