current_offer_price 全链路(超详细版)
1. 业务定义(一句话)
⚡⚡⚡ 订单级插件(如积分兑换、买家保障、定制服务等)的明细价格逐条汇总,形成 current_offer_price,写入 o_order.current_offer_price 后参与 total_price 汇总。
2. 后台配置到前台计算的关系
2.1 商家后台可控项(配置映射表)
| 后台配置项 | 典型存储/来源 | 前台读取点 | 对计算的直接影响 |
|---|---|---|---|
| 插件启用状态 | 各 handler 配置 | OrderDiyOfferService | 决定是否写入明细行 |
| 插件来源 | o_order_diy_offer.from_name | 明细表 | 区分积分/保障/改价等不同插件 |
| 插件价格 | o_order_diy_offer.price | 明细表 | 正数=附加费,负数=抵扣 |
| 订单ID | o_order_diy_offer.order_id | 查询条件 | 保证只汇总当前订单 |
2.2 全链路时序图(配置 → 计算 → 落库)
flowchart TD A[插件策略/后台操作] --> B[OrderDiyOfferModel 写 o_order_diy_offer 明细] B --> C["getOrderDiyOfferPrice(order_id)"] C --> D[SQL 查询该订单全部明细行] D --> E["PHP: Σ(price) 求和"] E --> F[round 保留2位小数] F --> G[setAttr current_offer_price] G --> H[renew 重算 total_price]
3. 核心入口与数据结构
3.1 核心方法链路
OrderDiyOfferService.php
└─ getOrderDiyOfferPrice(OrderModel $orderInfo) 汇总计算
└─ OrderDiyOfferModel::getDiyOfferList() 查明细
└─ updateOrderInfo(OrderModel $orderInfo) 触发写回+renew
3.2 插件类型(from_name 典型取值)
| from_name | 含义 | price 典型符号 |
|---|---|---|
points / points_off | 积分兑换抵扣 | 负数 |
buyer_protection | 买家保障附加 | 正数 |
gift_pack | 礼品包装附加 | 正数 |
custom_service | 定制服务附加 | 正数 |
assembly_fee | 组装费附加 | 正数 |
⚠️ from_name 仅为追踪来源,不参与求和逻辑,所有插件明细的 price 一律求和。
4. 完整计算逻辑
4.1 getOrderDiyOfferPrice
private function getOrderDiyOfferPrice(OrderModel $orderInfo) : float
{
$list = (new OrderDiyOfferModel())
->getDiyOfferList($orderInfo->getStoreId(), $orderInfo->getId());
if ($list->isEmpty()) {
return 0.00;
}
return array_sum(array_column($list->toArray(), 'price'));
}- SQL 查出订单所有插件明细
- PHP 一行
array_sum求和 - 无明细时返回
0.00
⚡⚡⚡ price 字段本身可正可负——负数表示抵扣(如积分兑换),正数表示附加费,最终汇总后可能相互抵消。
4.2 updateOrderInfo(触发重算)
public function updateOrderInfo(OrderModel $orderInfo)
{
$newOfferPrice = round($this->getOrderDiyOfferPrice($orderInfo), 2);
$orderInfo->setAttr('current_offer_price', $newOfferPrice);
(new OrderService())->renew($orderInfo->getId());
}5. 字段输出结构
| 字段 | 类型 | 含义 | 示例 |
|---|---|---|---|
o_order.current_offer_price | float | 汇总金额(可正可负) | -7.00 |
o_order_diy_offer.price | float | 单笔插件金额 | -10.00 / 3.00 |
o_order_diy_offer.from_name | string | 插件来源标识 | points_off |
6. 边界场景说明
6.1 明细为空
getDiyOfferList 返回空集合 → current_offer_price = 0.00
6.2 多插件同时生效且正负相抵
积分抵扣 -10 + 礼品包装 +3 → current_offer_price = -7
6.3 同一插件重复写入
若 o_order_diy_offer 有重复行,会被重复累计——这是数据质量问题,需在上游写入时做幂等校验。
6.4 updateOrderInfo 后总价未变
可能是 renew 未执行到写入逻辑,检查 renew 中 current_offer_price 的写回分支。
7. 与总价 total_price 的关系
total_price 的组成(9字段):
subtotal_price = Σ(final_line_price) 商品行小计
discount_price = 整单折扣(负数)
refund_price = 退款口径独立(不在此9字段中)
current_total_price = subtotal + shipping 仅展示
total_price = subtotal - promotion - coupon + shipping + tax + tip + payment + insurance + offer
└─ offer_price 在此处被加(可正可负)
⚡⚡⚡ offer_price 可正可负(附加费为正,抵扣为负),在 total_price 中做相应加减。
8. 关键代码索引
| 逻辑 | 文件:行号 |
|---|---|
| getOrderDiyOfferPrice | OrderDiyOfferService.php:181-189 |
| updateOrderInfo(触发renew) | OrderDiyOfferService.php:174-179 |
| OrderDiyOfferModel::getDiyOfferList | OrderDiyOfferModel.php |
| 明细表字段 schema | OrderDiyOfferModel.php:18 |
| total_price 9字段汇总 | OrderService.php:2282-2290 |