文件
hl-api-changelog/changelogs-v2/2026-09/08_7344_取消班期活跃订单判据failclosed聚合失败取保守侧CANCELLING-修复-管理后台.md
T
2026-09-08 17:29:52 +08:00

6.7 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 7344 管理端取消班期:order-v3 活跃订单聚合失败时不再落终态 CANCELLED,改取保守侧 CANCELLING(无接口、字段、路径、参数、枚举、错误码变化) admin jw(GIT) 修复 deployed verified not_required mmg 纯后端修复(PR #7348 合 dev-v3),接口/字段/路径/参数/枚举/错误码全不变,仅聚合失败路径落库 CANCELLED→CANCELLING。前端 grep 实证:CANCELLING/CANCELLED 走字典 schedule_status 直显(BatchPanel/BatchCard)本就同等排除,取消班期仅 cancelSchedule+confirm 无「等退款」反推,响应 code=200 结构不变。not_required 成立。 2026-09-08 dev-v3

取消班期的活跃订单判据改 fail-closed(修复)

一、给前端的一句话

前端无需任何改动。 本次修复不动接口、不动字段、不动路径、不动参数、不动枚举、不动错误码。POST /admin/product/item/:id/schedule/:scheduleId/cancel 的响应在全部场景下仍是 code=200 / message="班期取消成功" / data=null;batchStatus 的取值集合(ENROLLING / NEARLY_FULL / FULL / FINISHED / CANCELLING / CANCELLED)与语义也不变。变的只是订单服务聚合失败时落库取哪一个取消态。

二、症状(改前)

管理端「取消班期」要先问 order-v3「这个班期还有没有活跃订单」,再决定落 CANCELLING(还有订单待订单域处理)还是 CANCELLED(确实没订单)。

这次取数走的是 fail-open 的降级路径:向 order-v3 的实时聚合一旦失败(Feign 超时 / 5xx / 返回 code != 200 / 目标班期缺席结果),失败分片的班期就退化为「无活跃订单」,活跃数被当成 0,班期于是被落成终态 CANCELLED。

后果不是钱退不出去(取消班期本来就不发起任何退款,见第五节),而是三件事:

  1. 状态语义错误:明明还有活跃订单的班期,被记成「已取消、无遗留」。
  2. 与订单域口径分裂:order-v3 流团触发的同语义入口(内部接口)早已收口为 fail-closed,两条路径对同一件事给出相反结论。
  3. 写错后不自愈:全仓没有任何路径会把 CANCELLED 改回来——班期状态重算只在 ENROLLING ↔ FULL 之间流转、明确不碰取消态;编辑班期会保留原状态;订单域再次回调时对已取消态幂等直接返回。一旦写错,只能手工改库。

触发窗口窄(order-v3 抖动期间恰好有人点取消),但一旦命中就是永久性的错误状态。

三、修复(改后)

活跃数取数改用严格版本:聚合成功才按真实活跃订单数判定,聚合失败取保守侧 CANCELLING 并记一条 WARN 日志,与订单域内部入口逐字对齐。不新增任何接口、不新增任何方法。

场景 改前落库 batchStatus 改后落库 batchStatus
聚合成功且有活跃订单 CANCELLING CANCELLING(不变)
聚合成功且无活跃订单 CANCELLED CANCELLED(不变)
聚合失败(超时 / 5xx / code != 200 / 班期缺席结果) CANCELLED CANCELLING + 一条后端 WARN

保守侧的代价是:order-v3 抖动窗口内被取消的空班期会显示「取消中」而不是「已取消」。这是刻意接受的——两个状态在全部下游判定里等价(下一节),差异只是展示文案;而反方向的错误会丢失「这批还有订单要处理」这一运营信号,且同样不自愈。

四、受影响接口(全部「复用不改」)

端 接口 变化
管理后台 POST /admin/product/item/:id/schedule/:scheduleId/cancel method / path / 入参 / 出参 / 错误码均无变化;只有「聚合失败」这一条路径的落库值变了。Swagger notes 文案一并修正(原文误称「标记为 CANCELLING 触发退款」,实际不触发任何退款)
管理后台 GET /admin/product/item/:id/schedule/list 无变化。仅作为取证入口,batchStatus 字段读到的就是上面落库的值

CANCELLING 与 CANCELLED 在下游四处判定中完全等价,前端已有的渲染逻辑不受影响:

  • 班期展示态解析:两者都原样保留持久值,不参与实时库存重算
  • 可报名谓词:两者都返回不可报名
  • 下单选品列表:两者都被排除
  • order-v3 下单闸:可下单状态只含 ENROLLING / NEARLY_FULL,两者都不在其中

五、澄清:取消班期不触发退款

修复顺带纠正了两处误导性文案(服务层注释与 Swagger notes)。它们原本写「CANCELLING → 触发退款 / 等退款流程异步处理」,但产品域取消班期的方法体只有一次班期状态落库,不发 MQ、不调 Feign、不发事件;全仓也没有任何代码读产品侧的 CANCELLING 去发起退款。团期退款实际由订单域的流团审批链路驱动。前端如果据旧文案做过「取消班期后等退款」的假设,可以去掉。

六、影响范围

  • 只影响管理端「取消班期」这一个动作,且只在 order-v3 聚合失败时表现不同。
  • 后端只滚 hl-product-service-v2;order-v3 / 网关 / 小程序端 / 其它服务一律不动。
  • 无表结构变更、无 Flyway、无数据迁移;group_tour_batch.batch_status 的列定义与取值字典不变。

七、测试环境已验证

测试环境(api.test.1814.love)经真实网关实测三条路径,落库均以 SQL 复核:

路径 实测结果
无活跃订单 → 取消 code=200,batchStatus=CANCELLED(不回归)
真实下单后 → 取消 code=200,batchStatus=CANCELLING(不回归)
注入聚合失败 → 取消无订单班期 code=200,batchStatus=CANCELLING,后端 WARN「取消班期: 活跃订单数聚合失败, 取保守侧 CANCELLING」

聚合失败用「只压单个 Feign 客户端超时」的方式构造,未停 order-v3;取证后配置已还原并复核一致。合并进 dev-v3 后又在 dev-v3 构建上复核过正常路径。本机单测 BUILD SUCCESS(1621 例,0 失败 0 错误),含新增的聚合失败用例与架构门禁。

关联 / 联系人