|
|
@@ -10,11 +10,15 @@ namespace common\helpers\bonus;
|
|
|
|
|
|
use common\helpers\Cache;
|
|
|
use common\helpers\Date;
|
|
|
+use common\helpers\LoggerTool;
|
|
|
use common\helpers\snowflake\SnowFake;
|
|
|
use common\helpers\Tool;
|
|
|
+use common\models\BsBonus103Calc;
|
|
|
+use common\models\BsBonus103CalcEvent;
|
|
|
use common\models\CalcBonus;
|
|
|
use common\models\CalcBonusBD;
|
|
|
use common\models\CalcBonusBS;
|
|
|
+use common\models\CalcBonusBsDefaultBonus;
|
|
|
use common\models\CalcBonusBT;
|
|
|
use common\models\CalcBonusCF;
|
|
|
use common\models\CalcBonusFL;
|
|
|
@@ -52,9 +56,11 @@ use common\models\User;
|
|
|
use common\models\UserInfo;
|
|
|
use common\models\UserPerf;
|
|
|
use SebastianBergmann\CodeCoverage\Report\PHP;
|
|
|
+use Yii;
|
|
|
use yii\base\BaseObject;
|
|
|
use yii\base\Exception;
|
|
|
use yii\base\StaticInstanceTrait;
|
|
|
+use yii\db\Expression;
|
|
|
use yii\helpers\Json;
|
|
|
|
|
|
class BonusCalc extends BaseObject {
|
|
|
@@ -107,6 +113,10 @@ class BonusCalc extends BaseObject {
|
|
|
//最小报单pv
|
|
|
const MIN_BD_PV = 980;
|
|
|
|
|
|
+ const QUALIFIED_NONE = 0; // 无达标状态
|
|
|
+ const QUALIFIED_SELF = 1; // 自身业绩达标
|
|
|
+ const QUALIFIED_CASCADE = 2; // 级联被动达标
|
|
|
+
|
|
|
/**
|
|
|
* 1、抓取所有报单、订单,把能当时产生业绩的报单存入业绩单。例如注册单,订单
|
|
|
* 2、从业绩单中循环,并计算上下级业绩
|
|
|
@@ -240,14 +250,44 @@ class BonusCalc extends BaseObject {
|
|
|
$t17 = microtime(true);
|
|
|
// 蓝星奖入库,实际上是插入有奖金会员数据缓存中.
|
|
|
// 调用存储过程,计算蓝星管理奖金
|
|
|
- $this->calcBsProcedure();
|
|
|
- // 将有蓝星管理奖金的用户加入到有奖金缓存用户中
|
|
|
- $this->calcBonusBsGL();
|
|
|
- $this->calcBonusBsGLCF();
|
|
|
- $this->calcBonusBsYJCF();
|
|
|
- $t18 = microtime(true);
|
|
|
- echo('计算蓝星管理奖'.($this->_sysConfig['openGL']['VALUE']?'完成':'关闭').',耗时:' . round($t18 - $t17, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
|
|
|
- $this->_updatePercent(65);
|
|
|
+// $this->calcBsProcedure();
|
|
|
+// // 将有蓝星管理奖金的用户加入到有奖金缓存用户中
|
|
|
+// $this->calcBonusBsGL();
|
|
|
+// $this->calcBonusBsGLCF();
|
|
|
+// $this->calcBonusBsYJCF();
|
|
|
+
|
|
|
+ // 不是结算月,则不进行计算
|
|
|
+ if ($this->_isCalcMonth) {
|
|
|
+ echo('计算蓝星管理奖开始,' . PHP_EOL);
|
|
|
+ // 期数配置
|
|
|
+ $calcData = Period::findOneAsArray('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
|
|
|
+ // 删除日志
|
|
|
+ BsBonus103CalcEvent::deleteAll();
|
|
|
+ // 清除数据
|
|
|
+ $this->calcClean($this->_periodNum);
|
|
|
+ // 初始化
|
|
|
+ $this->calcBsInitProcedure($this->_periodNum, $calcData['CALC_MONTH'], $calcData['CALC_YEAR']);
|
|
|
+
|
|
|
+ // 推荐网最大层级,用于循环
|
|
|
+ $maxLayer = BsBonus103Calc::getMaxLayer($periodNum);
|
|
|
+
|
|
|
+ // 报单业绩上推
|
|
|
+ $this->calcBsPushPerf($this->_periodNum, $maxLayer);
|
|
|
+ // 业绩汇总
|
|
|
+ $this->calcBsSummaryPerf($this->_periodNum);
|
|
|
+ // 第一次紧缩网络、连带达标
|
|
|
+ $this->calcBsNetworkAusterity($this->_periodNum, $maxLayer);
|
|
|
+ // 计算1星奖金、赋星级
|
|
|
+// $this->calcBsBonus($this->_periodNum);
|
|
|
+
|
|
|
+ // TODO: 任务进度
|
|
|
+ $this->calcTask(10, '完成', $this->_periodNum);
|
|
|
+
|
|
|
+ $t18 = microtime(true);
|
|
|
+ echo('计算蓝星管理奖'.($this->_sysConfig['openGL']['VALUE']?'完成':'关闭').',耗时:' . round($t18 - $t17, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
|
|
|
+ $this->_updatePercent(65);
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
//把奖金会员写入缓存
|
|
|
$this->loopMonthBonusUserFromDbToCache();
|
|
|
@@ -1701,6 +1741,241 @@ class BonusCalc extends BaseObject {
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 记录任务进度
|
|
|
+ * @param $taskId
|
|
|
+ * @param $taskName
|
|
|
+ * @param $period
|
|
|
+ * @return int
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcTask($taskId, $taskName, $period) {
|
|
|
+ // 写任务进度
|
|
|
+ return \Yii::$app->db->createCommand("CALL CalcRecord(:taskId, :taskName, :period, :time)")
|
|
|
+ ->bindValues([':taskId' => $taskId, ':taskName' => $taskName, ':period' => $period, ':time' => date('Y-m-d H:i:s')])
|
|
|
+ ->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除数据
|
|
|
+ * @param $periodNum
|
|
|
+ * @return int
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcClean($periodNum)
|
|
|
+ {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(1, '清除数据', $periodNum);
|
|
|
+ // 蓝星奖初始化
|
|
|
+ return \Yii::$app->db->createCommand("CALL CalcClean(:periodNum)")
|
|
|
+ ->bindValue(':periodNum' , $this->_periodNum )
|
|
|
+ ->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 蓝星奖初始化
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcBsInitProcedure($periodNum, $calcMonth, $calcYear) {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(2, '初始化', $periodNum);
|
|
|
+ // 蓝星奖初始化
|
|
|
+ return \Yii::$app->db->createCommand("CALL CalcInit(:periodNum, :calcMonth, :calcYear)")
|
|
|
+ ->bindValues([':periodNum' => $periodNum, ':calcMonth' => $calcMonth, ':calcYear' => $calcYear])
|
|
|
+ ->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 报单业绩上推
|
|
|
+ * @param $periodNum
|
|
|
+ * @param $maxLayer
|
|
|
+ * @return bool
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcBsPushPerf($periodNum, $maxLayer) {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(3, '报单业绩上推', $periodNum);
|
|
|
+ for ($i = $maxLayer; $i > 0; $i--) {
|
|
|
+ // 查询本层会员
|
|
|
+ $calcLayers = BsBonus103Calc::findAllAsArray('CALC_PERIOD_ID=:CALC_PERIOD_ID AND LAYER=:LAYER AND PV_ZC>0', [':CALC_PERIOD_ID' => $periodNum, ':LAYER' => $i]);
|
|
|
+ foreach ($calcLayers as $data) {
|
|
|
+ // 会员报单业绩上推
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['PV_UP_ZC' => new Expression('PV_UP_ZC+' . $data['PV_ZC'])],
|
|
|
+ 'USER_ID=:USER_ID AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => $data['INTRODUCER_ID'], ':CALC_PERIOD_ID' => $data['CALC_PERIOD_ID']]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 业绩汇总
|
|
|
+ * @param $periodNum
|
|
|
+ * @return int
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcBsSummaryPerf($periodNum) {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(4, '业绩汇总', $periodNum);
|
|
|
+ return BsBonus103Calc::updateAll(['GPV10' => new Expression('PV_UP_ZC+PV_FX')], 'CALC_PERIOD_ID=:CALC_PERIOD_ID', [':CALC_PERIOD_ID' => $periodNum]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 第一次紧缩网络、连带达标、赋星级
|
|
|
+ * @param $periodNum
|
|
|
+ * @param $maxLayer
|
|
|
+ * @return bool
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcBsNetworkAusterity($periodNum, $maxLayer): bool
|
|
|
+ {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(5, '第一次紧缩网络&连带达标&赋星', $periodNum);
|
|
|
+ // 一星达标业绩
|
|
|
+ $achievePv = Cache::getEmpLevelConfig()['E121497617216708615']['ACHIEVE_PV'];
|
|
|
+
|
|
|
+ for ($i = $maxLayer; $i >= 0; $i--) {
|
|
|
+ if ($i > 0) {
|
|
|
+ // 需要清空业绩的会员
|
|
|
+ $unQualified = [];
|
|
|
+ // 查询本层会员
|
|
|
+ $calcLayers = BsBonus103Calc::findAllAsArray('CALC_PERIOD_ID=:CALC_PERIOD_ID AND LAYER=:LAYER AND GPV10 > 0', [':CALC_PERIOD_ID' => $periodNum, ':LAYER' => $i]);
|
|
|
+
|
|
|
+ foreach ($calcLayers as $data) {
|
|
|
+ LoggerTool::debug(['qualified', $data['USER_ID'], $data['LAYER'], $data['GPV10']]);
|
|
|
+ $t1 = microtime(true);
|
|
|
+ // 业绩达标
|
|
|
+ if ($data['GPV10'] >= $achievePv) {
|
|
|
+ // 标记自身业绩达标、赋星级、汇总业绩
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['QUALIFIED' => self::QUALIFIED_SELF, 'USER_TYPE10' => 10],
|
|
|
+ 'USER_ID=:USER_ID AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => $data['USER_ID'], ':CALC_PERIOD_ID' => $data['CALC_PERIOD_ID']]);
|
|
|
+
|
|
|
+ // 所有上级
|
|
|
+ $introducerList = $this->getIntroducerList($data['USER_ID'], $data['CALC_PERIOD_ID']);
|
|
|
+ LoggerTool::debug([$data['USER_ID'], $introducerList]);
|
|
|
+ if ($introducerList) {
|
|
|
+ $introducerList = implode(',', $introducerList);
|
|
|
+ // 连带达标
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['QUALIFIED' => self::QUALIFIED_CASCADE],
|
|
|
+ 'USER_ID IN (:USER_ID) AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => $introducerList, ':CALC_PERIOD_ID' => $data['CALC_PERIOD_ID']]);
|
|
|
+ }
|
|
|
+ } else if ($data['QUALIFIED'] == self::QUALIFIED_NONE) {
|
|
|
+ // 未达标会员,且未被连带达标,业绩上推给上级
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['GPV10' => new Expression('GPV10+' . $data['GPV10'])],
|
|
|
+ 'USER_ID=:INTRODUCER_ID AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':INTRODUCER_ID' => $data['INTRODUCER_ID'], ':CALC_PERIOD_ID' => $data['CALC_PERIOD_ID']]);
|
|
|
+ // 清空自身业绩
|
|
|
+ $unQualified[] = $data['USER_ID'];
|
|
|
+ }
|
|
|
+
|
|
|
+ $t2 = microtime(true);
|
|
|
+ LoggerTool::notice(['calcBsNetworkAusterityForEach', $i, round($t2 - $t1, 3)]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($unQualified) {
|
|
|
+ // 清空自身业绩
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['GPV10' => 0],
|
|
|
+ 'USER_ID IN (:USER_ID) AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => implode(',', $unQualified), ':CALC_PERIOD_ID' => $periodNum]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 查询本层会员
|
|
|
+ $calcLayers = BsBonus103Calc::findAllAsArray('CALC_PERIOD_ID=:CALC_PERIOD_ID AND LAYER=:LAYER AND GPV10 > 0', [':CALC_PERIOD_ID' => $periodNum, ':LAYER' => $i]);
|
|
|
+
|
|
|
+ foreach ($calcLayers as $data) {
|
|
|
+ LoggerTool::debug(['qualified', $data['USER_ID'], $data['LAYER'], $data['GPV10']]);
|
|
|
+ $t1 = microtime(true);
|
|
|
+ // 自身业绩达标
|
|
|
+ if ($data['GPV10'] >= $achievePv) {
|
|
|
+ // 标记自身业绩达标
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['QUALIFIED' => self::QUALIFIED_SELF, 'USER_TYPE10' => 10, 'GPV10' => new Expression('GPV10+' . $data['GPV10'])],
|
|
|
+ 'USER_ID=:USER_ID AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => $data['USER_ID'], ':CALC_PERIOD_ID' => $data['CALC_PERIOD_ID']]);
|
|
|
+ } else if ($data['QUALIFIED'] == self::QUALIFIED_NONE) {
|
|
|
+ // 未达标会员,且未被连带达标,清空自身业绩
|
|
|
+ BsBonus103Calc::updateAll(
|
|
|
+ ['GPV10' => 0],
|
|
|
+ 'USER_ID IN (:USER_ID) AND CALC_PERIOD_ID=:CALC_PERIOD_ID',
|
|
|
+ [':USER_ID' => $data['USER_ID'], ':CALC_PERIOD_ID' => $periodNum]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $t2 = microtime(true);
|
|
|
+ LoggerTool::notice(['calcBsNetworkAusterityForEach', $i, round($t2 - $t1, 3)]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算奖金
|
|
|
+ * @param $periodNum
|
|
|
+ * @return bool
|
|
|
+ * @throws \yii\db\Exception
|
|
|
+ */
|
|
|
+ public function calcBsBonus($periodNum): bool
|
|
|
+ {
|
|
|
+ // 任务进度
|
|
|
+ $this->calcTask(4, '计算一星奖金', $periodNum);
|
|
|
+ // 一星奖金比例
|
|
|
+ $percent = Cache::getEmpLevelConfig()['E121497617216708615']['BS_PERCENT'] / 100;
|
|
|
+ // 推荐网最大层级,用于循环
|
|
|
+ $maxLayer = BsBonus103Calc::getMaxLayer($periodNum);
|
|
|
+
|
|
|
+ $rows = [];
|
|
|
+ for ($i = $maxLayer; $i >= 0; $i--) {
|
|
|
+ // 查询本层会员
|
|
|
+ $calcLayers = BsBonus103Calc::find()->where('CALC_PERIOD_ID=:CALC_PERIOD_ID AND LAYER=:LAYER AND QUALIFIED>:QUALIFIED', [':CALC_PERIOD_ID' => $periodNum, ':LAYER' => $i, ':QUALIFIED' => 0])->all();
|
|
|
+
|
|
|
+ foreach ($calcLayers as $data) {
|
|
|
+ $rows[] = [
|
|
|
+ $data['USER_ID'],
|
|
|
+ $data['INTRODUCER_ID'],
|
|
|
+ $data['USER_TYPE10'],
|
|
|
+ $data['GPV10'] * $percent,
|
|
|
+ $data['GPV10'],
|
|
|
+ $percent,
|
|
|
+ $data['CALC_PERIOD_ID'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($rows) {
|
|
|
+ // 奖金入库
|
|
|
+ $columns = ['USER_ID', 'INTRODUCER_ID', 'LAST_EMP_LV', 'LAST_EMP_LV', 'ORI_BONUS', 'PV', 'RATE', 'PERIOD_NUM'];
|
|
|
+ Yii::$app->db->createCommand()->batchInsert(CalcBonusBsDefaultBonus::tableName(), $columns, $rows)->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取上级
|
|
|
+ * @param $userId
|
|
|
+ * @param $period
|
|
|
+ * @param array $introducerList
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function getIntroducerList($userId, $period, array $introducerList = []): array
|
|
|
+ {
|
|
|
+ $introducer = BsBonus103Calc::getIntroducer($userId, $period);
|
|
|
+ // 如果会员的上级已经被标记达标,则不再向上查找
|
|
|
+ if ($introducer['QUALIFIED'] == self::QUALIFIED_NONE) {
|
|
|
+ $introducerList[] = $introducer['INTRODUCER_ID'];
|
|
|
+ $this->getIntroducerList($introducer['INTRODUCER_ID'], $period, $introducerList);
|
|
|
+ }
|
|
|
+ return $introducerList;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 蓝星管理奖金未拆分
|