文件
hl-api-changelog/changelogs-v2/2026-09/12_7535_团期接口返回值整改非破坏批-修改接口-管理后台.md
Mimingguang 10502ccdd3
changelog-filename-gate / validate (push) Failing after 2s
chore(changelog): 补回写漏网 8 条(7510×2/7511/7512 verified+not_required;7513/7530/7531/7535 not_required)
7510/7511/7512 代码早已随供应商关系系列交付(a17a2c2a/4bedc8be),实证后回写 verified 挂 a17a2c2a;
11_7510 为正本 12_7510 的重复副本(canonical_path),标 not_required 消除 pending;
7513/7530/7531/7535 实证前端零改动 not_required。
2026-09-13 09:51:52 +08:00

88 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 7535 团期接口返回值整改·非破坏批(opsStage / 负责人 / 报账人 / 审批行补全 / 枚举中文配对 / 命名统一) admin jw(GIT) 修改接口 deployed not_required not_required mmg 2026-09-12 19 个团期读端点纯加响应字段,既有 key 的名称/类型/取值/null 语义一行未动,前端零改动即可继续运行。零 DDL、零错误码、零网关改动。四组旧字段已标 @Deprecated 但本批不删,请新代码逐步切到新名。 前端 2026-09-13 闭环 not_required:前端无严格 schema 校验多余 key 静默忽略,五组 @Deprecated 旧字段本批仍返回不 break,改读新名为非强制改进项本批不动。零业务代码改动。 2026-09-13 dev-v3

order-v3: 团期接口返回值整改·非破坏批

服务: hl-order-service-v3 PR: #7583 Issue: #7535


⚠️ 关键变化

🟢 本批纯加字段,前端零改动即可继续运行。 19 个端点只多出响应 key,既有 key 的名称、类型、取值与 null 语义一行没动。新字段按需取用。

🔴 opsStage 以后端八桶为准,原型侧的 stage 取值需要改(wx 2026-09-11 定案)。后端八值: RECRUIT 招募中 / FORMED 已成团 / PENDING_TRIP 待出行 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / AUDITING 核团中 / CHECKED 已验团 / DISBANDED 已流团。 FORMED 是复合桶(RESOURCE_PREPARING + MATERIAL_PREPARING 两个九态都落它)。 前端不要再自己复刻九态 → 八桶的折叠逻辑,直接读 opsStage。

🔴 四个 Text / Label 后缀字段已标 @Deprecated,本批不删、值不变,请新代码改用同值的 Name 字段,删除时间另行通知:

旧字段(仍返回) 新字段(同值) 所在响应
batchStatusLabel batchStatusName 团期看板行
productBatchStatusLabel productBatchStatusName 团期分页项
statusText statusName 芯片逐户行
bizTypeText bizTypeName 审批中心统一列表行

🔴 审批中心统一列表的 orderNo / customerName / departDate 只在 bizType=WITHDRAW 行有值,DISBAND 行恒 null(与已有的 orderId 同一条规则)。前端按行类型判断再渲染,否则 DISBAND 行会出现三个空列。

🔴 checkedResourceTypes 恒 ["HOTEL"]:需求确认预检只检查住宿、不检查用车,ready=true 不代表用车需求齐备。

🔴 联系人 key 统一为 customerName:芯片逐户 / 合同逐户 / 行程汇总预警行 / 行程下钻逐户四处新增 customerName,与既有 contactName 逐字同值;contactName 已标 @Deprecated,本期仍返回、计划下一期删除。 报名清单「联系人」列显示 — 是前端读错 key(后端一直给的是客户姓名),请改读 customerName。

🔴 团期主键 key 统一为 groupBatchId:名额调整 / 芯片详情 / 合同面板三处响应新增 groupBatchId,与既有 batchId 逐字同值、同为字符串形态;batchId 已标 @Deprecated。 staff 的 PUT .../staff 与 GET .../staff/candidates 响应新增 productBatchId + groupBatchId—— ⚠️ 候选端点的 groupBatchId 在团期尚未创建时为 null(staff 允许在成团前先配,该端点不报错),前端不得把它当必有主键去拼请求,否则会打出 /group-batch/null/...。 GET .../staff 返回裸数组、没有顶层信封,因此不带这两个 ID。

