PR #7065 合入 dev-v3(合并提交 f37b6ee0f),2026-09-04 部署测试环境 并经真实网关鉴权实测 AC-2/AC-3/AC-4/AC-5/AC-9。 4 个接口的副作用与取值口径变更,路径/入参/出参结构全部不变: - PUT /v3/admin/group-batch/:groupBatchId/staff 导游位配 GUIDE 也置 guide_ready - POST /v3/admin/order/:id/staff GUIDE 也写 guide_status 与 GUIDE_DONE - DELETE /v3/admin/order/:id/staff/:staffAssignmentId 按导游位整组计数,不再误置空 - GET /v3/admin/order/:id/print-itinerary 导游栏 GUIDE 优先、缺位回退 LEADER 顺带修一处更深的缺陷:ready 回填此前用产品侧 batchId 打 order_group_batch 主键, rows=0 只 WARN 不抛,改前不论配 GUIDE 还是 LEADER,guide_ready 从未被置位过。 frontend_status=not_required:路径、入参、出参结构均未变,前端无需改动。
这个提交包含在:
@@ -0,0 +1,537 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "7063"
|
||||||
|
title: "团期导游位下游按配置位归组,GUIDE 与 LEADER 一视同仁"
|
||||||
|
consumer: "admin"
|
||||||
|
author: "jw(GIT)"
|
||||||
|
change_type: "修改接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "verified"
|
||||||
|
frontend_status: "not_required"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: ""
|
||||||
|
status_note: "PR #7065 已合入 dev-v3(合并提交 f37b6ee0f);2026-09-04 部署测试环境并经网关实测 AC-2/AC-3/AC-4/AC-5/AC-9。第 2 波配置位字典化未做"
|
||||||
|
updated_at: "2026-09-04"
|
||||||
|
base: "dev-v3"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 团期人员配置: 导游位下游判定由单一角色改为按配置位归组
|
||||||
|
|
||||||
|
> **服务**: hl-order-service-v3
|
||||||
|
> **PR**: #7065 | **Issue**: #7063 | **合并提交**: `f37b6ee0f`
|
||||||
|
> **影响范围**: 管理后台「团期详情 → 配置导游/摄影」、「订单详情 → 人员」、行程单打印
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 关键变化
|
||||||
|
|
||||||
|
**「导游位并收导游与领队」这条裁决此前只落到了候选列表一层,保存之后的下游仍只认单一角色。**
|
||||||
|
|
||||||
|
结果是配置人怎么选都会踩一边:
|
||||||
|
|
||||||
|
| 存成 | 丢什么 |
|
||||||
|
|---|---|
|
||||||
|
| `GUIDE` | `guide_ready` 不置位、`guide_status` 不写、`GUIDE_DONE` 流水不写、订单资源就绪闸门推不动 |
|
||||||
|
| `LEADER` | 行程单「导游」栏为空 |
|
||||||
|
|
||||||
|
**本机实测还暴露了第二处更深的缺陷**:团期人员配置保存时,`ready` 回填用的是**产品侧 batchId**,
|
||||||
|
而 `order_group_batch` 的 ready 列按**主键**更新,两者不是同一个 ID 空间。
|
||||||
|
Mapper `rows=0` 只打 WARN 不抛,所以这个洞一直没被发现——
|
||||||
|
**改前不论配 GUIDE 还是 LEADER,`guide_ready` / `photographer_ready` 从来就没被置位过。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、背景
|
||||||
|
|
||||||
|
人员类型 `staff_type` 在服务人员管理里是维护好的字典,团期现场谁带团由业务按实际安排:
|
||||||
|
有的团派导游,有的团派领队,也有两人都上。2026-09-02 已裁决「导游位并收 GUIDE 与 LEADER,
|
||||||
|
服务端不替业务做取舍」,本次把这条裁决贯彻到保存之后的全部下游链路。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、变更接口清单
|
||||||
|
|
||||||
|
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||||
|
|---|------|------|------|----------|------|
|
||||||
|
| 1 | 全量保存团期人员配置 | PUT | `/v3/admin/group-batch/:groupBatchId/staff` | **副作用变更** | 导游位配 `GUIDE` 也置 `guide_ready`;并修正 ready 回填的 ID 空间 |
|
||||||
|
| 2 | 订单新增人员 | POST | `/v3/admin/order/:id/staff` | **副作用变更** | `staffRole=GUIDE` 也写 `guide_status` 与 `GUIDE_DONE` 流水 |
|
||||||
|
| 3 | 订单删除人员 | DELETE | `/v3/admin/order/:id/staff/:staffAssignmentId` | **副作用变更** | 计数按导游位整组,删其一不再误置空 `guide_status` |
|
||||||
|
| 4 | 打印行程单 | GET | `/v3/admin/order/:id/print-itinerary` | **出参取值口径变更** | 导游栏 `GUIDE` 优先、缺位回退 `LEADER` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、接口详情
|
||||||
|
|
||||||
|
### 1. 全量保存团期人员配置 `PUT /v3/admin/group-batch/:groupBatchId/staff`
|
||||||
|
|
||||||
|
**VO**: `BatchStaffConfigReqVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
团期详情「配置导游 / 配置摄影」弹窗点保存时调用。全量覆盖语义:传入列表即为最终配置。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| `groupBatchId` | Path | Long | ✅ | — | **产品侧团期 batchId**,非 `order_group_batch` 主键 |
|
||||||
|
| `staffList` | Body | Array | ❌ | 传空则清空 | 人员配置列表,全量覆盖 |
|
||||||
|
| `staffList[].staffId` | Body | Long | ✅ | — | 资源域人员 ID |
|
||||||
|
| `staffList[].staffRole` | Body | String | ✅ | `LEADER` `GUIDE` `DRIVER` `PHOTOGRAPHER` `OTHER` | 团期角色 |
|
||||||
|
| `staffList[].sortOrder` | Body | Integer | ❌ | 缺省 0 | 展示排序 |
|
||||||
|
|
||||||
|
#### 出参 `Result<BatchStaffConfigRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `staffList` | Array | 落库后的人员快照,**结构未变** |
|
||||||
|
| `affectedOrderCount` | Integer | 扇出到的活跃子订单数,**未变** |
|
||||||
|
|
||||||
|
> **出参结构完全没有变化**,变的是写库之后的副作用。
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"staffList": [
|
||||||
|
{
|
||||||
|
"staffId": 1002,
|
||||||
|
"staffRole": "GUIDE",
|
||||||
|
"sortOrder": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"staffList": [
|
||||||
|
{
|
||||||
|
"staffId": 1002,
|
||||||
|
"staffRole": "GUIDE",
|
||||||
|
"staffName": "李雪梅",
|
||||||
|
"staffPhone": "138****1002",
|
||||||
|
"sortOrder": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"affectedOrderCount": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
`staffList` 传空数组即清空该团期全部人员配置,返回空列表:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"staffList": [],
|
||||||
|
"affectedOrderCount": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
团期不存在时 ready 回填跳过并打 WARN,接口本身仍成功;未携带令牌时:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 401,
|
||||||
|
"message": "缺少有效的 Authorization 头",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 导游位认 `GUIDE` 与 `LEADER` 两种角色,任一有人即置 `guide_ready`
|
||||||
|
- 摄影位只认 `PHOTOGRAPHER`
|
||||||
|
- 同时配了导游和领队时 `markGuideReady` 只调一次,幂等
|
||||||
|
- 团期查不到(未成团 / 已解散)时 ready 回填跳过,不抛异常
|
||||||
|
- `DRIVER` 不参与任何配置位判定,由车务派车投影产生
|
||||||
|
|
||||||
|
### 2. 订单新增人员 `POST /v3/admin/order/:id/staff`
|
||||||
|
|
||||||
|
**VO**: `StaffAssignReqVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
订单详情「人员」区手工新增一名服务人员时调用。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| `id` | Path | Long | ✅ | — | 订单 ID |
|
||||||
|
| `staffId` | Body | Long | ✅ | — | 资源域人员 ID |
|
||||||
|
| `staffRole` | Body | String | ✅ | `LEADER` `GUIDE` `DRIVER` `PHOTOGRAPHER` `OTHER` | 团期角色 |
|
||||||
|
|
||||||
|
#### 出参 `Result<StaffAssignmentVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `assignmentId` | Long | 新建行 ID,**未变** |
|
||||||
|
| `staffRole` | String | 角色,**未变** |
|
||||||
|
| `staffPhone` | String | 脱敏手机号,**未变** |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"staffId": 1002,
|
||||||
|
"staffRole": "GUIDE"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"assignmentId": 2095758914858471425,
|
||||||
|
"staffId": 1002,
|
||||||
|
"staffRole": "GUIDE",
|
||||||
|
"staffName": "李雪梅",
|
||||||
|
"staffPhone": "138****1002"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
本接口为写入,无空数据形态;资源域人员查询失败时整批 fail-fast:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 582103,
|
||||||
|
"message": "员工信息查询失败,请稍后重试",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
同一订单同一角色重复添加同一人:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 582101,
|
||||||
|
"message": "该员工已分配此角色到此订单",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- `staffRole=GUIDE` 现在与 `LEADER` 等价地触发 `guide_status=DONE` 与 `GUIDE_DONE` 流水
|
||||||
|
- 流水姓名脱敏为首字符加星号,操作人由 `operatorResolver` 自动带出
|
||||||
|
- 写完状态后触发 `maybeAdvanceToConfirm`,尝试推进订单资源就绪
|
||||||
|
- `DRIVER` 与 `OTHER` 不落任何 staff 状态列
|
||||||
|
- 团期来源行(`source=GROUP_BATCH`)不允许在订单侧增删改
|
||||||
|
|
||||||
|
### 3. 订单删除人员 `DELETE /v3/admin/order/:id/staff/:staffAssignmentId`
|
||||||
|
|
||||||
|
**VO**: `StaffAssignmentVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
订单详情「人员」区移除一名手工添加的服务人员。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| `id` | Path | Long | ✅ | — | 订单 ID |
|
||||||
|
| `staffAssignmentId` | Path | Long | ✅ | — | 人员配置行 ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<Void>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `data` | Null | 无返回体,**未变** |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```http
|
||||||
|
DELETE /v3/admin/order/990706300101/staff/2095758914858471425
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
行不存在或不属于该订单:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 582102,
|
||||||
|
"message": "员工分配记录不存在",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
团期共享行不可在订单侧删除:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 582109,
|
||||||
|
"message": "团期共享员工不可在订单侧增删改,请到团期配置页操作",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 删除后按**导游位整组**重新计数,而不是只数被删的那个角色
|
||||||
|
- 导游位同时有导游和领队时,删掉其一 `guide_status` 保持 `DONE`
|
||||||
|
- 整组归零时才把 `guide_status` 置空,且不写状态流水
|
||||||
|
- 摄影位口径不变,仍只数 `PHOTOGRAPHER`
|
||||||
|
|
||||||
|
### 4. 打印行程单 `GET /v3/admin/order/:id/print-itinerary`
|
||||||
|
|
||||||
|
**VO**: `PrintItineraryRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
订单详情点「打印行程单」,抬头区展示司机 / 导游 / 领队的姓名与电话。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| `id` | Path | Long | ✅ | — | 订单 ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<PrintItineraryRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `guideName` | String | 导游姓名。**取值口径变更**:导游位内 `GUIDE` 优先,缺位回退 `LEADER` |
|
||||||
|
| `guidePhone` | String | 导游电话,同上口径 |
|
||||||
|
| `leaderName` | String | 领队姓名,仍只取 `LEADER` 行,**未变** |
|
||||||
|
| `leaderPhone` | String | 领队电话,**未变** |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /v3/admin/order/990706300101/print-itinerary
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
导游位只配了领队时,导游栏回退取到领队:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"header": {
|
||||||
|
"guideName": "刘大山",
|
||||||
|
"guidePhone": "13800001005",
|
||||||
|
"leaderName": "刘大山",
|
||||||
|
"leaderPhone": "13800001005"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
导游位无人时四个字段均为 null,接口仍成功:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"header": {
|
||||||
|
"guideName": null,
|
||||||
|
"guidePhone": null,
|
||||||
|
"leaderName": null,
|
||||||
|
"leaderPhone": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
非本人名下订单且无数据权限:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 581008,
|
||||||
|
"message": "无权查看此订单",
|
||||||
|
"success": false,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 只读接口,不产生任何写入
|
||||||
|
- 导游位同时有导游和领队时,导游栏取导游,不取领队
|
||||||
|
- `leaderName` 与 `leaderPhone` 语义不变,仍是领队本身
|
||||||
|
- 导游与领队是同一人时两栏显示同一姓名,属预期
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、契约约束与正确调用方式
|
||||||
|
|
||||||
|
- **导游位的角色集合是 `GUIDE` 与 `LEADER` 两个**,前端配置弹窗可以把两类人员一起列出来,服务端不做取舍。
|
||||||
|
- **`guideName` 不再等价于「`staffRole=GUIDE` 那一行」**,它是「导游位上的人」。要精确区分导游与领队请分别读 `guideName` 与 `leaderName`。
|
||||||
|
- **`groupBatchId` 在人员配置接口里是产品侧 batchId**,不是 `order_group_batch` 主键,两者不可互换。
|
||||||
|
- 判断「导游是否配齐」请读团期的 `guide_ready` 或订单的 `guide_status`,不要自行按角色字符串比对。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、数据库行为
|
||||||
|
|
||||||
|
无 DDL、无迁移、无新增列。写入行为的变化:
|
||||||
|
|
||||||
|
| 表 | 列 | 变化 |
|
||||||
|
|---|---|---|
|
||||||
|
| `order_group_batch` | `guide_ready` | 改前因 ID 空间用错**从未被置位**;改后按主键正确置 true |
|
||||||
|
| `order_group_batch` | `photographer_ready` | 同上 |
|
||||||
|
| `order_main` | `guide_status` | `staffRole=GUIDE` 的行现在也会写 `DONE`;删除时按导游位整组判空 |
|
||||||
|
| `order_status_log` | — | `staffRole=GUIDE` 现在也会产生一条 `GUIDE_DONE` 数据流水 |
|
||||||
|
| `order_batch_staff` / `order_staff_assignment` | — | 结构与写入内容均**未变** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、边界行为
|
||||||
|
|
||||||
|
- 导游位配 `GUIDE` → `guide_ready=true`
|
||||||
|
- 导游位配 `LEADER` → `guide_ready=true`
|
||||||
|
- 导游位同时配两者 → `markGuideReady` 只调一次
|
||||||
|
- 团期查不到 → ready 回填跳过并 WARN,接口不报错
|
||||||
|
- 导游位删剩一人 → `guide_status` 保持 `DONE`
|
||||||
|
- 导游位清空 → `guide_status` 置空且不写流水
|
||||||
|
- 行程单导游位只有领队 → 导游栏取领队
|
||||||
|
|
||||||
|
## 六.5、枚举 / 数据字典
|
||||||
|
|
||||||
|
本次无新增枚举。`staffRole` 取值域与 `SettlementStaffRoleEnum` 保持一致,未扩展。
|
||||||
|
|
||||||
|
## 六.6、修改前后对比
|
||||||
|
|
||||||
|
| 项 | 变更前 | 变更后 |
|
||||||
|
|---|---|---|
|
||||||
|
| `guide_ready` 回填 | **从未生效**(用产品侧 batchId 打主键,rows=0 只 WARN) | 反查真实主键后正确置位 |
|
||||||
|
| 导游位判定 | 只认 `LEADER` | 认 `GUIDE` 与 `LEADER` |
|
||||||
|
| `guide_status` 写入 | `GUIDE` 行不写 | `GUIDE` 行同样写 |
|
||||||
|
| `GUIDE_DONE` 流水 | `GUIDE` 行不写 | `GUIDE` 行同样写 |
|
||||||
|
| 删除后计数 | 只数被删角色,可能误置空 | 按导游位整组计数 |
|
||||||
|
| 行程单导游栏 | 只取 `GUIDE` 行,配领队时为空 | `GUIDE` 优先,缺位回退 `LEADER` |
|
||||||
|
| 接口路径 / 入参 / 出参结构 | — | **全部不变** |
|
||||||
|
|
||||||
|
## 六.7、影响评估
|
||||||
|
|
||||||
|
| 维度 | 评估 |
|
||||||
|
|---|---|
|
||||||
|
| 兼容性 | **只放宽不收紧**。原来不触发的现在会触发,存量 `staffRole=LEADER` 的配置行行为与改前完全一致 |
|
||||||
|
| 前端 | **无需改动**。路径、入参、出参结构均未变;行程单导游栏由「可能为空」变为「有值」,是修复不是破坏 |
|
||||||
|
| 数据 | 无 DDL、无迁移、无回填 |
|
||||||
|
| 性能 | 删除路径的计数由单值等值查询改为 `IN` 两值;行程单导游栏由一次点查改为一次整组查询后按序挑选,**查询次数不增** |
|
||||||
|
| 回滚 | `git revert`,单一 PR,无数据侧残留 |
|
||||||
|
| 风险 | 低。`guide_ready` 修复后会让原本推不动的团期开始推进资源就绪闸门,属预期恢复 |
|
||||||
|
|
||||||
|
## 七、不影响范围
|
||||||
|
|
||||||
|
- **零影响**:所有接口的路径、HTTP 方法、入参、出参结构
|
||||||
|
- **零影响**:摄影位口径,仍只收 `PHOTOGRAPHER`
|
||||||
|
- **零影响**:`leaderName` / `leaderPhone` 的语义与取值
|
||||||
|
- **零影响**:`DRIVER` 与 `OTHER` 角色的处理
|
||||||
|
- **零影响**:staff-fees 导游费用录入分流逻辑(裁决 D-2,配在导游位的领队不录导游费用,属预期)
|
||||||
|
- **未新建端点**,未改动任何路径与入参
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、测试环境已验证
|
||||||
|
|
||||||
|
✅ 2026-09-04 于测试环境网关实测,真实鉴权(管理端 `test_admin`,角色定制师)。
|
||||||
|
|
||||||
|
- 网关 `https://api.test.1814.love:9443`,分支 `dev-v3`,合并提交 `f37b6ee0f`
|
||||||
|
- 部署方式:双实例滚动更新(8186 → 8086),各 11s 就绪,零停机
|
||||||
|
- 部署内容经部署面板 `/api/git/backend` 交叉核对:构建时点 `f37b6ee0f` 已是 `dev-v3` 顶端
|
||||||
|
|
||||||
|
| # | 用例 | 期望 | 实测 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | 配 `staffType=GUIDE` 到导游位 | `guide_ready` 置 1 | ✅ 0 → 1(AC-2) |
|
||||||
|
| 2 | 配 `staffType=LEADER` 到导游位 | `guide_ready` 置 1 | ✅ 0 → 1(AC-4) |
|
||||||
|
| 3 | 配摄影师 | `photographer_ready` 置 1 | ✅ 0 → 1(AC-9) |
|
||||||
|
| 4 | 订单侧配 `staffRole=GUIDE` | `guide_status=DONE` + `GUIDE_DONE` 流水 | ✅ 流水操作人 `test_admin`,内容脱敏为首字加星 |
|
||||||
|
| 5 | 导游位删剩领队 | `guide_status` 保持 `DONE` | ✅ 未被置空 |
|
||||||
|
| 6 | 行程单,导游位只有领队 | 导游栏取到领队 | ✅ `guideName` 为领队姓名,电话一致 |
|
||||||
|
| 7 | 行程单,导游位两者都有 | 导游栏取导游 | ✅ 导游优先生效 |
|
||||||
|
| 8 | 扇出 | 团期配置扇出到活跃子订单 | ✅ 2 单,`source=GROUP_BATCH` |
|
||||||
|
|
||||||
|
**观察**:部署后双实例持续 running 无重启,服务日志最近 200 行 `ERROR` / `Exception` 命中 **0** 条。
|
||||||
|
日志中可见 `Parameters: 990706300101(Long), GUIDE(String), LEADER(String)`,即按导游位整组计数的查询确已在测试环境执行。
|
||||||
|
|
||||||
|
**本地单测**:`AssignmentServiceTest` 65 例、`GroupBatchStaffConfigServiceTest` 31 例、
|
||||||
|
`AssignmentServiceCallbackDriverTest` 42 例、`OrderServiceTest` 205 例、
|
||||||
|
架构与错误码门禁 51 例,合计 **401 例全过**,其中新增 7 例覆盖本次全部行为变化。
|
||||||
|
|
||||||
|
**测试数据**:测试环境所造数据一律 `T7063-` 前缀,验证后已物理删除,残留合计 0 条。
|
||||||
|
所用 `test_admin` 口令为一次性置换,取到令牌后立即按备份还原,与备份逐字节一致。
|
||||||
|
|
||||||
|
> ⚠️ **一处未做实测**:团期人员配置的扇出链路(`doFanOutForOrder`)**不调用** `syncStaffStatusToOrder`,
|
||||||
|
> 因此经团期配置这条路进来时 `order_main.guide_status` 始终为 null。用例 4 走的是**订单侧**新增人员端点。
|
||||||
|
> 这是先于本次变更就存在的第三处缺口,不在本波范围,已在工单中记录待另议。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、相关历史 PR
|
||||||
|
|
||||||
|
- #7065 本次变更(第 1 波 P1 止血)
|
||||||
|
- #6962(Refs #6950)团期人员配置候选列表——本次修的正是它的下游遗漏
|
||||||
|
- 裁决来源:2026-09-02「导游位并收 GUIDE 与 LEADER,服务端不替业务做取舍」
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、相关文档
|
||||||
|
|
||||||
|
- 团期需求文档:`docs/group/`(dev-v3 分支)
|
||||||
|
- 一期实施拆分详细设计 v1.0 §0.26.4(AC-TD-13~16)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 关联 / 联系人
|
||||||
|
|
||||||
|
- **Issue**: #7063
|
||||||
|
- **PR**: #7065(合并提交 `f37b6ee0f`)
|
||||||
在新工单中引用
屏蔽一个用户