文件
hl-api-changelog/changelogs-v2/2026-09/08_7294_流团对已付款户也取消并发起退款-修改接口-管理后台.md
T
jw和Claude Opus 5 b22345d167
changelog-filename-gate / validate (push) Successful in 2s
docs(changelog): #7294 补充 actualRefundAmount 的暂定值/定稿值口径(PR #7354)
退款单在流团事务【提交之后】才建(异步),所以 approve 响应体里的
actualRefundAmount 是暂定值=退款诉求合计;随后服务端逐户回读实际建单结果,
把没建出退款单的户剔掉,改写成定稿值。要展示准确金额请重新拉一次详情。

本文原本已写「actualRefundAmount 只统计成功发起退款的户」,PR #7354 之前
实现其实是 Σ诉求、有户建单失败就对不上;现在实现与本文口径一致了。

顺带修两处当前校验器不再接受的 frontmatter:
consumer hl-ui → admin;not_required 不得保留 frontend_owner / verified_at。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 18:58:20 +08:00

17 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 7294 批准流团后已付款户会被自动取消并发起退款;审批单实退金额不再恒为 0;新增 589554 出行中户硬闸 admin jw(GIT) 修改接口 deployed verified not_required 前端不改:接口出入参零变化;actualRefundAmount 前端本就直显后端权威值(group-batch-approval/index.vue 与 withdraw/index.vue formatPrice 直读),口径修正由后端算;589554 出行中户硬闸由拦截器透后端 message(无中央错误码字典)。补充(PR #7354):approve 响应里的 actualRefundAmount 是暂定值,定稿在提交后异步改写(约 1 秒内);上述两个页面读的是列表/详情接口不是 approve 响应,故仍不需要改,但请勿改成直接渲染 approve 响应的该字段。 2026-09-08 dev-v3

团期: 流团对已付款户也取消并发起退款 + 出行中户硬闸 589554

服务: hl-order-service-v3(只需部署这一个) PR: #7333 Issue: #7294 日期: 2026-09-08 影响范围: 团期流团申请与审批(GB-ADM-060 / GB-ADM-062)


⚠️ 关键变化

出入参结构一个字段都没改。 前端不改不报错,但有三件事必须知道:

  1. 批准流团后,已付款的户现在会被自动取消并发起退款。改前只有「待支付」的户被取消, 付过定金或全款的户既不取消也不退款——团已解散,活跃子订单和客户的钱都还留着。
  2. 审批单的「实退金额」不再恒为 0。改前 actualRefundAmount 是系统性的 0, 与「预估退款」形成无人负责的落差;现在它等于本次实际发起的退款诉求合计。 ⚠️ 这是退款诉求不是实际到账,界面文案建议写「已发起退款金额」。
  3. 新增错误码 589554「团期下有出行中的子订单,不可流团」,前端错误码字典需补录。 发起流团与批复流团两个入口都会返这个码。

改前实测(AC-4,在部署本次改动之前于测试服复现):三户(未付款 / 付订金 2000 / 已补尾款 6000) 批准流团后,只有未付款那户被取消,另两户仍是「制作中」,审批单 estimated=8000 / actual=0, 团期已「已取消」而底下残留 2 张活跃单。


一、背景

流团在 #7196 之后是一条完整审批链:发起申请 → 管理员审批 → 通过后系统自动置团期取消、 批量退各户定金、释放配车占用。设计目标是「批准后系统一次做完,不留手工尾巴」。

但「批量退各户定金」这一步从未真正实现:执行时逐户调的是「系统自动取消」, 而它只处理待支付订单,其余状态一律跳过。而待支付订单的已付金额恒为 0 (付款成功即离开待支付态),所以实退恒为 0。

这不是低频边界,是每次流团都会发生:只要团里有一户付过钱,这一户就会被跳过。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 同意流团申请 POST /v3/admin/order/group-batch/disband/:approvalId/approve 行为变化 已付款户一并取消并发起退款;actualRefundAmount 口径修正;新增 589544 / 589554 两条拒绝路径
2 提交流团申请 POST /v3/admin/order/group-batch/:groupBatchId/disband 行为变化 新增 589554 前置拒绝;出入参与响应结构不变

三、接口详情

1. 同意流团申请 POST /v3/admin/order/group-batch/disband/:approvalId/approve

VO: DisbandApprovalRespVO

使用场景

管理后台团期「流团审批」中同意一条待审流团申请。调用方 hl-ui 团期审批页。 权限:仅管理员角色。

入参

字段 位置 类型 必填 约束 说明
approvalId Path Long ✅ — 流团审批单 ID;入参一个都没变
remark Body String ❌ ≤256 批复备注;请求体整体可不传

出参 Result<DisbandApprovalRespVO>

字段 类型 说明
approvalId Long 审批单 ID;响应结构完全不变
approvalStatus String PENDING / APPROVED / REJECTED
affectedOrderCount Integer 影响子订单户数
estimatedRefundAmount BigDecimal 提交时算的预估退款(Σ已付),口径未变
actualRefundAmount BigDecimal 口径修正:本次实际发起的退款诉求合计。改前系统性恒为 0
其余全部字段 — 完全不变

请求示例

POST /v3/admin/order/group-batch/disband/2097220075659415553/approve HTTP/1.1
Authorization: Bearer <admin-token>
Content-Type: application/json

{"remark":"确认无法成团"}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "approvalId": "2097220075659415553",
    "approvalStatus": "APPROVED",
    "affectedOrderCount": 3,
    "estimatedRefundAmount": 8000.0,
    "actualRefundAmount": 8000.0,
    "approvedByName": "admin",
    "approvedAt": "2026-09-08 15:06:46"
  }
}

