文件
hl-api-changelog/changelogs-v2/2026-09/23_8231_配导游配摄影物资放开到出行前四态-修改接口-管理后台.md
T
2026-09-23 15:15:48 +08:00

24 KiB
原始文件 Blame 文件历史

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 8231 配导游 / 配摄影 / 物资取消阶段门——出行前四态均可随时配置;取消成团改为放行并回收导摄配置 admin jw(GIT) 修改接口 deployed not_required verified mmg e15dd73bd36a1d27374f9206797243f8a5e4326c 2026-09-23 jw 2026-09-23 裁决:配导游 / 配摄影 / 物资三项取消节点限制,只要在出行节点之前都可以随时配置。改前配导游 / 配摄影被 assertFormed 拦在招募中(589552),物资被 assertInMaterialStage 限死在 MATERIAL_PREPARING(589520)——而团期要集齐四项 ready(房 / 车 / 导 / 摄)才推得进 MATERIAL_PREPARING,实际「物资配不了」的根因多半是房车没配齐。本次三处写口统一引用新常量 PRE_DEPARTURE_CONFIGURABLE_STATUSES(RECRUITING / RESOURCE_PREPARING / MATERIAL_PREPARING / PENDING_DEPARTURE),出行后与已取消一律拒成新错误码 589598,未建团仍 589553。连带改的是取消成团:放开招募中可配之后,若导摄仍算「已派单资源」,招募中配过人的团一成团就再也取消不了成团(开工前实测:TEST 团期 2099750660965584898 在房车 ready 全 0、已确认子订单 0 的情况下,仅凭导游一项就返 589502)。故按方案 C,导摄两项移出 R10 判定,取消成团改为放行并在同事务内回收导摄配置(order_batch_staff 整期软删 + 各子订单 order_staff_assignment 中 source=GROUP_BATCH 的扇出行软删),房 / 车两项仍照旧阻断。取证阶段另修一处本单引入的回归:招募中清空导摄配置后 ready 位回不到 false(免闸豁免只对已成团成立,needs_* 招募中恒 0),已随 PR #8237 修复。TEST 实测 2026-09-23 12:15~12:25:物资三端点在四态各放行、在 REVIEWING / TRIP_FINISHED / CANCELLED 各返 589598 且零写入;配导摄在四态各落库成功、在三个出行后态返 589598 且零写入;取消成团对仅导摄 dispatched 的样本返 200 并完成回收,对 hotel_ready=1 / vehicle_ready=1 两个样本仍返 589502 且零写入;连续两次取消成团第二次返 589501、不重复回收。前端侧:配导游 / 配摄影按钮本来就不看 batchStatus,零改动;物资 tab 的操作列在 SuppliesPanel.vue 里按 MATERIAL_PREPARING 前置隐藏,后端放开后前端不改则本单无实际效果,交接件见同批 frontend 条目,故 frontend_status 记 pending。 | 2026-09-23 mmg 交付:SuppliesPanel 拆双判据四态放行三写口,配导摄零改动实证,随配套 frontend 条目同 commit 2026-09-23 dev-v3

团期资源配置: 配导游 / 配摄影 / 物资放开到出行前四态(管理后台)

服务: hl-order-service-v3(端口 8086/8186) PR: #8234、#8237 Issue: #8231 日期: 2026-09-23 影响范围: 管理后台团期详情页的「配导游 / 配摄影」弹窗、「物资」tab、「取消成团」按钮


⚠️ 关键变化

本次是行为变更,不是纯增字段,三条都与调用方此前的预期不同:

  1. 可配窗口扩大。以前「招募中配不了导摄」「物资只有到了准备物资阶段才配得了」,现在出行前四态都能配。
  2. 拒绝时的错误码换了。以前物资拒是 589520、导摄拒是 589552,现在统一是新码 589598。按 589520 / 589552 做文案分支的前端要改。
  3. 取消成团的阻塞条件收窄了。以前「已派导游 / 已派摄影」会把取消成团拦住(589502),现在不会;作为代价,取消成团成功后会把该团期的导摄配置一并回收,配人列表会变空。

一、背景

GroupBatchStatus 状态机里,「出行之前」= 前四态:

允许配置 拒绝
RECRUITING 招募中 · RESOURCE_PREPARING 资源准备中 · MATERIAL_PREPARING 物料准备中 · PENDING_DEPARTURE 待出发 TRAVELLING 出行中 · TRIP_FINISHED 出行完毕 · REVIEWING 核单中 · SETTLED 已结算 · CANCELLED 已取消

