hl-api-changelog/changelogs/2026-04/24_fix_order-v2_balance-unconfirmed-discount.md

3.2 KiB

未确认优惠不再扣减尾款(修复 balanceAmount 负数显示)

日期: 2026-04-24 PR: #1340 (dev) Issue: #1339 类型: fix 服务: hl-order-service-v2


摘要

订单详情页/列表页的尾款字段 balanceAmount 之前会把未确认优惠也扣进去,导致优惠金额大于总售价时显示为负数(例如总售价 ¥2.00、未确认优惠 ¥560.00、已付 ¥0.10 → 尾款 ¥-558.10),但同页文案又写着「以下优惠未确认,暂不影响尾款」,自相矛盾。

本次修复统一让 3 处尾款计算走 BalanceCalculator(架构详设 3.1 唯一真相源),只扣 confirmed=1 的已确认优惠/增项,符合清单确认前「暂不影响尾款」的业务承诺。

影响接口(路径/返回结构不变)

所有返回 balanceAmount 字段的接口,行为一致性修复:

接口 来源
GET /admin/order/{orderId} OrderDetailQueryService.assembleDetail
GET /admin/order/page OrderListQueryService.toOrderListVO
GET /mp/order/page OrderListQueryService.toMpOrderListVO
GET /mp/order/{orderId} MpOrderDetailAssembler.buildBasicFields

新旧对比

旧公式(3 处都一样)

balance = totalPrice - order.discountAmount + order.surchargeAmount - (depositAmount 或 paidAmount)

其中 order.discountAmount = DB 缓存字段,包含未确认优惠

新公式(统一走 BalanceCalculator)

balance = totalPrice - Σ(confirmed=1 优惠) + Σ(confirmed=1 增项) - paidAmount

未确认条目(confirmed=0 或 NULL)不算入尾款

前端视图影响

  • 顶部「尾款」 由 -558.10 之类的异常值变为合理值(本订单场景 = 1.90)
  • 顶部「优惠」合计金额(discountAmount 字段) 保持不变 — 仍显示所有优惠之和(含 pending),前端继续按原字段渲染无需改动
  • 确认清单时后端 T5 状态机 guard 会拦截「尾款为负」导致的锁单(此行为原已存在,本 PR 不动)

行为举例

订单场景:总售价 ¥2.00,订金 ¥0.10,已付 ¥0.10,一条 ¥560 房间优惠 confirmed=0

字段 修复前 修复后
totalPrice 2.00 2.00
paidAmount 0.10 0.10
discountAmount(合计展示) 560.00 560.00
balanceAmount(尾款) -558.10 1.90

确认清单把优惠 confirmed 置 1 后,balanceAmount 才会变为 -558.10;届时 T5 状态机 guard 会拒绝锁单,提示管理员先清理超额优惠。

风险与回滚

  • 只改 VO 组装层,不改接口签名/字段/DB schema
  • 所有单测(MpOrderDetailAssemblerTest 63/63、OrderDetailQueryServiceTest 17/17、OrderListQueryServiceTest 8/8)+ 全量 2414/2415 通过
  • 测试服 curl 验证:订单 HL20260423175303-5448 balanceAmount 从 -558.10 修正为 1.90
  • 回滚:revert PR #1340 即可恢复旧行为

遗留优化(后续独立 PR)

order_info.discount_amount 字段由 OrderDiscountService.sumByOrderId 写入时未过滤 confirmed,语义上包含 pending。本 PR 未动(前端「优惠合计」依赖这个字段显示 pending+confirmed 总和)。后续会单独统一语义并给前端提供独立 pendingDiscountSum / confirmedDiscountSum 字段,本次不涉及。