CalcServePerfCalc.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. <?php
  2. /**
  3. */
  4. namespace common\helpers\bonus;
  5. use common\helpers\Cache;
  6. use common\helpers\Date;
  7. use common\helpers\snowflake\SnowFake;
  8. use common\models\PerfOrder;
  9. use common\models\PerfPeriod;
  10. use common\models\Period;
  11. use common\models\PerfMonth;
  12. use common\models\ServeLog;
  13. use common\models\User;
  14. use common\models\UserNetwork;
  15. use yii\base\Exception;
  16. use yii\base\StaticInstanceTrait;
  17. class CalcServePerfCalc {
  18. use StaticInstanceTrait;
  19. private $_limit = 3000;
  20. private $_companyMonthPerf = 0;
  21. private $_cfTotalPercent = 0;
  22. private $_lxTotalPercent = 0;
  23. private $_sysConfig = [];
  24. private $_decLevelConfig = [];
  25. private $_empLevelConfig = [];
  26. private $_decRoleConfig = [];
  27. private $_periodNum = 0;
  28. private $_isCalcMonth = 0;
  29. private $_calcYear;
  30. private $_calcMonth;
  31. private $_calcYearMonth;
  32. private $_lastCalcYear;
  33. private $_lastCalcMonth;
  34. private $_lastCalcYearMonth;
  35. private $_lastPeriodNum;
  36. private $_periodObj;
  37. const LOOP_FINISH = 1;
  38. const LOOP_CONTINUE = 2;
  39. const ORDER_PAY_TYPE_CASH = 'cash';
  40. const ORDER_PAY_TYPE_STACK = 'pay_stack'; // pay_stack支付方式
  41. /**
  42. * 获取期数
  43. * @return int
  44. */
  45. public function getPeriodNum() {
  46. return $this->_periodNum;
  47. }
  48. // 校验是否可进行计算
  49. public function isCalcIng($periodNum) {
  50. $periodObj = Period::instance();
  51. $periodDataArr = $periodObj->setPeriodNum($periodNum);
  52. if (empty($periodDataArr)) {
  53. return false;
  54. }
  55. if ($periodDataArr['IS_PREPARE'] != 1) {
  56. return false;
  57. }
  58. $this->_periodNum = $periodDataArr['PERIOD_NUM'];
  59. $this->_periodObj = $periodObj;
  60. return true;
  61. }
  62. /**
  63. * 累计业绩数据
  64. * @param $periodNum
  65. * @return bool
  66. */
  67. public function calcStep($periodNum = null) {
  68. try {
  69. //一、查询此业绩状态,是否能进行计算
  70. $calcIng = $this->isCalcIng($periodNum);
  71. if ($calcIng !== true) {
  72. return false;
  73. } else {
  74. // 将IS_PREPARE改成2,计算中
  75. Period::updateCalcProcess(2, $this->_periodNum);
  76. }
  77. $this->initCalcTask();
  78. // 日志----记录开始,业绩期,结算年月
  79. ServeLog::periodMonth($this->_periodNum, $this->_calcYearMonth);
  80. // 日志----记录推送过来的基础数据
  81. ServeLog::basicData($this->_periodNum, $this->_calcYearMonth);
  82. $t1 = microtime(true);
  83. //二、初始化
  84. echo '业绩期为:'.$this->_periodNum;
  85. Period::updatePercent(10, $this->_periodNum);
  86. //三、 设置结算状态
  87. $this->setCalcStatus('start', $this->_periodNum);
  88. //四、 清空所有本期结算用到的缓存
  89. CalcCache::clearAll($this->_periodNum);
  90. //五、 清空会员推荐和接点关系缓存
  91. CalcCache::clearNetCache();
  92. //六、 清空相关表数据
  93. // 日志----清除业绩表
  94. ServeLog::clearPerf($this->_periodNum, $this->_calcYearMonth);
  95. $this->clearTableData();
  96. $this->_updatePercent(15);
  97. $t2 = microtime(true);
  98. echo(date('Y-m-d H:i:s',time()).'初始化、清空缓存及相关数据表完成,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  99. //七、 添加缓存中用户数据
  100. // 日志----开始缓存用户
  101. ServeLog::noParamsLog($this->_periodNum, $this->_calcYearMonth, '缓存用户信息-开始', 400);
  102. CalcCache::addUsers($this->_periodNum);
  103. // 日志----缓存用户结束
  104. ServeLog::cacheUserTotal($this->_periodNum, $this->_calcYearMonth);
  105. $t3 = microtime(true);
  106. echo(date('Y-m-d H:i:s',time()).'计算业绩向缓存中加入用户完成,耗时:' . round($t3 - $t2, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  107. $this->_updatePercent(20);
  108. // 八、循环累计用户各项业绩数据
  109. $this->loopGrandPerf();
  110. $t4 = microtime(true);
  111. echo(date('Y-m-d H:i:s',time()).'累计用户业绩完成' . round($t4 - $t3, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  112. $this->_updatePercent(60);
  113. // 九、本期业绩入库
  114. $this->loopWriteNowPerf();
  115. $t6 = microtime(true);
  116. echo(date('Y-m-d H:i:s',time()).'本期业绩入库完成,耗时:' . round($t6 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  117. //日志----记录期业绩数据
  118. ServeLog::perfPeriodInfo($this->_periodNum, $this->_calcYearMonth);
  119. $this->_updatePercent(70);
  120. //十、计算月业绩表中的数据
  121. $this->loopCalcMonthPerfTableData();
  122. $t7 = microtime(true);
  123. echo(date('Y-m-d H:i:s',time()).'计算月业绩表中的数据完成,耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  124. $this->_updatePercent(80);
  125. //十一、本月业绩入库
  126. $this->loopWriteMonthPerf();
  127. $t8 = microtime(true);
  128. echo(date('Y-m-d H:i:s',time()).'本月业绩入库完成,耗时:' . round($t8 - $t7, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  129. //日志----记录月期业绩数据
  130. ServeLog::perfMonthInfo($this->_periodNum, $this->_calcYearMonth);
  131. $this->_updatePercent(90);
  132. //十二、期业绩表,增加是否活跃字段
  133. $this->loopUpdatePeriodActive();
  134. $t9 = microtime(true);
  135. echo(date('Y-m-d H:i:s',time()).'期业绩表活跃状态更新完成,耗时:' . round($t9 - $t8, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  136. $this->_updatePercent(100);
  137. //日志----记录期业绩表活跃多少人
  138. ServeLog::perfPeriodActive($this->_periodNum, $this->_calcYearMonth);
  139. echo(date('Y-m-d H:i:s',time()).'计算业绩业绩结算全部完成,共耗时:' . round($t9 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
  140. ServeLog::noParamsLog($this->_periodNum, $this->_calcYearMonth, '业绩计算完毕', 900);
  141. } catch (\Exception $e) {
  142. $this->errorCalcTask();
  143. var_dump($e->getMessage());
  144. return false;
  145. }
  146. $this->endCalcTask();
  147. return true;
  148. }
  149. /**
  150. * 结算完成
  151. * @return bool
  152. */
  153. public function endCalcTask() {
  154. // 更新结算状态
  155. $this->setCalcStatus('end');
  156. }
  157. /**
  158. * 结算错误
  159. */
  160. public function errorCalcTask() {
  161. // 清空所有本期结算用到的缓存
  162. CalcCache::clearAll($this->_periodNum);
  163. // 更新结算状态
  164. $this->setCalcStatus('fail');
  165. }
  166. /**
  167. * 设置生成业绩单状态
  168. * @param $type
  169. * start|end|fail
  170. */
  171. public function setCalcStatus($type, $periodNum = null) {
  172. if ($type == 'start') {
  173. Period::updateAll(['IS_PERFING' => 1, 'IS_PERFED' => Period::PERF_NONE, 'PERF_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  174. } elseif ($type == 'end') {
  175. Period::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FINISH, 'PERFED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  176. } elseif ($type == 'fail') {
  177. Period::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FAIL, 'PERFED_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  178. }
  179. }
  180. /**
  181. * 初始化结算任务
  182. * @throws \yii\db\Exception
  183. */
  184. public function initCalcTask() {
  185. try {
  186. $periodObj = Period::instance();
  187. $this->_sysConfig = Cache::getSystemConfig();
  188. $this->_decLevelConfig = Cache::getDecLevelConfig();
  189. $this->_empLevelConfig = Cache::getEmpLevelConfig();
  190. $this->_decRoleConfig = CalcCache::getDecRoleConfig($this->_periodNum);
  191. $this->_isCalcMonth = $periodObj->isCalcMonth($this->_periodNum);
  192. $this->_calcYear = $periodObj->getYear($this->_periodNum);
  193. $this->_calcMonth = $periodObj->getMonth($this->_periodNum);
  194. $this->_calcYearMonth = $periodObj->getYearMonth($this->_periodNum);
  195. } catch(Exception $e) {
  196. var_dump($e->getMessage());
  197. }
  198. }
  199. /**
  200. * 清空相关表数据
  201. */
  202. public function clearTableData() {
  203. PerfPeriod::pageDeleteAll('PERIOD_NUM='.$this->_periodNum);// 周业绩
  204. if ($this->_isCalcMonth) {
  205. PerfMonth::pageDeleteAll("CALC_MONTH='{$this->_calcYearMonth}'");// 月业绩表
  206. }
  207. }
  208. /**
  209. * 累计用户业绩
  210. * @param int $offset
  211. * @return bool
  212. * @throws \yii\db\Exception
  213. */
  214. public function loopGrandPerf($offset = 0) {
  215. $allData = PerfOrder::findUseDbCalc()
  216. ->select('ORDER_AMOUNT,DEC_TYPE,USER_ID,PV,PERIOD_NUM,DEC_USER_ID,PAY_TYPE')
  217. ->where(
  218. "PERIOD_NUM=:PERIOD_NUM",
  219. [':PERIOD_NUM' => $this->_periodNum]
  220. )
  221. ->orderBy('CREATED_AT DESC,ID DESC')
  222. ->offset($offset)
  223. ->limit($this->_limit)
  224. ->asArray()
  225. ->all();
  226. if (!empty($allData)) {
  227. foreach ($allData as $data) {
  228. // 循环累计报单业绩
  229. try{
  230. echo "开始累计用户业绩,用户ID为:".$data['USER_ID'].PHP_EOL;
  231. if ($data['DEC_TYPE'] == PerfOrder::ZC_TYPE) {
  232. // 给自己增加PCS(个人消费)
  233. CalcCache::nowPeriodPerf($data['USER_ID'], $this->_periodNum, [
  234. 'PV_PCS' => $data['PV'],
  235. 'PV_PCS_ZC' => $data['PV'],
  236. ]);
  237. // 把该会员加入到能拿到业绩的会员缓存中
  238. CalcCache::addHasPerfUsers($data['USER_ID'], $this->_periodNum);
  239. //加入到报单会员中
  240. $toInfo = CalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
  241. CalcCache::addHasBDUsers($data['USER_ID'], $this->_periodNum, [
  242. 'TO_USER_ID' => $data['USER_ID'],
  243. 'USER_ID' => $toInfo['DEC_ID'],
  244. 'DEC_ID' => $toInfo['DEC_ID'],
  245. //考虑可能会移网的情况
  246. 'REC_USER_ID' => $toInfo['REC_UID'] ?? '',
  247. 'CON_USER_ID' => $toInfo['CON_UID'] ?? '',
  248. 'DEC_AMOUNT' => $data['ORDER_AMOUNT'],
  249. 'DEC_PV' => $data['PV'],
  250. ]);
  251. // 给上追加业绩
  252. $this->loopNetworkParentDo($data['USER_ID'], function ($parent) use (&$data) {
  253. // 给上级会员追加本期业绩到缓存中
  254. CalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
  255. 'PV_' . $parent['LOCATION'] . 'L' => $data['PV'],
  256. 'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $data['PV'],
  257. 'PV_' . $parent['LOCATION'] . 'L_' . $data['DEC_TYPE'] => $data['PV'],
  258. ]);
  259. // 把该会员加入到能拿到业绩的会员缓存中
  260. CalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
  261. unset($parent);
  262. });
  263. //给推荐关系累计增加业绩
  264. $this->loopRelationParentDo($data['USER_ID'], function ($parent) use (&$data) {
  265. // 给上级会员追加本期业绩到缓存中
  266. CalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
  267. 'PV_PSS' => $data['PV'],
  268. ]);
  269. // 把该会员加入到能拿到业绩的会员缓存中
  270. CalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
  271. unset($parent);
  272. });
  273. }
  274. } catch(Exception $e) {
  275. var_dump(__LINE__,__FILE__,$e->getMessage(), $data);
  276. }
  277. // 循环累计复消业绩
  278. try{
  279. if ($data['DEC_TYPE'] == PerfOrder::FX_TYPE) {
  280. if( $data['PAY_TYPE'] === self::ORDER_PAY_TYPE_CASH || $data['PAY_TYPE'] === self::ORDER_PAY_TYPE_STACK) {
  281. $orderCashAmount = $data['ORDER_AMOUNT'];
  282. $payPv = $data['PV'] * $this->_sysConfig['cashReconsumeBonusPercent']['VALUE'] / 100;
  283. $cacheDataKey = 'PV_PCS_FX_CASH';
  284. } else {
  285. $orderCashAmount = 0;
  286. $payPv = $data['PV'];
  287. $cacheDataKey = 'PV_PCS_FX_POINT';
  288. }
  289. if( $payPv <= 0 ) continue;
  290. // 给自己增加PCS(个人消费)
  291. CalcCache::nowPeriodPerf($data['USER_ID'], $this->_periodNum, [
  292. 'FX_AMOUNT_CASH' => $orderCashAmount,
  293. 'PV_PCS' => $payPv,
  294. 'PV_PCS_FX' => $payPv,
  295. $cacheDataKey => $payPv,
  296. ]);
  297. // 把该会员加入到能拿到业绩的会员缓存中
  298. CalcCache::addHasPerfUsers($data['USER_ID'], $this->_periodNum);
  299. // 给上追加业绩
  300. $this->loopNetworkParentDo($data['USER_ID'], function ($parent) use (&$data, $payPv) {
  301. // 给上级会员追加本期业绩到缓存中
  302. CalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
  303. 'PV_' . $parent['LOCATION'] . 'L' => $payPv,
  304. 'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $payPv,
  305. 'PV_' . $parent['LOCATION'] . 'L_FX' => $payPv,
  306. ]);
  307. // 把该会员加入到能拿到业绩的会员缓存中
  308. CalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
  309. });
  310. //给推荐关系累计增加业绩
  311. $this->loopRelationParentDo($data['USER_ID'], function ($parent) use ($data, $payPv) {
  312. // 给上级会员追加本期业绩到缓存中
  313. CalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
  314. 'PV_PSS' => $payPv,
  315. ]);
  316. // 把该会员加入到能拿到业绩的会员缓存中
  317. CalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
  318. });
  319. }
  320. }catch(Exception $e) {
  321. var_dump(__LINE__,__FILE__,$e->getMessage(), $data);
  322. }
  323. }
  324. return $this->loopGrandPerf($offset + $this->_limit);
  325. }
  326. unset($allData);
  327. return true;
  328. }
  329. /**
  330. * 计算月业绩表相关的数据并写入数据库
  331. * @param int $offset
  332. * @return bool
  333. * @throws Exception
  334. * @throws \yii\db\Exception
  335. */
  336. public function loopCalcMonthPerfTableData(int $offset = 0) {
  337. if (!$this->_isCalcMonth) {
  338. return true;
  339. }
  340. echo sprintf("时间:[%s]月业绩,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
  341. $allData = PerfPeriod::findUseDbCalc()
  342. ->select('USER_ID, SUM(FX_AMOUNT_CASH) AS FX_AMOUNT_CASH_SUM,SUM(PV_PCS) AS PV_PCS_SUM,SUM(PV_PCS_FX) AS PV_PCS_FX_SUM,
  343. SUM(PV_PSS) AS PV_PSS_SUM,SUM(PV_1L) AS PV_1L_SUM,SUM(PV_2L) AS PV_2L_SUM,SUM(PV_3L) AS PV_3L_SUM,
  344. SUM(PV_4L) AS PV_4L_SUM,SUM(PV_5L) AS PV_5L_SUM,SUM(PV_1L_ZC) AS PV_1L_ZC_SUM,SUM(PV_2L_ZC) AS PV_2L_ZC_SUM,
  345. SUM(PV_3L_ZC) AS PV_3L_ZC_SUM,SUM(PV_4L_ZC) AS PV_4L_ZC_SUM,SUM(PV_5L_ZC) AS PV_5L_ZC_SUM')
  346. ->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])
  347. ->groupBy('USER_ID')
  348. ->orderBy('USER_ID DESC')
  349. ->offset($offset)
  350. ->limit($this->_limit)
  351. ->asArray()
  352. ->all();
  353. if ($allData) {
  354. // 月度业绩表
  355. foreach ($allData as $everyData) {
  356. $userId = $everyData['USER_ID'];
  357. //往期业绩
  358. $userLastPerf = CalcCache::userPerf($userId, $this->_periodNum);
  359. //本期业绩
  360. $periodPerf = CalcCache::nowPeriodPerf($userId, $this->_periodNum);
  361. $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum);
  362. $nowMonthPerf = [
  363. 'USER_ID' => $userId,
  364. 'FX_AMOUNT_CASH' => $everyData['FX_AMOUNT_CASH_SUM'],
  365. 'PV_PCS' => $everyData['PV_PCS_SUM'],
  366. 'PV_PCS_FX' => $everyData['PV_PCS_FX_SUM'],
  367. 'PV_PSS' => $everyData['PV_PSS_SUM'],
  368. 'PV_1L' => $everyData['PV_1L_SUM'],
  369. 'PV_2L' => $everyData['PV_2L_SUM'],
  370. 'PV_3L' => $everyData['PV_3L_SUM'],
  371. 'PV_4L' => $everyData['PV_4L_SUM'],
  372. 'PV_5L' => $everyData['PV_5L_SUM'],
  373. //总数据,历史+本期。不能用上月加本月,因为上月可能没业绩,上上个月有业绩。
  374. 'PV_1L_TOTAL' => $periodPerf['PV_1L'] + $userLastPerf['PV_1L'],
  375. 'PV_2L_TOTAL' => $periodPerf['PV_2L'] + $userLastPerf['PV_2L'],
  376. 'PV_3L_TOTAL' => $periodPerf['PV_3L'] + $userLastPerf['PV_3L'],
  377. 'PV_4L_TOTAL' => $periodPerf['PV_4L'] + $userLastPerf['PV_4L'],
  378. 'PV_5L_TOTAL' => $periodPerf['PV_5L'] + $userLastPerf['PV_5L'],
  379. 'PV_PSS_TOTAL' => $periodPerf['PV_PSS'] + $userLastPerf['PV_PSS_TOTAL'],
  380. ];
  381. // 把会员的月业绩写入缓存中,以便下面的奖金计算从缓冲中获取数据效率高
  382. CalcCache::addHasMonthPerfUsers($userId, $this->_periodNum);
  383. CalcCache::nowMonthPerf($userId, $this->_periodNum, $nowMonthPerf);
  384. unset($userId, $everyData, $nowMonthPerf, $lastMonthData, $userBaseInfo, $isVip);
  385. }
  386. unset($allData);
  387. $this->loopCalcMonthPerfTableData($offset + $this->_limit);
  388. }
  389. unset($allData);
  390. return true;
  391. }
  392. /**
  393. * 循环有业绩会员,并入库
  394. * @param int $offset
  395. * @return bool
  396. * @throws \yii\db\Exception
  397. */
  398. public function loopWriteNowPerf($offset = 0) {
  399. echo sprintf("时间:[%s]缓存本期业绩数据入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
  400. // 从缓存列表里面从底层往上倒序获取会员
  401. $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit);
  402. if($allData){
  403. $insertDataPeriodPerf = [];
  404. foreach($allData as $userId){
  405. $insertDataPeriodPerf[] = $this->nowPeriodPerfData($userId);
  406. unset($userId);
  407. }
  408. PerfPeriod::batchInsert($insertDataPeriodPerf);
  409. unset($insertDataPeriodPerf, $allData);
  410. return $this->loopWriteNowPerf($offset + $this->_limit);
  411. }
  412. unset($allData);
  413. return true;
  414. }
  415. /**
  416. * 循环有月业绩会员,并入库
  417. * @param int $offset
  418. * @return bool
  419. * @throws \yii\db\Exception
  420. */
  421. public function loopWriteMonthPerf($offset = 0) {
  422. if(!$this->_isCalcMonth){
  423. return true;
  424. }
  425. echo sprintf("时间:[%s]缓存本月业绩数据入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
  426. // 从缓存列表里面从底层往上倒序获取会员
  427. $allData = CalcCache::getHasMonthPerfUsers($this->_periodNum, $offset, $this->_limit);
  428. if($allData){
  429. $insertDataMonthPerf = [];
  430. foreach($allData as $userId){
  431. $insertDataMonthPerf[] = $this->nowMonthPerfData($userId);
  432. unset($userId);
  433. }
  434. PerfMonth::batchInsert($insertDataMonthPerf);
  435. unset($insertDataMonthPerf, $allData);
  436. return $this->loopWriteMonthPerf($offset + $this->_limit);
  437. }
  438. unset($allData);
  439. return true;
  440. }
  441. /**
  442. * 本期业绩数据
  443. * @param $userId
  444. * @return array
  445. */
  446. public function nowPeriodPerfData($userId){
  447. $data = CalcCache::nowPeriodPerf($userId, $this->_periodNum);
  448. $userInfo = CalcCache::getUserInfo($userId, $this->_periodNum);
  449. $result = [
  450. 'ID' => SnowFake::instance()->generateId(),
  451. 'USER_ID' => $userId,
  452. 'FX_AMOUNT_CASH' => $data['FX_AMOUNT_CASH'],
  453. 'PV_PCS' => $data['PV_PCS'],
  454. 'PV_PSS' => $data['PV_PSS'],
  455. 'PV_PCS_ZC' => $data['PV_PCS_ZC'],
  456. 'PV_PCS_FX' => $data['PV_PCS_FX'],
  457. 'PV_PCS_FX_CASH' => $data['PV_PCS_FX_CASH'],
  458. 'PV_PCS_FX_POINT' => $data['PV_PCS_FX_POINT'],
  459. 'PV_1L' => $data['PV_1L'],
  460. 'PV_1L_TOUCH' => $data['PV_1L_TOUCH'],
  461. 'PV_1L_ZC' => $data['PV_1L_ZC'],
  462. 'PV_1L_FX' => $data['PV_1L_FX'],
  463. 'PV_2L' => $data['PV_2L'],
  464. 'PV_2L_TOUCH' => $data['PV_2L_TOUCH'],
  465. 'PV_2L_ZC' => $data['PV_2L_ZC'],
  466. 'PV_2L_FX' => $data['PV_2L_FX'],
  467. 'PV_3L' => $data['PV_3L'],
  468. 'PV_3L_TOUCH' => $data['PV_3L_TOUCH'],
  469. 'PV_3L_ZC' => $data['PV_3L_ZC'],
  470. 'PV_3L_FX' => $data['PV_3L_FX'],
  471. 'PV_4L' => $data['PV_4L'],
  472. 'PV_4L_TOUCH' => $data['PV_4L_TOUCH'],
  473. 'PV_4L_ZC' => $data['PV_4L_ZC'],
  474. 'PV_4L_FX' => $data['PV_4L_FX'],
  475. 'PV_5L' => $data['PV_5L'],
  476. 'PV_5L_TOUCH' => $data['PV_5L_TOUCH'],
  477. 'PV_5L_ZC' => $data['PV_5L_ZC'],
  478. 'PV_5L_FX' => $data['PV_5L_FX'],
  479. 'SURPLUS_1L' => $data['SURPLUS_1L'],
  480. 'SURPLUS_2L' => $data['SURPLUS_2L'],
  481. 'SURPLUS_3L' => $data['SURPLUS_3L'],
  482. 'SURPLUS_4L' => $data['SURPLUS_4L'],
  483. 'SURPLUS_5L' => $data['SURPLUS_5L'],
  484. 'PERIOD_NUM' => $this->_periodNum,
  485. 'CALC_MONTH' => $this->_calcYearMonth,
  486. 'CREATED_AT' => Date::nowTime(),
  487. 'LAST_EMP_LV' => $userInfo['LAST_EMP_LV']
  488. ];
  489. unset($data);
  490. return $result;
  491. }
  492. /**
  493. * 本月业绩
  494. * @param $userId
  495. * @return array
  496. */
  497. public function nowMonthPerfData($userId){
  498. $data = CalcCache::nowMonthPerf($userId, $this->_periodNum);
  499. $baseInfo = CalcCache::getUserInfo($userId, $this->_periodNum);
  500. $result = [
  501. 'ID' => SnowFake::instance()->generateId(),
  502. 'USER_ID' => $userId,
  503. 'FX_AMOUNT_CASH' => $data['FX_AMOUNT_CASH'],
  504. 'PV_PCS' => $data['PV_PCS'],
  505. 'PV_PCS_FX' => $data['PV_PCS_FX'],
  506. 'PV_PSS' => $data['PV_PSS'],
  507. 'PV_1L' => $data['PV_1L'],
  508. 'PV_2L' => $data['PV_2L'],
  509. 'PV_3L' => $data['PV_3L'],
  510. 'PV_4L' => $data['PV_4L'],
  511. 'PV_5L' => $data['PV_5L'],
  512. 'PV_1L_TOTAL' => $data['PV_1L_TOTAL'],
  513. 'PV_2L_TOTAL' => $data['PV_2L_TOTAL'],
  514. 'PV_3L_TOTAL' => $data['PV_3L_TOTAL'],
  515. 'PV_4L_TOTAL' => $data['PV_4L_TOTAL'],
  516. 'PV_5L_TOTAL' => $data['PV_5L_TOTAL'],
  517. 'PV_PSS_TOTAL' => $data['PV_PSS_TOTAL'],
  518. 'CALC_MONTH' => $this->_calcYearMonth,
  519. 'CREATED_AT' => Date::nowTime(),
  520. 'LAST_EMP_LV' => $baseInfo['LAST_EMP_LV']
  521. ];
  522. unset($data);
  523. return $result;
  524. }
  525. /**
  526. * 循环父级并执行回调函数
  527. * @param $userId
  528. * @param callable $callbackFunc
  529. * @param int $offset
  530. * @return bool
  531. */
  532. public function loopNetworkParentDo($userId, callable $callbackFunc, int $offset = 0) {
  533. $allParents = Cache::getAllNetworkParents($userId, true);
  534. $allData = array_slice($allParents, $offset, $this->_limit);
  535. unset($allParents);
  536. if ($allData) {
  537. foreach ($allData as $data) {
  538. $funcResult = $callbackFunc($data);
  539. if ($funcResult === self::LOOP_FINISH) {
  540. return true;
  541. } elseif ($funcResult === self::LOOP_CONTINUE) {
  542. continue;
  543. }
  544. unset($data, $funcResult);
  545. }
  546. unset($allData);
  547. return $this->loopNetworkParentDo($userId, $callbackFunc, $offset + $this->_limit);
  548. }
  549. return true;
  550. }
  551. /**
  552. * 循环推荐网络的父级
  553. * @param $userId
  554. * @param callable $callbackFunc
  555. * @param int $offset
  556. * @return bool
  557. */
  558. public function loopRelationParentDo($userId, callable $callbackFunc, int $offset = 0) {
  559. $allParents = Cache::getAllRelationParents($userId,true);
  560. $allData = array_slice($allParents, $offset, $this->_limit);
  561. unset($allParents);
  562. if ($allData) {
  563. foreach ($allData as $data) {
  564. $funcResult = $callbackFunc($data);
  565. if ($funcResult === self::LOOP_FINISH) {
  566. return true;
  567. } elseif ($funcResult === self::LOOP_CONTINUE) {
  568. continue;
  569. }
  570. unset($data, $funcResult);
  571. }
  572. unset($allData);
  573. return $this->loopRelationParentDo($userId, $callbackFunc, $offset + $this->_limit);
  574. }
  575. return true;
  576. }
  577. /**
  578. * 更新百分比并发送
  579. * @param $percent
  580. */
  581. private function _updatePercent($percent) {
  582. // 把数据写入数据库中
  583. Period::updateAll(['PERF_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
  584. }
  585. // 期业绩表,增加是否活跃字段判断,就用isPerfActive 方法进行判断。
  586. public function loopUpdatePeriodActive($offset = 0) {
  587. echo sprintf("时间:[%s]更新期业绩表活跃状态字段,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
  588. $allData = PerfPeriod::findUseDbCalc()
  589. ->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum])
  590. ->offset($offset)
  591. ->limit($this->_limit)
  592. ->asArray()
  593. ->all();
  594. if ($allData) {
  595. foreach ($allData as $data) {
  596. $isActive = User::isPerfActive($data['USER_ID'], $this->_periodNum, $this->_calcYearMonth);
  597. // 期结算结果
  598. PerfPeriod::updateAll(['IS_ACTIVE' => $isActive], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM',
  599. [
  600. ':USER_ID' => $data['USER_ID'],
  601. ':PERIOD_NUM' => $this->_periodNum
  602. ]
  603. );
  604. }
  605. unset($allData);
  606. return $this->loopUpdatePeriodActive($offset + $this->_limit);
  607. }
  608. unset($allData);
  609. return true;
  610. }
  611. }