🔴 芯片逐户行与合同逐户行新增 teamNo(纯加)。⚠️ 逐行各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户是 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成订单号、不拿团期编号顶替,前端请按 null 渲染「—」。 另:「报名清单 / 财务 / 预支」三张表的同名字段由**破坏批那张单(#7536)**交付,两批的字段名、类型与 null 语义完全一致,前端可按同一套逻辑渲染。

🔴 应收 / 已收 / 待收命名统一:团期详情新增 receivableAmount / receivedAmount(与既有 totalReceivable / totalReceived 同值,旧名已 @Deprecated、计划下一期删除);团期分页项新增 unpaidAmount = max(0, 应收 − 已收),恒非负、恒非 null。⚠️ 与财务 tab 的同名字段同名不同源,权威待收值仍以财务 tab 为准。财务 tab 那 12 个金额字段的 JSON 形态本批不变,其变更由另一张单交接。

🔴 芯片逐户新增房务负责人三件套 claimerId / claimerName / claimerSource,六个芯片端点统一给。 claimerSource 取值 BATCH(团级指针)/ LEGACY(历史旧户的户级归属)/ null(真实无人认领,此时另两个字段也为 null)——让前端不必猜这个名字是团级还是户级。

🔴 十个裸 code 字段补齐了中文配对,统一兜底口径:code 为 null → Name 为 null;code 翻不出 → Name 回落原 code(不抛异常、不返空串)。


一、背景

团期模块的响应体长期存在四类不一致,都是前端一眼能看见、但后端没人系统清过的:

  1. 八桶只能筛、不能读:GET /v3/admin/order/group-batch 的入参早就支持按八桶 opsStage 筛选,出参却没有这个字段——前端只能拿九态 batchStatus 自己再折一遍桶,折叠规则一分叉就和服务端筛选结果对不上。
  2. 中文名后缀三套并存:同一个 batchStatus 在分页项叫 batchStatusName、在看板行叫 batchStatusLabel;芯片叫 statusText、审批叫 bizTypeText。同时还有 10 个裸 code 字段根本没有中文配对,前端只能自己维护映射表。
  3. 同义字段各叫各的:联系人在团期域 4 个 VO 里叫 contactName、在其余 8 个 VO 里叫 customerName;团期主键在 3 个 VO 里叫 batchId、其余一律 groupBatchId;整团应收/已收在三个端点有三套名字。
  4. 该有的字段缺位:芯片逐户看不到房务负责人、逐户行看不到团号、审批中心统一列表的退单户行看不到订单号与客户姓名、staff 名册看不到报账人等级、预检响应不告诉前端它到底检查了什么。

本单只加不改:19 个端点新增 47 个响应 key,旧字段一律同值保留并打 @Deprecated(本批不删)。 路径、方法、请求参数、既有字段的名称/类型/取值/null 语义一律不变,向后兼容纯增。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 团期分页列表(A1) GET /v3/admin/order/group-batch 修改 响应行新增 opsStage / opsStageName / unpaidAmount / productBatchStatusName
2 团期看板 GET /v3/admin/order/group-batch/board 修改 响应行新增 opsStage / opsStageName / batchStatusName
3 团期详情(A2) GET /v3/admin/order/group-batch/{groupBatchId} 修改 新增 opsStage / opsStageName / receivableAmount / receivedAmount / thresholdSourceName
4 团期配房逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/hotel 修改 信封 +2、逐户 +6
5 团期配车逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/vehicle 修改 同上
6 团期配导游逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/guide 修改 同上
7 团期配摄影逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/photo 修改 同上
8 团期合同逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/contract 修改 同上
9 团期保险逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/insurance 修改 同上
10 团期「合同保险」面板 GET /v3/admin/order/group-batch/{groupBatchId}/contracts 修改 信封 +1、逐户 +2
11 团期行程逐日汇总 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary 修改 天数预警行新增 customerName
12 团期行程某项逐户下钻 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary/nodes/{nodeKey} 修改 逐户行新增 customerName
13 审批中心统一列表 GET /v3/admin/order/group-batch/approvals/page 修改 新增 orderNo / customerName / departDate / approvalStatusName / bizTypeName
14 退单审批列表 GET /v3/admin/order/group-batch/withdraw/page 修改 新增 refundModeName / approvalStatusName
15 整团确认需求缺失预检 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check 修改 外层 +2、缺失项 +2
16 调整团期满团名额 PUT /v3/admin/order/group-batch/{groupBatchId}/capacity 修改 新增 groupBatchId
17 团期人员配置列表 GET /v3/admin/group-batch/{productBatchId}/staff 修改 每行新增 staffRoleName / reporterRank / reporterRankName
18 团期人员配置全量保存 PUT /v3/admin/group-batch/{productBatchId}/staff 修改 顶层 +2、每行 +3
19 团期人员配置候选列表 GET /v3/admin/group-batch/{productBatchId}/staff/candidates 修改 每项新增 6 个 key

三、接口详情

1. 团期分页列表(A1) GET /v3/admin/order/group-batch

VO: PageResult<GroupBatchPageItemRespVO>

使用场景

团期看板的分页列表。本单起每行多出 4 个 key:运营八桶 opsStage/opsStageName、整团待收 unpaidAmount、以及与 productBatchStatusLabel 同值的 productBatchStatusName。

入参字段表

字段 位置 类型 必填 约束 说明
pageNo / pageSize / productId / scope / batchStatus / opsStage / month / keyword / deadlineFrom / deadlineTo Query — — 本单一个入参都没改 含同名的入参筛选 opsStage,取值集与新出参 opsStage 完全一致

出参字段表

字段 类型 说明
opsStage String 本单新增。运营八桶:RECRUIT 招募中 / FORMED 已成团 / PENDING_TRIP 待出行 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / AUDITING 核团中 / CHECKED 已验团 / DISBANDED 已流团。由 batchStatus 九态折叠(FORMED 是复合桶 = RESOURCE_PREPARING + MATERIAL_PREPARING)。⚠️ batchStatus 为 null 或不在九态内(历史脏数据)时本字段为 null
opsStageName String 本单新增。八桶中文名;与 opsStage 同生同灭(一起为 null)
unpaidAmount String 本单新增。整团待收 = max(0, receivableAmount − receivedAmount),恒非负、恒非 null(两个被减数任一为 null 按 0 计;已收多于应收的历史脏数据返 0,不透负数)。JSON 字符串形态。⚠️ 与财务 tab 的同名字段同名不同源,权威待收以财务 tab 为准
productBatchStatusName String 本单新增。与 productBatchStatusLabel 逐字同值同源(产品域 Feign 给出,order 域不再映射一次)
productBatchStatusLabel String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 productBatchStatusName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch?pageNo=1&pageSize=20
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "groupBatchId": "2096412454643802114",
        "batchStatus": "RESOURCE_PREPARING",
        "batchStatusName": "资源准备中",
        "opsStage": "FORMED",
        "opsStageName": "已成团",
        "productBatchStatus": "FINISHED",
        "productBatchStatusLabel": "已结束",
        "productBatchStatusName": "已结束",
        "receivableAmount": "321750.00",
        "receivedAmount": "55000.00",
        "unpaidAmount": "266750.00"
      }
    ],
    "total": 28,
    "page": 1,
    "pageSize": 20
  },
  "success": true
}

空数据 / 降级响应

库里存在九态之外的脏 batch_status 时,只影响那一行:该行 opsStage 与 opsStageName 同为 null,batchStatus/batchStatusName 照旧(后者回落原 code),整页不会 500。未建团行 opsStage=RECRUIT。

错误响应

码 符号 触发
不变 400 pageNo / pageSize 非法
不变 GROUP_BATCH_PRODUCT_FETCH_FAILED(589515) productId 场景拉产品域班期失败
{
  "code": 589515,
  "message": "产品域班期获取失败",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 前端不要再自己复刻九态 → 八桶的折叠逻辑,直接读 opsStage。后端八桶是唯一真源(GroupBatchStageBuckets)。
  • unpaidAmount 是本行应收/已收的现算值,与财务 tab 的同名字段算法不同,某些历史脏数据下可能差一点。
  • productBatchStatusName / productBatchStatusLabel 在 productId 缺省的老调用里都是 null(不拉产品域),这一条与改前一致。

2. 团期看板 GET /v3/admin/order/group-batch/board

VO: List<GroupBatchBoardItemRespVO>

使用场景

团期看板的行列表。本单起每行多出 3 个 key:opsStage/opsStageName,以及与 batchStatusLabel 同值的 batchStatusName。

入参字段表

字段 位置 类型 必填 约束 说明
productId Query Long ✅ 产品 ID 本单不变
scope Query String ❌ 班期范围 本单不变

出参字段表

字段 类型 说明
opsStage String 本单新增。运营八桶:RECRUIT 招募中 / FORMED 已成团 / PENDING_TRIP 待出行 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / AUDITING 核团中 / CHECKED 已验团 / DISBANDED 已流团。由 batchStatus 九态折叠(FORMED 是复合桶 = RESOURCE_PREPARING + MATERIAL_PREPARING)。⚠️ batchStatus 为 null 或不在九态内(历史脏数据)时本字段为 null
opsStageName String 本单新增。八桶中文名;与 opsStage 同生同灭(一起为 null)
batchStatusName String 本单新增。与 batchStatusLabel 逐字同值(同一次装配取同一个变量,不会分叉)
batchStatusLabel String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 batchStatusName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/board?productId=2044306857534636034
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "groupBatchId": "2096412454643802114",
      "batchStatus": "RESOURCE_PREPARING",
      "batchStatusLabel": "资源准备中",
      "batchStatusName": "资源准备中",
      "opsStage": "FORMED",
      "opsStageName": "已成团"
    }
  ],
  "success": true
}

