refund_price 全链路(超详细版)

1. 业务定义(一句话)

⚡⚡⚡ 汇总订单所有「退款中 + 退款完成」状态的退款单金额,形成退款口径,用于展示和可退额度计算;独立于 total_price 体系,不参与订单应付金额汇总

2. 后台配置到前台计算的关系

2.1 商家后台可控项(配置映射表)

后台配置项典型存储/来源前台读取点对计算的直接影响
退款状态流转退款流程updateRefundStatus决定是否计入累计
退款单金额o_order_refund.pricegetRefundPrice参与求和
退款状态o_order_refund.statusgetRefundPrice 过滤仅 IN_PROGRESS + FINISH 计入
订单应付价保护total_priceupdateRefundStatus用于计算可退额度

2.2 全链路时序图(配置 → 计算 → 落库)

flowchart TD
A[退款申请/退款完成] --> B[写 o_order_refund 退款单]
B --> C[updateRefundStatus 更新退款状态]
C --> D{退款状态}
D -->|退款中| E[getRefundPrice: IN_PROGRESS+FINISH 求和]
D -->|退款完成| F[getRefundPrice: IN_PROGRESS+FINISH 求和]
D -->|退款失败| G[不计入 refund_price]
E --> H[写 o_order.refund_price]
F --> H
H --> I[计算 refund_status: 200=部分退款/300=全额退款]

3. 核心入口与数据结构

3.1 核心方法链路

OrderRefundService.php
  └─ getRefundPrice(OrderModel $orderInfo)    SQL SUM,退款口径
  └─ updateRefundStatus(...)                  写 refund_price + refund_status

3.2 退款状态常量

常量值常量名含义是否计入 refund_price
1REFUND_STATUS_IN_PROGRESS退款中✅ 是
2REFUND_STATUS_FINISH退款完成✅ 是
3REFUND_STATUS_ERROR退款失败❌ 否

只有状态为「退款中」和「退款完成」的退款单才会被计入 refund_price

4. 完整计算逻辑

4.1 getRefundPrice(查询统计)

public function getRefundPrice(OrderModel $orderInfo) : float
{
    return OrderRefundModel::master()->where([
        'store_id' => $this->storeId,
        'order_id' => $orderInfo->getId(),
    ])->whereIn('status', [
        OrderRefundModel::REFUND_STATUS_IN_PROGRESS,
        OrderRefundModel::REFUND_STATUS_FINISH,
    ])->sum('price');
}

特点:直接 SQL SUM,不走 PHP 循环,高效。

⚡⚡⚡ refund_price 的语义是「已申请退款的金额(无论是否到账)」,而不是「已实际退款到账的金额」。

4.2 updateRefundStatus(状态与金额联动)

// 当 status == 退款中 (REFUND_STATUS_IN_PROGRESS)
$refundPrice  = $this->getRefundPrice($orderInfo);
$refundStatus = bcsub($orderInfo['total_price'], $refundPrice, 2) <= 0 ? '300' : '200';
$save = [
    'refund_price'  => $refundPrice,
    'refund_status' => $refundStatus,  // 200=部分退款, 300=全额退款
];

refund_status 语义:

refund_status含义触发条件
200部分退款total_price - refund_price > 0(还有余款未退)
300全额退款total_price - refund_price <= 0(退够了)

4.3 refund_price 与 total_price 的关系

o_order.refund_price   = Σ(退款单.price),仅含 IN_PROGRESS + FINISH 状态
o_order.total_price    = Σ(9个current_字段),订单应付金额

两者完全独立:
- total_price 是「订单应收多少钱」
- refund_price 是「已经申请退了多少」
- total_price - refund_price = 「还需退多少 / 已退够否」

重要澄清refund_price 不参与 total_price 的9字段汇总,total_price 的9字段中没有 refund_price。两者是独立的平行指标。

5. 字段输出结构

字段类型含义示例
o_order.refund_pricefloat累计退款金额(正数)80.00
o_order.refund_statusstring退款状态(200/300等)200
o_order_refund[].pricefloat单笔退款金额50.00
o_order_refund[].statusint单笔退款状态2

6. 边界场景说明

6.1 退款失败(status=3)不计入

失败退款单有独立的回滚逻辑(dec('refund_price', price)),不会长期占用 refund_price 累计。

6.2 多笔退款单并存

同时存在 IN_PROGRESS(50) + FINISH(30) → refund_price = 80refund_status 由总额判断。

6.3 退款中变为退款完成

status 从 1→2,getRefundPrice 的条件仍然包含两者,结果不变——refund_price 保持,但 refund_status 可能从200变为300(取决于总金额)。

6.4 退款完成后又申请新退款

第二次退款中,新增的金额会叠加,refund_status 重新判断。

6.5 total_price 被修改后退款金额未同步

若退款时 total_price 因优惠等原因已变化,已计入的退款仍按原金额算(退款单 price 字段是固定值)。可能出现「退款金额 > total_price」(会触发 refund_status=300 全额判断)。

7. 关键代码索引

逻辑文件:行号
getRefundPrice SQL SUMOrderRefundService.php:566-572
updateRefundStatus 写回OrderRefundService.php:263-409
退款状态常量OrderRefundModel.php:35-37
退款完成回滚逻辑OrderRefundService.php 退款完成分支
total_price 9字段汇总(无 refund_price)OrderService.php:2282-2290