文件
xionggeshop/addons/shopro/library/commission/RepurchaseService.php

207 行
6.5 KiB
PHP

<?php
namespace addons\shopro\library\commission;
use think\Db;
/**
* 复购立减服务类
* 针对指定商品(开启复购规则)且买家历史买过的商品,在付款时直接减免
*/
class RepurchaseService
{
/**
* 获取全局复购立减配置
*
* @return array
*/
public static function getConfig()
{
$config = [];
try {
$configModel = new Config();
$config = [
'enable' => $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)
];
}
}