# order-v3 review 跟进:配房工作台 / 询房 URL 重排 + HOUSE swap 多项修复 + 出行人/大交通杂项

> **存放目录**: 二期(v3 `order-v3` 标签)→ `changelogs-v2/2026-05/`
> **服务**: hl-order-service-v3 (8086) + hl-user-service (8081)
> **PR**: #2833 / #2834 / #2835 / #2836 / #2840(hotfix)
> **Issue**: #2821 / #2822 / #2823 / #2824
> **日期**: 2026-05-21
> **影响范围**: 管理端 HOUSE 配房工作台 + HOUSE 询房 + HOUSE 换酒店 + 出行人/大交通若干字段

---

## ⚠️ 关键变化(前端必看)

### 🔴 路径变更(配房工作台 + 询房,5+2=7 个接口)

前端按 `API-SPEC-HOUSE-V1.1.html` 文档对接,**之前 4 个 PR (#2738-2754) 落地的代码路径与文档严重不一致,会全部 404**;本批 PR #2833 已**对齐文档**。前端按文档实现的请直接对接新路径;之前对接到旧路径的,请按下表改 URL:

| 接口 | 旧路径(已废弃) | 新路径(以此为准) |
|------|----------------|-------------------|
| §2.1 配房候选源 | `GET /v3/admin/house/assignments/candidates?requirementId=X` | **`GET /v3/admin/order/hotel-requirements/{rid}/candidates`** (rid 走 PathVariable) |
| §2.2 提交配房 | `POST /v3/admin/house/assignments`(rid 在 body) | **`POST /v3/admin/order/hotel-requirements/{rid}/assignments`**(rid 走 PathVariable;body 不再传 requirementId) |
| §2.3 修改配房 | `PUT /v3/admin/house/assignments/{id}` | **`PUT /v3/admin/order/assignments/{id}`** |
| §2.4 删除配房 | `DELETE /v3/admin/house/assignments/{id}` | **`DELETE /v3/admin/order/assignments/{id}`** |
| §2.5 房间分配 | `POST /v3/admin/house/assignments/{id}/rooms`(POST 写入) | **`GET /v3/admin/order/orders/{orderId}/rooms`**(HTTP 方法 + 路径 + 入参形态全改 — GET 查询语义,按家庭分组返结果) |
| §3.3 询房历史 | `GET /v3/admin/order/inquiry/by-order` | **`GET /v3/admin/order/inquiry?orderId=X`** |
| §3.6 加急 | `POST /v3/admin/order/inquiry/{id}/urgent` | **`POST /v3/admin/order/inquiry/{id}/escalate`** |

§2.5 GET 新 VO `OrderRoomsRespVO`:

```json
{
  "orderId": "string",
  "families": [
    {
      "familyNo": "F1",
      "travelers": [{ "travelerId": "string", "name": "张三", "phoneMasked": "138****5612" }],
      "days": [{ "dayNumber": 1, "rooms": [{ "hotelName": "...", "roomTypeName": "..." }] }]
    }
  ]
}
```

---

## 一、背景

dev-v3 近 3 天(2026-05-18~21)合并 30+ PR / 786 文件 / +74,352 行(出行人 + 大交通 + HOUSE H01-H10 + FIX A-H + 通知中心 internal),全模块工作流 review 检出 10 P0 + 36 P1。本批 4 张 P0/P1 工单(#2821-2824)+ 1 张 hotfix(#2840 Flyway 修)对应 4 张 PR + 1 张 hotfix 全部测试服部署 + Flyway 落库 + admin token round-trip 验证通过。

---

## 二、变更接口清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 配房候选源 | GET | `/v3/admin/order/hotel-requirements/{rid}/candidates` | **路径迁移** | 旧 `/v3/admin/house/assignments/candidates` 废弃 |
| 2 | 提交配房 | POST | `/v3/admin/order/hotel-requirements/{rid}/assignments` | **路径迁移** | rid 改 PathVariable,body 删 requirementId |
| 3 | 修改配房 | PUT | `/v3/admin/order/assignments/{id}` | **路径迁移** | |
| 4 | 删除配房 | DELETE | `/v3/admin/order/assignments/{id}` | **路径迁移** | |
| 5 | 房间分配 | **GET**(原 POST) | `/v3/admin/order/orders/{orderId}/rooms` | **方法+路径全改+新 VO** | 改为查询语义,按家庭分组聚合 |
| 6 | 询房历史 | GET | `/v3/admin/order/inquiry?orderId=X` | **路径迁移** | `/by-order` 后缀去掉 |
| 7 | 询房加急 | POST | `/v3/admin/order/inquiry/{id}/escalate` | **路径迁移** | `/urgent` 改 `/escalate` |
| 8 | 换酒店提交 | POST | `/v3/admin/order/swap-hotel/commit` | **权限校验补全** | 越权返 `808402`(详 §三-1) |
| 9 | 大交通 VO 字段类型 | - | `TransportPlanVO.id / orderId / travelers[].id` | **响应字段类型 Long → String** | 防 JS 精度丢失 |
| 10 | 出行人 internal Feign | GET | `/v3/internal/traveler/list-by-order/{orderId}` | **返回字段补值** | `transportPlanIds` 不再永空,合同/保险拿到真大交通批次 |
| 11 | 出行人错误码 | - | 多接口 | **错误码段位修正** | 见 §三-3 |
| 12 | 大交通 batchReplace | POST | `/v3/admin/order/{id}/transport-plan/batch-replace` | **加幂等 + 分布式锁** | 防重复提交触发全量替换 |

---

## 三、接口详情

### 1. 换酒店模块 (PR #2834)

#### 权限校验补齐(原 TODO)

之前 `POST /v3/admin/order/swap-hotel/commit` 没校验"当前用户是订单 assignee" — 任何房务 token 都能改别人的订单。**已修复,跨用户越权返 `808402`**。

```http
HTTP/1.1 200 OK
{ "code": 808402, "message": "当前用户必须为订单 assignee 才能操作", "success": false }
```

#### 状态机审计正确性

之前 `swap` 业务的状态机 fire 写死 `from=CLAIMING`,审计日志失真。现根据 `house_todo` 表 OPEN `SWAP_HOTEL`/`REFUND` 待办推导真实 from(`EXCEPTION` 或 `CLAIMING`)。**前端 UI 不直接感知,但订单操作日志看 from 字段会更准确**。

#### DRIVER 通知补发(原漏发,业务 BUG)

API-SPEC-HOUSE §5.3 列了 4 个 receiver_type(`OLD_HOTEL / NEW_HOTEL / DRIVER / ORDER_CUSTOMER`),之前代码只发 3 个,**司机收不到换酒店通知**。本 PR 补 DRIVER。

⚠️ DRIVER 实际企微推送需 FLEET `vehicle_plan` 反查 Feign(留尾,后续工单接通),当前发送链路 = 事件落库 + dispatcher noop 占位(不抛错不阻塞)。

#### 新增错误码(API-SPEC-HOUSE §5.3 / §11.6 已同步)

| 错误码 | 说明 |
|--------|------|
| `808404` | 旧酒店 ID 与新酒店 ID 相同 |
| `808405` | 仅 PROCESSING / EXCEPTION 状态可换酒店 |
| `808406` | 换酒店写库失败,请重试 |
| `808407` | 新酒店库存不足 |

---

### 2. 大交通 — Long 字段类型变化 (PR #2836)

`TransportPlanVO` 中以下三个字段以前响应是 JSON Number(可能精度丢失),现统一返字符串:

| VO 字段 | 旧类型 | 新类型 | 示例 |
|---------|--------|--------|------|
| `TransportPlanVO.id` | number | **string** | `"80012345"` |
| `TransportPlanVO.orderId` | number | **string** | `"30099887"` |
| `TransportPlanVO.travelers[].id` | number | **string** | `"40055001"` |

**前端检查**:`Number(id)` / `parseInt(id)` 这类用法需改;直接 `id` 字符串传回后端 / 当 key 用没影响。

---

### 3. 出行人错误码段位修正 (PR #2836)

`docs/order-v3/api/API-SPEC-V5.54.html` 错误码表 5 处更新(以代码为准):

| 章节 | 旧码 | 新码 |
|------|------|------|
| §2.1 列表 | `581100` | `581102` |
| §2.2 批量编辑 9 行错误码表 | 581100-581124 | **581101-581105 / 581110-581114 / 581111 / 581119** |
| §2.3 单个新增 | `581100` → `581102`;补 581115/581116/581118 |
| §2.4 删除 | `581119→581106 / 581120→581107 / 581100→581102` |
| §2.8 智能解析 | `581120-581123` | `581131-581134` |
| §2.9 校验 | `581124` | `581102` |

前端如做了 i18n 映射,请按新码更新 — 否则会命中默认文案。

---

### 4. 出行人 internal Feign `transportPlanIds` 真实化 (PR #2836)

`GET /v3/internal/traveler/list-by-order/{orderId}` 之前 `transportPlanIds` 字段硬编码空数组,合同/保险服务跨服务调用永远拿不到出行人绑定的大交通批次 ID。本 PR 修复,字段返真实值。**前端不直接调 internal,影响合同/保险出参的"出行人.transportPlanIds"字段**。

---

### 5. 大交通 batchReplace 并发保护 (PR #2836)

`POST /v3/admin/order/{id}/transport-plan/batch-replace` 全量替换接口加 `@Idempotent`(3s)+ `@Lock4j`(30s)— 短时间重复提交会拒绝,前端无需改但可减少重复提交风险。

---

### 6. 通知中心 internal 套件规范(后端内部) (PR #2835)

`/internal/notification/dispatch` / `/publish` 加幂等 + dispatch 返回类型从 void 改 `DispatchResult { success, channelsTriggered, errorMessage }`。**前端不调 internal,无影响**。

---

### 7. order_todo 唯一索引 (PR #2836 / hotfix #2840)

DB 加 `(order_id, todo_type, sequence, deleted_marker)` 唯一索引,防并发触发重复紧急待办。前端无感。

> hotfix #2840:V20260521_004 generated column 用 `UNIX_TIMESTAMP` 触发 MySQL 8 `ERROR 3763 disallowed function`,已改 `COALESCE(deleted_at, '1970-01-01')`(deterministic)。

---

## 四、测试服验证状态

| 服务 | 部署 commit | uptime | Flyway | admin round-trip |
|------|------------|--------|--------|------------------|
| hl-user-service | dev-v3 含 #2834/#2835 | 已重启 | V20260521_007 success=1 17:49 | ✅ |
| hl-order-service-v3 | dev-v3 含 #2833/#2836/#2840 | 18:12 重启 | V20260521_004 success=1 18:12 | ✅ §3.3 / §3.6 / §2.5 / §2.1 全 200/合理 400 |

唯一索引 `uk_todo_order_type_seq_active` 已在 `hl_order_service_v3.order_todo` 表生效。

---

## 五、留尾(后续 v3 工单)

- **HOUSE-SWAP DRIVER 通知** wework 真值切换 → 需 FLEET `vehicle_plan` 反查 Feign 工单
- **HOUSE-FIX-A 候选源数据真实化**(`loadProductPool`)→ 需 H04 完整接通 `ProductV2FeignClient`
- **`HouseInventoryCheckedEvent` 消费方**(`H09` MQ 桥接 PR)
- **TravelerErrorCode 段位整体迁移代码常量**(大版本可决议)
- **`operationLogMapper` 收敛** 到 `HotelOperationLogService`(待该 Service 出现)

---

## 六、关联

- 工单: #2821 / #2822 / #2823 / #2824(全部 closed)
- PR: #2833 / #2834 / #2835 / #2836 / #2840(全部 merged into dev-v3)
- Review 来源: Claude /@cr 7 个 agent 并发对照 `docs/order-v3/` SRS+API+DB+Detail