CANCELLED 按拒绝处理:它是终态取消,不属于「出行前」语义。

物资的实际约束比表面更紧:团期要先走到 MATERIAL_PREPARING 才开窗,而 RESOURCE_PREPARING → MATERIAL_PREPARING 的推进条件是四项 ready 齐(房 / 车 / 导 / 摄)+ 合同 / 保险。 即今天「物资配不了」的根因多数是房车没配齐。本次放开后,物资配置不再依赖这条链。

状态机推进逻辑本身不动:MATERIAL_PREPARING 这个阶段、以及「四项 ready 齐才推进」那条链一律不变。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 保存团期人员配置 PUT /v3/admin/group-batch/{productBatchId}/staff 修改接口 阶段门从「已成团」放宽到出行前四态;拒绝码 589552 → 589598
2 设置报账人等级 PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/reporter-rank 修改接口 同上,与保存口同窗口
3 新增团期备品行 POST /v3/admin/order/group-batch/{groupBatchId}/supplies 修改接口 阶段门从 MATERIAL_PREPARING 放宽到出行前四态;拒绝码 589520 → 589598
4 调整团期备品数量 PUT /v3/admin/order/group-batch/supplies/{batchSuppliesId}/quantity 修改接口 同上
5 软删团期备品行 DELETE /v3/admin/order/group-batch/supplies/{batchSuppliesId} 修改接口 同上
6 取消成团 POST /v3/admin/order/group-batch/{groupBatchId}/cancel-group 修改接口 导摄两项不再阻断;成功时额外回收导摄配置

路径、入参结构、权限码、成功响应结构均零变化;网关无改动。


三、接口详情

1. 保存团期人员配置 PUT /v3/admin/group-batch/{productBatchId}/staff

VO: BatchStaffConfigReqVO → BatchStaffConfigRespVO

使用场景

团期详情页「配导游 / 配摄影」弹窗点保存。整期全量覆盖:按 scopeRoles(不传即全量)软删旧配置、 写入新配置、异步扇出到各活跃子订单,并按配置结果回填 guide_ready / photographer_ready。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 正整数,产品侧排期 ID 团期所属班期;未建团返 589553
scopeRoles body List<String> 否 元素非空 限定本次覆盖的角色范围,不传则整期覆盖
staffList body List<Item> 否 null 按空列表处理 传空列表 = 清空覆盖范围内的配置
staffList[].staffId body Long 是 须命中候选人员 人员 ID
staffList[].staffRole body String 是 须与人员类型相符,否则 582114 角色(GUIDE / LEADER / PHOTOGRAPHER …)
staffList[].sortOrder body Integer 否 — 展示排序
staffList[].remark body String 否 — 备注

出参

字段 类型 说明
productBatchId Long 回显路径参数
groupBatchId Long 团期聚合主键,取守卫阶段那一次既有反查的结果,不额外查库
staffList List 保存后的整期最终状态
affectedOrderCount Integer 本次扇出触及的活跃子订单数

请求示例

PUT /v3/admin/group-batch/2097250420299530242/staff HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>
Content-Type: application/json

{"staffList":[{"staffId":1002,"staffRole":"GUIDE","sortOrder":0},{"staffId":1003,"staffRole":"PHOTOGRAPHER","sortOrder":1}]}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "productBatchId": "2097250420299530242",
    "groupBatchId": "2097250563497385985",
    "affectedOrderCount": 0,
    "staffList": [
      {"staffId": 1002, "staffRole": "GUIDE", "staffName": "李雪梅", "reporterRank": "NONE"},
      {"staffId": 1003, "staffRole": "PHOTOGRAPHER", "staffName": "王强", "reporterRank": "NONE"}
    ]
  }
}

空数据 / 降级响应

staffList 传空列表即清空覆盖范围内的配置,返回 200,staffList 为空数组、affectedOrderCount 为实际扇出订单数。 清空后 ready 位的回落口径本次有修正:已成团且该位 needs_*=false(成团免闸置位)时保持就绪、不回落; 其余情形(含招募中)一律回落为 false。改前招募中清空后 ready 位会卡在 true,与配置行数 0 自相矛盾。

错误响应

{"code": 589598, "message": "出行后不可再配置导游 / 摄影 / 物资", "data": null}

未建团(该班期还没有任何订单,团期行尚未 Lazy 建)仍是另一个码,两者不可合并:

{"code": 589553, "message": "团期尚未创建(该班期还没有任何订单),请先建团并完成成团后再操作", "data": null}