上面这单里,三户分别是「未付款 / 付订金 2000 / 已补尾款 6000」, 执行后三户全部取消,退款单 2000 + 6000 与 actualRefundAmount 逐笔对上。

空数据 / 降级响应

单户失败不中断整批:某户因状态不允许取消、或用车需求正处于最终确认中而被跳过时, 接口仍返 200、其余户照常取消、审批单与团期状态不回滚; actualRefundAmount 只统计成功发起退款的户,因此可能小于 estimatedRefundAmount, 差额由服务端日志里的「未处理清单」解释。

⚠️ actualRefundAmount 会在批准之后被改写一次,前端不要缓存 approve 响应里的那个值。 退款单是在流团事务提交之后才建的(异步),所以 approve 响应体里带回的 actualRefundAmount 是暂定值=本次发出的退款诉求合计;随后服务端逐户回读实际建单结果, 把没建出退款单的户剔掉,改写成定稿值。两者在「全部建单成功」时相同, 有户建单失败时定稿值更小。

定稿通常在 1 秒内完成。要展示准确金额,请在 approve 返回后重新拉一次 GET /v3/admin/order/group-batch/disband/:approvalId, 或直接以列表 / 详情接口的值为准,不要直接渲染 approve 响应里的这个字段。

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "approvalId": "2097216263326466050",
    "approvalStatus": "APPROVED",
    "affectedOrderCount": 3,
    "estimatedRefundAmount": 6000.0,
    "actualRefundAmount": 4000.0
  }
}

错误响应

{
  "code": 589554,
  "message": "团期下有出行中的子订单,不可流团;请等其出行完毕,或先对该户单独终止行程",
  "success": false,
  "data": null
}

错误码新增一条、新增两条触发路径:

码 含义 变化
589554 团期下有出行中的子订单,不可流团 本次新增。发起与批复两个入口都会返
589544 团期已出行,不可发起或批复流团 新增触发路径:此前只在发起入口出现,现在批复时也会按当时的团期状态重判
589545 / 589546 / 589547 / 589500 / 589501 申请不存在 / 已处理 / 非管理员 / 团期不存在 / 团期已终态 均未变

