| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <?php
- namespace App\Module\UrsPromotion\Services;
- use App\Module\UrsPromotion\Dtos\UrsProfitDto;
- use App\Module\UrsPromotion\Models\UrsUserMapping;
- use App\Module\UrsPromotion\Models\UrsUserReferral;
- use App\Module\UrsPromotion\Models\UrsUserTalent;
- use App\Module\UrsPromotion\Models\UrsProfit;
- /**
- * URS奖励分发服务
- *
- * 实现奖励发放逻辑:
- * 1. 根据URS用户ID查找上级关系链
- * 2. 检查每个上级是否已进入农场
- * 3. 如果上级未进入农场则跳过,继续处理上上级
- * 4. 记录奖励分发结果
- */
- class UrsRewardDistributionService
- {
- /**
- * 分发推广奖励
- *
- * @param int $ursUserId 产生收益的URS用户ID
- * @param int $sourceId 收益来源ID
- * @param string $sourceType 收益来源类型
- * @param string $profitType 收益类型
- * @param float $originalAmount 原始收益金额
- * @param array $rewardConfig 奖励配置 [level => rate]
- * @return array 分发结果
- */
- public static function distributeReward(
- int $ursUserId,
- int $sourceId,
- string $sourceType,
- string $profitType,
- float $originalAmount,
- array $rewardConfig
- ): array
- {
- $results = [];
- // 获取上级关系链
- $referralChain = self::getReferralChain($ursUserId, count($rewardConfig));
- $level = 1;
- foreach ($referralChain as $referrerUrsUserId) {
- if (!isset($rewardConfig[$level])) {
- break; // 超出配置层级
- }
- $rate = $rewardConfig[$level];
- $profitAmount = $originalAmount * $rate;
- // 检查推荐人是否已进入农场
- $farmUserId = UrsUserMapping::getFarmUserIdByUrsUserId($referrerUrsUserId);
- if ($farmUserId === 0) {
- // 推荐人未进入农场,记录跳过状态
- $results[] = self::recordSkippedReward(
- $referrerUrsUserId,
- $ursUserId,
- $sourceId,
- $sourceType,
- $profitType,
- $level,
- $originalAmount,
- $profitAmount,
- $rate
- );
- } else {
- // 推荐人已进入农场,记录正常奖励
- $results[] = self::recordNormalReward(
- $referrerUrsUserId,
- $farmUserId,
- $ursUserId,
- $sourceId,
- $sourceType,
- $profitType,
- $level,
- $originalAmount,
- $profitAmount,
- $rate
- );
- }
- $level++;
- }
- return $results;
- }
- /**
- * 获取推荐关系链
- *
- * @param int $ursUserId URS用户ID
- * @param int $maxLevels 最大层级数
- * @return array URS用户ID数组,按层级排序
- */
- private static function getReferralChain(int $ursUserId, int $maxLevels): array
- {
- return UrsReferralService::getReferralChain($ursUserId, $maxLevels);
- }
- /**
- * 记录跳过的奖励
- */
- private static function recordSkippedReward(
- $ursUserId,
- int $promotionMemberUrsUserId,
- int $sourceId,
- string $sourceType,
- string $profitType,
- int $relationLevel,
- float $originalAmount,
- float $profitAmount,
- float $profitRate
- ): array
- {
- $framUserId = UrsUserMappingService::getFarmUserId($ursUserId);
- $talent = UrsUserTalent::where('user_id', $framUserId)->first();
- $talentLevel = $talent ? $talent->talent_level : 0;
- $profit = UrsProfit::create([
- 'urs_user_id' => $ursUserId,
- 'urs_promotion_member_id' => $promotionMemberUrsUserId,
- 'source_id' => $sourceId,
- 'source_type' => $sourceType,
- 'profit_type' => $profitType,
- 'relation_level' => $relationLevel,
- 'original_amount' => $originalAmount,
- 'profit_amount' => $profitAmount,
- 'profit_rate' => $profitRate,
- 'talent_level' => $talentLevel,
- 'farm_user_id' => $framUserId,
- 'status' => UrsProfit::STATUS_SKIPPED,
- ]);
- return [
- 'urs_user_id' => $ursUserId,
- 'farm_user_id' => null,
- 'relation_level' => $relationLevel,
- 'profit_amount' => $profitAmount,
- 'status' => 'skipped',
- 'reason' => '用户未进入农场',
- 'profit_id' => $profit->id,
- ];
- }
- /**
- * 记录正常奖励
- */
- private static function recordNormalReward(
- int $ursUserId,
- int $farmUserId,
- int $promotionMemberUrsUserId,
- int $sourceId,
- string $sourceType,
- string $profitType,
- int $relationLevel,
- float $originalAmount,
- float $profitAmount,
- float $profitRate
- ): array
- {
- $framUserId = UrsUserMappingService::getFarmUserId($ursUserId);
- $talent = UrsUserTalent::where('user_id', $framUserId)->first();
- $talentLevel = $talent ? $talent->talent_level : 0;
- $profit = UrsProfit::create([
- 'urs_user_id' => $ursUserId,
- 'urs_promotion_member_id' => $promotionMemberUrsUserId,
- 'source_id' => $sourceId,
- 'source_type' => $sourceType,
- 'profit_type' => $profitType,
- 'relation_level' => $relationLevel,
- 'original_amount' => $originalAmount,
- 'profit_amount' => $profitAmount,
- 'profit_rate' => $profitRate,
- 'talent_level' => $talentLevel,
- 'farm_user_id' => $farmUserId,
- 'status' => UrsProfit::STATUS_NORMAL,
- ]);
- return [
- 'urs_user_id' => $ursUserId,
- 'farm_user_id' => $farmUserId,
- 'relation_level' => $relationLevel,
- 'profit_amount' => $profitAmount,
- 'status' => 'success',
- 'reason' => '奖励发放成功',
- 'profit_id' => $profit->id,
- ];
- }
- /**
- * 获取用户的奖励统计
- *
- * @param int $ursUserId URS用户ID
- * @param string|null $profitType 收益类型筛选
- * @return array
- */
- public static function getUserRewardStats(int $ursUserId, ?string $profitType = null): array
- {
- $query = UrsProfit::where('urs_user_id', $ursUserId);
- if ($profitType) {
- $query->where('profit_type', $profitType);
- }
- $stats = [
- 'total_amount' => $query->sum('profit_amount'),
- 'normal_count' => $query->where('status', UrsProfit::STATUS_NORMAL)->count(),
- 'skipped_count' => $query->where('status', UrsProfit::STATUS_SKIPPED)->count(),
- 'cancelled_count' => $query->where('status', UrsProfit::STATUS_CANCELLED)->count(),
- ];
- return $stats;
- }
- /**
- * 获取跳过的奖励列表
- *
- * @param int $ursUserId URS用户ID
- * @return UrsProfitDto[]
- */
- public static function getSkippedRewards(int $ursUserId): array
- {
- $profits = UrsProfit::where('urs_user_id', $ursUserId)
- ->where('status', UrsProfit::STATUS_SKIPPED)
- ->orderBy('created_at', 'desc')
- ->get();
- return $profits->map(function ($profit) {
- return UrsProfitDto::fromModel($profit);
- })->toArray();
- }
- }
|