jobable)) { case Order::class: $this->runOrderJob($job); break; case OrderRefundLog::class: $this->runOrderRefundJob($job); break; case AfterSale::class: $this->runOrderAfterSaleJob($job); break; } $job->update([ 'status' => DistributionPreIncomeJob::STATUS_SUCCESS, ]); } /** * 处理订单售后的预收益任务 * * @param \App\Models\DistributionPreIncomeJob $job * @return void */ protected function runOrderAfterSaleJob(DistributionPreIncomeJob $job) { // 售后单 $afterSale = $job->jobable; // 如果售后单不是退款或换货,则直接结束任务 if (! in_array($afterSale->type, [ AfterSale::TYPE_REFUND, AfterSale::TYPE_REFUND_AND_RETURN, AfterSale::TYPE_CHANGE, ])) { return; } // 售后商品 $afterSaleProduct = $afterSale->orderProduct; // 如果售后商品是赠品,则直接结束任务 if ($afterSaleProduct->isGift()) { return; } $preIncomes = DistributionPreIncome::where('order_id', $afterSale->order_id)->get(); $time = now(); $preIncomeLogs = []; foreach ($preIncomes as $preIncome) { $rule = $preIncome->rule; if ($preIncome->type === DistributionPreIncome::TYPE_PRICE_DIFF) { // 售后商品的总差价(元) $totalDiffPrice = 0; if (! is_null($afterSaleProduct->vip_price) && $afterSaleProduct->vip_discount_amount === 0) { $diffPrice = $afterSaleProduct->sell_price - $afterSaleProduct->vip_price; if ($diffPrice > 0) { $totalDiffPrice = bcdiv($diffPrice * $afterSaleProduct->quantity, '100'); } } if (bccomp($totalDiffPrice, '0', 2) <= 0) { continue; } $changeAmount = 0; if ($afterSaleProduct->total_amount > 0) { $amount = $afterSale->amount; if ($amount >= $afterSaleProduct->total_amount) { $amount = $afterSaleProduct->total_amount; } $changeAmount = bcdiv(bcmul($totalDiffPrice, $amount), $afterSaleProduct->total_amount); } else { $qty = $afterSale->num; if ($qty > $afterSaleProduct->quantity) { $qty = $afterSaleProduct->quantity; } $changeAmount = bcdiv(bcmul($totalDiffPrice, $qty), $afterSaleProduct->quantity); } // 差价奖励按变更的差价计算 $changeRevenue = bcmul($changeAmount, $rule['bonus_rate']); $changeRevenue = bcmul($changeRevenue, bcsub('1', $rule['fee_rate'])); $changeRevenue = round($changeRevenue, 2); // 变更金额 $changeAmount = round($changeAmount, 2); // 变更成长值 $changeSalesValue = $afterSale->sales_value; $preIncome->update([ 'total_amount' => DB::raw("total_amount-{$changeAmount}"), 'total_revenue' => DB::raw("total_revenue-{$changeRevenue}"), 'total_sales_value' => DB::raw("total_sales_value-{$changeSalesValue}"), ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => bcmul($changeAmount, '-1'), 'change_revenue' => bcmul($changeRevenue, '-1'), 'change_sales_value' => bcmul($changeSalesValue, '-1'), 'remarks' => $afterSale->isChange() ? '订单换货' : '订单退款', 'created_at' => $time, 'updated_at' => $time, ]; } elseif (in_array($preIncome->type, [DistributionPreIncome::TYPE_LEVEL_DIFF, DistributionPreIncome::TYPE_LEVEL_SAME])) { if (bccomp($afterSale->sales_value, '0', 2) <= 0) { continue; } $changeAmount = $afterSale->amount; if ($changeAmount > $afterSaleProduct->total_amount) { $changeAmount = $afterSaleProduct->total_amount; } $changeAmount = bcdiv($changeAmount, '100'); $changeSalesValue = $afterSale->sales_value; // 级差奖励和平级奖励按变更的销售值算收益 $changeRevenue = bcmul($changeSalesValue, $rule['bonus_rate']); $changeRevenue = bcmul($changeRevenue, bcsub('1', $rule['fee_rate'])); $changeRevenue = round($changeRevenue, 2); $preIncome->update([ 'total_amount' => DB::raw("total_amount-{$changeAmount}"), 'total_revenue' => DB::raw("total_revenue-{$changeRevenue}"), 'total_sales_value' => DB::raw("total_sales_value-{$changeSalesValue}"), ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => bcmul($changeAmount, '-1'), 'change_revenue' => bcmul($changeRevenue, '-1'), 'change_sales_value' => bcmul($changeSalesValue, '-1'), 'remarks' => $afterSale->isChange() ? '订单换货' : '订单退款', 'created_at' => $time, 'updated_at' => $time, ]; } } DistributionPreIncomeLog::insert($preIncomeLogs); } /** * 处理取消订单的预收益任务 * * @param \App\Models\DistributionPreIncomeJob $job * @return void */ protected function runOrderRefundJob(DistributionPreIncomeJob $job) { $time = now(); $preIncomeLogs = []; $orderRefundLog = $job->jobable; $preIncomes = DistributionPreIncome::where('order_id', $orderRefundLog->order_id)->get(); foreach ($preIncomes as $preIncome) { $original = $preIncome->replicate(); $preIncome->update([ 'total_amount' => 0, 'total_sales_value' => 0, 'total_revenue' => 0, 'status' => DistributionPreIncome::STATUS_PROCESSED, ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => bcmul($original->total_amount, '-1'), 'change_sales_value' => bcmul($original->total_sales_value, '-1'), 'change_revenue' => bcmul($original->total_revenue, '-1'), 'remarks' => '取消订单', 'created_at' => $time, 'updated_at' => $time, ]; } DistributionPreIncomeLog::insert($preIncomeLogs); } /** * 处理下单预的预收益任务 * * @param \App\Models\DistributionPreIncomeJob $job * @return void */ protected function runOrderJob(DistributionPreIncomeJob $job) { // 订单信息 $order = $job->jobable; // 下单用户信息 $user = $order->user->userInfo; // 总销售值 $totalSalesValue = $order->sales_value; // 总差价 $totalDiffPrice = 0; if ($order->vip_discount_amount === 0) { foreach ($order->products as $product) { // 赠品不算成长值和差价 if ($product->isGift()) { continue; } // 如果订单商品有会员价,并且没有会员折扣时,才计算总差价 if (! is_null($product->vip_price) && $product->vip_discount_amount === 0) { $diffPrice = $product->sell_price - $product->vip_price; if ($diffPrice > 0) { $totalDiffPrice = bcadd($totalDiffPrice, bcmul(bcdiv($diffPrice, '100'), $product->quantity)); } } } } // 分销配置 $config = $this->getConfig(); $preIncomeLogs = []; // 推粉丝赚差价 // 1. 总差价必须大于0 // 2. 下单用户必须有邀请人 // 3. 下单用户的邀请人必须可以享受分红 if ( $totalDiffPrice > 0 && $user->inviter_id && $user->inviterInfo->bonusable ) { // 手续费率 $feeRate = $config['price_diff_fee_rate'] ?? '0'; // 奖励比例 $bonusRate = '1'; // 总收益 $totalRevenue = bcmul($totalDiffPrice, $bonusRate); // 扣除手续费 $totalRevenue = bcmul($totalRevenue, bcsub('1', $feeRate)); $preIncome = $user->inviterInfo->distributionPreIncomes()->create([ 'order_id' => $order->id, 'type' => DistributionPreIncome::TYPE_PRICE_DIFF, 'agent_level' => $user->inviterInfo->agent_level, 'total_amount' => $totalDiffPrice, 'total_sales_value' => $totalSalesValue, 'total_revenue' => round($totalRevenue, 2), 'rule' => [ 'fee_rate' => bcmul($feeRate, '1', 2), 'bonus_rate' => bcmul($bonusRate, '1', 2), ], 'remarks' => "订单号: {$order->sn}", ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => bcdiv($order->total_amount, 100), 'change_sales_value' => $preIncome->total_sales_value, 'change_revenue' => $preIncome->total_revenue, 'remarks' => "订单号: {$order->sn}", 'created_at' => $preIncome->created_at, 'updated_at' => $preIncome->created_at, ]; } // 如果总销售值大于0,需计算各级代理的奖励 if ($totalSalesValue > 0) { // 可获取奖励 $agents = $this->getAgentsByUser($user); $lastAgent = null; // 已分配的级差奖励比例 $assignedLvlDiffBonusRate = 0; foreach ($agents as $agent) { $rule = Arr::get($config, "rules.{$agent->agent_level_key}"); if ($lastAgent && $agent->agent_level === $lastAgent->agent_level) { /* |----------------------------------------------- | 平级奖励 |----------------------------------------------- */ if ($agent->bonusable) { $bonusRate = $rule['lvl_same_bonus_rate'] ?? '0'; if (bccomp($bonusRate, '0') === 1) { // 手续费率 $feeRate = $config['lvl_same_bonus_fee_rate'] ?? '0'; // 总收益 $totalRevenue = bcmul($totalSalesValue, $bonusRate); // 扣除手续费 $totalRevenue = bcmul($totalRevenue, bcsub('1', $feeRate)); $preIncome = $agent->distributionPreIncomes()->create([ 'order_id' => $order->id, 'type' => DistributionPreIncome::TYPE_LEVEL_SAME, 'agent_level' => $agent->agent_level, 'total_amount' => $this->calculateOrderTotalAmount($order), 'total_sales_value' => $totalSalesValue, 'total_revenue' => round($totalRevenue, 2), 'rule' => [ // 手续费率 'fee_rate' => bcmul($feeRate, '1', 2), // 实际奖励比例 'bonus_rate' => bcmul($bonusRate, '1', 2), ], 'remarks' => "订单号: {$order->sn}", ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => $preIncome->total_amount, 'change_sales_value' => $preIncome->total_sales_value, 'change_revenue' => $preIncome->total_revenue, 'remarks' => "订单号: {$order->sn}", 'created_at' => $preIncome->created_at, 'updated_at' => $preIncome->created_at, ]; } } } else { /* |----------------------------------------------- | 级差奖励 |----------------------------------------------- */ $lvlDiffBonusRate = $rule['lvl_diff_bonus_rate'] ?? '0'; if (bccomp($lvlDiffBonusRate, '0') === 1) { // 可得级差奖励比例 = 当前等级的级差奖励 - 已分配的级差奖励比例 $bonusRate = bcsub($lvlDiffBonusRate, $assignedLvlDiffBonusRate); // 如果可得级差奖励比例小于或等于0,则停止分润 if (bccomp($bonusRate, '0') <= 0) { break; } if ($agent->bonusable) { // 手续费率 $feeRate = $config['lvl_diff_bonus_fee_rate'] ?? '0'; // 总收益 $totalRevenue = bcmul($totalSalesValue, $bonusRate); // 扣除手续费 $totalRevenue = bcmul($totalRevenue, bcsub('1', $feeRate)); $preIncome = $agent->distributionPreIncomes()->create([ 'order_id' => $order->id, 'type' => DistributionPreIncome::TYPE_LEVEL_DIFF, 'agent_level' => $agent->agent_level, 'total_amount' => $this->calculateOrderTotalAmount($order), 'total_sales_value' => $totalSalesValue, 'total_revenue' => round($totalRevenue, 2), 'rule' => [ // 手续费率 'fee_rate' => bcmul($feeRate, '1', 2), // 实际奖励比例 'bonus_rate' => bcmul($bonusRate, '1', 2), // 级差奖励比例 'lvl_diff_bonus_rate' => bcmul($lvlDiffBonusRate, '1', 2), ], 'remarks' => "订单号: {$order->sn}", ]); $preIncomeLogs[] = [ 'pre_income_id' => $preIncome->id, 'pre_income_job_id' => $job->id, 'change_amount' => $preIncome->total_amount, 'change_sales_value' => $preIncome->total_sales_value, 'change_revenue' => $preIncome->total_revenue, 'remarks' => "订单号: {$order->sn}", 'created_at' => $preIncome->created_at, 'updated_at' => $preIncome->created_at, ]; } $assignedLvlDiffBonusRate = $lvlDiffBonusRate; } } $lastAgent = $agent; } $user->incrPreGrowthValue($totalSalesValue, false); } DistributionPreIncomeLog::insert($preIncomeLogs); } /** * 根据下单用户,获取参与结算的所有代理 * * @param \App\Models\UserInfo $user * @return array */ protected function getAgentsByUser(UserInfo $user): array { // 可参与分销的所有代理 // 代理的等级必须从低到过,且同一等级连续出现次数不超过2次 $agents = [ $user, ]; // 如果下单用户没有上级,则只有下单用户参与奖励计算 if (empty($pids = $user->parent_ids)) { return $agents; } // 下单用户的所有上级 $ancestors = UserInfo::whereIn('user_id', $pids)->latest('depth')->get(); // 最后加入分销链的代理 $last = $user; // 最后加入分销链的代理的前一个代理 $previous = null; foreach ($ancestors as $ancestor) { if ($previous && $previous->agent_level_rank >= $ancestor->agent_level_rank) { continue; } if ($ancestor->agent_level_rank >= $last->agent_level_rank) { $previous = $last; $last = $ancestor; $agents[] = $last; } } return $agents; } /** * 订单总金额 * * @param \App\Models\Order $order * @return float */ protected function calculateOrderTotalAmount(Order $order) { $totalAmount = bcadd($order->products_total_amount, $order->shipping_fee); $totalAmount = bcsub($totalAmount, $order->coupon_discount_amount); $totalAmount = bcsub($totalAmount, $order->vip_discount_amount); $totalAmount = bcsub($totalAmount, $order->reduced_amount); return round(bcdiv($totalAmount, 100), 2); } /** * 分销配置 * * @return array */ protected function getConfig(): array { return app_settings('distribution'); } }