空数据 / 降级响应

未命中行(产品有班期、订单侧未建团)固定 batchStatus=RECRUITING,走同一条折桶得 opsStage=RECRUIT/招募中,不特判。脏状态行两个 opsStage 字段同为 null。

错误响应

码 符号 触发
不变 400 productId 缺失
{
  "code": 400,
  "message": "productId 不能为空",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 同一团期在 A1 分页、本端点、A2 详情三处的 opsStage 必然相同(同一个 resolve)。
  • batchStatusLabel 与 batchStatusName 永远同值,前端二选一即可。

3. 团期详情(A2) GET /v3/admin/order/group-batch/{groupBatchId}

VO: GroupBatchDetailRespVO

使用场景

团期详情。本单起多出 5 个 key:opsStage/opsStageName、与旧名同值的 receivableAmount/receivedAmount、以及 thresholdSource 的中文名 thresholdSourceName。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
opsStage String 本单新增。运营八桶:RECRUIT 招募中 / FORMED 已成团 / PENDING_TRIP 待出行 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / AUDITING 核团中 / CHECKED 已验团 / DISBANDED 已流团。由 batchStatus 九态折叠(FORMED 是复合桶 = RESOURCE_PREPARING + MATERIAL_PREPARING)。⚠️ batchStatus 为 null 或不在九态内(历史脏数据)时本字段为 null
opsStageName String 本单新增。八桶中文名;与 opsStage 同生同灭(一起为 null)
receivableAmount String 本单新增。与 totalReceivable 逐字同值、同一来源不重算,字段名与 A1 分页项 / 财务端点统一。JSON 字符串形态
receivedAmount String 本单新增。与 totalReceived 逐字同值、同一来源不重算。JSON 字符串形态
totalReceivable / totalReceived BigDecimal 值不变,本单起标 @Deprecated,本批不删;新代码请改读 receivableAmount / receivedAmount
thresholdSourceName String 本单新增。PRODUCT_REALTIME → 产品域实时值;SNAPSHOT_FALLBACK → 建团快照回退。thresholdSource 为 null 时为 null,取值不在枚举内时回落原 code
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2096412454643802114
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "groupBatchId": "2096412454643802114",
    "batchStatus": "RESOURCE_PREPARING",
    "batchStatusName": "资源准备中",
    "opsStage": "FORMED",
    "opsStageName": "已成团",
    "totalReceivable": "321750.00",
    "totalReceived": "55000.00",
    "receivableAmount": "321750.00",
    "receivedAmount": "55000.00",
    "thresholdSource": "PRODUCT_REALTIME",
    "thresholdSourceName": "产品域实时值"
  },
  "success": true
}

空数据 / 降级响应

thresholdSource 为 null 时 thresholdSourceName 也为 null;脏 batch_status 时两个 opsStage 字段同为 null。均不报错。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • thresholdSourceName 是派生只读字段(由 thresholdSource 现算),因此与它不可能分叉。
  • 新旧两对金额字段永远同值,前端二选一即可;旧名下一期删除。

4. 团期配房逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/hotel

VO: GroupBatchChipDetailVO

使用场景

团期看板「配房」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/hotel
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

5. 团期配车逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/vehicle

VO: GroupBatchChipDetailVO

使用场景

团期看板「配车」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/vehicle
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

6. 团期配导游逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/guide

VO: GroupBatchChipDetailVO

使用场景

团期看板「配导游」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/guide
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

7. 团期配摄影逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/photo

VO: GroupBatchChipDetailVO

使用场景

团期看板「配摄影」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/photo
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

8. 团期合同逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/contract

VO: GroupBatchChipDetailVO

使用场景

团期看板「合同」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/contract
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

9. 团期保险逐户明细 GET /v3/admin/order/group-batch/{groupBatchId}/chips/insurance

VO: GroupBatchChipDetailVO

使用场景

团期看板「保险」芯片下钻的逐户明细(六个芯片端点同构)。本单起信封多出 groupBatchId/aggregateStatusName,逐户行多出 teamNo/customerName/statusName 与三个负责人字段。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
teamNo String 本单新增。团号(order_main.team_no,形如 26-0001)。⚠️ 逐户各不相同,不是页头那一个团期编号的重复;⚠️ 订金支付成功后才生成,未付订金的户为 null(与是不是团期订单无关)。后端不做任何兜底——不返空串、不回退成 orderNo、不拿团期编号顶替
customerName String 本单新增。与 contactName 逐字同值(同一来源 order_main.customer_name)
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
statusName String 本单新增。与 statusText 逐字同值(同一次装配直接对拷)
statusText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 statusName
claimerId String 本单新增。该户房务负责人 adminId(字符串形态);整团与该户均无人认领时为 null
claimerName String 本单新增。负责人姓名;与 claimerId 同生同灭
claimerSource String 本单新增。BATCH 取自团级指针 order_group_batch.house_claimer_id(绝大多数情况)/ LEGACY 该户在历史旧户冻结名单内、取自该户 order_hotel_requirement.claimer_id / null 真实无人认领(此时另两个字段也为 null)
aggregateStatusName String 本单新增(信封层)。整团聚合态中文名:待开始 / 进行中 / 已完成 / 异常。aggregateStatus 为 null 时为 null
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/chips/insurance
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "chipLabel": "配房",
    "aggregateStatus": "TODO",
    "aggregateStatusName": "待开始",
    "totalCount": 4,
    "doneCount": 0,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "peopleCount": 2,
        "status": "PENDING",
        "statusText": "待房务配",
        "statusName": "待房务配",
        "needsIt": true,
        "updateTime": null,
        "claimerId": "30001",
        "claimerName": "张三",
        "claimerSource": "BATCH"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