业务边界

  • 退款按「已付全额」算,不扣违约金:流团是平台方单方面解散,客人无过错。 金额 = 该户已付款 − 已退款。不是按应付订金退——已补尾款的户按订金退会少退, 全款户更会因为没有订金而直接失败。
  • 已付款为 0 的户只取消不建退款单,属正常情形,不是失败。
  • 退款单是「诉求」不是「到账」:由取消事件的异步监听器创建、由渠道异步打款, 都可能后续失败。界面文案请写「已发起退款金额」。
  • 退款不再挂第二道审批:流团本身已经过一道管理员审批,退款单直接放行。
  • 有出行中户就整笔拒绝:拒的时候什么都不改——团期状态、子订单、审批单全部零变动, 审批单仍留在「待审批」,运营处理完那一户后可以直接再批一次。

2. 提交流团申请 POST /v3/admin/order/group-batch/:groupBatchId/disband

VO: DisbandApprovalRespVO

使用场景

管理后台团期详情页发起流团申请,只建待审批单、不执行。调用方 hl-ui 团期详情页。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ — 团期主订单 ID;入参一个都没变
reason Body String ✅ 非空 流团理由

出参 Result<DisbandApprovalRespVO>

字段 类型 说明
approvalId Long 新建的审批单 ID;响应结构完全不变
approvalStatus String 恒为 PENDING
affectedOrderCount Integer 影响子订单户数
estimatedRefundAmount BigDecimal 预估退款(Σ已付),口径未变
其余全部字段 — 完全不变

请求示例

POST /v3/admin/order/group-batch/2097220073544073217/disband HTTP/1.1
Authorization: Bearer <admin-token>
Content-Type: application/json

{"reason":"临近出团仍未达最低成团数"}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "approvalId": "2097220075659415553",
    "approvalStatus": "PENDING",
    "affectedOrderCount": 3,
    "estimatedRefundAmount": 8000.0
  }
}

空数据 / 降级响应

被 589554 拒时不会建出审批单,团期审批列表里不会多出一条待处理项, 运营处理完出行中那户后重新发起即可。

{
  "code": 589554,
  "message": "团期下有出行中的子订单,不可流团;请等其出行完毕,或先对该户单独终止行程",
  "success": false,
  "data": null
}

错误响应

{
  "code": 589543,
  "message": "该团期已有在途的流团申请",
  "success": false,
  "data": null
}

错误码:589543(已有在途申请)、589544(团期已出行)、589500(团期不存在)、 589554(有出行中的子订单,本次新增)。

业务边界

  • 本入口的 589554 是前置提示,让运营在提单那一刻就知道拦在哪; 权威的那道在批复侧——提单到批复之间订单还可能被出发任务推成出行中。
  • 提交阶段的「预估退款」口径未变,仍是全部活跃户的已付金额之和。

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

  • actualRefundAmount 请按「已发起退款金额」展示,不要写成「实退合计」。 它可能小于「预估退款」——差额来自被跳过的户,属正常情形而非数据错误。
  • 589554 是可恢复的拒绝:提示运营「该团有客人正在行程中,请等其出行完毕, 或先单独为该户办理终止行程」,而不是提示「系统繁忙,稍后重试」。
  • 589544 与 589554 是两件事:前者是「这个团期本身已经出发了」, 后者是「团期还没出发,但底下有客人已经在行程中」。两个提示语不要合并。

五、数据库行为

  • 本次无表结构变更、无数据迁移。
  • 批准流团后:已付款户的订单状态推进为「已取消」并写取消时间;审批单回填「已发起退款金额」; 退款申请由取消事件异步创建。
  • 被 589544 / 589554 拒时零写入:团期、子订单、审批单全部不变。

六、边界行为

  • 只含待支付户的团期:行为与改前逐字节一致——订单取消、无退款单、实退金额 0。
  • 已被全额退过的户:可退额为 0,只取消不建退款单。
  • 有历史部分退款的户:可退额按「已付 − 已退」算,不会撞退款复核的上限校验。
  • 用车需求正在最终确认中的户:本轮跳过(该冲突有 10 分钟租约会自动过期), 其余户照常处理,审批单与团期不回滚。

