$configModel->isRepurchaseEnable(), 'self_enable' => $configModel->isRepurchaseSelfEnable(), 'self_type' => $configModel->getRepurchaseSelfType(), 'self_amount' => $configModel->getRepurchaseSelfAmount(), 'self_rate' => $configModel->getRepurchaseSelfRate(), ]; } catch (\Throwable $e) { $config = [ 'enable' => false, 'self_enable' => false, 'self_type' => 'fixed', 'self_amount' => 0.0, 'self_rate' => 0.0, ]; } return $config; } /** * 检查商品是否开启复购规则 * * @param int $goodsId * @return bool */ public static function isGoodsRepurchaseEnable($goodsId) { if (!$goodsId) { return false; } try { $row = Db::name('shopro_commission_goods') ->where('goods_id', $goodsId) ->where('status', 1) ->field('repurchase_enable') ->find(); return !empty($row['repurchase_enable']); } catch (\Throwable $e) { return false; } } /** * 检查用户是否曾购买过该指定商品(有效付款订单) * * @param int $userId * @param int $goodsId * @return bool */ public static function isUserRepurchasedGoods($userId, $goodsId) { if (!$userId || !$goodsId) { return false; } try { $count = Db::name('shopro_order_item') ->alias('oi') ->join('shopro_order o', 'o.id = oi.order_id') ->where('o.user_id', $userId) ->where('o.status', 'in', [1, 2]) ->where('oi.goods_id', $goodsId) ->where('oi.refund_status', '<=', 0) ->count(); return $count > 0; } catch (\Throwable $e) { return false; } } /** * 计算单项商品的复购立减金额 * * @param array $item 商品信息 (goods_id, goods_num, goods_price, goods_amount) * @param array $config 复购配置 * @param bool $isGoodsEnable 该商品是否开启复购 * @param bool $isUserRepurchase 该用户是否复购该商品 * @return float */ public static function calculateItemDiscount($item, $config, $isGoodsEnable, $isUserRepurchase) { if (empty($config['enable']) || empty($config['self_enable'])) { return 0.0; } if (!$isGoodsEnable || !$isUserRepurchase) { return 0.0; } $goodsNum = isset($item['goods_num']) ? intval($item['goods_num']) : 1; $goodsAmount = isset($item['goods_amount']) ? floatval($item['goods_amount']) : 0.0; $goodsPrice = isset($item['goods_price']) ? floatval($item['goods_price']) : ($goodsNum > 0 ? $goodsAmount / $goodsNum : 0.0); if ($goodsAmount <= 0) { return 0.0; } $discount = 0.0; $selfType = $config['self_type'] ?? 'fixed'; if ($selfType === 'rate') { $rate = floatval($config['self_rate'] ?? 0); if ($rate > 0) { $discount = round($goodsAmount * $rate * 0.01, 2); } } else { // 固定金额模式:按件数累加立减 $unitAmount = floatval($config['self_amount'] ?? 0); if ($unitAmount > 0) { // 单件立减不可超过单件售价 $validUnitDiscount = min($unitAmount, $goodsPrice); $discount = round($validUnitDiscount * $goodsNum, 2); } } // 兜底保护:总立减金额不可超过商品总额 if ($discount > $goodsAmount) { $discount = $goodsAmount; } return max(0.0, $discount); } /** * 批量计算订单中各商品的复购立减金额 * * @param array $goodsList 商品列表 * @param int $userId 用户ID * @param array|null $config 配置 * @param callable|null $goodsRuleChecker 自定义商品规则检查器 (用于单测或依赖注入) * @param callable|null $historyChecker 自定义历史购买检查器 (用于单测或依赖注入) * @return array ['goods_list' => ..., 'total_repurchase_discount' => float] */ public static function calculateOrderRepurchaseDiscounts( $goodsList, $userId, $config = null, $goodsRuleChecker = null, $historyChecker = null ) { if ($config === null) { $config = self::getConfig(); } $totalDiscount = 0.0; foreach ($goodsList as $key => $item) { $goodsId = $item['goods_id'] ?? 0; // 检查商品是否参与复购 $isGoodsEnable = false; if ($goodsRuleChecker !== null) { $isGoodsEnable = (bool) call_user_func($goodsRuleChecker, $goodsId); } else { $isGoodsEnable = self::isGoodsRepurchaseEnable($goodsId); } // 检查用户是否复购该商品 $isUserRepurchase = false; if ($isGoodsEnable) { if ($historyChecker !== null) { $isUserRepurchase = (bool) call_user_func($historyChecker, $userId, $goodsId); } else { $isUserRepurchase = self::isUserRepurchasedGoods($userId, $goodsId); } } $discount = self::calculateItemDiscount($item, $config, $isGoodsEnable, $isUserRepurchase); $goodsList[$key]['repurchase_discount_money'] = $discount; $goodsList[$key]['is_repurchase'] = ($isGoodsEnable && $isUserRepurchase && $discount > 0) ? 1 : 0; $totalDiscount = bcadd((string) $totalDiscount, (string) $discount, 2); } return [ 'goods_list' => $goodsList, 'total_repurchase_discount' => floatval($totalDiscount) ]; } }