业务边界

  • 出行前四态(RECRUITING / RESOURCE_PREPARING / MATERIAL_PREPARING / PENDING_DEPARTURE)放行
  • TRAVELLING / TRIP_FINISHED / REVIEWING / SETTLED / CANCELLED 返 589598,被拒时一行都不写(闸在写库之前)
  • 未建团返 589553,且不会为配置动作提前建团期行
  • 589552「团期尚未成团」不再由本接口抛出,但该码仍被别处(车辆派单、房务)使用,未退役

2. 设置报账人等级 PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/reporter-rank

VO: ReporterRank(枚举入参)

使用场景

团期人员名单里把某个已配人员标为主报账人 / 协助报账人。它与保存口是同构写口——同样写 order_batch_staff 并扇出 order_staff_assignment,故口径必须与保存口完全一致。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 正整数 产品侧排期 ID
staffId path Long 是 须命中该团期已配人员 人员 ID
rank body String 是 PRIMARY / ASSIST / NONE 报账人等级

出参

字段 类型 说明
data Void 成功返回 null,判成败看 code

请求示例

PUT /v3/admin/group-batch/2097250420299530242/staff/1002/reporter-rank HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>
Content-Type: application/json

{"rank":"PRIMARY"}

响应示例

{"code": 200, "message": "成功", "data": null}

空数据 / 降级响应

本接口无列表出参,无空数据形态;团期已配人员为空时会先因 staffId 未命中报错,不会静默成功。

错误响应

{"code": 589598, "message": "出行后不可再配置导游 / 摄影 / 物资", "data": null}

业务边界

  • 窗口与保存口完全一致,不允许两个方法口径漂移
  • 被拒时连「查已派 staff」这一步读都不发生,零写入
  • 未建团仍返 589553

3. 新增团期备品行 POST /v3/admin/order/group-batch/{groupBatchId}/supplies

VO: AddSuppliesReqVO

使用场景

团期详情页「物资」tab 手工录入一行备品(产品侧没有、临时采购的)。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 正整数,团期聚合主键 不存在返 GROUP_BATCH_NOT_FOUND
suppliesName body String 否 传 suppliesResourceId 时可空 备品名称;纯手填时必填
suppliesResourceId body Long 否 — 备品库资源 ID,传了则名称取库值
category body String 否 — 分类
hasCost body Boolean 否 — 是否计费
billingType body String 否 PER_PERSON / PER_QUANTITY 计费方式
unitPrice body BigDecimal 否 — 单价
quantity body Integer 是 ≥ 1,否则 589522 数量
sortOrder body Integer 否 默认 0 展示排序

出参

字段 类型 说明
data Long 新建备品行 ID(batchSuppliesId),用于后续改数量 / 软删

请求示例

POST /v3/admin/order/group-batch/2099750365778886657/supplies HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>
Content-Type: application/json

{"suppliesName":"临时采购的雨衣","quantity":1,"sortOrder":999}

响应示例

{"code": 200, "message": "成功", "data": "2102611411027066881"}

空数据 / 降级响应

本接口是写接口,无空数据形态。创单时由系统固化产品侧备品的 freezeFromProduct 路径不过本阶段门—— 它是首单懒建事务内的系统行为,加门会把建团直接打断,该豁免本次不变。

错误响应

{"code": 589598, "message": "出行后不可再配置导游 / 摄影 / 物资", "data": null}

业务边界

  • 出行前四态放行,尤其 RESOURCE_PREPARING——改前该态必被 589520 拒
  • 出行后与 CANCELLED 返 589598,不落库
  • 团期不存在返 GROUP_BATCH_NOT_FOUND,不是阶段错误
  • 数量非法返 589522 参数错误,不是状态错误

4. 调整团期备品数量 PUT /v3/admin/order/group-batch/supplies/{batchSuppliesId}/quantity

VO: AdjustSuppliesQuantityReqVO

使用场景

物资 tab 行内编辑数量。

入参

字段 位置 类型 必填 约束 说明
batchSuppliesId path Long 是 须命中活跃备品行 不存在返 589521
quantity body Integer 是 ≥ 1,否则 589522 新数量

出参

字段 类型 说明
data Void 成功返回 null

请求示例

PUT /v3/admin/order/group-batch/supplies/2102611411027066881/quantity HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>
Content-Type: application/json

{"quantity":5}

响应示例

{"code": 200, "message": "成功", "data": null}

空数据 / 降级响应

无列表出参,无空数据形态。备品行已被软删时返 589521,不会静默成功。

错误响应

