'fwCoefficientFromZc', 'FX_CASH' => 'fwCoefficientFromFxCash', 'FX_POINT' => 'fwCoefficientFromFxPoint', ]; const JX_STANDARD_BASE_AMOUNT = 10000; const JX_STANDARD_MAX_TIMES = 50; const JX_STANDARD_BONUS_PERCENT = 15; //最小报单pv const MIN_BD_PV = 980; /** * 1、抓取所有报单、订单,把能当时产生业绩的报单存入业绩单。例如注册单,订单 * 2、从业绩单中循环,并计算上下级业绩 * 3、计算级别 * 4、计算各个奖项 * 5、给会员追加总业绩,在结算中不妥,打算把追加总业绩放到挂网中,因为结算完成以后的业绩都不是最终的,有可能还会变 */ /** * 初始化 */ public function init() { parent::init(); } /** * 设置期数 * @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; } /** * 开始执行结算步骤 * @param $periodNum * @param null $handleUserId * @return bool */ public function calcStep($periodNum, $handleUserId = null) { try { $this->_errors = []; $this->setPeriodNum($periodNum); $this->_handleUserId = $handleUserId; $t1 = microtime(true); // 初始化结算任务 $this->initCalcTask(); // 设置结算状态 $this->setCalcStatus('start'); // 清空所有本期结算用到的缓存 CalcCache::clearCalcBonusCache($this->_periodNum); // 清空相关表数据 $this->clearCalcTableData(); $t2 = microtime(true); echo('初始化、清空缓存及相关数据表完成,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(5); $t3 = microtime(true); $this->_updatePercent(10); // 奖金部分 if($this->_sysConfig['openFW']['VALUE']) { $this->calcBonusBDStepOne(); $this->calcBonusBDStepTwo(); } $t4 = microtime(true); echo('计算服务奖'.($this->_sysConfig['openFW']['VALUE']?'完成':'关闭').',耗时:' . round($t4 - $t3, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(15); if($this->_sysConfig['openTG']['VALUE']) { $this->calcBonusTG(); } $t5 = microtime(true); echo('计算推广奖'.($this->_sysConfig['openTG']['VALUE']?'完成':'关闭').',耗时:' . round($t5 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(20); if($this->_sysConfig['openXF']['VALUE']) { if( $this->_sysConfig['consumeRecPercent']['VALUE'] > 0 ) { $this->calcBonusXFToRec(); } if( $this->_sysConfig['consumeSelfPercent']['VALUE'] > 0 ) { $this->calcBonusXFToSelf(); } } $t6 = microtime(true); echo('计算消费奖'.($this->_sysConfig['openXF']['VALUE']?'完成':'关闭').',耗时:' . round($t6 - $t5, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(25); if($this->_sysConfig['openYJ']['VALUE']) { $this->calcBonusBdYJ(); } $t7 = microtime(true); echo('计算报单业绩奖'.($this->_sysConfig['openYJ']['VALUE']?'完成':'关闭').',耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(30); if($this->_sysConfig['fxOpenYJ']['VALUE']) { $this->calcBonusFxYJ(); } $t8 = microtime(true); echo('计算复消业绩奖'.($this->_sysConfig['fxOpenYJ']['VALUE']?'完成':'关闭').',耗时:' . round($t8 - $t7, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(35); if($this->_sysConfig['openQY']['VALUE']) { $this->calcBonusQY(); $this->calcBonusBdQY(); $this->calcBonusFxQY(); } $t9 = microtime(true); echo('计算团队奖'.($this->_sysConfig['openQY']['VALUE']?'完成':'关闭').',耗时:' . round($t9 - $t8, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(65); if($this->_sysConfig['openGX']['VALUE']) { $this->calcBonusGXBefore(); $this->calcBonusGX(); } $t11 = microtime(true); echo('计算共享奖'.($this->_sysConfig['openGX']['VALUE']?'完成':'关闭').',耗时:' . round($t11 - $t9, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(68); if($this->_sysConfig['openGL']['VALUE']) { $this->calcBonusBdGL(); } $t13 = microtime(true); echo('计算报单管理奖'.($this->_sysConfig['openGL']['VALUE']?'完成':'关闭').',耗时:' . round($t13 - $t11, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(50); // if($this->_sysConfig['fxOpenGL']['VALUE']) { // $this->calcBonusFxGL(); // } // $t14 = microtime(true); // echo('计算复消管理奖'.($this->_sysConfig['fxOpenGL']['VALUE']?'完成':'关闭').',耗时:' . round($t14 - $t13, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); // $this->_updatePercent(70); if($this->_sysConfig['openYC']['VALUE']) { $this->calcBonusYCStepOne(); $this->calcBonusYCStepTwo(); } $t16 = microtime(true); echo('计算荣衔奖'.($this->_sysConfig['openYC']['VALUE']?'完成':'关闭').',耗时:' . round($t16 - $t13, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(55); if($this->_sysConfig['openVIP']['VALUE']) { $this->calcBonusVIP(); } $t17 = microtime(true); echo('计算VIP奖'.($this->_sysConfig['openVIP']['VALUE']?'完成':'关闭').',耗时:' . round($t17 - $t16, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(60); if($this->_sysConfig['openJXS']['VALUE']) { $this->calcBonusStandard(); } $t18 = microtime(true); echo('计算达标奖'.($this->_sysConfig['openJXS']['VALUE']?'完成':'关闭').',耗时:' . round($t18 - $t17, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(65); // 蓝星奖入库,实际上是插入有奖金会员数据缓存中. // 调用存储过程,计算蓝星管理奖金 $this->calcBsProcedure(); // 将有【蓝星业绩奖金】的用户加入到有奖金缓存用户中 $this->calcBonusBsYJ(); // 将有【蓝星管理奖金】的用户加入到有奖金缓存用户中 $this->calcBonusBsGL(); $t18temp = microtime(true); echo('计算蓝星奖'.($this->_sysConfig['openGL']['VALUE']?'完成':'关闭').',耗时:' . round($t18temp - $t18, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(65); $this->calcBonusZoneBS($this->_sysConfig['openTravel']); $t18travel = microtime(true); echo('计算旅游奖' . ($this->_sysConfig['openTravel']['VALUE'] ? '完成' : '关闭') . ',耗时:' . round($t18travel - $t18temp, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(67); $this->calcBonusZoneBS($this->_sysConfig['openCar']); $t18car = microtime(true); echo('计算名车奖' . ($this->_sysConfig['openCar']['VALUE'] ? '完成' : '关闭').',耗时:' . round($t18car - $t18travel, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(68); $this->calcBonusZoneBS($this->_sysConfig['openHouse']); $t18house = microtime(true); echo('计算豪宅奖' . ($this->_sysConfig['openHouse']['VALUE'] ? '完成' : '关闭').',耗时:' . round($t18house - $t18car, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(69); //把奖金会员写入缓存 $this->loopMonthBonusUserFromDbToCache(); $t19 = microtime(true); echo('奖金会员写入缓存完成,耗时:' . round($t19 - $t18, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(70); //奖金写库 // 这里增加新的奖金入库操作. $this->loopBonusUsers(); // 入库完成,将各个奖金计算流水会员聘级,更新成蓝星奖当时计算的聘级 $this->loopCalcBlueEmpLv(); $this->_updatePercent(75); unset($calcWrite); $t20 = microtime(true); echo('奖金写库操作完成,耗时:' . round($t20 - $t19, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); //把本期奖金会员入库 - 把缓存中的月奖用户信息存到数据库.存储过程的入库不在这里进行,这里代码取的缓存,存储过程没有缓存,在上面进行入库 $this->loopMonthBonusUserToDb(); $t21 = microtime(true); echo('奖金会员入库完成,耗时:' . round($t21 - $t20, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); $this->_updatePercent(80); // 计算基础积分,不可以奖金入库之前计算这样可能会丢掉只有本期的奖金的会员 // $this->calcBaseScore(); // $this->_updatePercent(90); // $t22 = microtime(true); // echo('计算基础积分,耗时:' . round($t22 - $t21, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); //积分入库 // $this->loopWriteScore(); // $this->_updatePercent(100); // $t23 = microtime(true); // echo('积分写库操作完成,耗时:' . round($t23 - $t22, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); //@todo 计算房产奖 $t30 = microtime(true); echo('结算全部完成,共耗时:' . round($t30 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); } catch (\Exception $e) { $this->errorCalcTask(); $this->addError('calc', $e->getMessage()); return false; } return true; } /** * 结算完成 */ public function endCalcTask() { // 更新结算状态 $this->setCalcStatus('end'); } /** * 结算错误 */ public function errorCalcTask() { // 清空所有本期结算用到的缓存 CalcCache::clearCalcBonusCache($this->_periodNum); // 更新结算状态 $this->setCalcStatus('fail'); } /** * 初始化结算任务 * @throws \yii\db\Exception */ public function initCalcTask() { $this->_sysConfig = Cache::getSystemConfig(); $this->_decLevelConfig = Cache::getDecLevelConfig(); $this->_empLevelConfig = Cache::getEmpLevelConfig(); $this->_decRoleConfig = CalcCache::getDecRoleConfig($this->_periodNum); $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); $this->_calcMonthPeriodNumCount = $periodObj->getYearMonthAllPeriodNumCount($this->_calcYear, $this->_calcMonth); $lastYearMonthArr = $periodObj->getLastMonth($periodNum); $this->_lastCalcYear = $lastYearMonthArr['year']; $this->_lastCalcMonth = $lastYearMonthArr['month']; $this->_lastCalcYearMonth = $lastYearMonthArr['yearMonth']; $this->_lastPeriodNum = $periodNum - 1; if (Period::isExistsPeriodNum($this->_lastPeriodNum)) { $this->_lastPeriodYear = $periodObj->getYear($this->_lastPeriodNum); $this->_lastPeriodMonth = $periodObj->getMonth($this->_lastPeriodNum); $this->_lastPeriodYearMonth = $periodObj->getYearMonth($this->_lastPeriodNum); } else { $this->_lastPeriodYear = 0; $this->_lastPeriodMonth = 0; $this->_lastPeriodYearMonth = 0; } $this->_cfTotalPercent = CalcCache::getCFTotalPercent($this->_periodNum); $this->_lxTotalPercent = CalcCache::getLXTotalPercent($this->_periodNum); $this->_pvRatio = $this->_sysConfig['pvRatio']['VALUE']; if($perfCompany = PerfCompany::findOne(['CALC_MONTH' => $this->_calcYearMonth])){ $this->_companyMonthPerf = $perfCompany['PV']; } } /** * 设置结算状态 * @param $type * start|end|fail */ public function setCalcStatus($type) { if ($type == 'start') { Period::updateAll(['IS_CALCING' => 1, 'IS_CALCULATED' => Period::CALCULATE_NONE, 'CALCULATE_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } elseif ($type == 'end') { Period::updateAll(['IS_CALCING' => 0, 'IS_CALCULATED' => Period::CALCULATE_FINISH, 'CALCULATED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } elseif ($type == 'fail') { Period::updateAll(['IS_CALCING' => 0, 'IS_CALCULATED' => Period::CALCULATE_FAIL, 'CALCULATED_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); } } /** * 清空相关表数据 */ public function clearCalcTableData() { // 奖金表 CalcBonus::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusQY::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusBD::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusTG::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusYJ::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusGX::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusGL::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); // 月结时要清空的数据 if ($this->_isCalcMonth) { CalcBonusYC::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusVIP::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusStandard::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); ScoreMonth::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); CalcBonusZone::pageDeleteAll('PERIOD_NUM='.$this->_periodNum); } } /** * === 奖金结算部分 === */ /** * 服务奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBD(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasBDUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { $decInfo = CalcCache::getBDUsersInfo($userId, $this->_periodNum); if( !$decInfo ) continue; //服务奖使用报单原金额 $decBonus = Tool::formatPrice($decInfo['DEC_AMOUNT'] * $this->_sysConfig['decPercent']['VALUE'] / 100); if ($decBonus <= 0) continue; $bonusUserId = $decInfo['DEC_ID']; if( !$bonusUserId ) continue; // 获取会员的报单级别 $bonusUserInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //总金额限制 $decBonus = $this->bonusTotalLimit($decBonus, $bonusUserId, $bonusUserInfo['REC_NUM'], $bonusUserInfo['ZC_AMOUNT']); if( $decBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $decBonus); // 把对碰后的奖金存入缓存中 CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_BD', $decBonus, $deductData); //来源会员信息 $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //服务奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $fromUserInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $fromUserInfo['EMP_LV'], 'LAST_FROM_STATUS' => $fromUserInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'ORI_BONUS' => $decBonus, 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'decInfoArr' => $decInfo, 'decPercentConfig' => $this->_sysConfig['decPercent']['VALUE'], 'recNum' => $bonusUserInfo['REC_NUM'], 'decAmount' => $bonusUserInfo['ZC_AMOUNT'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($decInfo, $decBonus, $bonusUserId, $bonusUserInfo, $userId, $deductData, $fromUserInfo); } CalcBonusBD::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusBD($offset + $this->_limit); } unset($allData); return true; } /** * 推广奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusTG(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; //个人业绩都算推荐奖,包括报单和复消、二次购物 $perfPv = $perfData['PV_PCS_ZC'] ?? 0; if( $perfPv <= 0 ) continue; //推广奖使用个人PCS $recBonus = Tool::formatPrice($perfPv * $this->_sysConfig['recPercent']['VALUE'] / 100); if ($recBonus <= 0) continue; // 把对碰后的奖金存入缓存中 $perfUserInfo = CalcCache::getUserInfo($userId, $periodNum); $bonusUserId = $perfUserInfo['REC_UID'] ?? ''; if( !$bonusUserId ) continue; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //判断级别上限 // $recBonus = $this->declarationLevelCap($recBonus, $bonusUserId, $userBaseInfo['DEC_LV']); // if( $recBonus <= 0 ) continue; $recBonus = $this->bonusTotalLimit($recBonus, $bonusUserId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $recBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $recBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_TG', $recBonus, $deductData); //来源会员信息 $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //推广奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $fromUserInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $fromUserInfo['EMP_LV'], 'LAST_FROM_STATUS' => $fromUserInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $recBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfPv' => $perfPv, 'recPercentConfig' => $this->_sysConfig['recPercent']['VALUE'], 'recNum' => $userBaseInfo['REC_NUM'], 'decAmount' => $userBaseInfo['ZC_AMOUNT'], 'decLevel' => $userBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($perfData, $perfPv, $perfUserInfo, $recBonus, $bonusUserId, $userBaseInfo, $userId, $deductData, $fromUserInfo); } CalcBonusTG::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusTG($offset + $this->_limit); } unset($allData); return true; } /** * 消费奖-推荐人 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusXFToRec(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; //个人业绩都算推荐奖,包括报单和复消、二次购物 $perfPv = $perfData['PV_PCS_FX'] ?? 0; if( $perfPv <= 0 ) continue; //推广奖使用个人PCS $recBonus = Tool::formatPrice($perfPv * $this->_sysConfig['consumeRecPercent']['VALUE'] / 100); if ($recBonus <= 0) continue; // 把对碰后的奖金存入缓存中 $perfUserInfo = CalcCache::getUserInfo($userId, $periodNum); $bonusUserId = $perfUserInfo['REC_UID'] ?? ''; if( !$bonusUserId ) continue; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //判断级别上限 // $recBonus = $this->declarationLevelCap($recBonus, $bonusUserId, $userBaseInfo['DEC_LV']); // if( $recBonus <= 0 ) continue; $recBonus = $this->bonusTotalLimit($recBonus, $bonusUserId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $recBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $recBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_XF', $recBonus, $deductData); //来源会员信息 $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //推广奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $fromUserInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $fromUserInfo['EMP_LV'], 'LAST_FROM_STATUS' => $fromUserInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $recBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfPv' => $perfPv, 'recPercentConfig' => $this->_sysConfig['consumeRecPercent']['VALUE'], 'recNum' => $userBaseInfo['REC_NUM'], 'decAmount' => $userBaseInfo['ZC_AMOUNT'], 'decLevel' => $userBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($perfData, $perfPv, $perfUserInfo, $recBonus, $bonusUserId, $userBaseInfo, $userId, $deductData, $fromUserInfo); } CalcBonusXF::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusXFToRec($offset + $this->_limit); } unset($allData); return true; } /** * 消费奖-自己 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusXFToSelf(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; //个人业绩都算推荐奖,包括报单和复消、二次购物 $perfPv = $perfData['PV_PCS_FX'] ?? 0; if( $perfPv <= 0 ) continue; //推广奖使用个人PCS $recBonus = Tool::formatPrice($perfPv * $this->_sysConfig['consumeSelfPercent']['VALUE'] / 100); if ($recBonus <= 0) continue; // 把对碰后的奖金存入缓存中 // $perfUserInfo = CalcCache::getUserInfo($userId, $periodNum); $bonusUserId = $userId; if( !$bonusUserId ) continue; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //判断级别上限 // $recBonus = $this->declarationLevelCap($recBonus, $bonusUserId, $userBaseInfo['DEC_LV']); // if( $recBonus <= 0 ) continue; $recBonus = $this->bonusTotalLimit($recBonus, $bonusUserId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $recBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $recBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_XF', $recBonus, $deductData); //来源会员信息 $fromUserInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //推广奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $fromUserInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $fromUserInfo['EMP_LV'], 'LAST_FROM_STATUS' => $fromUserInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $recBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfPv' => $perfPv, 'recPercentConfig' => $this->_sysConfig['consumeSelfPercent']['VALUE'], 'recNum' => $userBaseInfo['REC_NUM'], 'decAmount' => $userBaseInfo['ZC_AMOUNT'], 'decLevel' => $userBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($perfData, $perfPv, $recBonus, $bonusUserId, $userBaseInfo, $userId, $deductData, $fromUserInfo); } CalcBonusXF::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusXFToSelf($offset + $this->_limit); } unset($allData); return true; } /** * 服务奖第一步 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBDStepOne(int $offset = 0) { echo sprintf("时间:[%s]服务奖第【1】步,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; // $decRoleBonusFrom = explode(',', $this->_sysConfig['decRoleBonusFrom']['VALUE']); $validPvPcs = 0; foreach ($decRoleBonusFrom as $orderType) { $orderTypeName = sprintf('PV_PCS_%s', $orderType); $orderTypeValue = $perfData[$orderTypeName] ?? 0; $coefficientName = self::ORDER_TYPE_TO_FW_COEFFICIENT[$orderType]; $coefficient = $this->_sysConfig[$coefficientName]['VALUE'] ?? 1; $validPvPcs += $orderTypeValue * $coefficient; unset($orderType, $orderTypeName, $orderTypeValue, $coefficientName, $coefficient); } unset($perfData, $decRoleBonusFrom); if ( $validPvPcs <= 0 ) continue; $this->loopRelationParentDo($userId, function ($parent) use($userId, $validPvPcs){ //判断parent的报单中心级别 和 服务奖比例 $bonusUserId = $parent['PARENT_UID']; //计算级别之后更新过userInfo的缓存,缓存中级别发生了变化 $bonusUserInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $isDec = $bonusUserInfo['IS_DEC']; if($isDec == 0) return self::LOOP_CONTINUE; $decRoleId = $bonusUserInfo['DEC_ROLE_ID']; if( !$decRoleId ) return self::LOOP_CONTINUE; if( !isset($this->_decRoleConfig[$decRoleId]) ) return self::LOOP_CONTINUE; $parentDecRoleLevel = $this->_decRoleConfig[$decRoleId]; $parentFwBonusPercent = $parentDecRoleLevel['FW_BONUS_PERCENT'] ?? 0; $cacheMaxPercent = CalcCache::fwMaxBonusPercent($userId, $this->_periodNum); $diffPercent = $parentFwBonusPercent - $cacheMaxPercent; if( $diffPercent <= 0 ) return self::LOOP_CONTINUE; $fwBonus = $validPvPcs * $diffPercent / 100; if( $fwBonus <= 0 ) return self::LOOP_CONTINUE; //给本人添加服务奖比例 CalcCache::fwMaxBonusPercent($userId, $this->_periodNum, $parentFwBonusPercent); //记录奖金和奖金来源到缓存 并实现在缓存中奖金累加 CalcCache::saveFwBonusList($bonusUserId, $this->_periodNum, $fwBonus, ['fromUid'=>$userId, 'fromPvPcs'=>$validPvPcs]); CalcCache::addHasFwBonusUsers($bonusUserId, $this->_periodNum); //达到最大的比例就不在向上找了 // if( $parentFwBonusPercent >= $maxLevelPercent ) return self::LOOP_FINISH; unset($bonusUserId, $bonusUserInfo, $isDec, $decRoleId, $parentDecRoleLevel, $parentFwBonusPercent, $cacheMaxPercent, $diffPercent, $fwBonus); }); unset($userId, $validPvPcs); } unset($allData, $insertBonusData); return $this->calcBonusBDStepOne($offset + $this->_limit); } unset($allData); return true; } /** * 服务奖第二步 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBDStepTwo(int $offset = 0) { echo sprintf("时间:[%s]服务奖第【2】步,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $allData = CalcCache::getHasFwBonusUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { $fwBonusData = CalcCache::getFwBonusList($userId, $this->_periodNum); if( !$fwBonusData ) continue; $fwBonus = $fwBonusData['fwBonus'] ?? 0; if( $fwBonus <=0 ) continue; //总金额限制 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $fwBonus = $this->bonusTotalLimit($fwBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $fwBonus <= 0 ) continue; //扣除相应的复消积分和管理费 // $deductData = $this->deduct($userId, $fwBonus); CalcCache::bonus($userId, $this->_periodNum, 'BONUS_BD', $fwBonus); $decRoleId = $userBaseInfo['DEC_ROLE_ID']; $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $fwBonus, 'ORI_BONUS' => $fwBonus, 'RECONSUME_POINTS' => 0, 'MANAGE_TAX' => 0, 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'decRoleId' => $decRoleId, ]) // 'FROM_DATA' => json_encode($ycBonusData['fromData']), ]; unset($userId, $fwBonusData, $userBaseInfo, $decRoleId, $fwBonus); } CalcBonusBD::batchInsert($insertBonusData); unset($insertBonusData, $allData); $this->calcBonusBDStepTwo($offset + $this->_limit); } unset($allData); return true; } /** * 报单业绩奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBdYJ(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { foreach ($allData as $userId) { $insertBonusData = []; // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; //个人业绩都算见点奖,包括报单和复消、二次购物 $perfPv = $perfData['PV_PCS_ZC'] ?? 0; if( $perfPv <= 0 ) continue; //业绩奖使用报单PV // $oriPointsBonus = Tool::formatPrice($perfPv * $this->_sysConfig['pointsPercent']['VALUE'] / 100); // if ($oriPointsBonus <= 0) continue; //偶数层数 $pointsEvenLayer = $this->_sysConfig['pointsLayer']['VALUE']; $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $userEmpLevel = $userBaseInfo['EMP_LV']; $netWorkParents = Cache::getAllNetworkParents($userId); foreach ($netWorkParents as $netWorkParent) { // $pointsBonus = $oriPointsBonus; //自已距顶端的深度减去父级距顶端的深度 $diffLayer = $netWorkParent['TOP_DEEP'] - $netWorkParent['PARENT_DEEP']; if( $diffLayer <= 0) continue; if( $diffLayer > 2 * $pointsEvenLayer ) continue; if( $diffLayer % 2 == 1 ) continue; $pointsPercentName = sprintf('pointsPercent_%d', $diffLayer); if( isset($this->_sysConfig[$pointsPercentName]['VALUE']) ) { $diffLayerPercent = $this->_sysConfig[$pointsPercentName]['VALUE']; }else { $diffLayerPercent = $this->_sysConfig['pointsPercent']['VALUE']; } $pointsBonus = Tool::formatPrice($perfPv * $diffLayerPercent / 100); if( $pointsBonus <= 0 ) continue; // 把对碰后的奖金存入缓存中 $bonusUserId = $netWorkParent['PARENT_UID']; if( !$bonusUserId ) continue; // 获取会员的报单级别 $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //判断上限 包括级别奖金上限和总上限 // $pointsBonus = $this->declarationLevelCap($pointsBonus, $bonusUserId, $bonusUserBaseInfo['DEC_LV']); // if( $pointsBonus <= 0 ) continue; //总金额限制 $pointsBonus = $this->bonusTotalLimit($pointsBonus, $bonusUserId, $bonusUserBaseInfo['REC_NUM'], $bonusUserBaseInfo['ZC_AMOUNT']); if( $pointsBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $pointsBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_YJ', $pointsBonus, $deductData, CalcCache::FROM_MEANS_BD); //业绩奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserBaseInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userEmpLevel, 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $pointsBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfPv' => $perfPv, 'pointsLayerConfig' => $this->_sysConfig['pointsLayer']['VALUE'], 'pointsPercentConfig' => $diffLayerPercent, 'recNum' => $bonusUserBaseInfo['REC_NUM'], 'decAmount' => $bonusUserBaseInfo['ZC_AMOUNT'], 'decLevel' => $bonusUserBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($netWorkParent, $pointsBonus, $diffLayer, $bonusUserId, $bonusUserBaseInfo, $deductData, $diffLayerPercent, $pointsPercentName); } CalcBonusYJ::batchInsert($insertBonusData); unset($insertBonusData, $userId, $perfData, $perfPv, $oriPointsBonus, $pointsEvenLayer, $userBaseInfo, $userEmpLevel, $netWorkParents); } unset($allData); return $this->calcBonusBdYJ($offset + $this->_limit); } unset($allData); return true; } /** * 复消业绩奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusFxYJ(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { foreach ($allData as $userId) { $insertBonusData = []; // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); if( !$perfData ) continue; //个人业绩都算见点奖,包括报单和复消、二次购物 $perfPv = $perfData['PV_PCS_FX'] ?? 0; if( $perfPv <= 0 ) continue; //业绩奖使用报单PV // $oriPointsBonus = Tool::formatPrice($perfPv * $this->_sysConfig['pointsPercent']['VALUE'] / 100); // if ($oriPointsBonus <= 0) continue; //偶数层数 $pointsEvenLayer = $this->_sysConfig['fxPointsLayer']['VALUE']; $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $userEmpLevel = $userBaseInfo['EMP_LV']; $netWorkParents = Cache::getAllNetworkParents($userId); foreach ($netWorkParents as $netWorkParent) { // $pointsBonus = $oriPointsBonus; //自已距顶端的深度减去父级距顶端的深度 $diffLayer = $netWorkParent['TOP_DEEP'] - $netWorkParent['PARENT_DEEP']; if( $diffLayer <= 0) continue; if( $diffLayer > 2 * $pointsEvenLayer ) continue; if( $diffLayer % 2 == 1 ) continue; $pointsPercentName = sprintf('fxPointsPercent_%d', $diffLayer); if( isset($this->_sysConfig[$pointsPercentName]['VALUE']) ) { $diffLayerPercent = $this->_sysConfig[$pointsPercentName]['VALUE']; }else { $diffLayerPercent = $this->_sysConfig['fxPointsPercent']['VALUE']; } $pointsBonus = Tool::formatPrice($perfPv * $diffLayerPercent / 100); if( $pointsBonus <= 0 ) continue; // 把对碰后的奖金存入缓存中 $bonusUserId = $netWorkParent['PARENT_UID']; if( !$bonusUserId ) continue; // 获取会员的报单级别 $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //判断上限 包括级别奖金上限和总上限 // $pointsBonus = $this->declarationLevelCap($pointsBonus, $bonusUserId, $bonusUserBaseInfo['DEC_LV']); // if( $pointsBonus <= 0 ) continue; //总金额限制 $pointsBonus = $this->bonusTotalLimit($pointsBonus, $bonusUserId, $bonusUserBaseInfo['REC_NUM'], $bonusUserBaseInfo['ZC_AMOUNT']); if( $pointsBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $pointsBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_YJ', $pointsBonus, $deductData, CalcCache::FROM_MEANS_FX); //业绩奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserBaseInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userEmpLevel, 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $pointsBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfPv' => $perfPv, 'pointsLayerConfig' => $this->_sysConfig['fxPointsLayer']['VALUE'], 'pointsPercentConfig' => $diffLayerPercent, 'recNum' => $bonusUserBaseInfo['REC_NUM'], 'decAmount' => $bonusUserBaseInfo['ZC_AMOUNT'], 'decLevel' => $bonusUserBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($netWorkParent, $pointsBonus, $diffLayer, $bonusUserId, $bonusUserBaseInfo, $deductData, $diffLayerPercent, $pointsPercentName); } CalcBonusYJ::batchInsert($insertBonusData); unset($insertBonusData, $userId, $perfData, $perfPv, $oriPointsBonus, $pointsEvenLayer, $userBaseInfo, $userEmpLevel, $netWorkParents); } unset($allData); return $this->calcBonusFxYJ($offset + $this->_limit); } unset($allData); return true; } /** * 团队奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusQY(int $offset = 0) { echo sprintf("时间:[%s]团队奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); // 从缓存中获取会员的上期结余业绩信息 $pervSurplusPerf = CalcCache::surplusPerf($userId, $periodNum); // 本期 + 上期结余 $perfArr = [ 'SURPLUS_1L' => $perfData['PV_1L_TOUCH'] + $pervSurplusPerf['SURPLUS_1L'], 'SURPLUS_2L' => $perfData['PV_2L_TOUCH'] + $pervSurplusPerf['SURPLUS_2L'], 'SURPLUS_3L' => $perfData['PV_3L_TOUCH'] + $pervSurplusPerf['SURPLUS_3L'], 'SURPLUS_4L' => $perfData['PV_4L_TOUCH'] + $pervSurplusPerf['SURPLUS_4L'], 'SURPLUS_5L' => $perfData['PV_5L_TOUCH'] + $pervSurplusPerf['SURPLUS_5L'], ]; $oriPerfArr = [ 'perfArr' => $perfArr, 'touchBonus' => 0, ]; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $decLevelConfig = $this->_decLevelConfig; $nowDecLevelConfig = $decLevelConfig[$userBaseInfo['DEC_LV']]; // 对碰 $touchBonusArr = $this->touchPerf($oriPerfArr, $perfArr, $nowDecLevelConfig['QY_PERCENT']/100); $touchPerfArr = []; foreach ($touchBonusArr['perfArr'] as $keyR => $perfR) { $touchPerfArr[$keyR] = $perfR; } // 对碰完成后把结余的业绩存入本期业绩缓存中 CalcCache::nowPeriodPerf($userId, $periodNum, $touchPerfArr); //更新数据库 PerfPeriod::updateAll($touchPerfArr, 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ 'USER_ID' => $userId, 'PERIOD_NUM' => $periodNum, ]); if ($touchBonusArr['touchBonus'] <= 0) continue; $teamBonus = $touchBonusArr['touchBonus']; //判断级别上限 $teamBonus = $this->declarationLevelCap($teamBonus, $userId, $userBaseInfo['DEC_LV']); if( $teamBonus <= 0 ) continue; $teamBonus = $this->bonusTotalLimit($teamBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $teamBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($userId, $teamBonus); // 把对碰后的奖金存入缓存中 CalcCache::bonus($userId, $periodNum, 'BONUS_QY', $teamBonus, $deductData); //团队奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $teamBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'perfArr' => $perfArr, 'touchPerfArrOri' => $touchBonusArr['perfArr'], 'touchPerfArr' => $touchPerfArr, 'nowDecLevelConfig' => $nowDecLevelConfig, 'decLevel' => $userBaseInfo['DEC_LV'], ]), ]; unset($perfData, $pervSurplusPerf, $perfArr, $oriPerfArr, $touchPerfArr, $userBaseInfo, $decLevelConfig, $touchBonusArr, $userId, $nowDecLevelConfig, $teamBonus, $deductData); } CalcBonusQY::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusQY($offset + $this->_limit); } unset($allData); return true; } /** * 报单团队奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBdQY(int $offset = 0) { echo sprintf("时间:[%s]报单团队奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); // 从缓存中获取会员的上期结余业绩信息 $pervSurplusPerf = CalcCache::surplusPerf($userId, $periodNum); // 本期 + 上期结余 $perfArr = [ 'SURPLUS_1L_ZC' => $perfData['PV_1L_ZC'] + $pervSurplusPerf['SURPLUS_1L_ZC'], 'SURPLUS_2L_ZC' => $perfData['PV_2L_ZC'] + $pervSurplusPerf['SURPLUS_2L_ZC'], 'SURPLUS_3L_ZC' => $perfData['PV_3L_ZC'] + $pervSurplusPerf['SURPLUS_3L_ZC'], 'SURPLUS_4L_ZC' => $perfData['PV_4L_ZC'] + $pervSurplusPerf['SURPLUS_4L_ZC'], 'SURPLUS_5L_ZC' => $perfData['PV_5L_ZC'] + $pervSurplusPerf['SURPLUS_5L_ZC'], ]; $oriPerfArr = [ 'perfArr' => $perfArr, 'touchBonus' => 0, ]; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $decLevelConfig = $this->_decLevelConfig; $nowDecLevelConfig = $decLevelConfig[$userBaseInfo['DEC_LV']]; // 对碰 $touchBonusArr = $this->touchPerf($oriPerfArr, $perfArr, $nowDecLevelConfig['QY_PERCENT']/100); $touchPerfArr = []; foreach ($touchBonusArr['perfArr'] as $keyR => $perfR) { $touchPerfArr[$keyR] = $perfR; } // 对碰完成后把结余的业绩存入本期业绩缓存中 CalcCache::nowPeriodPerf($userId, $periodNum, $touchPerfArr); //更新数据库 PerfPeriod::updateAll($touchPerfArr, 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ 'USER_ID' => $userId, 'PERIOD_NUM' => $periodNum, ]); if ($touchBonusArr['touchBonus'] <= 0) continue; $teamBonus = $touchBonusArr['touchBonus']; //判断级别上限 // $teamBonus = $this->declarationLevelCap($teamBonus, $userId, $userBaseInfo['DEC_LV']); // if( $teamBonus <= 0 ) continue; // $teamBonus = $this->bonusTotalLimit($teamBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); // if( $teamBonus <= 0 ) continue; //扣除相应的复消积分和管理费 // $deductData = $this->deduct($userId, $teamBonus); // 把对碰后的奖金存入缓存中 CalcCache::bonus($userId, $periodNum, 'BONUS_QY_BD', $teamBonus); unset($perfData, $pervSurplusPerf, $perfArr, $oriPerfArr, $touchPerfArr, $userBaseInfo, $decLevelConfig, $touchBonusArr, $userId, $nowDecLevelConfig, $teamBonus, $deductData); } unset($allData, $insertBonusData); return $this->calcBonusBdQY($offset + $this->_limit); } unset($allData); return true; } /** * 复消团队奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusFxQY(int $offset = 0) { echo sprintf("时间:[%s]复消团队奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $periodNum = $this->_periodNum; // 从缓存获取分页有业绩的会员信息 $allData = CalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { // 从缓存中获取会员的业绩信息 $perfData = CalcCache::nowPeriodPerf($userId, $periodNum); // 从缓存中获取会员的上期结余业绩信息 $pervSurplusPerf = CalcCache::surplusPerf($userId, $periodNum); // 本期 + 上期结余 $perfArr = [ 'SURPLUS_1L_FX' => $perfData['PV_1L_FX'] + $pervSurplusPerf['SURPLUS_1L_FX'], 'SURPLUS_2L_FX' => $perfData['PV_2L_FX'] + $pervSurplusPerf['SURPLUS_2L_FX'], 'SURPLUS_3L_FX' => $perfData['PV_3L_FX'] + $pervSurplusPerf['SURPLUS_3L_FX'], 'SURPLUS_4L_FX' => $perfData['PV_4L_FX'] + $pervSurplusPerf['SURPLUS_4L_FX'], 'SURPLUS_5L_FX' => $perfData['PV_5L_FX'] + $pervSurplusPerf['SURPLUS_5L_FX'], ]; $oriPerfArr = [ 'perfArr' => $perfArr, 'touchBonus' => 0, ]; // 获取会员的报单级别 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $decLevelConfig = $this->_decLevelConfig; $nowDecLevelConfig = $decLevelConfig[$userBaseInfo['DEC_LV']]; // 对碰 $touchBonusArr = $this->touchPerf($oriPerfArr, $perfArr, $nowDecLevelConfig['QY_PERCENT']/100); //大区封顶 $touchPerfArr = []; foreach ($touchBonusArr['perfArr'] as $keyR => $perfR) { // if ($perfR > $nowDecLevelConfig['QY_BIG_CAP']) $perfR = $nowDecLevelConfig['QY_BIG_CAP']; $touchPerfArr[$keyR] = $perfR; } // 对碰完成后把结余的业绩存入本期业绩缓存中 CalcCache::nowPeriodPerf($userId, $periodNum, $touchPerfArr); //更新数据库 PerfPeriod::updateAll($touchPerfArr, 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ 'USER_ID' => $userId, 'PERIOD_NUM' => $periodNum, ]); if ($touchBonusArr['touchBonus'] <= 0) continue; $teamBonus = $touchBonusArr['touchBonus']; //判断级别上限 // $teamBonus = $this->declarationLevelCap($teamBonus, $userId, $userBaseInfo['DEC_LV']); // if( $teamBonus <= 0 ) continue; // // $teamBonus = $this->bonusTotalLimit($teamBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); // if( $teamBonus <= 0 ) continue; //扣除相应的复消积分和管理费 // $deductData = $this->deduct($userId, $teamBonus); // 把对碰后的奖金存入缓存中 CalcCache::bonus($userId, $periodNum, 'BONUS_QY_FX', $teamBonus); unset($perfData, $pervSurplusPerf, $perfArr, $oriPerfArr, $touchPerfArr, $userBaseInfo, $decLevelConfig, $touchBonusArr, $userId, $nowDecLevelConfig, $teamBonus, $deductData); } unset($allData, $insertBonusData); return $this->calcBonusFxQY($offset + $this->_limit); } unset($allData); return true; } /** * 计算共享奖之前的操作 * @param int $offset * @return bool */ public function calcBonusGXBefore(int $offset = 0) { //获取所有激活会员 $allData = CalcCache::getActiveUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { echo sprintf("时间:[%s]共享奖之前,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); foreach ($allData as $userId) { //判断$userId 能否得共享奖 // //判断 是否本期小市场(安置关系)新增980pv 能否得奖 // if ( !$this->checkSmallMarketPerf($userId) ) { // unset($userId); // continue; // } // 20220407 小市场980判断->改成判断此期用户是否有原报单团队奖金 if ( !$this->checkHasOriBonusQyBd($userId) ) { unset($userId); continue; } //获取当前会员所有的推荐上级, 并查看是否有首单团队奖 $validDeep = 0; $this->loopRelationParentDo($userId, function ($parent) use ($userId, &$validDeep) { //判断$parent是否有首单团队奖 $parentBonus = CalcCache::bonus($parent['PARENT_UID'], $this->_periodNum); if( $parentBonus['ORI_BONUS_QY_BD'] > 0 ) { $validDeep += 1; //记录得奖缓存 CalcCache::addShareBonusOneRelation($userId, $parent['PARENT_UID'], $this->_periodNum, $validDeep); } unset($parent, $parentBonus); if ( $validDeep >= 2 ) { return self::LOOP_FINISH; } }); unset($userId, $validDeep); } unset($allData); return $this->calcBonusGXBefore($offset + $this->_limit); } unset($allData); return true; } /** * 共享奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusGX(int $offset = 0) { // 从缓存获取分页有的会员信息 $allData = CalcCache::getHasIncomeUsers($this->_periodNum, $offset, $this->_gxLimit); if ($allData) { echo sprintf("时间:[%s]共享奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $insertBonusData = []; // 获取线上找几层和是否开启找几层的限制 $configsGx = Config::find()->where( 'CONFIG_NAME="gxNoPvFindLimitSwitch" OR CONFIG_NAME="gxNoPvFindLimitTimes"' )->orderBy('SORT ASC')->indexBy('CONFIG_NAME')->asArray()->all(); $openFindLimit = isset($configsGx['gxNoPvFindLimitSwitch']) ? $configsGx['gxNoPvFindLimitSwitch']['VALUE'] : 1; // 是否开放了 得奖人不满足980就找一个满足980的人来得这个奖 的最大向上循环次数 $findLimitTimes = isset($configsGx['gxNoPvFindLimitTimes']) ? $configsGx['gxNoPvFindLimitTimes']['VALUE'] : 5 ; // 开放的限制层数 foreach ($allData as $userId) { $bonusUserData = []; $bonusPercentOne = $this->_sysConfig['shareRecPercent']['VALUE'] / 100; $bonusPercentTwo = $this->_sysConfig['sharePercent']['VALUE'] / 100; // 从缓存中获取会员的收入信息 $incomeBonus = CalcCache::bonus($userId, $this->_periodNum); $lastTwoIncome = $incomeBonus['ORI_BONUS_QY_BD'] ?? 0; $shareBonusOne = $lastTwoIncome * $bonusPercentOne; unset($lastTwoIncome); //找到上2代 新增个人+推荐团队业绩 加权平均分配 这个奖 if( $shareBonusOne > 0) { $bonusOneData = $this->gxLastTwoBonusData($userId, 1, $shareBonusOne); $bonusTwoData = $this->gxLastTwoBonusData($userId, 2, $shareBonusOne); $bonusUserData = array_merge($bonusUserData, $bonusOneData); $bonusUserData = array_merge($bonusUserData, $bonusTwoData); unset($bonusOneData, $bonusTwoData); } $nextFiveIncome = $incomeBonus['ORI_BONUS_QY_BD'] ?? 0; $shareBonusTwo = $nextFiveIncome * $bonusPercentTwo; unset($nextFiveIncome); //找到下5代(安置网) 紧缩 相对偶数层2、4、6、8、10层 if( $shareBonusTwo > 0 ) { $validDeep = 1; $this->loopNetworkParentDo($userId, function ($parent) use ($userId, $shareBonusTwo, &$validDeep, &$bonusUserData) { if ( $validDeep % 2 === 0 ) { $bonusUserData[] = [ 'bonusUid' => $parent['PARENT_UID'], 'bonus' => $shareBonusTwo, 'validMinPv' => true, ]; } //判断$parent是否有首单团队奖 $parentBonus = CalcCache::bonus($parent['PARENT_UID'], $this->_periodNum); if( $parentBonus['ORI_BONUS_QY_BD'] > 0 ) {//有效层 $validDeep += 1; } unset($parent, $parentBonus); if ( $validDeep >= 11 ) { return self::LOOP_FINISH; } }); unset($validDeep); } if ( !$bonusUserData ) continue; $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $userEmpLevel = $userBaseInfo['EMP_LV']; foreach ($bonusUserData as $bonusUserDataEvery) { $bonusUserId = $bonusUserDataEvery['bonusUid']; //判断 是否本期小市场(安置关系)新增980pv 能否得奖->20220407改成判断得奖人此期是否有报单团队奖金 // if ( $bonusUserDataEvery['validMinPv'] && !$this->checkSmallMarketPerf($bonusUserId) ) { 20220407 if ( $bonusUserDataEvery['validMinPv'] && !$this->checkHasOriBonusQyBd($bonusUserId) ) { // unset($bonusUserDataEvery, $bonusUserId); // continue; //得奖人不满足980就找一个满足980的人来得这个奖 // 20220407改成判断得奖人此期是否有报单团队奖金,如果没有则找一个此期有报单团队奖金得人 $bonusUserId = $this->getMinBdPvNetworkParent($bonusUserId, $openFindLimit, $findLimitTimes); if ( !$bonusUserId ) { unset($bonusUserDataEvery, $bonusUserId); continue; } } $bonus = Tool::formatPrice($bonusUserDataEvery['bonus']); $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); //总金额限制 $bonus = $this->bonusTotalLimit($bonus, $bonusUserId, $bonusUserBaseInfo['REC_NUM'], $bonusUserBaseInfo['ZC_AMOUNT']); if( $bonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $bonus); CalcCache::bonus($bonusUserId, $this->_periodNum, 'BONUS_GX', $bonus, $deductData); CalcCache::addHasMonthBonusUsers($bonusUserId, $this->_periodNum); //共享奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserBaseInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userEmpLevel, 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $bonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'sharePercent' => $bonusPercentOne, 'incomeBonus' => $incomeBonus, 'recNum' => $userBaseInfo['REC_NUM'], 'decAmount' => $userBaseInfo['ZC_AMOUNT'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($bonusUserDataEvery, $bonusUserId, $bonus, $bonusUserBaseInfo, $deductData); } unset($userId, $bonusUserData, $userBaseInfo, $userEmpLevel, $bonusPercentOne, $bonusPercentTwo, $incomeBonus, $sharePerson); // echo ('内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL); } if($insertBonusData) CalcBonusGX::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusGX($offset + $this->_gxLimit); } unset($allData); return true; } // 执行蓝星管理奖金的存储过程 public function calcBsProcedure() { if( !$this->_isCalcMonth ) { // 不是结算月,则不进行计算 return false; } $result = \Yii::$app->db->createCommand("CALL CalcBlue(:periodNum)") ->bindValue(':periodNum' , $this->_periodNum ) ->execute(); return $result; } // 执行旅游奖、名车奖、豪宅奖的计算 public function calcBonusZoneBS(array $bonusConfig) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } // 达标条件:聘级、级别、奖项比例 $config = json_decode($bonusConfig['OPTIONS'], true); // 奖金总比例 $mate = $bonusConfig['VALUE'] / 100; // 会员级别 $minDecLevel = $config['OPTIONS']['declarationLevel'] ?? []; // 会员聘级 $minEmpLevel = $config['OPTIONS']['employLevel'] ?? []; // 月度公司总PV $monthTotalPV = PerfMonth::find() ->yearMonth($this->_calcYearMonth) ->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth]) ->sum('PV_PCS'); if ($monthTotalPV <= 0) { return true; } // 基于蓝星奖结果计算符合获奖条件的会员 $userBonusData = CalcBonusBS::find() ->yearMonth($this->_calcYearMonth) ->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth]) ->select('USER_ID,LEVEL_ID,LAST_DEC_LV,LAST_EMP_LV,LAST_STATUS,RECONSUME_POINTS') ->groupBy('USER_ID') ->asArray() ->all(); // 获奖会员数 $userBonusNumber = count($userBonusData); if (!$userBonusNumber) { return true; } // 计算奖金:(公司月总PV * 奖金比) / 得奖人数 $amount = Tool::formatPrice(($monthTotalPV * $mate) / $userBonusNumber); if ($amount <= 0) { return true; } // 奖金标识 if ($bonusConfig['CONFIG_NAME'] == 'openTravel') { $bonusCacheKey = 'calc:travel:bonus_'; } else if ($bonusConfig['CONFIG_NAME'] == 'openCar') { $bonusCacheKey = 'calc:car:bonus_'; } else { $bonusCacheKey = 'calc:house:bonus_'; } $insertBonusData = []; foreach($userBonusData as $userBonus) { // 会员级别+聘级都达到要求才会发放奖金 if (in_array($userBonus['LAST_DEC_LV'], $minDecLevel) && in_array($userBonus['LEVEL_ID'], $minEmpLevel)) { // 放入缓存 CalcCache::zoneBonus($userBonus['USER_ID'], $this->_periodNum, $bonusCacheKey, $amount); // 加入月奖的会员 CalcCache::addHasMonthBonusUsers($userBonus['USER_ID'], $this->_periodNum); } $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userBonus['USER_ID'], 'LEVEL_ID' => $userBonus['LEVEL_ID'], 'LAST_DEC_LV' => $userBonus['LAST_DEC_LV'], 'LAST_EMP_LV' => $userBonus['LAST_EMP_LV'], 'LAST_STATUS' => $userBonus['LAST_STATUS'], 'AMOUNT' => $amount, 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'BONUS_TYPE' => $bonusConfig['CONFIG_NAME'], ]; } // 数据写入总表 if ($insertBonusData) { CalcBonusZone::batchInsert($insertBonusData); } return true; } /** * 蓝星管理奖金 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBsGL(int $offset = 0) { if( !$this->_isCalcMonth ) { // 不是结算月,则不进行计算 return false; } // 从缓存获取分页有收入的会员信息 $allData = CalcBonusBS::findUseDbCalc() ->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]) ->groupBy('USER_ID') ->offset($offset) ->limit($this->_limit) ->asArray() ->all(); if ($allData) { // 达标条件:会员级别:钻卡 $config = json_decode($this->_sysConfig['openGL']['OPTIONS'], true); $minDecLevel = $config['mntDec'] ?? []; foreach ($allData as $user) { //扣除相应的复消积分和管理费 $deductData = $this->deduct($user['USER_ID'], $user['ORI_BONUS_MNT']); $realBonusBs = $deductData['surplus']; // 扣除管理费和复消积分后的实发蓝星奖金 $manageTax = $deductData['manageTax']; // 管理费 $point = $deductData['reConsumePoints'] + $user['RECONSUME_POINTS'];// 复消积分 // 管理奖钻卡发放 if (in_array($user['LAST_DEC_LV'], $minDecLevel)) { // 把对碰后的奖金存入缓存中 CalcCache::bonus($user['USER_ID'], $this->_periodNum, 'BONUS_BS_MNT', $user['ORI_BONUS_MNT'], $deductData); // 加入月奖的会员 CalcCache::addHasMonthBonusUsers($user['USER_ID'], $this->_periodNum); } // 更新蓝星奖金存储过程的实发金额数据 CalcBonusBS::updateAll([ 'RECONSUME_POINTS' => $point, 'AMOUNT_MNT' => $realBonusBs, 'MANAGE_TAX_MNT' => $manageTax], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [':USER_ID' => $user['USER_ID'], ':PERIOD_NUM' => $this->_periodNum]); } return $this->calcBonusBsGL($offset + $this->_limit); } unset($allData); return true; } /** * 蓝星业绩奖金 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBsYJ(int $offset = 0) { if( !$this->_isCalcMonth ) { // 不是结算月,则不进行计算 return false; } // 从缓存获取分页有收入的会员信息 $allData = CalcBonusBS::findUseDbCalc() ->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]) ->groupBy('USER_ID') ->offset($offset) ->limit($this->_limit) ->asArray() ->all(); if ($allData) { // 达标条件:会员级别:金卡、钻卡 $config = json_decode($this->_sysConfig['openGL']['OPTIONS'], true); $minDecLevel = $config['abbrDec'] ?? []; foreach ($allData as $user) { //扣除相应的复消积分和管理费 $deductData = $this->deduct($user['USER_ID'], $user['ORI_BONUS_ABBR']); $realBonusBs = $deductData['surplus']; // 扣除管理费和复消积分后的实发蓝星奖金 $manageTax = $deductData['manageTax']; // 管理费 $point = $deductData['reConsumePoints'] + $user['RECONSUME_POINTS'];// 复消积分 // 业绩奖金卡、钻卡发放 if (in_array($user['LAST_DEC_LV'], $minDecLevel)) { // 把对碰后的奖金存入缓存中 CalcCache::bonus($user['USER_ID'], $this->_periodNum, 'BONUS_BS_ABBR', $user['ORI_BONUS_ABBR'], $deductData); // 加入月奖的会员 CalcCache::addHasMonthBonusUsers($user['USER_ID'], $this->_periodNum); } // 更新蓝星业绩奖金存储过程的实发金额数据 CalcBonusBS::updateAll([ 'AMOUNT_ABBR' => $realBonusBs, 'MANAGE_TAX_ABBR' => $manageTax, 'RECONSUME_POINTS' => $point], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [':USER_ID' => $user['USER_ID'], ':PERIOD_NUM' => $this->_periodNum]); } return $this->calcBonusBsYJ($offset + $this->_limit); } unset($allData); return true; } /** * 报单管理奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusBdGL(int $offset = 0) { // 从缓存获取分页有收入的会员信息 $allData = CalcCache::getHasIncomeUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { $bonusUserData = []; //会员信息 $validDeep = 1; $this->loopRelationParentDo($userId, function ($parent) use ($userId, &$validDeep, &$bonusUserData) { //判断$parent是否有首单团队奖 $bonusUserId = $parent['PARENT_UID']; $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $nowDecLevelConfig = $this->_decLevelConfig[$bonusUserBaseInfo['DEC_LV']]; $recNum = $bonusUserBaseInfo['REC_NUM']; if( $recNum <= 0 ) { $maxOddLayer = 0; }else if( $recNum == 1 ) { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_ONE'] ?? 0; }else if( $recNum == 2 ) { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_TWO'] ?? 0; }else { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_THREE'] ?? 0; } if ( $validDeep < 2 * $maxOddLayer && $validDeep % 2 === 1 ) {//奇数层 $bonusUserData[] = [ 'bonusUid' => $parent['PARENT_UID'], 'validDeep' => $validDeep ]; } $parentBonus = CalcCache::bonus($bonusUserId, $this->_periodNum); if( $parentBonus['ORI_BONUS_QY_BD'] > 0 ) {//有效层 $validDeep += 1; } unset($parent, $parentBonus, $bonusUserId, $bonusUserBaseInfo, $nowDecLevelConfig, $recNum, $maxOddLayer); //超过代数上限则结束 if ( $validDeep >= 18 ) { return self::LOOP_FINISH; } }); //发奖 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $userBonus = CalcCache::bonus($userId, $this->_periodNum); foreach ($bonusUserData as $everyData) { $bonusUserId = $everyData['bonusUid']; //判断 是否本期小市场(安置关系)新增980pv 能否得奖 if ( !$this->checkSmallMarketPerf($bonusUserId) ) { // unset($bonusUserId); // continue; //得奖人不满足980就找一个满足980的人来得这个奖 $bonusUserId = $this->getMinBdPvRelationParent($bonusUserId); if ( !$bonusUserId ) { unset($bonusUserId); continue; } } $parentOddPercentValue = floor($everyData['validDeep']/6); $parentOddPercentName = sprintf('parentOddPercent_%s', $parentOddPercentValue); if( !isset($this->_sysConfig[$parentOddPercentName]) ) continue; $bonusPercent = $this->_sysConfig[$parentOddPercentName]['VALUE']; $manageBonus = Tool::formatPrice($userBonus['ORI_BONUS_QY_BD'] * $bonusPercent / 100); if ($manageBonus <= 0) continue; //总金额限制 $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $recNum = $bonusUserBaseInfo['REC_NUM']; $manageBonus = $this->bonusTotalLimit($manageBonus, $bonusUserId, $recNum, $bonusUserBaseInfo['ZC_AMOUNT']); if( $manageBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $manageBonus); // 钻卡会员奖金记入缓存 $decLevelConfig = $this->_decLevelConfig; $nowDecLevelConfig = $decLevelConfig[$userBaseInfo['DEC_LV']]; if ($nowDecLevelConfig == '67ABCE0ECE705575E055736AECE8644D') { CalcCache::bonus($bonusUserId, $this->_periodNum, 'BONUS_GL', $manageBonus, $deductData, CalcCache::FROM_MEANS_BD); CalcCache::addHasMonthBonusUsers($bonusUserId, $this->_periodNum); } //管理奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserBaseInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $manageBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ $parentOddPercentName => $this->_sysConfig[$parentOddPercentName]['VALUE'], 'validDeep' => $everyData['validDeep'], 'recNum' => $bonusUserBaseInfo['REC_NUM'], 'decAmount' => $bonusUserBaseInfo['ZC_AMOUNT'], 'fromUserId' => $userId, 'decLevel' => $bonusUserBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($everyData, $bonusUserId, $parentOddPercentValue, $parentOddPercentName, $bonusPercent, $manageBonus, $deductData); } unset($userId, $validDeep, $userBaseInfo, $userBonus, $bonusUserData); } if($insertBonusData) CalcBonusGL::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusBdGL($offset + $this->_limit); } unset($allData); return true; } /** * 复消管理奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusFxGL(int $offset = 0) { $periodNum = $this->_periodNum; // 从缓存获取分页有收入的会员信息 $allData = CalcCache::getHasIncomeUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { //会员信息 $decLevelConfig = $this->_decLevelConfig; $netWorkParents = Cache::getAllRelationParents($userId); $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $userEmpLevel = $userBaseInfo['EMP_LV']; foreach ($netWorkParents as $netWorkParent) { //自已距顶端的深度减去父级距顶端的深度 $diffLayer = $netWorkParent['TOP_DEEP'] - $netWorkParent['PARENT_DEEP']; if( $diffLayer <= 0) continue; //@todo 超过最大代数就跳出本次循环 //偶数代跳过 if( $diffLayer % 2 == 0 ) continue; // 获取会员的报单级别 $bonusUserId = $netWorkParent['PARENT_UID']; if( !$bonusUserId ) continue; $bonusUserBaseInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $nowDecLevelConfig = $decLevelConfig[$bonusUserBaseInfo['DEC_LV']]; if( !$nowDecLevelConfig ) continue; //推荐人数 $recNum = $bonusUserBaseInfo['REC_NUM']; if( $recNum <= 0 ) continue; if( $recNum == 1 ) { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_ONE']; }else if( $recNum == 2 ) { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_TWO']; }else { $maxOddLayer = $nowDecLevelConfig['GL_ODD_DEEP_THREE']; } //超过代数上限也跳过 if( $diffLayer >= 2 * $maxOddLayer ) continue; // $everyLayer = floor(2 * $nowDecLevelConfig['GL_ODD_DEEP_THREE'] / $nowDecLevelConfig['SORT']); //多少代 // $theLayer = $diffLayer % $everyLayer; // $theLayerLevel = floor($diffLayer/$everyLayer); $theLayerLevel = floor($diffLayer/6); $parentOddPercentName = sprintf('parentOddPercent_%s', $theLayerLevel); if( !isset($this->_sysConfig[$parentOddPercentName]) ) continue; $bonusPercent = $this->_sysConfig[$parentOddPercentName]['VALUE']; // 从缓存中获取会员的收入信息 $incomeBonus = CalcCache::bonus($userId, $periodNum); $parentOddIncomeFromName = sprintf('parentOddIncomeFrom_%s', $theLayerLevel); $parentOddIncomeFrom = explode(',', $this->_sysConfig[$parentOddIncomeFromName]['VALUE']); $parentOddIncome = 0; foreach ($parentOddIncomeFrom as $incomeType) { if( $incomeType === 'XF' ) { $incomeTypeName = sprintf('ORI_BONUS_%s', $incomeType); }else { $incomeTypeName = sprintf('ORI_BONUS_%s_FX', $incomeType); } $incomeTypeValue = $incomeBonus[$incomeTypeName] ?? 0; $parentOddIncome += $incomeTypeValue; unset($incomeType, $incomeTypeName, $incomeTypeValue); } unset($parentOddIncomeFrom); $manageBonus = Tool::formatPrice($parentOddIncome * $bonusPercent / 100); if ($manageBonus <= 0) continue; //总金额限制 $manageBonus = $this->bonusTotalLimit($manageBonus, $bonusUserId, $recNum, $bonusUserBaseInfo['ZC_AMOUNT']); if( $manageBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($bonusUserId, $manageBonus); CalcCache::bonus($bonusUserId, $periodNum, 'BONUS_GL', $manageBonus, $deductData, CalcCache::FROM_MEANS_FX); //管理奖流水 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserBaseInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userEmpLevel, 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $manageBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ $parentOddPercentName => $this->_sysConfig[$parentOddPercentName]['VALUE'], $parentOddIncomeFromName => $this->_sysConfig[$parentOddIncomeFromName]['VALUE'], 'decLevelConfig' => $nowDecLevelConfig, 'recNum' => $bonusUserBaseInfo['REC_NUM'], 'decAmount' => $bonusUserBaseInfo['ZC_AMOUNT'], 'fromUserId' => $userId, 'decLevel' => $bonusUserBaseInfo['DEC_LV'], 'bonusTotalLimit' => [ $this->_sysConfig['bonusTotalZeroLimit']['VALUE'], $this->_sysConfig['bonusTotalOneLimit']['VALUE'], $this->_sysConfig['bonusTotalTwoLimit']['VALUE'], ], ]), ]; unset($netWorkParent, $diffLayer, $bonusUserId, $bonusUserBaseInfo, $bonusPercent, $nowDecLevelConfig, $manageBonus, $incomeBonus, $maxOddLayer, $theLayerLevel, $recNum, $parentOddPercentName, $parentOddIncomeFromName, $deductData); } unset($userId, $userBaseInfo, $userEmpLevel, $netWorkParents, $decLevelConfig); } CalcBonusGL::batchInsert($insertBonusData); unset($allData, $insertBonusData); return $this->calcBonusFxGL($offset + $this->_limit); } unset($allData); return true; } /** * 结算荣衔奖第一步 * @param int $offset * @return bool * @throws \yii\db\Exception * @throws \Exception */ public function calcBonusYCStepOne(int $offset = 0) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } echo sprintf("时间:[%s]荣衔奖第【1】步,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); //从缓存获取分页有本月业绩的会员 $allData = CalcCache::getHasMonthPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $maxLevelId = EmployLevel::SHX_ZJ_LEVEL_ID; $maxLevel = $this->_empLevelConfig[$maxLevelId]; $maxLevelPercent = $maxLevel['RX_PERCENT'] ?? 0; unset($maxLevelId, $maxLevel); foreach ($allData as $userId) { // echo sprintf("时间:[%s]荣衔奖,当前用户ID为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $userId); $nowMonthPerf = CalcCache::nowMonthPerf($userId, $this->_periodNum); $monthPvPcs = $nowMonthPerf['PV_PCS'] ?? 0; if( $monthPvPcs <= 0 ) continue; $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //个人业绩的奖金 $empLevelId = $userBaseInfo['EMP_LV']; $empLevel = $this->_empLevelConfig[$empLevelId]; $rxPercent = $empLevel['RX_PERCENT'] ?? 0; $empBonus = $monthPvPcs * $rxPercent / 100; if( $empBonus > 0 ) { //给本人添加聘级比例 CalcCache::ycMaxBonusPercent($userId, $this->_periodNum, $rxPercent); //记录奖金和奖金来源到缓存 并实现在缓存中奖金累加 CalcCache::saveYCBonusList($userId, $this->_periodNum, $empBonus, ['fromUid'=>$userId, 'fromPvPcs'=>$monthPvPcs]); CalcCache::addHasYcBonusUsers($userId, $this->_periodNum); //达到最大的比例其它人就得不到了 if( $rxPercent >= $maxLevelPercent ) continue; } unset($empLevelId, $empLevel, $rxPercent, $empBonus); //获取所有的父级 $this->loopRelationParentDo($userId, function ($parent) use ($userId, $monthPvPcs, $maxLevelPercent) { $bonusUserId = $parent['PARENT_UID']; //计算级别之后更新过userInfo的缓存,缓存中级别发生了变化 $bonusUserInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $parentEmpLevelId = $bonusUserInfo['EMP_LV']; $parentEmpLevel = $this->_empLevelConfig[$parentEmpLevelId]; $parentRxPercent = $parentEmpLevel['RX_PERCENT'] ?? 0; $cacheMaxPercent = CalcCache::ycMaxBonusPercent($userId, $this->_periodNum); $diffPercent = $parentRxPercent - $cacheMaxPercent; if( $diffPercent <= 0 ) return self::LOOP_CONTINUE; $empBonus = $monthPvPcs * $diffPercent / 100; if( $empBonus <= 0 ) return self::LOOP_CONTINUE; //给本人添加聘级比例 CalcCache::ycMaxBonusPercent($userId, $this->_periodNum, $parentRxPercent); //记录奖金和奖金来源到缓存 并实现在缓存中奖金累加 CalcCache::saveYCBonusList($bonusUserId, $this->_periodNum, $empBonus, ['fromUid'=>$userId, 'fromPvPcs'=>$monthPvPcs]); CalcCache::addHasYcBonusUsers($bonusUserId, $this->_periodNum); unset($cacheMaxPercent, $diffPercent, $parentEmpLevel, $bonusUserId, $bonusUserInfo, $parentEmpLevelId, $empBonus); //达到最大的比例就不在向上找了 if( $parentRxPercent >= $maxLevelPercent ) return self::LOOP_FINISH; unset($parentRxPercent); }); unset($nowMonthPerf, $monthPvPcs); } unset($allData, $maxLevelPercent); $this->calcBonusYCStepOne($offset + $this->_limit); } unset($periodNum, $allData); return true; } /** * 结算荣衔奖第二步 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusYCStepTwo(int $offset = 0) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } echo sprintf("时间:[%s]荣衔奖第【2】步,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $allData = CalcCache::getHasYcBonusUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { $monthPerfData = CalcCache::nowMonthPerf($userId, $this->_periodNum); $fxPvStatus = $monthPerfData['PV_PCS_FX'] >= $this->_sysConfig['monthPcsPvFxCondition']['VALUE']; unset($monthPerfData); if( !$fxPvStatus ) continue; unset($fxPvStatus); $ycBonusData = CalcCache::getYCBonusList($userId, $this->_periodNum); if( !$ycBonusData ) continue; $empBonus = $ycBonusData['empBonus'] ?? 0; if( $empBonus <=0 ) continue; //总金额限制 $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $empBonus = $this->bonusTotalLimit($empBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $empBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $empBonus = Tool::formatPrice($empBonus); $deductData = $this->deduct($userId, $empBonus); CalcCache::bonus($userId, $this->_periodNum, 'BONUS_YC', $empBonus, $deductData); $empLevelId = $userBaseInfo['EMP_LV']; $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'DEEP' => 0, 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $empBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'BONUS_TYPE' => CalcBonusYC::BONUS_TYPE_YC, 'PERIOD_NUM' => $this->_periodNum, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'empLevelId' => $empLevelId, ]) // 'FROM_DATA' => json_encode($ycBonusData['fromData']), ]; unset($ycBonusData, $deductData); //如果是总监以上拿平级2代 $empLevel = $this->_empLevelConfig[$empLevelId]; $userEmpLevelSort = $empLevel['SORT'] ?? EmployLevel::EMP_LEVEL_SORT['NO_LEVEL']; // if( $userEmpLevelSort >= EmployLevel::EMP_LEVEL_SORT['JX_ZR_LEVEL'] ) {} $newInsertBonusData = $this->calcParentYC($userId, $userBaseInfo, $userEmpLevelSort, $empBonus); $insertBonusData = array_merge($insertBonusData, $newInsertBonusData); unset($newInsertBonusData); unset($userId, $userBaseInfo, $empLevel, $empLevelId, $userEmpLevelSort, $empBonus); } CalcBonusYC::batchInsert($insertBonusData); unset($insertBonusData, $allData); $this->calcBonusYCStepTwo($offset + $this->_limit); } unset($allData); return true; } /** * VIP奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusVIP(int $offset = 0) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } echo sprintf("时间:[%s]VIP奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()), $offset); //从缓存获取分页有本月业绩的会员 $allData = CalcCache::getHasMonthPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $insertBonusData = []; foreach ($allData as $userId) { $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //条件一:级别必须为VIP $isVip = false; if( $userBaseInfo['DEC_LV'] === DeclarationLevel::VIP_LEVEL_ID ) { $isVip= true; } if( $this->_sysConfig['vipBonusGoldDecLevel']['VALUE'] && $userBaseInfo['DEC_LV'] === DeclarationLevel::JIN_ZUAN_LEVEL_ID ) { $isVip = true; } if ( !$isVip ) { unset($userId, $userBaseInfo); continue; } //判断其它两个条件,满足则计算月团队奖,不满足则留下大区剩余业绩,清除其它区的剩余业绩 //获取本月的业绩 $monthPerfData = CalcCache::nowMonthPerf($userId, $this->_periodNum); // 从缓存中获取会员的上期结余业绩信息 $pervSurplusPerf = CalcCache::surplusPerf($userId, $this->_periodNum); // 本期 + 上期结余 $perfArr = [ 'VIP_SURPLUS_1L_ZC' => $monthPerfData['VIP_PV_1L_ZC'] + $pervSurplusPerf['VIP_SURPLUS_1L_ZC'], 'VIP_SURPLUS_2L_ZC' => $monthPerfData['VIP_PV_2L_ZC'] + $pervSurplusPerf['VIP_SURPLUS_2L_ZC'], 'VIP_SURPLUS_3L_ZC' => $monthPerfData['VIP_PV_3L_ZC'] + $pervSurplusPerf['VIP_SURPLUS_3L_ZC'], 'VIP_SURPLUS_4L_ZC' => $monthPerfData['VIP_PV_4L_ZC'] + $pervSurplusPerf['VIP_SURPLUS_4L_ZC'], 'VIP_SURPLUS_5L_ZC' => $monthPerfData['VIP_PV_5L_ZC'] + $pervSurplusPerf['VIP_SURPLUS_5L_ZC'], ]; //条件二:本月复消金额达到300元 //fix-2021-03-26修改 条件二:本月个人复消PV300 $fxPvStatus = $monthPerfData['PV_PCS_FX'] >= $this->_sysConfig['monthPcsPvFxCondition']['VALUE']; unset($monthPerfData, $pervSurplusPerf); if( !$fxPvStatus ) { $this->dealWithMaxPerf($userId, $perfArr); unset($userBaseInfo, $userId, $perfArr, $fxPvStatus); continue; } //条件三:其它市场业绩 $isCanOtherDepartPerf = $this->_isCanVipBonusOtherAreaPerf($perfArr); if ( !$isCanOtherDepartPerf ) { $this->dealWithMaxPerf($userId, $perfArr); unset($userBaseInfo, $userId, $perfArr, $isCanOtherDepartPerf); continue; } $oriPerfArr = [ 'perfArr' => $perfArr, 'touchBonus' => 0, ]; // 对碰 $touchBonusArr = $this->touchPerf($oriPerfArr, $perfArr, $this->_sysConfig['vipBonusPercent']['VALUE']/100); unset($oriPerfArr, $perfArr); $touchPerfArr = []; foreach ($touchBonusArr['perfArr'] as $keyR => $perfR) { $touchPerfArr[$keyR] = $perfR; } // 对碰完成后把结余的业绩存入本期业绩缓存中 // CalcCache::nowPeriodPerf($userId, $this->_periodNum, $touchPerfArr); //更新数据库 PerfMonth::updateAll($touchPerfArr, 'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [ 'USER_ID' => $userId, 'CALC_MONTH' => $this->_calcYearMonth, ]); if ($touchBonusArr['touchBonus'] <= 0) continue; $vipBonus = $touchBonusArr['touchBonus']; //判断级别上限 $vipBonus = $this->declarationLevelCap($vipBonus, $userId, $userBaseInfo['DEC_LV']); if( $vipBonus <= 0 ) continue; $vipBonus = $this->bonusTotalLimit($vipBonus, $userId, $userBaseInfo['REC_NUM'], $userBaseInfo['ZC_AMOUNT']); if( $vipBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $deductData = $this->deduct($userId, $vipBonus); CalcCache::bonus($userId, $this->_periodNum, 'BONUS_VIP', $vipBonus, $deductData); $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $vipBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode($touchPerfArr) ]; unset($userBaseInfo, $userId, $perfArr, $fxAmountStatus, $isCanOtherDepartPerf, $touchBonusArr, $touchPerfArr, $vipBonus, $deductData); } if( $insertBonusData ) CalcBonusVIP::batchInsert($insertBonusData); unset($insertBonusData, $allData); $this->calcBonusVIP($offset + $this->_limit); } unset($allData); return true; } /** * 见习达标奖 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function calcBonusStandard(int $offset = 0) { // 月结,如果不是月结点,则直接退出 if (!$this->_isCalcMonth) { return true; } echo sprintf("时间:[%s]见习达标奖,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()), $offset); //从缓存获取分页有本月业绩的会员 $allData = CalcCache::getHasStandardMonthPerfUsers($this->_periodNum, $offset, $this->_limit); if ($allData) { $minSaleCondition = $this->_jxStandardMinSaleCondition(); $insertBonusData = []; foreach ($allData as $userId) { $userBaseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); //条件一:聘级必须为见习主任 if( $userBaseInfo['EMP_LV'] != EmployLevel::JX_ZR_LEVEL_ID ) { unset($userId, $userBaseInfo); continue; } $standardMonthPerf = CalcCache::nowStandardMonthPerf($userId, $this->_periodNum); $totalAmount = $standardMonthPerf['AMOUNT_PCS'] + $standardMonthPerf['AMOUNT_PSS']; if( $totalAmount < $minSaleCondition ) { unset($userId, $userBaseInfo, $standardMonthPerf, $totalAmount); continue; } $standardBonus = $this->_jxStandardAwardAmount($totalAmount); if( $standardBonus <= 0 ) { unset($userId, $userBaseInfo, $standardMonthPerf, $totalAmount, $standardBonus); continue; } CalcCache::standardBonus($userId, $this->_periodNum, $standardBonus); $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'LAST_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_STATUS' => $userBaseInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'AMOUNT' => $standardBonus, 'ORI_BONUS' => $standardBonus, 'RECONSUME_POINTS' => 0, 'MANAGE_TAX' => 0, 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode($standardMonthPerf) ]; unset($userId, $userBaseInfo, $standardMonthPerf, $totalAmount); } if( $insertBonusData ) CalcBonusStandard::batchInsert($insertBonusData); unset($insertBonusData, $minSaleCondition, $insertBonusData, $allData); $this->calcBonusStandard($offset + $this->_limit); } unset($allData); return true; } /** * === 运算相关的辅助功能开始 === */ /** * 获取上2代的得奖人信息 * @param $userId * @param $validDeep * @param $shareBonusOne * @return array */ protected function gxLastTwoBonusData($userId, $validDeep, $shareBonusOne) { $bonusUserList = CalcCache::getShareBonusOneRelation($userId, $this->_periodNum, $validDeep); if( !$bonusUserList ) { unset($bonusUserList); return []; } $bonusUserData = []; $bonusUserTotalPerf = 0; $bonusUserRealList = []; foreach ($bonusUserList as $bonusUserId) { //查看该用户的个人业绩和团队新增业绩总和 $nowPeriodData = CalcCache::nowPeriodPerf($bonusUserId, $this->_periodNum); //本期新增业绩 $bonusUserPerf = $nowPeriodData['PV_PCS'] + $nowPeriodData['PV_PSS']; if ($bonusUserPerf <= 0) { unset($bonusUserId, $nowPeriodData, $bonusUserPerf); continue; } $bonusUserTotalPerf += $bonusUserPerf; $bonusUserRealList[] = [ 'bonusUserId' => $bonusUserId, 'bonusUserPerf' => $bonusUserPerf, ]; unset($bonusUserId, $nowPeriodData, $bonusUserPerf); } unset($bonusUserList); foreach ($bonusUserRealList as $everyData) { $bonusUserData[] = [ 'bonusUid' => $everyData['bonusUserId'], 'bonus' => $shareBonusOne * $everyData['bonusUserPerf'] / $bonusUserTotalPerf, 'validMinPv' => false ]; unset($everyData); } unset($bonusUserRealList); return $bonusUserData; } /** * 获取达标奖的金额 * @param $amount * @return int|mixed */ private function _jxStandardAwardAmount($amount) { // $jxStandardConfig = Json::decode($this->_sysConfig['jxStandard']['VALUE']); // $awardAmount = 0; // foreach ($jxStandardConfig as $everyData) { // if( $amount >= $everyData['salesCondition'] ) { // $awardAmount = $everyData['awardAmount']; // } // unset($everyData); // } // // return $awardAmount; $realTimes = floor($amount/self::JX_STANDARD_BASE_AMOUNT); $calcTimes = min($realTimes, self::JX_STANDARD_MAX_TIMES); $awardAmount = $calcTimes * self::JX_STANDARD_BASE_AMOUNT * self::JX_STANDARD_BONUS_PERCENT / 100; unset($amount, $realTimes, $calcTimes); return $awardAmount; } /** * 获取达标奖的最小条件 * @return int|mixed */ private function _jxStandardMinSaleCondition() { return self::JX_STANDARD_BASE_AMOUNT; } /** * 处理只留最大业绩的逻辑 * @param $userId * @param $perfArr */ private function dealWithMaxPerf($userId, $perfArr) { $maxPerf = max($perfArr); $hitMaxPerf = false; foreach ($perfArr as $key=>$everyPerf) { if( !$hitMaxPerf && $everyPerf == $maxPerf ) { $hitMaxPerf = true; }else { $perfArr[$key] = 0; } unset($key, $everyPerf); } //更新数据库 PerfMonth::updateAll($perfArr, 'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [ 'USER_ID' => $userId, 'CALC_MONTH' => $this->_calcYearMonth ]); unset($userId, $maxPerf, $hitMaxPerf, $perfArr); } /** * VIP奖其它市场的报单业绩是否能满足 * @param $perfArr * @return bool */ private function _isCanVipBonusOtherAreaPerf($perfArr) { $maxAreaPerf = max($perfArr); $totalAreaPerf = array_sum($perfArr); $diffAreaPerf = strval($totalAreaPerf - $maxAreaPerf); if( $diffAreaPerf >= $this->_sysConfig['vipBonusOtherDepartPvCondition']['VALUE'] ) { unset($maxAreaPerf, $totalAreaPerf, $perfArr); return true; }else { unset($maxAreaPerf, $totalAreaPerf, $perfArr); return false; } } /** * 给父级计算的荣衔奖 * @param $userId * @param $userBaseInfo * @param $userEmpLevelSort * @param $qyBonus * @return array */ public function calcParentYC($userId, $userBaseInfo, $userEmpLevelSort, $qyBonus) { if( $userEmpLevelSort <= EmployLevel::EMP_LEVEL_SORT['NO_LEVEL'] ) return []; $validDeep = 0; $bonusDataList = []; $this->loopRelationParentDo($userId, function ($parent) use ($userId, $userEmpLevelSort, &$validDeep, &$bonusDataList) { $bonusUserId = $parent['PARENT_UID']; $bonusUserInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $bonusUserEmpLevel = $this->_empLevelConfig[$bonusUserInfo['EMP_LV']]; $bonusUserEmpLevelSort = $bonusUserEmpLevel['SORT'] ?? EmployLevel::EMP_LEVEL_SORT['NO_LEVEL']; unset($bonusUserInfo, $bonusUserEmpLevel); //必须是有聘级的用户 if( $bonusUserEmpLevelSort <= EmployLevel::EMP_LEVEL_SORT['NO_LEVEL'] ) return self::LOOP_CONTINUE; //超过级别就停止 if( $bonusUserEmpLevelSort > $userEmpLevelSort) return self::LOOP_FINISH; //级别小于就跳过 if( $bonusUserEmpLevelSort < $userEmpLevelSort ) return self::LOOP_CONTINUE; $validDeep++; array_push($bonusDataList, [ 'bonusUserId' => $bonusUserId, 'bonusType' => $validDeep, ]); if( $validDeep >= 2 ) return self::LOOP_FINISH; unset($bonusUserId, $bonusUserEmpLevelSort); }); $insertBonusData = []; foreach ($bonusDataList as $bonusUserData) { $bonusUserId = $bonusUserData['bonusUserId']; $bonusMonthPerfData = CalcCache::nowMonthPerf($bonusUserId, $this->_periodNum); $fxPvStatus = $bonusMonthPerfData['PV_PCS_FX'] >= $this->_sysConfig['monthPcsPvFxCondition']['VALUE']; unset($bonusMonthPerfData); if( !$fxPvStatus ) continue; unset($fxPvStatus); $bonusUserInfo = CalcCache::getUserInfo($bonusUserId, $this->_periodNum); $bonusEmpLevelId = $bonusUserInfo['EMP_LV']; $newEmpBonus = Tool::formatPrice($qyBonus * $this->_sysConfig['sameEmpLevelPercent']['VALUE'] / 100); //总金额限制 $newEmpBonus = $this->bonusTotalLimit($newEmpBonus, $bonusUserId, $bonusUserInfo['REC_NUM'], $bonusUserInfo['ZC_AMOUNT']); if( $newEmpBonus <= 0 ) continue; //扣除相应的复消积分和管理费 $newEmpBonus = Tool::formatPrice($newEmpBonus); $deductData = $this->deduct($bonusUserId, $newEmpBonus); CalcCache::bonus($bonusUserId, $this->_periodNum, 'BONUS_YC_EXTRA', $newEmpBonus, $deductData); // 把育成津贴追加到育成津贴结算表,以便奖金追溯育成津贴用 $insertBonusData[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $bonusUserId, 'LAST_DEC_LV' => $bonusUserInfo['DEC_LV'], 'LAST_EMP_LV' => $bonusUserInfo['EMP_LV'], 'LAST_STATUS' => $bonusUserInfo['STATUS'], 'FROM_USER_ID' => $userId, 'LAST_FROM_DEC_LV' => $userBaseInfo['DEC_LV'], 'LAST_FROM_EMP_LV' => $userBaseInfo['EMP_LV'], 'LAST_FROM_STATUS' => $userBaseInfo['STATUS'], 'DEEP' => 1, 'AMOUNT' => $deductData['surplus'], 'ORI_BONUS' => $newEmpBonus, 'RECONSUME_POINTS' => $deductData['reConsumePoints'], 'MANAGE_TAX' => $deductData['manageTax'], 'BONUS_TYPE' => $bonusUserData['bonusType'], 'PERIOD_NUM' => $this->_periodNum, 'CALC_MONTH' => $this->_calcYearMonth, 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), 'LOGS' => json_encode([ 'empLevelId' => $bonusEmpLevelId, 'qyBonus' => $qyBonus, 'sameEmpLevelPercent' => $this->_sysConfig['sameEmpLevelPercent']['VALUE'], ]), ]; unset($newEmpBonus, $bonusEmpLevelId, $bonusUserId, $bonusUserInfo, $deductData); } unset($userId, $userBaseInfo, $userEmpLevelSort, $qyBonus, $bonusDataList); return $insertBonusData; } /** * 对碰 * @param array $oriPerfArr * @param array $perfArr * @param $percent * @param $loopTimes * @return array */ public function touchPerf(array $oriPerfArr, array $perfArr, $percent, $loopTimes=1) { $resultArr = $oriPerfArr; foreach ($perfArr as $keyT => $perfT) { if ($perfT <= 0) { unset($perfArr[$keyT]); } } if (count($perfArr) >= 2 && $loopTimes < 6) { arsort($perfArr, SORT_NUMERIC); $onePerf = null; $oneKey = null; // $touchSurplusAmount = 0; $touchAmount = 0; // 前两个进行对碰 foreach ($perfArr as $key => $perf) { if ($onePerf === null) { $oneKey = $key; $onePerf = $perf; } else { $touchSurplusAmount = $perf - $onePerf; if ($touchSurplusAmount > 0) { unset($perfArr[$oneKey]); $resultArr['perfArr'][$oneKey] = 0; $perfArr[$key] = $touchSurplusAmount; $touchAmount = $onePerf; } elseif ($touchSurplusAmount < 0) { unset($perfArr[$key]); $resultArr['perfArr'][$key] = 0; $perfArr[$oneKey] = abs($touchSurplusAmount); $touchAmount = $perf; } else { unset($perfArr[$oneKey], $perfArr[$key]); $resultArr['perfArr'][$oneKey] = 0; $resultArr['perfArr'][$key] = 0; $touchAmount = $perf; } break; } } /*if ($touchAmount > $nowDecLevelConfig['QY_TOUCH_CAP']) { $touchAmount = $nowDecLevelConfig['QY_TOUCH_CAP']; }*/ $touchBonus = Tool::formatPrice($touchAmount * $percent); // if ($touchBonus > $nowDecLevelConfig['QY_TOUCH_CAP']) { // $resultArr['touchBonus'] += $nowDecLevelConfig['QY_TOUCH_CAP']; // } else { // $resultArr['touchBonus'] += $touchBonus; // } $resultArr['touchBonus'] += $touchBonus; foreach ($perfArr as $keyR => $perfR) { $resultArr['perfArr'][$keyR] = $perfR; } return $this->touchPerf($resultArr, $perfArr, $percent, $loopTimes+1); } return $resultArr; } /** * 对碰 * @param array $oriPerfArr * @param array $perfArr * @param $decLevel * @param $decLevelConfig * @param $loopTimes * @return array */ public function touchPerfBefore(array $oriPerfArr, array $perfArr, $decLevel, $decLevelConfig, $loopTimes=1) { $resultArr = $oriPerfArr; foreach ($perfArr as $keyT => $perfT) { if ($perfT <= 0) { unset($perfArr[$keyT]); } } if (count($perfArr) >= 2 && $loopTimes < 6) { $nowDecLevelConfig = $decLevelConfig[$decLevel]; arsort($perfArr, SORT_NUMERIC); $onePerf = null; $oneKey = null; // $touchSurplusAmount = 0; $touchAmount = 0; // 前两个进行对碰 foreach ($perfArr as $key => $perf) { if ($onePerf === null) { $oneKey = $key; $onePerf = $perf; } else { $touchSurplusAmount = $perf - $onePerf; if ($touchSurplusAmount > 0) { unset($perfArr[$oneKey]); $resultArr['perfArr'][$oneKey] = 0; $perfArr[$key] = $touchSurplusAmount; $touchAmount = $onePerf; } elseif ($touchSurplusAmount < 0) { unset($perfArr[$key]); $resultArr['perfArr'][$key] = 0; $perfArr[$oneKey] = abs($touchSurplusAmount); $touchAmount = $perf; } else { unset($perfArr[$oneKey], $perfArr[$key]); $resultArr['perfArr'][$oneKey] = 0; $resultArr['perfArr'][$key] = 0; $touchAmount = $perf; } break; } } /*if ($touchAmount > $nowDecLevelConfig['QY_TOUCH_CAP']) { $touchAmount = $nowDecLevelConfig['QY_TOUCH_CAP']; }*/ $touchBonus = Tool::formatPrice($touchAmount * 2 / 100); // if ($touchBonus > $nowDecLevelConfig['QY_TOUCH_CAP']) { // $resultArr['touchBonus'] += $nowDecLevelConfig['QY_TOUCH_CAP']; // } else { // $resultArr['touchBonus'] += $touchBonus; // } $resultArr['touchBonus'] += $touchBonus; foreach ($perfArr as $keyR => $perfR) { $resultArr['perfArr'][$keyR] = $perfR; } return $this->touchPerfBefore($resultArr, $perfArr, $decLevel, $decLevelConfig, $loopTimes+1); } return $resultArr; } /** * 循环父级并执行回调函数 * @param $userId * @param callable $callbackFunc * @param int $offset * @return bool */ public function loopNetworkParentDo($userId, callable $callbackFunc, int $offset = 0) { $allParents = Cache::getAllNetworkParents($userId); $allData = array_slice($allParents, $offset, $this->_limit); unset($allParents); if ($allData) { foreach ($allData as $data) { $funcResult = $callbackFunc($data); if ($funcResult === self::LOOP_FINISH) { return true; } elseif ($funcResult === self::LOOP_CONTINUE) { continue; } unset($data, $funcResult); } unset($allData); return $this->loopNetworkParentDo($userId, $callbackFunc, $offset + $this->_limit); } return true; } /** * 循环推荐网络的父级 * @param $userId * @param callable $callbackFunc * @param int $offset * @return bool */ public function loopRelationParentDo($userId, callable $callbackFunc, int $offset = 0) { $allParents = Cache::getAllRelationParents($userId); $allData = array_slice($allParents, $offset, $this->_limit); unset($allParents); if ($allData) { foreach ($allData as $data) { $funcResult = $callbackFunc($data); if ($funcResult === self::LOOP_FINISH) { return true; } elseif ($funcResult === self::LOOP_CONTINUE) { continue; } unset($data, $funcResult); } unset($allData); return $this->loopRelationParentDo($userId, $callbackFunc, $offset + $this->_limit); } return true; } /** * 共享奖,判断当期此用户,是否有原报单团队奖金 */ public function checkHasOriBonusQyBd($userId) { //判断$parent是否有首单团队奖 $bonus = CalcCache::bonus($userId, $this->_periodNum); if( isset($bonus['ORI_BONUS_QY_BD']) && $bonus['ORI_BONUS_QY_BD'] > 0 ) { return true; } return false; } /** * 判断除大市场外 其它市场的报单业绩 * @param $userId * @return bool * @throws \yii\db\Exception */ public function checkSmallMarketPerf($userId) { // 从缓存中获取会员的上期结余业绩信息 $pervSurplusPerf = CalcCache::surplusPerf($userId, $this->_periodNum); //判断出大市场 $areaNums = [1, 2, 3]; $maxArea = 0; $maxSurplusPerf = 0; foreach ($areaNums as $area) { $areaKey = sprintf('SURPLUS_%dL', $area); if ( isset($pervSurplusPerf[$areaKey]) && $pervSurplusPerf[$areaKey] > $maxSurplusPerf ) { $maxArea = $area; $maxSurplusPerf = $pervSurplusPerf[$areaKey]; } unset($area, $areaKey); } unset($pervSurplusPerf, $maxSurplusPerf); $otherAreaZcPv = 0; $nowPeriodPerf = CalcCache::nowPeriodPerf($userId, $this->_periodNum); foreach ($areaNums as $area) { if( $maxArea > 0 && $area === $maxArea ) continue; $areaKey = sprintf('PV_%dL_ZC', $area); if ( isset($nowPeriodPerf[$areaKey]) && $nowPeriodPerf[$areaKey] > 0 ) { $otherAreaZcPv += $nowPeriodPerf[$areaKey]; } unset($area, $areaKey); } unset($nowPeriodPerf, $areaNums, $maxArea); return $otherAreaZcPv >= self::MIN_BD_PV; } /** * 获取有最小报单PV的用效父级 * @param $userId * @return string */ public function getMinBdPvRelationParent($userId) { $validParentId = ''; $this->loopRelationParentDo($userId, function ($parent) use(&$validParentId) { if ( $this->checkSmallMarketPerf($parent['PARENT_UID']) ) { $validParentId = $parent['PARENT_UID']; unset($parent); return self::LOOP_FINISH; } unset($parent); }); return$validParentId; } /** * 获取有最小报单PV的用效父级 20220407修改成是否此期此用户有原报单团队奖金 * @param $userId * @return string */ public function getMinBdPvNetworkParent($userId, $openFindLimit = 1, $findLimitTimes = 5) { $validParentId = ''; $validDeep = 1; $this->loopNetworkParentDo($userId, function ($parent) use(&$validParentId,&$validDeep,$openFindLimit,$findLimitTimes) { if ( $this->checkHasOriBonusQyBd($parent['PARENT_UID']) ) { $validParentId = $parent['PARENT_UID']; unset($parent); return self::LOOP_FINISH; } // 只找5层 if ( $openFindLimit && $validDeep >= $findLimitTimes ) { unset($parent); return self::LOOP_FINISH; } $validDeep += 1; unset($parent); }); return$validParentId; } // public function getMinBdPvNetworkParent($userId, $openFindLimit = 1, $findLimitTimes = 5) { // $validParentId = ''; // $validDeep = 1; // $this->loopNetworkParentDo($userId, function ($parent) use(&$validParentId,&$validDeep,$openFindLimit,$findLimitTimes) { // if ( $this->checkSmallMarketPerf($parent['PARENT_UID']) ) { // $validParentId = $parent['PARENT_UID']; // unset($parent); // return self::LOOP_FINISH; // } // // 只找5层 // if ( $openFindLimit && $validDeep >= $findLimitTimes ) { // unset($parent); // return self::LOOP_FINISH; // } // $validDeep += 1; // unset($parent); // }); // return$validParentId; // } /** * 按级别的收入上限 * 新的需求调整: 改成不按月进行限制,并且去掉vip奖 * @param $bonus * @param $userId * @param $declarationLevel * @return float */ public function declarationLevelCap($bonus, $userId, $declarationLevel) { $decLevelConfig = $this->_decLevelConfig; $nowDecLevelConfig = $decLevelConfig[$declarationLevel]; unset($decLevelConfig); $maxGetBonus = $nowDecLevelConfig['INCOME_CAP']; if( $bonus <= $maxGetBonus) { return $bonus; }else { return $maxGetBonus; } } // public function declarationLevelCap($bonus, $userId, $declarationLevel) { // $decLevelConfig = $this->_decLevelConfig; // $nowDecLevelConfig = $decLevelConfig[$declarationLevel]; // unset($decLevelConfig); // //本月往期奖金 这里执行速度可能慢一些,但需求如此没有办法 // $lastData = CalcCache::lastPeriodMonthCalcBonus($userId, $this->_periodNum, $this->_calcMonth); // $lastTotal = $lastData['ORI_BONUS_QY_SUM'] + $lastData['ORI_BONUS_VIP_SUM']; // // 从缓存中获取用户的奖金 // $bonusData = CalcCache::bonus($userId, $this->_periodNum); // $thisTotal = $bonusData['ORI_BONUS_QY'] + $bonusData['ORI_BONUS_VIP']; // $maxGetBonus = $nowDecLevelConfig['INCOME_CAP'] * $this->_calcMonthPeriodNumCount - $lastTotal - $thisTotal; // unset($lastData, $lastTotal, $bonusData, $thisTotal); // if( $maxGetBonus <= 0 ) return 0.00; // if( $bonus <= $maxGetBonus) { // return $bonus; // }else { // return $maxGetBonus; // } // } /** * 总奖金限制 * @param $bonus * @param $userId * @param $recNum * @param $decAmount * @return float */ public function bonusTotalLimit($bonus, $userId, $recNum, $decAmount) { //@todo 临时不做总奖金限制 return $bonus; if( $recNum >= 3 ) return $bonus; $limitAmount = 0; switch ($recNum) { case 0: $limitAmount = $decAmount * $this->_sysConfig['bonusTotalZeroLimit']['VALUE']; break; case 1: $limitAmount = $decAmount * $this->_sysConfig['bonusTotalOneLimit']['VALUE']; break; case 2: $limitAmount = $decAmount * $this->_sysConfig['bonusTotalTwoLimit']['VALUE']; break; default: break; } // 从缓存中获取用户的奖金 $lastUserBonus = CalcCache::LastUserBonus($userId, $this->_periodNum);//往期的总金额 $bonusData = CalcCache::bonus($userId, $this->_periodNum); $bonusTotal = $bonusData['BONUS_TOTAL'] + $lastUserBonus['BONUS_TOTAL']; unset($lastUserBonus, $userId, $recNum, $decAmount, $bonusData); if( $bonusTotal >= $limitAmount ) return 0.00; if( $bonusTotal + $bonus <= $limitAmount) { return $bonus; }else { return $limitAmount - $bonusTotal; } } /** * 扣除复消积分和管理费 * @param $userId * @param $bonus * @return array * @throws \yii\db\Exception */ public function deductNoReconsumePoints($userId, $bonus): array { $manageTax = $bonus * $this->_sysConfig['manageTaxPercent']['VALUE'] / 100; $surplus = $bonus - $manageTax; return [ 'reConsumePoints' => 0.00, 'manageTax' => Tool::formatPrice($manageTax), 'surplus' => Tool::formatPrice($surplus), ]; } /** * 扣除复消积分和管理费 * @param $userId * @param $bonus * @return array * @throws \yii\db\Exception */ public function deduct($userId, $bonus) { //判断是否达到了本月扣除复消的上限 $cacheData = CalcCache::monthLastPeriodReconsumePoints($userId, $this->_periodNum, $this->_calcYearMonth); $bonusCache = CalcCache::bonus($userId, $this->_periodNum); $reConsumePointsTotal = $bonusCache['RECONSUME_POINTS'] + $cacheData['RECONSUME_POINTS_SUM']; $reConsumePointsCap = $this->_sysConfig['reConsumePointsMonthCap']['VALUE']; unset($cacheData, $bonusCache); $reConsumePoints = 0; if( $reConsumePointsTotal < $reConsumePointsCap ) { $reConsumePoints = $bonus * $this->_sysConfig['reConsumePointsPercent']['VALUE'] / 100; $reConsumePoints = min($reConsumePoints, $reConsumePointsCap-$reConsumePointsTotal); } unset($reConsumePointsTotal, $reConsumePointsCap); $manageTax = $bonus * $this->_sysConfig['manageTaxPercent']['VALUE'] / 100; $surplus = $bonus - $reConsumePoints - $manageTax; return [ 'reConsumePoints' => Tool::formatPrice($reConsumePoints),//复效积分 'manageTax' => Tool::formatPrice($manageTax),//管理费 'surplus' => Tool::formatPrice($surplus),//真实奖金 ]; } /** * 更新百分比并发送 * @param $percent */ private function _updatePercent($percent) { // 把数据写入数据库中 Period::updateAll(['CALC_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]); \Yii::$app->swooleAsyncTimer->pushAsyncPercentToAdmin($percent, ['MODEL' => 'PERIOD', 'ID' => $this->_periodId, 'FIELD' => 'CALC_PERCENT']); } /** * 把往期有月奖金的会员加到本期有奖会员缓存列表中 * @param int $offset * @return bool */ public function loopMonthBonusUserFromDbToCache($offset = 0) { if (!$this->_isCalcMonth) { return true; } $allData = CalcMonthBonusUser::findUseDbCalc()->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->offset($offset)->limit($this->_limit)->asArray()->all(); if ( $allData ) { foreach ($allData as $everyData) { CalcCache::addHasBonusUsers($everyData['USER_ID'], $this->_periodNum); unset($everyData); } unset($allData); $this->loopMonthBonusUserFromDbToCache($offset + $this->_limit); } unset($allData); return true; } /** * 把缓存中的月奖用户信息存到数据库 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function loopMonthBonusUserToDb($offset = 0) { echo sprintf("时间:[%s]月奖会员入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); $allData = CalcCache::getHasMonthBonusUsers($this->_periodNum, $offset, $this->_limit); if($allData) { $insertDataBonusUser = []; foreach($allData as $userId){ $insertDataBonusUser[] = [ 'ID' => SnowFake::instance()->generateId(), 'USER_ID' => $userId, 'CALC_MONTH' => $this->_calcYearMonth, 'PERIOD_NUM' => $this->_periodNum, 'CREATED_AT' => Date::nowTime() ]; unset($userId); } if( $insertDataBonusUser ) CalcMonthBonusUser::batchInsert($insertDataBonusUser); unset($insertDataBonus, $allData); return $this->loopMonthBonusUserToDb($offset + $this->_limit); } unset($allData); return true; } //奖金入库 /** * 循环奖服务奖金会员,并入库 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function loopBonusUsers($offset = 0) { echo sprintf("时间:[%s]缓存奖金数据入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); // 从缓存列表里面从底层往上倒序获取会员 // 这里有问题,因为蓝星奖,是存储过程计算的,并没有加入缓存,这里需要修改. // 给用户发送兑换积分,也需要进行调整查看。 // CalcCache::addHasBonusUsers($everyData['USER_ID'], $this->_periodNum); $allData = CalcCache::getHasBonusUsers($this->_periodNum, $offset, $this->_limit); if($allData){ $insertDataBonus = []; foreach($allData as $userId){ $tempBonusData = $this->bonusData($userId); if(!empty($tempBonusData['result'])){ $insertDataBonus[] = $tempBonusData['result']; } unset($userId, $tempBonusData); } CalcBonus::batchInsert($insertDataBonus); unset($insertDataBonus, $allData); return $this->loopBonusUsers($offset + $this->_limit); } return true; } // 奖金入库完成,将各个奖金计算流水会员聘级,更新成蓝星奖当时计算的聘级 public function loopCalcBlueEmpLv($offset = 0) { if( !$this->_isCalcMonth ) { // 不是结算月,则不需要进行聘级调整 return false; } // 从缓存获取分页有收入的会员信息 $allData = CalcBonusBS::findUseDbCalc() ->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]) ->groupBy('USER_ID') ->offset($offset) ->limit($this->_limit) ->asArray() ->all(); if ($allData) { foreach ($allData as $data) { $nowBsEmpLv = $data['LEVEL_ID']; // 当前蓝星奖计算(即管理奖) 的等级 // 修改AR_CALC_BONUS的LAST_EMP_LV聘级,修改奖金流水的聘级AR_FLOW_BONUS表的LAST_EMP_LV // 期结算结果 CalcBonus::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 奖金流水 FlowBonus::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 共享奖流水 CalcBonusGX::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 推广奖流水 CalcBonusTG::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 团队奖流水 CalcBonusQY::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 服务奖流水 CalcBonusBD::updateAll(['LAST_EMP_LV' => $nowBsEmpLv], 'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); // 更新form的聘级 CalcBonusGX::updateAll(['LAST_FROM_EMP_LV' => $nowBsEmpLv], 'FROM_USER_ID=:FROM_USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':FROM_USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); CalcBonusTG::updateAll(['LAST_FROM_EMP_LV' => $nowBsEmpLv], 'FROM_USER_ID=:FROM_USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':FROM_USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); CalcBonusBD::updateAll(['LAST_FROM_EMP_LV' => $nowBsEmpLv], 'FROM_USER_ID=:FROM_USER_ID AND PERIOD_NUM=:PERIOD_NUM', [ ':FROM_USER_ID' => $data['USER_ID'], ':PERIOD_NUM' => $this->_periodNum ] ); } unset($allData); return $this->loopCalcBlueEmpLv($offset + $this->_limit); } unset($allData); return true; } /** * 奖金 * @param $userId * @return array * @throws \yii\db\Exception */ public function bonusData($userId) { // 从缓存中获取用户的奖金 $bonus = CalcCache::bonus($userId, $this->_periodNum); $standardBonus = CalcCache::standardBonus($userId, $this->_periodNum); $baseInfo = CalcCache::getUserInfo($userId, $this->_periodNum); $perfData = CalcCache::nowPeriodPerf($userId, $this->_periodNum); $travelBonus = CalcCache::zoneBonus($userId, $this->_periodNum, CalcCache::REDIS_KEY_PREFIX_TRAVEL_BONUS); $carBonus = CalcCache::zoneBonus($userId, $this->_periodNum, CalcCache::REDIS_KEY_PREFIX_CAR_BONUS); $houseBonus = CalcCache::zoneBonus($userId, $this->_periodNum, CalcCache::REDIS_KEY_PREFIX_HOUSE_BONUS); $empLv = $baseInfo['EMP_LV']; // if($this->_isCalcMonth){ // $empLv = $this->nowMonthPerfData($userId)['LAST_EMP_LV']; // } $pervSurplusPerf = CalcCache::surplusPerf($userId, $this->_periodNum); // //没有共享和管理奖 以前的管理奖和共享奖逻辑 // $bonusReal = $bonus['BONUS_BD'] + $bonus['BONUS_TG'] + $bonus['BONUS_XF'] + $bonus['BONUS_YJ'] + $bonus['BONUS_QY'] + $bonus['BONUS_YC'] + $bonus['BONUS_YC_EXTRA'] + $bonus['BONUS_VIP'] + $standardBonus; // $realBonusGx = 0; // $realBonusGl = 0; // if( $this->_isCalcMonth ) { // //查看是否复消300 // $monthPerfData = CalcCache::nowMonthPerf($userId, $this->_periodNum); // $fxPvStatus = $monthPerfData['PV_PCS_FX'] >= $this->_sysConfig['monthPcsPvFxCondition']['VALUE']; // if ( $fxPvStatus ) {//加上本期和往期的共享和管理奖 // $monthSumData = CalcBonus::findUseSlaves()->select('SUM(BONUS_GX) AS BONUS_GX_SUM, SUM(BONUS_GL) AS BONUS_GL_SUM')->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', ['USER_ID'=>$userId, 'CALC_MONTH'=>$this->_calcYearMonth])->asArray()->one(); // $bonusGxSum = $monthSumData['BONUS_GX_SUM'] ?? 0; // $bonusGlSum = $monthSumData['BONUS_GL_SUM'] ?? 0; // $realBonusGx += $bonusGxSum + $bonus['BONUS_GX']; // $realBonusGl += $bonusGlSum + $bonus['BONUS_GL']; // $bonusReal += $realBonusGx + $realBonusGl; // unset($monthSumData, $bonusGxSum, $bonusGlSum); // } // } //没有共享和管理奖 $bonusReal = $bonus['BONUS_BD'] + $bonus['BONUS_TG'] + $bonus['BONUS_XF'] + $bonus['BONUS_YJ'] + $bonus['BONUS_QY'] + $bonus['BONUS_YC'] + $bonus['BONUS_YC_EXTRA'] + $bonus['BONUS_VIP'] + $standardBonus + $bonus['BONUS_BS_MNT'] + $bonus['BONUS_BS_ABBR']; $realBonusGx = 0; $realBonusGl = 0; $realBonusBs = 0; // 蓝星管理奖. BlueStar $blueStartOriBonus = 0; $blueStartManageTax = 0; $exchangePoints = 0; // 蓝星奖管理奖. 产生的兑换积分 $realBonusBsMnt = 0; // 蓝星管理奖——实发奖金 $blueStartOriBonusMnt = 0; // 蓝星管理奖——原奖金 $blueStartManageTaxMnt = 0; // 蓝星管理奖——管理费 $realBonusBsAbbr = 0; // 蓝星业绩奖——实发奖金 $blueStartOriBonusAbbr = 0; // 蓝星业绩奖——原奖金 $blueStartManageTaxAbbr = 0; // 蓝星业绩奖——管理费 if( $this->_isCalcMonth ) { // 个人月消费PV大于配置值,才会计算发放蓝星奖 $fxPvStatus = $this->_isMonthPerfLimit($userId); // BONUS_REAL 字段是发到用户的真实奖金 if ( $fxPvStatus ) { // 管理奖改成了蓝星奖,但是对于用户来说依旧叫管理奖.字段改成bs. // 因为管理奖(即蓝星奖,是用存储过程计算的,则此处直接取AR_CALC_BONUS_BS表中计算的结果数据使用, // 并将管理奖结果同步到当前结算月的CalcBonus中) // 由于单独奖金流水记录每次都插入,所以倒叙找最新的数据. $userBS = CalcBonusBS::find() ->where( 'PERIOD_NUM=:PERIOD_NUM AND USER_ID=:USER_ID', [ ':PERIOD_NUM' => $this->_periodNum, ':USER_ID' => $userId ] ) ->select('AMOUNT,ORI_BONUS,MANAGE_TAX,LEVEL_ID,PRODUCT_POINT,AMOUNT_MNT,ORI_BONUS_MNT,MANAGE_TAX_MNT,AMOUNT_ABBR,ORI_BONUS_ABBR,MANAGE_TAX_ABBR') ->limit(1) ->orderBy('CREATED_AT DESC') ->asArray() ->all(); $userBS = is_array($userBS) ? reset($userBS) : []; $blueStartAmount = isset($userBS['AMOUNT']) && !empty($userBS['AMOUNT']) ? $userBS['AMOUNT'] : 0; // 奖金 $blueStartOriBonus = isset($userBS['ORI_BONUS']) && !empty($userBS['ORI_BONUS']) ? $userBS['ORI_BONUS'] : 0; // 原奖金 $blueStartManageTax = isset($userBS['MANAGE_TAX']) && !empty($userBS['MANAGE_TAX']) ? $userBS['MANAGE_TAX'] : 0; // 管理费 $realBonusBsMnt = $userBS['AMOUNT_MNT'] ?? 0; // 蓝星管理奖. 实发奖金 $blueStartOriBonusMnt = $userBS['ORI_BONUS_MNT'] ?? 0; // 蓝星管理奖. 原奖金 $blueStartManageTaxMnt = $userBS['MANAGE_TAX_MNT'] ?? 0; // 蓝星管理奖. 管理费 $realBonusBsAbbr = $userBS['AMOUNT_ABBR'] ?? 0; // 蓝星业绩奖. 奖金 $blueStartOriBonusAbbr = $userBS['ORI_BONUS_ABBR'] ?? 0; // 蓝星业绩奖. 原奖金 $blueStartManageTaxAbbr = $userBS['MANAGE_TAX_ABBR'] ?? 0; // 蓝星业绩奖. 管理费 $blueStartManageTax += $blueStartManageTaxMnt + $blueStartManageTaxAbbr; // 管理费 $monthSumData = CalcBonus::findUseSlaves() ->select('SUM(BONUS_GX) AS BONUS_GX_SUM, SUM(BONUS_GL) AS BONUS_GL_SUM') ->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [ 'USER_ID'=>$userId, 'CALC_MONTH'=>$this->_calcYearMonth ] ) ->asArray() ->one(); $realBonusBs = $blueStartAmount; // 蓝星奖直接取数据库中算好的值PRODUCT_POINT $exchangePoints = isset($userBS['PRODUCT_POINT']) && !empty($userBS['PRODUCT_POINT']) ? $userBS['PRODUCT_POINT'] : 0; // 兑换积分 // 蓝星奖总奖金:管理奖+业绩奖 $blueStartOriBonus = $blueStartOriBonusMnt + $blueStartOriBonusAbbr; $bonus['BONUS_TOTAL'] = $bonus['BONUS_TOTAL'] + $blueStartOriBonus; // 管理奖在存储过程计算,这里单独加上管理奖(即蓝星奖) unset($monthSumData, $bonusGxSum, $bonusGlSum); } } $result = [ 'USER_ID' => $userId, 'LAST_USER_NAME' => $baseInfo['USER_NAME'], 'LAST_REAL_NAME' => $baseInfo['REAL_NAME'], 'LAST_DEC_LV' => $baseInfo['DEC_LV'], 'LAST_EMP_LV' => $empLv, 'LAST_STATUS' => $baseInfo['STATUS'], 'LAST_MOBILE' => $baseInfo['MOBILE'], 'LAST_PERIOD_AT' => $baseInfo['PERIOD_NUM'], 'LAST_CREATED_AT' => $baseInfo['CREATED_AT'], 'LAST_SUB_COM_ID' => $baseInfo['SUB_COM_ID'], 'LAST_PROVINCE' => $baseInfo['PROVINCE'], 'LAST_CITY' => $baseInfo['CITY'], 'LAST_COUNTY' => $baseInfo['COUNTY'], 'LAST_SYSTEM_ID' => $baseInfo['SYSTEM_ID'] ? $baseInfo['SYSTEM_ID'] : '', 'LAST_IS_DIRECT_SELLER' => $baseInfo['IS_DIRECT_SELLER'], 'LAST_REC_USER_NAME' => $baseInfo['REC_USER_NAME'], 'LAST_REC_REAL_NAME' => $baseInfo['REC_REAL_NAME'], 'LAST_CON_USER_NAME' => $baseInfo['CON_USER_NAME'], 'LAST_CON_REAL_NAME' => $baseInfo['CON_REAL_NAME'], 'EXCHANGE_POINTS' => $exchangePoints, // 兑换积分 // 'LAST_LOCATION' => $baseInfo['LOCATION'] ? $baseInfo['LOCATION'] : 1, //@todo 'LAST_LOCATION' => 1, 'BONUS_BD' => $bonus['BONUS_BD'], 'BONUS_TG' => $bonus['BONUS_TG'], 'BONUS_XF' => $bonus['BONUS_XF'], 'BONUS_YJ' => $bonus['BONUS_YJ'], 'BONUS_GX' => $bonus['BONUS_GX'], 'BONUS_GL' => $bonus['BONUS_GL'], 'BONUS_QY' => $bonus['BONUS_QY'], 'BONUS_YC' => $bonus['BONUS_YC'] + $bonus['BONUS_YC_EXTRA'], 'BONUS_VIP' => $bonus['BONUS_VIP'], 'RECONSUME_POINTS' => $bonus['RECONSUME_POINTS'], 'MANAGE_TAX' => $blueStartManageTax, // 管理费 'BONUS_INCOME'=>$bonus['INCOME_TOTAL'], 'BONUS_REAL'=> $bonusReal, 'BONUS_TOTAL'=>$bonus['BONUS_TOTAL'], 'ORI_BONUS_BD' => $bonus['ORI_BONUS_BD'], 'ORI_BONUS_TG' => $bonus['ORI_BONUS_TG'], 'ORI_BONUS_XF' => $bonus['ORI_BONUS_XF'], 'ORI_BONUS_YJ' => $bonus['ORI_BONUS_YJ'], 'ORI_BONUS_YJ_BD' => $bonus['ORI_BONUS_YJ_BD'], 'ORI_BONUS_YJ_FX' => $bonus['ORI_BONUS_YJ_FX'], 'ORI_BONUS_GX' => $bonus['ORI_BONUS_GX'], 'REAL_BONUS_GX' => $realBonusGx, 'ORI_BONUS_GL' => $bonus['ORI_BONUS_GL'], 'REAL_BONUS_GL' => $realBonusGl, 'BONUS_BS' => $realBonusBs, // 新的管理奖金,即蓝星管理奖 'ORI_BONUS_BS' => $blueStartOriBonus, // 蓝星管理奖金原奖金,即包含管理费 'REAL_BONUS_BS' => $realBonusBs, // 实发蓝星管理奖金 'BONUS_BS_MNT' => $realBonusBsMnt, // 蓝星管理奖 'ORI_BONUS_BS_MNT' => $blueStartOriBonusMnt, // 蓝星管理奖金原奖金,即包含管理费 'REAL_BONUS_BS_MNT' => $realBonusBsMnt, // 实发蓝星管理奖金 'MANAGE_TAX_MNT' => $blueStartManageTaxMnt, // 实发蓝星管理——管理费 'BONUS_BS_ABBR' => $realBonusBsAbbr, // 蓝星业绩奖 'ORI_BONUS_BS_ABBR' => $blueStartOriBonusAbbr, // 蓝星业绩奖金原奖金,即包含管理费 'REAL_BONUS_BS_ABBR' => $realBonusBsAbbr, // 实发蓝星业绩奖金 'MANAGE_TAX_ABBR' => $blueStartManageTaxAbbr, // 实发蓝星业绩奖——管理费 'ORI_BONUS_GL_BD' => $bonus['ORI_BONUS_GL_BD'], 'ORI_BONUS_GL_FX' => $bonus['ORI_BONUS_GL_FX'], 'ORI_BONUS_QY' => $bonus['ORI_BONUS_QY'], 'ORI_BONUS_QY_BD' => $bonus['ORI_BONUS_QY_BD'], 'ORI_BONUS_QY_FX' => $bonus['ORI_BONUS_QY_FX'], 'ORI_BONUS_YC' => $bonus['ORI_BONUS_YC'] + $bonus['ORI_BONUS_YC_EXTRA'], 'ORI_BONUS_VIP' => $bonus['ORI_BONUS_VIP'], 'ORI_BONUS_STANDARD' => $standardBonus, 'BONUS_TRAVEL' => $travelBonus, // 旅游奖 'BONUS_CAR' => $carBonus, // 名车奖 'BONUS_HOUSE' => $houseBonus, // 豪宅奖 //以下没有用 'BONUS_FW' => 0, 'BONUS_FX' => $bonus['BONUS_FX'], 'BONUS_LS' => $bonus['BONUS_LS'], 'BONUS_BT' => $bonus['BONUS_BT'], 'BONUS_BT_PROD' => $bonus['BONUS_BT_PROD'], 'BONUS_BT_TOOL' => $bonus['BONUS_BT_TOOL'], 'DEDUCT_ZR' => $bonus['DEDUCT_ZR'], 'BONUS_FL' => $bonus['BONUS_FL'], 'BONUS_CF' => $bonus['BONUS_CF'], 'BONUS_LX' => $bonus['BONUS_LX'], 'SHOULD_QY' => $bonus['BONUS_QY'], 'SHOULD_DEDUCT_ZR' => $bonus['DEDUCT_ZR'], 'PV_1L' => $perfData['PV_1L_TOUCH'],//TOUCH为碰业绩 'QY_1L' => $perfData['PV_1L_TOUCH'] + $pervSurplusPerf['SURPLUS_1L'], 'SURPLUS_1L' => $perfData['SURPLUS_1L'], 'PV_2L' => $perfData['PV_2L_TOUCH'], 'QY_2L' => $perfData['PV_2L_TOUCH'] + $pervSurplusPerf['SURPLUS_2L'], 'SURPLUS_2L' => $perfData['SURPLUS_2L'], 'PV_3L' => $perfData['PV_3L_TOUCH'], 'QY_3L' => $perfData['PV_3L_TOUCH'] + $pervSurplusPerf['SURPLUS_3L'], 'SURPLUS_3L' => $perfData['SURPLUS_3L'], 'PV_4L' => $perfData['PV_4L_TOUCH'], 'QY_4L' => $perfData['PV_4L_TOUCH'] + $pervSurplusPerf['SURPLUS_4L'], 'SURPLUS_4L' => $perfData['SURPLUS_4L'], 'PV_5L' => $perfData['PV_5L_TOUCH'], 'QY_5L' => $perfData['PV_5L_TOUCH'] + $pervSurplusPerf['SURPLUS_5L'], 'SURPLUS_5L' => $perfData['SURPLUS_5L'], 'PV_PCS' => $perfData['PV_PCS'], 'PV_LS_TOUCH' => 0.00, 'SURPLUS_LS' => 0.00, 'QY_LS' => 0.00, 'PV_TOUCH' => Tool::formatPrice($perfData['PV_1L_TOUCH'] + $perfData['PV_2L_TOUCH'] + $perfData['PV_3L_TOUCH'] + $perfData['PV_4L_TOUCH'] + $perfData['PV_5L_TOUCH'] + $perfData['PV_LS_TOUCH']), 'PERIOD_NUM' => $this->_periodNum, 'CALC_YEAR' => $this->_calcYear, 'CALC_MONTH' => $this->_calcYearMonth, 'CALCULATED_AT' => Date::nowTime(), 'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH), 'CREATED_AT' => Date::nowTime(), ]; $resend = []; unset($bonus, $realBonusGx, $realBonusGl, $bonusReal); return ['result'=>$result,'resend'=>$resend]; } /** * 根据本有收入计算基础积分 * @param int $offset * @return bool */ public function calcBaseScore(int $offset=0) { if (!$this->_isCalcMonth) { return true; } echo sprintf("时间:[%s]基础积分,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); //查询本月的,每人的累计总收入 $allData = CalcBonus::findUseDbCalc()->select('USER_ID, SUM(BONUS_TOTAL) AS TOTAL_SUM, SUM(ORI_BONUS_BD) AS BD_TOTAL_SUM')->where('CALC_MONTH=:CALC_MONTH', [':CALC_MONTH' => $this->_calcYearMonth])->groupBy('USER_ID')->orderBy('USER_ID DESC')->offset($offset)->limit($this->_limit)->asArray()->all(); if ($allData) { foreach ($allData as $everyData) { $validTotalSum = $everyData['TOTAL_SUM'] - $everyData['BD_TOTAL_SUM']; if( $validTotalSum <=0 ) continue; //达不到 见习主任级别,不产生基础积分 $userBaseInfo = CalcCache::getUserInfo($everyData['USER_ID'], $this->_periodNum); $userEmpLevel = $this->_empLevelConfig[$userBaseInfo['EMP_LV']]; $userEmpLevelSort = $userEmpLevel['SORT'] ?? EmployLevel::EMP_LEVEL_SORT['NO_LEVEL']; unset($userBaseInfo, $userEmpLevel); if( $userEmpLevelSort < EmployLevel::EMP_LEVEL_SORT['JX_ZR_LEVEL'] ) { unset($userEmpLevelSort); continue; } unset($userEmpLevelSort); //根据总收入获取积分 $baseScore = $this->_getBaseScoreByTotalBonus($validTotalSum); //根据用户的级别判断 能否得到级别积分 if( $baseScore > 0 ) { CalcCache::nowMonthScore($everyData['USER_ID'], $this->_periodNum, [ 'BASE_SCORE' => $baseScore, ]); CalcCache::addHasScoreUsers($everyData['USER_ID'], $this->_periodNum); } unset($everyData, $validTotalSum, $baseScore); } unset($allData); return $this->calcBaseScore($offset + $this->_limit); } unset($allData); return true; } /** * 循环积分入库 * @param int $offset * @return bool * @throws \yii\db\Exception */ public function loopWriteScore(int $offset = 0) { if(!$this->_isCalcMonth){ return true; } echo sprintf("时间:[%s]积分入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset); // 从缓存列表里面从底层往上倒序获取会员 $allData = CalcCache::getHasScoreUsers($this->_periodNum, $offset, $this->_limit); if($allData){ $insertDataMonthScore = []; foreach($allData as $userId){ $monthScoreData = CalcCache::nowMonthScore($userId, $this->_periodNum); $totalScore = $monthScoreData['BASE_SCORE'] + $monthScoreData['LEVEL_SCORE'] + $monthScoreData['UPGRADE_SCORE']; if( $totalScore <= 0 ) continue; $insertDataMonthScore[] = [ 'USER_ID' => $userId, 'BASE_SCORE' => $monthScoreData['BASE_SCORE'], 'LEVEL_SCORE' => $monthScoreData['LEVEL_SCORE'], 'UPGRADE_SCORE' => $monthScoreData['UPGRADE_SCORE'], 'TOTAL_SCORE' => $totalScore, 'PERIOD_NUM' => $this->_periodNum, 'CALC_MONTH' => $this->_calcYearMonth, 'CREATED_AT' => Date::nowTime(), ]; unset($userId, $monthScoreData, $totalScore); } ScoreMonth::batchInsert($insertDataMonthScore); unset($insertDataMonthScore, $allData); return $this->loopWriteScore($offset + $this->_limit); } unset($allData); return true; } /** * 根据总收入获取相应的基础积分 * @param $totalBonus * @return int|mixed */ private function _getBaseScoreByTotalBonus($totalBonus) { $baseScoreConfig = Json::decode($this->_sysConfig['baseScore']['VALUE']); $baseScore = 0; foreach ($baseScoreConfig as $everyScoreData) { if( $totalBonus < $everyScoreData['monthTotalPvMin'] ) continue; if( $everyScoreData['monthTotalPvMax'] != 0 && $totalBonus >= $everyScoreData['monthTotalPvMax'] ) continue; $baseScore = $everyScoreData['score']; unset($everyScoreData); break; } unset($baseScoreConfig, $totalBonus); return $baseScore; } // 判断是否满足月最低消费 public function _isMonthPerfLimit($userId) { $userMonthTotal = PerfMonth::find()->where( 'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', ['USER_ID'=>$userId, 'CALC_MONTH'=>$this->_calcYearMonth] ) ->asArray() ->one(); $fxPvStatus = false; if (isset($userMonthTotal['PV_PCS']) && $userMonthTotal['PV_PCS'] >= $this->_sysConfig['monthPcsPvFxCondition']['VALUE']) { $fxPvStatus = true; } return $fxPvStatus; } }