Kaynağa Gözat

修正URS推广模块业务逻辑

重要修正:
- 推广收益改为按人头奖励,使用奖励组配置固定金额
- 种植收益保持按比例分成
- 数据库添加reward_group_id字段支持奖励组
- 修改promotion_reward_rates为promotion_reward_groups
- 更新业务逻辑:UrsProfitLogic分离推广收益和种植收益处理
- 更新服务层和API接口,推广收益不再需要original_amount参数
- 测试验证:推广收益50金币固定奖励,种植收益0.5%比例分成

感谢指正业务逻辑错误!
notfff 7 ay önce
ebeveyn
işleme
43d3d7e974

+ 1 - 5
app/Module/UrsPromotion/Controllers/UrsPromotionApiController.php

@@ -167,7 +167,6 @@ class UrsPromotionApiController
             'user_id' => 'required|integer|min:1',
             'source_type' => 'required|string|max:32',
             'source_id' => 'required|integer|min:1',
-            'original_amount' => 'required|numeric|min:0',
         ]);
 
         if ($validator->fails()) {
@@ -182,13 +181,10 @@ class UrsPromotionApiController
             $userId = $request->input('user_id');
             $sourceType = $request->input('source_type');
             $sourceId = $request->input('source_id');
-            $originalAmount = $request->input('original_amount');
-            
             $profits = UrsProfitService::distributePromotionReward(
                 $userId,
                 $sourceType,
-                $sourceId,
-                (string)$originalAmount
+                $sourceId
             );
             
             return response()->json([

+ 13 - 9
app/Module/UrsPromotion/Docs/数据库设计.md

@@ -14,8 +14,8 @@ URS推广模块包含以下核心数据表:
 
 **v2.0.0 (三代推广版本) 主要变更:**
 - 支持三代推广关系(直推、间推、三推)
-- 新增两种收益类型:推广收益和种植收益
-- 达人等级配置支持不同收益类型的分成比例
+- 新增两种收益类型:推广收益(按人头奖励)和种植收益(按比例分成)
+- 推广收益使用奖励组配置固定金额,种植收益使用比例配置
 - 优化数据库表结构,提升查询性能
 
 ## 2. 表结构详细设计
@@ -79,9 +79,10 @@ URS推广模块包含以下核心数据表:
 | source_type | varchar | 32 | - | 收益来源类型 |
 | profit_type | varchar | 32 | - | 收益类型:promotion_reward推广收益,planting_reward种植收益 |
 | relation_level | tinyint | - | 1 | 推荐层级:1直推,2间推,3三推 |
-| original_amount | decimal | 30,10 | 0.0000000000 | 原始收益金额 |
-| profit_amount | decimal | 30,10 | 0.0000000000 | 分成收益金额 |
-| profit_rate | decimal | 8,6 | 0.000000 | 分成比例 |
+| original_amount | decimal | 30,10 | 0.0000000000 | 原始收益金额(种植收益时使用) |
+| profit_amount | decimal | 30,10 | 0.0000000000 | 获得收益金额 |
+| profit_rate | decimal | 8,6 | 0.000000 | 分成比例(种植收益时使用) |
+| reward_group_id | int | - | NULL | 奖励组ID(推广收益时使用) |
 | talent_level | tinyint | - | 0 | 获得收益时的达人等级 |
 | status | tinyint | - | 1 | 状态:1正常,0取消 |
 | created_at | timestamp | - | CURRENT_TIMESTAMP | 创建时间 |
@@ -132,7 +133,7 @@ URS推广模块包含以下核心数据表:
 | name | varchar | 32 | - | 等级名称 |
 | direct_count_required | int | - | 0 | 所需直推人数 |
 | promotion_count_required | int | - | 0 | 所需团队总人数 |
-| promotion_reward_rates | json | - | NULL | 推广收益分成比例配置 |
+| promotion_reward_groups | json | - | NULL | 推广收益奖励组配置 |
 | planting_reward_rates | json | - | NULL | 种植收益分成比例配置 |
 | icon | varchar | 255 | NULL | 等级图标 |
 | description | text | - | NULL | 等级描述 |
@@ -147,10 +148,13 @@ URS推广模块包含以下核心数据表:
 - KEY `idx_sort_order` (`sort_order`)
 - KEY `idx_status` (`status`)
 
-**分成比例配置说明:**
-- `promotion_reward_rates`: 推广收益分成比例,JSON格式:`{"1": 0.05, "2": 0.03, "3": 0.01}`
+**收益配置说明:**
+- `promotion_reward_groups`: 推广收益奖励组配置,JSON格式:`{"1": 1001, "2": 1002, "3": 1003}`
+  - 键值对应推荐层级:1=直推,2=间推,3=三推
+  - 值为奖励组ID,用于配置固定金额奖励
 - `planting_reward_rates`: 种植收益分成比例,JSON格式:`{"1": 0.05, "2": 0.03, "3": 0.01}`
-- 键值对应推荐层级:1=直推,2=间推,3=三推
+  - 键值对应推荐层级:1=直推,2=间推,3=三推
+  - 值为分成比例,用于按比例分成
 
 ## 3. 索引设计说明
 

+ 212 - 42
app/Module/UrsPromotion/Logics/UrsProfitLogic.php

@@ -19,20 +19,79 @@ use Illuminate\Support\Facades\Log;
 class UrsProfitLogic
 {
     /**
-     * 计算并分发URS推广收益
-     * 
+     * 计算并分发URS推广收益(按人头奖励)
+     *
+     * @param int $userId 新注册用户ID
+     * @param string $sourceType 收益来源类型
+     * @param int $sourceId 收益来源ID
+     * @return array 分成记录
+     */
+    public function distributePromotionReward(
+        int $userId,
+        string $sourceType,
+        int $sourceId
+    ): array {
+        $profits = [];
+
+        try {
+            // 获取用户的推荐关系链(三代)
+            $referralChain = $this->getUserReferralChain($userId);
+
+            if (empty($referralChain)) {
+                Log::info("用户 {$userId} 无推荐关系,无需分成");
+                return $profits;
+            }
+
+            // 获取达人等级配置
+            $talentConfigs = $this->getTalentConfigs();
+
+            // 为每一级推荐人发放奖励
+            foreach ($referralChain as $level => $referrerId) {
+                $profit = $this->calculatePromotionReward(
+                    $referrerId,
+                    $userId,
+                    $sourceType,
+                    $sourceId,
+                    $level,
+                    $talentConfigs
+                );
+
+                if ($profit) {
+                    $profits[] = $profit;
+                }
+            }
+
+            Log::info("用户 {$userId} 推广收益分发完成", [
+                'source_type' => $sourceType,
+                'source_id' => $sourceId,
+                'profits_count' => count($profits)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error("URS推广收益分发失败", [
+                'user_id' => $userId,
+                'source_type' => $sourceType,
+                'source_id' => $sourceId,
+                'error' => $e->getMessage()
+            ]);
+        }
+
+        return $profits;
+    }
+
+    /**
+     * 计算并分发URS种植收益(按比例分成)
+     *
      * @param int $userId 产生收益的用户ID
      * @param string $sourceType 收益来源类型
      * @param int $sourceId 收益来源ID
-     * @param UrsProfitType $profitType 收益类型
      * @param string $originalAmount 原始收益金额
      * @return array 分成记录
      */
-    public function distributeProfit(
-        int $userId, 
-        string $sourceType, 
-        int $sourceId, 
-        UrsProfitType $profitType, 
+    public function distributePlantingReward(
+        int $userId,
+        string $sourceType,
+        int $sourceId,
         string $originalAmount
     ): array {
         $profits = [];
@@ -51,36 +110,33 @@ class UrsProfitLogic
             
             // 为每一级推荐人计算分成
             foreach ($referralChain as $level => $referrerId) {
-                $profit = $this->calculateLevelProfit(
+                $profit = $this->calculatePlantingReward(
                     $referrerId,
                     $userId,
                     $sourceType,
                     $sourceId,
-                    $profitType,
                     $level,
                     $originalAmount,
                     $talentConfigs
                 );
-                
+
                 if ($profit) {
                     $profits[] = $profit;
                 }
             }
-            
-            Log::info("用户 {$userId} 收益分成完成", [
+
+            Log::info("用户 {$userId} 种植收益分成完成", [
                 'source_type' => $sourceType,
                 'source_id' => $sourceId,
-                'profit_type' => $profitType->value,
                 'original_amount' => $originalAmount,
                 'profits_count' => count($profits)
             ]);
-            
+
         } catch (\Exception $e) {
-            Log::error("URS收益分成失败", [
+            Log::error("URS种植收益分成失败", [
                 'user_id' => $userId,
                 'source_type' => $sourceType,
                 'source_id' => $sourceId,
-                'profit_type' => $profitType->value,
                 'error' => $e->getMessage()
             ]);
         }
@@ -136,24 +192,92 @@ class UrsProfitLogic
     }
     
     /**
-     * 计算单级推荐人的分成收益
-     * 
+     * 计算推广收益奖励(按人头)
+     *
+     * @param int $referrerId 推荐人ID
+     * @param int $memberId 新注册用户ID
+     * @param string $sourceType 收益来源类型
+     * @param int $sourceId 收益来源ID
+     * @param int $relationLevel 推荐层级
+     * @param array $talentConfigs 达人等级配置
+     * @return UrsProfit|null
+     */
+    private function calculatePromotionReward(
+        int $referrerId,
+        int $memberId,
+        string $sourceType,
+        int $sourceId,
+        int $relationLevel,
+        array $talentConfigs
+    ): ?UrsProfit {
+        // 获取推荐人的达人等级
+        $talent = UrsUserTalent::where('user_id', $referrerId)->first();
+        $talentLevel = $talent ? $talent->talent_level : 0;
+
+        // 获取对应等级的配置
+        $config = $talentConfigs[$talentLevel] ?? null;
+        if (!$config) {
+            Log::warning("推荐人 {$referrerId} 达人等级 {$talentLevel} 配置不存在");
+            return null;
+        }
+
+        // 获取奖励组ID
+        $rewardGroupId = $this->getPromotionRewardGroupId($config, $relationLevel);
+        if (!$rewardGroupId) {
+            Log::debug("推荐人 {$referrerId} 等级 {$talentLevel} 层级 {$relationLevel} 无奖励组配置");
+            return null;
+        }
+
+        // TODO: 这里需要根据奖励组ID获取具体的奖励金额
+        // 暂时使用固定金额作为示例
+        $rewardAmount = $this->getRewardAmountByGroupId($rewardGroupId);
+
+        // 创建收益记录
+        $profit = UrsProfit::create([
+            'user_id' => $referrerId,
+            'promotion_member_id' => $memberId,
+            'source_id' => $sourceId,
+            'source_type' => $sourceType,
+            'profit_type' => UrsProfitType::PROMOTION_REWARD->value,
+            'relation_level' => $relationLevel,
+            'original_amount' => '0', // 推广收益无原始金额概念
+            'profit_amount' => $rewardAmount,
+            'profit_rate' => 0, // 推广收益无比例概念
+            'reward_group_id' => $rewardGroupId,
+            'talent_level' => $talentLevel,
+            'status' => UrsProfit::STATUS_NORMAL,
+        ]);
+
+        Log::info("URS推广收益记录创建", [
+            'profit_id' => $profit->id,
+            'referrer_id' => $referrerId,
+            'member_id' => $memberId,
+            'relation_level' => $relationLevel,
+            'talent_level' => $talentLevel,
+            'reward_group_id' => $rewardGroupId,
+            'reward_amount' => $rewardAmount
+        ]);
+
+        return $profit;
+    }
+
+    /**
+     * 计算种植收益分成(按比例)
+     *
      * @param int $referrerId 推荐人ID
      * @param int $memberId 团队成员ID
      * @param string $sourceType 收益来源类型
      * @param int $sourceId 收益来源ID
-     * @param UrsProfitType $profitType 收益类型
      * @param int $relationLevel 推荐层级
      * @param string $originalAmount 原始收益金额
      * @param array $talentConfigs 达人等级配置
      * @return UrsProfit|null
      */
-    private function calculateLevelProfit(
+    private function calculatePlantingReward(
         int $referrerId,
         int $memberId,
         string $sourceType,
         int $sourceId,
-        UrsProfitType $profitType,
         int $relationLevel,
         string $originalAmount,
         array $talentConfigs
@@ -161,40 +285,41 @@ class UrsProfitLogic
         // 获取推荐人的达人等级
         $talent = UrsUserTalent::where('user_id', $referrerId)->first();
         $talentLevel = $talent ? $talent->talent_level : 0;
-        
+
         // 获取对应等级的配置
         $config = $talentConfigs[$talentLevel] ?? null;
         if (!$config) {
             Log::warning("推荐人 {$referrerId} 达人等级 {$talentLevel} 配置不存在");
             return null;
         }
-        
+
         // 获取分成比例
-        $profitRate = $this->getProfitRate($config, $profitType, $relationLevel);
+        $profitRate = $this->getPlantingRewardRate($config, $relationLevel);
         if ($profitRate <= 0) {
             Log::debug("推荐人 {$referrerId} 等级 {$talentLevel} 层级 {$relationLevel} 分成比例为0");
             return null;
         }
-        
+
         // 计算分成金额
         $profitAmount = bcmul($originalAmount, (string)$profitRate, 10);
-        
+
         // 创建收益记录
         $profit = UrsProfit::create([
             'user_id' => $referrerId,
             'promotion_member_id' => $memberId,
             'source_id' => $sourceId,
             'source_type' => $sourceType,
-            'profit_type' => $profitType->value,
+            'profit_type' => UrsProfitType::PLANTING_REWARD->value,
             'relation_level' => $relationLevel,
             'original_amount' => $originalAmount,
             'profit_amount' => $profitAmount,
             'profit_rate' => $profitRate,
+            'reward_group_id' => null, // 种植收益不使用奖励组
             'talent_level' => $talentLevel,
             'status' => UrsProfit::STATUS_NORMAL,
         ]);
-        
-        Log::info("URS收益分成记录创建", [
+
+        Log::info("URS种植收益记录创建", [
             'profit_id' => $profit->id,
             'referrer_id' => $referrerId,
             'member_id' => $memberId,
@@ -203,32 +328,77 @@ class UrsProfitLogic
             'profit_rate' => $profitRate,
             'profit_amount' => $profitAmount
         ]);
-        
+
         return $profit;
     }
+
+
     
     /**
-     * 获取分成比例
-     * 
+     * 获取推广收益奖励组ID
+     *
+     * @param array $config 达人等级配置
+     * @param int $relationLevel 推荐层级
+     * @return int|null
+     */
+    private function getPromotionRewardGroupId(array $config, int $relationLevel): ?int
+    {
+        $groups = $config['promotion_reward_groups'] ?? [];
+        if (is_string($groups)) {
+            $groups = json_decode($groups, true) ?? [];
+        }
+
+        return $groups[$relationLevel] ?? null;
+    }
+
+    /**
+     * 获取种植收益分成比例
+     *
      * @param array $config 达人等级配置
-     * @param UrsProfitType $profitType 收益类型
      * @param int $relationLevel 推荐层级
      * @return float
      */
-    private function getProfitRate(array $config, UrsProfitType $profitType, int $relationLevel): float
+    private function getPlantingRewardRate(array $config, int $relationLevel): float
     {
-        $ratesField = match($profitType) {
-            UrsProfitType::PROMOTION_REWARD => 'promotion_reward_rates',
-            UrsProfitType::PLANTING_REWARD => 'planting_reward_rates',
-        };
-        
-        $rates = $config[$ratesField] ?? [];
+        $rates = $config['planting_reward_rates'] ?? [];
         if (is_string($rates)) {
             $rates = json_decode($rates, true) ?? [];
         }
-        
+
         return (float)($rates[$relationLevel] ?? 0);
     }
+
+    /**
+     * 根据奖励组ID获取奖励金额
+     *
+     * TODO: 这里需要集成奖励组系统,暂时使用固定金额
+     *
+     * @param int $rewardGroupId 奖励组ID
+     * @return string
+     */
+    private function getRewardAmountByGroupId(int $rewardGroupId): string
+    {
+        // 暂时使用固定金额映射,实际应该从奖励组系统获取
+        $rewardAmounts = [
+            1001 => '50.0000000000',   // 初级达人直推奖励
+            1002 => '30.0000000000',   // 初级达人间推奖励
+            1003 => '10.0000000000',   // 初级达人三推奖励
+            1004 => '80.0000000000',   // 中级达人直推奖励
+            1005 => '50.0000000000',   // 中级达人间推奖励
+            1006 => '20.0000000000',   // 中级达人三推奖励
+            1007 => '120.0000000000',  // 高级达人直推奖励
+            1008 => '80.0000000000',   // 高级达人间推奖励
+            1009 => '40.0000000000',   // 高级达人三推奖励
+            1010 => '200.0000000000',  // 资深达人直推奖励
+            1011 => '120.0000000000',  // 资深达人间推奖励
+            1012 => '60.0000000000',   // 资深达人三推奖励
+            1013 => '300.0000000000',  // 顶级达人直推奖励
+            1014 => '200.0000000000',  // 顶级达人间推奖励
+            1015 => '100.0000000000',  // 顶级达人三推奖励
+        ];
+
+        return $rewardAmounts[$rewardGroupId] ?? '0.0000000000';
+    }
     
     /**
      * 获取用户的收益统计

+ 2 - 0
app/Module/UrsPromotion/Models/UrsProfit.php

@@ -51,6 +51,7 @@ class UrsProfit extends ModelCore
         'original_amount',
         'profit_amount',
         'profit_rate',
+        'reward_group_id',
         'talent_level',
         'status',
     ];
@@ -67,6 +68,7 @@ class UrsProfit extends ModelCore
         'original_amount' => 'decimal:10',
         'profit_amount' => 'decimal:10',
         'profit_rate' => 'decimal:6',
+        'reward_group_id' => 'integer',
         'talent_level' => 'integer',
         'status' => 'integer',
         'created_at' => 'datetime',

+ 16 - 13
app/Module/UrsPromotion/Models/UrsTalentConfig.php

@@ -38,7 +38,7 @@ class UrsTalentConfig extends ModelCore
         'name',
         'direct_count_required',
         'promotion_count_required',
-        'promotion_reward_rates',
+        'promotion_reward_groups',
         'planting_reward_rates',
         'icon',
         'description',
@@ -54,7 +54,7 @@ class UrsTalentConfig extends ModelCore
         'level' => 'integer',
         'direct_count_required' => 'integer',
         'promotion_count_required' => 'integer',
-        'promotion_reward_rates' => 'array',
+        'promotion_reward_groups' => 'array',
         'planting_reward_rates' => 'array',
         'sort_order' => 'integer',
         'status' => 'integer',
@@ -85,15 +85,18 @@ class UrsTalentConfig extends ModelCore
     }
 
     /**
-     * 获取推广收益分成比例
-     * 
+     * 获取推广收益奖励组ID
+     *
      * @param int $relationLevel 推荐层级 1:直推 2:间推 3:三推
-     * @return float
+     * @return int|null
      */
-    public function getPromotionRewardRate(int $relationLevel): float
+    public function getPromotionRewardGroupId(int $relationLevel): ?int
     {
-        $rates = $this->promotion_reward_rates ?? [];
-        return (float)($rates[$relationLevel] ?? 0);
+        $groups = $this->promotion_reward_groups ?? [];
+        if (is_string($groups)) {
+            $groups = json_decode($groups, true) ?? [];
+        }
+        return $groups[$relationLevel] ?? null;
     }
 
     /**
@@ -109,13 +112,13 @@ class UrsTalentConfig extends ModelCore
     }
 
     /**
-     * 设置推广收益分成比例
-     * 
-     * @param array $rates 分成比例配置 [1 => 0.05, 2 => 0.03, 3 => 0.01]
+     * 设置推广收益奖励组配置
+     *
+     * @param array $groups 奖励组配置 [1 => 1001, 2 => 1002, 3 => 1003]
      */
-    public function setPromotionRewardRates(array $rates): void
+    public function setPromotionRewardGroups(array $groups): void
     {
-        $this->promotion_reward_rates = $rates;
+        $this->promotion_reward_groups = $groups;
     }
 
     /**

+ 11 - 16
app/Module/UrsPromotion/Services/UrsProfitService.php

@@ -14,29 +14,25 @@ class UrsProfitService
 {
     /**
      * 分发推广收益
-     * 
-     * 当下级用户进入农场时调用此方法分发推广收益
-     * 
-     * @param int $userId 产生收益的用户ID
+     *
+     * 当新用户注册时调用此方法分发推广收益(按人头奖励)
+     *
+     * @param int $userId 新注册用户ID
      * @param string $sourceType 收益来源类型
      * @param int $sourceId 收益来源ID
-     * @param string $originalAmount 原始收益金额
      * @return array 分成记录
      */
     public static function distributePromotionReward(
-        int $userId, 
-        string $sourceType, 
-        int $sourceId, 
-        string $originalAmount
+        int $userId,
+        string $sourceType,
+        int $sourceId
     ): array {
         $logic = new UrsProfitLogic();
-        
-        return $logic->distributeProfit(
+
+        return $logic->distributePromotionReward(
             $userId,
             $sourceType,
-            $sourceId,
-            UrsProfitType::PROMOTION_REWARD,
-            $originalAmount
+            $sourceId
         );
     }
     
@@ -59,11 +55,10 @@ class UrsProfitService
     ): array {
         $logic = new UrsProfitLogic();
         
-        return $logic->distributeProfit(
+        return $logic->distributePlantingReward(
             $userId,
             $sourceType,
             $sourceId,
-            UrsProfitType::PLANTING_REWARD,
             $originalAmount
         );
     }