团期无活跃子订单时 items 为空数组、三格计数为 0,新增字段不出现在任何行里(没有行)。整团未认领时逐户三个负责人字段全为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 六个芯片端点的响应结构完全一致,本单 6 处一起加,不因芯片类型特判——「这个团归谁」与看哪张芯片无关。
  • 负责人默认读团级指针:整团认领只写团级、不回写户级,只读户级会让「已被正常认领并配房的新团」全团显示空负责人。
  • 超管接管后 CAS 落空的残留户级归属属待清理脏数据,本字段仍如实给 BATCH——claimerSource 就是给前端/运营分辨用的。
  • 一个团里有的户有 teamNo、有的户是 null 是正常态,不是后端漏填。

10. 团期「合同保险」面板 GET /v3/admin/order/group-batch/{groupBatchId}/contracts

VO: GroupBatchContractBoardVO

使用场景

合同保险面板一屏读。本单起信封多出 groupBatchId,逐户卡片多出 teamNo 与 customerName。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
groupBatchId String 本单新增(信封层)。与 batchId 逐字同值,同为字符串形态
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
teamNo String 本单新增(逐户)。口径与芯片逐户行完全一致:order_main.team_no,逐户各不相同,未付订金为 null,无任何兜底
customerName String 本单新增(逐户)。与 contactName 逐字同值
contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/contracts
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "issuable": false,
    "totalCount": 4,
    "items": [
      {
        "orderId": "2098372769329598466",
        "orderNo": "HL20260911192708661",
        "teamNo": "26-9069",
        "contactName": "何书禾",
        "customerName": "何书禾",
        "contractState": "NOT_ISSUED",
        "contractStateText": "未出"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

本期无活跃子订单时 items 为空数组、三格分子分母均 0。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 本端点与芯片 contract 端点的 teamNo 同一取值来源、同一 null 语义,两处必然一致。
  • 面板三格计数由 items 自算,本单未改一行计数逻辑。

11. 团期行程逐日汇总 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary

VO: GroupBatchItineraryRespVO

使用场景

团期行程汇总。本单起「天数不一致户」预警行多出 customerName。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
dayCountOutliers[].customerName String 本单新增。与同一项的 contactName 逐字同值
dayCountOutliers[].contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2096412454643802114/itinerary
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "dayCount": 3,
    "dayCountConsistent": false,
    "dayCountOutliers": [
      {
        "orderId": "2096655509804187650",
        "orderNo": "HL20260907014322086",
        "contactName": "沈怀妍",
        "customerName": "沈怀妍",
        "dayCount": 1
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

各户天数一致时 dayCountOutliers 为空数组,新增字段不出现(没有行)。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 本单只加字段,行程一致性判定逻辑一行未改。

12. 团期行程某项逐户下钻 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary/nodes/{nodeKey}

VO: GroupBatchItineraryNodeDetailVO

使用场景

行程某个节点的逐户下钻。本单起逐户行多出 customerName。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变
nodeKey Path String ✅ 节点键(由汇总端点给出) 本单不变

出参字段表

字段 类型 说明
items[].customerName String 本单新增。与同一项的 contactName 逐字同值
items[].contactName String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 customerName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2096412454643802114/itinerary/nodes/<nodeKey>
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "nodeName": "礼仪接机",
    "householdCount": 55,
    "items": [
      {
        "orderId": "2096655509804187650",
        "orderNo": "HL20260907001741975",
        "contactName": "蒋岚妍",
        "customerName": "蒋岚妍",
        "has": true
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

nodeKey 无人命中时 items 仍返回全部活跃户(has=false),新增字段照常有值。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 未命中该节点的户 has=false,但 customerName 与 contactName 照常有值。

13. 审批中心统一列表 GET /v3/admin/order/group-batch/approvals/page

VO: PageResult<GroupBatchApprovalItemRespVO>

使用场景

流团与退单户共用的审批中心列表。本单起每行多出 5 个 key:退单户三件套 orderNo/customerName/departDate,以及 approvalStatusName 与 bizTypeName。

入参字段表

字段 位置 类型 必填 约束 说明
pageNum / pageSize / bizType / approvalStatus / groupBatchId Query — — 本单一个入参都没改 —

出参字段表

字段 类型 说明
orderNo String 本单新增。⚠️ 只在 bizType=WITHDRAW 行有值,DISBAND 行恒 null(与已有的 orderId 同一条规则);订单查不到(已软删)时也为 null
customerName String 本单新增。同上规则
departDate String 本单新增。团期出发日 yyyy-MM-dd,与退单专用列表 GET .../withdraw/page 同源同格式、逐字相同。同上规则
approvalStatusName String 本单新增。待审批 / 已通过 / 已取消退单。approvalStatus 为 null 时为 null,取值不在枚举内时回落原 code
bizTypeName String 本单新增。与 bizTypeText 逐字同值(流团 / 退单户)
bizTypeText String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 bizTypeName
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/approvals/page?pageNum=1&pageSize=20
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "approvalId": "2096029515502243842",
        "bizType": "WITHDRAW",
        "bizTypeText": "退单户",
        "bizTypeName": "退单户",
        "approvalStatus": "APPROVED",
        "approvalStatusName": "已通过",
        "orderId": "2096029450184347649",
        "orderNo": "HL20260905081537435",
        "customerName": "退单复测-7100",
        "departDate": "2026-10-31"
      },
      {
        "approvalId": "2097963098638876674",
        "bizType": "DISBAND",
        "bizTypeText": "流团",
        "bizTypeName": "流团",
        "approvalStatus": "APPROVED",
        "approvalStatusName": "已通过",
        "orderId": null,
        "orderNo": null,
        "customerName": null,
        "departDate": null
      }
    ],
    "total": 38
  },
  "success": true
}

空数据 / 降级响应

页内一行 WITHDRAW 都没有时,后端一次订单查询都不发(空集合短路)。订单或团期已软删的 WITHDRAW 行三个新字段为 null,该行照常返回、不漏行、不报错。

错误响应

码 符号 触发
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589507,
  "message": "无操作权限",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 🔴 前端必须按行类型判断再渲染:三个新字段只在 bizType=WITHDRAW 行有值,DISBAND 行恒 null。按「字段存在即渲染」写会出现空列。
  • 整页一次批量取单(防 N+1),不是每行一次。

14. 退单审批列表 GET /v3/admin/order/group-batch/withdraw/page

VO: PageResult<WithdrawApprovalItemRespVO>

使用场景

退单户专用审批列表。本单起每行多出 refundModeName 与 approvalStatusName 两个中文名。

入参字段表

字段 位置 类型 必填 约束 说明
pageNum / pageSize / approvalStatus / … Query — — 本单一个入参都没改 —

出参字段表

字段 类型 说明
refundModeName String 本单新增。按政策退 / 订金全额退 / 已付全额退 / 部分退。refundMode 为 null 时为 null,取值不在枚举内时回落原 code
approvalStatusName String 本单新增。待审批 / 已通过 / 已取消退单。同上兜底口径
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/withdraw/page?pageNum=1&pageSize=20
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "approvalId": "2096029515502243842",
        "orderNo": "HL20260905081537435",
        "customerName": "退单复测-7100",
        "departDate": "2026-10-31",
        "refundMode": "FULL_DEPOSIT",
        "refundModeName": "订金全额退",
        "approvalStatus": "APPROVED",
        "approvalStatusName": "已通过"
      }
    ],
    "total": 2
  },
  "success": true
}

