<?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\Tool;
use common\helpers\user\Balance;
use common\helpers\user\Info;
use common\helpers\user\Reconsume;
use common\helpers\user\Status;
use common\libs\api\sms\SmsApi;
use common\libs\swoole\Process;
use common\models\DealType;
use common\models\FlowRemainPv;
use common\models\PerfPeriod;
use common\models\DecOrder;
use common\models\EmployLevel;
use common\models\UserBonus;
use common\models\UserPerfMonthUpdate;
use common\models\UserPeriodPoints;
use common\models\UserWallet;
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\helpers\user\Cash;
use common\models\CalcBonus;
use common\models\CalcBonusBD;
use common\models\CalcBonusBS;
use common\models\CalcBonusGX;
use common\models\CalcBonusQY;
use common\models\CalcBonusTG;
use common\models\FlowBonus;
use common\models\PerfActiveUser;
use common\models\PerfMonth;
use common\models\User;
use Yii;
use common\models\Period;
use common\models\Transfer;
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']; // 月达标条件 NC默认300
        $fakeOrder= Order::find()->where(['PERIOD_NUM'=>$this->_periodNum, 'IS_AUTO'=>'1'])->asArray()->all();
//        print_r($fakeOrder);exit;
        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->putFakeOrder();
            // 先把有remainPv的订单处理一下，将remainPv加入到remain_pv及流水表
            echo('处理当期REMAIN PV ' . date('Y-m-d  H:i:s', time()) . PHP_EOL);
            $this->_calcRemainPv();
            $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->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;
    }

    /**
     * 处理order表中有remain_pv的订单
     * 将结果写入到remainPv相关表中
     *
     */
    private function _calcRemainPv(){
        $sysConfig = Cache::getSystemConfig();
        $mesureUpCondition =  $sysConfig['monthPcsPvFxCondition']['VALUE']; // 月达标条件 NC默认300
        $orders = Order::find()->where('PERIOD_NUM=:PERIOD_NUM AND REMAIN_PV>0 AND IS_DELETE=0',[':PERIOD_NUM'=>$this->_periodNum])->asArray()->all();
        foreach($orders as $order){
            $oRemainPv = RemainPv::find()->where(['USER_ID' => $order['USER_ID']])->one();
            $myRemainPv = $oRemainPv?$oRemainPv['REMAIN_PV']:0;
            $transactionRemain = \Yii::$app->db->beginTransaction();
            try{
                $flowRemainPvModel = new FlowRemainPv();
                $flowRemainPvModel->ID = $this->_generateSn();
                $flowRemainPvModel->USER_ID = $order['USER_ID'];
                $flowRemainPvModel->REMAIN_PV_FLOW = $order['REMAIN_PV'];
                $flowRemainPvModel->REMAIN_PV_TOTAL = $oRemainPv?$oRemainPv['REMAIN_PV']:0 + $order['REMAIN_PV'];
                $flowRemainPvModel->PERIOD_NUM = $this->_periodNum;
                $flowRemainPvModel->UPDATED_AT = Date::nowTime();
                $flowRemainPvModel->ORDER_SN = $order['SN'];
                if(!$flowRemainPvModel->save()){
                    $this->addErrors($flowRemainPvModel->getErrors());
                    return false;
                }

                $oRemainPv = RemainPv::find()->where(['USER_ID' => $order['USER_ID']])->one();
                if($oRemainPv){
                    $oRemainPv->updateCounters(['REMAIN_PV'=>$order['REMAIN_PV']]);
                }else{
                    $remainPvModel = new RemainPv();
                    $remainPvModel->ID = $this->_generateSn();
                    $remainPvModel->USER_ID = $order['USER_ID'];
                    $remainPvModel->UPDATED_AT = Date::nowTime();
                    $remainPvModel->REMAIN_PV = $order['REMAIN_PV'];
                    $remainPvModel->STATUS = 1;
                    if(!$remainPvModel->save()){
                        $this->addErrors($remainPvModel->getErrors());
                        return false;
                    }
                }
                $transactionRemain->commit();
            } catch (Exception $e) {
                $transactionRemain->rollBack();
                $this->addError('add', $e->getMessage());
                return null;
            }
        }
        return null;
    }

    /**
     * 需要多进程执行的任务
     * @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['REAL_BONUS_GX'],
                            'GL' => $data['BONUS_GL'],
                            'BS' => $data['BONUS_BS'],
                            'ST' => $data['BONUS_ST'],

                            '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_ST' => $data['ORI_BONUS_ST'],

                            //'RECONSUME_POINTS_TOTAL' => $data['RECONSUME_POINTS'], 2022/05/17 复消积分,直接发放到余额账户
                            '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,
                        ]);
//                        $this->_teamworkBonus($data['USER_ID'], $periodAmount, $key);
                    }

                    //发放重消积分
                    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,
                        ]);
                        // 2022/05/17 复消积分,直接发放到余额账户
                        // Cash::changeUserCash(
                        //     $data['USER_ID'],
                        //     'CASH',
                        //     abs($data['RECONSUME_POINTS']),
                        //     [
                        //     'TRANSFER_SN' => Transfer::generateSN(),
                        //     'DEAL_TYPE_ID' => DealType::BONUS_SEND,
                        //     'REMARK' => '复销点数发放'
                        //     ]
                        // );
                    }

                    //发放兑换积分
                    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,
                        ]);
                    }
                    // 把记录标记为已发放状态
                    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->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 = CalcBonusBS::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();
            //@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);
            }

            // 刷新会员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();

            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;
    }

    // /**
    //  * 更新会员聘级
    //  * @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;
    }
}
