| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932 |
- <?php
- /**
- * Created by PhpStorm.
- * User: leo
- * Date: 2018/3/18
- * Time: 上午11:06
- */
- namespace common\helpers\bonus;
- use common\components\ActiveRecord;
- use common\helpers\DataBak;
- use common\helpers\Form;
- use common\helpers\LoggerTool;
- use common\helpers\Tool;
- use common\helpers\user\Balance;
- use common\helpers\user\Info;
- use common\helpers\user\Reconsume;
- use common\libs\api\sms\SmsApi;
- use common\models\Countries;
- use common\models\CurrencyConversions;
- use common\models\DealType;
- use common\models\EliteLevel;
- use common\models\FlowRemainPv;
- use common\models\PerfPeriod;
- use common\models\EmployLevel;
- use common\models\UserBonus;
- use common\models\UserPerfMonthUpdate;
- use common\models\UserPerformance;
- use common\models\UserPeriodPoints;
- use common\models\UserInfo;
- use common\models\UserPerf;
- use common\models\UserPerfUpdate;
- use common\models\UserTeamwork;
- use common\models\YearHighestEmpLv;
- use common\models\Order;
- use common\models\RemainPv;
- use yii\base\BaseObject;
- use yii\base\StaticInstanceTrait;
- use common\helpers\Cache;
- use common\helpers\Date;
- use common\models\CalcBonus;
- use common\models\CalcBonusBS;
- use common\models\CalcBonusQY;
- use common\models\PerfActiveUser;
- use common\models\PerfMonth;
- use common\models\User;
- use Yii;
- use common\models\Period;
- use yii\base\Exception;
- use yii\db\Expression;
- class BonusSend extends BaseObject {
- use StaticInstanceTrait;
- private $_limit = 1000;
- private $_appUserId = null;
- private $_sysConfig = [];
- private $_decLevelConfig = [];
- private $_empLevelConfig = [];
- private $_decRoleConfig = [];
- private $_errors = [];
- private $_periodNum = 0;
- private $_periodId;
- private $_isCalcMonth = 0;
- private $_isCalcYear = 0;
- private $_calcYear;
- private $_calcMonth;
- private $_calcYearMonth;
- private $_lastCalcYear;
- private $_lastCalcMonth;
- private $_lastCalcYearMonth;
- private $_workerId;
- private $_workerNum;
- public function init(int $periodNum = 0, $appUserId = null, $workerId = null, $workerNum = null) {
- parent::init();
- $this->_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;
- }
- /**
- * 挂网时处理虚假订单
- *
- */
- public function putFakeOrder() {
- echo('开始处理-假订单' . PHP_EOL);
- $sysConfig = Cache::getSystemConfig();
- $mesureUpCondition = $sysConfig['monthPcsPvFxCondition']['VALUE']; // 月达标条件 NG默认30
- $fakeOrder= Order::find()->where(['PERIOD_NUM'=>$this->_periodNum, 'IS_AUTO'=>'1'])->asArray()->all();
- foreach($fakeOrder as $fOrder){
- $oRemainPv=RemainPv::findOne(["USER_ID"=>$fOrder['USER_ID']]);
- $transactionRemain = \Yii::$app->db->beginTransaction();
- try{
- $fakeOrderPv = $oRemainPv->REMAIN_PV>=$mesureUpCondition?$mesureUpCondition:$oRemainPv->REMAIN_PV;
- $flowRemainPvModel = new FlowRemainPv();
- $flowRemainPvModel->ID = $this->_generateSn();
- $flowRemainPvModel->USER_ID = $fOrder['USER_ID'];
- $flowRemainPvModel->REMAIN_PV_FLOW = 0 - $fakeOrderPv;
- $flowRemainPvModel->REMAIN_PV_TOTAL = $oRemainPv->REMAIN_PV - $fakeOrderPv;
- $flowRemainPvModel->PERIOD_NUM = $this->_periodNum;
- $flowRemainPvModel->UPDATED_AT = Date::nowTime();
- $flowRemainPvModel->ORDER_SN = $fOrder['SN'];
- if(!$flowRemainPvModel->save()){
- $this->addErrors($flowRemainPvModel->getErrors());
- return false;
- }
- $oRemainPv->updateCounters(['REMAIN_PV'=>0-$fakeOrderPv]);
- $transactionRemain->commit();
- } catch (Exception $e) {
- $transactionRemain->rollBack();
- $this->addError('add', $e->getMessage());
- return null;
- }
- }
- echo('假订单处理完' . PHP_EOL);
- return true; // $flowRemainPvModel;
- }
- /**
- * 生成流水号
- * @return string
- */
- private function _generateSn() {
- return Date::today('Ymd') . $this->_random(10, 1);
- }
- /**
- * 生成随机数
- * @param $length
- * @param int $numeric
- * @return string
- */
- private function _random($length, $numeric = 0) {
- $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
- $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
- $hash = '';
- $max = strlen($seed) - 1;
- for ($i = 0; $i < $length; $i++) {
- $hash .= $seed[mt_rand(0, $max)];
- }
- return $hash;
- }
- /**
- * 进行奖金发放步骤
- * @return bool
- */
- public function sendStep() {
- try {
- $t1 = microtime(true);
- // 初始化
- $this->initTask();
- echo('挂网开始');
- // 改变状态
- $this->setSendStatus('start');
- // 发放荣衔级别(Honor/Emp)、Elite级别
- $this->sentMemberLevel();
- $this->_updatePercent(30);
- $t2 = microtime(true);
- echo('更新会员级别完成,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
- // 发放奖金
- $this->sendBonusLoop();
- $this->_updatePercent(80);
- $t3 = microtime(true);
- echo('发放奖金完成,耗时:' . round($t3 - $t2, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
- echo('全部奖金发放完成,耗时:'.round($t3 - $t1, 3).',内存使用:'.(round(memory_get_usage()/1024/1024, 3)).'MB'.PHP_EOL);
- $this->_updatePercent(100);
- } catch (\Exception $e) {
- LoggerTool::error('sendBonus' . sprintf('File【%s】, Line【%s】, Msg【%s】', $e->getFile(), $e->getLine(), $e->getMessage()));
- $this->addError('sendBonus', sprintf('%s',$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');
- }
- /**
- * 发放奖金
- * @return bool
- * @throws \yii\db\Exception
- */
- public function sendBonusLoop(): bool
- {
- echo sprintf("时间:[%s] 奖金挂网" . PHP_EOL, date('Y-m-d H:i:s', time()));
- $periodNum = $this->_periodNum;
- // 从奖金结算表中获取当期未发放的所有数据
- $allData = CalcBonus::find()
- ->select('ID, USER_ID, PERIOD_NUM, BONUS_TOTAL, MANAGE_TAX, BONUS_PB')
- ->where('IS_SENT=0 AND PERIOD_NUM=:PERIOD_NUM AND (BONUS_TOTAL>0 OR BONUS_PB>0)', [':PERIOD_NUM' => $this->_periodNum])
- ->asArray()
- ->all();
- if ($allData) {
- $transaction = Yii::$app->db->beginTransaction();
- try {
- foreach ($allData as $key => $data) {
- // 用户奖金发放
- if ($data['BONUS_TOTAL'] > 0) {
- Balance::changeUserBonus($data['USER_ID'], 'bonus', $data['BONUS_TOTAL'],
- [
- 'CALC_ID' => $data['ID'],
- 'REMARK' => 'From Period ' . $data['PERIOD_NUM'],
- 'PERIOD_NUM' => $periodNum,
- 'MANAGE_TAX' => $data['MANAGE_TAX'],
- 'BONUS_TOTAL' => $data['BONUS_TOTAL'],
- 'DEAL_TYPE_ID' => DealType::BONUS_SEND,
- 'SORT' => $key * 10,
- 'BONUS_ISSUE' => true,
- ]);
- }
- // 绩效奖金发放
- if ($data['BONUS_PB'] > 0) {
- // 汇率
- $countryId = User::getEnCodeInfo($data['USER_ID'])['COUNTRY_ID'];
- $currencyId = Countries::getById($countryId)['LOCAL_CURRENCY_ID'];
- $bonusConversions = CurrencyConversions::getToUSDRate($currencyId, 'bonus');
- // 奖金转化为会员所在国家汇率后进行发放
- $localAmount = $data['BONUS_PB'] * $bonusConversions;
- // 奖金发放
- UserPerformance::sentUserPerformance($data['USER_ID'], $localAmount, $data['PERIOD_NUM']);
- }
- // 把记录标记为已发放状态
- Period::updateAll(['IS_SENT' => 1, 'SENT_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $data['PERIOD_NUM']]);
- CalcBonus::updateAll(['IS_SENT' => 1, 'SENT_AT' => Date::nowTime()], 'ID=:ID', [':ID' => $data['ID']]);
- unset($key, $data);
- }
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollBack();
- $this->addError('sendBonus', '奖金发放失败,原因:' . $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage());
- return false;
- }
- }
- return true;
- }
- /**
- * 蓝星奖金(即新的管理奖),更新会员聘级
- * @param int $offset
- * @return bool
- * @throws \yii\db\Exception
- */
- public function updateEmpLevel(int $offset = 0) {
- if ($this->_isCalcMonth) {
- $empLv = EmployLevel::getIdConvertLevelSortCache();
- $allData = CalcBonusBS::find()
- ->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();
- LoggerTool::info($allData);
- //@todo 用户级别不变则不更新
- $defaultEmpLv = EmployLevel::getDefaultLevelId();
- if ($allData) {
- $transaction = Yii::$app->db->beginTransaction();
- try {
- foreach ($allData as $data) {
- // 蓝星奖计算的最新聘级
- $latestEmpLv = $data['LEVEL_ID']; // 本期计算最新管理级别
- $latestEmpLvSort = $empLv[$latestEmpLv]; // 当前蓝星计算的聘级 级别值
- if ($defaultEmpLv == $latestEmpLv) {
- continue;
- }
- // 用户存储的最高聘级
- $user = CalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
- $highestEmpLv = $user['EMP_LV']; // 用户的历史最高聘级
- $highestEmpLvSort = $empLv[$highestEmpLv]; // 历史最高聘级的 级别值
- // 如果当前期的聘级高于用户表的最高聘级,则进行更新
- if ($latestEmpLvSort > $highestEmpLvSort) {
- User::updateAll(['EMP_LV' => $latestEmpLv], 'ID=:USER_ID', [':USER_ID' => $data['USER_ID']]);
- User::deleteBaseInfoFromRedis($data['USER_ID']);
- }
- // 更新最新用户表级别
- User::updateAll([
- 'LAST_EMP_LV' => $latestEmpLv,
- 'LAST_EMP_LV_UPDATED_AT' => time(),
- 'LAST_EMP_LV_UPDATED_PERIOD' => $this->_periodNum
- ], '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);
- // 刷新会员EmpLv为0
- User::updateAll([
- 'LAST_EMP_LV' => '',
- 'LAST_EMP_LV_UPDATED_AT' => time(),
- 'LAST_EMP_LV_UPDATED_PERIOD' => $this->_periodNum,
- ], 'LAST_EMP_LV_UPDATED_PERIOD < :PERIOD_NUM AND LAST_EMP_LV <> ""', [':PERIOD_NUM' => $this->_periodNum]);
- User::deleteAllBaseInfoFromRedis();
- }
- return true;
- }
- /**
- * @return bool
- */
- public function sentMemberLevel(): bool
- {
- $transaction = Yii::$app->db->beginTransaction();
- try {
- $db = Yii::$app->db;
- // 刷新所有会员最新EliteLevel和最新EmpLevel为默认等级
- User::updateAll(
- [
- 'LAST_EMP_LV' => EmployLevel::getDefaultLevelId(),
- 'LAST_EMP_LV_UPDATED_AT' => time(),
- 'LAST_EMP_LV_UPDATED_PERIOD' => $this->_periodNum,
- 'LAST_ELITE_LV' => EliteLevel::getDefaultLevelId(),
- 'LAST_ELITE_LV_UPDATED_AT' => time(),
- 'LAST_ELITE_LV_UPDATED_PERIOD' => $this->_periodNum,
- ]);
- // 刷新会员最高EliteLevel和最高EmpLevel(统一数据,更新为默认Elite级别)
- User::updateAll(['EMP_LV' => EmployLevel::getDefaultLevelId()], "EMP_LV = '' OR EMP_LV IS NULL");
- User::updateAll(['ELITE_LV' => EliteLevel::getDefaultLevelId()], "ELITE_LV = '' OR ELITE_LV IS NULL");
- $sql =<<<SQL
- UPDATE `AR_USER` `user`
- INNER JOIN `AR_CALC_BONUS` `bonus` ON `user`.`ID` = `bonus`.`USER_ID` AND `bonus`.`PERIOD_NUM` = :PERIOD_NUM
- SET
- `user`.`EMP_LV` = `bonus`.`HIGHEST_HONOR_LV`,
- `user`.`LAST_EMP_LV` = `bonus`.`LAST_EMP_LV`,
- `user`.`LAST_EMP_LV_UPDATED_AT` = :UPDATED_AT,
- `user`.`LAST_EMP_LV_UPDATED_PERIOD` = :PERIOD_NUM,
-
- `user`.`ELITE_LV` = `bonus`.`HIGHEST_ELITE_LV`,
- `user`.`LAST_ELITE_LV` = `bonus`.`LAST_ELITE_LV`,
- `user`.`LAST_ELITE_LV_UPDATED_AT` = :UPDATED_AT,
- `user`.`LAST_ELITE_LV_UPDATED_PERIOD` = :PERIOD_NUM
- WHERE
- `bonus`.`PERIOD_NUM` = :PERIOD_NUM AND `bonus`.`IS_SENT` = 0
- SQL;
- $db->createCommand($sql)
- ->bindValues(
- [
- ':PERIOD_NUM' => $this->_periodNum,
- ':UPDATED_AT' => time(),
- ])
- ->execute();
- $transaction->commit();
- // 刷新本期无Elite的用户级别
- // 删除缓存中的会员信息
- User::deleteAllBaseInfoFromRedis();
- } catch (Exception $e) {
- $transaction->rollBack();
- $this->addError('sendLevelFailed', '发放会员级别失败,原因:' . $e->getMessage());
- return false;
- }
- return true;
- }
- // 更活跃会员,将is_send改成1
- public function updateActiveUser() {
- $ret = PerfActiveUser::updateAll(
- ['IS_SENT' => 1],
- 'PERIOD_NUM=:PERIOD_NUM AND IS_SENT=:IS_SENT',
- ['IS_SENT'=>0, 'PERIOD_NUM'=>$this->_periodNum]
- );
- return $ret;
- }
- /**
- * 更新会员的累计业绩
- * @param int $offset
- * @return bool
- * @throws \yii\db\Exception
- */
- public function updateUserPerf(int $offset = 0) {
- $allData = PerfPeriod::find()
- ->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::find()
- ->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) {
- // 判断本期是否已经更新过业绩
- if (!UserPerfUpdate::find()
- ->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()
- $allData = PerfMonth::find()
- ->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()
- if (UserPerf::find()
- ->where('USER_ID=:USER_ID', [':USER_ID' => $data['USER_ID']])->exists()) {
- // 判断本期是否已经更新过业绩
- // if (!UserPerfMonthUpdate::findUseDbCalc()
- if (!UserPerfMonthUpdate::find()
- ->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 int $offset
- * @return bool
- * @throws \yii\db\Exception
- */
- public function sendSmsLoop(int $offset = 0) {
- // $allData = UserInfo::findUseDbCalc()
- $allData = UserInfo::find()
- ->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;
- }
- }
|