15 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 | 8005 | 退单户候选列表 GB-ADM-070b 与提交前预览 GB-ADM-070c | admin | jw(GIT) | 新增接口 | deployed | verified | verified | mmg | 0ab85a7e31452d16483b718b6449d0534c8ddb02 | 2026-09-20 | 团期「退单户」弹窗两个新端点:候选下拉 GET .../{groupBatchId}/withdraw-candidates 每行给「联系人·团号·订单号·已付金额」并只返回当前可退的户(排除已取消/已完成/出行中,以及已提交待审的户);摘要条 GET .../{groupBatchId}/sub-order/{orderId}/withdraw-preview 在点「提交退团审核」之前给出「待退多少」,零写入,与提交响应逐分一致。A3 /orders 与 GB-ADM-070 提交端点不变。后端已合并 dev-v3(0139aebe4)并部署 TEST,网关实测 AC-1~AC-10 全通过。前端待办:下拉改调新端点并展示四段;选中一户后调预览端点渲染摘要条(不要用 /v3/admin/order/{id}/cancel-preview,那个恒按退改政策算,团期早期阶段会少显示)。注意人数字段是 participantCount(与 A3、GB-ADM-072/073 同名),不是 peopleCount。前端已交付(hl-ui v2.1 @ 0ab85a7e):下拉改调 withdraw-candidates 按四段渲染(teamNo null 省略团号段、customerName null 兜「未命名」);选中一户即调 withdraw-preview 渲染摘要条(FULL_DEPOSIT 显「待退定金」/POLICY 显「预计退款」,同行亮已付避免误读订金基数,warnings 逐条渲染,快速切换选中户有竞态防护);人数取 participantCount;未使用 cancel-preview。新建弹窗 spec 7/7,scoped checkpoint 全绿。 | 2026-09-20 | dev-v3 |
order-v3: 退单户候选列表与提交前预览
存放目录:
changelogs-v2/{YYYY-MM}/(管理后台,二期 order-v3)服务: hl-order-service-v3 (端口 8086) PR: #8010 Issue: #8005 日期: 2026-09-20 影响范围: 管理后台「团期订单 → 团期详情 → 退单户」弹窗
⚠️ 关键变化
- 新增候选下拉端点,每行给四段:订单联系人 · 团号 · 订单号 · 已付金额。原先前端拿 A3
/orders喂下拉,那是带出行人/需求明细的重装配分页接口,且没有可退性过滤。 - 新增提交前预览端点,在点「提交退团审核」之前就能给出「待退定金 ¥11,860」。原先唯一算这个数的入口是提交端点本身(写方法、会建待审申请单)。
- 候选只返回当前可退的户:已取消 / 已完成 / 出行中的户,以及已提交退单待审的户,不再出现在下拉里。
- 人数字段是
participantCount,与 A3 子订单项、GB-ADM-072/073 同名。
一、背景
退单弹窗的下拉每行只显示「未命名 · HL20260920105808925」——兜底文案加一串订单号,运营无法判断要退的是哪一户、退了要退多少钱。
后端其实一直在返回姓名与已付金额(A3 的 customerName / paidAmount),「未命名」是前端兜底文案;但后端确有三个缺口:候选集没有可退性过滤(已提交待审的户能被重复选中,提交端才靠 589529 兜底)、联系人姓名零回落、以及提交前拿不到预计退款额。本单补前两个缺口并新开预览端点,A3 与提交端点均不动。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 退单户候选列表 | GET | /v3/admin/order/group-batch/{groupBatchId}/withdraw-candidates |
新增 | 下拉候选行:联系人/团号/订单号/已付金额 + 人数 + 支付状态中文名 |
| 2 | 退单预览 | GET | /v3/admin/order/group-batch/{groupBatchId}/sub-order/{orderId}/withdraw-preview |
新增 | 提交前给两个金额与退改政策,零写入 |
三、接口详情
1. 退单户候选列表 GET /v3/admin/order/group-batch/{groupBatchId}/withdraw-candidates
VO: Result<List<WithdrawCandidateVO>>
使用场景
「退单户」弹窗的「选择要退的子订单」下拉。前端按 customerName · teamNo · orderNo · 已付 ¥paidAmount 渲染每一行;teamNo 为 null 时省略团号那一段,该行仍要展示。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | 是 | 团期主订单 ID | 团期不存在返 589500 |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
| orderId | String | 子订单 ID(Long 序列化为字符串,避免精度丢失) |
| orderNo | String | 订单号,HL + 17 位,创单即生成、永不变 |
| teamNo | String | 团号,形如 26-3627。订金支付成功后才生成,未付订金为 null |
| customerName | String | 订单联系人。order_main.customer_name 为空时回落首位出行人姓名;仍为空返 null(前端自行兜文案,后端不返「未命名」) |
| participantCount | Integer | 该户人数(成人+儿童+小童+婴儿)。与 A3、GB-ADM-072/073 同名,不是 peopleCount |
| paidAmount | BigDecimal | 该户已付(毛累计,含订金+尾款,退款不回减),与 GB-ADM-070 提交响应同源 |
| payStatusName | String | 支付状态中文名:未支付 / 已付定金 / 已付全款 |
请求示例
GET /v3/admin/order/group-batch/2101506167098511362/withdraw-candidates
Authorization: Bearer <token>
响应示例
(测试服真实响应,2026-09-20;团期「jw测试1期」5 户,其中 2 户未付订金)
{
"code": 200,
"message": "成功",
"data": [
{
"orderId": "2101506167043985410",
"orderNo": "HL20260920105808925",
"teamNo": "26-3627",
"customerName": "张三",
"participantCount": 6,
"paidAmount": 2000.00,
"payStatusName": "已付定金"
},
{
"orderId": "2101507603395973121",
"orderNo": "HL20260920110351387",
"teamNo": null,
"customerName": "晓辉",
"participantCount": 2,
"paidAmount": 0.00,
"payStatusName": "未支付"
}
],
"success": true
}
空数据 / 降级响应
团期下没有可退的户(全部已取消/已完成/出行中,或全部已提交待审)时返回空数组,不是 null:
{ "code": 200, "message": "成功", "data": [], "success": true }
错误响应
{ "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "data": null }
| code | 触发条件 |
|---|---|
| 589500 | 团期不存在(含已软删) |
| 589507 | 没有 group-batch:view 权限 |
| 401 | 未登录(网关拦截) |
业务边界
- 只读,零副作用。
- 只返回订单状态 ∈ {
PENDING_PAY,CUSTOMIZING,PENDING_DEPARTURE} 且没有在途(PENDING)退单申请的户。 - 未付订金的户不排除:
teamNo为 null、paidAmount为0.00照常下发。 - 排序与 A3 一致(按子订单 ID 升序)。
- 该户一旦提交退单申请,立即从本列表消失;申请被驳回后重新出现。
2. 退单预览 GET /v3/admin/order/group-batch/{groupBatchId}/sub-order/{orderId}/withdraw-preview
VO: Result<WithdrawSubOrderRespVO>(与 GB-ADM-070 提交响应同构,仅 approvalId 为 null)
使用场景
下拉里选中一户后、点「提交退团审核」之前,渲染摘要条「退款户:陈昊 · 2 人 · 定制师 王浩 · 待退定金 ¥11,860」。联系人与人数取候选行,定制师与两个金额取本端点。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | 是 | 团期主订单 ID | 团期不存在返 589500 |
| orderId | Path | Long | 是 | 子订单 ID | 不属于该团期返 589502 |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
| approvalId | String | 恒为 null——尚未建单,本端点不写库 |
| paidAmount | BigDecimal | 该户已付 |
| estimatedRefundAmount | BigDecimal | 预计退款额。FULL_DEPOSIT 模式下基数是订金应付额(不是已付额) |
| refundMode | String | FULL_DEPOSIT(招募中/资源准备中全退定金)/ POLICY(物资准备中/待出发按退改政策阶梯扣) |
| refundPolicy | Object | 退改政策明细,仅 POLICY 模式给,否则 null |
| consultantName | String | 该户定制师姓名(信息项,不是审批人) |
| warnings | Array | 非阻断提示,如满团提示、订金为 0 提示;无提示时为空数组 |
请求示例
GET /v3/admin/order/group-batch/2101506167098511362/sub-order/2101506167043985410/withdraw-preview
Authorization: Bearer <token>
响应示例
(测试服真实响应,2026-09-20;团期招募中 → FULL_DEPOSIT,该户已付 2000、订金应付 9000)
{
"code": 200,
"message": "成功",
"data": {
"approvalId": null,
"paidAmount": 2000.00,
"estimatedRefundAmount": 9000.00,
"refundMode": "FULL_DEPOSIT",
"refundPolicy": null,
"consultantName": "金卫",
"warnings": []
},
"success": true
}
空数据 / 降级响应
POLICY 模式下退改政策取不到时 refundPolicy 为 null,两个金额照常返回;warnings 无提示时是空数组而非 null。
{
"code": 200,
"message": "成功",
"data": {
"approvalId": null,
"paidAmount": 500.00,
"estimatedRefundAmount": 500.00,
"refundMode": "POLICY",
"refundPolicy": null,
"consultantName": null,
"warnings": []
},
"success": true
}
错误响应
{ "code": 589501, "message": "团期状态不允许当前操作", "data": null }
| code | 触发条件 |
|---|---|
| 589500 | 团期不存在 |
| 589501 | 团期已到出行中及以后(与提交端点同口径,走售后退款) |
| 589502 | 该子订单不属于本团期 |
| 589507 | 没有 group-batch:view 权限 |
业务边界
- 零写入:不建 PENDING 申请单、不写状态时间线、不动订单/名额/金额。测试服实测调用前后
group_batch_approval行数不变。 - 与提交端点走同一套退款模式解析与金额估算,两个金额与提交后逐分一致(
FULL_DEPOSIT与POLICY两种模式均已实测对照)。 - 不判「是否已有在途申请」:已提交待审的户本就不在候选列表里,预览是只读的。
- 实退以审批通过时按当时团期状态重算的为准;
POLICY下距出发天数每天在变。
四、契约约束与正确调用方式
| 场景 | 做法 |
|---|---|
| ✅ 渲染退单下拉 | 调 withdraw-candidates,按 customerName · teamNo · orderNo · 已付 ¥paidAmount 四段渲染 |
✅ teamNo 为 null |
省略团号那一段,该行仍要展示(未付订金的户照样能退) |
✅ customerName 为 null |
前端自行兜文案(如「未命名」);后端只在真没有姓名时返 null |
| ✅ 渲染摘要条的「待退多少」 | 调 withdraw-preview |
❌ 继续拿 A3 /orders 喂下拉 |
它没有可退性过滤,已取消户、已提交待审的户都会出现,运营可能重复提交 |
❌ 用 /v3/admin/order/{id}/cancel-preview 算待退金额 |
那个恒按退改政策算,团期早期阶段(全退定金)会少显示 |
❌ 用 peopleCount 取人数 |
本端点是 participantCount,与 A3、GB-ADM-072/073 一致 |
❌ 把 estimatedRefundAmount 当最终退款额 |
实退按审批通过时重算 |
六、边界行为
- 团期下无可退户 →
data: []。 - 未付订金户 →
teamNo: null、paidAmount: 0.00,仍在候选内。 - 联系人为空 → 回落首位出行人姓名;出行人也无名或无出行人 →
customerName: null。 - 该户已提交退单待审 → 从候选消失;驳回后重新出现(实测:5 户 → 提交后 4 户 → 驳回后 5 户)。
- 团期到出行中及以后 → 预览返 589501,与提交端点一致。
FULL_DEPOSIT模式estimatedRefundAmount取订金应付额,可能大于paidAmount(实测已付 2000 / 预计退 9000)。- 低权限角色(无
group-batch:view)→ 589507;SUPER_ADMIN/GROUP_BATCH_MANAGER/ADMIN/FINANCE放行。
七、不影响范围
- 仅新增两个只读端点,未改任何既有接口的入参、出参与行为。
- 零影响:
- A3
GET .../{groupBatchId}/orders(不动,仍带出行人/需求明细) - GB-ADM-070 提交退单
POST .../sub-order/{orderId}/withdraw(不动,重复提交仍按 589529 拒) - GB-ADM-072/073/074/075 审批列表、详情、通过、驳回
- 数据库:无表结构变更、无 Flyway
- 网关:新端点落在既有
/v3/admin/**通配路由内,无需改路由
- A3
八、测试环境已验证
被测版本:hl-order-service-v3 = dev-v3 0139aebe4(2026-09-20 12:53 部署,双实例滚动完成)。取证前确认面板检出 dev-v3 @ 0139aebe4、hl-order-service-v3 与 hl-gateway 均 running;部署前同样两条路径返回业务码 404,可证被测的就是本单代码。网关 https://api.test.1814.love:9443 实测:
AC-1 候选 5 行,四段齐全 + participantCount + payStatusName ✓
AC-2 未付订金 2 户(2101507603395973121 / 2101508527082336258)teamNo=null、paidAmount=0.00,仍在列 ✓
AC-3 customer_name 置空串 → 回落「回落出行人甲」;删出行人 → null;出行人姓名为空格 → null;
三种情况该户均仍在候选内,响应中「未命名」出现 0 次 ✓(夹具已回滚)
AC-4 对张三提交退单 → 候选 5→4 户、该户消失;驳回后 4→5 户恢复 ✓
AC-5 候选 paidAmount 与 GB-ADM-070 提交响应逐分一致:FULL_DEPOSIT 2000.00=2000.00、POLICY 500.00=500.00 ✓
AC-6 SALES → 589507(candidates 与 preview 均拦);SUPER_ADMIN / GROUP_BATCH_MANAGER / ADMIN / FINANCE → 200 ✓
AC-7 预览 vs 提交 estimatedRefundAmount:FULL_DEPOSIT 9000.00=9000.00、POLICY 500.00=500.00,refundMode 亦一致 ✓
AC-8 预览调用前后 group_batch_approval 行数 55→55 不变;提交后才 56 ✓
AC-9 TRIP_FINISHED 团期:预览 589501、提交 589501,口径一致 ✓
AC-10 提交时传 reason → 审批列表与详情均回读到该原因 ✓
AC-11 团期置 TRAVELLING:预览 / 提交 / 审批通过三处均 589501,且三次调用前后
审批单总数、该申请状态(PENDING)、团期已报名(5 户/17 人)、订单状态与金额逐项不变 = 零写入 ✓
本地:定向 61/0/0(新增 12 例);order-v3 全量两遍 11453/F1 + 748/F0,唯一失败 MapperBoundaryArchTest.non_refund_not_depend_on_refund_mapper 为 payment 域基线既存(干净 dev-v3 同样失败),与本单无交点。
十、相关文档
- 关联 Issue: wx/HL#8005
- 关联 PR: wx/HL#8010
- 接口文档:
docs/group/团期模块接口文档-v2.0.html已补 GB-ADM-070b / GB-ADM-070c 两节与判权表两行