文件
hl-api-changelog/changelogs-v2/2026-09/05_7100_团期退单户改为提交申请与管理员审批-修改接口-管理后台.md
T
Mimingguang 0dec0584f9
changelog-filename-gate / validate (push) Failing after 2s
chore(changelog): 回写 #7100 前端 verified
2026-09-05 11:20:24 +08:00

28 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 7100 团期退单户:提交退单申请 + 管理员审批(070 破坏性变更 + 072~075 新增) admin jw(GIT) 修改接口 deployed verified verified mmg 4bc8dd4d 2026-09-05 已过网关真测(2026-09-05,admin 切 ADMIN 角色,5 端点全链路含提交/驳回/再提交/通过);含 #7126 预估口径修复后的复测 2026-09-05 dev-v3

团期: 退单户改为「提交申请 + 管理员审批」

服务: hl-order-service-v3 PR: #7106 Issue: #7100 日期: 2026-09-04 影响范围: 管理后台团期详情「退单户」弹窗 + 新增退单审批中心


⚠️ 关键变化

POST .../sub-order/{orderId}/withdraw 是破坏性变更:调用它不再退款,只建一张待审申请单。

三条前端必读:

  1. 响应体由 Result<Void> 变成对象。老前端只看 code 不读 data 的话不会崩,但提示语必须改—— 现在的语义是「已提交审核」,不是「已退款」。
  2. 金额要显示两个数:paidAmount(已付)和 estimatedRefundAmount(预计退)。 两者可以不相等,而且早期阶段常常不等——招募中 / 资源准备中退的是订金应付额, 与已付多少无关(TEST 实测:已付 ¥0、订金 ¥2000 的单,预计退与实退都是 ¥2000)。 不要自己调 /v3/admin/order/{id}/cancel-preview 算——那个接口恒按退改政策算, 与早期阶段的订金口径对不上。
  3. 审批中心是新界面:列表 → 详情 → 通过 / 取消退单(4 个新端点),入口按角色显隐, 仅 ADMIN / SUPER_ADMIN 可见,其余角色调用返 589530。

一、背景

原来的退单户是「点一下就退款」:提交那一刻订单即 CANCELLED、团期名额当场释放、退款单自动建, 招募中/资源准备中甚至免审直退。但业务要的是可以取消退单,且取消后该户继续留在团期里走原流程—— 订单都取消了、名额可能已被新客户占走,这事根本做不到。

故改为先挂申请单、批了才执行:PENDING 期间订单 / 名额 / 钱三项零变动, 该户照常提需求、排房排车;管理员通过才真正退团,驳回则全程无痕、可再次提交。

退款口径没有变:仍按团期状态选模式(招募中 / 资源准备中全退定金,物资准备中 / 待出发按退改政策阶梯扣)。 变的只是「什么时候执行」和「谁点头」。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 退单户·提交退单申请 POST /v3/admin/order/group-batch/:groupBatchId/sub-order/:orderId/withdraw 修改 破坏性:由「直接退款」改为「建待审申请单」,响应体 Void → 对象
2 退单审批分页列表 GET /v3/admin/order/group-batch/withdraw/page 新增 审批中心列表,缺省只返待审
3 退单申请详情 GET /v3/admin/order/group-batch/withdraw/:approvalId 新增 含「提交时预估」与「当前预估」两个金额
4 退单审核通过 POST /v3/admin/order/group-batch/withdraw/:approvalId/approve 新增 此刻才执行退团:订单取消 + 名额回落 + 退款
5 取消退单(驳回) POST /v3/admin/order/group-batch/withdraw/:approvalId/reject 新增 该户继续留在团期中走原流程

三、接口详情

1. 退单户·提交退单申请 POST /v3/admin/order/group-batch/:groupBatchId/sub-order/:orderId/withdraw

VO: WithdrawSubOrderReqVO / WithdrawSubOrderRespVO

使用场景

