7510/7511/7512 代码早已随供应商关系系列交付(a17a2c2a/4bedc8be),实证后回写 verified 挂 a17a2c2a; 11_7510 为正本 12_7510 的重复副本(canonical_path),标 not_required 消除 pending; 7513/7530/7531/7535 实证前端零改动 not_required。
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(不抛异常、不返空串)。
一、背景
团期模块的响应体长期存在四类不一致,都是前端一眼能看见、但后端没人系统清过的:
- 八桶只能筛、不能读:
GET /v3/admin/order/group-batch的入参早就支持按八桶opsStage筛选,出参却没有这个字段——前端只能拿九态batchStatus自己再折一遍桶,折叠规则一分叉就和服务端筛选结果对不上。 - 中文名后缀三套并存:同一个
batchStatus在分页项叫batchStatusName、在看板行叫batchStatusLabel;芯片叫statusText、审批叫bizTypeText。同时还有 10 个裸 code 字段根本没有中文配对,前端只能自己维护映射表。 - 同义字段各叫各的:联系人在团期域 4 个 VO 里叫
contactName、在其余 8 个 VO 里叫customerName;团期主键在 3 个 VO 里叫batchId、其余一律groupBatchId;整团应收/已收在三个端点有三套名字。 - 该有的字段缺位:芯片逐户看不到房务负责人、逐户行看不到团号、审批中心统一列表的退单户行看不到订单号与客户姓名、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。 - 整批只反查一次团期,不是每个候选一次。
四、契约约束与正确调用方式
- 不需要改任何调用代码即可继续工作。本批是纯增,未消费新字段的页面行为完全不变。
opsStage直接读,不要自己折桶。服务端八桶的唯一真源是GroupBatchStageBuckets;前端复刻一份,规则一改就和入参筛选opsStage的结果对不上。- 同值字段对二选一即可,不要两个都渲染:
batchStatusLabel↔batchStatusName、productBatchStatusLabel↔productBatchStatusName、statusText↔statusName、bizTypeText↔bizTypeName、contactName↔customerName、batchId↔groupBatchId、totalReceivable↔receivableAmount、totalReceived↔receivedAmount。 服务端保证每一对在同一次响应里逐字相同(同一表达式/同一变量赋值,或派生只读字段)。 teamNo按null判空即可,不必区分""——后端永远不返空串。也不要用teamNo != null判断是不是团期单,那会两个方向都判错。- 审批中心统一列表按
bizType分支渲染:DISBAND行的orderId/orderNo/customerName/departDate恒null。 - 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 的前端页面无需任何改动即可继续工作。
- 需要前端动的:
- 团期列表 / 看板的「阶段」页签改读
opsStage,删掉自己那套九态→八桶折叠; - 报名清单「联系人」列改读
customerName(此前显示—是读错 key); - 芯片下钻逐户行可加「负责人」与「团号」两列;
- 审批中心统一列表可加订单号 / 客户姓名 / 出发日三列(按
bizType分支渲染); - 新代码逐步把四组
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 全部既存或环境所致(
SignVoucherServiceTest48 例是dev-v3上既存的测试间污染;其余 13 例全是Could not find a valid Docker environment)。与dev-v3基线逐类一致,本单净增 249 例、零新增失败。 - ArchUnit 全绿:
HouseModuleBoundaryArchTest4/0(本单新引入中立包依赖的专项)、RedLineArchTest12/0、MapperBoundaryArchTest26/0、LayerEnforcementTest5/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 个取值调整。