空数据 / 降级响应

无数据时 records 为空数组。两个 code 为 null 时对应的 Name 也为 null。

错误响应

码 符号 触发
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无权限
{
  "code": 589507,
  "message": "无操作权限",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 退单详情 GET .../withdraw/{approvalId} 的响应体继承自本 VO,同样多出这两个字段(向后兼容纯增)。
  • 本端点与审批中心统一列表对同一张审批单的 orderNo/customerName/departDate 逐字相同。

15. 整团确认需求缺失预检 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check

VO: GroupBatchRequirementCheckRespVO

使用场景

点「整体确认需求」之前的预检。本单起外层多出 checkedResourceTypes 与 batchStatusName,缺失项多出 customerName 与 reasonName。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变

出参字段表

字段 类型 说明
checkedResourceTypes String[] 本单新增。本期恒 ["HOTEL"],由服务端常量给出。🔴 预检只检查住宿、不检查用车——ready=true 不代表用车需求齐备
batchStatusName String 本单新增。团期状态中文名;batchStatus 为 null 时为 null,不在九态内时回落原 code
missing[].customerName String 本单新增。客户姓名(order_main.customer_name),运营据此直接认出是哪一户
missing[].reasonName String 本单新增。未提报 / 缺房型或房数 / 需求结构异常 / 住宿晚数对不上 / 晚序号异常。reason 为 null 时为 null,不在五值内时回落原 code
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/order/group-batch/2096412454643802114/requirement/confirm-check
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "groupBatchId": "2096412454643802114",
    "batchStatus": "RESOURCE_PREPARING",
    "batchStatusName": "资源准备中",
    "ready": false,
    "checkedResourceTypes": ["HOTEL"],
    "missing": [
      {
        "orderId": "2096655509804187650",
        "orderNo": "HL20260907014322086",
        "customerName": "沈怀妍",
        "consultantId": "1001",
        "consultantName": "admin",
        "reason": "NOT_SUBMITTED",
        "reasonName": "未提报"
      }
    ]
  },
  "success": true
}

空数据 / 降级响应

无缺失户时 missing 为空数组、ready 由阶段判定;checkedResourceTypes 无论如何都是 ["HOTEL"](不随团期配置变化)。

错误响应

码 符号 触发
不变 GROUP_BATCH_NOT_FOUND(589500) 团期不存在 / 非团期 / 已软删
不变 GROUP_BATCH_PERMISSION_DENIED(589507) 无 group-batch:view 权限
{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 🔴 checkedResourceTypes 存在的全部理由就是让前端知道「ready=true 只说明住宿齐了」。扩到用车是另一张单,届时本字段变成 ["HOTEL","VEHICLE"]。
  • 本单不扩大检查范围,预检行为一行未改。

16. 调整团期满团名额 PUT /v3/admin/order/group-batch/{groupBatchId}/capacity

VO: GroupBatchCapacityRespVO

使用场景

调整满团户数。本单起响应多出 groupBatchId。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期聚合主键 本单不变
capacityDelta Body Integer ✅ 净增量(户),不得为 0 本单不变

出参字段表

字段 类型 说明
groupBatchId String 本单新增。与 batchId 逐字同值,同为字符串形态。⚠️ 它是派生只读字段(由 batchId 现算),因此两者不可能分叉
batchId String 值不变,本单起标 @Deprecated,本批不删;新代码请改读 groupBatchId
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

PUT /v3/admin/order/group-batch/2097498512387104770/capacity
Content-Type: application/json

{"capacityDelta": 1}
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "batchId": "2097498512387104770",
    "groupBatchId": "2097498512387104770",
    "beforeMaxRooms": 4,
    "maxRooms": 5,
    "capacityDelta": 1,
    "enrolledRooms": 4,
    "remainRooms": 1
  },
  "success": true
}

空数据 / 降级响应

失败时 data 为 null(与改前一致),新增字段随之不出现。

错误响应

码 符号 触发
不变 589538 非招募中阶段不可调
不变 589539 名额调整量不能为 0
不变 589509 新满团户数低于已报名户数或为负
不变 589540 产品域库存同步失败
{
  "code": 589539,
  "message": "名额调整量不能为 0",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 本单只加返回字段,名额调整的权限门、阶段门、库存同步逻辑一行未改。

17. 团期人员配置列表 GET /v3/admin/group-batch/{productBatchId}/staff

VO: List<BatchStaffConfigRespVO.BatchStaffItemVO>

使用场景

团期已配人员名册(裸数组、无顶层信封,本单不改其形态)。本单起每行多出 staffRoleName 与报账人两字段。

入参字段表

字段 位置 类型 必填 约束 说明
productBatchId Path Long ✅ 产品侧班期 ID 本单不变

出参字段表

字段 类型 说明
staffRoleName String 本单新增。角色中文名(领队/司机/导游/摄影/其他/导游助理/研学老师/生活老师);staffRole 为 null 时为 null,不在枚举内时回落原 code
reporterRank String 本单新增。报账人等级 PRIMARY 主 / SECONDARY 次 / NONE 非报账人。本端点恒非 null(历史空值归一为 NONE)
reporterRankName String 本单新增。主报账人 / 次报账人 / 非报账人;与 reporterRank 同生同灭
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/group-batch/2052935476557328386/staff
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "id": "2098667039013941249",
      "staffId": 1002,
      "staffRole": "GUIDE",
      "staffRoleName": "导游",
      "staffName": "李雪梅",
      "staffPhone": "138****1002",
      "sortOrder": 0,
      "reporterRank": "PRIMARY",
      "reporterRankName": "主报账人"
    }
  ],
  "success": true
}

空数据 / 降级响应

未配置任何人员时返回空数组 [](与改前一致)。