团期详情底部操作条点「退单户」→ 弹窗选一户(下拉数据仍用既有的 GET /v3/admin/order/group-batch/:groupBatchId/orders,后端没有另开候选接口)→ 填退团原因 → 点「提交退团审核」时调用。调完钱不动,等管理员在审批中心处理。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ - 团期主订单 ID
orderId Path Long ✅ - 要退的子订单 ID(= 一户)
reason Body String ❌ ≤512 字 退团原因;不传后端记「团期退团」。整个 body 可省略

出参 Result<WithdrawSubOrderRespVO>

字段 类型 说明
approvalId String 退单审批单 ID(雪花,序列化为字符串),审批中心用它取详情
paidAmount BigDecimal 该户已付款额,弹窗「已付 ¥5,000」取此列
estimatedRefundAmount BigDecimal 预计退款额,弹窗「预计退 ¥3,500」取此列。FULL_DEPOSIT 时 = 订金应付额(与已付无关),POLICY 时 = 已付额按政策扣减后;实退以审批通过时重算为准
refundMode String FULL_DEPOSIT=全退定金 / POLICY=按退改政策阶梯扣
refundPolicy Object 退改政策明细,仅 POLICY 模式给(用于展示「距出发 6 天,扣 30%」),否则为 null
consultantName String 该户定制师姓名。信息项,不是审批人,前端不得暗示他要来点头
warnings String[] 非阻断提示(如当前已满团,退单通过后将空出 1 户);无则为空数组

请求示例

{ "reason": "客户临时有事无法参团" }

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "approvalId": "1955009900112233",
    "paidAmount": 5000.00,
    "estimatedRefundAmount": 3500.00,
    "refundMode": "POLICY",
    "refundPolicy": { "policyName": "标准退改政策", "policyId": 12 },
    "consultantName": "李雯",
    "warnings": []
  },
  "success": true
}

空数据 / 降级响应

写操作,无空数据形态。refundPolicy 在 FULL_DEPOSIT 阶段恒为 null(退订金不看政策), 此时 estimatedRefundAmount 是订金应付额,与 paidAmount 无关,两者不等属正常:

{
  "code": 200,
  "data": {
    "approvalId": "1955009900112234",
    "paidAmount": 5000.00,
    "estimatedRefundAmount": 2000.00,
    "refundMode": "FULL_DEPOSIT",
    "refundPolicy": null,
    "warnings": []
  },
  "success": true
}

错误响应

{
  "code": 589529,
  "message": "该户已有退单审核在途,请勿重复提交",
  "success": false,
  "data": null
}

四类拒绝:

code 含义
589500 团期不存在
589501 团期状态不允许退团(出行中及以后,走售后退款)
589512 子订单不属于该团期
589529 该户已有在途退单申请

业务边界

  • 零副作用:本接口只 INSERT 一行审批单。订单状态、团期已报名人数/户数、退款单三项分文未动。
  • 未付分文也能提交,但不等于退 0:
    • 招募中 / 资源准备中(FULL_DEPOSIT)退的是订金应付额,未付款的单照样会退订金并生成退款单—— 这是订单侧既有口径(D3 决策),不是本次引入;如果这不符合业务预期,需要在订单侧另开工单讨论。
    • 物资准备中 / 待出发(POLICY)以已付额为基数,未付则退 0、不生成退款单。
    • 订金为 0 时 warnings 会提示「该户订金为 0…」——这类单提交得进去但审批会被订单侧拒绝。
  • 出行后拒:出行中 / 核算中 / 已结算 / 已取消一律 589501,且在建单之前就拒,不会留下批不掉的单。
  • 幂等:同一 groupBatchId + orderId 5 秒窗口内重复提交只成功一次;顺序重复由 589529 兜底。
  • 金额会漂移:POLICY 模式下「距出发天数」每天在变,本接口返回的是提交时的预估,仅供展示。
  • 兼容:body 整体可省略;老前端不读 data 也不会报错,但提示文案必须改。

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

