BonusRewards.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <?php
  2. namespace app\common\logic;
  3. use app\common\model\EtcWithdrawRecordModel;
  4. use app\common\model\LedgerWalletModel;
  5. use app\common\model\ProductOrder;
  6. use app\common\model\UserModel;
  7. use app\common\model\TimedTaskLogModel;
  8. use app\common\model\UserPathModel;
  9. use fast\Action;
  10. use fast\Asset;
  11. use fast\MembershipLevel;
  12. use think\Db;
  13. use think\Log;
  14. use think\Model;
  15. use think\console\Output;
  16. use fast\Http;
  17. /**
  18. * 团队奖励发放逻辑
  19. * 定时任务,定时发放,每天一次,一般在凌晨12一过开始
  20. */
  21. class BonusRewards
  22. {
  23. /**
  24. * 奖励名称及类型ID
  25. * @var array
  26. */
  27. private array $rewards_type = [
  28. 'service' => [
  29. 'type_id' => 1,
  30. 'type_name' => "服务共创津贴"
  31. ],
  32. 'together' => [
  33. 'type_id' => 2,
  34. 'type_name' => "共创津贴"
  35. ]
  36. ];
  37. /**
  38. * 社区建设津贴
  39. * 1.直推几个有效用户,拿几层,最高10层;每次收益3.5%
  40. * 2.举例:会员A直推了三个有效用户,则会员A下三代内,每个用户购买RWA茶时,A都会收益对应PV的3.5%;
  41. */
  42. public function allowanceRewards()
  43. {
  44. $date = $this->getExeDate($this->rewards_type['service']['type_id']);
  45. if(empty($date)) return "本次没有可用时间";
  46. //创建定时任务执行日志
  47. $TimedTaskLog = new TimedTaskLogModel();
  48. $log_id = $TimedTaskLog->insertGetId([
  49. 'type_id' => $this->rewards_type['service']['type_id'],
  50. 'type_name' => $this->rewards_type['service']['type_name'],
  51. 'date_time' => $date,
  52. 'create_time' => date('Y-m-d H:i:s'),
  53. ]);
  54. //读取当日新增数据
  55. $bonus = self::getDayEarnings($date);
  56. // if(empty($bonus)){
  57. // (new Output())->writeln("本次没有可用新增数据:" . $date);
  58. // return $log_id;
  59. // }
  60. $ledgerWalletModel = new LedgerWalletModel();
  61. //1.服务津贴
  62. $recharge_record = UserModel::alias('a')
  63. ->join('user b', 'a.id = b.parent_id', 'left')
  64. ->field('a.id, SUM(a.rwa_num, b.rwa_num) as total_amount')->having('total_amount >= 10')->group("a.id")
  65. ->select();
  66. dump( collection($recharge_record)->toArray());die;
  67. $recharge_count = count($recharge_record);//总人数
  68. $pv = bcdiv(bcmul($bonus, config('service_ratio')), $recharge_count, 2); //收益
  69. foreach ($recharge_record as $info) {
  70. $ledgerWalletModel->changeWalletAccount($info->id, Asset::TOKEN, $pv, $ledgerWalletModel::Service, 0);
  71. }
  72. //2.共享津贴收益
  73. $rewards_record = UserModel::where('rwa_num', '>', 4)->column('id');
  74. if(!empty($rewards_record )){
  75. $rewards_count = count($rewards_record);//总人数
  76. $pvs = bcdiv(bcmul($bonus, config('together_ratio')), $rewards_count, 2); //收益
  77. foreach ($rewards_record as $info) {
  78. $ledgerWalletModel->changeWalletAccount($info, Asset::TOKEN, $pvs, $ledgerWalletModel::Together, 0);
  79. }
  80. }
  81. return $log_id;
  82. }
  83. /**
  84. * 计算理论收益
  85. * @var array
  86. */
  87. protected function calculateRewards($info, $team_level_config)
  88. {
  89. $user = DB::table('user')
  90. ->where('id', $info['user_id'])
  91. ->find();
  92. $level_info = [];
  93. foreach ($team_level_config as $level) {
  94. if ($user['team_power'] >= $level['compute_require']) {
  95. $level_info['id'] = $level['level_id'];
  96. $level_info['rate'] = $level['compute_incentive'];
  97. }
  98. }
  99. if(isset($level_info['id']) && $level_info['id'] > 0){
  100. //团队等级大于0,才发放收益
  101. $amount = $info['today_power'] * $level_info['rate'];
  102. DB::table('team_rewards')
  103. ->where('id', $info['id'])
  104. ->update([
  105. 'team_power' => $user['team_power'],
  106. 'level_id' => $level_info['id'],
  107. 'rate' => $level_info['rate'],
  108. 'commission' => $amount,
  109. 'update_time' => date('Y-m-d H:i:s')
  110. ]);
  111. //累计上级的团队收益
  112. DB::table('team_rewards')
  113. ->where('user_id', $user['parent_id'])
  114. ->where('date_time', $info['date_time'])
  115. ->update([
  116. 'team_commission' => DB::raw("team_commission + " . $amount),
  117. 'update_time' => date('Y-m-d H:i:s')
  118. ]);
  119. }
  120. }
  121. /**
  122. * 发放团队加权分红
  123. * 1.提取各个等级的会员列表
  124. * 2.再计算当日新增业绩
  125. * 3.根据每个等级现存的人数,按比例平分佣金
  126. */
  127. public function usdtRewards()
  128. {
  129. $date = $this->getExeDate($this->rewards_type['usdt']['type_id']);
  130. if(empty($date)){
  131. return "本次没有可用时间";
  132. }
  133. //创建定时任务执行日志
  134. $TimedTaskLog = new TimedTaskLogModel();
  135. $log_id = $TimedTaskLog->insertGetId([
  136. 'type_id' => $this->rewards_type['usdt']['type_id'],
  137. 'type_name' => $this->rewards_type['usdt']['type_name'],
  138. 'date_time' => $date,
  139. 'create_time' => date('Y-m-d H:i:s'),
  140. ]);
  141. $between_time = [strtotime($date), strtotime($date) + 86400];
  142. //读取当日新增数据,按用户分组统计
  143. $recharge_amount = DB::table('offline_recharge_record')
  144. ->whereBetween('create_time', $between_time)
  145. ->where('order_type', 1)
  146. ->where('status', 1)
  147. ->sum('amount');
  148. if($recharge_amount < 1){
  149. (new Output())->writeln("本次没有可用新增数据:" . $date);
  150. return $log_id;
  151. }
  152. //1.查找有等级的会员
  153. $level_user_list = DB::table('user')
  154. ->field('id,team_level_id')
  155. ->where('team_level_id', '>', 0)
  156. ->select();
  157. $levels_info = [];
  158. //整理数据格式,以team_level_id为键名,存放该等级下的会员id数组
  159. foreach ($level_user_list as $info) {
  160. $levels_info[$info['team_level_id']][] = $info['id'];
  161. }
  162. //读取团队等级配置
  163. $team_level_config = DB::table('team_level')
  164. ->field('level_id, weight_dividend')
  165. ->select();
  166. foreach ($team_level_config as $level) {
  167. if(isset($levels_info[$level['level_id']])){//存在当前等级的会员
  168. //计算当前等级平分佣金金额:当日新增业绩 * 分红比例 / 当前等级人数
  169. $amount = $recharge_amount * $level['weight_dividend'] / count($levels_info[$level['level_id']]);
  170. if($amount > 0){
  171. foreach ($levels_info[$level['level_id']] as $user_id){
  172. //发放佣金
  173. (new LedgerWalletModel)->changeWalletAccount($user_id, Asset::USDT, $amount, Action::UsdtWeightDividend);
  174. }
  175. }else{
  176. Log::info("分红等级" . $level['level_id'] . "在" . $date . "分红金额为0;当日新增业绩:" . $amount . ",分红比例:" . $level['weight_dividend']. ",分红人数" . dump($levels_info[$level['level_id']]));
  177. }
  178. }
  179. }
  180. return $log_id;
  181. }
  182. /**
  183. * 发放社区长、系统领导人加权分红
  184. * 1.提取社区长等级的会员列表
  185. * 2.再计算当日新增业绩
  186. * 3.根据每个等级现存的人数,按比例平分佣金
  187. * 5.提取系统领导人等级的会员列表
  188. * 6.再计算当日新增业绩
  189. * 7.根据每个等级现存的人数,按比例平分佣金
  190. */
  191. public function marketRewards()
  192. {
  193. $date = $this->getExeDate($this->rewards_type['market']['type_id']);
  194. if(empty($date)){
  195. return "本次没有可用时间";
  196. }
  197. //创建定时任务执行日志
  198. $TimedTaskLog = new TimedTaskLogModel();
  199. $log_id = $TimedTaskLog->insertGetId([
  200. 'type_id' => $this->rewards_type['market']['type_id'],
  201. 'type_name' => $this->rewards_type['market']['type_name'],
  202. 'date_time' => $date,
  203. 'create_time' => date('Y-m-d H:i:s'),
  204. ]);
  205. $between_time = [strtotime($date), strtotime($date) + 86400];
  206. //读取当日新增数据
  207. $recharge_power = DB::table('offline_recharge_record')
  208. ->whereBetween('create_time', $between_time)
  209. ->where('status', 1)
  210. ->sum('power');
  211. if($recharge_power < 1){
  212. (new Output())->writeln("本次没有可用新增数据:" . $date);
  213. return $log_id;
  214. }
  215. //团队长分红
  216. //查找有团队长等级的会员
  217. $community_user_list = DB::table('user')
  218. ->field('id,market_level_id')
  219. ->where('market_level_id', MembershipLevel::CommunityLeader)
  220. ->select();
  221. $community_rewards = (new ParametersModel())->getValue('communityRewards'); //社区长分红参数 数据格式为:0.02:0.5:0.5
  222. $usdt_rate = (new ParametersModel())->getValue('usdtToPowerRate');
  223. $community_rewards_arr = explode(':', $community_rewards);
  224. $reward = $recharge_power * $community_rewards_arr[0] / count($community_user_list);//新增业绩 * 分红比例 / 人数
  225. if($reward > 0) {
  226. $reward_power = $reward * $community_rewards_arr[1];
  227. $reward_usdt = $reward * $community_rewards_arr[2] / $usdt_rate;//算力折算成U
  228. foreach ($community_user_list as $info) {
  229. //发放分红
  230. (new LedgerWalletModel)->changeWalletAccount($info['id'], Asset::POWER, $reward_power, Action::PowerBonusAward);
  231. (new LedgerWalletModel)->changeWalletAccount($info['id'], Asset::USDT, $reward_usdt, Action::UsdtWeightDividend);
  232. }
  233. }else {
  234. Log::info("社区长分红在" . $date . "分红金额为0;当日新增业绩:" . $recharge_power . ",分红比例:" . $community_rewards_arr[0] . ",分红人数" . count($community_user_list));
  235. }
  236. //领导人分红
  237. //查找有团队长等级的会员
  238. $sys_leader_user_list = DB::table('user')
  239. ->field('id,market_level_id')
  240. ->where('market_level_id', MembershipLevel::SystemLeader)
  241. ->select();
  242. $sys_leade_rewards = (new ParametersModel())->getValue('sysLeaderRewards'); //系统领导人分红参数 数据格式为:0.02:0.5:0.5
  243. $sys_leade_rewards_arr = explode(':', $sys_leade_rewards);
  244. $reward = $recharge_power * $sys_leade_rewards_arr[0] / count($sys_leader_user_list);//新增业绩 * 分红比例 / 人数
  245. if($reward > 0) {
  246. $reward_power = $reward * $sys_leade_rewards_arr[1];
  247. $reward_usdt = $reward * $sys_leade_rewards_arr[2] * 8;//算力折算成U
  248. foreach ($sys_leader_user_list as $info) {
  249. //发放分红
  250. (new LedgerWalletModel)->changeWalletAccount($info['id'], Asset::POWER, $reward_power, Action::PowerBonusAward);
  251. (new LedgerWalletModel)->changeWalletAccount($info['id'], Asset::USDT, $reward_usdt, Action::UsdtWeightDividend);
  252. }
  253. }else {
  254. Log::info("系统领导人分红在" . $date . "分红金额为0;当日新增业绩:" . $recharge_power . ",分红比例:" . $community_rewards_arr[0] . ",分红人数" . count($community_user_list));
  255. }
  256. return $log_id;
  257. }
  258. /**
  259. * 获取当日收益 Daily earnings
  260. */
  261. private static function getDayEarnings(string $date)
  262. {
  263. $between_time = [strtotime($date), strtotime($date) + 86400];
  264. //读取当日新增数据
  265. return ProductOrder::where('type_id', ProductOrder::Popular)->where('status', ProductOrder::Paid)->whereBetween('create_time', $between_time)->sum('price');
  266. }
  267. /**
  268. * 获取可用日期
  269. * @var array
  270. */
  271. protected function getExeDate($type_id = 1)
  272. {
  273. $today = date('Y-m-d',strtotime("-1day"));//当前时间减一天为最后一次可用时间
  274. $dateInfo = DB::table('timed_task_log')
  275. ->where('type_id' ,$type_id)
  276. ->where('status', 1)
  277. ->order('date_time', 'desc')
  278. ->find();
  279. if(empty($dateInfo)){//首次
  280. return $today;
  281. }
  282. $new_date = date('Y-m-d',strtotime("+1day",strtotime($dateInfo['date_time'])));//最后一次发放日期+1天为本次执行时间
  283. if($new_date > $today){//超过今天
  284. return "";
  285. }
  286. return $new_date;
  287. }
  288. /**
  289. * 插入或更新收益统计信息
  290. * @var array
  291. */
  292. protected function createData($uids, $amount, $date)
  293. {
  294. foreach ($uids as $user_id) {
  295. $check = DB::table('team_rewards')
  296. ->field('id')
  297. ->where('user_id', $user_id)
  298. ->where('date_time', $date)
  299. ->find();
  300. if ($check) {//存在,则更新
  301. DB::table('team_rewards')
  302. ->where('id', $check['id'])
  303. ->update([
  304. 'today_power' => Db::raw('today_power+' . $amount),
  305. 'update_time' => date('Y-m-d H:i:s')
  306. ]);
  307. } else {//新增
  308. DB::table('team_rewards')
  309. ->insert([
  310. 'user_id' => $user_id,
  311. 'date_time' => $date,
  312. 'today_power' => Db::raw('today_power+' . $amount),
  313. 'create_time' => date('Y-m-d H:i:s')
  314. ]);
  315. }
  316. }
  317. }
  318. }