FrozenToActiveLogic.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. <?php
  2. /**
  3. * 红包拓客
  4. */
  5. namespace addons\Redpack\common\logic;
  6. use addons\Agent\common\models\Agent;
  7. use addons\Agent\common\models\AgentLevel;
  8. use addons\Redpack\common\enums\RedpackEnum;
  9. use addons\Redpack\common\helper\RedpackHelper;
  10. use addons\Redpack\common\models\Redpack;
  11. use addons\Redpack\common\models\RedpackTask;
  12. use addons\Redpack\common\models\RedpackWallet;
  13. use addons\BlueScore\common\models\BlueScore;
  14. use addons\BlueScore\common\enums\BlueScoreEnum;
  15. use common\enums\AddonsEnum;
  16. use common\enums\RedisKeyEnum;
  17. use common\enums\StatusEnum;
  18. use common\models\common\AddonsSetting;
  19. use common\models\mall\Mall;
  20. use common\models\mall\MallAddons;
  21. use common\models\user\User;
  22. use common\models\user\UserLevel;
  23. use common\models\user\UserPartitionRelationship;
  24. use common\traits\ErrorTrait;
  25. use phpDocumentor\Reflection\Types\Self_;
  26. use yii\db\Exception;
  27. use Yii;
  28. use yii\redis\Connection;
  29. class FrozenToActiveLogic
  30. {
  31. use ErrorTrait;
  32. /**
  33. * 执行冻结转激活红包之前进行记录
  34. * @Author: ltm
  35. * @DateTime: 2022/3/24 0024 11:07
  36. * @Copyright: copyright (c) 2021 广东七件事集团
  37. * @param $data
  38. * @return string
  39. */
  40. public static function FrozenToActive(){
  41. //查询当天是否执行过
  42. $time = time();
  43. $date = date("Y-m-d");
  44. $find_data = RedpackTask::find()->where(['day'=>$date])->orderBy('id desc')->one();
  45. $executed_ids = [];
  46. if(!empty($find_data['content'])){
  47. $executed_ids = json_decode($find_data['content']);
  48. }
  49. $open_mall_ids = self::getOpenRedpackMall();// 开启每日冻结转激活商城
  50. $where = [
  51. 'or',
  52. [//查询未过期商城
  53. 'and',
  54. ['=','status',StatusEnum::ENABLED],
  55. ['>','expired_at',time()],
  56. ],
  57. [//查询永久商城
  58. 'and',
  59. ['=','status',StatusEnum::ENABLED],
  60. ['=','expired_at',StatusEnum::DISABLED],
  61. ],
  62. ];
  63. //遍历所有商城
  64. $model = Mall::find()->select('id,name,status')->orderBy('id')->andwhere($where);
  65. foreach ($model->asArray()->batch(500) as $mall_ids_list) {
  66. $mall_ids = array_column($mall_ids_list, 'id');
  67. $mall_execute_ids = array_diff($mall_ids,$executed_ids);
  68. //获取开启红包拓客冻结红包转激活红包的 mall_id
  69. if(count($mall_ids)>0 && !empty($mall_execute_ids)) {
  70. $mall_config_time = self::getMallConfigtime($mall_execute_ids); //获取开启红包拓客设置定时时间
  71. $mall_config = self::getMallConfignum($mall_execute_ids); //获取需要进行任务商城红包转换比率
  72. $mall_blue_score_config = self::getOpenBlueScoreMall($mall_execute_ids);
  73. //执行冻结红包进行激活
  74. $is_execute = false;
  75. foreach ($mall_execute_ids as $k => $v){
  76. if(!empty($mall_config_time['activation_time'][$v])){
  77. $activation_time = $mall_config_time['activation_time'][$v];
  78. $activation_time = strtotime($activation_time);
  79. if($time>=$activation_time){
  80. if(!$executed_ids || !in_array($v,$executed_ids)){
  81. if (!in_array($v, $open_mall_ids)) continue;// 未开启配置直接跳过
  82. $res = self::redpackexecute($v,$mall_config, $mall_blue_score_config);
  83. if($res){
  84. $executed_ids[] = $v;
  85. if($find_data){
  86. $add_data['id'] = $find_data->id;
  87. }
  88. if($executed_ids) {
  89. $add_data['content'] = json_encode($executed_ids,true);
  90. $add_data['day'] = date("Y-m-d");
  91. $res = RedpackTask::setData($add_data,$is_execute,$find_data);
  92. }
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }
  99. }
  100. //更新活动的活动时间
  101. self::changeactivetime();
  102. return true;
  103. }
  104. /**
  105. * 修改每日活动时间
  106. * @Author: ltm
  107. * @DateTime: 2022/3/25 0025 10:35
  108. * @Copyright: copyright (c) 2021 广东七件事集团
  109. * @param $data
  110. * @return string
  111. */
  112. public static function changeactivetime(){
  113. $where = [
  114. 'and',
  115. ['time_type' => '1'],
  116. ['status' => StatusEnum::ENABLED],
  117. ];
  118. $redis = \Yii::$app->redis;
  119. $update_time = $redis->get(RedpackEnum::REDIS_REDPACK_STAK_KEY);
  120. $daytime = strtotime(date("Y-m-d"));
  121. $last_execute_time = strtotime(date('Y-m-d'));
  122. if(!$update_time || $update_time < $last_execute_time){
  123. $model = Redpack::find()->select('time_type,mall_id,start_time,end_time,day_award,award,id')->where($where);
  124. foreach ($model->batch(500) as $data) {
  125. foreach ($data as $key => $value) {
  126. $params['start_time'] = $daytime + strtotime(date("Y-m-d H:i:s",$value['start_time'])) - strtotime(date("Y-m-d",$value['start_time']));
  127. $params['end_time'] = $daytime + strtotime(date("Y-m-d H:i:s",$value['end_time'])) - strtotime(date("Y-m-d",$value['end_time']));
  128. $params['id'] = $value['id'];
  129. $params['mall_id'] = $value['mall_id'];
  130. $params['award'] = $value['day_award'];//每日总奖金每日凌晨将被覆盖
  131. $update = Redpack::setData($params);
  132. }
  133. }
  134. //更新标记执行过时间
  135. self::setRedpackTaskStatus(time());
  136. }
  137. }
  138. /**
  139. * @Author: ltm
  140. * @DateTime: 2022/3/25 0025 14:01
  141. * @Copyright: copyright (c) 2021 广东七件事集团
  142. * @param $data
  143. * @return string
  144. */
  145. public static function setRedpackTaskStatus($data) {
  146. $config = \Yii::$app->getComponents()['redis'];
  147. unset($config['class']);
  148. $redis = new Connection($config);
  149. $redis->set(RedpackEnum::REDIS_REDPACK_STAK_KEY,$data);
  150. $redis->close();
  151. }
  152. /**
  153. * 执行冻结红包转激活
  154. * @Author: ltm
  155. * @DateTime: 2022/3/24 0024 14:48
  156. * @Copyright: copyright (c) 2021 广东七件事集团
  157. * @param $data
  158. * @return string
  159. */
  160. public static function redpackexecute($mall_id,$mall_config, $mall_blue_score_config){
  161. //获取会员记录
  162. $where = [
  163. 'and',
  164. ['mall_id' => $mall_id],
  165. ['status' => StatusEnum::ENABLED],
  166. ['>','frozen_redpack',0],
  167. ];
  168. $model = RedpackWallet::find()->select('frozen_redpack,mall_id,user_id,id')->where($where);
  169. //冻结红包转激活红包
  170. $text = RedpackEnum::getRedpackText(RedpackEnum::WALLET_REDPACK_FROZEN, $mall_id).'转'.RedpackEnum::getRedpackText(RedpackEnum::WALLET_REDPACK, $mall_id);
  171. foreach ($model->asArray()->batch(500) as $walletdata) {
  172. foreach ($walletdata as $key => $value){
  173. $calculate_money = $value['frozen_redpack'] * $mall_config['activation_num'][$mall_id] / 100;
  174. $money = sprintf("%.2f",substr(sprintf("%.3f", $calculate_money), 0, -1));
  175. //小于一分钱,则不转出
  176. if ($money < 0.01) continue;
  177. //获取蓝色积分配置
  178. $blue_score_config = $mall_blue_score_config[$mall_id] ?? [];
  179. $t = Yii::$app->db->beginTransaction();
  180. try {
  181. if($money>0){
  182. //扣除冻结红包
  183. $res = RedpackWallet::setData([
  184. 'mall_id' => $mall_id,
  185. 'user_id' => $value['user_id'],
  186. 'is_frozen' => true,
  187. 'is_deduct' => true,
  188. 'money' => - $money,
  189. 'from_type' => $blue_score_config['is_enable'] == StatusEnum::ENABLED ? RedpackEnum::FROM_FROZEN_AUTO_ROLL_OUT : RedpackEnum::FROM_FROZEN_TO_ACTIVE,
  190. 'desc' => $text,
  191. ]);
  192. if($res === false) throw new Exception('执行失败');
  193. //是否安装and开启了蓝色积分转换
  194. $has_blue_score = \common\models\mall\MallAddons::isInstall($mall_id,AddonsEnum::ADDONS_BLUE_SCORE);
  195. if ($has_blue_score && !empty($blue_score_config) && $blue_score_config['is_enable'] == StatusEnum::ENABLED) {
  196. if (!empty($blue_score_config['transfer_rate']) || $blue_score_config['transfer_rate'] > 0) {
  197. //计算激活红包转换的蓝色积分
  198. $integral = round($money * $blue_score_config['transfer_rate'] / 100,2);
  199. //计算剩余的激活红包
  200. $money = round($money * (1 - ($blue_score_config['transfer_rate'] / 100)),2);;
  201. //转换蓝色积分
  202. BlueScore::setData([
  203. 'mall_id' => $mall_id,
  204. 'user_id' => $value['user_id'],
  205. 'integral' => $integral,
  206. 'from_type' => BlueScoreEnum::FROM_ACTIVE_AUTO_TO_BLUE_SCORE,
  207. 'desc' => '冻结红包自动转蓝色积分,蓝色积分+' . $integral,
  208. ]);
  209. }
  210. }
  211. //转激活红包
  212. $res = RedpackWallet::setData([
  213. 'mall_id' => $mall_id,
  214. 'user_id' => $value['user_id'],
  215. 'is_frozen' => false,
  216. 'is_deduct' => true,
  217. 'money' => $money,
  218. 'from_type' => RedpackEnum::FROM_FROZEN_TO_ACTIVE,
  219. 'desc' => $text,
  220. ]);
  221. }
  222. if($res === false) throw new Exception("执行失败");
  223. //加速激活冻结红包
  224. self::computeActive($mall_id, $value['user_id'], $money);
  225. $t->commit();
  226. } catch (\Exception $e) {
  227. $t->rollBack();
  228. echo '冻结红包转激活红包失败,' . $e->getMessage() . ',行数:' . $e->getLine();
  229. }
  230. }
  231. }
  232. return true;
  233. }
  234. /**
  235. * 获取已经开启冻结红包转激活红包商城配置
  236. * @Author: ltm
  237. * @DateTime: 2022/3/24 0024 10:21
  238. * @Copyright: copyright (c) 2021 广东七件事集团
  239. * @param $data
  240. * @return array
  241. */
  242. public static function getOpenRedpackMall()
  243. {
  244. //获取开启的商城ID
  245. $ids = [];
  246. $where[] = ['name' => "frozen_status"];
  247. $where[] = ['value' => 1];
  248. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_REDPACK];
  249. $redpack_config = AddonsSetting::lists(['where'=>$where],true);
  250. if($redpack_config){
  251. $ids = array_column($redpack_config,'mall_id');
  252. }
  253. return $ids;
  254. }
  255. /**
  256. *
  257. * @Author: ltm
  258. * @DateTime: 2022/3/24 0024 10:51
  259. * @Copyright: copyright (c) 2021 广东七件事集团
  260. * @param $data
  261. * @return string
  262. */
  263. public static function getMallConfigtime($mall_ids){
  264. //获取开启时间
  265. $where[] = ['in','mall_id',$mall_ids];
  266. $where[] = ['name' => "activation_time"];
  267. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_REDPACK];
  268. $redpack_config = AddonsSetting::lists(['where'=>$where,'select'=>'value,mall_id'],true);
  269. if($redpack_config){
  270. $list['activation_time'] = array_column($redpack_config,'value','mall_id');
  271. }
  272. return $list;
  273. }
  274. /**
  275. *
  276. * @Author: ltm
  277. * @DateTime: 2022/3/24 0024 10:51
  278. * @Copyright: copyright (c) 2021 广东七件事集团
  279. * @param $data
  280. * @return array
  281. */
  282. public static function getMallConfignum($mall_ids){
  283. //获取转换比率
  284. $where[] = ['in','mall_id',$mall_ids];
  285. $where[] = ['name' => "activation_num"];
  286. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_REDPACK];
  287. $redpack_config = AddonsSetting::lists(['where'=>$where,'select'=>'value,mall_id'],true);
  288. $list = [];
  289. if($redpack_config){
  290. $list['activation_num'] = array_column($redpack_config,'value','mall_id');
  291. }
  292. return $list;
  293. }
  294. /**
  295. * 获取蓝色积分商城配置
  296. * @Author:
  297. * @DateTime:
  298. * @Copyright:
  299. * @param $mall_ids
  300. * @return array
  301. */
  302. public static function getOpenBlueScoreMall($mall_ids)
  303. {
  304. $where[] = ['addons_name' => AddonsEnum::ADDONS_BLUE_SCORE];
  305. $where[] = ['status' => StatusEnum::ENABLED];
  306. $where[] = ['mall_id' => $mall_ids];
  307. $blue_score_config = AddonsSetting::lists(['where'=>$where, 'select'=>'name,value,mall_id'],true);
  308. $return_array = [];
  309. if ($blue_score_config) {
  310. foreach ($blue_score_config as $config) {
  311. $return_array[$config['mall_id']][$config['name']] = $config['value'];
  312. }
  313. }
  314. return $return_array;
  315. }
  316. /**
  317. * 冻结红包加速激活计算
  318. * @Author:
  319. * @DateTime:
  320. * @Copyright:
  321. * @param $mall_ids
  322. * @return bool|void
  323. */
  324. public static function computeActive($mall_id, $user_id, $init_money)
  325. {
  326. if ($init_money < 0.01) {
  327. return true;
  328. }
  329. //获取商城配置
  330. $config = Yii::$app->services->setting->addons->get($mall_id, AddonsEnum::ADDONS_NAME_REDPACK, 'basic');
  331. $config = RedpackHelper::initConfig($config);
  332. if (empty($config['is_set_activate'])) {
  333. //冻结红包加速激活设置未开启
  334. return true;
  335. }
  336. //获取用户路径,并获取奖励用户
  337. $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id);
  338. if (empty($parent_id_arr)) {
  339. //没有上级
  340. return true;
  341. }
  342. //倒转数组,直属在最前面
  343. $parent_id_arr = array_reverse($parent_id_arr);
  344. //获取直推用户的加速设置
  345. $setting_user_level_list = json_decode($config['setting_user_level_list'], true) ?? [];
  346. //查询直属上级信息
  347. $parent_id = $parent_id_arr[0];
  348. $parent_user_info = User::find()
  349. ->where([
  350. 'id' => $parent_id,
  351. 'status' => StatusEnum::ENABLED
  352. ])
  353. ->select('id,level')
  354. ->asArray()
  355. ->one();
  356. $parent_redpack_wallets = RedpackWallet::find()
  357. ->where([
  358. 'mall_id' => $mall_id,
  359. 'user_id' => $parent_id_arr
  360. ])
  361. ->indexBy('user_id')
  362. ->asArray()
  363. ->all();
  364. if ($parent_user_info) {
  365. $user_level = UserLevel::find()
  366. ->where([
  367. 'mall_id' => $mall_id,
  368. 'level' => $parent_user_info['level'],
  369. 'status' => StatusEnum::ENABLED
  370. ])
  371. ->one();
  372. if ($user_level && isset($setting_user_level_list[$parent_user_info['level']]) && isset($parent_redpack_wallets[$parent_id])) {
  373. //直属上级冻结红包数量需要大于0
  374. if ($parent_redpack_wallets[$parent_id]['frozen_redpack'] > 0) {
  375. $money = bcmul($init_money, $setting_user_level_list[$parent_user_info['level']] / 100, 2);
  376. $money = min($money, $parent_redpack_wallets[$parent_id]['frozen_redpack']);
  377. if ($money > 0.01) {
  378. //直属上级 加速转激活冻结红包
  379. $res = RedpackWallet::setData([
  380. 'mall_id' => $mall_id,
  381. 'user_id' => $parent_id,
  382. 'is_frozen' => true,
  383. 'is_deduct' => true,
  384. 'money' => - $money,
  385. 'from_type' => RedpackEnum::FROM_PUSH_ACCELERATION,
  386. 'desc' => '直推加速激活',
  387. ]);
  388. if($res === false) throw new Exception('直属上级加速-扣除冻结红包执行失败');
  389. //直属上级 加速转激活红包
  390. $res = RedpackWallet::setData([
  391. 'mall_id' => $mall_id,
  392. 'user_id' => $parent_id,
  393. 'is_frozen' => false,
  394. 'is_deduct' => true,
  395. 'money' => $money,
  396. 'from_type' => RedpackEnum::FROM_PUSH_ACCELERATION,
  397. 'desc' => '直推加速激活',
  398. ]);
  399. if ($res === false) throw new Exception("直属上级加速-转激活红包执行失败");
  400. $parent_redpack_wallets[$parent_id]['frozen_redpack'] = bcsub($parent_redpack_wallets[$parent_id]['frozen_redpack'], $money, 2);
  401. }
  402. }
  403. }
  404. }
  405. if (MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_AGENT)) {
  406. $agents = Agent::find()
  407. ->where([
  408. 'user_id' => $parent_id_arr,
  409. 'status' => StatusEnum::ENABLED
  410. ])
  411. ->select('id,user_id,level')
  412. ->asArray()
  413. ->all();
  414. // 按$parent_id_arr顺序重新排序
  415. usort($agents, function ($a, $b) use ($parent_id_arr) {
  416. return array_search($a['user_id'], $parent_id_arr) - array_search($b['user_id'], $parent_id_arr);
  417. });
  418. //渠道分红等级配置
  419. $setting_agent_level_list = json_decode($config['setting_agent_level_list'], true) ?? [];
  420. //安装了渠道分红
  421. $agent_level_list = AgentLevel::find()
  422. ->where([
  423. 'mall_id' => $mall_id,
  424. 'status' => StatusEnum::ENABLED
  425. ])
  426. ->select('id,name,level')
  427. ->indexBy('level')
  428. ->asArray()
  429. ->all();
  430. $has_reward_ratio = 0;
  431. foreach ($agents as $agent) {
  432. if (isset($agent_level_list[$agent['level']]) && isset($setting_agent_level_list[$agent['level']])) {
  433. if (!isset($parent_redpack_wallets[$agent['user_id']]) || empty($parent_redpack_wallets[$agent['user_id']]['frozen_redpack'])) {
  434. continue;
  435. }
  436. $reward_money = bcmul($init_money, ($setting_agent_level_list[$agent['level']] - $has_reward_ratio) / 100, 2);
  437. $reward_money = min($reward_money, $parent_redpack_wallets[$agent['user_id']]['frozen_redpack']);
  438. if ($reward_money > 0.01) {
  439. $has_reward_ratio = max($setting_agent_level_list[$agent['level']], $has_reward_ratio);
  440. $res = RedpackWallet::setData([
  441. 'mall_id' => $mall_id,
  442. 'user_id' => $agent['user_id'],
  443. 'is_frozen' => true,
  444. 'is_deduct' => true,
  445. 'money' => - $reward_money,
  446. 'from_type' => RedpackEnum::FROM_AGENT_ACCELERATION,
  447. 'desc' => '渠道加速激活',
  448. ]);
  449. if($res === false) throw new Exception('渠道分红团队加速-扣除冻结红包执行失败');
  450. // 团队加速转激活红包
  451. $res = RedpackWallet::setData([
  452. 'mall_id' => $mall_id,
  453. 'user_id' => $agent['user_id'],
  454. 'is_frozen' => false,
  455. 'is_deduct' => true,
  456. 'money' => $reward_money,
  457. 'from_type' => RedpackEnum::FROM_AGENT_ACCELERATION,
  458. 'desc' => '渠道加速激活',
  459. ]);
  460. if ($res === false) throw new Exception("渠道分红团队加速-转激活红包执行失败");
  461. }
  462. }
  463. }
  464. }
  465. return true;
  466. }
  467. }