文件
hl-api-changelog/changelogs-v2/2026-09/07_7080_团期人员配置扇出补同步订单侧staff状态-修改接口-管理后台.md
T
2026-09-07 15:56:09 +08:00

308 行
13 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "7080"
title: "团期人员配置扇出补同步订单侧 staff 状态,guide_status 不再恒为 NULL"
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: "2026-09-07"
status_note: "PR #7115 合入 dev-v3(468df6fa7),2026-09-07 测试服网关实测通过(配导游后 guide 芯片 TODO(0/55)→DONE(55/55),清空回落)。出参结构一个字段没变,只改扇出副作用(guide_status/photographer_status 不再恒 NULL、补 DONE 流水、触发就绪闸门)。前端 mmg 已实查为 not_required:全仓无 guide_status/photographer_status 消费点,也无「团期配过但订单侧未配置」的兼容逻辑或提示文案可撤,无需改码。"
updated_at: "2026-09-07"
base: "dev-v3"
---
# 团期: 人员配置扇出补同步订单侧 staff 状态
> **服务**: hl-order-service-v3
> **PR**: #7115
> **Issue**: #7080
> **日期**: 2026-09-04
> **影响范围**: 管理后台团期人员配置保存后,团内各子订单的导游/摄影资源状态与时间线
---
## ⚠️ 关键变化
**出参结构一个字段没变,变的是写库之后的副作用。**
改前:经「团期详情 → 配置导游/摄影」配的人,扇出只写 `order_staff_assignment` 表,
`order_main.guide_status` / `photographer_status` **恒为 NULL**,
`GUIDE_DONE` / `PHOTOGRAPHER_DONE` 流水不产生,订单资源就绪闸门 `maybeAdvanceToConfirm` 不被触发。
只有走订单侧「订单详情 → 人员 → 新增」才会写这些。
改后:扇出末尾按配置位全量同步订单侧状态,两条路口径一致。
**前端要注意的是**:以前拿到 `guide_status=null` 不代表没配人(可能是团期配的),
现在 null 就是真的没人。原先若有「团期配过但订单侧显示未配置」的兼容逻辑或提示文案,可以撤掉。
---
## 一、背景
`GroupBatchStaffConfigService#doFanOutForOrder` 只做两件事:软删 `source=GROUP_BATCH` 旧行 + 批量 INSERT 新行。
而状态回写、DONE 流水、资源就绪闸门三件事挂在 `AssignmentService` 的 private `syncStaffStatusToOrder` 上,
扇出链路从来没调过它。
| 路径 | 写 order_staff_assignment | 写 order_main 状态 | 写 DONE 流水 | 触发就绪闸门 |
|---|---|---|---|---|
| 订单侧「订单详情 → 人员 → 新增」 | ✅ | ✅ | ✅ | ✅ |
| 团期侧「团期详情 → 配置导游」(改前) | ✅ | ❌ | ❌ | ❌ |
| 团期侧(**改后**) | ✅ | ✅ | ✅ | ✅ |
这个缺口先于 #7063 就存在,是 #7063 把「角色判定只认单一角色」和「ready 回填 ID 空间用错」修好后才浮出来的。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 全量保存团期人员配置 | PUT | `/v3/admin/group-batch/:groupBatchId/staff` | 副作用变更 | 扇出后逐子订单同步 `guide_status`/`photographer_status` + DONE 流水 + 就绪闸门 |
---
## 三、接口详情
### 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 | 扇出到的活跃子订单数,**未变** |
> 本次**不改任何出参字段**。要观察效果请查子订单的 `guide_status` / `photographer_status` 与订单时间线。
#### 请求示例
```json
{
"staffList": [
{ "staffId": 1002, "staffRole": "GUIDE", "sortOrder": 0 }
]
}
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"staffList": [
{ "staffId": 1002, "staffRole": "GUIDE", "staffName": "李雪梅", "sortOrder": 0 }
],
"affectedOrderCount": 2
}
}
```
#### 空数据 / 降级响应
`staffList` 传空数组即清空配置,响应照常 200:
```json
{ "code": 200, "data": { "staffList": [], "affectedOrderCount": 2 }, "success": true }
```
清空后各子订单的 `guide_status` / `photographer_status` 会被置回 `null`(该位若无订单侧手工行)。
#### 错误响应
```json
{
"code": 589507,
"message": "无操作权限(非团期管理员 / 非本定制师名下)",
"success": false,
"data": null
}
```
本次**未新增任何错误码**,错误语义与改前完全一致。
#### 业务边界
- **异步**:扇出是 `@Async`,状态同步在扇出的单订单子事务内完成,不阻塞本接口响应。
即接口返回 200 时,子订单状态可能尚未写完——前端不要在收到响应的同一刻立即读子订单状态做断言。
- **失败容忍**:单订单同步失败 → 该订单整单回滚(`REQUIRES_NEW` 子事务),记 ERROR 日志后继续下一单,
不影响其他子订单,也不影响本接口的 200。
- **清空语义**:按配置位全量同步,清空时把无人的位置回 `null` 并且**不写流水**。
- **与订单侧手工行共存**:状态按「配置位整组」计数(导游位 = GUIDE + LEADER),与 `source` 无关。
团期行被软删后若该订单仍有 `source=ORDER` 的手工导游行,`guide_status` 保持 `DONE`,两边不互相覆盖。
- **鉴权与幂等**:均未变。
---
## 四、契约约束与正确调用方式
### ✅ 正确 / ❌ 错误 payload 对照
| 场景 | payload |
|------|---------|
| ✅ 配一名导游 | `{ "staffList": [{ "staffId": 1002, "staffRole": "GUIDE" }] }` |
| ✅ 清空配置 | `{ "staffList": [] }` |
| ❌ 收到 200 后立刻断言子订单状态 | 扇出是异步的,需轮询或稍后再查 |
### 调用方式没有变化
本次是纯副作用修复,**前端不需要改任何请求**。
---
## 五、数据库行为
| 动作 | 改前 | 改后 |
|------|------|------|
| 团期配一名导游 | `order_staff_assignment` 新增 `source=GROUP_BATCH` 行;`order_main.guide_status` 保持 `NULL` | 同样新增行;**`order_main.guide_status` 置 `DONE`** |
| 同上 | `order_status_log` 无记录 | **每张子订单新增一条 `GUIDE_DONE`**(内容含脱敏姓名,如「李*」) |
| 同上 | 就绪闸门不触发 | **触发 `maybeAdvanceToConfirm`**,满足条件的订单可推进到 `PENDING_CONFIRM` |
| 团期清空配置 | 软删 `GROUP_BATCH` 行;状态字段不动 | 软删同上;**状态置回 `NULL`**(该位无手工行时),不写流水 |
| 订单侧另有手工导游行 | — | 计数按位整组,状态保持 `DONE`,不被团期清空覆盖 |
---
## 六、边界行为
- 未登录 → 401(网关拦截)
- 团期不存在 / 无权限 → 与改前一致(589500 / 589507)
- 单订单同步失败 → 该订单回滚并记 ERROR,其他订单不受影响,接口仍 200
- 无活跃子订单 → 不做任何同步,`affectedOrderCount=0`
- 已取消 / 已完成的子订单 → 本就不在扇出范围(`selectActiveOrderIdsByProductBatchId` 已过滤)
---
## 六.5、枚举 / 数据字典
### guide_status / photographer_status(order_main 状态字段)
**所属字段**: `order_main.guide_status`、`order_main.photographer_status` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `DONE` | 已配置 | 该配置位至少有一人(不分 source) |
| `null` | 未配置 | 该配置位无人。**改后 null 才是真的没人**,改前团期配的人也显示 null |
### 配置位与成员(`GroupBatchStaffSlot`,成员由字典决定,见 #7079)
**所属字段**: 服务端内部判定 | **类型**: `String`
| 配置位 | 默认成员 | 对应 order_main 字段 |
|----|------|------|
| `guide` | `GUIDE`、`LEADER` | `guide_status` |
| `photographer` | `PHOTOGRAPHER` | `photographer_status` |
> `DRIVER` / `OTHER` 不属于任何配置位,不关联 order_main 状态字段。
## 六.6、修改前后对比
### 字段级对比
| 字段 | 改前 | 改后 |
|------|------|------|
| `order_main.guide_status`(经团期配置) | 恒 `NULL` | 有人 `DONE` / 无人 `NULL` |
| `order_main.photographer_status`(经团期配置) | 恒 `NULL` | 有人 `DONE` / 无人 `NULL` |
| 接口出参 | — | **完全未变** |
### 行为级对比
| 行为 | 改前 | 改后 |
|------|------|------|
| 团期配人 → 订单时间线 | 无记录 | 每子订单一条 `GUIDE_DONE` / `PHOTOGRAPHER_DONE` |
| 团期配人 → 资源就绪闸门 | 不触发 | 触发 `maybeAdvanceToConfirm` |
| 团期清空 → 订单状态 | 不动(本来就是 NULL) | 置回 `NULL`(该位无手工行时) |
| 订单侧 addStaff / editStaff / deleteStaff | — | **行为完全不变**(实现搬到公共组件,断言未改) |
## 六.7、影响评估
- **是否破坏向后兼容**: 否。出参与入参均未变,只是原本恒为 NULL 的字段开始有值。
- **前端是否必须同步上线**: 否。
- **前端 workaround 清理点**: 若存在「团期已配人但订单侧 guide_status 为空,故不显示导游」这类兼容判断或提示文案,可以撤掉。
## 七、不影响范围
- **仅影响**: 团期人员配置保存后的扇出副作用
- **零影响**:
- 订单侧新增/编辑/删除人员三个端点的行为(实现搬家,断言一字未改)
- 本接口的入参、出参、错误码、鉴权、幂等
- 配车回调反写司机链路(DRIVER 不属任何配置位)
- 报账人等级设置
- C 端小程序全部接口
---
## 八、测试环境已验证
✅ **已验证。** 2026-09-07 部署 dev-v3 到测试服并经网关实测(`https://api.test.1814.love:9443`,真实管理端鉴权)。
产品 2044306857534636034 第 7 期(gbId 2096412454643802114,**55 户活跃子订单**):
| # | 用例 | 期望 | 实测 |
|---|---|---|---|
| AC-1 | 经团期配置一名导游(staffId 1002)后全部子订单 guide 状态 DONE | guide 芯片 `DONE(55/55)` | ✅ 配置前 `TODO(0/55)` → 扇出后 `DONE(55/55)`,`affectedOrderCount=55` |
| AC-5 | 清空配置(空 staffList)后状态回落 | guide 芯片回 `TODO(0)` | ✅ 撤回后经中间态 `DOING(54)` 逐单回退至 `TODO(0)`,现场已复原 |
改前对比:经团期配置扇出只写 `order_staff_assignment` 表、不碰订单侧状态,guide 芯片恒 `TODO`——
本次实测 DONE(55/55) 即修复生效的直接证据。
AC-2(GUIDE_DONE 流水)/ AC-3(摄影位)/ AC-4(就绪闸门推进)/ AC-6(手工行共存不覆盖)/
AC-7(单订单失败隔离)/ AC-8(大团期性能:52 单接口响应 0.11s、扇出落库 0.47s、均摊 9ms)
由本地端到端实测 + 单测覆盖(见工单 #7080 验收总结 comment)。
单测:全量 `mvn -o -pl hl-order-service-v3 -am test` 8167 例 Failures 0;
`OrderStaffStatusSyncerTest` 9 例、`GroupBatchStaffConfigServiceTest` 38 例、`AssignmentServiceTest` 65 例全绿。
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| #7085 | #7079 | 配置位成员改由字典决定 | ✅ 有效 |
| #7076 | #7063 | 导游位下游按配置位归组(第 1 波) | ✅ 有效 |
| **本 PR #7115** | **#7080** | 补上扇出链路缺失的状态同步(#7063 AC-3 在团期路径上不成立的真因) | ✅ 最新 |
---
## 十、相关文档
- 关联 Issue: [wx/HL#7080](https://git.1814.love:8443/wx/HL/issues/7080)
- 关联 PR: [wx/HL#7115](https://git.1814.love:8443/wx/HL/pulls/7115)
- 前序: [wx/HL#7063](https://git.1814.love:8443/wx/HL/issues/7063)(本单从其测试环境验收中分离)
## 关联 / 联系人
### 链接
- **Issue**: [#7080](https://git.1814.love:8443/wx/HL/issues/7080)
- **PR**: [#7115](https://git.1814.love:8443/wx/HL/pulls/7115)
- **Merge commit**: [468df6fa7](https://git.1814.love:8443/wx/HL/commit/468df6fa7)
### 联系人
- **后端负责人**: @jw