文件
hl-api-changelog/changelogs-v2/2026-09/15_7327_团单取消终止REFUND待办owner回落团级认领人-修改接口-管理后台.md
T

29 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 7327 团单取消/终止产生的 REFUND 待办:owner 回落到团级认领人,不再恒为广播态 admin wx(GIT) 修改接口 deployed not_required not_required 2026-09-15 PR #7679(Issue #7327 AC-17)已 squash 合并 dev-v3(合并提交 6169a612a)。2026-09-15 代码已确认部署在测试服(deploy-status.sh 实测),并对 GET /v3/admin/order/todos 做了真实网关取证,证实了字段契约本身(含 2026-09-14 起草时写错的 todoTypeName/groupBatchId 已更正为 todoTypeLabel/teamNo,并补充了此前遗漏的 todoTypes[] 聚合数组)。backend_status 记 deployed:代码已部署且响应字段契约已实测。⚠️ 如实标注未覆盖范围:本单核心修复点(团单户级为空、回落读团级认领人这一分支)本轮未能采到「团单+户级为空+团期已认领+OPEN」四条件同时成立的真实样本,抓到的 REFUND 样本都是户级直接抢单的散客单——该分支目前只有单测覆盖,非测试服端到端验证,详见「八、测试环境已验证」。另需注意 #7459(PR #7731)已把本条讨论的取消触发路径改为约 1 秒的异步 outbox,详见正文「切换状态时的必要动作」更正。PR 正文已记录 2026-09-14 一次测试服实测(取消订单 2099318713927778306 产出 owner_user_id=NULL 的缺陷现象),那是修复前的缺陷复现证据,不是修复后的验证。gateway_status=not_required:受影响的 GET /v3/admin/order/todos 是已有路由,本次未新增/修改任何路径。frontend_status=pending:待前端确认房务待办列表页是否需要对「owner 从广播态变为团级认领人」这类变化做任何界面提示,故不定为 not_required。 前端 not_required(grep 实证):todos/index.vue owner 展示为 ownerName || "团队" 通用渲染,字段用 teamNo/todoTypeLabel 与真实契约一致;owner 从 null 变真实 ID 纯取值变化、scope 换桶为服务端行为,前端零改动。 2026-09-15 dev-v3

房务待办: 团单取消/终止产生的 REFUND 待办 owner 回落到团级认领人

存放目录:

  • 一期(v2,无 order-v3 标签的工单)→ changelogs/{YYYY-MM}/
  • 二期(v3,order-v3 标签的工单)→ changelogs-v2/{YYYY-MM}/

服务: hl-order-service-v3 (端口 8086) PR: #7679(Issue #7327 AC-17) Issue: #7327 日期: 2026-09-15 影响范围: 管理后台房务待办列表 GET /v3/admin/order/todos 中,团单取消/终止产生的 todoType=REFUND 记录的 ownerUserId/ownerName 取值,以及该记录归属的 scope(我的/同事在跟)


⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写)

  • 本次变了什么:HouseAssignmentService#findClaimerIdByOrder(HouseAssignmentService.java:767-777,2026-09-15 对照 origin/dev-v3 核实,因中间插入 #7459 outbox 改造行号较 2026-09-14 起草时的 752-762 漂移约 +15 行)在户级 order_hotel_requirement.claimer_id 为空时,新增回落逻辑——查该订单所属团期,读团级认领人(GroupBatchService#listHouseClaimersIncludeDeleted)作为兜底;HouseTodoService.handleOrderCancelled/handleOrderTerminated(HouseTodoService.java:1785、:1886,同日一并核实更新)取 owner 时调的就是这个方法,两处均无需改动即自动受益。⚠️ handleOrderCancelled 的触发方式已在 #7459(PR #7731,见另一份 changelog)改为异步 outbox 命令,详见本节末尾追加说明。
  • 前端/调用方以前以为的是什么:团单(order_main 挂了团期)取消或终止行程时产生的 REFUND 待办,ownerUserId 会像散客单一样,取自该订单用房需求的户级抢单人(order_hotel_requirement.claimer_id);抢单人存在就应该有值。
  • 实际现在是什么,以及此前的真实缺陷:团单的户级 claimer_id 结构性恒为 NULL——团单房务归属走的是团级认领(认领入口是抢单池,而抢单池的基础过滤 HotelRequirementMapper.java:718 w.isNull(OrderInfo::getProductBatchId) 把团单排除在外,团单根本进不了户级抢单流程)。修复前:这导致团单取消/终止产生的 REFUND 待办 ownerUserId 恒为 NULL,全部落入广播桶(PR 正文记录了 2026-09-14 的一次测试服实测:取消订单 2099318713927778306 产出 house_todo id=2099341634310201345, todoType=REFUND, owner_user_id=NULL,同团 house_claimer_id=1001 却没有被用上)。修复后:户级取不到时会回落读团级认领人,团单产生的 REFUND 待办会有真实 owner;两级都无归属时仍保留广播态(ownerUserId=null),不是失败,是设计内语义。