{"code": 589598, "message": "出行后不可再配置导游 / 摄影 / 物资", "data": null}

业务边界

  • 阶段门由该备品行反查所属团期后判定,窗口与新增口一致
  • 「确认物资之后能不能改」不归本门管:确认后仍可增删改是有意为之,窗口扩大后该结论不变
  • 被拒时数量不变、行不被软删

5. 软删团期备品行 DELETE /v3/admin/order/group-batch/supplies/{batchSuppliesId}

VO: Result<Void>(无请求体)

使用场景

物资 tab 删除一行备品。

入参

字段 位置 类型 必填 约束 说明
batchSuppliesId path Long 是 须命中活跃备品行 不存在返 589521

出参

字段 类型 说明
data Void 成功返回 null

请求示例

DELETE /v3/admin/order/group-batch/supplies/2102611411027066881 HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>

响应示例

{"code": 200, "message": "成功", "data": null}

空数据 / 降级响应

软删是幂等的:对已软删的行再调返 589521「备品行不存在」,不会重复写。

错误响应

{"code": 589598, "message": "出行后不可再配置导游 / 摄影 / 物资", "data": null}

业务边界

  • 窗口与新增 / 改数量完全一致
  • 被拒时行的 deleted_at 保持为空

6. 取消成团 POST /v3/admin/order/group-batch/{groupBatchId}/cancel-group

VO: Result<Void>(无请求体)

使用场景

团期从「资源准备中」退回「招募中」。本次没有改它的入参或路径,改的是它的阻塞条件与成功时的副作用。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 正整数,团期聚合主键 不存在返 GROUP_BATCH_NOT_FOUND;非 RESOURCE_PREPARING 返 589501

出参

字段 类型 说明
data Void 成功返回 null,团期状态已回到 RECRUITING

请求示例

POST /v3/admin/order/group-batch/2099750660965584898/cancel-group HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <admin token>

响应示例

{"code": 200, "message": "成功", "data": null}

空数据 / 降级响应

成功时无返回体。该团期没有任何导摄配置时,回收步骤是零行软删的空操作,不影响成功。

错误响应

{"code": 589502, "message": "取消成团被阻塞(有已确认子订单或已派单资源)", "data": null}

连续两次调用,第二次因状态已不是 RESOURCE_PREPARING 被 CAS 拒:

{"code": 589501, "message": "团期状态不允许当前操作", "data": null}

业务边界

  • 仍阻塞:有已确认子订单(PENDING_DEPARTURE / TRAVELLING / COMPLETED)、hotel_ready=true、 vehicle_ready=true(且非整团免车)
  • 不再阻塞:已派导游、已派摄影
  • 成功时依次:状态 CAS 回 RECRUITING → 四项 ready 与物资确认全部重置 → 回收导摄配置 → 登记配车释放命令
  • 回收范围只含 source=GROUP_BATCH 的扇出行,子订单自己单独派的人不受影响
  • 幂等:第二次调用被 589501 拒,不重复回收

四、契约约束与正确调用方式

  • 判拒绝原因不要再认 589520 / 589552。这两个码不再由上述五个配置接口抛出(589520 保留占位防号段复用,589552 仍由车辆派单、房务等别处使用)。统一认 589598。
  • 589598 与 589553 是两件事,不要合并成一个 toast:前者是「这个团已经出发了,配不了了」,后者是「这个班期还没有任何订单,先去建团」。
  • 配导摄成功后,若调用方缓存了 guide_ready / photographer_ready,需重新拉取团期详情——本次修正了清空时的回落口径。
  • 取消成功后,团期人员名单会变空,调用方若停在配人弹窗需主动刷新。

五、数据库行为

  • 配导摄保存:整期(或 scopeRoles 范围内)软删旧配置行 + 写入新配置行 + 异步扇出到各活跃子订单;随后按配置结果回填团期行的两个 ready 标志
  • 物资三口:分别为插入一行、更新一行的数量、软删一行
  • 取消成团:状态 CAS 一行 + 重置该团期四项 ready 与物资确认 + 软删该团期全部导摄配置行 + 软删其各子订单中来源为团期扇出的人员分配行,全部在同一个事务内,任一步失败整体回滚
  • 被阶段门拒绝时零写入:闸在所有写库动作之前

六、边界行为

  • CANCELLED(已流团)按拒绝处理,返 589598
  • 未建团(团期行尚未 Lazy 建)返 589553,不会为配置动作提前建行——否则会出现「零单可配 → 首单落地反而不可配 → 成团后又可配」这种非单调行为
  • 创单时固化产品侧备品的系统路径不过阶段门,该豁免不变
  • 「确认物资之后仍可增删改」不变