错误响应

码 符号 触发
不变 400 productBatchId 非法
{
  "code": 400,
  "message": "参数校验失败",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 🔴 本端点返回裸数组、没有顶层信封,因此不带 productBatchId / groupBatchId。包信封是结构变更(破坏性),另有工单跟进。
  • reporterRank 由 PUT .../staff/{staffId}/reporter-rank 设置,本单未改那个写端点一行。

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

VO: BatchStaffConfigRespVO

使用场景

全量保存团期人员配置。本单起响应顶层多出 productBatchId/groupBatchId,staffList[] 每项多出 staffRoleName 与报账人两字段。

入参字段表

字段 位置 类型 必填 约束 说明
productBatchId Path Long ✅ 产品侧班期 ID 本单不变
staffList Body Array ✅ 全量配置(传空数组 = 清空) 本单不变

出参字段表

字段 类型 说明
productBatchId String 本单新增(顶层)。直接回显路径参数,恒非 null
groupBatchId String 本单新增(顶层)。由 productBatchId 反查得到。⚠️ 本端点的 200 响应中恒非 null——入口第一道守卫就是成团校验(未建团 589553 / 未成团或已流团 589552),团期不存在时根本返不到这里
staffList[].staffRoleName / reporterRank / reporterRankName String 本单新增,口径同上一个端点;新配的人 reporterRank 为 NONE
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

PUT /v3/admin/group-batch/2052935476557328386/staff
Content-Type: application/json

{"staffList": [{"staffId": 1002, "staffRole": "GUIDE", "sortOrder": 0}]}
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "productBatchId": "2052935476557328386",
    "groupBatchId": "2096412454643802114",
    "staffList": [
      {
        "id": "2098667039013941249",
        "staffId": 1002,
        "staffRole": "GUIDE",
        "staffRoleName": "导游",
        "staffName": "李雪梅",
        "reporterRank": "NONE",
        "reporterRankName": "非报账人"
      }
    ],
    "affectedOrderCount": 55
  },
  "success": true
}

空数据 / 降级响应

传空数组 = 清空配置,staffList 返回空数组,两个顶层 ID 照常有值。

错误响应

码 符号 触发
不变 589553 团期尚未创建(该班期还没有任何订单)
不变 589552 团期未成团或已流团
不变 589582 请求体内 staffId 重复
不变 582114 角色与人员类型不符
{
  "code": 589553,
  "message": "团期尚未创建(该班期还没有任何订单),请先建团并完成成团后再操作",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 🔴 未建团时本端点返 589553,不是 200——这是工单 #7287 T5 定的既有守卫,本单未改。想在成团前拿团期 ID,用候选端点。
  • 反查团期用的是入口守卫已经查过的那一次结果,新增查询数为 0。

19. 团期人员配置候选列表 GET /v3/admin/group-batch/{productBatchId}/staff/candidates

VO: List<StaffCandidateRespVO>

使用场景

「配置导游 / 配置摄影」弹窗的人员资源库。本单起每项多出 6 个 key。

入参字段表

字段 位置 类型 必填 约束 说明
productBatchId Path Long ✅ 产品侧班期 ID 本单不变
role Query String ✅ GUIDE 导游位 / PHOTOGRAPHER 摄影位 本单不变

出参字段表

字段 类型 说明
productBatchId String 本单新增。直接回显路径参数,恒非 null
groupBatchId String 本单新增。由 productBatchId 反查。🔴 团期尚未创建时为 null(staff 允许在成团前先配,本端点不报错、返 200)。前端不得把它当必有主键去拼后续请求,否则会打出 /group-batch/null/...
staffTypeName String 本单新增。人员类型中文名;staffType 为 null 时为 null,不在枚举内时回落原 code
assignedRoleName String 本单新增。已选角色中文名;assignedRole 为 null 时为 null
reporterRank String 本单新增。⚠️ 未进入本团期名册的候选为 null,不是 NONE——NONE 的语义是「已在名册里、但不是报账人」,两者必须能区分
reporterRankName String 本单新增。与 reporterRank 同生同灭
(其余字段) — 全部不变,本单不改动任何既有字段的名称、类型、取值与 null 语义

请求示例

GET /v3/admin/group-batch/2052935476557328386/staff/candidates?role=GUIDE
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "productBatchId": "2052935476557328386",
      "groupBatchId": "2096412454643802114",
      "staffId": 1002,
      "staffName": "李雪梅",
      "staffPhone": "138****1002",
      "staffType": "GUIDE",
      "staffTypeName": "导游",
      "assigned": true,
      "assignedRole": "GUIDE",
      "assignedRoleName": "导游",
      "reporterRank": "PRIMARY",
      "reporterRankName": "主报账人"
    },
    {
      "productBatchId": "2052935476557328386",
      "groupBatchId": "2096412454643802114",
      "staffId": 1010,
      "staffType": "LEADER",
      "staffTypeName": "领队",
      "assigned": false,
      "assignedRole": null,
      "assignedRoleName": null,
      "reporterRank": null,
      "reporterRankName": null
    }
  ],
  "success": true
}

空数据 / 降级响应

资源域无可用人员时返回空数组。团期尚未创建时 groupBatchId 为 null、HTTP 200、code=200(不返 589500)。

错误响应

码 符号 触发
不变 582116 role 不是 GUIDE / PHOTOGRAPHER
不变 STAFF_INFO_FETCH_FAILED 资源域不可达
{
  "code": 582116,
  "message": "候选角色非法",
  "data": null,
  "traceId": null,
  "success": false
}

业务边界

  • 🔴 reporterRank / assignedRole 是【本团期名册】维度,assigned 是【本配置位】维度,两者口径不同。 一个被配到另一个位上的人,在本位会是 assigned=false 但 reporterRank 非 null——这是对的,不是 bug。
  • 整批只反查一次团期,不是每个候选一次。

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

  1. 不需要改任何调用代码即可继续工作。本批是纯增,未消费新字段的页面行为完全不变。
  2. opsStage 直接读,不要自己折桶。服务端八桶的唯一真源是 GroupBatchStageBuckets;前端复刻一份,规则一改就和入参筛选 opsStage 的结果对不上。
  3. 同值字段对二选一即可,不要两个都渲染: batchStatusLabel↔batchStatusName、productBatchStatusLabel↔productBatchStatusName、 statusText↔statusName、bizTypeText↔bizTypeName、contactName↔customerName、 batchId↔groupBatchId、totalReceivable↔receivableAmount、totalReceived↔receivedAmount。 服务端保证每一对在同一次响应里逐字相同(同一表达式/同一变量赋值,或派生只读字段)。
  4. teamNo 按 null 判空即可,不必区分 ""——后端永远不返空串。也不要用 teamNo != null 判断是不是团期单,那会两个方向都判错。
  5. 审批中心统一列表按 bizType 分支渲染:DISBAND 行的 orderId / orderNo / customerName / departDate 恒 null。
  6. staff 候选端点的 groupBatchId 可能为 null,拿它拼后续请求前必须判空。