VO: WithdrawApprovalListReqVO / WithdrawApprovalItemRespVO

使用场景

退单审批中心的列表页。缺省只返待审单,管理员进来就是「待我处理」的视图。

入参

字段 位置 类型 必填 约束 说明
approvalStatus Query String ❌ PENDING/APPROVED/REJECTED/ALL 缺省 PENDING;查全部传 ALL
groupBatchId Query Long ❌ - 按团期筛选
keyword Query String ❌ - 客户姓名 / 订单号模糊匹配(两者取并集)
createdFrom Query String ❌ yyyy-MM-dd 提交时间起;格式非法则忽略该条件
createdTo Query String ❌ yyyy-MM-dd 提交时间止,含当日
pageNo Query Integer ❌ ≥1,默认 1 页码
pageSize Query Integer ❌ ≤100,默认 20 每页条数,超 100 截断

出参 Result<PageResult<WithdrawApprovalItemRespVO>>

字段 类型 说明
approvalId String 退单审批单 ID
groupBatchId String 团期 ID
batchNo String 团期号
productName String 产品名称
departDate String 出发日期 yyyy-MM-dd
orderId String 子订单 ID
orderNo String 订单号
customerName String 客户姓名
participantCount Integer 该户人数(成人+儿童+小童+婴儿)
paidAmount BigDecimal 已付款额(提交时快照)
estimatedRefundAmount BigDecimal 预计退款额(提交时快照)
refundMode String FULL_DEPOSIT / POLICY
reason String 退团原因
applicantName String 提交人姓名
approvalStatus String PENDING / APPROVED / REJECTED
createdAt DateTime 提交时间

请求示例

GET /v3/admin/order/group-batch/withdraw/page?approvalStatus=PENDING&pageNo=1&pageSize=20

响应示例

