FrozenToActiveLogic.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?php
  2. /**
  3. * 积分拓客
  4. */
  5. namespace addons\ScoreExpansion\common\logic;
  6. use addons\Redpack\common\enums\RedpackEnum;
  7. use addons\Redpack\common\models\Redpack;
  8. use addons\Redpack\common\models\RedpackTask;
  9. use addons\ScoreExpansion\common\enums\ScoreExpansionEnum;
  10. use addons\ScoreExpansion\common\models\ScoreExpansion;
  11. use addons\ScoreExpansion\common\models\ScoreExpansionGoodsSetting;
  12. use addons\ScoreExpansion\common\models\ScoreExpansionRateTask;
  13. use addons\ScoreExpansion\common\models\ScoreExpansionTask;
  14. use addons\ScoreExpansion\common\models\ScoreExpansionWallet;
  15. use addons\ScoreExpansion\common\models\ScoreExpansionWalletLog;
  16. use addons\ScoreExpansion\common\services\SettingService;
  17. use addons\Store\common\models\StoreOrder;
  18. use common\models\order\OrderDetail;
  19. use common\enums\AddonsEnum;
  20. use common\enums\RedisKeyEnum;
  21. use common\enums\StatusEnum;
  22. use common\models\common\AddonsSetting;
  23. use common\models\mall\Mall;
  24. use common\models\order\Order;
  25. use common\traits\ErrorTrait;
  26. use yii\db\Exception;
  27. use Yii;
  28. use yii\db\Expression;
  29. use yii\redis\Connection;
  30. class FrozenToActiveLogic
  31. {
  32. use ErrorTrait;
  33. /**
  34. * 执行冻结转激活积分之前进行记录
  35. * @Author: ltm
  36. * @DateTime: 2022/3/24 0024 11:07
  37. * @Copyright: copyright (c) 2021 广东七件事集团
  38. * @param $data
  39. * @return string
  40. */
  41. public static function FrozenToActive()
  42. {
  43. //查询当天是否执行过
  44. $time = time();
  45. $date = date("Y-m-d");
  46. $find_data = ScoreExpansionTask::find()->where(['day' => $date])->orderBy('id desc')->one();
  47. $executed_ids = [];
  48. if (!empty($find_data['content'])) {
  49. $executed_ids = json_decode($find_data['content']);
  50. }
  51. $where = [
  52. 'or',
  53. [//查询未过期商城
  54. 'and',
  55. ['=', 'status', StatusEnum::ENABLED],
  56. ['>', 'expired_at', time()],
  57. ],
  58. [//查询永久商城
  59. 'and',
  60. ['=', 'status', StatusEnum::ENABLED],
  61. ['=', 'expired_at', StatusEnum::DISABLED],
  62. ],
  63. ];
  64. // 遍历所有商城
  65. $mall_ids = Mall::find()->where($where)->select('id')->column();
  66. $mall_execute_ids = array_diff($mall_ids, $executed_ids);
  67. if (empty($mall_execute_ids)) return true;
  68. // 当前开启配置的商城
  69. $open_mall_ids = self::getOpenRedpackMall($mall_execute_ids);
  70. $mall_config_time = self::getMallConfigtime($mall_execute_ids); //获取开启积分拓客设置定时时间
  71. $mall_config = self::getMallConfignum($mall_execute_ids); //获取需要进行任务商城积分转换比率
  72. $order_detail = self::carryOutAppraiseSetting($mall_execute_ids);//批量处理超时未评价的订单
  73. // 配置service
  74. $settingService = new SettingService([]);
  75. // 执行冻结积分进行激活
  76. $is_execute = false;
  77. foreach ($open_mall_ids as $k => $v) {
  78. // 获取配置,如果今天不激活积分则跳过
  79. $settingService->mall_id = $v;
  80. $inactiveDates = $settingService->getSetting()['inactive_dates'] ?? [];
  81. if (is_array($inactiveDates) && in_array($date, $inactiveDates)) {
  82. Yii::$app->custom->logs('【积分拓客】今日不激活', ['mall_id' => $v, 'inactive_dates' => $inactiveDates]);
  83. continue;
  84. }
  85. // 判断后台冻结转激活开关是否开启end
  86. if (!empty($mall_config_time['activation_time'][$v])) {
  87. $activation_time = $mall_config_time['activation_time'][$v];
  88. $activation_time = strtotime($activation_time);
  89. if ($time >= $activation_time && $time < $activation_time + 1800) {
  90. if (!$executed_ids || !in_array($v, $executed_ids)) {
  91. $res = self::redpackexecute($v);
  92. if ($res) {
  93. $executed_ids[] = $v;
  94. if ($find_data) {
  95. $add_data['id'] = $find_data->id;
  96. }
  97. if ($executed_ids) {
  98. $add_data['content'] = json_encode($executed_ids, true);
  99. $add_data['day'] = date("Y-m-d");
  100. $res = ScoreExpansionTask::setData($add_data, $is_execute, $find_data);
  101. }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. //更新活动的活动时间
  108. self::changeactivetime();
  109. return true;
  110. }
  111. /**
  112. * 修改每日活动时间
  113. * @Author: ltm
  114. * @DateTime: 2022/3/25 0025 10:35
  115. * @Copyright: copyright (c) 2021 广东七件事集团
  116. * @param $data
  117. * @return string
  118. */
  119. public static function changeactivetime()
  120. {
  121. $where = [
  122. 'and',
  123. ['time_type' => '1'],
  124. ['status' => StatusEnum::ENABLED],
  125. ];
  126. $redis = \Yii::$app->redis;
  127. $update_time = $redis->get(ScoreExpansionEnum::REDIS_SCORE_EXPANSION_STAK_KEY);
  128. $daytime = strtotime(date("Y-m-d"));
  129. $last_execute_time = strtotime(date('Y-m-d'));
  130. if (!$update_time || $update_time < $last_execute_time) {
  131. $model = ScoreExpansion::find()->select('time_type,mall_id,start_time,end_time,day_award,award,id')->where($where);
  132. foreach ($model->batch(500) as $data) {
  133. foreach ($data as $key => $value) {
  134. $params['start_time'] = $daytime + strtotime(date("Y-m-d H:i:s", $value['start_time'])) - strtotime(date("Y-m-d", $value['start_time']));
  135. $params['end_time'] = $daytime + strtotime(date("Y-m-d H:i:s", $value['end_time'])) - strtotime(date("Y-m-d", $value['end_time']));
  136. $params['id'] = $value['id'];
  137. $params['mall_id'] = $value['mall_id'];
  138. $params['award'] = $value['day_award'];//每日总奖金每日凌晨将被覆盖
  139. $update = ScoreExpansion::setData($params);
  140. }
  141. }
  142. //更新标记执行过时间
  143. self::setRedpackTaskStatus(time());
  144. }
  145. }
  146. /**
  147. * @Author: ltm
  148. * @DateTime: 2022/3/25 0025 14:01
  149. * @Copyright: copyright (c) 2021 广东七件事集团
  150. * @param $data
  151. * @return string
  152. */
  153. public static function setRedpackTaskStatus($data)
  154. {
  155. $config = \Yii::$app->getComponents()['redis'];
  156. unset($config['class']);
  157. $redis = new Connection($config);
  158. $redis->set(ScoreExpansionEnum::REDIS_SCORE_EXPANSION_STAK_KEY, $data);
  159. $redis->close();
  160. }
  161. /**
  162. * 执行冻结积分转激活
  163. * @Author: ltm
  164. * @DateTime: 2022/3/24 0024 14:48
  165. * @Copyright: copyright (c) 2021 广东七件事集团
  166. * @param $data
  167. * @return string
  168. */
  169. public static function redpackexecute($mall_id)
  170. {
  171. //获取用户记录
  172. $where = [
  173. 'and',
  174. ['mall_id' => $mall_id],
  175. ['status' => StatusEnum::ENABLED],
  176. ['>', 'frozen_integral', 0],
  177. ];
  178. $model = ScoreExpansionWallet::find()->select('frozen_integral,total_frozen_integral,total_integral,mall_id,user_id,id')->where($where);
  179. // 设置服务
  180. $service = new SettingService(['mall_id' => $mall_id]);
  181. //冻结积分转激活积分
  182. $text = ScoreExpansionEnum::getRedpackText(ScoreExpansionEnum::WALLET_INTEGRAL_FROZEN, $mall_id) . '转' . ScoreExpansionEnum::getRedpackText(ScoreExpansionEnum::WALLET_INTEGRAL, $mall_id);
  183. foreach ($model->asArray()->batch(500) as $walletdata) {
  184. foreach ($walletdata as $value) {
  185. // 计算积分 等比例
  186. if ($service->isEqualEatio()) {
  187. $calculate_money = bcdiv(bcmul($value['total_frozen_integral'], $service->getActivationNum(), 2), 100, 2);
  188. $money = sprintf("%.2f", substr(sprintf("%.3f", $calculate_money), 0, -1));
  189. }
  190. // 计算积分 递减
  191. if ($service->isDecrement()) {
  192. $calculate_money = bcdiv(bcmul($value['frozen_integral'], $service->getActivationNum(), 2), 100, 2);
  193. $money = sprintf("%.2f", substr(sprintf("%.3f", $calculate_money), 0, -1));
  194. }
  195. // 固定金额
  196. if ($service->isFixed()) {
  197. $money = bcmul($service->getActivationNum(), 1, 2);
  198. }
  199. // 小于一分钱,则不转出
  200. if ($money < 0.01) continue;
  201. // 判断当前用户冻结积分是否足以抵扣转换金额,不足则转换金额默认为当前冻结积分
  202. if ($value['frozen_integral'] < $money) {
  203. $money = $value['frozen_integral'];
  204. }
  205. $t = Yii::$app->db->beginTransaction();
  206. try {
  207. // 因为积分计算出当积分不足时,会只扣除剩余部分。但是转换发放又是全部。所以需要进行判断用户剩余积分是否充足。不足的话,则不执行
  208. if ($money > 0) {
  209. // 扣除冻结积分
  210. $res = ScoreExpansionWallet::setData([
  211. 'mall_id' => $mall_id,
  212. 'user_id' => $value['user_id'],
  213. 'is_frozen' => true,
  214. 'is_deduct' => true,
  215. 'integral' => -$money,
  216. 'from_type' => ScoreExpansionEnum::FROM_FROZEN_TO_ACTIVE,
  217. 'desc' => $text,
  218. ]);
  219. if ($res === false) throw new Exception('执行失败');
  220. // 转激活积分
  221. $res = ScoreExpansionWallet::setData([
  222. 'mall_id' => $mall_id,
  223. 'user_id' => $value['user_id'],
  224. 'is_frozen' => false,
  225. 'is_deduct' => true,
  226. 'integral' => $money,
  227. 'from_type' => ScoreExpansionEnum::FROM_FROZEN_TO_ACTIVE,
  228. 'desc' => $text,
  229. ]);
  230. }
  231. $t->commit();
  232. } catch (\Exception $e) {
  233. $t->rollBack();
  234. echo '冻结积分转激活积分失败,' . $e->getMessage() . ',行数:' . $e->getLine(), 'file:' . $e->getFile();
  235. }
  236. }
  237. }
  238. return true;
  239. }
  240. /**
  241. * 获取已经开启冻结积分转激活积分商城配置
  242. *
  243. * @param array $mall_ids
  244. * @return array
  245. */
  246. public static function getOpenRedpackMall(array $mall_ids)
  247. {
  248. //获取开启的商城ID
  249. $where[] = ['in', 'mall_id', $mall_ids];
  250. $where[] = ['name' => "frozen_status"];
  251. $where[] = ['value' => 1];
  252. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_SCORE_EXPANSION];
  253. $redpack_config = AddonsSetting::lists(['where' => $where], true);
  254. if ($redpack_config) {
  255. $ids = array_column($redpack_config, 'mall_id');
  256. }
  257. return $ids ?? [];
  258. }
  259. /**
  260. *
  261. * @Author: ltm
  262. * @DateTime: 2022/3/24 0024 10:51
  263. * @Copyright: copyright (c) 2021 广东七件事集团
  264. * @param $data
  265. * @return string
  266. */
  267. public static function getMallConfigtime($mall_ids)
  268. {
  269. //获取开启时间
  270. $where[] = ['in', 'mall_id', $mall_ids];
  271. $where[] = ['name' => "activation_time"];
  272. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_SCORE_EXPANSION];
  273. $redpack_config = AddonsSetting::lists(['where' => $where, 'select' => 'value,mall_id'], true);
  274. if ($redpack_config) {
  275. $list['activation_time'] = array_column($redpack_config, 'value', 'mall_id');
  276. }
  277. return $list;
  278. }
  279. /**
  280. *
  281. * @Author: ltm
  282. * @DateTime: 2022/3/24 0024 10:51
  283. * @Copyright: copyright (c) 2021 广东七件事集团
  284. * @param $data
  285. * @return array
  286. */
  287. public static function getMallConfignum($mall_ids)
  288. {
  289. //获取转换比率
  290. $where[] = ['in', 'mall_id', $mall_ids];
  291. $where[] = ['name' => "activation_num"];
  292. $where[] = ['addons_name' => AddonsEnum::ADDONS_NAME_SCORE_EXPANSION];
  293. $redpack_config = AddonsSetting::lists(['where' => $where, 'select' => 'value,mall_id'], true);
  294. $list = [];
  295. if ($redpack_config) {
  296. $list['activation_num'] = array_column($redpack_config, 'value', 'mall_id');
  297. }
  298. return $list;
  299. }
  300. /**
  301. * 订单确认收货但未完成评价,n天后,扣减冻结积分 + 到激活积分
  302. */
  303. public static function carryOutAppraiseSetting($mall_ids)
  304. {
  305. //查询定时任务表查看未执行的任务
  306. //Order
  307. $orderSource = Order::tableName();
  308. $orderTaskList = ScoreExpansionRateTask::find()->where(['is_work' => 0,'source_table'=>$orderSource])->indexBy('order_id')->orderBy(['id' => SORT_DESC])->asArray()->all();
  309. $orderIds = array_column($orderTaskList, 'order_id');
  310. $order_select = "id,mall_id,is_comment,sign_time,user_id";
  311. //StoreOrder
  312. if (class_exists(StoreOrder::class)) {
  313. $storeOrderSource = StoreOrder::tableName();
  314. $storeOrderTaskList = ScoreExpansionRateTask::find()->where(['is_work' => 0,'source_table'=>$storeOrderSource])->indexBy('order_id')->orderBy(['id' => SORT_DESC])->asArray()->all();
  315. $storeOrderIds = array_column($storeOrderTaskList, 'order_id');
  316. }
  317. //获取配置
  318. foreach ($mall_ids as $mall_id) {
  319. $service = new SettingService(['mall_id' => $mall_id]);
  320. $config = $service->getSetting();
  321. if ($config['change_activation_integral'] != 0) continue;
  322. $time_limit = $config['time_limit'] ?? 0;//超过这个时间限制将扣除积分
  323. //查询所有订单商品表判断是否评价
  324. $orderList = Order::find()->select($order_select)
  325. ->where(['in', 'id', $orderIds])
  326. ->andWhere(['mall_id' => $mall_id])
  327. ->andWhere(['in', 'order_status', [3, 4]])//3已收货 4已完成
  328. // ->andWhere(['is_comment' => 0])//订单评价
  329. ->orderBy(['id' => SORT_DESC])
  330. ->asArray()
  331. ->all();
  332. foreach ($orderList as $order) {
  333. //拿到商品计算价格
  334. //20230406-------
  335. $source_table = $orderTaskList[$order['id']]['source_table'];
  336. $log_list = ScoreExpansionWalletLog::find()
  337. ->where(['integral_wallet_type' => ScoreExpansionEnum::WALLET_INTEGRAL_FROZEN, 'source_table_id' => $order['id'], 'change_type' => 'add','source_table'=>$source_table])
  338. ->asArray()
  339. ->all();
  340. if (empty($log_list)) continue;
  341. foreach ($log_list as $item) {
  342. // 计算可赠送的红包金额
  343. $money = $item['change_num'];
  344. if ($money <= 0) continue;
  345. //判断冻结积分是否足够
  346. $thisWallet = ScoreExpansionWallet::findOne(['mall_id' => $item['mall_id'], 'user_id' => $item['user_id']]);
  347. if (empty($thisWallet) || $thisWallet->frozen_integral <= $money) {
  348. continue;
  349. }
  350. if ($item['integral_wallet_type'] == ScoreExpansionEnum::WALLET_INTEGRAL_FROZEN) {
  351. //判断当前时间 大于扣减
  352. $end_time = $order['sign_time'] + ($time_limit * 1 * 24 * 60 * 60);
  353. $time = time();
  354. if ($time >= $end_time) {
  355. //扣减冻结积分
  356. $activationWallet = ScoreExpansionWallet::setData([
  357. 'mall_id' => $item['mall_id'],
  358. 'user_id' => $item['user_id'],
  359. 'is_frozen' => true,
  360. 'integral' => -$money,
  361. 'source_table' => Order::tableName(),
  362. 'source_table_id' => $order['id'],
  363. 'from_type' => ScoreExpansionEnum::FROM_GOODS_REVIEWS,
  364. 'desc' => '未在规定时间内完成评价,自动转换扣减冻结积分',
  365. ]);
  366. if ($activationWallet == false) throw new Exception(ScoreExpansionWallet::getStaticError());
  367. //---
  368. // 增加激活积分
  369. $frozenWallet = ScoreExpansionWallet::setData([
  370. 'mall_id' => $item['mall_id'],
  371. 'user_id' => $item['user_id'],
  372. 'is_frozen' => false,
  373. 'integral' => $money,
  374. 'source_table' => Order::tableName(),
  375. 'source_table_id' => $order['id'],
  376. 'from_type' => ScoreExpansionEnum::FROM_GOODS_REVIEWS,
  377. 'desc' => '未在规定时间内完成评价,自动转换增加激活积分',
  378. ]);
  379. if ($frozenWallet == false) throw new Exception(ScoreExpansionWallet::getStaticError());
  380. //---
  381. //修改定时任务状态
  382. $task = ScoreExpansionRateTask::findOne(['order_id' => $order['id'],'source_table'=>$source_table]);
  383. $task->is_work = 1;
  384. if (!$task->save()) {
  385. throw new Exception(ScoreExpansionRateTask::getStaticError());
  386. }
  387. }
  388. }
  389. }
  390. }
  391. if(!empty($storeOrderIds)){
  392. $storeOrderList = StoreOrder::find()->select($order_select)
  393. ->where(['in', 'id', $storeOrderIds])
  394. ->andWhere(['mall_id' => $mall_id])
  395. ->andWhere(['in', 'order_status', [3, 4]])//3已收货 4已完成
  396. // ->andWhere(['is_comment' => 0])//订单评价
  397. ->orderBy(['id' => SORT_DESC])
  398. ->asArray()
  399. ->all();
  400. if(!empty($storeOrderList)){
  401. foreach ($storeOrderList as $storeOrder) {
  402. //拿到商品计算价格
  403. //20230406-------
  404. $source_table = $storeOrderTaskList[$storeOrder['id']]['source_table'];
  405. $log_list = ScoreExpansionWalletLog::find()
  406. ->where(['integral_wallet_type' => ScoreExpansionEnum::WALLET_INTEGRAL_FROZEN, 'source_table_id' => $storeOrder['id'], 'change_type' => 'add','source_table'=>$source_table])
  407. ->asArray()
  408. ->all();
  409. if (empty($log_list)) continue;
  410. foreach ($log_list as $item) {
  411. // 计算可赠送的红包金额
  412. $money = $item['change_num'];
  413. if ($money <= 0) continue;
  414. //判断冻结积分是否足够
  415. $thisWallet = ScoreExpansionWallet::findOne(['mall_id' => $item['mall_id'], 'user_id' => $item['user_id']]);
  416. if (empty($thisWallet) || $thisWallet->frozen_integral <= $money) {
  417. continue;
  418. }
  419. if ($item['integral_wallet_type'] == ScoreExpansionEnum::WALLET_INTEGRAL_FROZEN) {
  420. //判断当前时间 大于扣减
  421. $end_time = $storeOrder['sign_time'] + ($time_limit * 1 * 24 * 60 * 60);
  422. $time = time();
  423. if ($time >= $end_time) {
  424. //扣减冻结积分
  425. $storeActivationWallet = ScoreExpansionWallet::setData([
  426. 'mall_id' => $item['mall_id'],
  427. 'user_id' => $item['user_id'],
  428. 'is_frozen' => true,
  429. 'integral' => -$money,
  430. 'source_table' => $storeOrderSource,
  431. 'source_table_id' => $storeOrder['id'],
  432. 'from_type' => ScoreExpansionEnum::FROM_GOODS_REVIEWS,
  433. 'desc' => '未在规定时间内完成评价,自动转换扣减冻结积分',
  434. ]);
  435. if ($storeActivationWallet == false) throw new Exception(ScoreExpansionWallet::getStaticError());
  436. //---
  437. // 增加激活积分
  438. $storeFrozenWallet = ScoreExpansionWallet::setData([
  439. 'mall_id' => $item['mall_id'],
  440. 'user_id' => $item['user_id'],
  441. 'is_frozen' => false,
  442. 'integral' => $money,
  443. 'source_table' => $storeOrderSource,
  444. 'source_table_id' => $storeOrder['id'],
  445. 'from_type' => ScoreExpansionEnum::FROM_GOODS_REVIEWS,
  446. 'desc' => '未在规定时间内完成评价,自动转换增加激活积分',
  447. ]);
  448. if ($storeFrozenWallet == false) throw new Exception(ScoreExpansionWallet::getStaticError());
  449. //---
  450. //修改定时任务状态
  451. $task = ScoreExpansionRateTask::findOne(['order_id' => $storeOrder['id'],'source_table'=>$source_table]);
  452. $task->is_work = 1;
  453. if (!$task->save()) {
  454. throw new Exception(ScoreExpansionRateTask::getStaticError());
  455. }
  456. }
  457. }
  458. }
  459. }
  460. }
  461. }
  462. }
  463. return true;
  464. }
  465. }