五、数据库行为

本单零数据库变更:无新增 / 修改表、无新增列、无新增索引、无 Flyway 迁移脚本、无新增 Mapper 方法。

清单里的两个写端点(16 PUT .../capacity、18 PUT .../staff)写库行为一行未改,本单只是在它们返回前多填了展示字段:

  • PUT .../capacity 的 groupBatchId 是派生只读字段,由已有的 batchId 现算,不读库;
  • PUT .../staff 的两个顶层 ID 复用入口成团守卫已经查过的那一次 getByProductBatchId 结果,新增查询数为 0。

唯一的 Mapper 改动是给两条既有列受限投影各加一个已有列: OrderInfoMapper.selectChipProjectionByProductBatchIds 与 selectContractPanelProjectionByProductBatchIds 各加一个 OrderInfo::getTeamNo(映射 order_main.team_no,非加密列,不触发逐行解密)。 git diff 上该文件只有两行新增、无第三个 hunk。

新增字段的取数全部零新增查询:

  • 团号来自上述两条已有的批量投影;
  • 芯片负责人的团级指针来自 chipDetail 里已在手的团期实体;
  • 冻结名单每次请求读 1 次(按 groupBatchId 单表命中),名单为空时短路掉户级需求那次查询;
  • 审批列表整页一次批量取单,页内无 WITHDRAW 行时一次都不取;
  • staff 报账人来自已有的名册查询。

六、边界行为

场景 行为
batch_status 是九态之外的脏值 / 为 null 该行 opsStage 与 opsStageName 同为 null,batchStatus / batchStatusName 照旧;整页不会 500
未建团行(产品有班期、订单侧无团期) batchStatus=RECRUITING → opsStage=RECRUIT/招募中,走同一条折桶、不特判
整团未认领(house_claimer_id IS NULL) 芯片逐户 claimerId/claimerName/claimerSource 三者全为 null,不是空串、不是 0
该户在历史旧户冻结名单内 读该户 order_hotel_requirement.claimer_id,claimerSource=LEGACY;户级也为空则三者整体 null(不回落团级)
超管接管后 CAS 落空、户级残留旧人 该户不在冻结名单里,按定案显示团级新接管人 + claimerSource=BATCH。这是对的:团级指针是唯一真源,户级残留是待清理脏数据
订金未支付成功 teamNo 为 null(不是空串、不回退成 orderNo);同团其他已付订金的户照常有值
审批行是 DISBAND orderNo / customerName / departDate 恒 null,该行照常返回、不漏行、不报错
审批行是 WITHDRAW 但订单/团期已软删 三个字段为 null,该行照常返回;统一列表与退单专用列表给出相同的 null
页内一条 WITHDRAW 都没有 后端一次订单查询都不发
任一 code 为 null 对应的 Name 为 null(不造空串)
任一 code 不在枚举内 对应的 Name 回落原 code(不抛异常、不返空串);opsStage 是唯一例外——它回落 null,因为八桶取值集是前端页签,透一个不存在的值出去会渲染出不存在的页签
应收 / 已收任一为 null 按 0 参与计算,unpaidAmount 恒非 null
已收 > 应收(退款/多收的历史脏数据) unpaidAmount 返回 0,不透负数
staff 候选:团期尚未创建 groupBatchId 为 null,HTTP 200 + code=200(不返 589500)
staff 候选:人已被配到另一个位 assigned=false(本配置位口径)但 assignedRole / reporterRank 非 null(本团期名册口径)——两者口径不同,不是 bug
staff 候选:人还没进本团期名册 reporterRank 为 null(不是 NONE)
staff 名册:reporter_rank 历史空值 归一为 NONE / 非报账人(名册端点恒非 null)

六.6、修改前后对比

维度 改前 改后
团期分页项 GroupBatchPageItemRespVO 27 个 key 31 个 key(+opsStage/opsStageName/unpaidAmount/productBatchStatusName)
团期看板行 GroupBatchBoardItemRespVO 27 30(+opsStage/opsStageName/batchStatusName)
团期详情 GroupBatchDetailRespVO 43 48(+opsStage/opsStageName/receivableAmount/receivedAmount/thresholdSourceName)
芯片信封 GroupBatchChipDetailVO 6 8(+aggregateStatusName/groupBatchId)
芯片逐户 GroupBatchChipItemRespVO 8 14(+teamNo/customerName/statusName/claimerId/claimerName/claimerSource)
合同面板 GroupBatchContractBoardVO 10 11(+groupBatchId)
合同逐户 GroupBatchContractItemVO 15 17(+teamNo/customerName)
预检 GroupBatchRequirementCheckRespVO 4 6(+checkedResourceTypes/batchStatusName;missing[] 另 +2)
统一审批行 GroupBatchApprovalItemRespVO 14 19(+orderNo/customerName/departDate/approvalStatusName/bizTypeName)
退单行 WithdrawApprovalItemRespVO 16 18(+refundModeName/approvalStatusName)
staff 候选 StaffCandidateRespVO 7 13(+6)
团期子订单项 GroupBatchOrderItemRespVO(A3) 29 29 —— 零变化
路径 / 方法 / 请求参数 — 完全不变
既有字段的名称 / 类型 / 取值 / null 语义 — 完全不变(源码 diff 中零条字段删除或改名)
错误码 — 无新增、无调整
数据库 / Flyway / 网关路由 — 零改动

