CalcServePerfCalc.php 26 KB

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