── 以下是给代码的注释(会落在 miniapp_orders.py 里)──

-- 🔴 下单/退款两处「按未核销比例分摊」重复 —— 为什么不能抽成函数

-- (2026-10-10 审查记录,留档避免下一个人把它当技术债"修"掉)

--

-- ## 表面上看是重复

-- 申请退款(L1811): key_refund_fen = key_deduct_fen * pending_fen // total_fen

-- 执行退款(L1957): key_refund_fen = order["key_deduct_fen"] * pending_fen // total_fen

-- 公式一样,像是同一段代码抄了两遍。

--

-- ## 但两处 pending_fen 的算法有实质差异,而且是故意的

--

-- ① 申请退款(L1795-1805)

-- if status == "completed" or redeemed_at: → 算已核销

-- else: → 算未核销

-- 有兜底:没有 fulfillment_items 时,pending_fen = total_fen

-- ⇒ 无履约项的订单也能申请退款(按整单退)

--

-- ② 执行退款(L1946-1951)

-- if status != "completed" and not redeemed_at: → 算未核销

-- 无兜底:pending_fen == 0 直接 422「无未核销履约项,不可退款」

-- ⇒ 无履约项的订单申请时通过、执行时拒绝

--

-- ## 结论:这是两个阶段的不同设计,不是同一逻辑的重复实现

-- 申请阶段对用户宽容(先受理,别当场拦死);

-- 执行阶段要求可核验(没有履约项就无法判断退多少,直接拒)。

-- 抽成一个函数会把这条差异抹平 ⇒

-- 轻则「申请通过的、执行时被拒」变成静默行为差异,

-- 重则下一个人以为"两处算法不一致是 bug",去"修"成一致 ⇒ 真的引入 bug。

--

-- ## 所以本次不改代码,只留这段说明。

-- 若将来确实要合并,前提是先跟业务确认:

-- 「无履约项的订单,退款申请通过但执行时 422」到底是不是期望行为?

-- 答案若是「不是」,那才是 bug,应该单独修而不是顺手重构。

🔴 2026-10-10:退款金额计算在申请与执行两处各有一份,看着像重复实现,其实不能合并:

- pending_fen 的兜底不同(申请阶段无履约项时按整单、执行阶段直接 422);

- 这是「申请宽、执行严」的有意设计,合并会把差异抹平。

⇒ 详见 backend/sql/../docs 或本文件末尾的说明。改动前请先确认业务期望。