六.7、影响评估

  • 兼容性:响应体纯增字段,未消费新 key 的前端页面无需任何改动即可继续工作。
  • 需要前端动的:
    1. 团期列表 / 看板的「阶段」页签改读 opsStage,删掉自己那套九态→八桶折叠;
    2. 报名清单「联系人」列改读 customerName(此前显示 — 是读错 key);
    3. 芯片下钻逐户行可加「负责人」与「团号」两列;
    4. 审批中心统一列表可加订单号 / 客户姓名 / 出发日三列(按 bizType 分支渲染);
    5. 新代码逐步把四组 Text/Label/batchId/total* 旧名切到新名(本批不强制,删除时间另行通知)。
  • 性能:新增开销只有「每次芯片请求多读一次冻结名单(按 groupBatchId 单表命中,名单为空时到此为止)」与「审批列表整页一次批量取单(页内无 WITHDRAW 行则零次)」。 团号与负责人全部复用已有的批量投影与已在手的团期实体,零新增查询。
  • 响应体积:团期分页每行多 4 个 key、芯片逐户每户多 6 个 key。芯片明细端点返回全量逐户、没有分页,几百户的团会多出上千个字段,仍在 KB 量级、不触任何网关限制。
  • 连带生效(无需单独对接):退单审批详情 GET .../withdraw/{approvalId} 的响应体继承自 WithdrawApprovalItemRespVO,同样多出 refundModeName / approvalStatusName。
  • 两个只读派生字段:GroupBatchCapacityRespVO.groupBatchId 与 GroupBatchDetailRespVO.thresholdSourceName 是只读派生 getter(分别由 batchId 与 thresholdSource 现算)。对前端没有任何差别;对后端的意义是这两对 key 在结构上不可能分叉。

七、不影响范围

  • 团期子订单列表(A3)GroupBatchOrderItemRespVO 一个字段都没加,改前改后 29 个 key 完全一致——它的 5 个裸 code 与 roomTypeName 归 #7536。
  • 财务 tab 的 12 个金额字段 JSON 形态本批不变(GroupBatchFinanceRespVO / GroupBatchFinanceItemVO 零改动),其变更由 #7536 交接。
  • 「报名清单 / 财务 / 预支」三张表逐行的 teamNo 不在本批,归 #7536;两批的字段名、类型与 null 语义完全一致。
  • GET /v3/admin/group-batch/{productBatchId}/staff 仍返回裸数组、不包顶层信封(包信封属结构变更,另有工单)。
  • 预检不扩到用车:本批只是把「只检查住宿」这个事实透出成 checkedResourceTypes,检查行为一行未改。
  • 小程序端(mp 域)全部 VO 不动;/v3/internal/ 端点不动。
  • 零改动:Controller 方法体、Entity、Flyway、错误码、hl-gateway 配置、其他微服务。

八、测试环境已验证

部署:hl-order-service-v3 @ dev-v3 / bb68be409(PR #7583 合并提交),双实例滚动重启完成。 全部实测经真实网关 api.test.1814.love:9443 + Bearer 鉴权。 本单零新增 Controller、零网关路由改动,网关无需重滚。

验证点 结果
八桶三端点一致 团期 2096412454643802114(RESOURCE_PREPARING)在 A1 分页 / A2 详情 / 看板三处均 opsStage=FORMED、opsStageName=已成团
FORMED 复合桶 RESOURCE_PREPARING 与 MATERIAL_PREPARING 两个团期同为 FORMED/已成团
芯片负责人(已认领) 六个芯片端点逐户全部 claimerId=30001 / claimerName=验收房务甲 / claimerSource=BATCH
芯片负责人(未认领) 三个字段全为 null
报账人 置 PRIMARY 前名册读到 NONE/非报账人,置后读到 PRIMARY/主报账人
候选 reporterRank 未被本团期选中的 5 人全部 null(不是 NONE);已选未任报账人的返 NONE/非报账人
审批统一列表 vs 退单列表 同一审批单 orderNo/customerName/departDate 三项逐字相同(2 条正向 + 1 条降级态同为 null)
DISBAND 行 一页 38 行(34 DISBAND / 4 WITHDRAW),34 行三字段全 null、零漏行、零报错
预检 4 个团期均返 checkedResourceTypes=["HOTEL"],missing[] 每项带 customerName 与 reasonName
后缀四处同值 芯片 55 户 statusText==statusName;A1 17 行 productBatchStatusLabel==productBatchStatusName;看板与审批同理
联系人四处同值 芯片 / 合同 / 行程下钻实测逐户 customerName==contactName
团期 ID 三处同值 名额调整 / 芯片详情 / 合同面板 groupBatchId==batchId,均为字符串形态
金额 详情两对逐字同值;A1 全 28 行 unpaidAmount == max(0, 应收−已收) 零例外
teamNo 正负 同一团期一户 26-9069、三户 null,芯片与合同两端点一致;orderNo 同一对象里照常非空
staff 候选未建团 groupBatchId=null,HTTP 200 + code=200(不返 589500)
零破坏(真·双部署对拍) 同一台 TEST 上先后部署 93bd823b4(合入前)与 bb68be409(合入后),逐端点抓取响应并摊平成规范化字段路径做集合对拍:20 个端点删除字段路径 = 0,新增 +90;另用同 commit 重跑一趟作对照组,键集漂移 = 0。A3 GET .../{groupBatchId}/orders 新增 0 / 删除 0 / 值变 0

本地全量:

  • 第一遍(排除 *IT / *IntegrationTest / *MysqlTest / *MysqlMigrationTest):Tests 9800 / Failures 0 / Errors 52 / Skipped 8
  • 第二遍(只跑上面排除的类,每类独立 JVM):Tests 308 / Failures 0 / Errors 9 / Skipped 41
  • 两遍 61 个 Errors 全部既存或环境所致(SignVoucherServiceTest 48 例是 dev-v3 上既存的测试间污染;其余 13 例全是 Could not find a valid Docker environment)。与 dev-v3 基线逐类一致,本单净增 249 例、零新增失败。
  • ArchUnit 全绿:HouseModuleBoundaryArchTest 4/0(本单新引入中立包依赖的专项)、RedLineArchTest 12/0、MapperBoundaryArchTest 26/0、LayerEnforcementTest 5/0。

十、相关文档

  • Issue:https://git.1814.love:8443/wx/HL/issues/7535
  • PR:https://git.1814.love:8443/wx/HL/pulls/7583
  • API-SPEC §17.1 / §17.2 字段清单已同步:docs/order-v3/api/API-SPEC.html
  • 团期接口文档「已落地清单」已登记:docs/group/团期模块接口文档-v2.0.html §0A.10
  • 八桶唯一真源:hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/helper/GroupBatchStageBuckets.java
  • 团号生成器:hl-order-service-v3/src/main/java/com/hulalv/order/core/service/GroupCodeService.java

关联 / 联系人

  • 后端:jw
  • 前端(hl-ui 管理后台):mmg
  • 需求定案:wx(2026-09-11:「原型上有的必须有;可以多给;不能加离谱的字段」「后缀统一为 Name」「opsStage 以后端八桶为准,原型侧改」)
  • ⚠️ 待 mmg 确认:原型侧的 8 个 stage 取值与后端八桶的重合度是 wx 口述、撰写工单时未核对原型文件。本批以后端八桶为准,原型侧需按上表 8 个取值调整。