13 KiB
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 | 7080 | 团期人员配置扇出补同步订单侧 staff 状态,guide_status 不再恒为 NULL | admin | jw(GIT) | 修改接口 | deployed | verified | not_required | 2026-09-07 | 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 消费点,也无「团期配过但订单侧未配置」的兼容逻辑或提示文案可撤,无需改码。 | 2026-09-07 | 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与订单时间线。
请求示例
{
"staffList": [
{ "staffId": 1002, "staffRole": "GUIDE", "sortOrder": 0 }
]
}
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"staffList": [
{ "staffId": 1002, "staffRole": "GUIDE", "staffName": "李雪梅", "sortOrder": 0 }
],
"affectedOrderCount": 2
}
}
空数据 / 降级响应
staffList 传空数组即清空配置,响应照常 200:
{ "code": 200, "data": { "staffList": [], "affectedOrderCount": 2 }, "success": true }
清空后各子订单的 guide_status / photographer_status 会被置回 null(该位若无订单侧手工行)。
错误响应
{
"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
- 关联 PR: wx/HL#7115
- 前序: wx/HL#7063(本单从其测试环境验收中分离)
关联 / 联系人
链接
联系人
- 后端负责人: @jw