_sysConfig = Cache::getSystemConfig(); $this->_decLevelConfig = Cache::getDecLevelConfig(); $this->_empLevelConfig = Cache::getEmpLevelConfig(); $this->_decRoleConfig = CalcCache::getDecRoleConfig($this->_periodNum); $this->_periodNum = $periodNum; $this->_appUserId = $appUserId; $this->_workerId = $workerId; $this->_workerNum = $workerNum; } /** * 设置期数 * @param int $periodNum * @return int */ public function setPeriodNum(int $periodNum) { return $this->_periodNum = $periodNum; } /** * 获取期数 * @return int */ public function getPeriodNum() { return $this->_periodNum; } /** * 加入错误错误 * @param $attr * @param $error */ public function addError($attr, $error) { $this->_errors[$attr][] = $error; } /** * 获取错误信息 * @return array */ public function getErrors() { return $this->_errors; } /** * 进行奖金发放步骤 * @return bool */ public function sendStep() { try { $t1 = microtime(true); // 初始化 $this->initTask(); $t2 = microtime(true); echo('初始化完成,当前期数【' . $this->_periodNum . '】,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 改变状态 $this->setSendStatus('start'); $t3 = microtime(true); echo('改变状态完成,耗时:' . round($t3 - $t2, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(20); //Yii::$app->db->close(); //Yii::$app->dbShop->close(); // 更新聘级 $this->updateEmpLevel(); $this->_updatePercent(40); $t4 = microtime(true); echo('更新聘级完成,耗时:' . round($t4 - $t3, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 更新星级 $this->updateStarLevel(); $this->_updatePercent(50); $t41 = microtime(true); echo('更新星级完成,耗时:' . round($t41 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 发放奖金 $this->sendBonusLoop(); $this->_updatePercent(60); $t5 = microtime(true); echo('发放奖金完成,耗时:' . round($t5 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 更新会员上次报单级别 // $this->updateUserDevLv(); // $this->_updatePercent(80); $t6 = microtime(true); // echo('更新会员上次报单级别完成,耗时:' . round($t6 - $t5, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 更新会员累计业绩 $this->updateUserPerf(); $this->_updatePercent(80); $t7 = microtime(true); echo('更新会员累计业绩完成,耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->updateUserPerfMonth(); $this->_updatePercent(90); $t8 = microtime(true); echo('更新会员累计月业绩完成,耗时:' . round($t8 - $t7, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 更新活跃用户状态,更新为已处理 // $this->updateActiveUser(); // $this->_updatePercent(95); // $t9 = microtime(true); // echo('更新会员累计月业绩完成,耗时:' . round($t9 - $t8, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // 开启子进程去完成下面的循环发放和循环改聘级和循环更新累计业绩 /*$process = new Process('sendBonus', 3); $process->run(function($workId, $pmid){ $this->processStep($workId); }); while (true){ if($process->isFinish()) break; } unset($process); $this->_updatePercent(90); $t4 = microtime(true); echo('所有子进程的任务完成,耗时:'.round($t4 - $t3, 3).',内存使用:'.(round(memory_get_usage()/1024/1024, 3)).'MB'.PHP_EOL);*/ echo('全部奖金发放完成,耗时:'.round($t7 - $t1, 3).',内存使用:'.(round(memory_get_usage()/1024/1024, 3)).'MB'.PHP_EOL); $this->_updatePercent(100); } catch (\Exception $e) { $this->addError('sendBonus', $e->getMessage()); return false; } if (count($this->_errors) > 0) { return false; } return true; } /** * 需要多进程执行的任务 * @param $workId * @throws \yii\db\Exception */ public function processStep($workId = null) { if ($workId == 1 || $workId === null) { // 发放奖金 $this->sendBonusLoop(); } if ($workId == 2 || $workId === null) { // 更新聘级 $this->updateEmpLevel(); } if ($workId == 3 || $workId === null) { // 更新会员累计业绩 $this->updateUserPerf(); } Yii::$app->db->close(); Yii::$app->dbShop->close(); } /** * 初始化发放任务 * @throws Exception */ public function initTask() { $this->_errors = []; $periodNum = $this->_periodNum; // 获取传入期数的相关信息 $periodObj = Period::instance(); $periodDataArr = $periodObj->setPeriodNum($periodNum); $this->_periodId = $periodDataArr['ID']; $this->_isCalcMonth = $periodObj->isCalcMonth($periodNum); $this->_calcYear = $periodObj->getYear($periodNum); $this->_calcMonth = $periodObj->getMonth($periodNum); $this->_calcYearMonth = $periodObj->getYearMonth($periodNum); $lastYearMonthArr = $periodObj->getLastMonth($periodNum); $this->_lastCalcYear = $lastYearMonthArr['year']; $this->_lastCalcMonth = $lastYearMonthArr['month']; $this->_lastCalcYearMonth = $lastYearMonthArr['yearMonth']; } /** * 设置结算状态 * @param $type * start|end|fail */ public function setSendStatus($type) { Yii::$app->db->close(); if ($type == 'start') { Period::updateAll(['IS_SENDING' => 1, 'SEND_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } elseif ($type == 'end') { Period::updateAll(['IS_SENDING' => 0, 'IS_SENT' => Period::SEND_FINISH, 'SENT_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } elseif ($type == 'fail') { Period::updateAll(['IS_SENDING' => 0, 'IS_SENT' => Period::SEND_FAIL, 'SENT_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } } /** * 结束计算任务 * @throws \yii\db\Exception */ public function endTask() { CalcCache::clearAll($this->_periodNum); $this->setSendStatus('end'); //@todo 先不备份数据 // DataBak::backup($this->_periodNum); //发送复销短信 // if ($this->_isCalcMonth && $this->_sysConfig['smsOpen']['VALUE']) { // $this->sendSmsLoop(); // } } /** * 出现错误 */ public function errorTask() { $this->setSendStatus('fail'); } /** * 发放奖金 * @param int $page * @return bool * @throws \yii\db\Exception */ public function sendBonusLoop($page=1) { echo sprintf("时间:[%s]数据库发奖,当前page为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()), $page); $periodNum = $this->_periodNum; // 从奖金结算表中获取当期未发放的所有数据 $allData = CalcBonus::findUseDbCalc() ->yearMonth($this->_calcYearMonth) ->where( '(IS_SENT=0 OR IS_SENT=2) AND CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM', [':CALC_MONTH' => $this->_calcYearMonth, ':PERIOD_NUM' => $periodNum] ) ->limit($this->_limit) ->asArray() ->all(); if ($allData) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $key => $data) { // 期奖金 // $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']; $periodAmount = $data['BONUS_REAL']; // 获取本期结算的管理员 // $period = Period::findOneAsArray(['PERIOD_NUM'=>$periodNum]); // $updateAminId = $period['CALC_ADMIN_ID']; if ($periodAmount > 0) { Balance::changeUserBonus($data['USER_ID'], 'bonus', $periodAmount, [ 'CALC_ID' => $data['ID'], 'REMARK' => 'From ' . $periodNum . '期', 'PERIOD_NUM' => $periodNum, 'QY' => $data['BONUS_QY'], 'FW' => $data['BONUS_FW'], 'YC' => $data['BONUS_YC'], 'VIP' => $data['BONUS_VIP'], 'BD' => $data['BONUS_BD'], 'TG' => $data['BONUS_TG'], 'YJ' => $data['BONUS_YJ'], 'GX' => $data['BONUS_GX'], 'GL' => $data['BONUS_GL'], 'BS' => $data['BONUS_BS'], 'BS_MNT' => $data['BONUS_BS_MNT'], 'BS_ABBR' => $data['BONUS_BS_ABBR'], 'ORI_QY' => $data['ORI_BONUS_QY'], 'ORI_YC' => $data['ORI_BONUS_YC'], 'ORI_VIP' => $data['ORI_BONUS_VIP'], 'ORI_STANDARD' => $data['ORI_BONUS_STANDARD'], 'ORI_BD' => $data['ORI_BONUS_BD'], 'ORI_TG' => $data['ORI_BONUS_TG'], 'ORI_YJ' => $data['ORI_BONUS_YJ'], 'ORI_GX' => $data['ORI_BONUS_GX'], 'ORI_GL' => $data['ORI_BONUS_GL'], 'ORI_BS' => $data['ORI_BONUS_BS'], 'ORI_BS_MNT' => $data['ORI_BONUS_BS_MNT'], 'ORI_BS_ABBR' => $data['ORI_BONUS_BS_ABBR'], 'RECONSUME_POINTS_TOTAL' => $data['RECONSUME_POINTS'], 'EXCHANGE_POINTS_TOTAL' => $data['EXCHANGE_POINTS'], 'MANAGE_TAX' => $data['MANAGE_TAX'], 'BONUS_TOTAL' => $data['BONUS_TOTAL'], 'DEAL_TYPE_ID' => DealType::BONUS_SEND, 'SORT' => $key * 10, 'BONUS_ISSUE' => true, ]); // $this->_teamworkBonus($data['USER_ID'], $periodAmount, $key); } // 旅游奖 if ($data['BONUS_TOURISM'] > 0) { Balance::changeUserBonus($data['USER_ID'], 'tourism_points', $data['BONUS_TOURISM'], [ 'CALC_ID' => $data['ID'], 'REMARK' => 'From ' . $periodNum . '期', 'PERIOD_NUM' => $periodNum, 'TOURISM_POINTS' => $data['BONUS_TOURISM'], 'DEAL_TYPE_ID' => DealType::TOURISM_SEND, 'SORT' => $key * 10, 'BONUS_ISSUE' => true, ]); } // 车房奖 if ($data['BONUS_GARAGE'] > 0) { Balance::changeUserBonus($data['USER_ID'], 'garage_points', $data['BONUS_GARAGE'], [ 'CALC_ID' => $data['ID'], 'REMARK' => 'From ' . $periodNum . '期', 'PERIOD_NUM' => $periodNum, 'GARAGE_POINTS' => $data['BONUS_GARAGE'], 'DEAL_TYPE_ID' => DealType::GARAGE_SEND, 'SORT' => $key * 10, 'BONUS_ISSUE' => true, ]); } //发放重消积分 // if ($data['RECONSUME_POINTS'] > 0) { // Balance::changeUserBonus($data['USER_ID'], 'reconsume_points', $data['RECONSUME_POINTS'], [ // 'CALC_ID' => $data['ID'], // 'REMARK' => 'From ' . $periodNum . '期', // 'PERIOD_NUM' => $periodNum, // 'RECONSUME_POINTS' => $data['RECONSUME_POINTS'], // 'DEAL_TYPE_ID' => DealType::RECONSUME_POINTS_SEND, // ]); // } // // //发放兑换积分 // if ($data['EXCHANGE_POINTS'] > 0) { // Balance::changeUserBonus($data['USER_ID'], 'exchange_points', $data['EXCHANGE_POINTS'], [ // 'CALC_ID' => $data['ID'], // 'REMARK' => 'From ' . $periodNum . '期', // 'PERIOD_NUM' => $periodNum, // 'EXCHANGE_POINTS' => $data['EXCHANGE_POINTS'], // 'DEAL_TYPE_ID' => DealType::EXCHANGE_POINTS_SEND, // 'BONUS_ISSUE' => true, // ]); // } // 把记录标记为已发放状态 CalcBonus::updateAll(['IS_SENT' => 1, 'SENT_AT' => Date::nowTime()], 'ID=:ID', [':ID' => $data['ID']]); unset($periodAmount, $key, $data); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('sendBonus', '奖金发放失败,原因:' . $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage()); return false; } unset($allData, $transaction); $page++; return $this->sendBonusLoop($page); } unset($allData); return true; } /** * 蓝星奖金(即新的管理奖),更新会员聘级 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function updateEmpLevel(int $offset = 0) { if ($this->_isCalcMonth) { $empLv = EmployLevel::getIdConvertLevelSortCache(); $allData = CalcBonus::findUseDbCalc() ->yearMonth($this->_calcYearMonth) ->where( 'CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM', [ ':CALC_MONTH' => $this->_calcYearMonth, ':PERIOD_NUM' =>$this->_periodNum ] ) ->orderBy('CREATED_AT DESC') ->offset($offset) ->limit($this->_limit) ->all(); //@todo 用户级别不变则不更新 $defaultEmpLv = EmployLevel::getDefaultLevelId(); if ($allData) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $data) { //@todo 用户级别不变则不更新 if( $data['LAST_EMP_LV'] === $defaultEmpLv ) continue; $nowBsEmpLv = $data['LAST_EMP_LV']; // 当前蓝星奖计算(即管理奖) 的等级 $user = CalcCache::getUserInfo($data['USER_ID'], $this->_periodNum); $userEmpLv = $user['EMP_LV']; // 用户的历史最高聘级 $userEmpLvSort = $empLv[$userEmpLv]; // 历史最高聘级的 级别值 $nowBsEmpLvSort = $empLv[$nowBsEmpLv]; // 当前蓝星计算的聘级 级别值 if ($nowBsEmpLvSort > $userEmpLvSort) { // 如果当前期的级别值大于历史最高级别,则更新用户表里的最高聘级 User::updateAll(['EMP_LV' => $nowBsEmpLv], 'ID=:USER_ID', [':USER_ID' => $data['USER_ID']]); User::deleteBaseInfoFromRedis($data['USER_ID']); unset($data); } else { continue; } } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('updateEmpLevel', '更新聘级失败,原因:' . $e->getMessage()); return false; } unset($transaction, $allData, $defaultEmpLv); return $this->updateEmpLevel($offset + $this->_limit); } unset($allData); } return true; } /** * 更新用户星级 * @param int $offset * @return bool */ public function updateStarLevel(int $offset = 0) { $allData = CalcBonusQY::findUseDbCalc() ->yearMonth($this->_calcYearMonth) ->where( 'CALC_MONTH=:CALC_MONTH AND PERIOD_NUM=:PERIOD_NUM', [ ':CALC_MONTH' => $this->_calcYearMonth, ':PERIOD_NUM' =>$this->_periodNum ] ) ->orderBy('CREATED_AT DESC') ->groupBy('USER_ID') ->offset($offset) ->limit($this->_limit) ->all(); if ($allData) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $data) { User::updateAll(['STAR_LV' => $data['LAST_STAR_LV']], 'ID = :USER_ID', [':USER_ID' => $data['USER_ID']]); User::deleteBaseInfoFromRedis($data['USER_ID']); unset($data); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('updateStarCrownLevel', '更新星级失败,原因:' . $e->getMessage()); return false; } unset($transaction, $allData); return $this->updateStarLevel($offset + $this->_limit); } unset($allData); return true; } // /** // * 更新会员聘级 // * @param int $offset // * @return bool // * @throws \yii\db\Exception // */ // public function updateEmpLevel(int $offset = 0) { // if ($this->_isCalcMonth) { // $allData = PerfMonth::findUseDbCalc()->yearMonth($this->_calcYearMonth)->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->offset($offset)->limit($this->_limit)->all(); // //@todo 用户级别不变则不更新 // $defaultEmpLv = EmployLevel::getDefaultLevelId(); // if ($allData) { // $transaction = Yii::$app->db->beginTransaction(); // try { // foreach ($allData as $data) { // //@todo 用户级别不变则不更新 // if( $data['LAST_EMP_LV'] === $defaultEmpLv ) continue; // User::updateAll(['EMP_LV' => $data['LAST_EMP_LV']], 'ID=:USER_ID', [':USER_ID' => $data['USER_ID']]); // User::deleteBaseInfoFromRedis($data['USER_ID']); // unset($data); // } // $transaction->commit(); // } catch (Exception $e) { // $transaction->rollBack(); // $this->addError('updateEmpLevel', '更新聘级失败,原因:' . $e->getMessage()); // return false; // } // unset($transaction, $allData, $defaultEmpLv); // return $this->updateEmpLevel($offset + $this->_limit); // } // unset($allData); // } // return true; // } // 更活跃会员,将is_send改成1 public function updateActiveUser() { try { $ret = PerfActiveUser::updateAll( ['IS_SENT' => 1], 'PERIOD_NUM=:PERIOD_NUM AND IS_SENT=:IS_SENT', ['IS_SENT'=>0, 'PERIOD_NUM'=>$this->_periodNum] ); return $ret; } catch(Exception $e) { $this->addError('updateActiveUser', '更新活跃会员业绩期处理状态失败,原因:' . $e->getMessage()); return false; } } /** * 更新会员的累计业绩 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function updateUserPerf(int $offset = 0) { $allData = PerfPeriod::findUseDbCalc()->yearMonth($this->_calcYearMonth)->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum])->orderBy('ID ASC')->offset($offset)->limit($this->_limit)->all(); if ($allData) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $data) { $isUpdate = false; if (UserPerf::findUseDbCalc()->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) { // 判断本期是否已经更新过业绩 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()) { $isUpdate = true; // 更新业绩 UserPerf::updateAll([ 'PV_PCS_ZC' => new Expression('PV_PCS_ZC+' . $data['PV_PCS_ZC']), 'PV_PCS_YH' => new Expression('PV_PCS_YH+' . $data['PV_PCS_YH']), 'PV_PCS_ZG' => new Expression('PV_PCS_ZG+' . $data['PV_PCS_ZG']), 'PV_PCS_LS' => new Expression('PV_PCS_LS+' . $data['PV_PCS_LS']), 'PV_PCS_FX' => new Expression('PV_PCS_FX+' . $data['PV_PCS_FX']), 'PV_PSS' => new Expression('PV_PSS+' . $data['PV_PSS']), 'PV_PSS_TOTAL' => new Expression('PV_PSS_TOTAL+' . $data['PV_PSS']), 'PV_1L' => new Expression('PV_1L+' . $data['PV_1L']), 'PV_2L' => new Expression('PV_2L+' . $data['PV_2L']), 'PV_3L' => new Expression('PV_3L+' . $data['PV_3L']), 'PV_4L' => new Expression('PV_4L+' . $data['PV_4L']), 'PV_5L' => new Expression('PV_5L+' . $data['PV_5L']), 'SURPLUS_1L' => $data['SURPLUS_1L'], 'SURPLUS_2L' => $data['SURPLUS_2L'], 'SURPLUS_3L' => $data['SURPLUS_3L'], 'SURPLUS_4L' => $data['SURPLUS_4L'], 'SURPLUS_5L' => $data['SURPLUS_5L'], 'SURPLUS_1L_ZC' => $data['SURPLUS_1L_ZC'], 'SURPLUS_2L_ZC' => $data['SURPLUS_2L_ZC'], 'SURPLUS_3L_ZC' => $data['SURPLUS_3L_ZC'], 'SURPLUS_4L_ZC' => $data['SURPLUS_4L_ZC'], 'SURPLUS_5L_ZC' => $data['SURPLUS_5L_ZC'], 'SURPLUS_1L_FX' => $data['SURPLUS_1L_FX'], 'SURPLUS_2L_FX' => $data['SURPLUS_2L_FX'], 'SURPLUS_3L_FX' => $data['SURPLUS_3L_FX'], 'SURPLUS_4L_FX' => $data['SURPLUS_4L_FX'], 'SURPLUS_5L_FX' => $data['SURPLUS_5L_FX'], ], 'USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']]); } } else { $isUpdate = true; UserPerf::insertOne([ 'USER_ID' => $data['USER_ID'], 'PV_PCS_ZC' => $data['PV_PCS_ZC'], 'PV_PCS_YH' => $data['PV_PCS_YH'], 'PV_PCS_ZG' => $data['PV_PCS_ZG'], 'PV_PCS_LS' => $data['PV_PCS_LS'], 'PV_PCS_FX' => $data['PV_PCS_FX'], 'PV_PSS' => $data['PV_PSS'], 'PV_PSS_TOTAL' => $data['PV_PSS'], 'PV_1L' => $data['PV_1L'], 'PV_2L' => $data['PV_2L'], 'PV_3L' => $data['PV_3L'], 'PV_4L' => $data['PV_4L'], 'PV_5L' => $data['PV_5L'], 'SURPLUS_1L' => $data['SURPLUS_1L'], 'SURPLUS_2L' => $data['SURPLUS_2L'], 'SURPLUS_3L' => $data['SURPLUS_3L'], 'SURPLUS_4L' => $data['SURPLUS_4L'], 'SURPLUS_5L' => $data['SURPLUS_5L'], 'SURPLUS_1L_ZC' => $data['SURPLUS_1L_ZC'], 'SURPLUS_2L_ZC' => $data['SURPLUS_2L_ZC'], 'SURPLUS_3L_ZC' => $data['SURPLUS_3L_ZC'], 'SURPLUS_4L_ZC' => $data['SURPLUS_4L_ZC'], 'SURPLUS_5L_ZC' => $data['SURPLUS_5L_ZC'], 'SURPLUS_1L_FX' => $data['SURPLUS_1L_FX'], 'SURPLUS_2L_FX' => $data['SURPLUS_2L_FX'], 'SURPLUS_3L_FX' => $data['SURPLUS_3L_FX'], 'SURPLUS_4L_FX' => $data['SURPLUS_4L_FX'], 'SURPLUS_5L_FX' => $data['SURPLUS_5L_FX'], 'CREATED_AT' => Date::nowTime(), ]); } if ($isUpdate) { // 变为已更新 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()]); } unset($data, $isUpdate); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('updateUserPerf', '更新会员业绩失败,原因:' . $e->getMessage()); return false; } unset($allData, $transaction); return $this->updateUserPerf($offset + $this->_limit); } unset($allData); return true; } /** * 更新会员的月剩余业绩 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function updateUserPerfMonth(int $offset = 0) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } $allData = PerfMonth::findUseDbCalc()->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->orderBy('ID ASC')->offset($offset)->limit($this->_limit)->all(); if ($allData) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $data) { $isUpdate = false; if (UserPerf::findUseDbCalc()->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) { // 判断本期是否已经更新过业绩 if (!UserPerfMonthUpdate::findUseDbCalc()->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $data['USER_ID'], ':CALC_MONTH' => $this->_calcYearMonth])->exists()) { $isUpdate = true; // 更新业绩 UserPerf::updateAll([ 'VIP_SURPLUS_1L_ZC' => $data['VIP_SURPLUS_1L_ZC'], 'VIP_SURPLUS_2L_ZC' => $data['VIP_SURPLUS_2L_ZC'], 'VIP_SURPLUS_3L_ZC' => $data['VIP_SURPLUS_3L_ZC'], 'VIP_SURPLUS_4L_ZC' => $data['VIP_SURPLUS_4L_ZC'], 'VIP_SURPLUS_5L_ZC' => $data['VIP_SURPLUS_5L_ZC'] ], 'USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']]); } } else { $isUpdate = true; UserPerf::insertOne([ 'USER_ID' => $data['USER_ID'], 'VIP_SURPLUS_1L_ZC' => $data['VIP_SURPLUS_1L_ZC'], 'VIP_SURPLUS_2L_ZC' => $data['VIP_SURPLUS_2L_ZC'], 'VIP_SURPLUS_3L_ZC' => $data['VIP_SURPLUS_3L_ZC'], 'VIP_SURPLUS_4L_ZC' => $data['VIP_SURPLUS_4L_ZC'], 'VIP_SURPLUS_5L_ZC' => $data['VIP_SURPLUS_5L_ZC'], 'CREATED_AT' => Date::nowTime(), ]); } if ($isUpdate) { // 变为已更新 UserPerfMonthUpdate::insertOne(['USER_ID' => $data['USER_ID'], 'CALC_MONTH' => $this->_calcYearMonth, 'CREATED_AT' => Date::nowTime()]); } unset($data, $isUpdate); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('updateUserPerf', '更新会员月业绩失败,原因:' . $e->getMessage()); return false; } unset($allData, $transaction); return $this->updateUserPerfMonth($offset + $this->_limit); } unset($allData); return true; } /** * 检测复消积分是否过期 * @return bool * @throws \yii\db\Exception */ public function checkReconsumePointsExpired(int $offset = 0) { $periodNum = $this->_periodNum; //一期为7天,那么365天为52.14即53期 $expiredPeriodNum = $periodNum - 53; if( $expiredPeriodNum <= 0 ) return true; //查询需要过期的期数 $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(); if( $allData ) { $transaction = Yii::$app->db->beginTransaction(); try{ //扣除钱包的复消积分 foreach ($allData as $everyData) { //过期 UserPeriodPoints::updateAll([ 'REMAINDER_POINTS' => 0, 'EXPIRED' => 1, 'EXPIRED_PERIOD' => $periodNum, 'EXPIRED_AT' => Date::nowTime(), ], 'ID=:ID', ['ID'=>$everyData['ID']]); if( !isset($everyData['REMAINDER_POINTS']) || !$everyData['REMAINDER_POINTS'] ) continue; UserBonus::updateAllCounters([ 'RECONSUME_POINTS' => (-1) * $everyData['REMAINDER_POINTS'], ], 'USER_ID=:USER_ID', $everyData['USER_ID']); unset($everyData); } unset($periodNum, $expiredPeriodNum, $allData); $transaction->commit(); }catch (\Exception $e){ $transaction->rollBack(); $this->addError('checkReconsumePointsExpired', '检测过期在复消积分失败,原因:' . $e->getMessage()); return false; } return $this->checkReconsumePointsExpired($offset + $this->_limit); } unset($allData); return true; } /** * 更新会员上次报单级别 * @return bool */ public function updateUserDevLv() { $transaction = Yii::$app->dbShop->beginTransaction(); try { \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(); $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('updateUserDevLv', '更新会员上次报单级别失败,原因:' . $e->getMessage()); return false; } return true; } /** * 给商城会员增加货款 * @param $userId * @param $amount * @param $remark * @throws Exception */ private function _shopAddPaymentForGoods($userId, $amount, $remark) { $db = \Yii::$app->dbShop; $transaction = $db->beginTransaction(); try { ActiveRecord::batchUpdate(['PAYMENT_FOR_GOODS' => new Expression('PAYMENT_FOR_GOODS+' . abs($amount))], 'USER_ID=:USER_ID', [':USER_ID' => $userId], '{{%USER_WALLET}}', 'dbShop'); // 增加流水 $flowInsertData[] = [ 'USER_ID' => $userId, 'USER_NAME' => Cache::getUserBaseInfo($userId)['USER_NAME'], 'DEC_LV' => Cache::getUserBaseInfo($userId)['DEC_LV'], 'ORDER_SN' => null, 'AMOUNT' => $amount, 'CREATED_AT' => Date::nowTime(), 'PERIOD_AT' => $this->_periodNum, 'IS_INCR' => 1, 'REMARK' => $remark, 'PARTITION_DATE' => Date::ociToDate(), 'WALLET_TYPE' => 'payment_for_goods', 'FROM_TYPE' => 'incr', ]; ActiveRecord::batchInsert($flowInsertData, '{{%FLOW_WALLET}}', 'dbShop'); $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); throw new Exception($e->getMessage()); } } /** * 更新百分比并发送 * @param $percent */ private function _updatePercent($percent) { // 把数据写入数据库中 Period::updateAll(['SENT_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); \Yii::$app->swooleAsyncTimer->pushAsyncPercentToAdmin($percent, ['MODEL' => 'PERIOD', 'ID' => $this->_periodId, 'FIELD' => 'SENT_PERCENT']); } /** * 更新最高聘级 * @param $user_id * @return bool * @throws Exception */ private function _updateHighestEmpLv($user_id) { $empLv = Info::getEmpLv($user_id); $highEmpLv = Info::getHighEmpLv($user_id); $empLvSort = EmployLevel::getSortById($empLv); $empLvHighSort = EmployLevel::getSortById($highEmpLv); if ($empLvHighYear = YearHighestEmpLv::findOneAsArray('USER_ID=:USER_ID AND YEAR=:YEAR', [':USER_ID' => $user_id, ':YEAR' => $this->_calcYear], 'HIGHEST_EMP_LV_SORT')) { if ($empLvSort > $empLvHighYear['HIGHEST_EMP_LV_SORT']) { 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]); } } else { $yearHighest = new YearHighestEmpLv(); $yearHighest->USER_ID = $user_id; $yearHighest->YEAR = $this->_calcYear; $yearHighest->HIGHEST_EMP_LV = $empLv; $yearHighest->HIGHEST_EMP_LV_SORT = $empLvSort; $yearHighest->HIGHEST_EMP_LV_PERIOD = $this->_periodNum; $yearHighest->CREATED_AT = Date::nowTime(); if (!$yearHighest->save()) { throw new \yii\db\Exception(Form::formatErrorsForApi($yearHighest->getErrors())); } } if ($empLvSort > $empLvHighSort) { UserInfo::updateAll(['HIGHEST_EMP_LV' => $empLv, 'HIGHEST_EMP_LV_PERIOD' => $this->_periodNum], 'USER_ID=:USER_ID', [':USER_ID' => $user_id]); //发送历史最高聘级短信 if($this->_sysConfig['smsEmpOpen']['VALUE']){ if(in_array($empLvSort,explode(",",$this->_sysConfig['smsEmp']['VALUE']))){ $realName = Info::getUserRealNameByUserId($user_id); $empLvDate = Date::convert(); $empLvName = EmployLevel::getNameById($empLv); $content = str_replace(['{%REAL_NAME%}', '{%EMP_LV_DATE%}', '{%EMP_LV%}'], [$realName, $empLvDate, $empLvName], $this->_sysConfig['smsContent']['VALUE']); $params = [ 'mobiles' => Info::getUserMobileByUserId($user_id), 'content' => $content, ]; SmsApi::instance()->clearError(); SmsApi::instance()->goSend($params); } } return true; } return false; } /** * 点位合作奖金 * @param $userId * @param $amount * @param null $type * @return bool * @throws Exception * @throws \yii\db\Exception */ private function _teamworkBonus($userId, $amount, $key) { 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; $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum); foreach ($teamwork as $value) { $bonus = Tool::formatPrice($amount * $value['DIVIDE_PERCENT'] * 0.01); if ($bonus <= 0) continue; $toUserInfo = CalcCache::getUserInfo($value['USER_ID'], $this->_periodNum); 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'] . '%']); 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'] . '%']); } } /** * 发送短信 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function sendSmsLoop(int $offset = 0) { $allData = UserInfo::findUseDbCalc()->select('USER_ID,ALLOW_RECONSUME_SMS_TO')->where('ALLOW_RECONSUME_SMS=1')->offset($offset)->limit($this->_limit)->all(); if ($allData) { $smsWallet = explode(",", $this->_sysConfig['smsWallet']['VALUE']); $smsFee = $this->_sysConfig['smsFee']['VALUE']; //获取剩余月份 $period = Period::instance(); $year = $period->getYear($this->_periodNum); $monthLeft = Period::getMonthLeft($this->_periodNum); $smsFee = Tool::formatPrice($smsFee * $monthLeft); $to = Date::yearEnd(); $transaction = Yii::$app->db->beginTransaction(); try { foreach ($allData as $data) { $userId = $data['USER_ID']; //过期续费 if ($data['ALLOW_RECONSUME_SMS_TO'] < Date::nowTime()) { foreach ($smsWallet as $item) { //1奖金钱包2现金钱包 if ($item == 1) { //看余额是否充足 if (Balance::getAvailableBalance($userId) < $smsFee){ UserInfo::updateAll(['ALLOW_RECONSUME_SMS' => 0], 'USER_ID=:USER_ID', [':USER_ID' => $userId]); continue; }; Balance::changeUserBonus($userId, 'bonus', -abs($smsFee), ['DEAL_TYPE_ID' => DealType::SMS, 'REMARK' => $year . '年复销提醒短信服务费'], false); UserInfo::updateAll(['ALLOW_RECONSUME_SMS_TO' => $to], 'USER_ID=:USER_ID', [':USER_ID' => $userId]); $data['ALLOW_RECONSUME_SMS_TO'] = $to; break; } elseif ($item == 2) { throw new Exception('不存在此方式'); break; } } } if ($data['ALLOW_RECONSUME_SMS_TO'] > Date::nowTime() && $mobile = Info::getUserMobileByUserId($userId)) { $realName = Info::getUserRealNameByUserId($userId); $reconsumPool = Reconsume::getUserReconsumePool($userId); $lastRechargeDate = $reconsumPool['toRechargeDate']; $isPass = $reconsumPool['isPass'] == 1 ? '合格' : '不合格'; $month = $period->getNowMonth(); $content = str_replace(['{%REAL_NAME%}', '{%LAST_RECHARGE_DATE%}', '{%MONTH%}', '{%IS_PASS%}'], [$realName, $lastRechargeDate, $month, $isPass], $this->_sysConfig['smsContent']['VALUE']); //todo 发短信函数 待测试 $params = [ 'mobiles' => $mobile, 'content' => $content, ]; SmsApi::instance()->clearError(); SmsApi::instance()->goSend($params); } unset($userId,$mobile,$realName,$reconsumPool,$lastRechargeDate,$isPass,$month,$content); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); return false; } unset($data); return $this->sendSmsLoop($offset + $this->_limit); } unset($allData); return true; } }