Explorar o código

增加月预计业绩

root %!s(int64=3) %!d(string=hai) anos
pai
achega
3de603bf52

+ 1 - 0
backendApi/config/menu.php

@@ -184,6 +184,7 @@ return [
         'routePath'=>'bonus',
         'show'=>1,
         'child'=>[
+            ['name'=>'预算月业绩', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'prepare-period', 'routePath'=>'bonus/prepare-period', 'show'=>1,],
             ['name'=>'封期管理', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'period', 'routePath'=>'bonus/period', 'show'=>1,],
             ['name'=>'封期操作', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'close-period', 'routePath'=>'bonus/close-period', 'show'=>0,],
             ['name'=>'生成业绩单', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'perf-period', 'routePath'=>'bonus/perf-period', 'show'=>0,],

+ 2 - 0
backendApi/config/urlManagerRules.php

@@ -298,8 +298,10 @@ return [
         'controller' => 'v1/bonus',
         'extraPatterns' => [
             'GET period' => 'period',
+            'GET prepare-period' => 'prepare-period',
             'GET close-period/<periodNum>' => 'close-period',
             'GET perf-period/<periodNum>' => 'perf-period',
+            'GET prepare-perf-period/<periodNum>' => 'prepare-perf-period',
             'GET calc-period/<periodNum>' => 'calc-period',
             'GET send-period/<periodNum>' => 'send-period',
             'GET perf' => 'perf',

+ 62 - 0
backendApi/modules/v1/controllers/BonusController.php

@@ -61,7 +61,9 @@ use common\models\Config;
 use common\models\FlowBonus;
 use common\models\FlowExchangePoints;
 use common\models\forms\PeriodForm;
+use common\models\forms\PreparePeriodForm;
 use common\models\Period;
+use common\models\PeriodPrepare;
 use Exception;
 
 class BonusController extends BaseController {
@@ -73,6 +75,66 @@ class BonusController extends BaseController {
         return $behaviors;
     }
 
+    /**
+     * 查看预计计算月业绩数据状态
+     * @return mixed
+     * @throws \yii\db\Exception
+     * @throws \yii\web\HttpException
+     */
+    public function actionPreparePeriod() {
+        $filter = $this->filterCondition([
+            'periodNum' => 'PERIOD_NUM',
+            'year' => 'CALC_YEAR',
+            'month' => 'CALC_MONTH',
+            'startTime' => 'START_TIME',
+            'endTime' => 'END_TIME',
+            'closedAt' => 'CLOSED_AT',
+            'perfStartedAt' => 'PERF_STARTED_AT',
+            'perfedAt' => 'PERFED_AT',
+            'calStartedAt' => 'CALCULATE_STARTED_AT',
+            'calculatedAt' => 'CALCULATED_AT',
+            'sendStartedAt' => 'SEND_STARTED_AT',
+            'sentAt' => 'SENT_AT',
+        ]);
+        $oriPeriodObj = Period::instance();
+        $nowPeriodNum = $oriPeriodObj->getNowPeriodNum();
+        $condition = $filter['condition'];
+        $params = $filter['params'];
+        $condition .= ' AND PERIOD_NUM=:PERIOD_NUM';
+        $params[':PERIOD_NUM'] = $nowPeriodNum;
+        $data = PeriodPrepare::lists($condition, $params, ['orderBy' => 'PERIOD_NUM DESC']);
+        foreach ($data['list'] as $key => $value) {
+           
+            // 是否可生成业绩单
+            $data['list'][$key]['IS_CAN_PERF'] = true;
+                        
+            // 操作数据按钮是否可用
+            $data['list'][$key]['BUTTON_IS_CAN'] = true;
+            
+        }
+        return static::notice($data);
+    }
+
+    /**
+     * 对预计算业绩进行生成
+     * @return mixed
+     * @throws \yii\web\HttpException
+     */
+    public function actionPreparePerfPeriod() {
+        $periodNum = \Yii::$app->request->get('periodNum');
+        if (!$periodNum) {
+            return static::notice('期数不存在', 400);
+        }
+        
+        $formModel = new PreparePeriodForm();
+        $formModel->scenario = 'perf';
+        if ($formModel->load(Yii::$app->request->get(), '') && $formModel->perfWebToAsync()) {
+            return static::notice('预计算正在生成月业绩单,请等待');
+        } else {
+            return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
+        }
+    }
+
     /**
      * 期数列表
      * @return mixed

+ 12 - 0
backendEle/src/router/index.js

@@ -667,6 +667,18 @@ export const constantRouterMap = [
     component: layout,
     redirect: '/bonus/period',
     children: [
+      {
+        path: '/bonus/prepare-period',
+        component: _import('bonus/prepare-period'),
+        name: 'bonus_prepare-period',
+        meta: {
+          title: '预算月业绩',
+          breadcrumb: [
+            {title: '首页', path: '/dashboard/index'},
+            {title: '奖金管理', path: '/bonus/period'},
+          ],
+        },
+      },
       {
         path: '/bonus/period',
         component: _import('bonus/period'),

+ 212 - 0
backendEle/src/views/bonus/prepare-period.vue

@@ -0,0 +1,212 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-table :data="tableData" stripe style="width: 100%;" @selection-change="handleSelectionChange"
+                :height="tool.getTableHeight()">
+        <el-table-column prop="PERIOD_NUM" label="期数">
+          <template slot-scope="scope">
+            <el-tag type="" size="small" class="no-border">{{scope.row.PERIOD_NUM}}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="所在结算月" width="100">
+          <template slot-scope="scope">
+            <el-tag type="warning" size="small" class="no-border">{{scope.row.CALC_YEAR}}-{{scope.row.CALC_MONTH}}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="时间范围" width="260">
+          <template slot-scope="scope">
+            应开始于:{{tool.formatDate(scope.row.START_TIME)}}<br/>
+            应结束于:{{tool.formatDate(scope.row.END_TIME)}}
+          </template>
+        </el-table-column>
+        <el-table-column label="业绩单进度" width="90">
+          <template slot-scope="scope">
+            <el-progress type="circle" :percentage="Number.parseInt(percentList['PERF_PERCENT'][scope.row.ID])"
+                         :width="50" :stroke-width="3"></el-progress>
+          </template>
+        </el-table-column>
+        <el-table-column label="生成业绩单时间" width="210">
+          <template slot-scope="scope">
+            开始:{{tool.formatDate(scope.row.PERF_STARTED_AT)}}<br>
+            完成:{{tool.formatDate(scope.row.PERFED_AT)}}
+          </template>
+        </el-table-column>
+        <el-table-column fixed="right" label="操作" width="180">
+          <template slot-scope="scope">
+            <el-dropdown size="small" trigger="click" v-if="scope.row.BUTTON_IS_CAN">
+              <el-button type="primary" size="small" @click.stop="">
+                操作该数据<i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="perfHandle(scope.row)"
+                                  v-if="scope.row.IS_PERFING === '0' && scope.row.IS_CAN_PERF && permission.hasPermission(`bonus/prepare-perf-period`)">
+                  生成预计算月业绩单
+                </el-dropdown-item>
+                <el-dropdown-item @click.native="perfHandle(scope.row)"
+                                  v-if="scope.row.IS_PERFING === '1' && scope.row.IS_CAN_PERF && permission.hasPermission(`bonus/prepare-perf-period`)">
+                  强制生成预计算月业绩单
+                </el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="white-box-footer">
+        <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import Vue from 'vue'
+  import {BONUS_WEBSOCKET_HOST} from '@/utils/config'
+  import userInfo from '@/utils/userInfo'
+  import network from './../../utils/network'
+  import tool from './../../utils/tool'
+  import store from '@/utils/vuexStore'
+  import FilterUser from '@/components/FilterUser'
+  import permission from '@/utils/permission'
+  import Pagination from '@/components/Pagination'
+  import filterHelper from '../../utils/filterHelper'
+
+  export default {
+    name: 'bonus_prepare-period',
+    components: {FilterUser,Pagination},
+    created() {
+      let wsServer = BONUS_WEBSOCKET_HOST
+      let webSocket = new WebSocket(wsServer)
+      webSocket.onopen = function (evt) {
+        let userId = userInfo.userId()
+        let sendData = {app: 'admin', userId: userId}
+        webSocket.send(JSON.stringify(sendData))
+      }
+      webSocket.onmessage = (env) => {
+        let data = JSON.parse(env.data)
+        if (data.handle === 'adminAsyncPercent') {
+          this.onMessageCallback(data)
+        }
+      }
+    },
+    mounted() {
+      this.getData(this.currentPage, this.pageSize)
+      store.state.socket.onMessageCallback = this.onMessageCallback
+    },
+    data() {
+      return {
+        tableData: null,
+        loading: true,
+        multipleSelection: [],
+        currentPage: 1,
+        totalPages: 1,
+        totalCount: 1,
+        pageSize: 10,
+        tool: tool,
+        permission: permission,
+        filterTypes: {
+          'periodNum': {isUserTable: false, name: '期数'},
+          'year': {isUserTable: false, name: '所在结算年'},
+          'month': {isUserTable: false, name: '所在结算月'},
+          'startTime': {isUserTable: false, name: '期数开始时间', other: 'date'},
+          'endTime': {isUserTable: false, name: '期数结束时间', other: 'date'},
+          'closedAt': {isUserTable: false, name: '封期时间', other: 'date'},
+          'perfStartedAt': {isUserTable: false, name: '生成业绩单开始时间', other: 'date'},
+          'perfedAt': {isUserTable: false, name: '生成业绩单结束时间', other: 'date'},
+          'calStartedAt': {isUserTable: false, name: '结算开始时间', other: 'date'},
+          'calculatedAt': {isUserTable: false, name: '结算结束时间', other: 'date'},
+          'sendStartedAt': {isUserTable: false, name: '挂网开始时间', other: 'date'},
+          'sentAt': {isUserTable: false, name: '挂网结束时间', other: 'date'},
+        },
+        filterModel: {},
+        percentList: {
+          'PERF_PERCENT': {},
+          'CALC_PERCENT': {},
+          'SENT_PERCENT': {},
+        },
+      }
+    },
+    methods: {
+      closeHandle(row) {
+        this.$confirm('确定对当前期进行手动封期操作?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          return network.getData(`bonus/close-period/${row.PERIOD_NUM}`)
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+          this.getData(this.currentPage, this.pageSize)
+        }).catch(response => {
+        })
+      },
+      calcHandle(row) {
+        this.$confirm('确定对当前期进行结算操作?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          return network.getData(`bonus/calc-period/${row.PERIOD_NUM}`)
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+          this.getData(this.currentPage, this.pageSize)
+        }).catch(response => {
+        })
+      },
+      perfHandle(row) {
+        this.$confirm('确定进行预计算业绩吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          return network.getData(`bonus/prepare-perf-period/${row.PERIOD_NUM}`)
+        }).then(response => {
+          this.$message({
+            message: response,
+            type: 'success'
+          })
+          this.getData(this.currentPage, this.pageSize)
+        }).catch(response => {
+        })
+      },
+      handleSelectionChange(val) {
+        this.multipleSelection = val
+      },
+      handleCurrentChange(page) {
+        this.getData(page, this.pageSize)
+      },
+      handleSizeChange(pageSize) {
+        this.getData(this.currentPage, pageSize)
+      },
+      handleFilterUser(filterData) {
+        filterHelper.handleFilterUser(this, filterData)
+      },
+      handleFilter() {
+        this.getData()
+      },
+      getData(page, pageSize) {
+        let filterData = this.filterModel
+        let vueObj = this
+        network.getPageData(this, 'bonus/prepare-period', page, pageSize, filterData, function (response) {
+          vueObj.allData = response
+        }, null, ['PERF_PERCENT', 'CALC_PERCENT', 'SENT_PERCENT'])
+      },
+      onMessageCallback(data) {
+        if (data) {
+          if (data.other && data.other.MODEL === 'PERIOD' && data.other.ID) {
+            this.$set(this.percentList[data.other.FIELD], data.other.ID, data.percent)
+          }
+          if (data.other && data.other.MODEL === 'PERIOD' && data.percent === 100) {
+            this.getData(this.currentPage, this.pageSize)
+          }
+        }
+      },
+    }
+  }
+</script>

+ 37 - 29
common/helpers/bonus/PreparePerfCalc.php

@@ -103,12 +103,11 @@ class PreparePerfCalc {
      */
     public function calcStep($periodNum = null, $handleUserId = null) {
         try {
-            // 疑问,是否要将最后结算月的业绩同步过来
             // 先计算是否是结算月,并且是否到了周日0点
             // 需要将线上的数据perf_order,perf_period两个表的数据同步过来
             // Period表数据同步过来,只要是结算月的数据
-            $checkPrepare = $this->checkCanCalcPref();
-            if (!$checkPrepare) {
+            $checkPrepare = $this->checkCanCalcPref($periodNum);
+            if ($checkPrepare !== true) {
                 return true;
             }
             $this->_errors = [];
@@ -116,7 +115,7 @@ class PreparePerfCalc {
             $this->_updatePercent(5);
             $t1 = microtime(true);
             // 初始化结算任务
-            $this->initCalcTask();
+            $this->initCalcTask($periodNum);
             $this->_updatePercent(10);
             // 设置结算状态
             $this->setCalcStatus('start');
@@ -221,36 +220,45 @@ class PreparePerfCalc {
         }
     }
 
-    public function checkCanCalcPref() {
+    public function checkCanCalcPref($periodNum = null) {
+        
         // 先判断时间,现在是周几,如果不是周日,则直接结束
-        $w = date('w',time());
-        if ($w != '0') {
-            return false;
-        }
-        // 判断是否是周日0点
-        $h = date('H',time());
-        if ($h !=0 ) {
-            return false;
+        // 如果是手动触发,即有业绩期$periodNum变量值,则不校验必须周日0点
+        $w = $h = '';
+        if (empty($periodNum)) {
+            $w = date('w',time());
+            if ($w != '0') {
+                return false;
+            }
+            // 判断是否是周日0点
+            $h = date('H',time());
+            if ($h !=0 ) {
+                return false;
+            }
         }
         // 判断此结算周期是否是月结算节点 
+        // 这里 如果定时任务业绩期是nul
         $periodObj = Period::instance();
-        $periodDataArr = $periodObj->setPeriodNum(null);
+        $periodDataArr = $periodObj->setPeriodNum($periodNum);
         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;
+        if (empty($periodNum)) {
+            $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;
@@ -260,10 +268,10 @@ class PreparePerfCalc {
      * 初始化结算任务
      * @throws \yii\db\Exception
      */
-    public function initCalcTask() {
+    public function initCalcTask($periodNum = null) {
         $periodObj = Period::instance();
-        $periodDataArr = $periodObj->setPeriodNum(null);
-        $this->_lastTime = $periodDataArr['END_TIME']-86399; // 周日的23:35:59秒, 结算为周日的0:0:0秒
+        $periodDataArr = $periodObj->setPeriodNum($periodNum);
+        $this->_lastTime = $periodDataArr['END_TIME']; 
         $this->_periodNum = $periodDataArr['PERIOD_NUM'];
         $this->_sysConfig = Cache::getSystemConfig();
         $this->_decLevelConfig = Cache::getDecLevelConfig();

+ 121 - 0
common/models/forms/PreparePeriodForm.php

@@ -0,0 +1,121 @@
+<?php
+namespace common\models\forms;
+
+use common\helpers\bonus\BonusCalc;
+use common\helpers\bonus\BonusSend;
+use common\helpers\bonus\PerfCalc;
+use common\helpers\Cache;
+use common\helpers\Date;
+use common\components\Model;
+use common\helpers\bonus\PreparePerfCalc;
+use common\helpers\Form;
+use common\models\Period;
+use common\models\PeriodPrepare;
+use common\models\UserWallet;
+use common\models\User;
+use common\models\UserStatusAudit;
+use common\models\Withdraw;
+use yii\base\Exception;
+
+/**
+ * Login form
+ */
+class PreparePeriodForm extends Model
+{
+    public $periodNum;
+
+    private $_periodModel;
+    private $_limit = 1000;
+
+    /**
+     * @inheritdoc
+     */
+    public function rules()
+    {
+        return [
+            [['periodNum'], 'trim'],
+            [['periodNum'], 'required'],
+            [['periodNum'], 'integer'],
+            [['periodNum'], 'isPeriod'],
+        ];
+    }
+
+    public function scenarios()
+    {
+        $parentScenarios =  parent::scenarios();
+        $customScenarios = [
+            'close' => ['periodNum'],
+            'perf' => ['periodNum'],
+            'calc' => ['periodNum'],
+            'send' => ['periodNum'],
+            'autoClose' => ['periodNum'],
+        ];
+        return array_merge($parentScenarios, $customScenarios);
+    }
+
+    public function attributeLabels()
+    {
+        return [
+            'periodNum' => '期数',
+        ];
+    }
+
+    public function isPeriod($attributes){
+        $periodModel = PeriodPrepare::findOne(['PERIOD_NUM' => $this->periodNum]);
+        if(!$periodModel){
+            $this->addError($attributes, '所传期数不存在');
+        }
+
+        $this->_periodModel = $periodModel;
+    }
+
+    /**
+     * 页面请求异步处理生成业绩单
+     * @return string | null
+     */
+    public function perfWebToAsync(){
+        if(!$this->validate()){
+            return null;
+        }
+        $model = $this->_periodModel;
+        $model->IS_PERFING = 1;
+        $model->PERF_ADMIN_ID = \Yii::$app->user->id;
+        if(!$model->save()){
+            $this->addError('perf', Form::formatErrorsForApi($model->getErrors()));
+            return null;
+        }
+        // 异步处理添加任务
+        $settings = \Yii::$app->params['swooleAsyncTimer'];
+        $bonusSettings = \Yii::$app->params['swooleBonusConfig'];
+        $settings = array_merge($settings, $bonusSettings);
+        $taskKey = \Yii::$app->swooleAsyncTimer->asyncHandle('bonus/prepare-perf', \Yii::$app->request->get(), $settings);
+        if($taskKey === false){
+            $this->addError('perf', '请求失败');
+            return null;
+        }
+        return $model;
+    }
+
+    /**
+     * 异步处理逻辑
+     * @param $handleUserId
+     * @return bool|null
+     * @throws Exception
+     * @throws \yii\db\Exception
+     */
+    public function perfAsync($handleUserId,$periodNum){
+        if(!$this->validate()){
+            return null;
+        }
+        $bonusCalc = PreparePerfCalc::instance();
+        $periodNum = $periodNum ? $periodNum : $this->periodNum;
+        $asyncResult = $bonusCalc->calcStep($periodNum, $handleUserId);
+        if($asyncResult){
+            $bonusCalc->endCalcTask();
+        } else {
+            $bonusCalc->errorCalcTask();
+            $this->addErrors($bonusCalc->getErrors());
+        }
+        return $asyncResult;
+    }
+}

+ 23 - 0
console/controllers/BonusController.php

@@ -53,6 +53,7 @@ use common\helpers\http\RemoteUploadApi;
 use common\helpers\Log;
 use common\libs\export\module\BonusExport;
 use common\models\forms\PeriodForm;
+use common\models\forms\PreparePeriodForm;
 use common\models\LogAsync;
 use common\models\Withdraw;
 use yii\db\Exception;
@@ -60,6 +61,28 @@ use yii\db\Exception;
 class BonusController extends BaseController
 {
 
+    /**
+     * 预计计算生成月业绩,如果是月节点的话
+     * @param $taskKey
+     * @throws Exception
+     * @throws \yii\base\Exception
+     */
+    public function actionPreparePerf($taskKey){
+        $params = Cache::getAsyncParams($taskKey);
+        $formModel = new PreparePeriodForm();
+        $handleResult = false;
+        $periodNum = isset($params['periodNum']) && !empty($params['periodNum']) ? $params['periodNum'] : null;
+        if($formModel->load($params, '') && $formModel->perfAsync($params['handleUserId'],$periodNum)){
+            $handleResult = true;
+            \Yii::$app->swooleAsyncTimer->pushAsyncResultToAdmin($params['handleUserId'], "预计算月业绩第{$params['periodNum']}期生成业绩单更新成功");
+        } else {
+            \Yii::$app->swooleAsyncTimer->pushAsyncResultToAdmin($params['handleUserId'], "预计算月业绩第{$params['periodNum']}期生成业绩单更新失败,原因:".Form::formatErrorsForApi($formModel->getErrors()), false);
+        }
+        if(!$handleResult){
+            echo "预计算月业绩,第{$params['periodNum']}期生成业绩单更新失败,原因:".Form::formatErrorsForApi($formModel->getErrors());
+        }
+    }
+
     /**
      * 生成业绩单并计算业绩
      * @param $taskKey

+ 3 - 4
frontendApi/modules/v1/controllers/BonusController.php

@@ -110,12 +110,11 @@ class BonusController extends BaseController {
         // 判断是否是月节点
         $isCalcMonth = $period->isCalcMonth($periodNum);
         $w = date('w', time());
-        // if ($w != '0' || $isCalcMonth != 1) {
-        //     return static::notice(['user' => [],'team'=>[]]);
-        // }
+        if ($w != '0' || $isCalcMonth != 1) {
+            return static::notice(['user' => [],'team'=>[]]);
+        }
         
         // 达标规则,小组底下有一个大于等于一万.或者个人情况里的合计大于等于一万
-        $month = '202203';
         $data = PerfMonthPrepare::getMonthPerfPrepare($userId, $month);
         // PV_PCS 个人业绩  PV_PSS 月新增团队业绩  PV_PSS_TOTAL月累计团队业绩
         // 其中页面使用的是月新增团队业绩