CalcServePerfCalc.php 27 KB

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