六.6、修改前后对比

场景 改前 改后
批准流团,团里有付过定金 / 全款的户 那些户既不取消也不退款,团期已「已取消」而底下残留活跃单 全部取消并发起退款,团期下无残留
审批单「实退金额」 系统性恒为 0 等于本次已发起退款金额合计,与退款单逐笔对得上
已补尾款的户(已付 6000 / 订金 2000) 不取消不退款 取消并退 6000(按已付款,不是按订金)
全款支付户 不取消不退款 取消并退全部已付款
只含待支付户的团期 取消、无退款单、实退 0 完全一致,无回归
批复时团期已出行 放行,团被流掉 589544 拒绝,零变动
团期下有出行中的子订单 放行,团被流掉而该户残留 589554 拒绝,零变动
单户因状态或用车确认冲突被跳过 — 其余户照常成功,审批单与团期不回滚,接口仍 200

六.7、影响评估

  • 前端零改动:两个接口的出入参与响应结构完全不变。
  • 需要前端做的一件事:错误码字典补录 589554。不补也不会报错,只是拿不到友好文案。
  • 建议改一处文案:审批单上的 actualRefundAmount 若显示为「实退金额」, 建议改为「已发起退款金额」——它是退款诉求,不是到账确认。
  • 对客户的净效果:团解散后钱会自动退,不用等客户来问。
  • 对运营的净效果:审批单上的金额第一次有了真实含义; 「团期已取消却还挂着活跃单」这种需要人工善后的现场大幅减少。
  • 风险:户数多时批复会串行处理各户退款,接口耗时随户数上升;正确性有 CAS 兜底, 不会双执行。

七、不影响范围

  • 拒绝流团(reject)未改。
  • 退单户审批(withdraw)未改。
  • C 端自主取消、管理后台单笔取消订单未改——新增的「已付全额退」模式不进后台取消下拉, 只由流团执行链路内部使用。
  • 团期名额计数、对账 Job 未改。
  • 定制师提交房 / 车需求的权限未收紧。

八、测试环境已验证

只部署 hl-order-service-v3。验收后已滚回主干,造数已清理。

验证项 结果
三户(未付款 / 付订金 / 已补尾款)批准流团 三户全部「已取消」,cancelled_at 非空
退款单落库 付订金户 2000、已补尾款户 6000(按已付款不是订金)、未付款户无退款单
审批单金额 estimated=8000 / actual=8000,与两张退款单逐笔对上
改前对照 同样三户 → 只取消未付款那户,另两户仍「制作中」,actual=0,残留 2 张活跃单
单户不可取消时 接口 200、其余户全成功、审批单与团期未回滚、actual 只算成功户(4000 / 预估 6000)
用车最终确认在途的户 该户跳过、其余成功、审批单与团期未回滚、接口 200
团期下无残留 三户全可取消的场景下,活跃单数 = 0
只含待支付户 取消、无退款单、实退 0——与改前一致
全款户(无订金) 取消并退全部已付款 6000
批复时团期已出行 589544,团期 / 子订单 / 审批单零变动
团期下有出行中子订单(提单侧 / 批复侧) 均 589554,且提单侧不建审批单、批复侧审批单仍「待审批」
待办同步真实失败时 流团照常提交(真数据库 + 真事务代理的集成测试坐实)
单元测试 order-v3 9060 例,0 失败 0 错误

十、相关文档

  • Issue #7294、PR #7333
  • 关联工单:#7196(流团申请与审批)、#7283(流团后班期置为不可售)
  • 未覆盖项:退款建单失败注入、进程中断恢复、批复与出发任务并发—— 三条需要 kill 进程或精确并发构造,未在共享测试环境执行

关联 / 联系人

  • 后端:jw
  • 前端:mmg(hl-ui)
  • 前端待办:错误码字典补录 589554;建议把审批单的「实退金额」文案改为「已发起退款金额」。 接口结构零变化,不改也不会报错。