BonusSend.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: leo
  5. * Date: 2018/3/18
  6. * Time: 上午11:06
  7. */
  8. namespace common\helpers\bonus;
  9. use common\components\ActiveRecord;
  10. use common\helpers\DataBak;
  11. use common\helpers\Form;
  12. use common\helpers\Tool;
  13. use common\helpers\user\Balance;
  14. use common\helpers\user\Info;
  15. use common\helpers\user\Reconsume;
  16. use common\helpers\user\Status;
  17. use common\libs\api\sms\SmsApi;
  18. use common\libs\swoole\Process;
  19. use common\models\DealType;
  20. use common\models\PerfPeriod;
  21. use common\models\DecOrder;
  22. use common\models\EmployLevel;
  23. use common\models\StarCrownLevel;
  24. use common\models\UserBonus;
  25. use common\models\UserPerfMonthUpdate;
  26. use common\models\UserPeriodPoints;
  27. use common\models\UserWallet;
  28. use common\models\UserInfo;
  29. use common\models\UserPerf;
  30. use common\models\UserPerfUpdate;
  31. use common\models\UserTeamwork;
  32. use common\models\YearHighestEmpLv;
  33. use yii\base\BaseObject;
  34. use yii\base\StaticInstanceTrait;
  35. use common\helpers\Cache;
  36. use common\helpers\Date;
  37. use common\models\CalcBonus;
  38. use common\models\CalcBonusBD;
  39. use common\models\CalcBonusBS;
  40. use common\models\CalcBonusGX;
  41. use common\models\CalcBonusQY;
  42. use common\models\CalcBonusTG;
  43. use common\models\FlowBonus;
  44. use common\models\PerfActiveUser;
  45. use common\models\PerfMonth;
  46. use common\models\User;
  47. use Yii;
  48. use common\models\Period;
  49. use yii\base\Exception;
  50. use yii\db\Expression;
  51. class BonusSend extends BaseObject {
  52. use StaticInstanceTrait;
  53. private $_limit = 1000;
  54. private $_appUserId = null;
  55. private $_sysConfig = [];
  56. private $_decLevelConfig = [];
  57. private $_empLevelConfig = [];
  58. private $_decRoleConfig = [];
  59. private $_errors = [];
  60. private $_periodNum = 0;
  61. private $_periodId;
  62. private $_isCalcMonth = 0;
  63. private $_isCalcYear = 0;
  64. private $_calcYear;
  65. private $_calcMonth;
  66. private $_calcYearMonth;
  67. private $_lastCalcYear;
  68. private $_lastCalcMonth;
  69. private $_lastCalcYearMonth;
  70. private $_workerId;
  71. private $_workerNum;
  72. public function init(int $periodNum = 0, $appUserId = null, $workerId = null, $workerNum = null) {
  73. parent::init();
  74. $this->_sysConfig = Cache::getSystemConfig();
  75. $this->_decLevelConfig = Cache::getDecLevelConfig();
  76. $this->_empLevelConfig = Cache::getEmpLevelConfig();
  77. $this->_decRoleConfig = CalcCache::getDecRoleConfig($this->_periodNum);
  78. $this->_periodNum = $periodNum;
  79. $this->_appUserId = $appUserId;
  80. $this->_workerId = $workerId;
  81. $this->_workerNum = $workerNum;
  82. }
  83. /**
  84. * 设置期数
  85. * @param int $periodNum
  86. * @return int
  87. */
  88. public function setPeriodNum(int $periodNum) {
  89. return $this->_periodNum = $periodNum;
  90. }
  91. /**
  92. * 获取期数
  93. * @return int
  94. */
  95. public function getPeriodNum() {
  96. return $this->_periodNum;
  97. }
  98. /**
  99. * 加入错误错误
  100. * @param $attr
  101. * @param $error
  102. */
  103. public function addError($attr, $error) {
  104. $this->_errors[$attr][] = $error;
  105. }
  106. /**
  107. * 获取错误信息
  108. * @return array
  109. */
  110. public function getErrors() {
  111. return $this->_errors;
  112. }
  113. /**
  114. * 进行奖金发放步骤
  115. * @return bool
  116. */
  117. public function sendStep() {
  118. try {
  119. $t1 = microtime(true);
  120. // 初始化
  121. $this->initTask();
  122. $t2 = microtime(true);
  123. echo('初始化完成,当前期数【' . $this->_periodNum . '】,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  124. // 改变状态
  125. $this->setSendStatus('start');
  126. $t3 = microtime(true);
  127. echo('改变状态完成,耗时:' . round($t3 - $t2, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  128. $this->_updatePercent(20);
  129. //Yii::$app->db->close();
  130. //Yii::$app->dbShop->close();
  131. // 更新聘级
  132. $this->updateEmpLevel();
  133. $this->_updatePercent(40);
  134. $t4 = microtime(true);
  135. echo('更新聘级完成,耗时:' . round($t4 - $t3, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  136. // 更新星级
  137. $this->updateCrownLevel();
  138. $this->_updatePercent(50);
  139. $t41 = microtime(true);
  140. echo('更新星级完成,耗时:' . round($t41 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  141. // 发放奖金
  142. $this->sendBonusLoop();
  143. $this->_updatePercent(60);
  144. $t5 = microtime(true);
  145. echo('发放奖金完成,耗时:' . round($t5 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  146. // 更新会员上次报单级别
  147. // $this->updateUserDevLv();
  148. // $this->_updatePercent(80);
  149. $t6 = microtime(true);
  150. // echo('更新会员上次报单级别完成,耗时:' . round($t6 - $t5, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  151. // 更新会员累计业绩
  152. $this->updateUserPerf();
  153. $this->_updatePercent(80);
  154. $t7 = microtime(true);
  155. echo('更新会员累计业绩完成,耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  156. $this->updateUserPerfMonth();
  157. $this->_updatePercent(90);
  158. $t8 = microtime(true);
  159. echo('更新会员累计月业绩完成,耗时:' . round($t8 - $t7, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  160. // 更新活跃用户状态,更新为已处理
  161. // $this->updateActiveUser();
  162. // $this->_updatePercent(95);
  163. // $t9 = microtime(true);
  164. // echo('更新会员累计月业绩完成,耗时:' . round($t9 - $t8, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  165. // 开启子进程去完成下面的循环发放和循环改聘级和循环更新累计业绩
  166. /*$process = new Process('sendBonus', 3);
  167. $process->run(function($workId, $pmid){
  168. $this->processStep($workId);
  169. });
  170. while (true){
  171. if($process->isFinish()) break;
  172. }
  173. unset($process);
  174. $this->_updatePercent(90);
  175. $t4 = microtime(true);
  176. echo('所有子进程的任务完成,耗时:'.round($t4 - $t3, 3).',内存使用:'.(round(memory_get_usage()/1024/1024, 3)).'MB'.PHP_EOL);*/
  177. echo('全部奖金发放完成,耗时:'.round($t7 - $t1, 3).',内存使用:'.(round(memory_get_usage()/1024/1024, 3)).'MB'.PHP_EOL);
  178. $this->_updatePercent(100);
  179. } catch (\Exception $e) {
  180. $this->addError('sendBonus', sprintf('File【%s】, Line【%s】, Msg【%s】', $e->getFile(), $e->getLine(), $e->getMessage()));
  181. return false;
  182. }
  183. if (count($this->_errors) > 0) {
  184. return false;
  185. }
  186. return true;
  187. }
  188. /**
  189. * 需要多进程执行的任务
  190. * @param $workId
  191. * @throws \yii\db\Exception
  192. */
  193. public function processStep($workId = null) {
  194. if ($workId == 1 || $workId === null) {
  195. // 发放奖金
  196. $this->sendBonusLoop();
  197. }
  198. if ($workId == 2 || $workId === null) {
  199. // 更新聘级
  200. $this->updateEmpLevel();
  201. }
  202. if ($workId == 3 || $workId === null) {
  203. // 更新会员累计业绩
  204. $this->updateUserPerf();
  205. }
  206. Yii::$app->db->close();
  207. Yii::$app->dbShop->close();
  208. }
  209. /**
  210. * 初始化发放任务
  211. * @throws Exception
  212. */
  213. public function initTask() {
  214. $this->_errors = [];
  215. $periodNum = $this->_periodNum;
  216. // 获取传入期数的相关信息
  217. $periodObj = Period::instance();
  218. $periodDataArr = $periodObj->setPeriodNum($periodNum);
  219. $this->_periodId = $periodDataArr['ID'];
  220. $this->_isCalcMonth = $periodObj->isCalcMonth($periodNum);
  221. $this->_calcYear = $periodObj->getYear($periodNum);
  222. $this->_calcMonth = $periodObj->getMonth($periodNum);
  223. $this->_calcYearMonth = $periodObj->getYearMonth($periodNum);
  224. $lastYearMonthArr = $periodObj->getLastMonth($periodNum);
  225. $this->_lastCalcYear = $lastYearMonthArr['year'];
  226. $this->_lastCalcMonth = $lastYearMonthArr['month'];
  227. $this->_lastCalcYearMonth = $lastYearMonthArr['yearMonth'];
  228. }
  229. /**
  230. * 设置结算状态
  231. * @param $type
  232. * start|end|fail
  233. */
  234. public function setSendStatus($type) {
  235. Yii::$app->db->close();
  236. if ($type == 'start') {
  237. Period::updateAll(['IS_SENDING' => 1, 'SEND_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  238. } elseif ($type == 'end') {
  239. Period::updateAll(['IS_SENDING' => 0, 'IS_SENT' => Period::SEND_FINISH, 'SENT_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  240. } elseif ($type == 'fail') {
  241. Period::updateAll(['IS_SENDING' => 0, 'IS_SENT' => Period::SEND_FAIL, 'SENT_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  242. }
  243. }
  244. /**
  245. * 结束计算任务
  246. * @throws \yii\db\Exception
  247. */
  248. public function endTask() {
  249. CalcCache::clearAll($this->_periodNum);
  250. $this->setSendStatus('end');
  251. //@todo 先不备份数据
  252. // DataBak::backup($this->_periodNum);
  253. //发送复销短信
  254. // if ($this->_isCalcMonth && $this->_sysConfig['smsOpen']['VALUE']) {
  255. // $this->sendSmsLoop();
  256. // }
  257. }
  258. /**
  259. * 出现错误
  260. */
  261. public function errorTask() {
  262. $this->setSendStatus('fail');
  263. }
  264. /**
  265. * 发放奖金
  266. * @param int $page
  267. * @return bool
  268. * @throws \yii\db\Exception
  269. */
  270. public function sendBonusLoop($page=1) {
  271. echo sprintf("时间:[%s]数据库发奖,当前page为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()), $page);
  272. $periodNum = $this->_periodNum;
  273. // 从奖金结算表中获取当期未发放的所有数据
  274. $allData = CalcBonus::findUseDbCalc()
  275. ->yearMonth($this->_calcYearMonth)
  276. ->where(
  277. '(IS_SENT=0 OR IS_SENT=2) AND CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM',
  278. [':CALC_MONTH' => $this->_calcYearMonth, ':PERIOD_NUM' => $periodNum]
  279. )
  280. ->limit($this->_limit)
  281. ->asArray()
  282. ->all();
  283. if ($allData) {
  284. $transaction = Yii::$app->db->beginTransaction();
  285. try {
  286. foreach ($allData as $key => $data) {
  287. // 期奖金
  288. // $periodAmount = $data['BONUS_QY'] + $data['BONUS_YC'] + $data['BONUS_XF'] + $data['BONUS_BD'] + $data['BONUS_TG'] + $data['BONUS_YJ'] + $data['BONUS_GX'] + $data['BONUS_GL'];
  289. $periodAmount = $data['BONUS_REAL'];
  290. // 获取本期结算的管理员
  291. // $period = Period::findOneAsArray(['PERIOD_NUM'=>$periodNum]);
  292. // $updateAminId = $period['CALC_ADMIN_ID'];
  293. if ($periodAmount > 0) {
  294. Balance::changeUserBonus($data['USER_ID'], 'bonus', $periodAmount, [
  295. 'CALC_ID' => $data['ID'],
  296. 'REMARK' => 'From Period ' . $periodNum,
  297. 'PERIOD_NUM' => $periodNum,
  298. 'QY' => $data['BONUS_QY'],
  299. 'FW' => $data['BONUS_FW'],
  300. 'YC' => $data['BONUS_YC'],
  301. 'VIP' => $data['BONUS_VIP'],
  302. 'BD' => $data['BONUS_BD'],
  303. 'TG' => $data['BONUS_TG'],
  304. 'YJ' => $data['BONUS_YJ'],
  305. 'GX' => $data['BONUS_GX'],
  306. 'GL' => $data['BONUS_GL'],
  307. 'BS' => $data['BONUS_BS'],
  308. 'BS_MNT' => $data['BONUS_BS_MNT'],
  309. 'BS_ABBR' => $data['BONUS_BS_ABBR'],
  310. 'ORI_QY' => $data['ORI_BONUS_QY'],
  311. 'ORI_YC' => $data['ORI_BONUS_YC'],
  312. 'ORI_VIP' => $data['ORI_BONUS_VIP'],
  313. 'ORI_STANDARD' => $data['ORI_BONUS_STANDARD'],
  314. 'ORI_BD' => $data['ORI_BONUS_BD'],
  315. 'ORI_TG' => $data['ORI_BONUS_TG'],
  316. 'ORI_YJ' => $data['ORI_BONUS_YJ'],
  317. 'ORI_GX' => $data['ORI_BONUS_GX'],
  318. 'ORI_GL' => $data['ORI_BONUS_GL'],
  319. 'ORI_BS' => $data['ORI_BONUS_BS'],
  320. 'ORI_BS_MNT' => $data['ORI_BONUS_BS_MNT'],
  321. 'ORI_BS_ABBR' => $data['ORI_BONUS_BS_ABBR'],
  322. 'RECONSUME_POINTS_TOTAL' => $data['RECONSUME_POINTS'],
  323. 'EXCHANGE_POINTS_TOTAL' => $data['EXCHANGE_POINTS'],
  324. 'MANAGE_TAX' => $data['MANAGE_TAX'],
  325. 'BONUS_TOTAL' => $data['BONUS_TOTAL'],
  326. 'DEAL_TYPE_ID' => DealType::BONUS_SEND,
  327. 'SORT' => $key * 10,
  328. 'BONUS_ISSUE' => true,
  329. ]);
  330. // $this->_teamworkBonus($data['USER_ID'], $periodAmount, $key);
  331. }
  332. // 旅游奖
  333. if ($data['BONUS_TOURISM'] > 0) {
  334. Balance::changeUserBonus($data['USER_ID'], 'tourism_points', $data['BONUS_TOURISM'], [
  335. 'CALC_ID' => $data['ID'],
  336. 'REMARK' => 'From Period ' . $periodNum,
  337. 'PERIOD_NUM' => $periodNum,
  338. 'TOURISM_POINTS' => $data['BONUS_TOURISM'],
  339. 'DEAL_TYPE_ID' => DealType::TOURISM_SEND,
  340. 'SORT' => $key * 10,
  341. 'BONUS_ISSUE' => true,
  342. ]);
  343. }
  344. // 车奖
  345. if ($data['BONUS_GARAGE'] > 0) {
  346. Balance::changeUserBonus($data['USER_ID'], 'garage_points', $data['BONUS_GARAGE'], [
  347. 'CALC_ID' => $data['ID'],
  348. 'REMARK' => 'From Period ' . $periodNum,
  349. 'PERIOD_NUM' => $periodNum,
  350. 'GARAGE_POINTS' => $data['BONUS_GARAGE'],
  351. 'DEAL_TYPE_ID' => DealType::GARAGE_SEND,
  352. 'SORT' => $key * 10,
  353. 'BONUS_ISSUE' => true,
  354. ]);
  355. }
  356. // 房奖
  357. if ($data['BONUS_VILLA'] > 0) {
  358. Balance::changeUserBonus($data['USER_ID'], 'villa_points', $data['BONUS_VILLA'], [
  359. 'CALC_ID' => $data['ID'],
  360. 'REMARK' => 'From Period ' . $periodNum,
  361. 'PERIOD_NUM' => $periodNum,
  362. 'VILLA_POINTS' => $data['BONUS_VILLA'],
  363. 'DEAL_TYPE_ID' => DealType::VILLA_SEND,
  364. 'SORT' => $key * 10,
  365. 'BONUS_ISSUE' => true,
  366. ]);
  367. }
  368. //发放重消积分
  369. // if ($data['RECONSUME_POINTS'] > 0) {
  370. // Balance::changeUserBonus($data['USER_ID'], 'reconsume_points', $data['RECONSUME_POINTS'], [
  371. // 'CALC_ID' => $data['ID'],
  372. // 'REMARK' => 'From ' . $periodNum . '期',
  373. // 'PERIOD_NUM' => $periodNum,
  374. // 'RECONSUME_POINTS' => $data['RECONSUME_POINTS'],
  375. // 'DEAL_TYPE_ID' => DealType::RECONSUME_POINTS_SEND,
  376. // ]);
  377. // }
  378. //
  379. // //发放兑换积分
  380. // if ($data['EXCHANGE_POINTS'] > 0) {
  381. // Balance::changeUserBonus($data['USER_ID'], 'exchange_points', $data['EXCHANGE_POINTS'], [
  382. // 'CALC_ID' => $data['ID'],
  383. // 'REMARK' => 'From ' . $periodNum . '期',
  384. // 'PERIOD_NUM' => $periodNum,
  385. // 'EXCHANGE_POINTS' => $data['EXCHANGE_POINTS'],
  386. // 'DEAL_TYPE_ID' => DealType::EXCHANGE_POINTS_SEND,
  387. // 'BONUS_ISSUE' => true,
  388. // ]);
  389. // }
  390. // 把记录标记为已发放状态
  391. CalcBonus::updateAll(['IS_SENT' => 1, 'SENT_AT' => Date::nowTime()], 'ID=:ID', [':ID' => $data['ID']]);
  392. unset($periodAmount, $key, $data);
  393. }
  394. $transaction->commit();
  395. } catch (Exception $e) {
  396. $transaction->rollBack();
  397. $this->addError('sendBonus', '奖金发放失败,原因:' . $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage());
  398. return false;
  399. }
  400. unset($allData, $transaction);
  401. $page++;
  402. return $this->sendBonusLoop($page);
  403. }
  404. unset($allData);
  405. return true;
  406. }
  407. /**
  408. * 蓝星奖金(即新的管理奖),更新会员聘级
  409. * @param int $offset
  410. * @return bool
  411. * @throws \yii\db\Exception
  412. */
  413. public function updateEmpLevel(int $offset = 0) {
  414. if ($this->_isCalcMonth) {
  415. $empLv = EmployLevel::getIdConvertLevelSortCache();
  416. $allData = CalcBonus::findUseDbCalc()
  417. ->yearMonth($this->_calcYearMonth)
  418. ->where(
  419. 'CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM',
  420. [
  421. ':CALC_MONTH' => $this->_calcYearMonth,
  422. ':PERIOD_NUM' =>$this->_periodNum
  423. ]
  424. )
  425. ->orderBy('CREATED_AT DESC')
  426. ->offset($offset)
  427. ->limit($this->_limit)
  428. ->all();
  429. //@todo 用户级别不变则不更新
  430. $defaultEmpLv = EmployLevel::getDefaultLevelId();
  431. if ($allData) {
  432. $transaction = Yii::$app->db->beginTransaction();
  433. try {
  434. foreach ($allData as $data) {
  435. //@todo 用户级别不变则不更新
  436. if( $data['LAST_EMP_LV'] === $defaultEmpLv ) continue;
  437. $nowBsEmpLv = $data['LAST_EMP_LV']; // 当前蓝星奖计算(即管理奖) 的等级
  438. $user = CalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
  439. $userEmpLv = $user['EMP_LV']; // 用户的历史最高聘级
  440. $userEmpLvSort = $empLv[$userEmpLv]; // 历史最高聘级的 级别值
  441. $nowBsEmpLvSort = $empLv[$nowBsEmpLv]; // 当前蓝星计算的聘级 级别值
  442. if ($nowBsEmpLvSort > $userEmpLvSort) {
  443. // 如果当前期的级别值大于历史最高级别,则更新用户表里的最高聘级
  444. User::updateAll(['EMP_LV' => $nowBsEmpLv], 'ID=:USER_ID', [':USER_ID' => $data['USER_ID']]);
  445. User::deleteBaseInfoFromRedis($data['USER_ID']);
  446. unset($data);
  447. } else {
  448. continue;
  449. }
  450. }
  451. $transaction->commit();
  452. } catch (Exception $e) {
  453. $transaction->rollBack();
  454. $this->addError('updateEmpLevel', '更新聘级失败,原因:' . $e->getMessage());
  455. return false;
  456. }
  457. unset($transaction, $allData, $defaultEmpLv);
  458. return $this->updateEmpLevel($offset + $this->_limit);
  459. }
  460. unset($allData);
  461. }
  462. return true;
  463. }
  464. /**
  465. * 更新用户星级
  466. * @param int $offset
  467. * @return bool
  468. */
  469. public function updateCrownLevel(int $offset = 0)
  470. {
  471. $allData = CalcBonusQY::findUseDbCalc()
  472. ->yearMonth($this->_calcYearMonth)
  473. ->where(
  474. 'CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM',
  475. [
  476. ':CALC_MONTH' => $this->_calcYearMonth,
  477. ':PERIOD_NUM' =>$this->_periodNum
  478. ]
  479. )
  480. ->orderBy('CREATED_AT DESC')
  481. ->groupBy('USER_ID')
  482. ->offset($offset)
  483. ->limit($this->_limit)
  484. ->all();
  485. if ($allData) {
  486. $transaction = Yii::$app->db->beginTransaction();
  487. try {
  488. foreach ($allData as $data) {
  489. User::updateAll(['CROWN_LV' => $data['LAST_CROWN_LV']], 'ID = :USER_ID', [':USER_ID' => $data['USER_ID']]);
  490. User::deleteBaseInfoFromRedis($data['USER_ID']);
  491. unset($data);
  492. }
  493. $transaction->commit();
  494. } catch (Exception $e) {
  495. $transaction->rollBack();
  496. $this->addError('updateStarCrownLevel', '更新星级失败,原因:' . $e->getMessage());
  497. return false;
  498. }
  499. unset($transaction, $allData);
  500. return $this->updateCrownLevel($offset + $this->_limit);
  501. }
  502. unset($allData);
  503. return true;
  504. }
  505. // /**
  506. // * 更新会员聘级
  507. // * @param int $offset
  508. // * @return bool
  509. // * @throws \yii\db\Exception
  510. // */
  511. // public function updateEmpLevel(int $offset = 0) {
  512. // if ($this->_isCalcMonth) {
  513. // $allData = PerfMonth::findUseDbCalc()->yearMonth($this->_calcYearMonth)->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->offset($offset)->limit($this->_limit)->all();
  514. // //@todo 用户级别不变则不更新
  515. // $defaultEmpLv = EmployLevel::getDefaultLevelId();
  516. // if ($allData) {
  517. // $transaction = Yii::$app->db->beginTransaction();
  518. // try {
  519. // foreach ($allData as $data) {
  520. // //@todo 用户级别不变则不更新
  521. // if( $data['LAST_EMP_LV'] === $defaultEmpLv ) continue;
  522. // User::updateAll(['EMP_LV' => $data['LAST_EMP_LV']], 'ID=:USER_ID', [':USER_ID' => $data['USER_ID']]);
  523. // User::deleteBaseInfoFromRedis($data['USER_ID']);
  524. // unset($data);
  525. // }
  526. // $transaction->commit();
  527. // } catch (Exception $e) {
  528. // $transaction->rollBack();
  529. // $this->addError('updateEmpLevel', '更新聘级失败,原因:' . $e->getMessage());
  530. // return false;
  531. // }
  532. // unset($transaction, $allData, $defaultEmpLv);
  533. // return $this->updateEmpLevel($offset + $this->_limit);
  534. // }
  535. // unset($allData);
  536. // }
  537. // return true;
  538. // }
  539. // 更活跃会员,将is_send改成1
  540. public function updateActiveUser() {
  541. try {
  542. $ret = PerfActiveUser::updateAll(
  543. ['IS_SENT' => 1],
  544. 'PERIOD_NUM=:PERIOD_NUM AND IS_SENT=:IS_SENT',
  545. ['IS_SENT'=>0, 'PERIOD_NUM'=>$this->_periodNum]
  546. );
  547. return $ret;
  548. } catch(Exception $e) {
  549. $this->addError('updateActiveUser', '更新活跃会员业绩期处理状态失败,原因:' . $e->getMessage());
  550. return false;
  551. }
  552. }
  553. /**
  554. * 更新会员的累计业绩
  555. * @param int $offset
  556. * @return bool
  557. * @throws \yii\db\Exception
  558. */
  559. public function updateUserPerf(int $offset = 0) {
  560. $allData = PerfPeriod::findUseDbCalc()->yearMonth($this->_calcYearMonth)->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum])->orderBy('ID ASC')->offset($offset)->limit($this->_limit)->all();
  561. if ($allData) {
  562. $transaction = Yii::$app->db->beginTransaction();
  563. try {
  564. foreach ($allData as $data) {
  565. $isUpdate = false;
  566. if (UserPerf::findUseDbCalc()->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) {
  567. // 判断本期是否已经更新过业绩
  568. if (!UserPerfUpdate::findUseDbCalc()->yearMonth($this->_calcYearMonth)->where('USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum])->exists()) {
  569. $isUpdate = true;
  570. // 更新业绩
  571. UserPerf::updateAll([
  572. 'PV_PCS_ZC' => new Expression('PV_PCS_ZC+' . $data['PV_PCS_ZC']),
  573. 'PV_PCS_YH' => new Expression('PV_PCS_YH+' . $data['PV_PCS_YH']),
  574. 'PV_PCS_ZG' => new Expression('PV_PCS_ZG+' . $data['PV_PCS_ZG']),
  575. 'PV_PCS_LS' => new Expression('PV_PCS_LS+' . $data['PV_PCS_LS']),
  576. 'PV_PCS_FX' => new Expression('PV_PCS_FX+' . $data['PV_PCS_FX']),
  577. 'PV_PSS' => new Expression('PV_PSS+' . $data['PV_PSS']),
  578. 'PV_PSS_TOTAL' => new Expression('PV_PSS_TOTAL+' . $data['PV_PSS']),
  579. 'PV_1L' => new Expression('PV_1L+' . $data['PV_1L']),
  580. 'PV_2L' => new Expression('PV_2L+' . $data['PV_2L']),
  581. 'PV_3L' => new Expression('PV_3L+' . $data['PV_3L']),
  582. 'PV_4L' => new Expression('PV_4L+' . $data['PV_4L']),
  583. 'PV_5L' => new Expression('PV_5L+' . $data['PV_5L']),
  584. 'SURPLUS_1L' => $data['SURPLUS_1L'],
  585. 'SURPLUS_2L' => $data['SURPLUS_2L'],
  586. 'SURPLUS_3L' => $data['SURPLUS_3L'],
  587. 'SURPLUS_4L' => $data['SURPLUS_4L'],
  588. 'SURPLUS_5L' => $data['SURPLUS_5L'],
  589. 'SURPLUS_1L_ZC' => $data['SURPLUS_1L_ZC'],
  590. 'SURPLUS_2L_ZC' => $data['SURPLUS_2L_ZC'],
  591. 'SURPLUS_3L_ZC' => $data['SURPLUS_3L_ZC'],
  592. 'SURPLUS_4L_ZC' => $data['SURPLUS_4L_ZC'],
  593. 'SURPLUS_5L_ZC' => $data['SURPLUS_5L_ZC'],
  594. 'SURPLUS_1L_FX' => $data['SURPLUS_1L_FX'],
  595. 'SURPLUS_2L_FX' => $data['SURPLUS_2L_FX'],
  596. 'SURPLUS_3L_FX' => $data['SURPLUS_3L_FX'],
  597. 'SURPLUS_4L_FX' => $data['SURPLUS_4L_FX'],
  598. 'SURPLUS_5L_FX' => $data['SURPLUS_5L_FX'],
  599. ], 'USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']]);
  600. }
  601. } else {
  602. $isUpdate = true;
  603. UserPerf::insertOne([
  604. 'USER_ID' => $data['USER_ID'],
  605. 'PV_PCS_ZC' => $data['PV_PCS_ZC'],
  606. 'PV_PCS_YH' => $data['PV_PCS_YH'],
  607. 'PV_PCS_ZG' => $data['PV_PCS_ZG'],
  608. 'PV_PCS_LS' => $data['PV_PCS_LS'],
  609. 'PV_PCS_FX' => $data['PV_PCS_FX'],
  610. 'PV_PSS' => $data['PV_PSS'],
  611. 'PV_PSS_TOTAL' => $data['PV_PSS'],
  612. 'PV_1L' => $data['PV_1L'],
  613. 'PV_2L' => $data['PV_2L'],
  614. 'PV_3L' => $data['PV_3L'],
  615. 'PV_4L' => $data['PV_4L'],
  616. 'PV_5L' => $data['PV_5L'],
  617. 'SURPLUS_1L' => $data['SURPLUS_1L'],
  618. 'SURPLUS_2L' => $data['SURPLUS_2L'],
  619. 'SURPLUS_3L' => $data['SURPLUS_3L'],
  620. 'SURPLUS_4L' => $data['SURPLUS_4L'],
  621. 'SURPLUS_5L' => $data['SURPLUS_5L'],
  622. 'SURPLUS_1L_ZC' => $data['SURPLUS_1L_ZC'],
  623. 'SURPLUS_2L_ZC' => $data['SURPLUS_2L_ZC'],
  624. 'SURPLUS_3L_ZC' => $data['SURPLUS_3L_ZC'],
  625. 'SURPLUS_4L_ZC' => $data['SURPLUS_4L_ZC'],
  626. 'SURPLUS_5L_ZC' => $data['SURPLUS_5L_ZC'],
  627. 'SURPLUS_1L_FX' => $data['SURPLUS_1L_FX'],
  628. 'SURPLUS_2L_FX' => $data['SURPLUS_2L_FX'],
  629. 'SURPLUS_3L_FX' => $data['SURPLUS_3L_FX'],
  630. 'SURPLUS_4L_FX' => $data['SURPLUS_4L_FX'],
  631. 'SURPLUS_5L_FX' => $data['SURPLUS_5L_FX'],
  632. 'CREATED_AT' => Date::nowTime(),
  633. ]);
  634. }
  635. if ($isUpdate) {
  636. // 变为已更新
  637. UserPerfUpdate::insertOne(['USER_ID' => $data['USER_ID'], 'PERIOD_NUM' => $this->_periodNum, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime()]);
  638. }
  639. unset($data, $isUpdate);
  640. }
  641. $transaction->commit();
  642. } catch (Exception $e) {
  643. $transaction->rollBack();
  644. $this->addError('updateUserPerf', '更新会员业绩失败,原因:' . $e->getMessage());
  645. return false;
  646. }
  647. unset($allData, $transaction);
  648. return $this->updateUserPerf($offset + $this->_limit);
  649. }
  650. unset($allData);
  651. return true;
  652. }
  653. /**
  654. * 更新会员的月剩余业绩
  655. * @param int $offset
  656. * @return bool
  657. * @throws \yii\db\Exception
  658. */
  659. public function updateUserPerfMonth(int $offset = 0) {
  660. // 月结,如果不是月结点,则直接退出
  661. if (!$this->_isCalcMonth) {
  662. return true;
  663. }
  664. $allData = PerfMonth::findUseDbCalc()->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->orderBy('ID ASC')->offset($offset)->limit($this->_limit)->all();
  665. if ($allData) {
  666. $transaction = Yii::$app->db->beginTransaction();
  667. try {
  668. foreach ($allData as $data) {
  669. $isUpdate = false;
  670. if (UserPerf::findUseDbCalc()->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) {
  671. // 判断本期是否已经更新过业绩
  672. if (!UserPerfMonthUpdate::findUseDbCalc()->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $data['USER_ID'], ':CALC_MONTH' => $this->_calcYearMonth])->exists()) {
  673. $isUpdate = true;
  674. // 更新业绩
  675. UserPerf::updateAll([
  676. 'VIP_SURPLUS_1L_ZC' => $data['VIP_SURPLUS_1L_ZC'],
  677. 'VIP_SURPLUS_2L_ZC' => $data['VIP_SURPLUS_2L_ZC'],
  678. 'VIP_SURPLUS_3L_ZC' => $data['VIP_SURPLUS_3L_ZC'],
  679. 'VIP_SURPLUS_4L_ZC' => $data['VIP_SURPLUS_4L_ZC'],
  680. 'VIP_SURPLUS_5L_ZC' => $data['VIP_SURPLUS_5L_ZC']
  681. ], 'USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']]);
  682. }
  683. } else {
  684. $isUpdate = true;
  685. UserPerf::insertOne([
  686. 'USER_ID' => $data['USER_ID'],
  687. 'VIP_SURPLUS_1L_ZC' => $data['VIP_SURPLUS_1L_ZC'],
  688. 'VIP_SURPLUS_2L_ZC' => $data['VIP_SURPLUS_2L_ZC'],
  689. 'VIP_SURPLUS_3L_ZC' => $data['VIP_SURPLUS_3L_ZC'],
  690. 'VIP_SURPLUS_4L_ZC' => $data['VIP_SURPLUS_4L_ZC'],
  691. 'VIP_SURPLUS_5L_ZC' => $data['VIP_SURPLUS_5L_ZC'],
  692. 'CREATED_AT' => Date::nowTime(),
  693. ]);
  694. }
  695. if ($isUpdate) {
  696. // 变为已更新
  697. UserPerfMonthUpdate::insertOne(['USER_ID' => $data['USER_ID'], 'CALC_MONTH' => $this->_calcYearMonth, 'CREATED_AT' => Date::nowTime()]);
  698. }
  699. unset($data, $isUpdate);
  700. }
  701. $transaction->commit();
  702. } catch (Exception $e) {
  703. $transaction->rollBack();
  704. $this->addError('updateUserPerf', '更新会员月业绩失败,原因:' . $e->getMessage());
  705. return false;
  706. }
  707. unset($allData, $transaction);
  708. return $this->updateUserPerfMonth($offset + $this->_limit);
  709. }
  710. unset($allData);
  711. return true;
  712. }
  713. /**
  714. * 检测复消积分是否过期
  715. * @return bool
  716. * @throws \yii\db\Exception
  717. */
  718. public function checkReconsumePointsExpired(int $offset = 0) {
  719. $periodNum = $this->_periodNum;
  720. //一期为7天,那么365天为52.14即53期
  721. $expiredPeriodNum = $periodNum - 53;
  722. if( $expiredPeriodNum <= 0 ) return true;
  723. //查询需要过期的期数
  724. $allData = UserPeriodPoints::find()->select('ID,USER_ID,REMAINDER_POINTS')->where('PERIOD_NUM<=:PERIOD_NUM AND EXPIRED=0', ['PERIOD_NUM'=>$expiredPeriodNum])->orderBy('ID ASC')->offset($offset)->limit($this->_limit)->asArray()->all();
  725. if( $allData ) {
  726. $transaction = Yii::$app->db->beginTransaction();
  727. try{
  728. //扣除钱包的复消积分
  729. foreach ($allData as $everyData) {
  730. //过期
  731. UserPeriodPoints::updateAll([
  732. 'REMAINDER_POINTS' => 0,
  733. 'EXPIRED' => 1,
  734. 'EXPIRED_PERIOD' => $periodNum,
  735. 'EXPIRED_AT' => Date::nowTime(),
  736. ], 'ID=:ID', ['ID'=>$everyData['ID']]);
  737. if( !isset($everyData['REMAINDER_POINTS']) || !$everyData['REMAINDER_POINTS'] ) continue;
  738. UserBonus::updateAllCounters([
  739. 'RECONSUME_POINTS' => (-1) * $everyData['REMAINDER_POINTS'],
  740. ], 'USER_ID=:USER_ID', $everyData['USER_ID']);
  741. unset($everyData);
  742. }
  743. unset($periodNum, $expiredPeriodNum, $allData);
  744. $transaction->commit();
  745. }catch (\Exception $e){
  746. $transaction->rollBack();
  747. $this->addError('checkReconsumePointsExpired', '检测过期在复消积分失败,原因:' . $e->getMessage());
  748. return false;
  749. }
  750. return $this->checkReconsumePointsExpired($offset + $this->_limit);
  751. }
  752. unset($allData);
  753. return true;
  754. }
  755. /**
  756. * 更新会员上次报单级别
  757. * @return bool
  758. */
  759. public function updateUserDevLv() {
  760. $transaction = Yii::$app->dbShop->beginTransaction();
  761. try {
  762. \Yii::$app->dbShop->createCommand()->update(User::tableName(), ['LAST_DEC_LV' => new Expression('DEC_LV'), 'LAST_DEC_LV_UPDATED_AT' => Date::nowTime(), 'LAST_DEC_LV_UPDATED_PERIOD' => $this->_periodNum], 'LAST_DEC_LV!=DEC_LV')->execute();
  763. $transaction->commit();
  764. } catch (Exception $e) {
  765. $transaction->rollBack();
  766. $this->addError('updateUserDevLv', '更新会员上次报单级别失败,原因:' . $e->getMessage());
  767. return false;
  768. }
  769. return true;
  770. }
  771. /**
  772. * 给商城会员增加货款
  773. * @param $userId
  774. * @param $amount
  775. * @param $remark
  776. * @throws Exception
  777. */
  778. private function _shopAddPaymentForGoods($userId, $amount, $remark) {
  779. $db = \Yii::$app->dbShop;
  780. $transaction = $db->beginTransaction();
  781. try {
  782. ActiveRecord::batchUpdate(['PAYMENT_FOR_GOODS' => new Expression('PAYMENT_FOR_GOODS+' . abs($amount))], 'USER_ID=:USER_ID', [':USER_ID' => $userId], '{{%USER_WALLET}}', 'dbShop');
  783. // 增加流水
  784. $flowInsertData[] = [
  785. 'USER_ID' => $userId,
  786. 'USER_NAME' => Cache::getUserBaseInfo($userId)['USER_NAME'],
  787. 'DEC_LV' => Cache::getUserBaseInfo($userId)['DEC_LV'],
  788. 'ORDER_SN' => null,
  789. 'AMOUNT' => $amount,
  790. 'CREATED_AT' => Date::nowTime(),
  791. 'PERIOD_AT' => $this->_periodNum,
  792. 'IS_INCR' => 1,
  793. 'REMARK' => $remark,
  794. 'PARTITION_DATE' => Date::ociToDate(),
  795. 'WALLET_TYPE' => 'payment_for_goods',
  796. 'FROM_TYPE' => 'incr',
  797. ];
  798. ActiveRecord::batchInsert($flowInsertData, '{{%FLOW_WALLET}}', 'dbShop');
  799. $transaction->commit();
  800. } catch (Exception $e) {
  801. $transaction->rollBack();
  802. throw new Exception($e->getMessage());
  803. }
  804. }
  805. /**
  806. * 更新百分比并发送
  807. * @param $percent
  808. */
  809. private function _updatePercent($percent) {
  810. // 把数据写入数据库中
  811. Period::updateAll(['SENT_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  812. \Yii::$app->swooleAsyncTimer->pushAsyncPercentToAdmin($percent, ['MODEL' => 'PERIOD', 'ID' => $this->_periodId, 'FIELD' => 'SENT_PERCENT']);
  813. }
  814. /**
  815. * 更新最高聘级
  816. * @param $user_id
  817. * @return bool
  818. * @throws Exception
  819. */
  820. private function _updateHighestEmpLv($user_id) {
  821. $empLv = Info::getEmpLv($user_id);
  822. $highEmpLv = Info::getHighEmpLv($user_id);
  823. $empLvSort = EmployLevel::getSortById($empLv);
  824. $empLvHighSort = EmployLevel::getSortById($highEmpLv);
  825. if ($empLvHighYear = YearHighestEmpLv::findOneAsArray('USER_ID=:USER_ID AND YEAR=:YEAR', [':USER_ID' => $user_id, ':YEAR' => $this->_calcYear], 'HIGHEST_EMP_LV_SORT')) {
  826. if ($empLvSort > $empLvHighYear['HIGHEST_EMP_LV_SORT']) {
  827. YearHighestEmpLv::updateAll(['HIGHEST_EMP_LV' => $empLv, 'HIGHEST_EMP_LV_SORT' => $empLvSort, 'HIGHEST_EMP_LV_PERIOD' => $this->_periodNum, 'UPDATED_AT' => Date::nowTime()], 'USER_ID=:USER_ID AND YEAR=:YEAR', [':USER_ID' => $user_id, ':YEAR' => $this->_calcYear]);
  828. }
  829. } else {
  830. $yearHighest = new YearHighestEmpLv();
  831. $yearHighest->USER_ID = $user_id;
  832. $yearHighest->YEAR = $this->_calcYear;
  833. $yearHighest->HIGHEST_EMP_LV = $empLv;
  834. $yearHighest->HIGHEST_EMP_LV_SORT = $empLvSort;
  835. $yearHighest->HIGHEST_EMP_LV_PERIOD = $this->_periodNum;
  836. $yearHighest->CREATED_AT = Date::nowTime();
  837. if (!$yearHighest->save()) {
  838. throw new \yii\db\Exception(Form::formatErrorsForApi($yearHighest->getErrors()));
  839. }
  840. }
  841. if ($empLvSort > $empLvHighSort) {
  842. UserInfo::updateAll(['HIGHEST_EMP_LV' => $empLv, 'HIGHEST_EMP_LV_PERIOD' => $this->_periodNum], 'USER_ID=:USER_ID', [':USER_ID' => $user_id]);
  843. //发送历史最高聘级短信
  844. if($this->_sysConfig['smsEmpOpen']['VALUE']){
  845. if(in_array($empLvSort,explode(",",$this->_sysConfig['smsEmp']['VALUE']))){
  846. $realName = Info::getUserRealNameByUserId($user_id);
  847. $empLvDate = Date::convert();
  848. $empLvName = EmployLevel::getNameById($empLv);
  849. $content = str_replace(['{%REAL_NAME%}', '{%EMP_LV_DATE%}', '{%EMP_LV%}'], [$realName, $empLvDate, $empLvName], $this->_sysConfig['smsContent']['VALUE']);
  850. $params = [
  851. 'mobiles' => Info::getUserMobileByUserId($user_id),
  852. 'content' => $content,
  853. ];
  854. SmsApi::instance()->clearError();
  855. SmsApi::instance()->goSend($params);
  856. }
  857. }
  858. return true;
  859. }
  860. return false;
  861. }
  862. /**
  863. * 点位合作奖金
  864. * @param $userId
  865. * @param $amount
  866. * @param null $type
  867. * @return bool
  868. * @throws Exception
  869. * @throws \yii\db\Exception
  870. */
  871. private function _teamworkBonus($userId, $amount, $key) {
  872. if (!$teamwork = UserTeamwork::findAllAsArray('USER_ID!=:MAIN_UID AND MAIN_UID=:MAIN_UID AND IS_DEL=0', [':MAIN_UID' => $userId], 'USER_ID,DIVIDE_PERCENT')) return false;
  873. $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum);
  874. foreach ($teamwork as $value) {
  875. $bonus = Tool::formatPrice($amount * $value['DIVIDE_PERCENT'] * 0.01);
  876. if ($bonus <= 0) continue;
  877. $toUserInfo = CalcCache::getUserInfo($value['USER_ID'], $this->_periodNum);
  878. Balance::changeUserBonus($userId, 'bonus', -abs($bonus), ['SORT' => $key*10+1, 'DEAL_TYPE_ID' => DealType::TEAMWORK_TRANSFER_OUT, 'REMARK' => 'To:' . $toUserInfo['USER_NAME'] . ' Per:' . $value['DIVIDE_PERCENT'] . '%']);
  879. Balance::changeUserBonus($value['USER_ID'], 'bonus', abs($bonus), ['SORT' => $key*10+2, 'DEAL_TYPE_ID' => DealType::TEAMWORK_TRANSFER_IN, 'REMARK' => 'From: ' . $fromUserInfo['USER_NAME'] . ' Per:' . $value['DIVIDE_PERCENT'] . '%']);
  880. }
  881. }
  882. /**
  883. * 发送短信
  884. * @param int $offset
  885. * @return bool
  886. * @throws \yii\db\Exception
  887. */
  888. public function sendSmsLoop(int $offset = 0) {
  889. $allData = UserInfo::findUseDbCalc()->select('USER_ID,ALLOW_RECONSUME_SMS_TO')->where('ALLOW_RECONSUME_SMS=1')->offset($offset)->limit($this->_limit)->all();
  890. if ($allData) {
  891. $smsWallet = explode(",", $this->_sysConfig['smsWallet']['VALUE']);
  892. $smsFee = $this->_sysConfig['smsFee']['VALUE'];
  893. //获取剩余月份
  894. $period = Period::instance();
  895. $year = $period->getYear($this->_periodNum);
  896. $monthLeft = Period::getMonthLeft($this->_periodNum);
  897. $smsFee = Tool::formatPrice($smsFee * $monthLeft);
  898. $to = Date::yearEnd();
  899. $transaction = Yii::$app->db->beginTransaction();
  900. try {
  901. foreach ($allData as $data) {
  902. $userId = $data['USER_ID'];
  903. //过期续费
  904. if ($data['ALLOW_RECONSUME_SMS_TO'] < Date::nowTime()) {
  905. foreach ($smsWallet as $item) {
  906. //1奖金钱包2现金钱包
  907. if ($item == 1) {
  908. //看余额是否充足
  909. if (Balance::getAvailableBalance($userId) < $smsFee){
  910. UserInfo::updateAll(['ALLOW_RECONSUME_SMS' => 0], 'USER_ID=:USER_ID', [':USER_ID' => $userId]);
  911. continue;
  912. };
  913. Balance::changeUserBonus($userId, 'bonus', -abs($smsFee), ['DEAL_TYPE_ID' => DealType::SMS, 'REMARK' => $year . '年复销提醒短信服务费'], false);
  914. UserInfo::updateAll(['ALLOW_RECONSUME_SMS_TO' => $to], 'USER_ID=:USER_ID', [':USER_ID' => $userId]);
  915. $data['ALLOW_RECONSUME_SMS_TO'] = $to;
  916. break;
  917. } elseif ($item == 2) {
  918. throw new Exception('不存在此方式');
  919. break;
  920. }
  921. }
  922. }
  923. if ($data['ALLOW_RECONSUME_SMS_TO'] > Date::nowTime() && $mobile = Info::getUserMobileByUserId($userId)) {
  924. $realName = Info::getUserRealNameByUserId($userId);
  925. $reconsumPool = Reconsume::getUserReconsumePool($userId);
  926. $lastRechargeDate = $reconsumPool['toRechargeDate'];
  927. $isPass = $reconsumPool['isPass'] == 1 ? '合格' : '不合格';
  928. $month = $period->getNowMonth();
  929. $content = str_replace(['{%REAL_NAME%}', '{%LAST_RECHARGE_DATE%}', '{%MONTH%}', '{%IS_PASS%}'], [$realName, $lastRechargeDate, $month, $isPass], $this->_sysConfig['smsContent']['VALUE']);
  930. //todo 发短信函数 待测试
  931. $params = [
  932. 'mobiles' => $mobile,
  933. 'content' => $content,
  934. ];
  935. SmsApi::instance()->clearError();
  936. SmsApi::instance()->goSend($params);
  937. }
  938. unset($userId,$mobile,$realName,$reconsumPool,$lastRechargeDate,$isPass,$month,$content);
  939. }
  940. $transaction->commit();
  941. } catch (Exception $e) {
  942. $transaction->rollBack();
  943. return false;
  944. }
  945. unset($data);
  946. return $this->sendSmsLoop($offset + $this->_limit);
  947. }
  948. unset($allData);
  949. return true;
  950. }
  951. }