{
  "code": 200,
  "data": {
    "records": [
      {
        "approvalId": "1955009900112233",
        "batchNo": "GT-26-0007",
        "productName": "小蒙马亲子团",
        "departDate": "2026-10-01",
        "orderNo": "GT-26-0099",
        "customerName": "林婉清",
        "participantCount": 2,
        "paidAmount": 5000.00,
        "estimatedRefundAmount": 3500.00,
        "refundMode": "POLICY",
        "reason": "临时有事无法参团",
        "applicantName": "王磊",
        "approvalStatus": "PENDING",
        "createdAt": "2026-09-04 17:20:11"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20
  },
  "success": true
}

空数据 / 降级响应

无待审单,或 keyword 未命中任何客户/订单号时返回空页(不是 null):

{ "code": 200, "data": { "records": [], "total": 0, "page": 1, "pageSize": 20 }, "success": true }

错误响应

{
  "code": 589530,
  "message": "仅管理员可处理退单审核",
  "success": false,
  "data": null
}
code 含义
589530 当前登录人不是管理员角色

业务边界

  • 鉴权:仅 ADMIN / SUPER_ADMIN 放行;定制师 / 财务 / 房务 / 车务一律 589530。前端入口应按角色显隐,不要靠调用失败来判断。
  • 排序:按提交时间倒序。
  • 性能:整页的团期与子订单各批量取一次,不随行数放大查询。
  • 日期容错:createdFrom / createdTo 格式非法时忽略该条件并继续查询,不报错。

3. 退单申请详情 GET /v3/admin/order/group-batch/withdraw/:approvalId

VO: WithdrawApprovalDetailRespVO

使用场景

审批中心点进某一单。管理员在这里看清楚「退谁、退多少、现在退多少」再决定通过还是取消。

入参

字段 位置 类型 必填 约束 说明
approvalId Path Long ✅ - 退单审批单 ID

出参 Result<WithdrawApprovalDetailRespVO>

字段 类型 说明
(列表行全部字段) - 见接口 2 的出参表
currentEstimatedRefundAmount BigDecimal 当前预计退款额(实时重算)。审批通过时按它执行
currentRefundMode String 当前退款模式;团期状态推进后可能与提交时不同
refundPolicy Object 当前退改政策明细(POLICY 模式给)
actualRefundAmount BigDecimal 实际退款额,审批通过后回填;未通过为 null
consultantName String 该户定制师(信息项,非审批人)
approvedByName String 批复人姓名;未批复为 null
approvedAt DateTime 批复时间;未批复为 null
approveRemark String 批复备注
refundApplicationId String 通过后生成的退款申请 ID

请求示例

GET /v3/admin/order/group-batch/withdraw/1955009900112233

响应示例

{
  "code": 200,
  "data": {
    "approvalId": "1955009900112233",
    "orderNo": "GT-26-0099",
    "customerName": "林婉清",
    "participantCount": 2,
    "paidAmount": 5000.00,
    "estimatedRefundAmount": 3500.00,
    "refundMode": "POLICY",
    "currentEstimatedRefundAmount": 3200.00,
    "currentRefundMode": "POLICY",
    "consultantName": "李雯",
    "approvalStatus": "PENDING",
    "approvedByName": null,
    "approvedAt": null,
    "actualRefundAmount": null,
    "refundApplicationId": null
  },
  "success": true
}

空数据 / 降级响应

团期已推进到不可退阶段(出行中及以后)时,当前预估取不到,currentEstimatedRefundAmount / currentRefundMode 降级为 null,单子仍可查看——但点通过会被 589501 拦住:

{
  "code": 200,
  "data": {
    "approvalId": "1955009900112233",
    "estimatedRefundAmount": 3500.00,
    "currentEstimatedRefundAmount": null,
    "currentRefundMode": null
  },
  "success": true
}

refundApplicationId 目前恒为 null——退款单由订单取消事件异步建,取消响应里不带该 ID。 需要跳退款单请用 orderId 去退款工作台查。

错误响应

{
  "code": 589531,
  "message": "退单申请不存在",
  "success": false,
  "data": null
}
code 含义
589530 非管理员角色
589531 申请单不存在 / 已删除

业务边界

  • 两个预估都要展示:estimatedRefundAmount 是提交时快照,currentEstimatedRefundAmount 是当前值。 POLICY 下距出发天数每天在变,实退按当前值算,只给前者会误导审批人。
  • 鉴权:同列表,仅管理员。

4. 退单审核通过 POST /v3/admin/order/group-batch/withdraw/:approvalId/approve

VO: ApproveWithdrawReqVO / WithdrawApprovalDetailRespVO

使用场景

审批中心详情页点「通过」。这一刻才真正退团:订单取消、团期名额回落、退款进实退链路。

入参

字段 位置 类型 必填 约束 说明
approvalId Path Long ✅ - 退单审批单 ID
remark Body String ❌ ≤512 字 批复备注;body 可整体省略

出参 Result<WithdrawApprovalDetailRespVO>

字段 类型 说明
(详情全部字段) - 见接口 3
approvalStatus String 固定 APPROVED
actualRefundAmount BigDecimal 实际退款额(按批复时团期状态重算,可能与提交时快照不同)
approvedByName String 批复人(当前登录人)
approvedAt DateTime 批复时间

请求示例

{ "remark": "已与客户确认,同意退单" }

响应示例

{
  "code": 200,
  "data": {
    "approvalId": "1955009900112233",
    "approvalStatus": "APPROVED",
    "refundMode": "POLICY",
    "estimatedRefundAmount": 3500.00,
    "actualRefundAmount": 3200.00,
    "approvedByName": "刘涛",
    "approvedAt": "2026-09-04 18:02:35"
  },
  "success": true
}

空数据 / 降级响应

写操作,无空数据形态。团期时间线写失败会降级(记 WARN)但不影响退团成功。 paidAmount = 0 的零元退单:订单照常取消,actualRefundAmount 为 0,不生成退款单:

{ "code": 200, "data": { "approvalStatus": "APPROVED", "actualRefundAmount": 0.00 }, "success": true }

错误响应

{
  "code": 589532,
  "message": "该退单申请已处理,不可重复操作",
  "success": false,
  "data": null
}
code 含义
589501 团期已推进到不可退阶段(出行中及以后)
589512 子订单不属于该团期
589530 非管理员角色
589531 申请单不存在
589532 申请单已是终态(已通过 / 已取消)

业务边界

  • 钱以批复时为准:审批通过时重新按当时团期状态选模式、重算金额,不认提交时的快照。 典型场景:提交时团期还在资源准备中(全退 5000),批复时已进物资准备(按政策退 3200)→ 实退 3200。
  • 一次到位:团期侧审批完即执行,退款不再进退款审批中心二次审。
  • 名额回落:1 单 = 1 户 = 1 房,通过后该团期已报名 −1 户 / −N 人。
  • 并发:按 approvalId 加分布式锁 + 状态 CAS 双保险,两名管理员同时点通过只有一个成功,另一个 589532。
  • 不可撤销:钱一旦进实退链路就撤不回来,要撤走售后退款。

5. 取消退单(驳回) POST /v3/admin/order/group-batch/withdraw/:approvalId/reject

VO: RejectWithdrawReqVO / WithdrawApprovalDetailRespVO

使用场景

审批中心详情页点「取消退单」。该户继续留在团期中走原流程,可以继续提需求、住房用车、正常出行。

入参

字段 位置 类型 必填 约束 说明
approvalId Path Long ✅ - 退单审批单 ID
remark Body String ✅ 非空,≤512 字 驳回原因(合规要求必填),body 不可省略

出参 Result<WithdrawApprovalDetailRespVO>

字段 类型 说明
(详情全部字段) - 见接口 3
approvalStatus String 固定 REJECTED
approveRemark String 驳回原因
approvedByName String 操作人
approvedAt DateTime 操作时间

请求示例

{ "remark": "客户已改口,继续参团" }

响应示例

{
  "code": 200,
  "data": {
    "approvalId": "1955009900112233",
    "approvalStatus": "REJECTED",
    "approveRemark": "客户已改口,继续参团",
    "approvedByName": "刘涛",
    "approvedAt": "2026-09-04 18:05:12"
  },
  "success": true
}

空数据 / 降级响应

写操作,无空数据形态。时间线写失败降级不阻断驳回。

错误响应

{
  "code": 589532,
  "message": "该退单申请已处理,不可重复操作",
  "success": false,
  "data": null
}
code 含义
589530 非管理员角色
589531 申请单不存在
589532 申请单已是终态

remark 为空时走参数校验,返回校验失败提示(非业务码)。

业务边界

  • 零副作用:只改申请单状态。订单状态、团期名额、退款单三项分文未动。
  • 可再次提交:驳回后该户可以再走一遍退单户流程(在途判重只拦 PENDING 单)。
  • 并发:同 approve,锁 + CAS 双保险。

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

✅ 正确 / ❌ 错误 payload 对照

// ✅ 提交退单:body 可省略,也可只带 reason
{ "reason": "客户临时有事无法参团" }

// ❌ 不要再期待「调完就退款了」——现在只是建了一张待审单
// ❌ 不要传 refundMode:退款模式由后端按团期状态定,前端无权指定

// ✅ 取消退单:remark 必填
{ "remark": "客户已改口,继续参团" }

// ❌ 取消退单不传 remark → 参数校验失败
{}

金额取哪个数

  • 弹窗展示 → 提交接口返回的 paidAmount + estimatedRefundAmount
  • 审批详情展示 → paidAmount + currentEstimatedRefundAmount(当前值才是实退依据)
  • 都不要调 /v3/admin/order/{id}/cancel-preview 自己算,它恒按退改政策算,团期早期会少显示

五、数据库行为

  • 提交时新增一条退单审批记录(待审),不改订单、不改团期计数、不建退款单。
  • 审批通过时才发生:订单流转为已取消、团期已报名人数/户数回落、按金额生成退款申请并进实退链路 (金额为 0 时不生成退款申请)。
  • 取消退单(驳回)只更新审批记录的状态与批复信息,其余数据零变动。
  • 提交 / 通过 / 驳回各写一条团期时间线;写失败降级为 WARN,不影响主流程。
  • 同一子订单同时只允许存在一条待审记录。

六、边界行为

  • 出行中及以后不允许退单,提交与审批两处都拦(589501),走售后退款。
  • 未付分文可以退单;早期阶段(全退订金)仍会按订金应付额退并生成退款单,后期阶段(按政策)才退 0 且不生成退款单。
  • 已满团的团期提交退单会返回 warnings 提示,不阻断。
  • 审批期间该户完全正常:可提需求、可排房排车、可被派资源。
  • 审批期间若该户又付了尾款,通过时按当前已付款额重算退款。

六.5、枚举 / 数据字典

审批状态(approvalStatus)

值 含义 可做的操作
PENDING 待审 通过 / 取消退单
APPROVED 已通过(已退团) 无(终态)
REJECTED 已取消退单 无(终态);该户可再次提交新申请

退款模式(refundMode)

值 含义 出现阶段
FULL_DEPOSIT 全额退订金应付额(与已付款额无关;订金为 0 时订单侧拒绝退款) 招募中 / 资源准备中
POLICY 以已付款额为基数按退改政策阶梯扣减 物资准备中 / 待出发

六.6、修改前后对比

针对 POST /v3/admin/order/group-batch/:groupBatchId/sub-order/:orderId/withdraw:

维度 修改前 修改后
调用后果 立即退款:订单取消、名额释放、退款单自动建 只建待审申请单,三项零变动
招募中 / 资源准备中 免审直退,钱当场退 同样要管理员审批
物资准备中 / 待出发 退款单挂起等定制师审 团期侧审批通过后一次到位,不再二次审
响应体 Result<Void>,data 为 null Result<WithdrawSubOrderRespVO>,含两个金额与审批单 ID
能否反悔 不能,订单已取消 能,管理员可「取消退单」,该户继续留在团期
退款金额口径 按团期状态选模式 不变,仍按团期状态选模式
谁审批 定制师(且早期免审) 管理员角色(ADMIN / SUPER_ADMIN)

六.7、影响评估

  • 前端必改:提交成功后的提示语(「已退款」→「已提交审核,待管理员确认后退款」); 弹窗金额改为两行展示;新增审批中心三个页面(列表 / 详情 / 通过与取消)。
  • 不改也不会崩:响应体从 null 变对象是向后兼容的(老前端不读 data 即可), 但业务语义会错——用户以为钱退了,实际还在等审批。属必须跟进项。
  • 运营流程变化:招募期退款不再是秒退,需要管理员点一下;换来的是可撤销。
  • 其他端:C 端、小程序、财务侧退款工作台均不受影响——退款单的建立与实退链路完全没动。
  • 回滚:回滚本次发布即恢复旧行为;已建的待审申请单不会自动执行,需人工处理。

七、不影响范围

  • 转订单 POST .../transfer-in(#7095)——两件事,各走各的,本次未动。
  • 团期成团 / 取消成团 / 流团 / 调整容量 / 预支等其余团期动作端点。
  • 子订单列表 GET /v3/admin/order/group-batch/:groupBatchId/orders——退单弹窗下拉仍用它,出参未变。
  • 订单侧散客退改政策与 /v3/admin/order/{id}/cancel-preview,口径与实现均未动。
  • 退款工作台的申请、审核、实退链路。
  • C 端 / 小程序全部接口。

八、测试环境已验证

过网关真测已完成(2026-09-05,https://api.test.1814.love:9443, admin 账号经 POST /admin/auth/login + POST /admin/auth/switch-role 切到 ADMIN 角色)。 测试数据:在团期 Q202610312089667212070612994(资源准备中)代下两单并全程验证后作废。

# 验证项 结果
1 角色门:ROOM_MANAGER 调审批列表 589530 拒绝 ✅
2 072 列表(ADMIN,缺省 PENDING / ALL) 200,分页结构 records/total/page/pageSize ✅
3 073 详情:不存在的单 589531 ✅
4 070 提交:不存在的团期 589500 ✅
5 070 提交:真团期 + 不存在的子订单 581007 订单不存在 ✅
6 070 提交:真实子订单 200,返 approvalId + 两个金额 + 模式 ✅
7 提交后订单/名额零变动 订单仍 PENDING_PAY,enrolled 仍 2/1 ✅
8 072 列表出现该待审单 total=1,字段齐 ✅
9 073 详情双预估 提交时预估与当前预估均返回 ✅
10 070 重复提交 589529 ✅
11 075 取消退单 200 → REJECTED ✅
12 驳回后该户仍在团里 订单仍 PENDING_PAY,enrolled 仍 2/1,三项零变动 ✅
13 已处理的单再驳 589532 ✅
14 驳回后可再次提交 200,新 approvalId ✅
15 074 审核通过 200 → APPROVED,回填批复人/实退额 ✅
16 通过后订单取消 + 名额回落 订单 CANCELLED,enrolled 2/1 → 0/0 ✅
17 已通过的单再批 589532 ✅
18 075 remark 为空 400「驳回原因不能为空」✅
19 预估 == 实退 预估 ¥2000 = 实退 ¥2000 ✅(见下方缺陷)

实测暴露并已修复的缺陷

首轮实测发现:已付 ¥0 的单,弹窗显示「预计退 ¥0」,审批通过后实退 ¥2000——预估与实退不同源。 根因是订单侧 FULL_DEPOSIT 退的是订金应付额而非已付额,本模块的预估函数错用了已付额。 已由 PR #7126 修复(预估改用订金、订金为 0 时出 warning),重新部署后复测预估与实退一致。 两轮验证产生的退款单(2096027837650616321、2096029516789915650)均已置 REJECTED, 无实退记录,测试环境资金零变动。

部署记录

  • 2026-09-04 19:39–19:40 首次部署(PR #7106)
  • 2026-09-05 08:14–08:15 修复后重新部署(PR #7126)

两次均从 dev-v3 重新构建 hl-order-service-v3 并滚动重启,8186 / 8086 双实例先后健康。

本地测试

mvn -pl hl-order-service-v3 -am test 共 8175 例,Failures: 0、Errors: 7—— 7 例全部是 Testcontainers 迁移测试因本机无 Docker 报 IllegalState,与本次改动无关。 GroupBatchWithdrawApprovalServiceTest 18 例(含 3 例订金口径回归)、 GroupBatchFinanceServiceTest 24 例、团期全域 553 例全绿;ArchUnit 架构规则全绿。


九、相关历史 PR

PR Issue 说明 是否仍有效
PR #7126 #7100 实测暴露的预估口径修复(FULL_DEPOSIT 按订金算) ✅ 最新
PR #7106 #7100 退单户改为申请 + 管理员审批,新增 072~075 ✅ 有效
#7103 #7095 团期转订单(与本次并行开发,错误码与迁移号已错开) ✅ 有效

十、相关文档

  • 关联 Issue: wx/HL#7100
  • 关联 PR: wx/HL#7106
  • 后续计划: 流团审批复用同一套审批表(本次只做退单);已通过后的撤销走售后,不在本次范围

关联 / 联系人

链接

联系人

  • 后端负责人: @jw