diff --git a/changelogs-v2/2026-09/24_8253_团期审批中心统一审核补字段与团期名称搜索-修改接口-管理后台.md b/changelogs-v2/2026-09/24_8253_团期审批中心统一审核补字段与团期名称搜索-修改接口-管理后台.md new file mode 100644 index 00000000..1133a4d9 --- /dev/null +++ b/changelogs-v2/2026-09/24_8253_团期审批中心统一审核补字段与团期名称搜索-修改接口-管理后台.md @@ -0,0 +1,1172 @@ +--- +schema: "hl-changelog/v2" +ticket: "8253" +title: "团期审批中心统一审核:列表与流团/退单两类详情、批复响应补团期名称/期号/出行人数/审核时间/联系人电话/canApprove,列表支持团期名称搜索" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "团期审批中心改为一页统一审核流团与退单户。后端改动全部是纯增出参或可选入参,路径、判权、错误码零变化:GB-ADM-061 审批中心列表新增入参 batchName(团期名称包含匹配,「第N期」/「N」另按期号精确匹配,不匹配 batch_no),出参新增 batchLabel、participantCount、approvedAt、customerPhoneMasked、canApprove;流团详情/提交/同意/拒绝共用的 DisbandApprovalRespVO 新增 batchName、batchLabel、approvalStatusName、participantCount、canApprove;退单列表/详情/同意/拒绝共用的 WithdrawApprovalItemRespVO 新增 batchName、batchLabel、customerPhoneMasked、affectedOrderCount(恒 1),详情另增 canApprove。口径订正两处:审批中心列表 WITHDRAW 行 affectedOrderCount 由 null 改为 1;流团驳回 approvalStatusName 由「已取消退单」改为「已拒绝」(退单户驳回仍为「已取消退单」)。participantCount 为提交时快照,group_batch_approval 新增可空列 participant_count(Flyway V20260924_825,版本 20260924.825),流团批准后子订单全取消仍返回快照。canApprove = PENDING 且过审批端点同一道角色门(当前 ADMIN/SUPER_ADMIN)且团期存在,退单户另要求团期仍可退团。已合并 dev-v3:PR #8256(merge 4f9b6facb)、PR #8260(merge 11dd1e2fb,退单 072/073 补 affectedOrderCount=1)。2026-09-23 在 TEST(dev-v3 含 4f9b6facb)验收:列表 62 行逐行对库零异常、WITHDRAW 19 行 affectedOrderCount=1;名称搜索 6 类用例、四条批复路径、四类角色 canApprove 与审批端点拒绝码、participant_count 快照 4/3/3/1 及批准后仍返回 4 均符合;16:17 部署含 11dd1e2fb 的 dev-v3 后,退单列表 19 行与退单详情的 affectedOrderCount 实测均为 1。2026-09-24 在 TEST(dev-v3 检出 cc70c9ba3)补验退单户团期不可退团格:测试团期临时置 TRAVELLING 后,超管查审批中心列表与退单详情该 PENDING 单 canApprove 均为 false(详情 currentRefundMode 为 null),超管调退单同意返回 589501「团期状态不允许当前操作」,审批行仍 PENDING、订单未取消;团期状态已恢复为 RECRUITING 并回查确认。流团 canApprove 的阶段条件由 #8308 追加,以其 changelog 为准。前端需:退单户行加眼睛图标与详情弹窗;弹窗同意/拒绝按钮接 GB-ADM-074/075;按 canApprove 显隐同意/拒绝按钮;新增列(团期名称、出行人数、审核时间、联系人电话)与团期/订单两类跳转;默认 Tab;金额提示文案;另注意 hl-ui 两个审批页各有 isAdmin 整页门禁(见 #8246 A9)。" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# 团期审批中心统一审核:补字段与团期名称搜索(管理后台) + +> **服务**: hl-order-service-v3(端口 8086/8186) +> **PR**: #8256(merge commit `4f9b6facb`)、#8260(merge commit `11dd1e2fb`) +> **Issue**: #8253 +> **日期**: 2026-09-23 +> **影响范围**: 团期审批中心列表与流团/退单两类详情弹窗、批复响应 + +--- + +## 一、背景 + +审批中心要在**一页**里统一审核「流团」与「退单户」两类申请:列表要能看团期名称/期号、出行人数、审核时间、 +退单户联系人电话,要能按团期名称搜,并且要能直接在本页点「同意 / 拒绝」。 + +此前接口缺这些字段:列表只有 `batchName`(且流团/退单两类详情没有),没有期号、出行人数、审核时间、电话; +前端也无从判断当前账号能不能批,只能把按钮全摆出来、点了再吃 589530 / 589547。 +另有两处口径错误一并订正:列表里退单户行的「影响订单数」返回 `null`(实为一户一单,恒 1); +流团被驳回时状态文案显示「已取消退单」(流团驳回的语义是团期继续招募,应为「已拒绝」)。 + +「出行人数」必须落**提交时快照**:流团批准后整团子订单全部 `CANCELLED`,读时现算恒为 0。 +为此 `group_batch_approval` 新增可空列 `participant_count`,与既有的 `affected_order_count` / `estimated_refund_amount` +同一批户、同一时刻取数。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|---|---|---|---|---| +| 1 | GB-ADM-061 团期审批中心列表 | GET | `/v3/admin/order/group-batch/approvals/page` | 修改接口 | 入参新增 `batchName`;出参新增 `batchLabel` `participantCount` `approvedAt` `customerPhoneMasked` `canApprove`;WITHDRAW 行 `affectedOrderCount` 由 null 改为 1;流团驳回文案改为「已拒绝」 | +| 2 | GB-ADM-061 流团申请详情 | GET | `/v3/admin/order/group-batch/disband/{approvalId}` | 修改接口 | 出参新增 `batchName` `batchLabel` `approvalStatusName` `participantCount` `canApprove` | +| 3 | GB-ADM-060 提交流团申请 | POST | `/v3/admin/order/group-batch/{groupBatchId}/disband` | 修改接口 | 响应同 `DisbandApprovalRespVO`,随之新增同上字段;提交时写出行人数快照 | +| 4 | GB-ADM-062 同意流团 | POST | `/v3/admin/order/group-batch/disband/{approvalId}/approve` | 修改接口 | 响应新增同上字段 | +| 5 | GB-ADM-062 拒绝流团 | POST | `/v3/admin/order/group-batch/disband/{approvalId}/reject` | 修改接口 | 响应新增同上字段,`approvalStatusName` 为「已拒绝」 | +| 6 | GB-ADM-072 退单审批分页列表 | GET | `/v3/admin/order/group-batch/withdraw/page` | 修改接口 | 出参新增 `batchName` `batchLabel` `customerPhoneMasked` `affectedOrderCount`(恒 1);`participantCount` 改为快照优先 | +| 7 | GB-ADM-073 退单申请详情 | GET | `/v3/admin/order/group-batch/withdraw/{approvalId}` | 修改接口 | 同 6,另新增 `canApprove` | +| 8 | GB-ADM-074 退单审核通过 | POST | `/v3/admin/order/group-batch/withdraw/{approvalId}/approve` | 修改接口 | 响应随 `WithdrawApprovalDetailRespVO` 新增同 7 的字段 | +| 9 | GB-ADM-075 取消退单(驳回) | POST | `/v3/admin/order/group-batch/withdraw/{approvalId}/reject` | 修改接口 | 响应随 `WithdrawApprovalDetailRespVO` 新增同 7 的字段 | + +> 退单提交 `POST /v3/admin/order/group-batch/{groupBatchId}/sub-order/{orderId}/withdraw`(GB-ADM-070) +> 名称、入参、出参、返回值四项均未变,只在提交时多写一列出行人数快照,不列入清单,见「五、数据库行为」。 + +--- + +## 三、接口详情 + +### 1. GB-ADM-061 团期审批中心列表 `GET /v3/admin/order/group-batch/approvals/page` + +**VO**: `GroupBatchApprovalListReqVO` → `PageResult` + +#### 使用场景 + +审批中心主列表,一页同时展示流团(DISBAND)与退单户(WITHDRAW)两类申请,支持按类型、状态、团期、团期名称筛选。 +前端据 `canApprove` 决定每行是否显示「同意 / 拒绝」按钮。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| bizType | Query | String | 否 | `DISBAND` / `WITHDRAW` | 不传 = 两类都要(既有) | +| approvalStatus | Query | String | 否 | `PENDING` / `APPROVED` / `REJECTED` | 不传 = 全部(既有) | +| groupBatchId | Query | Long | 否 | 团期 ID | 不传 = 全部(既有) | +| batchName | Query | String | 否 | 空白视为不传 | **本次新增**。团期名称搜索:名称包含匹配(`%` `_` 按字面转义);输入形如「第N期」或纯数字「N」时另按期号 `batch_label = N` **精确**匹配(输入 14 不会命中 114 期);**不匹配**团期号 batch_no | +| pageNum | Query | Integer | 否 | ≥1,默认 1 | 页码(既有) | +| pageSize | Query | Integer | 否 | 1–100,默认 20 | 每页条数(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| records[].batchLabel | String | **本次新增**。期号,如 `1`。界面「团期名称」列渲染为 `第{batchLabel}期 {batchName}`;团期已软删时 null | +| records[].batchName | String | 团期名称(既有字段);团期已软删时 null | +| records[].participantCount | Integer | **本次新增**。出行人数:DISBAND = 提交时整团非取消子订单人数合计(成人+儿童+小童+婴儿);WITHDRAW = 该户人数。取数规则见「业务边界」;存量已处理流团无快照时为 null | +| records[].approvedAt | LocalDateTime | **本次新增**。审核时间 `yyyy-MM-dd HH:mm:ss`;未批复为 null | +| records[].customerPhoneMasked | String | **本次新增**。退单户客户手机(脱敏,3 位 + `****` + 4 位,与订单列表同口径);DISBAND 行恒 null;订单查不到或无手机号时 null | +| records[].canApprove | Boolean | **本次新增**。当前账号能否在本页审批此单,恒非 null。定义见「四、契约约束」 | +| records[].affectedOrderCount | Integer | 影响子订单户数。DISBAND = 提交时整团户数(既有);**WITHDRAW 由 null 改为恒 1** | +| records[].approvalStatusName | String | 审批状态中文名。**流团驳回由「已取消退单」改为「已拒绝」**;退单户驳回仍为「已取消退单」;其余「待审批 / 已通过」不变 | +| records[].approvalId / bizType / bizTypeName / bizTypeText / groupBatchId / batchNo / approvalStatus / orderId / estimatedRefundAmount / reason / applicantName / approvedByName / createTime / orderNo / customerName / departDate | — | 既有字段,本次未改 | +| total / page / pageSize | Long / Integer / Integer | 分页包装(既有),列表字段名是 `records` | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/approvals/page?approvalStatus=PENDING&batchName=%E7%AC%AC1%E6%9C%9F&pageNum=1&pageSize=20 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [ + { + "approvalId": "2102579024482197505", + "bizType": "WITHDRAW", + "bizTypeText": "退单户", + "bizTypeName": "退单户", + "groupBatchId": "2101506167098511362", + "batchNo": "Q202609272101502082564407298", + "batchName": "jw测试1期", + "batchLabel": "1", + "approvalStatus": "PENDING", + "approvalStatusName": "待审批", + "orderId": "2101947902601646081", + "affectedOrderCount": 1, + "participantCount": 2, + "estimatedRefundAmount": 3000.00, + "reason": null, + "applicantName": "金卫", + "approvedByName": null, + "approvedAt": null, + "canApprove": true, + "createTime": "2026-09-23 10:01:18", + "orderNo": "HL20260921161326904", + "customerName": "秋雅", + "customerPhoneMasked": "156****7788", + "departDate": "2026-09-27" + }, + { + "approvalId": "2102668636865089537", + "bizType": "DISBAND", + "bizTypeText": "流团", + "bizTypeName": "流团", + "groupBatchId": "2102668504199254017", + "batchNo": "Q202612132102668472729395201", + "batchName": "#8253-流团拒绝 50%_x", + "batchLabel": "128", + "approvalStatus": "REJECTED", + "approvalStatusName": "已拒绝", + "orderId": null, + "affectedOrderCount": 1, + "participantCount": 3, + "estimatedRefundAmount": 0.00, + "reason": "8253 验收:流团拒绝路径", + "applicantName": "admin", + "approvedByName": "admin", + "approvedAt": "2026-09-23 15:59:30", + "canApprove": false, + "createTime": "2026-09-23 15:57:23", + "orderNo": null, + "customerName": null, + "customerPhoneMasked": null, + "departDate": null + } + ], + "total": 2, + "page": 1, + "pageSize": 20 + } +} +``` + +(两行分别取自 TEST 实测响应;为展示两类行拼在同一页,`total` 按示例行数写。) + +#### 空数据 / 降级响应 + +`batchName` 有值但零命中时直接返回空页,**不会**退化成「不筛」返回全表: + +```json +{ + "code": 200, + "message": "成功", + "data": { "records": [], "total": 0, "page": 1, "pageSize": 100 }, + "success": true +} +``` + +挂在已软删团期上的申请单照常返回,但团期侧字段(`batchNo` / `batchName` / `batchLabel`)为 null,`canApprove=false`。 + +#### 错误响应 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589507 | 当前角色无 `group-batch:view`(既有) | +| 400 | `pageNum` < 1 或 `pageSize` 不在 1–100(既有) | +| 401 | 缺少有效 Authorization 头(响应体 code,HTTP 仍为 200) | + +#### 业务边界 + +- 判权不变:仍走 `group-batch:view`,与审批端点(ADMIN/SUPER_ADMIN 角色门)不是同一道门,见「四」已知旁路。 +- `canApprove` 按请求算一次角色门后逐行套用;已处理(APPROVED / REJECTED)行恒 false。 +- `participantCount`:优先读提交时快照;无快照的存量 PENDING 流团按同口径现算;无快照的已处理流团返回 null;无快照的退单户按该户订单现算(退单只取消订单、不清人数列)。 +- `batchName` 与 `groupBatchId` 等其他筛选条件同时传时取交集。 +- 本页不展示「当前预估退款」「实退金额」,接口既有的 `estimatedRefundAmount` 字段保留不动。 + +--- + +### 2. GB-ADM-061 流团申请详情 `GET /v3/admin/order/group-batch/disband/{approvalId}` + +**VO**: `DisbandApprovalRespVO` + +#### 使用场景 + +审批中心点开一条流团申请时拉详情弹窗;弹窗「同意 / 拒绝」按钮按 `canApprove` 显隐。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 审批单 ID | 须为 DISBAND 类型,否则 589545 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName | String | **本次新增**。团期名称;团期已软删时 null | +| batchLabel | String | **本次新增**。期号,渲染为 `第{batchLabel}期 {batchName}`;团期已软删时 null | +| approvalStatusName | String | **本次新增**。待审批 / 已通过 / 已拒绝 | +| participantCount | Integer | **本次新增**。提交时整团非取消子订单人数合计;批准后仍返回快照;存量无快照时 PENDING 现算、已处理为 null | +| canApprove | Boolean | **本次新增**。PENDING 且过审批端点同一道角色门且团期存在;恒非 null。流团 canApprove 的阶段条件由 #8308 追加,以其 changelog 为准 | +| approvalId / groupBatchId / batchNo / approvalStatus / reason / affectedOrderCount / estimatedRefundAmount / actualRefundAmount / applicantId / applicantName / ccUserNames / approvedById / approvedByName / approvedAt / approveRemark / createTime | — | 既有字段,本次未改 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/disband/2102668636605026306 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636605026306", + "groupBatchId": "2102668502144028673", + "batchNo": "Q202612122102668472460963841", + "batchName": "#8253-流团同意", + "batchLabel": "126", + "approvalStatus": "PENDING", + "approvalStatusName": "待审批", + "reason": "8253 验收:流团同意路径", + "affectedOrderCount": 2, + "participantCount": 4, + "estimatedRefundAmount": 1500.00, + "actualRefundAmount": null, + "applicantId": "1001", + "applicantName": "admin", + "ccUserNames": ["admin"], + "approvedById": null, + "approvedByName": null, + "approvedAt": null, + "approveRemark": null, + "createTime": "2026-09-23 15:57:23", + "canApprove": true + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无列表空态。团期已软删时:`batchNo` / `batchName` / `batchLabel` 为 null,`canApprove=false`; +存量已处理单无快照时 `participantCount` 为 null。其余字段照常返回。 + +#### 错误响应 + +```json +{ + "code": 589545, + "message": "流团申请不存在", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589545 | 审批单不存在 / 已软删 / 不是 DISBAND 类型(既有) | +| 589507 | 当前角色无 `group-batch:view`(既有) | + +#### 业务边界 + +- 判权仍是 `group-batch:view`;持该权限但非 ADMIN/SUPER_ADMIN 的账号能看详情,但 `canApprove=false`。 +- 本单交付时 `canApprove` 不校验团期阶段:团期若已推进到出行中,按钮仍可能显示,点同意由端点返回拒绝码,前端以端点返回为准。流团 canApprove 的阶段条件由 #8308 追加,以其 changelog 为准。 +- 只读,无副作用。 + +--- + +### 3. GB-ADM-060 提交流团申请 `POST /v3/admin/order/group-batch/{groupBatchId}/disband` + +**VO**: `DisbandSubmitReqVO` → `DisbandApprovalRespVO` + +#### 使用场景 + +团期详情页「流团」按钮提交申请(语义为提交审批,不立即流团)。响应即新建的审批单,字段同接口 2。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| groupBatchId | Path | Long | 是 | 团期 ID | 既有 | +| reason | Body | String | 是 | 非空白,≤512 字 | 流团理由(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / approvalStatusName / participantCount / canApprove | — | **本次新增**,含义同接口 2。提交成功时 `approvalStatusName=待审批`,`participantCount` 即本次写入的快照 | +| 其余字段 | — | 同接口 2 既有字段,本次未改 | + +#### 请求示例 + +```json +{ + "reason": "8253 验收:流团同意路径" +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636605026306", + "groupBatchId": "2102668502144028673", + "batchNo": "Q202612122102668472460963841", + "batchName": "#8253-流团同意", + "batchLabel": "126", + "approvalStatus": "PENDING", + "approvalStatusName": "待审批", + "reason": "8253 验收:流团同意路径", + "affectedOrderCount": 2, + "participantCount": 4, + "estimatedRefundAmount": 1500.00, + "actualRefundAmount": null, + "applicantId": "1001", + "applicantName": "admin", + "ccUserNames": ["admin"], + "approvedById": null, + "approvedByName": null, + "approvedAt": null, + "approveRemark": null, + "createTime": "2026-09-23 15:57:23", + "canApprove": true + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +团期下无非取消子订单时照常提交:`affectedOrderCount=0`、`participantCount=0`(不是 null)。 + +#### 错误响应 + +```json +{ + "code": 589543, + "message": "该团期已有流团申请在审批中,请勿重复提交", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589500 | 团期不存在(既有) | +| 589507 | 无 `group-batch:manage`(既有) | +| 589543 | 同团期已有在途流团申请(既有) | +| 589544 | 团期已出行,不可发起(既有) | +| 589554 | 团期下有出行中子订单(既有) | +| 400 | `reason` 为空或超长(既有) | + +#### 业务边界 + +- 校验顺序与失败语义不变;任何拒绝都不写审批单、不写快照。 +- 快照与 `affectedOrderCount`、`estimatedRefundAmount` 取自同一批非取消子订单、同一时刻。 +- 响应里 `canApprove` 反映**提交人**自己能否批,不代表审批人。 + +--- + +### 4. GB-ADM-062 同意流团 `POST /v3/admin/order/group-batch/disband/{approvalId}/approve` + +**VO**: `ApproveDisbandReqVO` → `DisbandApprovalRespVO` + +#### 使用场景 + +审批中心列表行或流团详情弹窗点「同意」。批准后执行流团(团期置 CANCELLED、子订单取消、批量退定金)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 审批单 ID | 既有 | +| remark | Body | String | 否 | ≤512 字;请求体可整体省略 | 批复备注(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / approvalStatusName / participantCount / canApprove | — | **本次新增**,含义同接口 2。成功后 `approvalStatusName=已通过`、`canApprove=false`;`participantCount` 返回提交时快照(子订单已全取消也不归零) | +| 其余字段 | — | 同接口 2 既有字段,本次未改 | + +#### 请求示例 + +```json +{ + "remark": "8253 验收:本页同意流团" +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636605026306", + "groupBatchId": "2102668502144028673", + "batchNo": "Q202612122102668472460963841", + "batchName": "#8253-流团同意", + "batchLabel": "126", + "approvalStatus": "APPROVED", + "approvalStatusName": "已通过", + "reason": "8253 验收:流团同意路径", + "affectedOrderCount": 2, + "participantCount": 4, + "estimatedRefundAmount": 1500.00, + "actualRefundAmount": 1500.00, + "applicantId": "1001", + "applicantName": "admin", + "ccUserNames": ["admin"], + "approvedById": "2102028348437970945", + "approvedByName": "cw_test_8006_x", + "approvedAt": "2026-09-23 15:59:30", + "approveRemark": "8253 验收:本页同意流团", + "createTime": "2026-09-23 15:57:23", + "canApprove": false + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空态。存量无快照的申请单批准后 `participantCount` 为 null(子订单已取消,无法还原)。 + +#### 错误响应 + +```json +{ + "code": 589547, + "message": "仅管理员可处理流团审批", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589547 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | +| 589545 | 审批单不存在或非 DISBAND(既有) | +| 589546 | 审批单已处理 / 并发下已被他人处理(既有) | +| 589500 | 团期不存在(既有) | +| 589544 / 589554 | 执行流团时团期已出行 / 有出行中子订单(既有) | + +#### 业务边界 + +- 执行语义、幂等(行锁 + CAS)与失败回滚本次未改;本次只改响应字段。 +- 按钮显隐看 `canApprove`,但最终以本端点返回为准。 + +--- + +### 5. GB-ADM-062 拒绝流团 `POST /v3/admin/order/group-batch/disband/{approvalId}/reject` + +**VO**: `RejectDisbandReqVO` → `DisbandApprovalRespVO` + +#### 使用场景 + +审批中心列表行或流团详情弹窗点「拒绝」,团期继续正常招募。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 审批单 ID | 既有 | +| remark | Body | String | 是 | 非空白,≤512 字 | 拒绝原因(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / approvalStatusName / participantCount / canApprove | — | **本次新增**,含义同接口 2。成功后 `approvalStatusName=已拒绝`、`canApprove=false` | +| 其余字段 | — | 同接口 2 既有字段,本次未改 | + +#### 请求示例 + +```json +{ + "remark": "8253 验收:本页拒绝流团" +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636865089537", + "groupBatchId": "2102668504199254017", + "batchNo": "Q202612132102668472729395201", + "batchName": "#8253-流团拒绝 50%_x", + "batchLabel": "128", + "approvalStatus": "REJECTED", + "approvalStatusName": "已拒绝", + "reason": "8253 验收:流团拒绝路径", + "affectedOrderCount": 1, + "participantCount": 3, + "estimatedRefundAmount": 0.00, + "actualRefundAmount": null, + "applicantId": "1001", + "applicantName": "admin", + "ccUserNames": ["admin"], + "approvedById": "1001", + "approvedByName": "admin", + "approvedAt": "2026-09-23 15:59:30", + "approveRemark": "8253 验收:本页拒绝流团", + "createTime": "2026-09-23 15:57:23", + "canApprove": false + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空态。`actualRefundAmount` 恒 null(拒绝不退款)。 + +#### 错误响应 + +```json +{ + "code": 589547, + "message": "仅管理员可处理流团审批", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589547 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | +| 589545 | 审批单不存在或非 DISBAND(既有) | +| 589546 | 审批单已处理(既有) | +| 400 | `remark` 为空或超长(既有) | + +#### 业务边界 + +- 只改审批单状态,团期、子订单、名额零变化(本次未改)。 +- 文案订正:流团驳回的 `approvalStatusName` 为「已拒绝」,不再是「已取消退单」。 + +--- + +### 6. GB-ADM-072 退单审批分页列表 `GET /v3/admin/order/group-batch/withdraw/page` + +**VO**: `WithdrawApprovalListReqVO` → `PageResult` + +#### 使用场景 + +退单专用列表(既有,保留兼容)。与审批中心列表的退单户行同口径补字段。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalStatus | Query | String | 否 | `PENDING`/`APPROVED`/`REJECTED`/`ALL` | 缺省只返 PENDING(既有) | +| groupBatchId | Query | Long | 否 | 团期 ID | 既有 | +| keyword | Query | String | 否 | — | 客户姓名 / 订单号模糊(既有) | +| createdFrom | Query | String | 否 | `yyyy-MM-dd` | 提交时间起(既有) | +| createdTo | Query | String | 否 | `yyyy-MM-dd`,含当日 | 提交时间止(既有) | +| pageNo | Query | Integer | 否 | 默认 1 | 页码(既有;注意本接口叫 `pageNo`,审批中心列表叫 `pageNum`) | +| pageSize | Query | Integer | 否 | 默认 20,最大 100 | 既有 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| records[].batchName | String | **本次新增**。团期名称;团期查不到时 null | +| records[].batchLabel | String | **本次新增**。期号 | +| records[].customerPhoneMasked | String | **本次新增**。客户手机脱敏(3 位 + `****` + 4 位);订单查不到或无手机号时 null | +| records[].affectedOrderCount | Integer | **本次新增**。影响子订单户数,退单户一户一单,恒 1 | +| records[].participantCount | Integer | 该户人数(既有字段)。**取数改为提交时快照优先**,无快照的存量行按订单现算,数值口径不变 | +| 其余字段 | — | 既有字段(approvalId、groupBatchId、batchNo、productName、departDate、orderId、orderNo、customerName、paidAmount、estimatedRefundAmount、refundMode、refundModeName、reason、applicantName、approvalStatus、approvalStatusName、createdAt),本次未改 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/withdraw/page?approvalStatus=PENDING&pageNo=1&pageSize=5 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [ + { + "approvalId": "2102668636105904130", + "groupBatchId": "2102668373412450306", + "batchNo": "Q202612112102668347315511298", + "batchName": "#8253-退单户同意与拒绝", + "batchLabel": "125", + "productName": "冻干粉发短信给", + "departDate": "2026-12-11", + "orderId": "2102668373257261058", + "orderNo": "HL20260923155620281", + "customerName": "测试八二五三", + "customerPhoneMasked": "138****5678", + "participantCount": 3, + "affectedOrderCount": 1, + "paidAmount": 1500.00, + "estimatedRefundAmount": 1500.00, + "refundMode": "FULL_DEPOSIT", + "refundModeName": "订金全额退", + "reason": "8253 验收:退单户同意路径", + "applicantName": "admin", + "approvalStatus": "PENDING", + "approvalStatusName": "待审批", + "createdAt": "2026-09-23 15:57:23" + } + ], + "total": 1, + "page": 1, + "pageSize": 5 + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +```json +{ + "code": 200, + "message": "成功", + "data": { "records": [], "total": 0, "page": 1, "pageSize": 20 }, + "success": true +} +``` + +#### 错误响应 + +```json +{ + "code": 589530, + "message": "仅管理员可处理退单审核", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589530 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | + +#### 业务边界 + +- 判权不变:仅 ADMIN/SUPER_ADMIN。 +- 本接口**不返回** `canApprove`(能调通本接口即已过审批角色门;是否仍可退团请看详情接口 7)。 +- `affectedOrderCount` 与审批中心列表 WITHDRAW 行同口径,恒 1。 + +--- + +### 7. GB-ADM-073 退单申请详情 `GET /v3/admin/order/group-batch/withdraw/{approvalId}` + +**VO**: `WithdrawApprovalDetailRespVO`(继承 `WithdrawApprovalItemRespVO`) + +#### 使用场景 + +审批中心退单户行点「眼睛」图标打开详情弹窗;弹窗「同意 / 拒绝」按 `canApprove` 显隐,分别接接口 8 / 9。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 退单审批单 ID | 须为 WITHDRAW 类型,否则 589531 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / customerPhoneMasked / affectedOrderCount | — | **本次新增**,同接口 6 | +| participantCount | Integer | 同接口 6(快照优先) | +| canApprove | Boolean | **本次新增**。PENDING 且过审批端点同一道角色门、团期与订单都存在、且团期状态仍允许退团(出行中及以后为 false);恒非 null | +| currentEstimatedRefundAmount / currentRefundMode / refundPolicy / actualRefundAmount / consultantName / approvedByName / approvedAt / approveRemark / refundApplicationId | — | 既有字段,本次未改 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/withdraw/2102668636105904130 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636105904130", + "groupBatchId": "2102668373412450306", + "batchNo": "Q202612112102668347315511298", + "batchName": "#8253-退单户同意与拒绝", + "batchLabel": "125", + "productName": "冻干粉发短信给", + "departDate": "2026-12-11", + "orderId": "2102668373257261058", + "orderNo": "HL20260923155620281", + "customerName": "测试八二五三", + "customerPhoneMasked": "138****5678", + "participantCount": 3, + "affectedOrderCount": 1, + "paidAmount": 1500.00, + "estimatedRefundAmount": 1500.00, + "refundMode": "FULL_DEPOSIT", + "refundModeName": "订金全额退", + "reason": "8253 验收:退单户同意路径", + "applicantName": "admin", + "approvalStatus": "PENDING", + "approvalStatusName": "待审批", + "createdAt": "2026-09-23 15:57:23", + "currentEstimatedRefundAmount": 1500.00, + "currentRefundMode": "FULL_DEPOSIT", + "refundPolicy": null, + "actualRefundAmount": null, + "consultantName": "admin", + "approvedByName": null, + "approvedAt": null, + "approveRemark": null, + "refundApplicationId": null, + "canApprove": true + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空态。团期或订单查不到时对应字段为 null,`canApprove=false`;团期已推进到不可退团的状态时 +`currentEstimatedRefundAmount` / `currentRefundMode` 为 null、`canApprove=false`(既有降级行为,本次只新增 `canApprove`)。 + +#### 错误响应 + +```json +{ + "code": 589530, + "message": "仅管理员可处理退单审核", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589530 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | +| 589531 | 退单申请不存在 / 已软删 / 非 WITHDRAW(既有) | + +#### 业务边界 + +- 判权不变:仅 ADMIN/SUPER_ADMIN;因此能看到本详情的账号角色门恒过,`canApprove=false` 只可能因为非 PENDING、团期/订单缺失或团期已不可退团。 +- 本页不展示「当前预估退款」「实退金额」,字段保留不动。 + +--- + +### 8. GB-ADM-074 退单审核通过 `POST /v3/admin/order/group-batch/withdraw/{approvalId}/approve` + +**VO**: `ApproveWithdrawReqVO` → `WithdrawApprovalDetailRespVO` + +#### 使用场景 + +退单详情弹窗或审批中心列表行点「同意」:取消该户订单、名额 −1 户 / −N 人、按批复时团期状态生成退款。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 退单审批单 ID | 既有 | +| remark | Body | String | 否 | ≤512 字;请求体可整体省略 | 批复备注(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / customerPhoneMasked / affectedOrderCount / canApprove | — | **本次新增**,同接口 7。成功后 `approvalStatusName=已通过`、`canApprove=false` | +| 其余字段 | — | 同接口 7 既有字段,本次未改 | + +#### 请求示例 + +```json +{ + "remark": "8253 验收:本页同意退单" +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636105904130", + "groupBatchId": "2102668373412450306", + "batchNo": "Q202612112102668347315511298", + "batchName": "#8253-退单户同意与拒绝", + "batchLabel": "125", + "productName": "冻干粉发短信给", + "departDate": "2026-12-11", + "orderId": "2102668373257261058", + "orderNo": "HL20260923155620281", + "customerName": "测试八二五三", + "customerPhoneMasked": "138****5678", + "participantCount": 3, + "affectedOrderCount": 1, + "paidAmount": 1500.00, + "estimatedRefundAmount": 1500.00, + "refundMode": "FULL_DEPOSIT", + "refundModeName": "订金全额退", + "reason": "8253 验收:退单户同意路径", + "applicantName": "admin", + "approvalStatus": "APPROVED", + "approvalStatusName": "已通过", + "createdAt": "2026-09-23 15:57:23", + "currentEstimatedRefundAmount": 1500.00, + "currentRefundMode": "FULL_DEPOSIT", + "refundPolicy": null, + "actualRefundAmount": 1500.00, + "consultantName": "admin", + "approvedByName": "cw_test_8006_x", + "approvedAt": "2026-09-23 15:58:55", + "approveRemark": "8253 验收:本页同意退单", + "refundApplicationId": null, + "canApprove": false + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空态。零元退单时 `refundApplicationId` 为 null(既有)。 + +#### 错误响应 + +```json +{ + "code": 589530, + "message": "仅管理员可处理退单审核", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589530 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | +| 589531 | 退单申请不存在(既有) | +| 589532 | 已处理,不可重复操作(既有) | +| 589500 | 团期不存在(既有) | +| 589501 | 团期状态已不允许退团(出行中及以后,既有) | + +#### 业务边界 + +- 执行语义、金额以批复时重算为准、幂等与回滚均未改;本次只改响应字段。 +- `canApprove=true` 时点同意仍可能因团期状态刚变化而收到 589501,以端点返回为准。 + +--- + +### 9. GB-ADM-075 取消退单(驳回) `POST /v3/admin/order/group-batch/withdraw/{approvalId}/reject` + +**VO**: `RejectWithdrawReqVO` → `WithdrawApprovalDetailRespVO` + +#### 使用场景 + +退单详情弹窗或审批中心列表行点「拒绝」:该户继续留在团期,订单 / 名额 / 钱零变动。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| approvalId | Path | Long | 是 | 退单审批单 ID | 既有 | +| remark | Body | String | 是 | 非空白,≤512 字 | 驳回原因(既有) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| batchName / batchLabel / customerPhoneMasked / affectedOrderCount / canApprove | — | **本次新增**,同接口 7。成功后 `approvalStatusName=已取消退单`、`canApprove=false` | +| 其余字段 | — | 同接口 7 既有字段,本次未改 | + +#### 请求示例 + +```json +{ + "remark": "8253 验收:本页取消退单" +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "approvalId": "2102668636365967361", + "groupBatchId": "2102668373412450306", + "batchNo": "Q202612112102668347315511298", + "batchName": "#8253-退单户同意与拒绝", + "batchLabel": "125", + "productName": "冻干粉发短信给", + "departDate": "2026-12-11", + "orderId": "2102668407507963905", + "orderNo": "HL20260923155628432", + "customerName": "测试八二五三乙", + "customerPhoneMasked": "139****1234", + "participantCount": 1, + "affectedOrderCount": 1, + "paidAmount": 500.00, + "estimatedRefundAmount": 500.00, + "refundMode": "FULL_DEPOSIT", + "refundModeName": "订金全额退", + "reason": "8253 验收:退单户拒绝路径", + "applicantName": "admin", + "approvalStatus": "REJECTED", + "approvalStatusName": "已取消退单", + "createdAt": "2026-09-23 15:57:23", + "currentEstimatedRefundAmount": 500.00, + "currentRefundMode": "FULL_DEPOSIT", + "refundPolicy": null, + "actualRefundAmount": null, + "consultantName": "admin", + "approvedByName": "admin", + "approvedAt": "2026-09-23 15:58:55", + "approveRemark": "8253 验收:本页取消退单", + "refundApplicationId": null, + "canApprove": false + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空态。`actualRefundAmount` / `refundApplicationId` 恒 null(驳回不退款)。 + +#### 错误响应 + +```json +{ + "code": 589532, + "message": "该退单申请已处理,不可重复操作", + "data": null, + "success": false +} +``` + +| 错误码 | 触发条件 | +|---|---| +| 589530 | 当前角色不是 ADMIN/SUPER_ADMIN(既有) | +| 589531 | 退单申请不存在(既有) | +| 589532 | 已处理,不可重复操作(既有) | +| 400 | `remark` 为空或超长(既有) | + +#### 业务边界 + +- 订单、名额、退款零变动(本次未改)。 +- 退单户驳回文案保持「已取消退单」,与流团驳回「已拒绝」区分。 + +--- + +## 四、契约约束与正确调用方式 + +### `canApprove` 的定义 + +`canApprove = 审批单为 PENDING && 当前账号过审批端点同一道角色门 && 团期存在 && (退单户:团期状态仍允许退团)` + +- 角色门与审批端点(062/074/075)**复用同一段判定代码**,当前为 ADMIN / SUPER_ADMIN;#8246 若把审批闸改为权限码,本字段同步改。 +- 前端据此**显隐**同意 / 拒绝按钮;按钮点下去的结果仍以端点返回为准(团期状态可能在两次请求之间变化)。 +- 本单交付时流团的 `canApprove` 不看团期阶段,团期已出行时同意会收到 589544 / 589554。 +- 流团 canApprove 的阶段条件由 #8308 追加,以其 changelog 为准。 + +### 团期名称渲染与搜索 + +| 场景 | 请求 | 结果 | +|---|---|---| +| ✅ 名称子串 | `batchName=退单户` | 名称包含该子串的团期下的申请 | +| ✅ 期号 | `batchName=第14期` 或 `batchName=14` | 期号恰为 14 的团期;`14` 另命中名称含「14」的团期;都**不会**命中 114 期 | +| ✅ 含通配符 | `batchName=%_` | `%` `_` 按字面匹配,不当通配符 | +| ✅ 空白 | `batchName=` 或全空格 | 视为不传,返回全部 | +| ❌ 用团期号搜 | `batchName=Q2026...` | 不匹配 batch_no,返回空页;按团期精确筛请用 `groupBatchId` | + +「团期名称」列渲染为 `第{batchLabel}期 {batchName}`;两字段任一为 null(团期已软删)时前端自行兜底。 + +### 电话与金额 + +- `customerPhoneMasked` 已脱敏,库内为密文,接口不提供明文。流团行恒 null。 +- 本页不展示「当前预估退款」「实退金额」;`estimatedRefundAmount` 等既有金额字段保留,老调用方不受影响。 + +### 已知旁路(非本单引入) + +持 `group-batch:view` 的非管理员角色(如 CUSTOMIZER、GROUP_BATCH_MANAGER)能打开审批中心列表与流团详情(含退单户联系人与脱敏电话), +此时 `canApprove` 全为 false;调退单列表 / 详情返回 589530,调审批端点返回 589530(退单)/ 589547(流团)。 +审批中心列表按 bizType 分权属另议,本单不改判权。 + +--- + +## 五、数据库行为 + +- `group_batch_approval` 新增可空列 `participant_count INT NULL`(Flyway `V20260924_825__group_batch_approval_add_participant_count.sql`,版本 `20260924.825`),纯 ADD COLUMN,存量行不回填。 +- 写入时机只有两个提交端点: + - 提交流团(GB-ADM-060,本清单接口 3):写提交时团期下非取消子订单的人数合计(成人+儿童+小童+婴儿),与 `affected_order_count` 同一批户、同一时刻。 + - 提交退单(GB-ADM-070,契约四项未变,不在清单):写被退那一户的人数。 +- 同意 / 拒绝端点(接口 4、5、8、9)对该列只读不写;执行流团、退单、退款的写库行为本次零改动。 +- 列表 / 详情接口只读。名称搜索是先按团期名称 / 期号取团期 ID,再对审批单做 IN 筛选,不写库。 + +--- + +## 六、边界行为 + +- **挂在已软删团期上的申请单**:照常出现在列表,团期侧字段为 null,`canApprove=false`(批复端点届时也会拒绝)。 +- **出行人数取数**:有快照读快照;无快照的存量 PENDING 流团按同口径现算;无快照的已处理流团返回 null;无快照的退单户按该户订单现算。 +- **流团批准后**:子订单全部取消,`participantCount` 仍返回提交时快照(不归零)。 +- **名称搜索零命中**:直接返回 `total=0` 空页,不退化为全表。 +- **角色门拒绝时**:`canApprove` 置 false,列表 / 详情本身不因此报错;对「请求缺角色声明」的处理与审批端点走同一段判定(含同一灰度开关),两者不会分叉。 +- **无 token**:响应体 `code=401`(HTTP 状态码仍为 200),与网关既有行为一致。 + +--- + +## 六.6、修改前后对比 + +| 项 | 修改前 | 修改后 | +|---|---|---| +| 审批中心列表入参 | 无名称搜索 | 新增可选 `batchName` | +| 审批中心列表出参 | 无 `batchLabel` / `participantCount` / `approvedAt` / `customerPhoneMasked` / `canApprove` | 五个字段纯增 | +| 审批中心列表 WITHDRAW 行 `affectedOrderCount` | `null` | `1` | +| 流团驳回 `approvalStatusName` | 「已取消退单」 | 「已拒绝」 | +| 退单户驳回 `approvalStatusName` | 「已取消退单」 | 「已取消退单」(不变) | +| `DisbandApprovalRespVO`(接口 2–5) | 无 `batchName` / `batchLabel` / `approvalStatusName` / `participantCount` / `canApprove` | 五个字段纯增 | +| `WithdrawApprovalItemRespVO`(接口 6–9) | 无 `batchName` / `batchLabel` / `customerPhoneMasked` / `affectedOrderCount` | 四个字段纯增;`participantCount` 改为快照优先(数值口径不变) | +| `WithdrawApprovalDetailRespVO`(接口 7–9) | 无 `canApprove` | 纯增 | +| 路径 / 判权 / 错误码 | — | 逐字未变 | +| 数据库 | — | `group_batch_approval` 新增可空列 `participant_count` | + +--- + +## 六.7、影响评估 + +- **兼容性**:九个接口均为纯增出参或可选入参;两处口径订正(WITHDRAW 行 `affectedOrderCount` null→1、流团驳回文案)只影响展示,未发现依赖旧值做分支判断的调用方。 +- **性能**:列表的角色门整页只算一次;名称搜索多一次按团期名称 / 期号取主键的查询,零命中短路不再查审批单;出行人数优先读快照,只有存量 PENDING 流团才现算。 +- **数据**:新列可空、不回填;存量已处理流团的出行人数返回 null 属预期。 +- **回滚**:撤销 PR #8256、#8260 即可;新列可空,保留不影响旧代码读写。 +- **判权**:未改任何判权;已知旁路见「四」。 + +--- + +## 七、不影响范围 + +- 退单提交(GB-ADM-070)的入参、出参、返回值;流团 / 退单的执行语义、退款金额计算、幂等与并发控制。 +- 审批中心列表与退单列表的既有筛选参数、分页包装(`records` / `total` / `page` / `pageSize`)。 +- 团期看板、团期详情等其他团期接口;小程序端。 +- 网关:路径未变、无新增路由与权限码。 + +--- + +## 八、测试环境已验证 + +2026-09-23,TEST(api.test.1814.love:9443),部署 dev-v3(含 `4f9b6facb`)。造数:新建 3 个团期(期号 125 / 126 / 128), +提交 2 张退单、2 张流团申请,分别走同意 / 拒绝四条路径,逐项对库。 + +| 验证项 | 读数 | +|---|---| +| 审批中心列表全量对库 | 接口 `total=62`、本页 62 行、库内未删行 62;逐行比对异常 0;已处理 57 行 `approvedAt` 与库一致,`canApprove` 全 false | +| 审批中心列表 WITHDRAW 行 `affectedOrderCount` | 19 行全部为 1(改前同一接口为 null) | +| 流团驳回文案 | 列表 DISBAND/REJECTED 行 `approvalStatusName` 全为「已拒绝」(改前为「已取消退单」);WITHDRAW/REJECTED 仍为「已取消退单」 | +| 已软删团期上的 PENDING 单 | 4 行团期字段为 null、`canApprove=false` | +| 电话脱敏 | WITHDRAW 19 行中 18 行形如 `138****5678`,1 行为 null;DISBAND 行全 null | +| 名称搜索:子串 | 命中「#8253-退单户同意与拒绝」2 行 | +| 名称搜索:期号 | `第14期` → 6 行全为 14 期,不含 114 期;`14` → 8 行(14 期 6 行 + 名称含「14」的 2 行),同样不含 114 期;`第1期` → 3 行全为 1 期 | +| 名称搜索:零命中 | `total=0`、`records=[]` | +| 名称搜索:`%` / `_` / `%_` | 各只命中名称为「#8253-流团拒绝 50%_x」的 1 行 | +| 名称搜索:空串 / 全空白 | 与不传一致,`total=62` | +| 名称搜索:团期号 | 两种团期号输入均 `total=0` | +| `canApprove`(4 张 PENDING) | SUPER_ADMIN / ADMIN:列表与两类详情全 true;GROUP_BATCH_MANAGER / CUSTOMIZER:列表与流团详情全 false,退单列表 / 详情 589530 | +| 低权限调审批端点 | GROUP_BATCH_MANAGER / CUSTOMIZER 调流团同意 / 拒绝 589547,调退单同意 / 拒绝 589530 | +| 出行人数快照 | 提交后 `participant_count` 落库:流团 4 / 3,退单 3 / 1 | +| 退单同意 | 订单 `CUSTOMIZING → CANCELLED`;团期 enrolled 人/户 4/2 → 1/1;退款申请 `2102669022577479682` APPROVED,应退 1500.00 / 实退 1500.00;`approved_by_name` 有值 | +| 退单拒绝 | 该户订单状态与 update_time 不变,无退款申请;`approvalStatusName=已取消退单` | +| 流团同意 | 团期 `RECRUITING → CANCELLED`,2 张活跃子订单取消,退款申请 `2102669171114561538` APPROVED 1500.00 / 1500.00;批准后接口 `participantCount` 仍为 4 | +| 流团拒绝 | 团期状态、名额、update_time 不变;`approvalStatusName=已拒绝` | +| 无 token | 响应体 `code=401`,HTTP 200 | +| 退单列表 / 详情(072/073)`affectedOrderCount` | 16:17 部署 dev-v3(含 `11dd1e2fb`)后实测:退单列表 `approvalStatus=ALL` 共 19 行,`affectedOrderCount` 全为 1;退单详情 `2102668636105904130` 连取 4 次(覆盖两实例)均为 1 | + +**2026-09-24 补验:退单户团期不可退团**(TEST,部署面板显示后端检出为 dev-v3 `cc70c9ba3`,含 `4f9b6facb` / `11dd1e2fb`)。 +提交时团期若已出行,GB-ADM-070 就会直接返回 589501,所以先在招募中的测试团期「#8253-退单户同意与拒绝」(`2102668373412450306`)上提交退单 +`2102953813164072962`,再用 SQL 把该团期 `batch_status` 从 `RECRUITING` 临时改为 `TRAVELLING`: + +| 验证项 | 读数 | +|---|---| +| 招募中基线 | 列表与退单详情该单 `canApprove=true`,详情 `currentRefundMode=FULL_DEPOSIT` | +| 出行中:审批中心列表(`groupBatchId` 过滤,超管) | 该 PENDING 单 `canApprove=false` | +| 出行中:退单详情(超管) | `canApprove=false`,`currentRefundMode` / `currentEstimatedRefundAmount` 为 null | +| 出行中:超管调退单同意 | `code=589501`,message「团期状态不允许当前操作」(HTTP 200) | +| 同意被拦后对库 | 审批行仍 `PENDING`、无批复人;订单仍 `CUSTOMIZING` / `DEPOSIT_PAID`,update_time 不变 | +| 恢复 | 团期 `batch_status` 改回 `RECRUITING`,`update_time` 也改回原值 `2026-09-23 15:58:55`,并回查确认;恢复后退单详情 `canApprove=true`。随后驳回这张补验用的退单,清掉造数 | + +单元测试(本地):`GroupBatchDisbandApprovalServiceTest` 56 例、`GroupBatchWithdrawApprovalServiceTest` 35 例、 +`GroupBatchWithdrawApprovalControllerRoleGateTest` 13 例,合计 104 例 0 失败。 + +--- + +## 十、相关文档 + +- 工单 #8253;PR #8256(merge `4f9b6facb`)、PR #8260(merge `11dd1e2fb`) +- 审批中心列表补 orderNo / customerName / departDate 的前序:#7535 +- 名称 / 期号搜索口径同团期看板 keyword:#7942 +- 审批闸改权限码的后续:#8246(hl-ui 两个审批页 isAdmin 整页门禁见其 A9) +- 流团审批:#7196;退单审批:#7100 + +## 关联 / 联系人 + +- 后端:jw +- 前端:待认领(`frontend_status: pending`)