root 3 лет назад
Родитель
Сommit
00e1b91188

+ 2 - 0
common/components/SwooleAsyncTimer.php

@@ -22,6 +22,7 @@ use common\libs\taskQueue\TaskFunc;
 use common\models\UserInfo;
 use Yii;
 use anlity\swooleAsyncTimer\SwooleAsyncTimerController;
+use common\helpers\bonus\PreparePerfCalc;
 use yii\base\Exception;
 use yii\helpers\Json;
 
@@ -50,6 +51,7 @@ class SwooleAsyncTimer extends SwooleAsyncTimerComponent implements SocketInterf
         // file_put_contents('aaa.txt', var_export([
         //     'time' =>  date('Y-m-d H:i:s')
         // ],true),FILE_APPEND);
+        PreparePerfCalc::instance()->calcStep(); // 预计算月业绩
         AutoClosePeriod::instance()->autoClose();
         // 自动执行任务队列中的任务
         Queue::instance()->consumeTask();

+ 31 - 0
common/helpers/bonus/PerfCalc.php

@@ -32,6 +32,8 @@ use common\models\Period;
 use common\models\DecOrder;
 use common\models\EmployLevel;
 use common\models\PerfActiveUser;
+use common\models\PerfOrderPrepare;
+use common\models\PerfPeriodPrepare;
 use common\models\UserRelation;
 use yii\base\Exception;
 use yii\base\StaticInstanceTrait;
@@ -297,6 +299,12 @@ class PerfCalc {
             //达标业绩表
             PerfStandard::pageDeleteAll("CALC_MONTH='{$this->_calcYearMonth}'");
         }