一、背景(选填)

Issue #7327 AC-17:口径 8 把 HouseAssignmentService#hasActiveAssignment 扩成两段判定后,团单取消/终止也会走进 HouseTodoService 的「已配房」分支产 REFUND 待办(HouseTodoService.java:1750、原 handleOrderCancelled 分支 2a)。但取 owner 的那条链路当时没有跟着扩——两处都只调 findClaimerIdByOrder,而它此前只读户级 claimer_id。

维度 证据
户级 claimer_id 写口 全仓只有两处:HotelRequirementMapper.casClaimByRequirementId(抢单,WHERE claimer_id IS NULL)、casTransferByRequirementId(转单,WHERE claimer_id 已非空)
抢单入口的过滤 HotelRequirementMapper.java:718:w.isNull(OrderInfo::getProductBatchId),团单(product_batch_id 非空)结构性进不去
结论 团单户级 claimer_id 永远是 NULL,不是偶发脏数据

(以上引用自 PR #7679 正文「🔴 户级恒 NULL 是结构性的,不是『数据没跑到』」一节)

修复只动了 owner 取值这一条链路,不改「是否产生 REFUND 待办」的既有判定(hasActiveAssignment/口径 8 是先于本次改动就存在的逻辑,不在本次变更范围内)。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 房务待办列表 GET /v3/admin/order/todos 响应内容修正 团单取消/终止产生的 todoType=REFUND 记录,ownerUserId/ownerName 从恒为 null 改为回落团级认领人

三、接口详情

响应字段结构、请求参数、错误码均未变化,本次只修正了特定条件下返回内容的取值(一个此前恒为 null 的字段,在团单场景下会有真实值)。

1. 房务待办列表 GET /v3/admin/order/todos

VO: HouseTodoPageReqVO → Result<HouseTodoListRespVO>

使用场景

房务在「待办」页面查看自己的/同事的/全部待办时调用,13 个查询参数支持按归属范围、类型、状态、紧急度等筛选。本次起,团单(挂了团期的子订单)取消或终止后产生的 todoType=REFUND 待办,若该团有房务认领人,会带着真实 ownerUserId 出现——这决定了它出现在谁的 scope=mine 列表里,以及是否出现在别人的 scope=others 列表里。

入参

字段 位置 类型 必填 约束 说明
scope Query String ❌ mine(默认)/others/all mine=owner=当前用户 或 owner=NULL;others=owner≠当前用户 且 非 NULL;all=不过滤(仅房务组长/超管可用)。本次未改语义,但受影响记录会因 owner 从 NULL 变为团级认领人 ID 而换到不同 scope 桶
todoType Query String ❌ 逗号分隔多选,如 REFUND,SWAP_HOTEL 待办类型过滤,空=全部
status Query String ❌ OPEN/RESOLVED 状态过滤,空=全部
urgency Query String ❌ danger/warn/normal 紧急度过滤(运行时推导值)
keyword Query String ❌ ≤32 字 模糊搜 title/reason/团号
orderId Query Long ❌ - 订单 ID 过滤
ownerUserId Query Long ❌ 配合 scope=others/all 归属房务 ID 过滤
hotelId Query Long ❌ - 酒店 ID 过滤
createTimeFrom / createTimeTo Query String(ISO 8601) ❌ - 创建时间范围
overdueMinutes Query Integer ❌ - 仅看超时 N 分钟以上
sortBy Query String ❌ 默认 urgency,desc,createTime,desc 排序
pageNo / pageSize Query Integer ❌ 继承自 PageParam,本次未改 分页

(以上入参字段结构本次未改,见 HouseTodoPageReqVO.java)

出参 Result<HouseTodoListRespVO>

字段 类型 说明
data.list[] Array<Object> ⚠️ 2026-09-15 核实更正:这是订单聚合行(一个订单一行,同订单多类型待办聚合进 todoTypes[]),不是「待办列表(已按默认排序)」这种一条待办一行的旧描述——2026-09-14 起草时未对照源码,按字面猜测成了扁平列表,实际结构见 HouseTodoItemVO.java。本条 changelog 讨论的 REFUND 类型走顶层「主标签」兼容字段,读顶层字段即可拿到 owner,不强制读 todoTypes[]
data.list[].id Long 该行「主标签」(本单最高紧急度类型)对应的待办 ID
data.list[].todoType String 该行「主标签」类型 code,本次涉及 REFUND
data.list[].todoTypeLabel String 待办类型中文标签。⚠️ 字段名更正:字段是 todoTypeLabel,不是 2026-09-14 起草时写的 todoTypeName(源码 HouseTodoItemVO.java 无 todoTypeName 字段)
data.list[].title String 标题,如「客人取消订单 · 请处理酒店退订」/「客人终止行程 · 请处理酒店退订」
data.list[].orderId Long 订单 ID
data.list[].orderNo String 订单号
data.list[].teamNo String/null 团号(未生成时为 null)。⚠️ 字段名更正:字段是 teamNo,不是 2026-09-14 起草时写的 groupBatchId(该 VO 里不存在 groupBatchId 字段,写成这个名字是未对照源码的臆造)。本次涉及的记录该字段应非空(团单才会走到本次修复的回落逻辑)
data.list[].todoTypes[] Array<Object> 本单待办类型标签数组(同订单多类型聚合,一类型一标签),2026-09-14 起草时遗漏未记录。子字段含 typeCode/typeLabel/urgency/count/derived/todoId/requirementId/unreadCount,见 HouseTodoItemVO.TodoTypeTag
data.list[].ownerUserId Long/null 本次修正取值来源。归属房务 ID,null=广播态。团单场景下:户级抢单人为空时,本次起改为读团级认领人;两级都空仍为 null(设计内广播态)
data.list[].ownerName String/null 随 ownerUserId 联动。归属房务姓名;ownerUserId 非空时应有对应姓名
data.total Long 总条数(过滤后,分页前)
data.stats Object 按 todoType 分类的统计(9 类),本次未改结构

(fromValue/toValue/reason/urgency/status/productType/orderTodoCount/guestName/personsDesc/hotelId/assignmentId/createTime/elapsedMinutes/requirementSummary/requirementVersion/hasUnresolvedReturn/departDate/derived/unreadCount/requirementId 等其余字段本次未改,且非本条 changelog 讨论重点,完整定义见 HouseTodoItemVO.java)

(reason/urgency/status/hotelId/assignmentId/travelerCount/departDate 等其余字段本次未改,未逐一列出,见 HouseTodoItemVO.java)

请求示例

GET /v3/admin/order/todos?scope=mine&todoType=REFUND&status=OPEN
Authorization: Bearer <token>

响应示例

以下字段名称/结构 2026-09-15 已对照源码 HouseTodoItemVO.java 更正(2026-09-14 起草版把字段名写成了 todoTypeName/groupBatchId,源码实际是 todoTypeLabel/teamNo,且遗漏了 todoTypes[] 聚合数组,见「出参」节说明);orderId=30456/teamNo=90001 取自 HouseAssignmentServiceTest#findClaimerIdByOrder_householdNullAndGroupClaimed_returnsGroupClaimerId 用例夹具(团级认领人 houseClaimerId=2002),其余展示性字段(id/title/orderNo/时间等)为示意值,不是测试服抓包报文:

{
  "code": 200,
  "message": "成功",
  "data": {
    "list": [
      {
        "id": "70500",
        "todoType": "REFUND",
        "todoTypeLabel": "退订",
        "title": "客人取消订单 · 请处理酒店退订",
        "reason": "客人临时取消行程",
        "fromValue": null,
        "toValue": null,
        "urgency": "danger",
        "status": "OPEN",
        "orderId": "30456",
        "orderNo": "26-0518",
        "teamNo": "90001",
        "productType": "GROUP",
        "orderTodoCount": 1,
        "todoTypes": [
          { "typeCode": "REFUND", "typeLabel": "退订", "urgency": "danger", "count": 1, "derived": false, "todoId": "70500", "requirementId": null, "unreadCount": null }
        ],
        "guestName": "赵先生",
        "hotelId": 11,
        "ownerUserId": "2002",
        "ownerName": "小呼",
        "createTime": "2026-09-14T10:13:00",
        "elapsedMinutes": 30
      }
    ],
    "total": 1,
    "stats": { }
  },
  "success": true
}

2026-09-15 测试服真实抓包对照(账号 1001,只读 GET,见「八、测试环境已验证」)——字段名与上方更正后的一致,证明 todoTypeLabel/teamNo/todoTypes[] 是真实线上契约而不是本次更正时的另一次猜测:

{
  "id": "2099707745790779394",
  "todoType": "REFUND",
  "todoTypeLabel": "退订",
  "title": "客人取消订单 · 请处理酒店退订",
  "status": "RESOLVED",
  "orderId": "2099707703508054018",
  "orderNo": "HL20260915115141720",
  "teamNo": "26-6171",
  "productType": "CORE",
  "ownerUserId": "1001",
  "ownerName": "admin",
  "createTime": "2026-09-15 11:51:52"
}

⚠️ 上面这条真实抓包是散客单(productType=CORE,户级直接抢单,不经过本条 changelog 的团级回落分支),只用来坐实字段名与 todoTypes[] 结构;它不是团单回落场景的证据,团单回落场景(户级为空、读团级认领人)目前仍只有单测覆盖,见「八、测试环境已验证」的说明。

两级都无归属(团期未认领)时的广播态形态(取自 HouseAssignmentServiceTest#findClaimerIdByOrder_householdNullAndGroupUnclaimed_returnsNullForBroadcast 用例:户级为空、listHouseClaimersIncludeDeleted 返回空列表):

{ "ownerUserId": null, "ownerName": null }

空数据 / 降级响应

筛选条件下无匹配待办:

{
  "code": 200,
  "message": "成功",
  "data": { "list": [], "total": 0, "stats": { } },
  "success": true
}

错误响应

keyword 超长(既有校验,本次未改):

{
  "code": 100001,
  "message": "keyword 最长 32 字",
  "data": null,
  "success": false
}

业务边界

  • 鉴权:走网关统一鉴权,未登录 401;scope=all 仅房务组长/超管可用(既有逻辑,本次未改)。
  • 本次只改变 REFUND 类型记录、且仅限满足两个条件同时成立时:①该订单是团单(orderService.resolveGroupBatchLinks 能解析出 groupBatchId);②户级 order_hotel_requirement.claimer_id 为空。散客单(无团期归属)的 REFUND 待办行为逐字节不变——findClaimerIdByOrder_householdClaimerPresent_returnsHouseholdIdWithoutGroupLookup 用例断言了户级有值时不会额外查团期(HouseAssignmentServiceTest.java 新增用例)。
  • 归团判定走 OrderService#resolveGroupBatchLinks 门面,不直读 order_main.group_batch_id:工单 #7083 遗留的、group_batch_id 未回填的老团单,只有经这个门面才能被正确识别为团单;直读该列会把它们误判为散客单,本次修复对它们不生效(HouseAssignmentService.java:788- 起 findGroupBatchClaimerIdByOrder 私有方法 javadoc,2026-09-15 核实更新)。
  • 团级认领人只经 GroupBatchService#listHouseClaimersIncludeDeleted 读:与既有 HouseGroupBatchClaimGuard、HouseGroupBatchBoardManager 等同一单源,不引入第二个认领人数据来源。
  • 两级都空仍返回广播态 null,不是缺陷:这是既有设计语义(未认领时任一房务可接),本次未改这条语义,只是改了「取不到户级值时该不该再查一层」。

四、契约约束与正确调用方式(接口类必写)

本节只写后端接受/拒绝查询参数的规则与调用后必须知道的取值规则,不写 UI 渲染建议。

✅ 正确 / ❌ 错误 理解对照

场景 说明
✅ 团单 REFUND 待办 ownerUserId 非空时,展示为「该团认领房务在跟」 这个 owner 来自团级认领人,不是户级抢单人;前端不应把它误标为「已抢单」(散客单语义),应标「团期认领人」或直接沿用既有的房务姓名展示(字段名不变,语义按订单是否团单区分即可,无需新增字段)
✅ 团单 REFUND 待办 ownerUserId 为 null 时,视为广播态(任一房务可处理) 与散客单未抢单时的语义完全一致,不是新语义
❌ 认为团单 REFUND 待办的 ownerUserId 一定等于团级认领人 只有「户级 claimer_id 为空」这一条件成立时才回落团级;理论上若某天户级抢单口径变化导致团单也能写户级 claimer_id(当前无此写口),则仍以户级值优先
❌ 用 groupBatchId 字段是否非空来判断「这条待办的 owner 一定不是广播态」 团期未认领(listHouseClaimersIncludeDeleted 返回空)时,团单待办的 ownerUserId 依然是 null

切换状态时的必要动作

无状态切换(本端点为只读查询)。⚠️ 2026-09-15 更正:2026-09-14 起草时写的「立即可查到」已不成立——同日晚些时候合并的 #7459(PR #7731,另一份 changelog)把订单取消(handleOrderCancelled)触发的房务处置改成了异步 outbox 命令,实测约 1 秒内完成;订单终止(handleOrderTerminated)未受 #7459 影响,仍走原 HouseTodoEventListener 同步事件路径。也就是说:团单终止触发的带真实 owner 的 REFUND 待办目前仍是同步可查;团单取消触发的这类待办现在需要等约 1 秒(详见 changelogs-v2/2026-09/15_7459_订单取消房务处置改走outbox耐久命令流团逐户REFUND-修改接口-管理后台.md),前端如果在取消成功后立即查询本端点校验 owner 是否正确,需要预留这个延迟窗口。


五、数据库行为

本次改动位于读路径(findClaimerIdByOrder 只读团级认领人,不写任何列),但它的调用方 createRefundTodo(现分两个重载:3 参业务入口 HouseTodoService.java:2043 起,4 参实现 :2066 起,2026-09-15 核实更新)会把取到的值写进 house_todo.owner_user_id 列。本次不新增任何写口/写路径,只是让既有写口(团单取消/终止触发的 REFUND 待办创建)在写这一列时,从「恒写 NULL」变成「先查户级、再查团级、最后才写 NULL」。

场景 house_todo.owner_user_id(新建 REFUND 待办时)
散客单,户级已抢单 户级 claimer_id(本次未改)
散客单,未抢单 NULL(本次未改)
团单,团期已认领 本次起:团级 house_claimer_id
团单,团期未认领 NULL(不变,广播态)

该待办创建走 @Transactional(rollbackFor = Exception.class)(3 参入口的注解在 HouseTodoService.java:2042,2026-09-15 核实更新),dedupKey="REFUND-{orderId}" 幂等复用,本次未改。


六、边界行为

  • 未登录 → 401(网关拦截)
  • keyword 超长 → 100001(既有,未改)
  • 无匹配待办 → 200 + 空列表 + total=0
  • 订单查不到(理论场景,触发方是已存在的订单事件)→ findClaimerIdByOrder 返回 null,不抛错(HouseAssignmentServiceTest#findClaimerIdByOrder_orderMissing_returnsNullWithoutGroupResolve 覆盖)
  • 非团单 → 不查团级认领人,直接返回户级值或 null(findClaimerIdByOrder_nonGroupOrder_returnsNullWithoutClaimerLookup 覆盖)
  • 团期未认领 → owner 为 null,广播态,不是错误

六.5、枚举 / 数据字典(接口出现枚举时必写)

本次改动不引入任何新枚举值。受影响记录的 todoType 恒为既有值 REFUND,未新增/修改该枚举的取值域,仅作为定位记录的上下文列出:

todoType(com.hulalv.house.enums.HouseTodoType,节选)

所属字段: HouseTodoItemVO.todoType(GET /v3/admin/order/todos,既有字段) | 类型: String

值 中文 说明
REFUND 退订 本次唯一涉及的类型;订单取消/终止且已配房时产生,本次只改其 ownerUserId 取值来源,不改该枚举值本身

六.6、修改前后对比(修改/删除类接口必写,新增跳过)

字段级对比

字段 改前 改后
list[].ownerUserId(团单 REFUND 待办,团期已认领) 恒为 null 团级认领人 ID(如 2002)
list[].ownerName(同上条件) 恒为 null 团级认领人姓名快照
list[].ownerUserId(散客单 REFUND 待办) 户级抢单人或 null 不变
list[].ownerUserId(团单 REFUND 待办,团期未认领) null 不变(仍为 null,广播态)

行为级对比

行为 改前 改后
团单取消/终止产 REFUND 待办的 owner 归属 恒落广播桶,全体房务在自己的 scope=mine 都能看到 团期已认领时,归属到该团认领人的 scope=mine;其他房务改为在 scope=others/all 里看到(归属他人)
findClaimerIdByOrder 内部查询次数(团单,户级为空场景) 只查一次(户级) 新增两次库查(orderService.getById + resolveGroupBatchLinks),仅发生在取消/终止产 REFUND 时,非热路径
散客单 REFUND 待办 owner 归属 不变 不变

六.7、影响评估(修改/删除类必写)

  • 是否破坏向后兼容:否。请求参数、响应字段结构、错误码均未变化;改动完全体现在特定条件下(团单 + 户级为空 + 团期已认领)的 ownerUserId/ownerName 取值上。
  • 前端是否必须同步上线:否,不同步上线不会导致接口调用失败或报错。但会有真实的行为差异:此前所有房务都能在自己的「我的待办」里看到团单 REFUND 待办(广播态),本次上线后,团期已认领的这类待办会收窄到认领人一人的「我的待办」,其他房务需要切到「同事在跟」或「全部」才能看到。若前端/运营对「REFUND 待办为什么从我的列表消失了」没有心理准备,可能产生疑问,建议知会一线房务。
  • 前端 workaround 清理点:无(此前没有相关字段可供 workaround)。

七、不影响范围(显式声明, 帮前端/QA 缩小排查面)

  • 仅影响:GET /v3/admin/order/todos 中,团单取消/终止产生的 todoType=REFUND 记录的 ownerUserId/ownerName 取值及其 scope 归属。
  • 零影响:
    • 散客单的 REFUND 待办 owner 取值(逐字节不变)
    • REFUND 待办是否产生的判定(hasActiveAssignment/口径 8,先于本次改动即已存在)
    • REFUND 待办的 RESOLVE 闭环(由主 API V5.49 退款成功触发,本次未改)
    • 其余 8 类待办类型(SWAP_HOTEL/HOTEL_REPLY_TIMEOUT/PENDING_ARRANGE/PENDING_FINALIZE/UNREAD_CHAT 等)
    • 户级抢单/转单流程(casClaimByRequirementId/casTransferByRequirementId)
    • 团级认领/释放流程本身(GroupBatchService#listHouseClaimersIncludeDeleted 只读,未新增写口)
    • #7326(分房重算/人工微调)相关端点,见 changelogs-v2/2026-09/15_7326_团期分房重算人工微调把重判不平已完成户退回处理中-修改接口-管理后台.md

八、测试环境已验证

部署与实测状态:修复本身(PR #7679,合并提交 6169a612a)已合入 dev-v3 并是测试服当前部署基线(hl-order-service-v3 2026-09-15 13:12 部署于 6a7b43a17,经 deploy-status.sh 实测确认)的祖先,代码已在测试服跑着。2026-09-15 对 GET /v3/admin/order/todos 做了真实网关取证(账号 1001,只读 GET),证实了字段契约本身(见下方「2026-09-15 测试服真实取证」)。⚠️ 如实标注未覆盖范围:本单核心修复点(团单户级为空、回落读团级认领人这一分支)本轮没有证实——当天在测试服上没能定位到一个满足「团单 + 户级 claimer_id 为空 + 团期已认领 + REFUND 待办处于 OPEN 状态」四个条件同时成立的真实样本,抓到的 REFUND 样本都是户级直接抢单的散客单。这不是负面证据(不代表修复无效,单测已覆盖该分支),backend_status 仍记 deployed(代码已部署、字段契约已实测),但团单回落分支这一核心场景请前端联调时按「单测覆盖、未端到端验证」对待。以下分三部分:

修复前的缺陷复现(PR 正文自报,2026-09-14 测试服实测,验证的是问题存在,不是修复生效):

取消订单 2099318713927778306
  → house_todo id=2099341634310201345, todo_type=REFUND, owner_user_id=NULL
  同团 order_group_batch 2099318712929566721: house_claimer_id=1001, house_claimed_at=10:13:13
  该户 order_hotel_requirement.claimer_id 取消前快照即为 NULL(非本次取消动作清掉)

修复后的本机自动化单测(origin/dev-v3,HouseAssignmentServiceTest.java 新增 5 例):

findClaimerIdByOrder_householdClaimerPresent_returnsHouseholdIdWithoutGroupLookup
  → 户级有值时直接返回,不查团期(verify never resolveGroupBatchLinks/listHouseClaimersIncludeDeleted) ✓
findClaimerIdByOrder_householdNullAndGroupClaimed_returnsGroupClaimerId
  → 户级为空、团期已认领(houseClaimerId=2002) → 返回 2002(本单修复点:修复前此处恒为 null) ✓
findClaimerIdByOrder_householdNullAndGroupUnclaimed_returnsNullForBroadcast
  → 户级为空、团期未认领 → 返回 null,广播态(verify 确实查过团级,不是没问就落空) ✓
findClaimerIdByOrder_nonGroupOrder_returnsNullWithoutClaimerLookup
  → 非团单(resolveGroupBatchLinks 返回空 Map)→ 返回 null,不查团级认领人 ✓
findClaimerIdByOrder_orderMissing_returnsNullWithoutGroupResolve
  → 订单查不到 → 返回 null,不判团、不抛错 ✓

PR 自报定向轮:Tests run: 179, Failures: 0, Errors: 0, Skipped: 6(Skipped 为既有 @Disabled,非本次引入)。

2026-09-15 测试服真实取证(账号 1001,只读 GET,覆盖字段契约,未覆盖团单回落分支):

GET /v3/admin/order/todos?scope=mine&orderId=2099707703508054018&status=RESOLVED&pageNo=1&pageSize=10 → 200
  → 命中 1 条 REFUND,字段名与「出参」节更正后的一致:
    todoTypeLabel="退订"(不是 todoTypeName)、teamNo="26-6171"(不是 groupBatchId)、
    存在 todoTypes[] 聚合数组、ownerUserId="1001" 正确回显
  → 该订单 productType=CORE,是散客单直接抢单场景,不是本单要修的团单回落场景
GET /v3/admin/order/todos?scope=mine&todoType=REFUND&status=OPEN → 200,list=[],stats.REFUND=9
  → 说明当前测试库里存在 9 条 OPEN 状态的 REFUND(按 owner 过滤后),但受「订单聚合改造」
    的聚合/排序规则影响,未能在这次会话里筛出具体是哪些订单、是否含团单回落样本,
    本节不据此下任何结论,如实记录为未查明

网关:本次未新增/修改路径,沿用既有路由。测试服部署已确认(见上),字段契约已实测,但团单回落分支这一核心修复点仍待专项造数验证(造一个团单:团期已认领 + 该户从未走户级抢单 + 触发取消或终止),验证方式建议按此专项补测。


十、相关文档

  • 关联 Issue: wx/HL#7327
  • 关联 PR: wx/HL#7679
  • 同一 Issue 相关的既有背景(住宿核单/月度对账): changelogs-v2/2026-09/13_7327_团期配房行合流核单结算-修改接口-管理后台.md、changelogs-v2/2026-09/14_7327_月度对账并入团期计划与分房行-修改接口-管理后台.md
  • 关联改动(订单取消房务处置改走 outbox,改变本条讨论的取消路径时序,工单 #7459,已部署已实测): changelogs-v2/2026-09/15_7459_订单取消房务处置改走outbox耐久命令流团逐户REFUND-修改接口-管理后台.md

关联 / 联系人

链接

联系人

  • 后端负责人: @wx