781 行
16 KiB
PHP
781 行
16 KiB
PHP
<?php
|
|
|
|
|
|
|
|
namespace addons\shopro\library\commission;
|
|
|
|
|
|
|
|
use addons\shopro\library\commission\Config;
|
|
|
|
use addons\shopro\model\commission\Level as LevelModel;
|
|
|
|
use addons\shopro\model\commission\Order as OrderModel;
|
|
|
|
use addons\shopro\model\commission\Reward as RewardModel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 分佣业务
|
|
|
|
*/
|
|
|
|
class Commission
|
|
|
|
{
|
|
|
|
public $_config;
|
|
|
|
public $item;
|
|
|
|
public $buyer;
|
|
|
|
public $goods;
|
|
|
|
public $amount = 0;
|
|
|
|
public $commissionLevel = 0;
|
|
|
|
public $selfBuy;
|
|
|
|
|
|
|
|
/** @var array */
|
|
|
|
protected $agentLevelRulesCache = [];
|
|
|
|
|
|
|
|
const COMMISSION_CLOSE = 0;
|
|
|
|
|
|
|
|
public function __construct($item)
|
|
|
|
{
|
|
|
|
$this->buyer = new Agent($item['user_id']);
|
|
|
|
$this->item = $item;
|
|
|
|
$this->_config = new Config();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function checkAndSetCommission()
|
|
|
|
{
|
|
|
|
if (!$this->item || !$this->buyer->user) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->goods = new Goods($this->item['goods_id'], $this->item['goods_sku_price_id']);
|
|
|
|
if (!$this->goods->commissionGoods) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->goods->getCommissionConfig()) {
|
|
|
|
$this->_config->setConfig($this->goods->getCommissionConfig());
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->commissionLevel = $this->_config->getCommissionLevel();
|
|
|
|
if (self::COMMISSION_CLOSE === $this->commissionLevel) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->selfBuy = $this->buyer->isAgentAvaliable() && $this->_config->isSelfBuy();
|
|
|
|
$hasParentOrSelfBuy = $this->buyer->getParentAgentId() || $this->selfBuy;
|
|
|
|
|
|
|
|
$hasChainCommission = $this->_config->isChainCommissionEnable()
|
|
|
|
&& $this->goods->getCommissionRules()
|
|
|
|
&& $hasParentOrSelfBuy;
|
|
|
|
|
|
|
|
$hasTierCommission = ($this->_config->isDifferentialCommissionEnable() && $this->goods->isDifferentialEnable())
|
|
|
|
|| ($this->_config->isManagementAwardEnable() && $this->goods->isManagementEnable());
|
|
|
|
$hasTierCommission = $hasTierCommission && $hasParentOrSelfBuy;
|
|
|
|
|
|
|
|
// 复购已在下单付款时直接减免,分销佣金奖池中不再发放买家本人复购返现
|
|
$hasRepurchaseSelf = false;
|
|
|
|
if (!$hasChainCommission && !$hasTierCommission && !$hasRepurchaseSelf) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->amount = $this->getGoodsCommissionAmount();
|
|
|
|
if ($this->amount <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getGoodsCommissionAmount()
|
|
|
|
{
|
|
|
|
$commissionType = $this->_config->getCommissionPriceType();
|
|
|
|
$amount = round(0, 2);
|
|
|
|
switch ($commissionType) {
|
|
|
|
case 'pay_price':
|
|
|
|
$amount = $this->item['pay_price'];
|
|
|
|
break;
|
|
|
|
case 'goods_price':
|
|
|
|
$amount = round($this->item['goods_price'] * $this->item['goods_num'], 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return $amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addCommissionOrder()
|
|
|
|
{
|
|
|
|
$commissionOrder = OrderModel::where('order_item_id', $this->item['id'])->find();
|
|
|
|
if ($commissionOrder) {
|
|
|
|
return $commissionOrder;
|
|
|
|
}
|
|
|
|
|
|
|
|
$agentId = $this->selfBuy
|
|
|
|
? $this->buyer->user->id
|
|
|
|
: ($this->buyer->getParentAgentId() ?: $this->buyer->user->id);
|
|
|
|
|
|
|
|
$commissionOrderParams = [
|
|
|
|
'self_buy' => intval($this->selfBuy),
|
|
|
|
'order_id' => $this->item['order_id'],
|
|
|
|
'order_item_id' => $this->item['id'],
|
|
|
|
'buyer_id' => $this->buyer->user->id,
|
|
|
|
'goods_id' => $this->item['goods_id'],
|
|
|
|
'agent_id' => $agentId,
|
|
|
|
'amount' => $this->amount,
|
|
|
|
'commission_price_type' => $this->_config->getCommissionPriceType(),
|
|
|
|
'commission_rules' => json_encode([
|
|
|
|
'rules' => $this->goods->getCommissionRules(),
|
|
|
|
'differential_enable' => $this->goods->isDifferentialEnable() ? 1 : 0,
|
|
|
|
'management_enable' => $this->goods->isManagementEnable() ? 1 : 0,
|
|
|
|
'repurchase_enable' => $this->goods->isRepurchaseEnable() ? 1 : 0,
|
|
|
|
]),
|
|
|
|
'commission_event' => $this->_config->getCommissionEvent(),
|
|
|
|
'commission_order_status' => $this->goods->commissionGoods->commission_order_status,
|
|
|
|
];
|
|
|
|
$commissionOrder = OrderModel::create($commissionOrderParams);
|
|
|
|
|
|
|
|
$orderAgent = new Agent($commissionOrder->agent_id);
|
|
|
|
if ($orderAgent->isAgentAvaliable() && $commissionOrder->commission_order_status) {
|
|
|
|
$orderAgent->agent->setInc('order_money', $commissionOrder->amount);
|
|
|
|
$orderAgent->agent->setInc('order_count', 1);
|
|
|
|
Log::write($commissionOrder['agent_id'], 'order', [
|
|
|
|
'action' => 'payed',
|
|
|
|
'order' => $commissionOrder,
|
|
|
|
'order_item' => $this->item,
|
|
|
|
'buyer' => $this->buyer->user
|
|
|
|
], ['oper_type' => 'user', 'oper_id' => $this->buyer->user->id]);
|
|
|
|
$orderAgent->agent->save();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $commissionOrder;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 执行分销计划:关系链、级差、管理奖可同时发放
|
|
|
|
*/
|
|
|
|
public function runCommissionPlan($commissionOrder, $currentAgent = null, $currentCommissionLevel = 1)
|
|
|
|
{
|
|
|
|
$skipReferrer = $this->isRepurchase() && !$this->_config->isRepurchaseReferrerEnable();
|
|
|
|
|
|
|
|
if (!$skipReferrer) {
|
|
|
|
if ($this->_config->isChainCommissionEnable() && $this->goods->getCommissionRules()) {
|
|
|
|
$this->runChainCommissionPlan($commissionOrder, $currentAgent, $currentCommissionLevel);
|
|
|
|
}
|
|
|
|
if ($this->_config->isDifferentialCommissionEnable() && $this->goods->isDifferentialEnable()) {
|
|
|
|
$this->runDifferentialCommissionPlan($commissionOrder);
|
|
|
|
}
|
|
|
|
if ($this->_config->isManagementAwardEnable() && $this->goods->isManagementEnable()) {
|
|
|
|
$this->runManagementAwardPlan($commissionOrder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->runRepurchaseRewards($commissionOrder);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runChainCommissionPlan($commissionOrder, $currentAgent = null, $currentCommissionLevel = 1)
|
|
|
|
{
|
|
|
|
if ($this->commissionLevel < $currentCommissionLevel) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ($currentCommissionLevel === 1) {
|
|
|
|
$currentAgent = new Agent($commissionOrder->agent_id);
|
|
|
|
}
|
|
|
|
if ($currentAgent && !empty($currentAgent->user)) {
|
|
|
|
$commissionReward = RewardModel::get([
|
|
|
|
'commission_order_id' => $commissionOrder->id,
|
|
|
|
'agent_id' => $currentAgent->user->id,
|
|
|
|
'commission_level' => $currentCommissionLevel,
|
|
|
|
]);
|
|
|
|
if (!$commissionReward) {
|
|
|
|
$currentAgentLevel = $currentAgent->getAgentLevel();
|
|
|
|
$currentCommissionLevelRule = $this->goods->getCommissionLevelRule($currentAgentLevel, $currentCommissionLevel);
|
|
|
|
if ($currentCommissionLevelRule) {
|
|
|
|
// repurchase_rate 已废弃:级差模式下无效;一级佣金为 0 时也不应再发关系链推广佣金
|
|
if (
|
|
$currentCommissionLevel === 1
|
|
&& $this->isRepurchase()
|
|
&& $this->_config->isRepurchaseEnable()
|
|
&& !$this->_config->isDifferentialMode()
|
|
) {
|
|
$baseRate = floatval($currentCommissionLevelRule['rate'] ?? 0);
|
|
if ($baseRate > 0) {
|
|
$repurchaseRate = $this->_config->getRepurchaseRate();
|
|
if ($repurchaseRate > 0) {
|
|
$currentCommissionLevelRule = ['rate' => $repurchaseRate];
|
|
}
|
|
}
|
|
}
|
|
|
|
$commission = $this->goods->caculateGoodsCommission($currentCommissionLevelRule, $this->amount, $this->item['goods_num']);
|
|
|
|
if ($commission > 0) {
|
|
|
|
$this->createCommissionReward($commissionOrder, $currentAgent, $currentCommissionLevel, $commission, $currentCommissionLevelRule, $currentAgentLevel, 'chain');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$currentCommissionLevel++;
|
|
|
|
if ($this->commissionLevel < $currentCommissionLevel) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
$parentAgentId = $currentAgent->getParentAgentId();
|
|
|
|
if ($parentAgentId) {
|
|
|
|
$parentAgent = new Agent($parentAgentId);
|
|
|
|
$this->runChainCommissionPlan($commissionOrder, $parentAgent, $currentCommissionLevel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runDifferentialCommissionPlan($commissionOrder)
|
|
|
|
{
|
|
|
|
$chain = $this->getAgentChain($commissionOrder);
|
|
|
|
if (!$chain) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$isSelfBuy = intval($commissionOrder->self_buy) === 1;
|
|
|
|
$buyerId = intval($commissionOrder->buyer_id);
|
|
|
|
$prevTier = 0;
|
|
|
|
|
|
|
|
if ($isSelfBuy) {
|
|
|
|
$buyerAgent = new Agent($buyerId);
|
|
|
|
if ($buyerAgent->isAgentAvaliable()) {
|
|
|
|
$prevTier = $this->getTierAmount($buyerAgent->getAgentLevel());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($chain as $item) {
|
|
|
|
$currentAgent = $item['agent'];
|
|
|
|
$commissionLevel = $item['level'];
|
|
|
|
if ($isSelfBuy && intval($currentAgent->user->id) === $buyerId) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$currentAgentLevel = $currentAgent->getAgentLevel();
|
|
|
|
$tier = $this->getTierAmount($currentAgentLevel);
|
|
|
|
$payout = round(max(0, $tier - $prevTier), 2);
|
|
|
|
$prevTier = max($prevTier, $tier);
|
|
|
|
|
|
|
|
if ($payout > 0) {
|
|
|
|
$rule = [
|
|
|
|
'award_type' => 'differential',
|
|
|
|
'differential_amount' => $tier,
|
|
|
|
'payout' => $payout,
|
|
|
|
];
|
|
|
|
$this->createCommissionReward($commissionOrder, $currentAgent, $commissionLevel, $payout, $rule, $currentAgentLevel, 'differential');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runManagementAwardPlan($commissionOrder)
|
|
|
|
{
|
|
|
|
$chain = $this->getAgentChain($commissionOrder);
|
|
|
|
if (!$chain) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$isSelfBuy = intval($commissionOrder->self_buy) === 1;
|
|
|
|
$buyerId = intval($commissionOrder->buyer_id);
|
|
|
|
|
|
|
|
if ($isSelfBuy) {
|
|
|
|
$buyerInChain = false;
|
|
|
|
foreach ($chain as $item) {
|
|
|
|
if (intval($item['agent']->user->id) === $buyerId) {
|
|
|
|
$buyerInChain = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$buyerInChain) {
|
|
|
|
$buyerAgent = new Agent($buyerId);
|
|
|
|
if ($buyerAgent->isAgentAvaliable()) {
|
|
|
|
array_unshift($chain, ['agent' => $buyerAgent, 'level' => 0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($chain as $item) {
|
|
|
|
$currentAgent = $item['agent'];
|
|
|
|
$commissionLevel = $item['level'] ?: 1;
|
|
|
|
$currentAgentLevel = $currentAgent->getAgentLevel();
|
|
|
|
$rate = $this->getManagementRate($currentAgentLevel);
|
|
|
|
if ($rate <= 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$commission = round($this->amount * $rate * 0.01, 2);
|
|
|
|
if ($commission > 0) {
|
|
|
|
$rule = [
|
|
|
|
'award_type' => 'management',
|
|
|
|
'management_rate' => $rate,
|
|
|
|
];
|
|
|
|
$this->createCommissionReward($commissionOrder, $currentAgent, $commissionLevel, $commission, $rule, $currentAgentLevel, 'management');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getAgentChain($commissionOrder)
|
|
|
|
{
|
|
|
|
$chain = [];
|
|
|
|
$depth = 1;
|
|
|
|
$agent = new Agent($commissionOrder->agent_id);
|
|
|
|
|
|
|
|
while ($agent && $agent->user && $depth <= $this->commissionLevel) {
|
|
|
|
if ($agent->isAgentAvaliable()) {
|
|
|
|
$chain[] = ['agent' => $agent, 'level' => $depth];
|
|
|
|
}
|
|
|
|
$parentId = $agent->getParentAgentId();
|
|
|
|
if (!$parentId) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
$agent = new Agent($parentId);
|
|
|
|
$depth++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $chain;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getTierAmount($agentLevel)
|
|
|
|
{
|
|
|
|
$rules = $this->getAgentLevelRules($agentLevel);
|
|
|
|
return floatval($rules['differential_amount'] ?? 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getManagementRate($agentLevel)
|
|
|
|
{
|
|
|
|
$rules = $this->getAgentLevelRules($agentLevel);
|
|
|
|
return floatval($rules['management_rate'] ?? 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getAgentLevelRules($agentLevel)
|
|
|
|
{
|
|
|
|
if (!isset($this->agentLevelRulesCache[$agentLevel])) {
|
|
|
|
$level = LevelModel::where('level', $agentLevel)->find();
|
|
|
|
$rules = $level ? ($level->commission_rules ?? []) : [];
|
|
|
|
$this->agentLevelRulesCache[$agentLevel] = is_array($rules) ? $rules : [];
|
|
|
|
}
|
|
|
|
return $this->agentLevelRulesCache[$agentLevel];
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runRepurchaseRewards($commissionOrder)
|
|
{
|
|
// 复购优惠已在商品下单付款时直接立减,此处不再发放买家本人复购返现佣金
|
|
return;
|
|
}
|
|
|
|
protected function isRepurchase()
|
|
{
|
|
$goodsId = $this->item['goods_id'] ?? 0;
|
|
$userId = $this->buyer->user->id ?? 0;
|
|
if (!$goodsId || !$userId) {
|
|
return false;
|
|
}
|
|
|
|
$count = \addons\shopro\model\OrderItem::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('o.id', '<', $this->item['order_id'])
|
|
->where('oi.refund_status', '<=', 0)
|
|
->count();
|
|
|
|
return $count > 0;
|
|
}
|
|
|
|
|
|
|
|
protected function createCommissionReward($commissionOrder, $currentAgent, $commissionLevel, $commission, $rule, $agentLevel, $awardType = 'chain')
|
|
|
|
{
|
|
|
|
if (!is_array($rule)) {
|
|
|
|
$rule = [];
|
|
|
|
}
|
|
|
|
$rule['award_type'] = $awardType;
|
|
|
|
|
|
|
|
$exists = RewardModel::where('commission_order_id', $commissionOrder->id)
|
|
|
|
->where('agent_id', $currentAgent->user->id)
|
|
|
|
->where('commission_level', $commissionLevel)
|
|
|
|
->select();
|
|
|
|
foreach ($exists as $item) {
|
|
|
|
$existRules = json_decode($item->commission_rules, true);
|
|
|
|
if (($existRules['award_type'] ?? 'chain') === $awardType) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$commissionReward = RewardModel::create([
|
|
|
|
'order_id' => $commissionOrder->order_id,
|
|
|
|
'order_item_id' => $commissionOrder->order_item_id,
|
|
|
|
'buyer_id' => $commissionOrder->buyer_id,
|
|
|
|
'commission_order_id' => $commissionOrder->id,
|
|
|
|
'agent_id' => $currentAgent->user->id,
|
|
|
|
'type' => 'money',
|
|
|
|
'commission' => $commission,
|
|
|
|
'status' => 0,
|
|
|
|
'original_commission' => $commission,
|
|
|
|
'commission_level' => $commissionLevel,
|
|
|
|
'commission_rules' => json_encode($rule),
|
|
|
|
'agent_level' => $agentLevel,
|
|
|
|
]);
|
|
|
|
Log::write($commissionReward['agent_id'], 'reward', [
|
|
|
|
'action' => 'payed',
|
|
|
|
'reward' => $commissionReward,
|
|
|
|
], ['oper_type' => 'user', 'oper_id' => $commissionOrder->buyer_id]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|