+
+        // 新增特殊逻辑,当是非月节点的时候,需要将同步到prepare前缀的订单业绩,期业绩表数据 同时删除
+        if (!$this->_isCalcMonth) {
+            PerfPeriodPrepare::pageDeleteAll('PERIOD_NUM='.$this->_periodNum);
+            PerfOrderPrepare::pageDeleteAll('PERIOD_NUM='.$this->_periodNum);
+        }
     }
 
     /**
@@ -502,6 +510,11 @@ class PerfCalc {
                 unset($data, $decInfo, $sn, $toInfo);
             }
             PerfOrder::batchInsert($insertPerfOrderData);
+            // 预算业绩需求,当不是月结点的时候,才插入数据.当是月节点的结算周期,预计算业绩,由定时任务提前插入到预计算表. 
+            if(!$this->_isCalcMonth){
+                // 不是月节点,则同步数据到预计算中.月节点的预计算数据,由定时任务写入.
+                PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            }
             unset($insertPerfOrderData, $allData, $snArr);
             return $this->loopCalcPeriodPerfByDecOrder($offset + $this->_limit);
         }
@@ -604,6 +617,11 @@ class PerfCalc {
                 unset($data, $decInfo, $sn, $toInfo);
             }
             PerfOrder::batchInsert($insertPerfOrderData);
+            // 预算业绩需求,当不是月结点的时候,才插入数据.当是月节点的结算周期,预计算业绩,由定时任务提前插入到预计算表. 
+            if(!$this->_isCalcMonth){
+              PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            }
+
             unset($insertPerfOrderData, $allData, $snArr);
             return $this->loopCalcPeriodPerfByOrderDec($offset + $this->_limit);
         }
@@ -727,6 +745,9 @@ class PerfCalc {
                 unset($data, $baseInfo, $sn, $orderCashAmount, $payPv, $cacheDataKey);
             }
             PerfOrder::batchInsert($insertPerfOrderData);
+            if(!$this->_isCalcMonth){
+                PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            }
 
             unset($insertPerfOrderData, $allData, $snArr);
             return $this->loopCalcPerfByFXOrder($offset + $this->_limit);
@@ -843,6 +864,10 @@ class PerfCalc {
                 unset($data, $baseInfo, $sn, $orderCashAmount, $payPv, $cacheDataKey);
             }
             PerfOrder::batchInsert($insertPerfOrderData);
+            // 预算业绩需求,当不是月结点的时候,才插入数据.当是月节点的结算周期,预计算业绩,由定时任务提前插入到预计算表. 
+            if(!$this->_isCalcMonth){
+                PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            }
 
             unset($insertPerfOrderData, $allData, $snArr);
             return $this->loopCalcPerfByShopFXOrder($offset + $this->_limit);
@@ -935,6 +960,7 @@ class PerfCalc {
         if (!$this->_isCalcMonth) {
             return true;
         }
+        // 预计计算月业绩的时候,预计计算月业绩数据,只需要定时任务进行处理AR_PERF_MONTH_PREPARE表中即可. 正常的月业绩计算正常执行.
         echo sprintf("时间:[%s]月业绩,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
         // 从缓存列表里面从底层往上倒序获取会员
 
@@ -1129,6 +1155,11 @@ class PerfCalc {
                 unset($userId);
             }
             PerfPeriod::batchInsert($insertDataPeriodPerf);
+            // 预算业绩需求,当不是月结点的时候,才插入数据.当是月节点的结算周期,预计算业绩,由定时任务提前插入到预计算表. 
+            // 预算期业绩表,结算月那期因为要提前算,所以只有是结算月那期的时候,不插入到预算期业绩表中,结算那月由定时任务提前计算并插入
+            if(!$this->_isCalcMonth) {
+                PerfPeriodPrepare::batchInsert($insertDataPeriodPerf);
+            }
 
             unset($insertDataPeriodPerf, $allData);
             return $this->loopWriteNowPerf($offset + $this->_limit);

+ 65 - 27
common/helpers/bonus/PreparePerfCalc.php

@@ -30,6 +30,7 @@ use common\models\PerfActiveUser;
 use common\models\PerfMonthPrepare;
 use common\models\PerfOrderPrepare;
 use common\models\PerfPeriodPrepare;
+use common\models\PeriodPrepare;
 use yii\base\Exception;
 use yii\base\StaticInstanceTrait;
 
@@ -102,11 +103,19 @@ class PreparePerfCalc {
      */
     public function calcStep($periodNum = null, $handleUserId = null) {
         try {
+            // 疑问,是否要将最后结算月的业绩同步过来
+            // 先计算是否是结算月,并且是否到了周日0点
+            $checkPrepare = $this->checkCanCalcPref();
+            if (!$checkPrepare) {
+                return true;
+            }
             $this->_errors = [];
             $this->_handleUserId = $handleUserId;
+            $this->_updatePercent(5);
             $t1 = microtime(true);
             // 初始化结算任务
             $this->initCalcTask();
+            $this->_updatePercent(10);
             // 设置结算状态
             $this->setCalcStatus('start');
             // 清空所有本期结算用到的缓存
@@ -115,6 +124,7 @@ class PreparePerfCalc {
             PrepareCalcCache::clearNetCache();
             // 清空相关表数据
             $this->clearTableData();
+            $this->_updatePercent(15);
             $t2 = microtime(true);
             echo('初始化、清空缓存及相关数据表完成,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
             // 计算月奖,才需要向缓存中加入按推荐深度的所有用户
@@ -157,20 +167,19 @@ class PreparePerfCalc {
 
             $t9 = microtime(true);
             echo('本月业绩入库完成,耗时:' . round($t9 - $t7, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
-            $this->_updatePercent(95);
 
-            
-            // 通过插入到perforder中的业绩订单数据,生成此业绩期活跃用户数据
-            // $this->loopWriteActiveUser();
             $this->_updatePercent(100);
             $t10 = microtime(true);
-
+            
             echo('业绩结算全部完成,共耗时:' . round($t10 - $t9, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
         } catch (\Exception $e) {
             $this->errorCalcTask();
             $this->addError('calc', $e->getMessage());
             return false;
         }
+
+        $this->endCalcTask();
+
         return true;
     }
 
@@ -181,20 +190,6 @@ class PreparePerfCalc {
     public function endCalcTask() {
         // 更新结算状态
         $this->setCalcStatus('end');
-        //如果自动结算
-        if(boolval($this->_sysConfig['autoCalcPeriod']['VALUE'])){
-            $period = Period::instance();
-            if($period->isLastSent($this->_periodNum)) {
-                $bonusCalc = BonusCalc::instance();
-                $asyncResult = $bonusCalc->calcStep($this->_periodNum);
-                if ($asyncResult) {
-                    $bonusCalc->endCalcTask();
-                } else {
-                    $bonusCalc->errorCalcTask();
-                }
-                return $asyncResult;
-            }
-        }
     }
 
     /**
@@ -214,14 +209,49 @@ class PreparePerfCalc {
      */
     public function setCalcStatus($type) {
         if ($type == 'start') {
-            Period::updateAll(['IS_PERFING' => 1, 'IS_PERFED' => Period::PERF_NONE, 'PERF_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+            PeriodPrepare::updateAll(['IS_PERFING' => 1, 'IS_PERFED' => Period::PERF_NONE, 'PERF_STARTED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
         } elseif ($type == 'end') {
-            Period::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FINISH, 'PERFED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+            PeriodPrepare::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FINISH, 'PERFED_AT' => Date::nowTime()], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
         } elseif ($type == 'fail') {
-            Period::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FAIL, 'PERFED_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+            PeriodPrepare::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FAIL, 'PERFED_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
         }
     }
 
+    public function checkCanCalcPref() {
+        // 先判断时间,现在是周几,如果不是周日,则直接结束
+        $w = date('w',time());
+        if ($w != '0') {
+            return false;
+        }
+        // 判断是否是周日0点
+        $h = date('H',time());
+        if ($h !=0 ) {
+            return false;
+        }
+        // 判断此结算周期是否是月结算节点 
+        $periodObj = Period::instance();
+        $periodDataArr = $periodObj->setPeriodNum(null);
+        if ($periodDataArr['IS_MONTH'] != 1) {
+            return false;
+        }
+        // 判断此结算周期是否已经进行业绩计算,如果已进行或者进行过,则不能继续执行
+        $prepare = PeriodPrepare::find()
+        ->select('IS_MONTH, IS_PERFING,IS_PERFED')
+        ->where(
+            'PERIOD_NUM=:PERIOD_NUM', 
+            [
+                'PERIOD_NUM'=>$periodDataArr['PERIOD_NUM']
+            ])
+        ->asArray()
+        ->one();
+        // 如果正在结算或者已计算完,则不进行计算,因为预计计算是定时任务每5秒扫一次,所以不能再触发预计算业绩
+        if ($prepare['IS_PERFING'] == 1 || $prepare['IS_PERFED'] == 1) {
+            return false;
+        }
+
+        return true;
+    }
+
     /**
      * 初始化结算任务
      * @throws \yii\db\Exception
@@ -757,11 +787,11 @@ class PreparePerfCalc {
         if (!$this->_isCalcMonth) {
             return true;
         }
-        // 因为预业绩计算,是从另外一个表记录的,所以需要再获取prepare表数据一起sum上
-        // 干脆正常的时候,也同步维护此per表中.当不是结算月的时候才维护进来,是结算月的话,就不维护进来了.
+        // 正常计算的时候,维护业绩到prepare表中,预计计算月业绩的时候,只需要插入定时任务的结算那期的业绩即可.
+        // 这里直接获取预计计算业绩单数据
         echo sprintf("时间:[%s]月业绩,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
         // 从缓存列表里面从底层往上倒序获取会员       
-        $allData = PerfPeriod::findUseDbCalc()
+        $allData = PerfPeriodPrepare::findUseDbCalc()
         ->select('USER_ID, SUM(FX_AMOUNT_CASH) AS FX_AMOUNT_CASH_SUM,SUM(PV_PCS) AS PV_PCS_SUM,
         SUM(PV_PCS_FX) AS PV_PCS_FX_SUM,SUM(PV_PSS) AS PV_PSS_SUM,
         SUM(PV_1L) AS PV_1L_SUM,SUM(PV_2L) AS PV_2L_SUM,
@@ -882,8 +912,8 @@ class PreparePerfCalc {
                 $insertDataMonthPerf[] = $this->nowMonthPerfData($userId);
                 unset($userId);
             }
-
-            PerfMonth::batchInsert($insertDataMonthPerf);
+            // 月预计计算业绩插入数据
+            PerfMonthPrepare::batchInsert($insertDataMonthPerf);
             unset($insertDataMonthPerf, $allData);
             return $this->loopWriteMonthPerf($offset + $this->_limit);
         }
@@ -1078,4 +1108,12 @@ class PreparePerfCalc {
         return true;
     }
 
+    /**
+     * 更新百分比并发送
+     * @param $percent
+     */
+    private function _updatePercent($percent) {
+        // 把数据写入数据库中
+        PeriodPrepare::updateAll(['PERF_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+    }
 }

+ 127 - 0
common/models/PeriodPrepare.php

@@ -0,0 +1,127 @@
+<?php
+
+namespace common\models;
+
+use common\helpers\Date;
+use common\helpers\Tool;
+use Yii;
+use yii\db\Exception;
+
+/**
+ * This is the model class for table "{{%PERIOD_PREPARE}}".
+ *
+ * @property string $ID
+ * @property int $PERIOD_NUM 期数
+ * @property int $CALC_MONTH 所在结算月
+ * @property int $CALC_YEAR 所在结算年
+ * @property int $START_TIME 期数开始时间戳
+ * @property int $END_TIME 期数结束时间戳
+ * @property int $IS_MONTH 是否结算月节点
+ * @property int $IS_YEAR 是否结算年节点
+ * @property int $IS_CLOSED 是否已封期
+ * @property int $IS_PERFED 是否已生成业绩单
+ * @property int $IS_CALCULATED 是否已结算
+ * @property int $IS_SENT 是否已发放
+ * @property int $IS_PERFING 是否正在生成业绩单
+ * @property int $IS_CALCING 是否正在计算状态
+ * @property int $IS_SENDING 是否正在挂网状态
+ * @property int $CALC_PERCENT 结算进度
+ * @property int $SENT_PERCENT 发放进度
+ * @property string $PERF_ADMIN_ID 生成业绩单管理员
+ * @property string $CLOSE_ADMIN_ID 手动封期管理员ID
+ * @property string $CALC_ADMIN_ID 结算管理员ID
+ * @property string $SENT_ADMIN_ID 发放管理员ID
+ * @property int $CLOSED_AT 发放管理员ID
+ * @property int $PERF_STARTED_AT 生成业绩单开始时间
+ * @property int $PERFED_AT 生成业绩单结束时间
+ * @property int $CALCULATE_STARTED_AT 结算开始时间
+ * @property int $CALCULATED_AT 结算完成时间
+ * @property int $SEND_STARTED_AT 发放开始时间
+ * @property int $SENT_AT 发放完成时间
+ * @property int $CREATED_AT 创建时间
+ */
+class PeriodPrepare extends \common\components\ActiveRecord
+{
+    const CALCULATE_NONE = 0;
+    const CALCULATE_FINISH = 1;
+    const CALCULATE_FAIL = 2;
+
+    const SEND_NONE = 0;
+    const SEND_FINISH = 1;
+    const SEND_FAIL = 2;
+
+    const PERF_NONE = 0;
+    const PERF_FINISH = 1;
+    const PERF_FAIL = 2;
+
+    const SYSTEM_START_PERIOD_NUM = 100;
+
+    public $nowPeriodArr = null;
+    public $periodNum = null;
+    public $periodArr = null;
+
+    public function init()
+    {
+        parent::init();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public static function tableName()
+    {
+        return '{{%PERIOD_PREPARE}}';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rules()
+    {
+        return [
+            [['PERIOD_NUM', 'CALC_MONTH', 'CALC_YEAR', 'START_TIME', 'END_TIME', 'CREATED_AT'], 'required'],
+            [['PERIOD_NUM', 'CALC_MONTH', 'CALC_YEAR', 'START_TIME', 'END_TIME', 'IS_MONTH', 'IS_YEAR', 'IS_CLOSED', 'IS_PERFED', 'IS_CALCULATED', 'IS_SENT', 'IS_PERFING', 'IS_CALCING', 'IS_SENDING', 'CALC_PERCENT', 'SENT_PERCENT', 'CLOSED_AT', 'PERF_STARTED_AT', 'PERFED_AT', 'CALCULATE_STARTED_AT', 'CALCULATED_AT', 'SEND_STARTED_AT', 'SENT_AT', 'CREATED_AT'], 'integer'],
+            [['ID', 'PERF_ADMIN_ID', 'CLOSE_ADMIN_ID', 'CALC_ADMIN_ID', 'SENT_ADMIN_ID'], 'string', 'max' => 32],
+            [['PERIOD_NUM'], 'unique'],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'PERIOD_NUM' => '期数',
+            'CALC_MONTH' => '所在结算月',
+            'CALC_YEAR' => '所在结算年',
+            'START_TIME' => '期数开始时间戳',
+            'END_TIME' => '期数结束时间戳',
+            'IS_MONTH' => '是否结算月节点',
+            'IS_YEAR' => '是否结算年节点',
+            'IS_CLOSED' => '是否已封期',
+            'IS_PERFED' => '是否已生成业绩单',
+            'IS_CALCULATED' => '是否已结算',
+            'IS_SENT' => '是否已发放',
+            'IS_PERFING' => '是否正在生成业绩单',
+            'IS_CALCING' => '是否正在计算状态',
+            'IS_SENDING' => '是否正在挂网状态',
+            'CALC_PERCENT' => '结算进度',
+            'SENT_PERCENT' => '发放进度',
+            'PERF_ADMIN_ID' => '生成业绩单管理员',
+            'CLOSE_ADMIN_ID' => '手动封期管理员ID',
+            'CALC_ADMIN_ID' => '结算管理员ID',
+            'SENT_ADMIN_ID' => '发放管理员ID',
+            'CLOSED_AT' => '发放管理员ID',
+            'PERF_STARTED_AT' => '生成业绩单开始时间',
+            'PERFED_AT' => '生成业绩单结束时间',
+            'CALCULATE_STARTED_AT' => '结算开始时间',
+            'CALCULATED_AT' => '结算完成时间',
+            'SEND_STARTED_AT' => '发放开始时间',
+            'SENT_AT' => '发放完成时间',
+            'CREATED_AT' => '创建时间',
+        ];
+    }
+}