referralLogic = $referralLogic; $this->talentLogic = $talentLogic; } /** * 计算并记录团队收益分成 * * @param int $userId 产生收益的用户ID * @param string $sourceType 收益来源类型 * @param int $sourceId 收益来源ID * @param int $itemId 物品ID * @param int $amount 收益数量 * @return bool */ public function calculateAndRecordProfit(int $userId, string $sourceType, int $sourceId, int $itemId, int $amount): bool { try { // 获取收益分成规则 $rule = $this->getProfitRule($sourceType); if (!$rule || !$rule->isActive()) { Log::info("收益分成规则不存在或未激活: {$sourceType}"); return false; } // 检查收益是否满足最小数量要求 $minAmount = $rule->getRuleAttribute('min_amount', 0); if ($amount < $minAmount) { Log::info("收益数量不满足最小要求: {$amount} < {$minAmount}"); return false; } // 检查收益是否超过最大数量限制 $maxAmount = $rule->getRuleAttribute('max_amount', PHP_INT_MAX); if ($amount > $maxAmount) { $amount = $maxAmount; Log::info("收益数量超过最大限制,已调整为: {$maxAmount}"); } // 检查物品是否在排除列表中 $excludedItems = $rule->getRuleAttribute('excluded_items', []); if (in_array($itemId, $excludedItems)) { Log::info("物品在排除列表中: {$itemId}"); return false; } // 获取用户的所有上级 $referrers = $this->referralLogic->getAllReferrers($userId, $rule->max_indirect_level); if (empty($referrers)) { Log::info("用户没有上级: {$userId}"); return true; } // 检查事务是否已开启 \UCore\Db\Helper::check_tr(); // 记录收益分成 $success = true; foreach ($referrers as $referrer) { $referrerId = $referrer['user_id']; $level = $referrer['level']; $depth = $referrer['depth']; // 计算分成比例 $profitRate = $this->calculateProfitRate($level, $depth, $rule); // 计算分成数量 $profitAmount = (int)($amount * $profitRate); if ($profitAmount <= 0) { continue; } // 记录收益 $profit = new PromotionProfit(); $profit->user_id = $referrerId; $profit->promotion_member_id = $userId; $profit->source_id = $sourceId; $profit->source_type = $sourceType; $profit->item_id = $itemId; $profit->profit_amount = $profitAmount; $profit->profit_rate = $profitRate; $profit->relation_type = $level; if (!$profit->save()) { $success = false; Log::error("记录收益分成失败: 用户 {$referrerId}, 来源 {$sourceType}, 数量 {$profitAmount}"); } } return $success; } catch (\Exception $e) { Log::error("计算并记录团队收益分成失败: " . $e->getMessage()); return false; } } /** * 计算分成比例 * * @param int $level 关系层级 * @param int $depth 层级深度 * @param PromotionProfitRule $rule 分成规则 * @return float */ private function calculateProfitRate(int $level, int $depth, PromotionProfitRule $rule): float { // 直推关系 if ($level == REFERRAL_LEVEL::DIRECT) { return $rule->direct_profit_rate; } // 间推关系 if ($level == REFERRAL_LEVEL::INDIRECT) { // 获取用户的达人等级 $talent = $this->talentLogic->getUserTalent($depth); if (!$talent || $talent->talent_level == 0) { return 0.0; } // 获取达人等级对应的分成比例 $profitRate = $this->talentLogic->getTalentProfitRate($talent->talent_level); // 应用特殊规则 $specialRates = $rule->getRuleAttribute('special_rates', []); foreach ($specialRates as $specialRate) { if (isset($specialRate['talent_level']) && $specialRate['talent_level'] == $talent->talent_level) { if (isset($specialRate['bonus_rate'])) { $profitRate += $specialRate['bonus_rate']; } } } return $profitRate; } return 0.0; } /** * 获取收益分成规则 * * @param string $sourceType 收益来源类型 * @return PromotionProfitRule|null */ public function getProfitRule(string $sourceType): ?PromotionProfitRule { return PromotionProfitRule::where('source_type', $sourceType) ->where('status', 1) ->first(); } /** * 获取用户的团队收益记录 * * @param int $userId 用户ID * @param string|null $sourceType 收益来源类型 * @param int $page 页码 * @param int $pageSize 每页数量 * @return array */ public function getUserProfits(int $userId, ?string $sourceType = null, int $page = 1, int $pageSize = 20): array { $query = PromotionProfit::where('user_id', $userId); if ($sourceType) { $query->where('source_type', $sourceType); } $total = $query->count(); $profits = $query->orderBy('created_at', 'desc') ->offset(($page - 1) * $pageSize) ->limit($pageSize) ->with(['promotionMember', 'item']) ->get(); return [ 'total' => $total, 'page' => $page, 'page_size' => $pageSize, 'total_pages' => ceil($total / $pageSize), 'profits' => $profits ]; } /** * 统计用户的团队收益 * * @param int $userId 用户ID * @param string|null $sourceType 收益来源类型 * @param int|null $itemId 物品ID * @return array */ public function sumUserProfits(int $userId, ?string $sourceType = null, ?int $itemId = null): array { $query = PromotionProfit::where('user_id', $userId); if ($sourceType) { $query->where('source_type', $sourceType); } if ($itemId) { $query->where('item_id', $itemId); } $directSum = (clone $query)->where('relation_type', REFERRAL_LEVEL::DIRECT)->sum('profit_amount'); $indirectSum = (clone $query)->where('relation_type', REFERRAL_LEVEL::INDIRECT)->sum('profit_amount'); $totalSum = $directSum + $indirectSum; return [ 'direct_profit' => $directSum, 'indirect_profit' => $indirectSum, 'total_profit' => $totalSum ]; } }