UrsBackfillRewardLogic.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <?php
  2. namespace App\Module\UrsPromotion\Logics;
  3. use App\Module\UrsPromotion\Enums\UrsProfitType;
  4. use App\Module\UrsPromotion\Models\UrsProfit;
  5. use App\Module\UrsPromotion\Services\UrsReferralService;
  6. use App\Module\UrsPromotion\Services\UrsTalentService;
  7. use App\Module\UrsPromotion\Models\UrsTalentConfig;
  8. use App\Module\Game\Services\RewardService;
  9. use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
  10. use Illuminate\Support\Facades\Log;
  11. use Illuminate\Support\Facades\DB;
  12. /**
  13. * URS推荐奖励补发逻辑层
  14. *
  15. * 处理用户首次进入农场时的推荐奖励补发核心逻辑
  16. */
  17. class UrsBackfillRewardLogic
  18. {
  19. /**
  20. * 为用户补发推荐奖励
  21. *
  22. * @param int $ursUserId URS用户ID
  23. * @param int $farmUserId 农场用户ID
  24. * @return array 补发结果
  25. */
  26. public function backfillPromotionReward(int $ursUserId, int $farmUserId): array
  27. {
  28. // 1. 检查用户是否需要补发奖励
  29. if (!$this->needsBackfillReward($ursUserId)) {
  30. return [
  31. 'success' => false,
  32. 'message' => '用户无下级或不需要补发奖励',
  33. 'backfilled_count' => 0,
  34. 'total_subordinates' => 0,
  35. 'talent_level' => 0,
  36. 'reward_group_id' => 0
  37. ];
  38. }
  39. // 2. 获取用户下级统计
  40. $subordinateStats = $this->getSubordinateStats($ursUserId);
  41. $totalSubordinates = $subordinateStats['total_count'];
  42. if ($totalSubordinates <= 0) {
  43. return [
  44. 'success' => false,
  45. 'message' => '用户无下级,无需补发奖励',
  46. 'backfilled_count' => 0,
  47. 'total_subordinates' => 0,
  48. 'talent_level' => 0,
  49. 'reward_group_id' => 0
  50. ];
  51. }
  52. // 3. 获取用户当前达人等级
  53. $talentLevel = $this->getUserTalentLevel($ursUserId);
  54. // 4. 获取对应等级的推荐奖励组配置
  55. $rewardGroups = $this->getPromotionRewardGroups($talentLevel);
  56. if (empty($rewardGroups)) {
  57. return [
  58. 'success' => false,
  59. 'message' => "达人等级 {$talentLevel} 无对应的奖励组配置",
  60. 'backfilled_count' => 0,
  61. 'total_subordinates' => $totalSubordinates,
  62. 'talent_level' => $talentLevel,
  63. 'reward_details' => []
  64. ];
  65. }
  66. // 5. 按推荐层级分别发放奖励
  67. try {
  68. DB::beginTransaction();
  69. $rewardDetails = [];
  70. $totalBackfilledCount = 0;
  71. // 直推奖励
  72. if ($subordinateStats['direct_count'] > 0 && $rewardGroups['direct'] > 0) {
  73. $directResult = RewardService::grantReward(
  74. $farmUserId,
  75. $rewardGroups['direct'],
  76. REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL,
  77. $ursUserId,
  78. $subordinateStats['direct_count']
  79. );
  80. if (!$directResult->success) {
  81. DB::rollBack();
  82. return [
  83. 'success' => false,
  84. 'message' => "直推奖励发放失败: {$directResult->errorMessage}",
  85. 'backfilled_count' => 0,
  86. 'total_subordinates' => $totalSubordinates,
  87. 'talent_level' => $talentLevel,
  88. 'reward_details' => []
  89. ];
  90. }
  91. $rewardDetails['direct'] = [
  92. 'type' => '直推奖励',
  93. 'count' => $subordinateStats['direct_count'],
  94. 'reward_group_id' => $rewardGroups['direct'],
  95. 'items_count' => count($directResult->items)
  96. ];
  97. $totalBackfilledCount += count($directResult->items);
  98. // 创建收益记录
  99. $profit = UrsProfit::create([
  100. 'urs_user_id' => $ursUserId,
  101. 'urs_promotion_member_id' => 0,
  102. 'promotion_member_farm_user_id' => 0,
  103. 'farm_user_id' => $farmUserId,
  104. 'source_id' => $directResult->sourceId,
  105. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  106. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  107. 'relation_level' => 1,
  108. 'original_amount' => (string)0,
  109. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  110. 'profit_rate' => 1,
  111. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  112. 'talent_level' => $talentLevel,
  113. 'status' => UrsProfit::STATUS_NORMAL,
  114. ]);
  115. }else{
  116. // 创建收益记录-跳过
  117. $profit = UrsProfit::create([
  118. 'urs_user_id' => $ursUserId,
  119. 'urs_promotion_member_id' => 0,
  120. 'promotion_member_farm_user_id' => 0,
  121. 'farm_user_id' => $farmUserId,
  122. 'source_id' => 0,
  123. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  124. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  125. 'relation_level' => 1,
  126. 'original_amount' => (string)0,
  127. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  128. 'profit_rate' => 1,
  129. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  130. 'talent_level' => $talentLevel,
  131. 'status' => UrsProfit::STATUS_SKIPPED,
  132. ]);
  133. }
  134. // 间推奖励
  135. if ($subordinateStats['indirect_count'] > 0 && $rewardGroups['indirect'] > 0) {
  136. $indirectResult = RewardService::grantReward(
  137. $farmUserId,
  138. $rewardGroups['indirect'],
  139. REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL,
  140. $ursUserId,
  141. $subordinateStats['indirect_count']
  142. );
  143. if (!$indirectResult->success) {
  144. DB::rollBack();
  145. return [
  146. 'success' => false,
  147. 'message' => "间推奖励发放失败: {$indirectResult->errorMessage}",
  148. 'backfilled_count' => $totalBackfilledCount,
  149. 'total_subordinates' => $totalSubordinates,
  150. 'talent_level' => $talentLevel,
  151. 'reward_details' => $rewardDetails
  152. ];
  153. }
  154. $rewardDetails['indirect'] = [
  155. 'type' => '间推奖励',
  156. 'count' => $subordinateStats['indirect_count'],
  157. 'reward_group_id' => $rewardGroups['indirect'],
  158. 'items_count' => count($indirectResult->items)
  159. ];
  160. $totalBackfilledCount += count($indirectResult->items);
  161. // 创建收益记录
  162. $profit = UrsProfit::create([
  163. 'urs_user_id' => $ursUserId,
  164. 'urs_promotion_member_id' => 0,
  165. 'promotion_member_farm_user_id' => 0,
  166. 'farm_user_id' => $farmUserId,
  167. 'source_id' => $directResult->sourceId,
  168. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  169. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  170. 'relation_level' => 2,
  171. 'original_amount' => (string)0,
  172. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  173. 'profit_rate' => 1,
  174. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  175. 'talent_level' => $talentLevel,
  176. 'status' => UrsProfit::STATUS_NORMAL,
  177. ]);
  178. }else{
  179. // 创建收益记录-跳过
  180. $profit = UrsProfit::create([
  181. 'urs_user_id' => $ursUserId,
  182. 'urs_promotion_member_id' => 0,
  183. 'promotion_member_farm_user_id' => 0,
  184. 'farm_user_id' => $farmUserId,
  185. 'source_id' => 0,
  186. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  187. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  188. 'relation_level' => 2,
  189. 'original_amount' => (string)0,
  190. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  191. 'profit_rate' => 1,
  192. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  193. 'talent_level' => $talentLevel,
  194. 'status' => UrsProfit::STATUS_SKIPPED,
  195. ]);
  196. }
  197. // 三推奖励
  198. if ($subordinateStats['third_count'] > 0 && $rewardGroups['third'] > 0) {
  199. $thirdResult = RewardService::grantReward(
  200. $farmUserId,
  201. $rewardGroups['third'],
  202. REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL,
  203. $ursUserId,
  204. $subordinateStats['third_count']
  205. );
  206. if (!$thirdResult->success) {
  207. DB::rollBack();
  208. return [
  209. 'success' => false,
  210. 'message' => "三推奖励发放失败: {$thirdResult->errorMessage}",
  211. 'backfilled_count' => $totalBackfilledCount,
  212. 'total_subordinates' => $totalSubordinates,
  213. 'talent_level' => $talentLevel,
  214. 'reward_details' => $rewardDetails
  215. ];
  216. }
  217. $rewardDetails['third'] = [
  218. 'type' => '三推奖励',
  219. 'count' => $subordinateStats['third_count'],
  220. 'reward_group_id' => $rewardGroups['third'],
  221. 'items_count' => count($thirdResult->items)
  222. ];
  223. $totalBackfilledCount += count($thirdResult->items);
  224. // 创建收益记录
  225. $profit = UrsProfit::create([
  226. 'urs_user_id' => $ursUserId,
  227. 'urs_promotion_member_id' => 0,
  228. 'promotion_member_farm_user_id' => 0,
  229. 'farm_user_id' => $farmUserId,
  230. 'source_id' => $directResult->sourceId,
  231. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  232. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  233. 'relation_level' => 2,
  234. 'original_amount' => (string)0,
  235. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  236. 'profit_rate' => 1,
  237. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  238. 'talent_level' => $talentLevel,
  239. 'status' => UrsProfit::STATUS_NORMAL,
  240. ]);
  241. }else{
  242. // 创建收益记录-跳过
  243. $profit = UrsProfit::create([
  244. 'urs_user_id' => $ursUserId,
  245. 'urs_promotion_member_id' => 0,
  246. 'promotion_member_farm_user_id' => 0,
  247. 'farm_user_id' => $farmUserId,
  248. 'source_id' => 0,
  249. 'source_type' => REWARD_SOURCE_TYPE::URSPROMOTION_BACKFILL->value(),
  250. 'profit_type' => UrsProfitType::PLANTING_REWARD->value,
  251. 'relation_level' => 3,
  252. 'original_amount' => (string)0,
  253. 'profit_amount' => (string)0, // 记录实际发放的物品数量
  254. 'profit_rate' => 1,
  255. 'reward_group_id' => $rewardGroups['direct'], // 种植收益不使用奖励组
  256. 'talent_level' => $talentLevel,
  257. 'status' => UrsProfit::STATUS_SKIPPED,
  258. ]);
  259. }
  260. DB::commit();
  261. Log::info('URS推荐奖励补发成功', [
  262. 'urs_user_id' => $ursUserId,
  263. 'farm_user_id' => $farmUserId,
  264. 'talent_level' => $talentLevel,
  265. 'subordinate_stats' => $subordinateStats,
  266. 'reward_details' => $rewardDetails,
  267. 'total_backfilled_count' => $totalBackfilledCount
  268. ]);
  269. return [
  270. 'success' => true,
  271. 'message' => '推荐奖励补发成功',
  272. 'backfilled_count' => $totalBackfilledCount,
  273. 'total_subordinates' => $totalSubordinates,
  274. 'talent_level' => $talentLevel,
  275. 'reward_details' => $rewardDetails
  276. ];
  277. } catch (\Exception $e) {
  278. DB::rollBack();
  279. throw $e;
  280. }
  281. }
  282. /**
  283. * 检查用户是否需要补发推荐奖励
  284. *
  285. * @param int $ursUserId URS用户ID
  286. * @return bool
  287. */
  288. public function needsBackfillReward(int $ursUserId): bool
  289. {
  290. // 检查用户是否有下级
  291. $subordinateStats = $this->getSubordinateStats($ursUserId);
  292. return $subordinateStats['total_count'] > 0;
  293. }
  294. /**
  295. * 获取用户的下级统计信息
  296. *
  297. * @param int $ursUserId URS用户ID
  298. * @return array
  299. */
  300. public function getSubordinateStats(int $ursUserId): array
  301. {
  302. // 获取直推下级
  303. $directReferrals = UrsReferralService::getDirectReferrals($ursUserId);
  304. $directCount = count($directReferrals);
  305. // 获取间推下级(直推的直推)
  306. $indirectCount = 0;
  307. $indirectReferrals = [];
  308. foreach ($directReferrals as $directUserId) {
  309. $secondLevelReferrals = UrsReferralService::getDirectReferrals($directUserId);
  310. $indirectReferrals = array_merge($indirectReferrals, $secondLevelReferrals);
  311. $indirectCount += count($secondLevelReferrals);
  312. }
  313. // 获取三推下级(间推的直推)
  314. $thirdCount = 0;
  315. foreach ($indirectReferrals as $indirectUserId) {
  316. $thirdLevelReferrals = UrsReferralService::getDirectReferrals($indirectUserId);
  317. $thirdCount += count($thirdLevelReferrals);
  318. }
  319. $totalCount = $directCount + $indirectCount + $thirdCount;
  320. return [
  321. 'direct_count' => $directCount,
  322. 'indirect_count' => $indirectCount,
  323. 'third_count' => $thirdCount,
  324. 'total_count' => $totalCount
  325. ];
  326. }
  327. /**
  328. * 获取用户当前达人等级
  329. *
  330. * @param int $ursUserId URS用户ID
  331. * @return int 达人等级,最低为0(青铜级)
  332. */
  333. private function getUserTalentLevel(int $ursUserId): int
  334. {
  335. $talentDto = UrsTalentService::getTalentInfo($ursUserId);
  336. // 如果用户没有达人等级记录,返回最低级(青铜级)
  337. if (!$talentDto) {
  338. return 0;
  339. }
  340. return $talentDto->talentLevel;
  341. }
  342. /**
  343. * 获取指定达人等级的推荐奖励组配置
  344. *
  345. * @param int $talentLevel 达人等级
  346. * @return array 奖励组配置数组,包含direct、indirect、third三个层级的奖励组ID
  347. */
  348. private function getPromotionRewardGroups(int $talentLevel): array
  349. {
  350. $config = UrsTalentConfig::where('level', $talentLevel)
  351. ->where('status', UrsTalentConfig::STATUS_ENABLED)
  352. ->first();
  353. if (!$config) {
  354. Log::warning('达人等级配置不存在', [
  355. 'talent_level' => $talentLevel
  356. ]);
  357. return [];
  358. }
  359. return [
  360. 'direct' => $config->promotion_direct_group ?? 0,
  361. 'indirect' => $config->promotion_indirect_group ?? 0,
  362. 'third' => $config->promotion_third_group ?? 0,
  363. ];
  364. }
  365. }