六.6、修改前后对比

维度 改前 改后
配导摄可配状态 已成团各态(招募中被拒) RECRUITING / RESOURCE_PREPARING / MATERIAL_PREPARING / PENDING_DEPARTURE
配导摄拒绝码 589552(未成团)/ 589553(未建团) 589598(已出行 / 已取消)/ 589553(未建团)
物资三口可配状态 仅 MATERIAL_PREPARING 同上四态
物资三口拒绝码 589520 589598
取消成团:已派导游 / 摄影 返 589502 被阻塞 放行,且回收导摄配置
取消成团:房 / 车 ready 返 589502 被阻塞 不变,仍返 589502
招募中清空导摄后的 ready 位 卡在 true(与配置行数 0 矛盾) 回落为 false

六.7、影响评估

面 评估
管理后台配导摄 按钮本来就不看 batchStatus,招募中点得下去、只是被后端拒。后端放开后前端零改动即可生效
管理后台物资 tab 操作列按 MATERIAL_PREPARING 前置隐藏,前端不改则本次无实际效果,交接件见同批 frontend 条目
已有错误文案分支 按 589520 / 589552 做文案的地方需改认 589598
取消成团 可取消的团期变多;成功后人员名单会被清空,属预期
小程序端 不受影响,物资清单在小程序端是只读视图
状态机 不变,MATERIAL_PREPARING 阶段与「四项 ready 齐才推进」那条链一律不动

七、不影响范围

  • 团期状态机的推进逻辑、四项 ready 的计算口径
  • 流团(disband):只校验状态白名单,不看 ready 位,本次完全不受影响
  • 子订单自己单独派的人员(order_staff_assignment 中 source 非 GROUP_BATCH 的行):回收不碰它们
  • 车辆派单、房务等仍在用 assertFormed 的写口:口径不变
  • 权限码、路径、入参结构、成功响应结构、网关配置

八、测试环境已验证

2026-09-23 12:15~12:25,api.test.1814.love:9443,分支 dev-v3(fe752f16c)。

AC 内容 结果
物资四态放行 RECRUITING / RESOURCE_PREPARING / MATERIAL_PREPARING / PENDING_DEPARTURE 各跑「增 → 改数量 → 删」三端点 12 次调用全 200,自造行自删、零残留
物资出行后拒 REVIEWING / TRIP_FINISHED / CANCELLED 各跑三端点 全返 589598;既有行的 quantity 未变、未软删、未新增行
配导摄四态放行 四态各保存「1002 GUIDE + 1003 PHOTOGRAPHER」 全 200 且落库;逐个还原为改前配置,四组还原判定全 ✔
配导摄出行后拒 REVIEWING / TRIP_FINISHED / CANCELLED 全返 589598;活跃行与表内总行数逐字未变
未建团 不存在的 productBatchId 返 589553,未被新码吞掉
取消成团放行 + 回收 团期 2099750660965584898(needs_guide=1 & guide_ready=1,房车 ready 全 0,已确认子订单 0)——同一样本开工前实测返 589502 返 200;状态 RESOURCE_PREPARING → RECRUITING;guide_ready / photographer_ready 归 0;配置行与子订单扇出行同时间戳软删
房车仍阻断 hotel_ready=1 与 vehicle_ready=1 两个样本 均返 589502;团期行与两张配置表逐字未变
幂等 对同一团期连调两次取消成团 第二次返 589501;三处读数与第一次后完全一致,无重复回收

本地单测:assignment + groupbatch + house 4103 条、archunit / core / requirement 等 3456 条、其余 26 个包 4621 条,全绿。

取证用到的写操作及还原:新增的备品行均由本次自行软删;配导摄的四个团期均按改前配置逐条还原; 取消成团样本 2099750660965584898 已按改前值还原(状态、两个 ready 位、配置行与扇出行的软删标记)。


十、相关文档

  • Issue #8231(含开工前的 AC-6 实测与方案 C 裁决)
  • PR #8234(主体)、PR #8237(ready 回落回归修复)
  • 被推翻:#7287 T5(assertFormed)、#7023 AC-TD-13(物资单一阶段窗口)、wx 2026-09-15「放行但配置行保留」
  • 保持不变:#7023 AC-TD-15(确认后仍可改)、#7441 PR-2e(整团免车的 ready 剥离)

关联 / 联系人

  • 后端:jw
  • 前端:mmg(物资 tab 显隐条件,见同批 frontend 条目)