Ver Fonte

Untracked files: backendEle/src/views/bonus/prepare-period.vue

root há 3 anos atrás
pai
commit
0fc69c9302

+ 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>

+ 1509 - 0
common/helpers/bonus/PrepareCalcCache.php

@@ -0,0 +1,1509 @@
+<?php
+/**
+ * 月结算的时候,周日晚0点进行预计算,此月用户和团队的业绩信息. 让会员参考,进行补业绩使用的缓存key
+ * Created by PhpStorm.
+ * User: leo
+ * Date: 2018/8/2
+ * Time: 上午10:38
+ */
+
+namespace common\helpers\bonus;
+
+use common\helpers\Cache;
+use common\helpers\user\Info;
+use common\models\CalcBonus;
+use common\models\PerfMonth;
+use common\models\Period;
+use common\models\DeclarationLevel;
+use common\models\DecRole;
+use common\models\EmployLevel;
+use common\models\User;
+use common\models\UserBonus;
+use common\models\UserPerf;
+use Yii;
+use common\models\UserInfo;
+use yii\helpers\Json;
+
+class PrepareCalcCache {
+    const LIMIT = 1000;
+
+    const REDIS_KEY_PREFIX_USER = 'prepare:calc:user_';
+    const REDIS_KEY_PREFIX_USER_ACTIVE = 'prepare:calc:userActive_';
+    const REDIS_KEY_PREFIX_USER_INFO = 'prepare:calc:userInfo_';
+    const REDIS_KEY_PREFIX_USER_BONUS = 'prepare:calc:userBonus_';
+    const REDIS_KEY_PREFIX_PERIOD_MONTH_CALC_BONUS = 'prepare:calc:periodMonthCalcBonus_';
+    const REDIS_KEY_PREFIX_USER_PERF = 'prepare:calc:userPerf_';
+    const REDIS_KEY_PREFIX_SURPLUS_PERF = 'prepare:calc:spPerf_';
+    const REDIS_KEY_PREFIX_NOW_PERIOD_PERF = 'prepare:calc:nowPeriodPerf_';
+    const REDIS_KEY_PREFIX_NOW_STANDARD_MONTH_PERF = 'prepare:calc:nowStandardMonthPerf_';
+    const REDIS_KEY_PREFIX_LAST_MONTH_PERF = 'prepare:calc:lastMonthPerf_';
+    const REDIS_KEY_PREFIX_NOW_MONTH_PERF = 'prepare:calc:nowMonthPerf_';
+    const REDIS_KEY_PREFIX_NOW_MONTH_SCORE = 'prepare:calc:nowMonthScore_';
+    const REDIS_KEY_PREFIX_NOW_MONTH_LAST_PERIOD_RECONSUME_POINTS = 'prepare:calc:nowMonthLastPeriodReconsumePoints_';
+    const REDIS_KEY_PREFIX_EMP_NUM_PERF = 'prepare:calc:empLevelNum_';
+    const REDIS_KEY_PREFIX_BONUS = 'prepare:calc:bonus_';
+    const REDIS_KEY_PREFIX_STANDARD_BONUS = 'prepare:calc:standard:bonus_';
+    const REDIS_KEY_PREFIX_YC_BONUS = 'prepare:calc:yc:bonus_';
+    const REDIS_KEY_PREFIX_FW_BONUS = 'prepare:calc:fw:bonus_';
+    const REDIS_KEY_PREFIX_HAS_PERF_USER = 'prepare:calc:hasPerfUser_';
+    const REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER = 'prepare:calc:hasMonthPerfUser_';
+    const REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER = 'prepare:calc:hasStandardMonthPerfUser_';
+    const REDIS_KEY_PREFIX_HAS_BD_USER = 'prepare:calc:hasBDUser_';
+    const REDIS_KEY_PREFIX_HAS_INCOME_USER = 'prepare:calc:hasIncomeUser_';
+    const REDIS_KEY_PREFIX_HAS_BONUS_USER = 'prepare:calc:hasBonusUser_';
+    const REDIS_KEY_PREFIX_HAS_YC_BONUS_USER = 'prepare:calc:hasYcBonusUser_';
+    const REDIS_KEY_PREFIX_HAS_FW_BONUS_USER = 'prepare:calc:hasFwBonusUser_';
+    const REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER = 'prepare:calc:hasMonthBonusUser_';
+    const REDIS_KEY_PREFIX_HAS_PERF_USER_POOL = 'prepare:calc:hasPerfUserPool_';
+    const REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER_POOL = 'prepare:calc:hasMonthPerfUserPool_';
+    const REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER_POOL = 'prepare:calc:hasStandardMonthPerfUserPool_';
+    const REDIS_KEY_PREFIX_HAS_BD_USER_POOL = 'prepare:calc:hasBDUserPool_';
+    const REDIS_KEY_PREFIX_HAS_INCOME_USER_POOL = 'prepare:calc:hasIncomeUserPool_';
+    const REDIS_KEY_PREFIX_HAS_BONUS_USER_POOL = 'prepare:calc:hasBonusUserPool_';
+    const REDIS_KEY_PREFIX_HAS_YC_BONUS_USER_POOL = 'prepare:calc:hasYcBonusUserPool_';
+    const REDIS_KEY_PREFIX_HAS_FW_BONUS_USER_POOL = 'prepare:calc:hasFwBonusUserPool_';
+    const REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER_POOL = 'prepare:calc:hasMonthBonusUserPool_';
+    const REDIS_KEY_PREFIX_HAS_SCORE_USER = 'prepare:calc:hasScoreUser_';
+    const REDIS_KEY_PREFIX_HAS_SCORE_USER_POOL = 'prepare:calc:hasScoreUserPool_';
+    const REDIS_KEY_PREFIX_HAS_LS_PCS_USER = 'prepare:calc:hasLSPCSUser_';
+    const REDIS_KEY_PREFIX_HAS_LS_PCS_USER_POOL = 'prepare:calc:hasLSPCSUserPool_';
+    const REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER = 'prepare:calc:hasCFPercentPCSUser_';
+    const REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER_POOL = 'prepare:calc:hasCFPercentPCSUserPool_';
+    const REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER = 'prepare:calc:hasLXPercentPCSUser_';
+    const REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER_POOL = 'prepare:calc:hasLXPercentPCSUserPool_';
+    const REDIS_KEY_PREFIX_DEC_ROLE_CONFIG = 'prepare:calc:decRoleConfig_';
+    const REDIS_KEY_PREFIX_CF_TOTAL_PERCENT = 'prepare:calc:cfTotalPercent_';
+    const REDIS_KEY_PREFIX_LX_TOTAL_PERCENT = 'prepare:calc:lxTotalPercent_';
+    const REDIS_KEY_PREFIX_USER_INFO_CHILD_ONE_DEEP = 'prepare:calc:userInfo:ChildOneDeep_';
+    const REDIS_KEY_PREFIX_GX_BONUS_DEEP_ONE_LIST_DATA = 'prepare:calc:gxBonusDeepOneListData_';
+    const REDIS_KEY_PREFIX_GX_BONUS_DEEP_TWO_LIST_DATA = 'prepare:calc:gxBonusDeepTwoListData_';
+    const REDIS_KEY_PREFIX_YC_BONUS_LIST_DATA = 'prepare:calc:ycBonusListData_';
+    const REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA = 'prepare:calc:fwBonusListData_';
+
+    //@todo
+    const REDIS_KEY_PREFIX_REPAIR_SURPLUS_PERF = 'prepare:calc:repairSurplusPerf_';
+    const REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER = 'prepare:calc:hasRepairPerfUser_';
+    const REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER_POOL = 'prepare:calc:hasRepairPerfPool_';
+
+    //收入的奖金类型
+//    const INCOME_TG_BONUS = 'BONUS_TG';
+//    const INCOME_XF_BONUS = 'BONUS_XF';
+//    const INCOME_YJ_BONUS = 'BONUS_YJ';
+//    const INCOME_QY_BONUS = 'BONUS_QY';
+    const INCOME_QY_BONUS_BD = 'BONUS_QY_BD';
+    const INCOME_QY_BONUS_FX = 'BONUS_QY_FX';
+    const INCOME_BONUS_LIST = [
+//        self::INCOME_TG_BONUS,
+//        self::INCOME_XF_BONUS,
+//        self::INCOME_YJ_BONUS,
+//        self::INCOME_QY_BONUS,
+        self::INCOME_QY_BONUS_BD,
+//        self::INCOME_QY_BONUS_FX,
+    ];
+    const NOT_SEND_BONUS_LIST = [
+        self::INCOME_QY_BONUS_BD,
+        self::INCOME_QY_BONUS_FX,
+    ];
+
+    const FROM_MEANS_BD = 'BD';
+    const FROM_MEANS_FX = 'FX';
+
+    /**
+     * 结算奖金时要清空的缓存
+     * @param $periodNum
+     */
+    public static function clearCalcBonusCache($periodNum) {
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_STANDARD_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_YC_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_YC_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_YC_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_ONE_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_TWO_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_YC_BONUS_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_FW_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA . $periodNum);
+    }
+
+    /**
+     * 清网络缓存
+     * 用户的网络是一套,应该用一个缓存,获取最新推荐关系
+     */
+    public static function clearNetCache(){
+        \Yii::$app->redis->del(Cache::PREPARE_USER_NETWORK_PARENTS);
+        \Yii::$app->redis->del(Cache::PREPARE_USER_RELATION_PARENTS);
+    }
+
+    /**
+     * 清空所有临时计算用到的缓存
+     * @param $periodNum
+     */
+    public static function clearAll($periodNum) {
+        //Yii::$app->redis->del(Yii::$app->redis->keys('calc*'));
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER_ACTIVE . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER_INFO . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_PERIOD_MONTH_CALC_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_SURPLUS_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_NOW_PERIOD_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_NOW_STANDARD_MONTH_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_LAST_MONTH_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_NOW_MONTH_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_NOW_MONTH_SCORE . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_NOW_MONTH_LAST_PERIOD_RECONSUME_POINTS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_EMP_NUM_PERF . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_STANDARD_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_YC_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_FW_BONUS . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_PERF_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_PERF_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BD_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BD_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_INCOME_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_INCOME_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_YC_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_YC_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_SCORE_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_SCORE_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER_POOL . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_DEC_ROLE_CONFIG . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_USER_INFO_CHILD_ONE_DEEP . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_ONE_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_TWO_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_YC_BONUS_LIST_DATA . $periodNum);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA . $periodNum);
+    }
+
+    /**
+     * 会员信息加入缓存
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return bool
+     */
+    public static function addUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+//        echo sprintf("时间:[%s]缓存用户,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
+        // 修复USER_INFO表里面已经没有PERIOD_NUM了
+        $allData = UserInfo::findUseDbCalc()->from(UserInfo::tableName(). 'AS UI')->select('UI.USER_ID,U.STATUS')->leftJoin(User::tableName() . 'AS U', 'U.ID=UI.USER_ID')->where('1=1')->orderBy('UI.RELATION_DEEP DESC,UI.ID DESC')->offset($offset)->limit($limit)->asArray()->all();
+        //$allData = User::findUseDbShopCalc()->select('ID AS USER_ID')->where('PERIOD_AT<=:PERIOD_AT AND IS_UNION=0 AND DELETED=0', [':PERIOD_AT' => $periodNum])->offset($offset)->limit($limit)->asArray()->all();
+        if ($allData) {
+            foreach ($allData as $data) {
+//                if(User::find()->where('ID=:ID',[':ID'=>$data['USER_ID']])->exists()) continue;
+                // 会员ID加入缓存
+                $cacheKey = self::REDIS_KEY_PREFIX_USER . $periodNum;
+                $value = $data['USER_ID'];
+                Yii::$app->redis->rpush($cacheKey, $value);
+                if( $data['STATUS'] == 1 ) {
+                    $activeCacheKey = self::REDIS_KEY_PREFIX_USER_ACTIVE . $periodNum;
+                    Yii::$app->redis->rpush($activeCacheKey, $value);
+                    unset($activeCacheKey);
+                }
+                unset($data, $cacheKey, $value);
+            }
+            unset($allData);
+            return self::addUsers($periodNum, $offset + $limit, $limit);
+        }
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 获取会员从缓存中
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 获取激活会员从缓存中
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getActiveUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_USER_ACTIVE . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有业绩的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasPerfUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_PERF_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_PERF_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_PERF_USER . $periodNum, $userId);
+        }
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有业绩的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasPerfUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_PERF_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有月业绩的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasMonthPerfUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER . $periodNum, $userId);
+        }
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有业绩的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasMonthPerfUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_MONTH_PERF_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有达标业绩的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasStandardMonthPerfUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER . $periodNum, $userId);
+        }
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有达标业绩的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasStandardMonthPerfUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_STANDARD_MONTH_PERF_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+
+    /**
+     * 加入被报单的会员
+     * @param $userId
+     * @param $periodNum
+     * @param $saveData
+     */
+    public static function addHasBDUsers($userId, $periodNum, $saveData) {
+        // 先从已存在的会员池里面获取
+        $data = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_BD_USER_POOL . $periodNum, $userId);
+        if (!$data) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_BD_USER_POOL . $periodNum, $userId, Json::encode($saveData));
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_BD_USER . $periodNum, $userId);
+        }
+        unset($userId, $periodNum, $saveData, $isset);
+    }
+
+    /**
+     * 获取被报单的会员信息
+     * @param $userId
+     * @param $periodNum
+     * @return array
+     */
+    public static function getBDUsersInfo($userId, $periodNum) {
+        $data = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_BD_USER_POOL . $periodNum, $userId);
+        if( !$data ) return [];
+
+        return Json::decode($data, true);
+    }
+
+    /**
+     * 获取被报单的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasBDUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_BD_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有收入的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasIncomeUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_INCOME_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_INCOME_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_INCOME_USER . $periodNum, $userId);
+        }
+
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有收入的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasIncomeUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_INCOME_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有奖金的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasBonusUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_BONUS_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_BONUS_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_BONUS_USER . $periodNum, $userId);
+        }
+
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有奖金的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasBonusUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_BONUS_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 获取有服务奖的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasFwBonusUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+
+    /**
+     * 加入服务奖的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasFwBonusUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_FW_BONUS_USER . $periodNum, $userId);
+        }
+
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 获取有月奖的会员
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasMonthBonusUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+
+    /**
+     * 加入月奖的会员
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasMonthBonusUsers($userId, $periodNum) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER_POOL . $periodNum, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_MONTH_BONUS_USER . $periodNum, $userId);
+        }
+
+        unset($userId, $periodNum, $isset);
+    }
+
+    /**
+     * 保存荣衔奖奖金
+     * @param $userId
+     * @param $periodNum
+     * @param $fwBonus
+     * @param array $fromData
+     */
+    public static function saveFwBonusList($userId, $periodNum, $fwBonus, $fromData=[]) {
+        $userFwBonusData = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA . $periodNum, $userId);
+
+        if( $userFwBonusData ) {
+            $fwBonusData = Json::decode($userFwBonusData, true);
+            $fwBonusData['fwBonus'] += $fwBonus;
+//            $ycBonusData['fromData'][] = $fromData;
+        }else {
+            $fwBonusData = [
+                'fwBonus' => $fwBonus,
+//                'fromData' => [
+//                    $fromData
+//                ]
+            ];
+        }
+        unset($userFwBonusData);
+
+        Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA . $periodNum, $userId, Json::encode($fwBonusData));
+        unset($fwBonusData, $userId, $periodNum, $empBonus, $fromData);
+    }
+
+    /**
+     * 返回服务奖信息
+     * @param $userId
+     * @param $periodNum
+     * @return array
+     */
+    public static function getFwBonusList($userId, $periodNum) {
+        $userYcBonusData = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_FW_BONUS_LIST_DATA . $periodNum, $userId);
+
+        return $userYcBonusData ? Json::decode($userYcBonusData, true) : [];
+    }
+
+    /**
+     * 加入有复销业绩的会员列表
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasScoreUsers($userId, $periodNum) {
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_SCORE_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_SCORE_USER_POOL . $periodNum, $userId, 1);
+            $key = self::REDIS_KEY_PREFIX_HAS_SCORE_USER . $periodNum;
+            Yii::$app->redis->rpush($key, $userId);
+        }
+    }
+
+    /**
+     * 获取有复销业绩的会员列表
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasScoreUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_SCORE_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 加入有零售个人消费的会员列表
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasLSPCSUsers($userId, $periodNum) {
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER_POOL . $periodNum, $userId, 1);
+            $key = self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER . $periodNum;
+            $value = $userId;
+            Yii::$app->redis->rpush($key, $value);
+        }
+    }
+
+    /**
+     * 加入有零售消费的会员列表
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasLSPCSUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_LS_PCS_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 有车房补贴比例的人
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasCFPercentUsers($userId, $periodNum) {
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER_POOL . $periodNum, $userId, 1);
+            $key = self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER . $periodNum;
+            $value = $userId;
+            Yii::$app->redis->rpush($key, $value);
+        }
+    }
+
+    /**
+     * 获取有车房补贴的人
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasCFPercentUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_CF_PERCENT_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 有领袖分红的人
+     * @param $userId
+     * @param $periodNum
+     */
+    public static function addHasLXPercentUsers($userId, $periodNum) {
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER_POOL . $periodNum, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER_POOL . $periodNum, $userId, 1);
+            $key = self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER . $periodNum;
+            $value = $userId;
+            Yii::$app->redis->rpush($key, $value);
+        }
+    }
+
+    /**
+     * 获取有领袖分红的人
+     * @param $periodNum
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasLXPercentUsers($periodNum, $offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_LX_PERCENT_USER . $periodNum, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 通过创建时间获取指定长度的用户列表
+     * @param $userId
+     * @param $limit
+     * @return array|\yii\db\ActiveRecord[]
+     */
+    public static function getUserListByCreatedAtFromDb($userId, $limit)
+    {
+        //查找这个人的CREATED_AT
+        $user = User::findUseDbCalc()->select('ID,CREATED_AT')->where('ID=:ID', ['ID'=>$userId])->asArray()->one();
+        if( !$user ) return [];
+
+        return User::findUseDbCalc()->select('ID,CREATED_AT')->where('ID<:ID AND CREATED_AT<=:CREATED_AT', [
+            'ID'=>$userId,
+            'CREATED_AT' => $user['CREATED_AT']
+        ])->orderBy('CREATED_AT DESC,ID DESC')->limit($limit)->asArray()->all();
+    }
+
+    /**
+     * 通过创建时间获取指定长度的用户列表
+     * @param $userId
+     * @param $limit
+     * @return array|\yii\db\ActiveRecord[]
+     */
+    public static function getAfterUserListByCreatedAtFromDb($userId, $limit)
+    {
+        $cacheKey = Cache::PRE_USER_CREATED_AT_LIST . $limit;
+        $value = Yii::$app->redis->hGet($cacheKey, $userId);
+        if( $value ) {
+            unset($cacheKey);
+            return json_decode($value, true);
+        }
+        unset($value);
+
+        $list = UserInfo::findUseDbCalc()->select('USER_ID')->where('USER_ID>:USER_ID', [
+            'USER_ID'=>$userId,
+        ])->orderBy('USER_ID ASC')->limit($limit)->asArray()->all();
+        if ( $limit == count($list) ) {
+            Yii::$app->redis->hSet($cacheKey, $userId, json_encode($list));
+        }
+
+        unset($cacheKey);
+        return $list;
+    }
+
+    /**
+     * 获取会员信息从缓存
+     * @param $userId
+     * @param $periodNum
+     * @return array
+     * @throws \Exception
+     */
+    public static function getUserInfo($userId, $periodNum) {
+        $key = self::REDIS_KEY_PREFIX_USER_INFO . $periodNum;
+        $data = Yii::$app->redis->hget($key, $userId);
+        if (!$data) {
+            $userInfo = UserInfo::findUseDbCalc()->select('USER_ID,USER_NAME,ZC_AMOUNT,ZC_PV,CON_UID,REC_UID,CON_NUM,REC_NUM,NETWORK_DEEP,RELATION_DEEP,STORE_TYPE,UPDATED_AT,SYSTEM_ID')->where('USER_ID=:USER_ID', [':USER_ID' => $userId])->asArray()->one();
+            if( !$userInfo ) {
+                throw new \Exception('用户信息表数据不存在,userId:'.$userId);
+            }
+            // 在获取商城库的会员的级别信息和是否报单中心的会员
+            $userShopInfo = User::find()->select('REAL_NAME,LAST_DEC_LV,DEC_LV,EMP_LV,IS_DEC,DEC_ID,DEC_ROLE_ID,STATUS,PERIOD_AT,MOBILE,CREATED_AT,SUB_COM_ID,PROVINCE,CITY,COUNTY,DEC_PROVINCE,DEC_CITY,DEC_COUNTY,IS_DIRECT_SELLER,SUB_COM_LEADER')->where('ID=:ID', [':ID' => $userId])->asArray()->one();
+            if ( !$userShopInfo ) {
+                throw new \Exception('用户表数据不存在,userId:'.$userId);
+            }
+            $userInfo['REAL_NAME'] = $userShopInfo['REAL_NAME'];
+//            $userInfo['DEC_LV'] = $userShopInfo['DEC_LV'];
+            //先用last_dec_lv
+            $userInfo['DEC_LV'] = $userShopInfo['LAST_DEC_LV'];
+            $userInfo['EMP_LV'] = $userShopInfo['EMP_LV'];
+            $userInfo['IS_DEC'] = $userShopInfo['IS_DEC'];
+            $userInfo['DEC_ID'] = $userShopInfo['DEC_ID'];
+            $userInfo['DEC_ROLE_ID'] = $userShopInfo['DEC_ROLE_ID'];
+            $userInfo['DEC_PROVINCE'] = $userShopInfo['DEC_PROVINCE'];
+            $userInfo['DEC_CITY'] = $userShopInfo['DEC_CITY'];
+            $userInfo['DEC_COUNTY'] = $userShopInfo['DEC_COUNTY'];
+            $userInfo['STATUS'] = $userShopInfo['STATUS'];
+            $userInfo['PERIOD_NUM'] = $userShopInfo['PERIOD_AT'];
+            $userInfo['MOBILE'] = $userShopInfo['MOBILE'];
+            $userInfo['CREATED_AT'] = $userShopInfo['CREATED_AT'];
+            $userInfo['SUB_COM_ID'] = $userShopInfo['SUB_COM_ID'];
+            $userInfo['PROVINCE'] = $userShopInfo['PROVINCE'];
+            $userInfo['CITY'] = $userShopInfo['CITY'];
+            $userInfo['COUNTY'] = $userShopInfo['COUNTY'];
+            $userInfo['IS_DIRECT_SELLER'] = $userShopInfo['IS_DIRECT_SELLER'];
+            $userInfo['SUB_COM_LEADER'] = $userShopInfo['SUB_COM_LEADER'];
+            $userInfo['REC_USER_NAME'] = isset($userInfo['REC_UID']) && $userInfo['REC_UID'] ? Info::getUserNameByUserId($userInfo['REC_UID']) : '';
+            $userInfo['REC_REAL_NAME'] = isset($userInfo['REC_UID']) && $userInfo['REC_UID'] ? Info::getUserRealNameByUserId($userInfo['REC_UID']) : '';
+            $userInfo['CON_USER_NAME'] = isset($userInfo['CON_UID']) && $userInfo['CON_UID'] ? Info::getUserNameByUserId($userInfo['CON_UID']) : '';
+            $userInfo['CON_REAL_NAME'] = isset($userInfo['CON_UID']) && $userInfo['CON_UID'] ? Info::getUserRealNameByUserId($userInfo['CON_UID']) : '';
+            unset($userShopInfo);
+
+            if (!$userInfo['DEC_LV']) {
+                $userInfo['DEC_LV'] = DeclarationLevel::getDefaultLevelId();
+            }
+            if (!$userInfo['EMP_LV']) {
+                $userInfo['EMP_LV'] = EmployLevel::getDefaultLevelId();
+            }
+            $data = Json::encode($userInfo);
+            Yii::$app->redis->hset($key, $userId, $data);
+            unset($userInfo, $key, $userId, $periodNum);
+        }
+        return $data ? Json::decode($data, true) : [];
+    }
+
+    public static function setUserInfo($userId, $periodNum, $userInfo) {
+        $key = self::REDIS_KEY_PREFIX_USER_INFO . $periodNum;
+        $data = Json::encode($userInfo);
+        Yii::$app->redis->hset($key, $userId, $data);
+        unset($userId, $key, $data, $userInfo, $periodNum);
+        return true;
+    }
+
+    /**
+     * 用户奖金信息
+     * @param $userId
+     * @param $periodNum
+     * @return array|mixed|null|\yii\db\ActiveRecord
+     */
+    public static function LastUserBonus($userId, $periodNum) {
+
+        $cacheKey = self::REDIS_KEY_PREFIX_USER_BONUS . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue, true);
+        } else {
+            $value = UserBonus::findUseDbCalc()->select('USER_ID,BONUS_TOTAL')->where('USER_ID=:USER_ID', [
+                'USER_ID'=>$userId
+            ])->asArray()->one();
+
+            \Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 用户奖金信息
+     * @param $userId
+     * @param $periodNum
+     * @param $yearMonth
+     * @return array|mixed|null|\yii\db\ActiveRecord
+     */
+    public static function lastPeriodMonthCalcBonus($userId, $periodNum, $yearMonth) {
+
+        $cacheKey = self::REDIS_KEY_PREFIX_PERIOD_MONTH_CALC_BONUS . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue, true);
+        } else {
+            $value = CalcBonus::findUseDbCalc()->select('SUM(ORI_BONUS_QY) AS ORI_BONUS_QY_SUM,SUM(ORI_BONUS_VIP) AS ORI_BONUS_VIP_SUM')->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [
+                'USER_ID'=>$userId,
+                'CALC_MONTH'=>$yearMonth
+            ])->asArray()->one();
+
+            \Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+
+    /**
+     * 本月往期的复消积分的数据
+     * @param $userId
+     * @param $periodNum
+     * @param $calcYearMonth
+     * @return array|mixed|null|\yii\db\ActiveRecord
+     * @throws \yii\db\Exception
+     */
+    public static function monthLastPeriodReconsumePoints($userId, $periodNum, $calcYearMonth) {
+        $cacheKey = self::REDIS_KEY_PREFIX_NOW_MONTH_LAST_PERIOD_RECONSUME_POINTS . $periodNum;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $userId);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue, true);
+        } else {
+            $value = CalcBonus::findUseDbCalc()->select(["SUM(RECONSUME_POINTS) as RECONSUME_POINTS_SUM"])->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $userId, ':CALC_MONTH'=>$calcYearMonth])->asArray()->one();
+            \Yii::$app->redis->hset($cacheKey, $userId, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 获取结算时这一期的报单中心级别的配置
+     * @param $periodNum
+     * @return array|\yii\db\ActiveRecord[]
+     */
+    public static function getDecRoleConfig($periodNum) {
+        $key = self::REDIS_KEY_PREFIX_DEC_ROLE_CONFIG . $periodNum;
+        Yii::$app->redis->del($key);
+        $data = Yii::$app->redis->get($key);
+        if (!$data) {
+            $data = DecRole::find()->where('1=1')->indexBy('ID')->asArray()->all();
+            $data = Json::encode($data);
+            Yii::$app->redis->set($key, $data);
+        }
+        return $data ? Json::decode($data) : [];
+    }
+
+    /**
+     * 上一期结余业绩
+     * @param $userId
+     * @param $periodNum
+     * @return array|mixed|\yii\db\ActiveRecord|null
+     * @throws \yii\db\Exception
+     */
+    public static function surplusPerf($userId, $periodNum) {
+        $userPerf = self::userPerf($userId, $periodNum);
+        return [
+            'SURPLUS_1L' => $userPerf['SURPLUS_1L'],
+            'SURPLUS_2L' => $userPerf['SURPLUS_2L'],
+            'SURPLUS_3L' => $userPerf['SURPLUS_3L'],
+            'SURPLUS_4L' => $userPerf['SURPLUS_4L'],
+            'SURPLUS_5L' => $userPerf['SURPLUS_5L'],
+            'SURPLUS_1L_ZC' => $userPerf['SURPLUS_1L_ZC'],
+            'SURPLUS_2L_ZC' => $userPerf['SURPLUS_2L_ZC'],
+            'SURPLUS_3L_ZC' => $userPerf['SURPLUS_3L_ZC'],
+            'SURPLUS_4L_ZC' => $userPerf['SURPLUS_4L_ZC'],
+            'SURPLUS_5L_ZC' => $userPerf['SURPLUS_5L_ZC'],
+            'SURPLUS_1L_FX' => $userPerf['SURPLUS_1L_FX'],
+            'SURPLUS_2L_FX' => $userPerf['SURPLUS_2L_FX'],
+            'SURPLUS_3L_FX' => $userPerf['SURPLUS_3L_FX'],
+            'SURPLUS_4L_FX' => $userPerf['SURPLUS_4L_FX'],
+            'SURPLUS_5L_FX' => $userPerf['SURPLUS_5L_FX'],
+            'VIP_SURPLUS_1L_ZC' => $userPerf['VIP_SURPLUS_1L_ZC'],
+            'VIP_SURPLUS_2L_ZC' => $userPerf['VIP_SURPLUS_2L_ZC'],
+            'VIP_SURPLUS_3L_ZC' => $userPerf['VIP_SURPLUS_3L_ZC'],
+            'VIP_SURPLUS_4L_ZC' => $userPerf['VIP_SURPLUS_4L_ZC'],
+            'VIP_SURPLUS_5L_ZC' => $userPerf['VIP_SURPLUS_5L_ZC'],
+            'SURPLUS_LS' => 0,
+        ];
+    }
+
+    /**
+     * 获取repairSurplusPerf
+     * @param $userId
+     * @return int[]|mixed|null
+     */
+    public static function getRepairSurplusPerf($userId) {
+        $cacheKey = self::REDIS_KEY_PREFIX_REPAIR_SURPLUS_PERF;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $userId);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        }else {
+            $value = [
+                'SURPLUS_1L' => 0,
+                'SURPLUS_2L' => 0,
+                'SURPLUS_3L' => 0,
+                'SURPLUS_4L' => 0,
+                'SURPLUS_5L' => 0,
+            ];
+        }
+
+        return $value;
+    }
+
+    /**
+     * 累加repairSurplusPerf
+     * @param $userId
+     * @param $surplusPerf
+     * @return int[]|mixed|null
+     */
+    public static function setRepairSurplusPerf($userId, $surplusPerf) {
+        $surplusPerfList = self::getRepairSurplusPerf($userId);
+        foreach ($surplusPerfList as $key => $perf) {
+            $thisPerf = $surplusPerf[$key] ?? 0;
+            $surplusPerfList[$key] = $perf + $thisPerf;
+
+            unset($key, $perf, $thisPerf);
+        }
+
+        $cacheKey = self::REDIS_KEY_PREFIX_REPAIR_SURPLUS_PERF;
+        \Yii::$app->redis->hset($cacheKey, $userId, Json::encode($surplusPerfList));
+        self::addHasRepairPerfUsers($userId);
+
+        unset($userId, $cacheKey, $surplusPerf);
+
+        return $surplusPerfList;
+    }
+
+    /**
+     * 加入有往期结余业绩的会员
+     * @param $userId
+     */
+    public static function addHasRepairPerfUsers($userId) {
+        // 先从已存在的会员池里面获取
+        $isset = Yii::$app->redis->hget(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER_POOL, $userId);
+        if (!$isset) {
+            Yii::$app->redis->hset(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER_POOL, $userId, 1);
+            Yii::$app->redis->rpush(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER, $userId);
+        }
+        unset($userId, $isset);
+    }
+
+    /**
+     * 获取有往期结余业绩的会员
+     * @param int $offset
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getHasRepairPerfUsers($offset = 0, $limit = self::LIMIT) {
+        return Yii::$app->redis->lrange(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER, $offset, ($offset + $limit - 1));
+    }
+
+    /**
+     * 修正业绩缓存清空
+     */
+    public static function clearRepairAllCache() {
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_REPAIR_SURPLUS_PERF);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER);
+        Yii::$app->redis->del(self::REDIS_KEY_PREFIX_HAS_REPAIR_PERF_USER_POOL);
+    }
+
+    /**
+     * 上一期结余业绩
+     * @param $userId
+     * @param $periodNum
+     * @return array|mixed|\yii\db\ActiveRecord|null
+     * @throws \yii\db\Exception
+     */
+    public static function userPerf($userId, $periodNum) {
+        $cacheKey = self::REDIS_KEY_PREFIX_USER_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $value = UserPerf::getOneUserPerf($userId);
+            \Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 当前期数的的业绩
+     * @param $userId
+     * @param $periodNum
+     * @param null $perf
+     * @return array|mixed
+     */
+    public static function nowPeriodPerf($userId, $periodNum, $perf = null) {
+        $cacheKey = self::REDIS_KEY_PREFIX_NOW_PERIOD_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $value = [
+                'FX_AMOUNT_CASH' => 0,
+                'PV_PCS' => 0,
+                'PV_PSS' => 0,//本期的团队业绩
+                'PV_PCS_ZC' => 0,//注册
+                'PV_PCS_YH' => 0,
+                'PV_PCS_ZG' => 0,//增购
+                'PV_PCS_LS' => 0,
+                'PV_PCS_FX' => 0,
+                'PV_PCS_FX_CASH' => 0,//现金复消
+                'PV_PCS_FX_POINT' => 0,//积分复消
+                'PV_1L' => 0,
+                'PV_1L_TOUCH' => 0,
+                'PV_1L_ZC' => 0,
+                'PV_1L_YH' => 0,
+                'PV_1L_ZG' => 0,
+                'PV_1L_LS' => 0,
+                'PV_1L_FX' => 0,
+                'PV_2L' => 0,
+                'PV_2L_TOUCH' => 0,
+                'PV_2L_ZC' => 0,
+                'PV_2L_YH' => 0,
+                'PV_2L_ZG' => 0,
+                'PV_2L_LS' => 0,
+                'PV_2L_FX' => 0,
+                'PV_3L' => 0,
+                'PV_3L_TOUCH' => 0,
+                'PV_3L_ZC' => 0,
+                'PV_3L_YH' => 0,
+                'PV_3L_ZG' => 0,
+                'PV_3L_LS' => 0,
+                'PV_3L_FX' => 0,
+                'PV_4L' => 0,
+                'PV_4L_TOUCH' => 0,
+                'PV_4L_ZC' => 0,
+                'PV_4L_YH' => 0,
+                'PV_4L_ZG' => 0,
+                'PV_4L_LS' => 0,
+                'PV_4L_FX' => 0,
+                'PV_5L' => 0,
+                'PV_5L_TOUCH' => 0,
+                'PV_5L_ZC' => 0,
+                'PV_5L_YH' => 0,
+                'PV_5L_ZG' => 0,
+                'PV_5L_LS' => 0,
+                'PV_5L_FX' => 0,
+                'PV_LS_TOUCH' => 0,
+                'SURPLUS_1L' => 0,
+                'SURPLUS_2L' => 0,
+                'SURPLUS_3L' => 0,
+                'SURPLUS_4L' => 0,
+                'SURPLUS_5L' => 0,
+                'SURPLUS_1L_ZC' => 0,
+                'SURPLUS_2L_ZC' => 0,
+                'SURPLUS_3L_ZC' => 0,
+                'SURPLUS_4L_ZC' => 0,
+                'SURPLUS_5L_ZC' => 0,
+                'SURPLUS_1L_FX' => 0,
+                'SURPLUS_2L_FX' => 0,
+                'SURPLUS_3L_FX' => 0,
+                'SURPLUS_4L_FX' => 0,
+                'SURPLUS_5L_FX' => 0,
+                'SURPLUS_LS' => 0,
+            ];
+        }
+        if ($perf !== null) {
+            foreach ($perf as $key => $pv) {
+                if (strpos($key, 'SURPLUS') !== false) {
+                    $value[$key] = $pv;
+                } else {
+                    $value[$key] = $pv + $value[$key];
+                }
+            }
+            Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 上个月的业绩
+     * @param $userId
+     * @param $periodNum
+     * @return array|mixed|null|\yii\db\ActiveRecord
+     */
+    public static function lastMonthPerf($userId, $periodNum) {
+        $period = Period::instance();
+        $last = $period->getLastMonth($periodNum);
+        $lastYearMonth = $last['yearMonth'];
+        $cacheKey = self::REDIS_KEY_PREFIX_LAST_MONTH_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $value = PerfMonth::getMonthPerf($lastYearMonth, $userId);
+            \Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 当前月的业绩
+     * @param $userId
+     * @param $periodNum
+     * @param $perf
+     * @return array|mixed
+     */
+    public static function nowMonthPerf($userId, $periodNum, $perf = null) {
+        $cacheKey = self::REDIS_KEY_PREFIX_NOW_MONTH_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $baseInfo = self::getUserInfo($userId, $periodNum);
+            $value = [
+                'USER_ID' => $userId,
+                'FX_AMOUNT_CASH' => 0,
+                'PV_PCS' => 0,
+                'PV_PCS_FX' => 0,
+                'PV_PSS' => 0,
+                'PV_1L' => 0,
+                'PV_2L' => 0,
+                'PV_3L' => 0,
+                'PV_4L' => 0,
+                'PV_5L' => 0,
+                'VIP_PV_1L_ZC' => 0,
+                'VIP_PV_2L_ZC' => 0,
+                'VIP_PV_3L_ZC' => 0,
+                'VIP_PV_4L_ZC' => 0,
+                'VIP_PV_5L_ZC' => 0,
+                'PV_1L_TOTAL' => 0,
+                'PV_2L_TOTAL' => 0,
+                'PV_3L_TOTAL' => 0,
+                'PV_4L_TOTAL' => 0,
+                'PV_5L_TOTAL' => 0,
+                'PV_PSS_TOTAL' => 0,
+                'DEC_LEVEL' => $baseInfo['DEC_LV'],
+                'EMP_LEVEL' => EmployLevel::getDefaultLevelId(),
+                'CF_PERCENT' => 0,
+                'LX_PERCENT' => 0,
+                'FX_STATUS' => PerfMonth::NEXT_MONTH_FX_FALSE,
+            ];
+        }
+        if ($perf !== null) {
+            foreach ($perf as $key => $item) {
+                $value[$key] = $item;
+            }
+        }
+        Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        return $value;
+    }
+
+    /**
+     * 当前期数的的业绩
+     * @param $userId
+     * @param $periodNum
+     * @param null $perf
+     * @return array|mixed
+     */
+    public static function nowStandardMonthPerf($userId, $periodNum, $perf = null) {
+        $cacheKey = self::REDIS_KEY_PREFIX_NOW_STANDARD_MONTH_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $field);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $value = [
+                'AMOUNT_PCS' => 0,
+                'AMOUNT_PSS' => 0
+            ];
+        }
+        if ($perf !== null) {
+            foreach ($perf as $key => $pv) {
+                $value[$key] = $pv + $value[$key];
+            }
+            Yii::$app->redis->hset($cacheKey, $field, Json::encode($value));
+        }
+        return $value;
+    }
+
+    /**
+     * 当前月的积分
+     * @param $userId
+     * @param $periodNum
+     * @param $perf
+     * @return array|mixed
+     */
+    public static function nowMonthScore($userId, $periodNum, $perf = null) {
+        $cacheKey = self::REDIS_KEY_PREFIX_NOW_MONTH_SCORE . $periodNum;
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $userId);
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $value = [
+                'USER_ID' => $userId,
+                'BASE_SCORE' => 0,
+                'LEVEL_SCORE' => 0,
+                'UPGRADE_SCORE' => 0,
+//                'TOTAL_SCORE' => 0,
+            ];
+        }
+        unset($cacheValue);
+        if ($perf !== null) {
+            foreach ($perf as $key => $item) {
+                $value[$key] = $item;
+//                $value['TOTAL_SCORE'] += $item;
+                unset($key, $item);
+            }
+            Yii::$app->redis->hset($cacheKey, $userId, Json::encode($value));
+        }
+
+        unset($userId, $periodNum, $perf, $cacheKey);
+        return $value;
+    }
+
+    /**
+     * 获取直推的所有子会员
+     * @param $userId
+     * @param $periodNum
+     * @return array
+     */
+    public static function getChildrenOneDeepFromRedis($userId, $periodNum){
+        $key = self::REDIS_KEY_PREFIX_USER_INFO_CHILD_ONE_DEEP . $periodNum;
+        $data = Yii::$app->redis->hget($key, $userId);
+        if(!$data){
+            $list = UserInfo::findUseDbCalc()->select('USER_ID')->where('REC_UID=:REC_UID', [
+                'REC_UID' => $userId
+            ])->asArray()->all();
+            $data = Json::encode($list);
+            unset($list);
+            Yii::$app->redis->hset($key, $userId, $data);
+        }
+        unset($key, $userId, $periodNum);
+        return $data ? Json::decode($data, true) : [];
+    }
+
+    /**
+     * 每个区有多少个什么级别的数量
+     * @param $userId
+     * @param $periodNum
+     * @param null $levelNumArr
+     * @return array|mixed
+     */
+    public static function hasEmpLevelNum($userId,  $periodNum, $levelNumArr = null) {
+        $key = self::REDIS_KEY_PREFIX_EMP_NUM_PERF . $periodNum;
+        $field = $userId;
+        $cacheValue = Yii::$app->redis->hget($key, $field);
+
+        if ($cacheValue) {
+            $value = Json::decode($cacheValue);
+        } else {
+            $allEmpLevel = EmployLevel::getFromCache();
+            $value = [];
+            $relationList = self::getChildrenOneDeepFromRedis($userId, $periodNum);
+            foreach ($relationList as $relationData) {
+                foreach ($allEmpLevel as $level) {
+                    // 从月度业绩表中找到所有下级的各个部门的数量
+                    $value[$relationData['USER_ID']][$level['ID']] = 0;
+                }
+            }
+        }
+        if ($levelNumArr != null) {
+            foreach ($levelNumArr as $departUserId => $item) {
+                foreach ($item as $levelID => $num) {
+                    if( isset($value[$departUserId][$levelID]) ) {
+                        $value[$departUserId][$levelID] += $num;
+                    }else {
+                        $value[$departUserId][$levelID] = $num;
+                    }
+                }
+            }
+        }
+        Yii::$app->redis->hset($key, $field, Json::encode($value));
+
+        if ($levelNumArr == null) return $value;
+    }
+
+    /**
+     * 会员是否本月注册
+     * @param $userId
+     * @param $periodNum
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public static function isMonthJoinFromRedis($userId, $periodNum) {
+        $period = Period::instance();
+        $calcYearMonth = $period->getYearMonth($periodNum);
+        $userInfo = self::getUserInfo($userId, $periodNum);
+        $addYearMonth = $period->getYearMonth($userInfo['PERIOD_NUM']);
+        //当月注册
+        if ($addYearMonth == $calcYearMonth) return true;
+        //上月注册
+        $calcLastYearMonth = $period->getLastMonth($periodNum);
+        if ($addYearMonth == $calcLastYearMonth['yearMonth']) return true;
+        // 未来注册
+        if ($addYearMonth > $calcYearMonth) return true;
+        return false;
+    }
+
+    /**
+     * 服务奖最大比例
+     * @param $userId
+     * @param $periodNum
+     * @param int $percent
+     * @return float|int
+     */
+    public static function fwMaxBonusPercent($userId, $periodNum, $percent=0) {
+        $cacheKey = self::REDIS_KEY_PREFIX_FW_BONUS . $periodNum;
+        $value = Yii::$app->redis->hget($cacheKey, $userId);
+        $maxPercent = floatval($value)>0 ? floatval($value) : 0;
+        if ( $percent > 0 && $percent > $maxPercent ) {
+            $maxPercent = $percent;
+            unset($periodNum, $percent);
+            Yii::$app->redis->hset($cacheKey, $userId, $maxPercent);
+
+            return $maxPercent;
+        }
+
+        unset($userId, $periodNum, $oriBonus, $cacheKey, $value);
+        return $maxPercent;
+    }
+
+    /**
+     * 奖金缓存
+     * @param $userId
+     * @param $periodNum
+     * @param string $bonusType
+     * @param float $oriBonus
+     * @param array $deductData
+     * @return array|mixed
+     */
+    public static function bonus($userId, $periodNum, $bonusType = null, $oriBonus = 0.00, $deductData=[], $fromMeans='') {
+        $cacheKey = self::REDIS_KEY_PREFIX_BONUS . $periodNum;
+        $value = [
+            'BONUS_BD' => 0,
+            'BONUS_TG' => 0,
+            'BONUS_XF' => 0,
+            'BONUS_YJ' => 0,
+            'BONUS_GX' => 0,
+            'BONUS_GL' => 0,
+            'BONUS_QY' => 0,
+            'BONUS_YC' => 0,
+            'BONUS_VIP' => 0,
+            'BONUS_YC_EXTRA' => 0,
+            'ORI_BONUS_BD' => 0,
+            'ORI_BONUS_TG' => 0,
+            'ORI_BONUS_XF' => 0,
+            'ORI_BONUS_YJ' => 0,
+            'ORI_BONUS_YJ_BD' => 0,
+            'ORI_BONUS_YJ_FX' => 0,
+            'ORI_BONUS_GX' => 0,
+            'ORI_BONUS_GL' => 0,
+            'ORI_BONUS_GL_BD' => 0,
+            'ORI_BONUS_GL_FX' => 0,
+            'ORI_BONUS_QY' => 0,
+            'ORI_BONUS_QY_BD' => 0,
+            'ORI_BONUS_QY_FX' => 0,
+            'ORI_BONUS_YC' => 0,
+            'ORI_BONUS_VIP' => 0,
+            'ORI_BONUS_YC_EXTRA' => 0,
+//            'INCOME_TG_TOTAL' => 0,
+//            'INCOME_YJ_TOTAL' => 0,
+//            'INCOME_QY_TOTAL' => 0,
+            'INCOME_TOTAL' => 0,
+            'BONUS_TOTAL' => 0,
+            'RECONSUME_POINTS' => 0,
+            'MANAGE_TAX' => 0,
+
+            //没有用到的
+            'BONUS_FX' => 0,
+            'BONUS_LS' => 0,
+            'BONUS_CF' => 0,
+            'BONUS_LX' => 0,
+            'BONUS_HB' => 0,
+            'BONUS_BT' => 0,
+            'BONUS_BT_PROD' => 0,
+            'BONUS_BT_TOOL' => 0,
+            'DEDUCT_ZR' => 0,
+            'BONUS_FL' => 0,
+        ];
+        // 从 redis 中获取当前的结果
+        $cacheValue = \Yii::$app->redis->hget($cacheKey, $userId);
+        if ($cacheValue) {
+            $cacheValue = Json::decode($cacheValue);
+            $value = $cacheValue;
+        }
+        unset($cacheValue);
+        if ($oriBonus > 0) {
+            $oriBonusType = sprintf('ORI_%s', $bonusType);
+            $value[$oriBonusType] += $oriBonus;
+            if( $fromMeans !== '' ) {
+                $oriBonusMeansType = sprintf('ORI_%s_%s', $bonusType, $fromMeans);
+                $value[$oriBonusMeansType] += $oriBonus;
+            }
+
+            if( !in_array($bonusType, self::NOT_SEND_BONUS_LIST) ) {
+                if( $deductData ) {
+                    $value[$bonusType] += $deductData['surplus'];
+                    $value['RECONSUME_POINTS'] += $deductData['reConsumePoints'];
+                    $value['MANAGE_TAX'] += $deductData['manageTax'];
+                }else {
+                    $value[$bonusType] += $oriBonus;
+                }
+                $value['BONUS_TOTAL'] += $oriBonus;
+            }
+
+            if( in_array($bonusType, self::INCOME_BONUS_LIST) ) {
+                self::addHasIncomeUsers($userId, $periodNum);
+//                if( !in_array($bonusType, self::NOT_SEND_BONUS_LIST) ) {
+//                    $value['INCOME_TOTAL'] += $oriBonus;
+//                }
+            }
+
+            Yii::$app->redis->hset($cacheKey, $userId, Json::encode($value));
+            unset($oriBonusType);
+            self::addHasBonusUsers($userId, $periodNum);
+        }
+        unset($userId, $periodNum, $bonusType, $oriBonus, $deductData, $cacheKey);
+        return $value;
+    }
+
+    public static function standardBonus($userId, $periodNum, $bonus=0.00) {
+        $cacheKey = self::REDIS_KEY_PREFIX_STANDARD_BONUS . $periodNum;
+
+        $value = 0.00;
+        if( $bonus > 0 ) {
+            Yii::$app->redis->hset($cacheKey, $userId, $bonus);
+            $value = $bonus;
+            //加入有奖金的会员中
+            self::addHasBonusUsers($userId, $periodNum);
+        }else {
+            $cacheValue = \Yii::$app->redis->hget($cacheKey, $userId);
+            if ($cacheValue) {
+                $value = $cacheValue;
+            }
+            unset($cacheValue);
+        }
+
+        unset($cacheKey, $userId, $periodNum, $bonus);
+        return $value;
+    }
+
+    /**
+     * 设置车房总系数
+     * @param $periodNum
+     * @param $value
+     */
+    public static function setCFTotalPercent($periodNum, $value) {
+        Yii::$app->redis->set(self::REDIS_KEY_PREFIX_CF_TOTAL_PERCENT . $periodNum, $value);
+    }
+
+    /**
+     * 获得车房总系数
+     * @param $periodNum
+     * @return mixed
+     */
+    public static function getCFTotalPercent($periodNum) {
+        return Yii::$app->redis->get(self::REDIS_KEY_PREFIX_CF_TOTAL_PERCENT . $periodNum);
+    }
+
+    /**
+     * 设置领袖总系数
+     * @param $periodNum
+     * @param $value
+     */
+    public static function setLXTotalPercent($periodNum, $value) {
+        Yii::$app->redis->set(self::REDIS_KEY_PREFIX_LX_TOTAL_PERCENT . $periodNum, $value);
+    }
+
+    /**
+     * 获得领袖总系数
+     * @param $periodNum
+     * @return mixed
+     */
+    public static function getLXTotalPercent($periodNum) {
+        return Yii::$app->redis->get(self::REDIS_KEY_PREFIX_LX_TOTAL_PERCENT . $periodNum);
+    }
+
+
+    /**
+     * 添加上2代共享奖关系
+     * @param $bonusUserId
+     * @param $fromUserId
+     * @param $periodNum
+     * @param $validDeep
+     * @return  boolean
+     */
+    public static function addShareBonusOneRelation($bonusUserId, $fromUserId, $periodNum, $validDeep) {
+        if ($validDeep == 1) {
+            $cacheKey = self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_ONE_LIST_DATA . $periodNum;
+        }else {
+            $cacheKey = self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_TWO_LIST_DATA . $periodNum;
+        }
+        $fromUserDataJson = Yii::$app->redis->hget($cacheKey, $fromUserId);
+
+        $fromUserData = [];
+        if( $fromUserDataJson ) {
+            $fromUserData = Json::decode($fromUserDataJson, true);
+        }
+        unset($fromUserDataJson);
+
+        $fromUserData[] = $bonusUserId;
+
+        Yii::$app->redis->hset($cacheKey, $fromUserId, Json::encode($fromUserData));
+
+        unset($fromUserData, $bonusUserId, $fromUserId, $periodNum);
+
+        return true;
+    }
+
+    /**
+     * 获取上2代共享奖关系
+     * @param $fromUserId
+     * @param $periodNum
+     * @param $validDeep
+     * @return array
+     */
+    public static function getShareBonusOneRelation($fromUserId, $periodNum, $validDeep) {
+        if ($validDeep == 1) {
+            $cacheKey = self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_ONE_LIST_DATA . $periodNum;
+        }else {
+            $cacheKey = self::REDIS_KEY_PREFIX_GX_BONUS_DEEP_TWO_LIST_DATA . $periodNum;
+        }
+        $fromUserDataJson = Yii::$app->redis->hget($cacheKey, $fromUserId);
+
+        $bonusUserData = [];
+        if( $fromUserDataJson ) {
+            $bonusUserData = Json::decode($fromUserDataJson, true);
+        }
+        unset($fromUserDataJson);
+
+        return $bonusUserData;
+    }
+}

+ 1290 - 0
common/helpers/bonus/PreparePerfCalc.php

@@ -0,0 +1,1290 @@
+<?php
+/**
+ * 月结算的时候,周日晚0点进行预计算,此月用户和团队的业绩信息. 让会员参考,进行补业绩
+ * Created by PhpStorm.
+ * User: liyunlong
+ * Date: 2019-01-11
+ * Time: 15:27
+ */
+namespace common\helpers\bonus;
+
+use common\helpers\Cache;
+use common\helpers\Date;
+use common\helpers\Form;
+use common\helpers\snowflake\SnowFake;
+use common\models\DeclarationLevel;
+use common\models\forms\DeclarationForm;
+use common\models\Order;
+use common\models\OrderDec;
+use common\models\OrderShop;
+use common\models\OrderStandard;
+use common\models\PerfCompany;
+use common\models\PerfMonth;
+use common\models\PerfOrder;
+use common\models\PerfPeriod;
+use common\models\PerfStandard;
+use common\models\Period;
+use common\models\DecOrder;
+use common\models\EmployLevel;
+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;
+
+class PreparePerfCalc {
+    use StaticInstanceTrait;
+
+    private $_limit = 1000;
+    private $_handleUserId;
+    private $_companyMonthPerf = 0;
+    private $_cfTotalPercent = 0;
+    private $_lxTotalPercent = 0;
+    private $_sysConfig = [];
+    private $_decLevelConfig = [];
+    private $_empLevelConfig = [];
+    private $_decRoleConfig = [];
+    private $_errors = [];
+    private $_periodNum = 0;
+    private $_periodId;
+    private $_isCalcMonth = 0;
+    private $_calcYear;
+    private $_calcMonth;
+    private $_calcYearMonth;
+    private $_lastCalcYear;
+    private $_lastCalcMonth;
+    private $_lastCalcYearMonth;
+    private $_lastPeriodNum;
+    private $_lastPeriodYear;
+    private $_lastPeriodMonth;
+    private $_lastPeriodYearMonth;
+    private $_lastTime = 0;
+    //pv
+    private $_pvRatio;
+
+    const LOOP_FINISH = 1;
+    const LOOP_CONTINUE = 2;
+
+    const ORDER_PAY_TYPE_CASH = 'cash';
+//    const ORDER_PAY_TYPE_POINT = 'point';
+
+    /**
+     * 获取期数
+     * @return int
+     */
+    public function getPeriodNum() {
+        return $this->_periodNum;
+    }
+
+    /**
+     * 加入错误错误
+     * @param string $attr
+     * @param string $error
+     */
+    public function addError(string $attr, string $error) {
+        $this->_errors[$attr][] = $error;
+    }
+
+    /**
+     * 获取错误信息
+     * @return array
+     */
+    public function getErrors() {
+        return $this->_errors;
+    }
+
+    /**
+     * 计算步骤
+     * @param $periodNum
+     * @param null $handleUserId
+     * @return bool
+     */
+    public function calcStep($periodNum = null, $handleUserId = null) {
+        try {
+            // 先计算是否是结算月,并且是否到了周日0点
+            // 需要将线上的数据perf_order,perf_period两个表的数据同步过来
+            // Period表数据同步过来,只要是结算月的数据
+            $checkPrepare = $this->checkCanCalcPref($periodNum);
+            if ($checkPrepare !== true) {
+                return true;
+            }
+            $this->_errors = [];
+            $this->_handleUserId = $handleUserId;
+            if (empty($periodNum)) {
+                echo('定时器执行预业绩计算 ,内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            }
+            $this->_updatePercent(5);
+            $t1 = microtime(true);
+            // 初始化结算任务
+            $this->initCalcTask($periodNum);
+            $this->_updatePercent(10);
+            // 设置结算状态
+            $this->setCalcStatus('start', $periodNum);
+            // 清空所有本期结算用到的缓存
+            PrepareCalcCache::clearAll($this->_periodNum);
+            // 清空会员推荐和接点关系缓存
+            PrepareCalcCache::clearNetCache();
+            // 清空相关表数据
+            $this->clearTableData();
+            $this->_updatePercent(15);
+            $t2 = microtime(true);
+            echo(date('Y-m-d H:i:s',time()).'初始化、清空缓存及相关数据表完成,耗时:' . round($t2 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            // 计算月奖,才需要向缓存中加入按推荐深度的所有用户
+            //修改每一期都缓存所有用户
+            PrepareCalcCache::addUsers($this->_periodNum);
+            $t3 = microtime(true);
+            echo('预计算业绩向缓存中加入用户完成,耗时:' . round($t3 - $t2, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(20);
+            // 周结,循环向上级计入业绩并加入业绩单
+            $this->loopCalcPeriodPerfByDecOrder();
+            $this->loopCalcPeriodPerfByOrderDec();
+            $t4 = microtime(true);
+            echo('预计算业绩计算周业绩表中的数据完成,耗时:' . round($t4 - $t1, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(40);
+            // 从会员的复销订单会员计算复销业绩并加入业绩单
+            $this->loopCalcPerfByFXOrder();
+            $this->loopCalcPerfByShopFXOrder();
+            $t5 = microtime(true);
+            echo('预计算业绩计算复销业绩并写入业绩单完成,耗时:' . round($t5 - $t4, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(60);
+            //本期业绩入库
+            $this->loopWriteNowPerf();
+            $t6 = microtime(true);
+            echo('预计算业绩本期业绩入库完成,耗时:' . round($t6 - $t5, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(70);
+
+            //计算月业绩表中的数据
+            $this->loopCalcMonthPerfTableData();
+            $t7 = microtime(true);
+            echo('预计算业绩计算月业绩表中的数据完成,耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(80);
+
+            $t8 = microtime(true);
+            // 计算预计月业绩表的数据,这些数据用户不在前三期非月节点的数据.需要将此期新用户业绩统计一下
+            $this->loopCalcMonthPerfTableDataPrepare();
+  
+            //本月业绩入库
+            $this->loopWriteMonthPerf();
+            $t7 = microtime(true);
+            echo('预计算业绩本月业绩入库完成,耗时:' . round($t7 - $t6, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL);
+            $this->_updatePercent(90);
+
+            $t9 = microtime(true);
+
+            $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();
+            file_put_contents('error_test.txt', var_export([
+                'err' => $e->getMessage()
+            ],true),FILE_APPEND);
+            $this->addError('calc', $e->getMessage());
+            return false;
+        }
+
+        $this->endCalcTask();
+
+        return true;
+    }
+
+    /**
+     * 结算完成
+     * @return bool
+     */
+    public function endCalcTask() {
+        // 更新结算状态
+        $this->setCalcStatus('end');
+    }
+
+    /**
+     * 结算错误
+     */
+    public function errorCalcTask() {
+        // 清空所有本期结算用到的缓存
+        PrepareCalcCache::clearAll($this->_periodNum);
+        // 更新结算状态
+        $this->setCalcStatus('fail');
+    }
+
+    /**
+     * 设置生成业绩单状态
+     * @param $type
+     * start|end|fail
+     */
+    public function setCalcStatus($type, $periodNum = null) {
+        if ($type == 'start') {
+            $this->_lastTime = !empty($periodNum) ? Date::nowTime() : $this->_lastTime;
+            PeriodPrepare::updateAll(['IS_PERFING' => 1, 'IS_PERFED' => Period::PERF_NONE, 'PERF_STARTED_AT' => $this->_lastTime], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+        } elseif ($type == 'end') {
+            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') {
+            PeriodPrepare::updateAll(['IS_PERFING' => 0, 'IS_PERFED' => Period::PERF_FAIL, 'PERFED_AT' => 0], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+        }
+    }
+
+    public function checkCanCalcPref($periodNum = null) {
+        
+        // 先判断时间,现在是周几,如果不是周日,则直接结束
+        // 如果是手动触发,即有业绩期$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($periodNum);
+        if ($periodDataArr['IS_MONTH'] != 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;
+    }
+
+    /**
+     * 初始化结算任务
+     * @throws \yii\db\Exception
+     */
+    public function initCalcTask($periodNum = null) {
+        $periodObj = Period::instance();
+        $periodDataArr = $periodObj->setPeriodNum($periodNum);
+        // 限制订单的时间:如果是定时器,则固定为每周日的0点. 如果是手动执行,则是进行异步代码的时间
+        // 这里直接使用后台生成业绩单的时间
+        $this->_lastTime = empty($periodNum)? $periodDataArr['END_TIME'] - 86399: $periodDataArr['END_TIME']; 
+        $this->_periodNum = $periodDataArr['PERIOD_NUM'];
+        $this->_sysConfig = Cache::getSystemConfig();
+        $this->_decLevelConfig = Cache::getDecLevelConfig();
+        $this->_empLevelConfig = Cache::getEmpLevelConfig();
+        $this->_decRoleConfig = PrepareCalcCache::getDecRoleConfig($this->_periodNum);
+        $periodNum = $this->_periodNum;
+        $this->_periodId = $periodDataArr['ID'];
+        $this->_isCalcMonth = $periodObj->isCalcMonth($periodNum);
+        $this->_calcYear = $periodObj->getYear($periodNum);
+        $this->_calcMonth = $periodObj->getMonth($periodNum);
+        $this->_calcYearMonth = $periodObj->getYearMonth($periodNum);
+        $lastYearMonthArr = $periodObj->getLastMonth($periodNum);
+        $this->_lastCalcYear = $lastYearMonthArr['year'];
+        $this->_lastCalcMonth = $lastYearMonthArr['month'];
+        $this->_lastCalcYearMonth = $lastYearMonthArr['yearMonth'];
+        $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->_pvRatio = $this->_sysConfig['pvRatio']['VALUE'];
+    }
+
+    /**
+     * 清空相关表数据
+     */
+    public function clearTableData() {
+        // 周业绩
+        PerfPeriodPrepare::pageDeleteAll('PERIOD_NUM='.$this->_periodNum);
+        // 业绩单
+        PerfOrderPrepare::pageDeleteAll('PERIOD_NUM='.$this->_periodNum);
+        // 月结时要清空的数据
+        if ($this->_isCalcMonth) {
+            // 月业绩表
+            PerfMonthPrepare::pageDeleteAll("CALC_MONTH='{$this->_calcYearMonth}'");
+        }
+    }
+
+    /**
+     * 周结,向上级算业绩,并计入业绩单
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcPeriodPerfByDecOrder($offset = 0) {
+        // 循环获取全部报单
+        $allData = DecOrder::findUseDbCalc()
+        ->select('ID,DEC_SN,ORDER_SN,USER_ID,TYPE,TO_USER_ID,IS_ADMIN,DEC_AMOUNT,DEC_PV,PERIOD_NUM,
+        CALC_MONTH,IS_DEL,P_CALC_MONTH,CREATED_AT,DEC_ID')
+        ->where(
+            "PERIOD_NUM=:PERIOD_NUM AND IS_DEL=0 AND TYPE='ZC'  AND CREATED_AT<=:CREATED_AT", 
+            [':PERIOD_NUM' => $this->_periodNum, ':CREATED_AT' => $this->_lastTime]
+        )
+        ->orderBy('CREATED_AT DESC,ID DESC')
+        ->offset($offset)
+        ->limit($this->_limit)
+        ->asArray()
+        ->all();
+        if ($allData) {
+            $insertPerfOrderData = [];
+            foreach ($allData as $data) {
+                // 是否关停等状态不能拿业绩
+                if (!$this->isHasPerf($data['TO_USER_ID'])) {
+                    continue;
+                }
+                // 给自己增加PCS(个人消费)
+                PrepareCalcCache::nowPeriodPerf($data['TO_USER_ID'], $this->_periodNum, [
+                    'PV_PCS' => $data['DEC_PV'],
+                    'PV_PCS_ZC' => $data['DEC_PV'],
+                ]);
+                // 把该会员加入到能拿到业绩的会员缓存中
+                PrepareCalcCache::addHasPerfUsers($data['TO_USER_ID'], $this->_periodNum);
+                //加入到报单会员中
+                $toInfo = PrepareCalcCache::getUserInfo($data['TO_USER_ID'], $this->_periodNum);
+                PrepareCalcCache::addHasBDUsers($data['TO_USER_ID'], $this->_periodNum, [
+                    'TO_USER_ID' => $data['TO_USER_ID'],
+                    'USER_ID' => $data['USER_ID'],
+                    'DEC_ID' => $data['DEC_ID'],
+                    //考虑可能会移网的情况
+                    'REC_USER_ID' => $toInfo['REC_UID'] ?? '',
+                    'CON_USER_ID' => $toInfo['CON_UID'] ?? '',
+                    'DEC_AMOUNT' => $data['DEC_AMOUNT'],
+                    'DEC_PV' => $data['DEC_PV'],
+                ]);
+                // 给上追加业绩
+                $this->loopNetworkParentDo($data['TO_USER_ID'], function ($parent) use (&$data) {
+                    
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_' . $parent['LOCATION'] . 'L' => $data['DEC_PV'],
+                        'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $data['DEC_PV'],
+                        'PV_' . $parent['LOCATION'] . 'L_' . $data['TYPE'] => $data['DEC_PV'],
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                    unset($parent);
+                });
+                //给推荐关系累计增加业绩
+                $this->loopRelationParentDo($data['TO_USER_ID'], function ($parent) use (&$data) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_PSS' => $data['DEC_PV'],
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                    unset($parent);
+                });
+                
+                // 写入业绩单表
+                $decInfo = PrepareCalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
+                $sn = PerfOrderPrepare::generateSN();
+                $insertPerfOrderData[] = [
+                    'ID' => SnowFake::instance()->generateId(),
+                    'SN' => $sn,
+                    'DEC_SN' => $data['DEC_SN'],
+                    'DEC_TYPE' => strtoupper($data['TYPE']),
+                    'DEC_STATUS' => PerfOrder::STATUS_NORMAL,
+                    'USER_ID' => $data['TO_USER_ID'],
+                    'LAST_REC_USER_NAME' => $toInfo['REC_USER_NAME'],
+                    'LAST_REC_REAL_NAME' => $toInfo['REC_REAL_NAME'],
+                    'LAST_DEC_LV' => $toInfo['DEC_LV'],
+                    'LAST_EMP_LV' => $toInfo['EMP_LV'],
+                    'LAST_STATUS' => $toInfo['STATUS'],
+                    'PV' => $data['DEC_PV'],
+                    'DEC_AMOUNT' => $data['DEC_AMOUNT'],
+                    'LAST_SUB_COM_ID' => $toInfo['SUB_COM_ID'],
+                    'LAST_PROVINCE' => $toInfo['PROVINCE'],
+                    'LAST_CITY' => $toInfo['CITY'],
+                    'LAST_COUNTY' => $toInfo['COUNTY'],
+                    'DEC_USER_ID' => $data['USER_ID'],
+                    'LAST_DEC_DEC_LV' => $decInfo['DEC_LV'],
+                    'LAST_DEC_SUB_COM_ID' => $decInfo['SUB_COM_ID'],
+                    'LAST_DEC_PROVINCE' => $decInfo['DEC_PROVINCE'],
+                    'LAST_DEC_CITY' => $decInfo['DEC_CITY'],
+                    'LAST_DEC_COUNTY' => $decInfo['DEC_COUNTY'],
+                    '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(),
+                    'CLOSED_AT' => 0,
+                    'ORDER_CREATED_AT' => $data['CREATED_AT'],
+                ];
+                unset($data, $decInfo, $sn, $toInfo);
+            }
+            PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            unset($insertPerfOrderData, $allData, $snArr);
+            return $this->loopCalcPeriodPerfByDecOrder($offset + $this->_limit);
+        }
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 周结,向上级算业绩,并计入业绩单
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcPeriodPerfByOrderDec($offset = 0) {
+        // 循环获取全部报单
+        $allData = OrderDec::findUseDbCalc()
+        ->select('CREATED_AT,ID,SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PV,PAY_AMOUNT,PAY_PV,PERIOD_NUM,PAY_TYPE')
+        ->where(
+            "PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE AND CREATED_AT<=:CREATED_AT", 
+            [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE'=>'ZC', ':CREATED_AT' => $this->_lastTime])
+            ->orderBy('ID DESC')
+            ->offset($offset)
+            ->limit($this->_limit)
+            ->asArray()
+            ->all();
+        if ($allData) {
+            $insertPerfOrderData = [];
+            foreach ($allData as $data) {
+                // 是否关停等状态不能拿业绩
+                if (!$this->isHasPerf($data['USER_ID'])) {
+                    continue;
+                }
+                // 给自己增加PCS(个人消费)
+                PrepareCalcCache::nowPeriodPerf($data['USER_ID'], $this->_periodNum, [
+                    'PV_PCS' => $data['PAY_PV'],
+                    'PV_PCS_ZC' => $data['PAY_PV'],
+                ]);
+                // 把该会员加入到能拿到业绩的会员缓存中
+                PrepareCalcCache::addHasPerfUsers($data['USER_ID'], $this->_periodNum);
+                //加入到报单会员中
+                $toInfo = PrepareCalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
+                PrepareCalcCache::addHasBDUsers($data['USER_ID'], $this->_periodNum, [
+                    'TO_USER_ID' => $data['USER_ID'],
+                    'USER_ID' => $toInfo['DEC_ID'],
+                    'DEC_ID' => $toInfo['DEC_ID'],
+                    //考虑可能会移网的情况
+                    'REC_USER_ID' => $toInfo['REC_UID'] ?? '',
+                    'CON_USER_ID' => $toInfo['CON_UID'] ?? '',
+                    'DEC_AMOUNT' => $data['ORDER_AMOUNT'],
+                    'DEC_PV' => $data['PAY_PV'],
+                ]);
+                // 给上追加业绩
+                $this->loopNetworkParentDo($data['USER_ID'], function ($parent) use (&$data) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_' . $parent['LOCATION'] . 'L' => $data['PAY_PV'],
+                        'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $data['PAY_PV'],
+                        'PV_' . $parent['LOCATION'] . 'L_' . $data['ORDER_TYPE'] => $data['PAY_PV'],
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                    unset($parent);
+                });
+                //给推荐关系累计增加业绩
+                $this->loopRelationParentDo($data['USER_ID'], function ($parent) use (&$data) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_PSS' => $data['PAY_PV'],
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                    unset($parent);
+                });
+
+                // 写入业绩单表
+                $decInfo = PrepareCalcCache::getUserInfo($toInfo['DEC_ID'], $this->_periodNum);
+                $sn = PerfOrderPrepare::generateSN();
+                $insertPerfOrderData[] = [
+                    'ID' => SnowFake::instance()->generateId(),
+                    'SN' => $sn,
+                    'DEC_SN' => $data['SN'],
+                    'DEC_TYPE' => strtoupper($data['ORDER_TYPE']),
+                    'DEC_STATUS' => PerfOrder::STATUS_NORMAL,
+                    'USER_ID' => $data['USER_ID'],
+                    'LAST_REC_USER_NAME' => $toInfo['REC_USER_NAME'],
+                    'LAST_REC_REAL_NAME' => $toInfo['REC_REAL_NAME'],
+                    'LAST_DEC_LV' => $toInfo['DEC_LV'],
+                    'LAST_EMP_LV' => $toInfo['EMP_LV'],
+                    'LAST_STATUS' => $toInfo['STATUS'],
+                    'PV' => $data['PAY_PV'],
+                    'DEC_AMOUNT' => $data['ORDER_AMOUNT'],
+                    'LAST_SUB_COM_ID' => $toInfo['SUB_COM_ID'],
+                    'LAST_PROVINCE' => $toInfo['PROVINCE'],
+                    'LAST_CITY' => $toInfo['CITY'],
+                    'LAST_COUNTY' => $toInfo['COUNTY'],
+                    'DEC_USER_ID' => $toInfo['DEC_ID'],
+                    'LAST_DEC_DEC_LV' => $decInfo['DEC_LV'],
+                    'LAST_DEC_SUB_COM_ID' => $decInfo['SUB_COM_ID'],
+                    'LAST_DEC_PROVINCE' => $decInfo['DEC_PROVINCE'],
+                    'LAST_DEC_CITY' => $decInfo['DEC_CITY'],
+                    'LAST_DEC_COUNTY' => $decInfo['DEC_COUNTY'],
+                    '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(),
+                    'CLOSED_AT' => 0,
+                    'ORDER_CREATED_AT' => $data['CREATED_AT']
+                ];
+                unset($data, $decInfo, $sn, $toInfo);
+            }
+            PerfOrderPrepare::batchInsert($insertPerfOrderData);
+            unset($insertPerfOrderData, $allData, $snArr);
+            return $this->loopCalcPeriodPerfByOrderDec($offset + $this->_limit);
+        }
+        unset($allData);
+        return true;
+    }
+
+
+    /**
+     * 从会员的复销订单会员计算复销业绩并加入业绩单
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcPerfByFXOrder(int $offset = 0) {
+        // 循环获取全部报单
+        $allData = Order::findUseDbCalc()
+        ->select('ID,SN,DEC_SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PAY_AMOUNT,PAY_PV,PAY_TYPE,PERIOD_NUM,STATUS,IS_DELETE,
+        P_CALC_MONTH,CREATED_AT')
+        ->where(
+            "PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE AND CREATED_AT<=:CREATED_AT", 
+            [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE'=>DeclarationForm::TYPE_FX,':CREATED_AT' => $this->_lastTime]
+        )
+        ->orderBy('CREATED_AT DESC,ID DESC')
+        ->offset($offset)
+        ->limit($this->_limit)
+        ->asArray()
+        ->all();
+        if ($allData) {
+            $insertPerfOrderData = [];
+            foreach ($allData as $data) {
+                // 是否关停等状态不能拿业绩
+                if (!$this->isHasPerf($data['USER_ID'])) {
+                    continue;
+                }
+
+                //如果支付方式是现金,那么实际业绩是支付PV的50%
+                if( $data['PAY_TYPE'] === self::ORDER_PAY_TYPE_CASH ) {
+                    $orderCashAmount = $data['ORDER_AMOUNT'];
+                    //111期开始由50%改为60%-by 2020-04-30修改
+                    $payPv = $data['PAY_PV'] * $this->_sysConfig['cashReconsumeBonusPercent']['VALUE'] / 100;
+                    $cacheDataKey = 'PV_PCS_FX_CASH';
+                }else {
+                    $orderCashAmount = 0;
+                    $payPv = $data['PAY_PV'];
+                    $cacheDataKey = 'PV_PCS_FX_POINT';
+                }
+
+                if( $payPv <= 0 ) continue;
+
+                // 给自己增加PCS(个人消费)
+                PrepareCalcCache::nowPeriodPerf($data['USER_ID'], $this->_periodNum, [
+                    'FX_AMOUNT_CASH' => $orderCashAmount,
+                    'PV_PCS' => $payPv,
+                    'PV_PCS_FX' => $payPv,
+                    $cacheDataKey => $payPv,
+                ]);
+                // 把该会员加入到能拿到业绩的会员缓存中
+                PrepareCalcCache::addHasPerfUsers($data['USER_ID'], $this->_periodNum);
+                // 给上追加业绩
+                try {
+                    $this->loopNetworkParentDo($data['USER_ID'], function ($parent) use (&$data, $payPv) {
+                        // 给上级会员追加本期业绩到缓存中
+                        PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                            'PV_' . $parent['LOCATION'] . 'L' => $payPv,
+                            'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $payPv,
+                            'PV_' . $parent['LOCATION'] . 'L_FX' => $payPv,
+                        ]);
+                        // 把该会员加入到能拿到业绩的会员缓存中
+                        PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                    });
+                } catch(\Exception $e) {
+                    file_put_contents('loopNetworkParentDo_error.txt', var_export([
+                        'USER_ID' => $data['USER_ID'],
+                        '_periodNum' => $this->_periodNum,
+                        'error' => $e->getMessage()
+                    ],true));
+                }
+                //给推荐关系累计增加业绩
+                $this->loopRelationParentDo($data['USER_ID'], function ($parent) use ($data, $payPv) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_PSS' => $payPv,
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                });
+
+//                }
+                // 写入业绩单表
+                $baseInfo = PrepareCalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
+                $sn = PerfOrderPrepare::generateSN();
+                $insertPerfOrderData[] = [
+                    'ID' => SnowFake::instance()->generateId(),
+                    'SN' => $sn,
+                    'DEC_SN' => null,
+                    'DEC_TYPE' => 'FX',
+                    'DEC_STATUS' => PerfOrder::STATUS_NORMAL,
+                    'USER_ID' => $data['USER_ID'],
+                    'LAST_REC_USER_NAME' => $baseInfo['REC_USER_NAME'],
+                    'LAST_REC_REAL_NAME' => $baseInfo['REC_REAL_NAME'],
+                    'LAST_DEC_LV' => $baseInfo['DEC_LV'],
+                    'LAST_EMP_LV' => $baseInfo['EMP_LV'],
+                    'LAST_STATUS' => $baseInfo['STATUS'],
+                    'PV' => $payPv,
+                    'DEC_AMOUNT' => $data['PAY_AMOUNT'],
+                    'LAST_SUB_COM_ID' => $baseInfo['SUB_COM_ID'],
+                    'LAST_PROVINCE' => $baseInfo['PROVINCE'],
+                    'LAST_CITY' => $baseInfo['CITY'],
+                    'LAST_COUNTY' => $baseInfo['COUNTY'],
+                    'DEC_USER_ID' => $data['USER_ID'],
+                    'LAST_DEC_DEC_LV' => $baseInfo['DEC_LV'],
+                    'LAST_DEC_SUB_COM_ID' => $baseInfo['SUB_COM_ID'],
+                    'LAST_DEC_PROVINCE' => $baseInfo['PROVINCE'],
+                    'LAST_DEC_CITY' => $baseInfo['CITY'],
+                    'LAST_DEC_COUNTY' => $baseInfo['COUNTY'],
+                    '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(),
+                    'CLOSED_AT' => 0,
+                    'ORDER_CREATED_AT' => $data['CREATED_AT']
+                ];
+                unset($data, $baseInfo, $sn, $orderCashAmount, $payPv, $cacheDataKey);
+            }
+            PerfOrderPrepare::batchInsert($insertPerfOrderData);
+
+            unset($insertPerfOrderData, $allData, $snArr);
+            return $this->loopCalcPerfByFXOrder($offset + $this->_limit);
+        }
+
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 从会员的商城复销订单会员计算复销业绩并加入业绩单
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcPerfByShopFXOrder(int $offset = 0) {
+        // 循环获取全部报单
+        $allData = OrderShop::findUseDbCalc()
+        ->select(
+            'ID,SN,DEC_SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PAY_AMOUNT,PAY_PV,PAY_TYPE,PERIOD_NUM,STATUS,IS_DELETE,
+            P_CALC_MONTH,CREATED_AT')
+        ->where(
+            "PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE AND CREATED_AT<=:CREATED_AT", 
+            [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE'=>DeclarationForm::TYPE_FX,':CREATED_AT' => $this->_lastTime]
+        )
+        ->orderBy('CREATED_AT DESC,ID DESC')
+        ->offset($offset)
+        ->limit($this->_limit)
+        ->asArray()
+        ->all();
+        if ($allData) {
+            $insertPerfOrderData = [];
+            foreach ($allData as $data) {
+                // 是否关停等状态不能拿业绩
+                if (!$this->isHasPerf($data['USER_ID'])) {
+                    continue;
+                }
+
+                //如果支付方式是现金,那么实际业绩是支付PV的50%
+                if( $data['PAY_TYPE'] === self::ORDER_PAY_TYPE_CASH ) {
+                    $orderCashAmount = $data['ORDER_AMOUNT'];
+                    //111期开始由50%改为60%-by 2020-04-30修改
+                    $payPv = $data['PAY_PV'] * $this->_sysConfig['cashReconsumeBonusPercent']['VALUE'] / 100;
+                    $cacheDataKey = 'PV_PCS_FX_CASH';
+                }else {
+                    $orderCashAmount = 0;
+                    $payPv = $data['PAY_PV'];
+                    $cacheDataKey = 'PV_PCS_FX_POINT';
+                }
+
+                if( $payPv <= 0 ) continue;
+
+                // 给自己增加PCS(个人消费)
+                PrepareCalcCache::nowPeriodPerf($data['USER_ID'], $this->_periodNum, [
+                    'FX_AMOUNT_CASH' => $orderCashAmount,
+                    'PV_PCS' => $payPv,
+                    'PV_PCS_FX' => $payPv,
+                    $cacheDataKey => $payPv,
+                ]);
+                // 把该会员加入到能拿到业绩的会员缓存中
+                PrepareCalcCache::addHasPerfUsers($data['USER_ID'], $this->_periodNum);
+                // 给上追加业绩
+                $this->loopNetworkParentDo($data['USER_ID'], function ($parent) use (&$data, $payPv) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_' . $parent['LOCATION'] . 'L' => $payPv,
+                        'PV_' . $parent['LOCATION'] . 'L_TOUCH' => $payPv,
+                        'PV_' . $parent['LOCATION'] . 'L_FX' => $payPv,
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                });
+                //给推荐关系累计增加业绩
+                $this->loopRelationParentDo($data['USER_ID'], function ($parent) use ($data, $payPv) {
+                    // 给上级会员追加本期业绩到缓存中
+                    PrepareCalcCache::nowPeriodPerf($parent['PARENT_UID'], $this->_periodNum, [
+                        'PV_PSS' => $payPv,
+                    ]);
+                    // 把该会员加入到能拿到业绩的会员缓存中
+                    PrepareCalcCache::addHasPerfUsers($parent['PARENT_UID'], $this->_periodNum);
+                });
+
+//                }
+                // 写入业绩单表
+                $baseInfo = PrepareCalcCache::getUserInfo($data['USER_ID'], $this->_periodNum);
+                $sn = PerfOrderPrepare::generateSN();
+                $insertPerfOrderData[] = [
+                    'ID' => SnowFake::instance()->generateId(),
+                    'SN' => $sn,
+                    'DEC_SN' => null,
+                    'DEC_TYPE' => 'FX',
+                    'DEC_STATUS' => PerfOrder::STATUS_NORMAL,
+                    'USER_ID' => $data['USER_ID'],
+                    'LAST_REC_USER_NAME' => $baseInfo['REC_USER_NAME'],
+                    'LAST_REC_REAL_NAME' => $baseInfo['REC_REAL_NAME'],
+                    'LAST_DEC_LV' => $baseInfo['DEC_LV'],
+                    'LAST_EMP_LV' => $baseInfo['EMP_LV'],
+                    'LAST_STATUS' => $baseInfo['STATUS'],
+                    'PV' => $payPv,
+                    'DEC_AMOUNT' => $data['PAY_AMOUNT'],
+                    'LAST_SUB_COM_ID' => $baseInfo['SUB_COM_ID'],
+                    'LAST_PROVINCE' => $baseInfo['PROVINCE'],
+                    'LAST_CITY' => $baseInfo['CITY'],
+                    'LAST_COUNTY' => $baseInfo['COUNTY'],
+                    'DEC_USER_ID' => $data['USER_ID'],
+                    'LAST_DEC_DEC_LV' => $baseInfo['DEC_LV'],
+                    'LAST_DEC_SUB_COM_ID' => $baseInfo['SUB_COM_ID'],
+                    'LAST_DEC_PROVINCE' => $baseInfo['PROVINCE'],
+                    'LAST_DEC_CITY' => $baseInfo['CITY'],
+                    'LAST_DEC_COUNTY' => $baseInfo['COUNTY'],
+                    '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(),
+                    'CLOSED_AT' => 0,
+                    'ORDER_CREATED_AT' => $data['CREATED_AT']
+                ];
+                unset($data, $baseInfo, $sn, $orderCashAmount, $payPv, $cacheDataKey);
+            }
+            PerfOrderPrepare::batchInsert($insertPerfOrderData);
+
+            unset($insertPerfOrderData, $allData, $snArr);
+            return $this->loopCalcPerfByShopFXOrder($offset + $this->_limit);
+        }
+
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 计算月业绩表相关的数据并写入数据库
+     * @param int $offset
+     * @return bool
+     * @throws Exception
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcMonthPerfTableData(int $offset = 0) {
+        if (!$this->_isCalcMonth) {
+            return true;
+        }
+        file_put_contents('ccctxt.txt',var_export([
+            'offset' => $offset,
+            'CALC_MONTH' => $this->_calcYearMonth,
+            'PERIOD_NUM' => $this->_periodNum
+        ],true), FILE_APPEND);
+        // AR_PERF_ORDER_PREPARE\AR_PERF_PERIOD_PREPARE\AR_PERIOD_PREPARE\AR_PERF_MONTH_PREPARE
+        // AR_PERIOD_PREPARE 表只需要是结算月的数据
+        // AR_PERF_PERIOD_PREPARE 表特殊,需要增加一个字段,是否存在于前三期中  已被第一次算月业绩使用过了
+        //  `IS_HAS_USER` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否有此用户,默认为0没有此用户1为有
+        // 如果依旧是0则再次循环此月业绩的时候,需要再次处理' 相当于前三期没有数据,需要单独再添加一次
+        //
+        // 月业绩由perfperiod表加上perfperiodprepare表之和,其中perfperiod表数据为此月非计算月的期业绩数据
+        // 先查询perfperiod表的数据,再查询perfperiodprepare这个表的数据.
+        // 如果查询到了perfperiodprepare的数据,则将此perfperiodprepare表的新增的是否已经在计算第一次统计到的字段标识为1.
+        // 最后再循环 perfperiodprepare 表中标识依旧为0的数据,再次循环.相当于这些数据是此结算月业绩期的新增用户
+        echo sprintf("时间:[%s]月业绩,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
+        // 从缓存列表里面从底层往上倒序获取会员       
+        $allData = PerfPeriod::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,
+        SUM(PV_3L) AS PV_3L_SUM,SUM(PV_4L) AS PV_4L_SUM,
+        SUM(PV_5L) AS PV_5L_SUM,SUM(PV_1L_ZC) AS PV_1L_ZC_SUM,
+        SUM(PV_2L_ZC) AS PV_2L_ZC_SUM,SUM(PV_3L_ZC) AS PV_3L_ZC_SUM,
+        SUM(PV_4L_ZC) AS PV_4L_ZC_SUM,SUM(PV_5L_ZC) AS PV_5L_ZC_SUM')
+        ->where('CALC_MONTH=:CALC_MONTH AND PERIOD_NUM!=:PERIOD_NUM', [':CALC_MONTH' => $this->_calcYearMonth,':PERIOD_NUM'=>$this->_periodNum])
+        ->groupBy('USER_ID')
+        ->orderBy('USER_ID DESC')
+        ->offset($offset)
+        ->limit($this->_limit)
+        ->asArray()
+        ->all();
+        if ($allData) {
+            // 月度业绩表
+            foreach ($allData as $everyData) {
+                $userId = $everyData['USER_ID'];
+                //往期业绩
+                $userLastPerf = PrepareCalcCache::userPerf($userId, $this->_periodNum);
+                //本期业绩
+                $periodPerf = PrepareCalcCache::nowPeriodPerf($userId, $this->_periodNum);
+
+                $userBaseInfo = PrepareCalcCache::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;
+                }
+                // 查询月节点此期业绩,是否包含此用户
+                // 查询perfperiodprepare表中数据,是否有此用户信息.因为是月提前结算,所以此结算期是只有一个数据
+                $monthPrepare = 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,
+                SUM(PV_3L) AS PV_3L_SUM,SUM(PV_4L) AS PV_4L_SUM,
+                SUM(PV_5L) AS PV_5L_SUM,SUM(PV_1L_ZC) AS PV_1L_ZC_SUM,
+                SUM(PV_2L_ZC) AS PV_2L_ZC_SUM,SUM(PV_3L_ZC) AS PV_3L_ZC_SUM,
+                SUM(PV_4L_ZC) AS PV_4L_ZC_SUM,SUM(PV_5L_ZC) AS PV_5L_ZC_SUM')
+                ->where('USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM ', [':USER_ID' => $userId, ':PERIOD_NUM' => $this->_periodNum])
+                ->asArray()
+                ->one();
+                if (!empty($monthPrepare)) {
+                    // 如果前三期中,在此提前计算业绩期中有数据,则需要加上此用户信息
+                    $everyData['FX_AMOUNT_CASH_SUM'] = $everyData['FX_AMOUNT_CASH_SUM'] + $monthPrepare['FX_AMOUNT_CASH_SUM'];
+                    $everyData['PV_PCS_SUM'] = $everyData['PV_PCS_SUM'] + $monthPrepare['PV_PCS_SUM'];
+                    $everyData['PV_PCS_FX_SUM'] =  $everyData['PV_PCS_FX_SUM'] + $monthPrepare['PV_PCS_FX_SUM'];
+                    $everyData['PV_PSS_SUM'] = $everyData['PV_PSS_SUM'] + $monthPrepare['PV_PSS_SUM'];
+                    $everyData['PV_1L_SUM'] = $everyData['PV_1L_SUM'] + $monthPrepare['PV_1L_SUM'];
+                    $everyData['PV_2L_SUM'] = $everyData['PV_2L_SUM'] + $monthPrepare['PV_2L_SUM'];
+                    $everyData['PV_3L_SUM'] = $everyData['PV_3L_SUM'] + $monthPrepare['PV_3L_SUM'];
+                    $everyData['PV_4L_SUM'] = $everyData['PV_4L_SUM'] + $monthPrepare['PV_4L_SUM'];
+                    $everyData['PV_5L_SUM'] = $everyData['PV_5L_SUM'] + $monthPrepare['PV_5L_SUM'];
+                    $everyData['PV_1L_ZC_SUM'] = $everyData['PV_1L_ZC_SUM'] + $monthPrepare['PV_1L_ZC_SUM'];
+                    $everyData['PV_2L_ZC_SUM'] = $everyData['PV_2L_ZC_SUM'] + $monthPrepare['PV_2L_ZC_SUM'];
+                    $everyData['PV_3L_ZC_SUM'] = $everyData['PV_3L_ZC_SUM'] + $monthPrepare['PV_3L_ZC_SUM'];
+                    $everyData['PV_4L_ZC_SUM'] = $everyData['PV_4L_ZC_SUM'] + $monthPrepare['PV_4L_ZC_SUM'];
+                    $everyData['PV_5L_ZC_SUM'] = $everyData['PV_5L_ZC_SUM'] + $monthPrepare['PV_5L_ZC_SUM'];
+                    // 将用户的状态改成1,为存在此用户.当之后再次循环PerfPeriodPrepare的时候,不再循环此用户了.
+                    PerfPeriodPrepare::updateAll(
+                        [
+                            'IS_HAS_USER' => 1
+                        ], 
+                        'PERIOD_NUM=:PERIOD_NUM AND USER_ID=:USER_ID', 
+                        [':PERIOD_NUM' => $this->_periodNum, ':USER_ID' => $userId]
+                    );
+                }
+
+                $nowMonthPerf = [
+                    'USER_ID' => $userId,
+                    'FX_AMOUNT_CASH' => $everyData['FX_AMOUNT_CASH_SUM'],
+                    'PV_PCS' => $everyData['PV_PCS_SUM'],
+                    'PV_PCS_FX' => $everyData['PV_PCS_FX_SUM'],
+                    'PV_PSS' => $everyData['PV_PSS_SUM'],
+                    'PV_1L' => $everyData['PV_1L_SUM'],
+                    'PV_2L' => $everyData['PV_2L_SUM'],
+                    'PV_3L' => $everyData['PV_3L_SUM'],
+                    'PV_4L' => $everyData['PV_4L_SUM'],
+                    'PV_5L' => $everyData['PV_5L_SUM'],
+
+                    //VIP统计相关业绩
+                    'VIP_PV_1L_ZC' => $isVip ? $everyData['PV_1L_ZC_SUM'] : 0,
+                    'VIP_PV_2L_ZC' => $isVip ? $everyData['PV_2L_ZC_SUM'] : 0,
+                    'VIP_PV_3L_ZC' => $isVip ? $everyData['PV_3L_ZC_SUM'] : 0,
+                    'VIP_PV_4L_ZC' => $isVip ? $everyData['PV_4L_ZC_SUM'] : 0,
+                    'VIP_PV_5L_ZC' => $isVip ? $everyData['PV_5L_ZC_SUM'] : 0,
+
+                    //总数据,历史+本期。不能用上月加本月,因为上月可能没业绩,上上个月有业绩。
+                    'PV_1L_TOTAL' => $periodPerf['PV_1L'] + $userLastPerf['PV_1L'],
+                    'PV_2L_TOTAL' => $periodPerf['PV_2L'] + $userLastPerf['PV_2L'],
+                    'PV_3L_TOTAL' => $periodPerf['PV_3L'] + $userLastPerf['PV_3L'],
+                    'PV_4L_TOTAL' => $periodPerf['PV_4L'] + $userLastPerf['PV_4L'],
+                    'PV_5L_TOTAL' => $periodPerf['PV_5L'] + $userLastPerf['PV_5L'],
+                    'PV_PSS_TOTAL' => $periodPerf['PV_PSS'] + $userLastPerf['PV_PSS_TOTAL'],
+                ];
+
+                // 把会员的月业绩写入缓存中,以便下面的奖金计算从缓冲中获取数据效率高
+                PrepareCalcCache::addHasMonthPerfUsers($userId, $this->_periodNum);
+                PrepareCalcCache::nowMonthPerf($userId, $this->_periodNum, $nowMonthPerf);
+
+                unset($userId, $everyData, $nowMonthPerf, $lastMonthData, $userBaseInfo, $isVip);
+            }
+            unset($allData);
+            return $this->loopCalcMonthPerfTableData($offset + $this->_limit);
+        }
+
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 预计计算月业绩,当前三期没有此最新业绩单的用户
+     * 再次添加进去
+     * @param int $offset
+     * @return bool
+     * @throws Exception
+     * @throws \yii\db\Exception
+     */
+    public function loopCalcMonthPerfTableDataPrepare(int $offset = 0) {
+        if (!$this->_isCalcMonth) {
+            return true;
+        }
+        // 上面的计算月业绩,计算了前三期有的用户,此次只计算此结算周期未含有前三期业绩的用户
+       
+        echo sprintf("时间:[%s]预计月业绩,结算月新添加的用户,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
+        // 从缓存列表里面从底层往上倒序获取会员      IS_HAS_USER 0 代表是此结算周期新增的业绩 
+        $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,
+        SUM(PV_3L) AS PV_3L_SUM,SUM(PV_4L) AS PV_4L_SUM,
+        SUM(PV_5L) AS PV_5L_SUM,SUM(PV_1L_ZC) AS PV_1L_ZC_SUM,
+        SUM(PV_2L_ZC) AS PV_2L_ZC_SUM,SUM(PV_3L_ZC) AS PV_3L_ZC_SUM,
+        SUM(PV_4L_ZC) AS PV_4L_ZC_SUM,SUM(PV_5L_ZC) AS PV_5L_ZC_SUM')
+        ->where('CALC_MONTH=:CALC_MONTH AND IS_HAS_USER=0', [':CALC_MONTH' => $this->_calcYearMonth])
+        ->groupBy('USER_ID')
+        ->orderBy('USER_ID DESC')
+        ->offset($offset)
+        ->limit($this->_limit)
+        ->asArray()
+        ->all();
+        if ($allData) {
+            // 月度业绩表
+            foreach ($allData as $everyData) {
+                $userId = $everyData['USER_ID'];
+                //往期业绩
+                $userLastPerf = PrepareCalcCache::userPerf($userId, $this->_periodNum);
+                //本期业绩
+                $periodPerf = PrepareCalcCache::nowPeriodPerf($userId, $this->_periodNum);
+
+                $userBaseInfo = PrepareCalcCache::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;
+                }
+
+                $nowMonthPerf = [
+                    'USER_ID' => $userId,
+                    'FX_AMOUNT_CASH' => $everyData['FX_AMOUNT_CASH_SUM'],
+                    'PV_PCS' => $everyData['PV_PCS_SUM'],
+                    'PV_PCS_FX' => $everyData['PV_PCS_FX_SUM'],
+                    'PV_PSS' => $everyData['PV_PSS_SUM'],
+                    'PV_1L' => $everyData['PV_1L_SUM'],
+                    'PV_2L' => $everyData['PV_2L_SUM'],
+                    'PV_3L' => $everyData['PV_3L_SUM'],
+                    'PV_4L' => $everyData['PV_4L_SUM'],
+                    'PV_5L' => $everyData['PV_5L_SUM'],
+
+                    //VIP统计相关业绩
+                    'VIP_PV_1L_ZC' => $isVip ? $everyData['PV_1L_ZC_SUM'] : 0,
+                    'VIP_PV_2L_ZC' => $isVip ? $everyData['PV_2L_ZC_SUM'] : 0,
+                    'VIP_PV_3L_ZC' => $isVip ? $everyData['PV_3L_ZC_SUM'] : 0,
+                    'VIP_PV_4L_ZC' => $isVip ? $everyData['PV_4L_ZC_SUM'] : 0,
+                    'VIP_PV_5L_ZC' => $isVip ? $everyData['PV_5L_ZC_SUM'] : 0,
+
+                    //总数据,历史+本期。不能用上月加本月,因为上月可能没业绩,上上个月有业绩。
+                    'PV_1L_TOTAL' => $periodPerf['PV_1L'] + $userLastPerf['PV_1L'],
+                    'PV_2L_TOTAL' => $periodPerf['PV_2L'] + $userLastPerf['PV_2L'],
+                    'PV_3L_TOTAL' => $periodPerf['PV_3L'] + $userLastPerf['PV_3L'],
+                    'PV_4L_TOTAL' => $periodPerf['PV_4L'] + $userLastPerf['PV_4L'],
+                    'PV_5L_TOTAL' => $periodPerf['PV_5L'] + $userLastPerf['PV_5L'],
+                    'PV_PSS_TOTAL' => $periodPerf['PV_PSS'] + $userLastPerf['PV_PSS_TOTAL'],
+                ];
+
+                // 把会员的月业绩写入缓存中,以便下面的奖金计算从缓冲中获取数据效率高
+                PrepareCalcCache::addHasMonthPerfUsers($userId, $this->_periodNum);
+                PrepareCalcCache::nowMonthPerf($userId, $this->_periodNum, $nowMonthPerf);
+                // 将用户的状态改成1,为存在此用户.当之后再次循环PerfPeriodPrepare的时候,不再循环此用户了.
+                PerfPeriodPrepare::updateAll(
+                    [
+                        'IS_HAS_USER' => 1
+                    ], 
+                    'PERIOD_NUM=:PERIOD_NUM AND USER_ID=:USER_ID', 
+                    [':PERIOD_NUM' => $this->_periodNum, ':USER_ID' => $userId]
+                );
+
+
+                unset($userId, $everyData, $nowMonthPerf, $lastMonthData, $userBaseInfo, $isVip);
+            }
+            unset($allData);
+            return $this->loopCalcMonthPerfTableDataPrepare($offset + $this->_limit);
+        }
+
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 循环有业绩会员,并入库
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopWriteNowPerf($offset = 0) {
+        echo sprintf("时间:[%s]缓存本期业绩数据入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
+        // 从缓存列表里面从底层往上倒序获取会员
+        $allData = PrepareCalcCache::getHasPerfUsers($this->_periodNum, $offset, $this->_limit);
+        if($allData){
+            $insertDataPeriodPerf = [];
+            foreach($allData as $userId){
+                $insertDataPeriodPerf[] = $this->nowPeriodPerfData($userId);
+                unset($userId);
+            }
+            PerfPeriodPrepare::batchInsert($insertDataPeriodPerf);
+
+            unset($insertDataPeriodPerf, $allData);
+            return $this->loopWriteNowPerf($offset + $this->_limit);
+        }
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 循环有月业绩会员,并入库
+     * @param int $offset
+     * @return bool
+     * @throws \yii\db\Exception
+     */
+    public function loopWriteMonthPerf($offset = 0) {
+        if(!$this->_isCalcMonth){
+            return true;
+        }
+        echo sprintf("时间:[%s]缓存本月业绩数据入库,当前offset为:【%s】" . PHP_EOL, date('Y-m-d H:i:s', time()) , $offset);
+        // 从缓存列表里面从底层往上倒序获取会员
+        $allData = PrepareCalcCache::getHasMonthPerfUsers($this->_periodNum, $offset, $this->_limit);
+        if($allData){
+            $insertDataMonthPerf = [];
+            foreach($allData as $userId){
+                $insertDataMonthPerf[] = $this->nowMonthPerfData($userId);
+                unset($userId);
+            }
+            // 月预计计算业绩插入数据
+            PerfMonthPrepare::batchInsert($insertDataMonthPerf);
+            unset($insertDataMonthPerf, $allData);
+            return $this->loopWriteMonthPerf($offset + $this->_limit);
+        }
+        unset($allData);
+        return true;
+    }
+
+    /**
+     * 本期业绩数据
+     * @param $userId
+     * @return array
+     */
+    public function nowPeriodPerfData($userId){
+        $data = PrepareCalcCache::nowPeriodPerf($userId, $this->_periodNum);
+        $baseInfo = PrepareCalcCache::getUserInfo($userId, $this->_periodNum);
+        $result = [
+            'ID' => SnowFake::instance()->generateId(),
+            'USER_ID' => $userId,
+            'LAST_DEC_LV' => $baseInfo['DEC_LV'],
+            'LAST_EMP_LV' => $baseInfo['EMP_LV'],
+            'LAST_STATUS' => $baseInfo['STATUS'],
+            'FX_AMOUNT_CASH' => $data['FX_AMOUNT_CASH'],
+            'PV_PCS' => $data['PV_PCS'],
+            'PV_PSS' => $data['PV_PSS'],
+            'PV_PCS_ZC' => $data['PV_PCS_ZC'],
+            'PV_PCS_YH' => $data['PV_PCS_YH'],
+            'PV_PCS_ZG' => $data['PV_PCS_ZG'],
+            'PV_PCS_LS' => $data['PV_PCS_LS'],
+            'PV_PCS_FX' => $data['PV_PCS_FX'],
+            'PV_PCS_FX_CASH' => $data['PV_PCS_FX_CASH'],
+            'PV_PCS_FX_POINT' => $data['PV_PCS_FX_POINT'],
+            'PV_1L' => $data['PV_1L'],
+            'PV_1L_TOUCH' => $data['PV_1L_TOUCH'],
+            'PV_1L_ZC' => $data['PV_1L_ZC'],
+            'PV_1L_YH' => $data['PV_1L_YH'],
+            'PV_1L_ZG' => $data['PV_1L_ZG'],
+            'PV_1L_LS' => $data['PV_1L_LS'],
+            'PV_1L_FX' => $data['PV_1L_FX'],
+            'PV_2L' => $data['PV_2L'],
+            'PV_2L_TOUCH' => $data['PV_2L_TOUCH'],
+            'PV_2L_ZC' => $data['PV_2L_ZC'],
+            'PV_2L_YH' => $data['PV_2L_YH'],
+            'PV_2L_ZG' => $data['PV_2L_ZG'],
+            'PV_2L_LS' => $data['PV_2L_LS'],
+            'PV_2L_FX' => $data['PV_2L_FX'],
+            'PV_3L' => $data['PV_3L'],
+            'PV_3L_TOUCH' => $data['PV_3L_TOUCH'],
+            'PV_3L_ZC' => $data['PV_3L_ZC'],
+            'PV_3L_YH' => $data['PV_3L_YH'],
+            'PV_3L_ZG' => $data['PV_3L_ZG'],
+            'PV_3L_LS' => $data['PV_3L_LS'],
+            'PV_3L_FX' => $data['PV_3L_FX'],
+            'PV_4L' => $data['PV_4L'],
+            'PV_4L_TOUCH' => $data['PV_4L_TOUCH'],
+            'PV_4L_ZC' => $data['PV_4L_ZC'],
+            'PV_4L_YH' => $data['PV_4L_YH'],
+            'PV_4L_ZG' => $data['PV_4L_ZG'],
+            'PV_4L_LS' => $data['PV_4L_LS'],
+            'PV_4L_FX' => $data['PV_4L_FX'],
+            'PV_5L' => $data['PV_5L'],
+            'PV_5L_TOUCH' => $data['PV_5L_TOUCH'],
+            'PV_5L_ZC' => $data['PV_5L_ZC'],
+            'PV_5L_YH' => $data['PV_5L_YH'],
+            'PV_5L_ZG' => $data['PV_5L_ZG'],
+            'PV_5L_LS' => $data['PV_5L_LS'],
+            'PV_5L_FX' => $data['PV_5L_FX'],
+            'PV_LS_TOUCH' => $data['PV_LS_TOUCH'],
+            'SURPLUS_1L' => $data['SURPLUS_1L'],
+            'SURPLUS_2L' => $data['SURPLUS_2L'],
+            'SURPLUS_3L' => $data['SURPLUS_3L'],
+            'SURPLUS_4L' => $data['SURPLUS_4L'],
+            'SURPLUS_5L' => $data['SURPLUS_5L'],
+            'SURPLUS_LS' => $data['SURPLUS_LS'],
+            '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(),
+        ];
+        unset($data);
+        return $result;
+    }
+
+
+
+    /**
+     * 本月业绩
+     * @param $userId
+     * @return array
+     */
+    public function nowMonthPerfData($userId){
+        $data = PrepareCalcCache::nowMonthPerf($userId, $this->_periodNum);
+        $baseInfo = PrepareCalcCache::getUserInfo($userId, $this->_periodNum);
+        $result = [
+            'ID' => SnowFake::instance()->generateId(),
+            'USER_ID' => $userId,
+            'LAST_DEC_LV' => $baseInfo['DEC_LV'],
+            'LAST_EMP_LV' => $data['EMP_LEVEL'],
+            'LAST_STATUS' => $baseInfo['STATUS'],
+            'FX_AMOUNT_CASH' => $data['FX_AMOUNT_CASH'],
+            'PV_PCS' => $data['PV_PCS'],
+            'PV_PCS_FX' => $data['PV_PCS_FX'],
+            'PV_PSS' => $data['PV_PSS'],
+            'PV_1L' => $data['PV_1L'],
+            'PV_2L' => $data['PV_2L'],
+            'PV_3L' => $data['PV_3L'],
+            'PV_4L' => $data['PV_4L'],
+            'PV_5L' => $data['PV_5L'],
+            'VIP_PV_1L_ZC' => $data['VIP_PV_1L_ZC'],
+            'VIP_PV_2L_ZC' => $data['VIP_PV_2L_ZC'],
+            'VIP_PV_3L_ZC' => $data['VIP_PV_3L_ZC'],
+            'VIP_PV_4L_ZC' => $data['VIP_PV_4L_ZC'],
+            'VIP_PV_5L_ZC' => $data['VIP_PV_5L_ZC'],
+            'PV_1L_TOTAL' => $data['PV_1L_TOTAL'],
+            'PV_2L_TOTAL' => $data['PV_2L_TOTAL'],
+            'PV_3L_TOTAL' => $data['PV_3L_TOTAL'],
+            'PV_4L_TOTAL' => $data['PV_4L_TOTAL'],
+            'PV_5L_TOTAL' => $data['PV_5L_TOTAL'],
+            'PV_PSS_TOTAL' => $data['PV_PSS_TOTAL'],
+            'CF_PERCENT' => $data['CF_PERCENT'],
+            'LX_PERCENT' => $data['LX_PERCENT'],
+            'FX_STATUS' => $data['FX_STATUS'],
+            'CALC_MONTH' => $this->_calcYearMonth,
+            'P_CALC_MONTH' => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH),
+            'CREATED_AT' => Date::nowTime(),
+        ];
+        unset($data);
+        return $result;
+    }
+
+    /**
+     * 循环父级并执行回调函数
+     * @param $userId
+     * @param callable $callbackFunc
+     * @param int $offset
+     * @return bool
+     */
+    public function loopNetworkParentDo($userId, callable $callbackFunc, int $offset = 0) {
+        $allParents = Cache::getAllNetworkParents($userId, true);
+        $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,true);
+        $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;
+    }
+
+    /**
+     * 是否可拿业绩(即注销、关停、停发状态)
+     * @param $userId
+     * @return bool
+     */
+    public function isHasPerf($userId) {
+        //@todo 所有人都有业绩
+        return true;
+    }
+
+    /**
+     * 更新百分比并发送
+     * @param $percent
+     */
+    private function _updatePercent($percent) {
+        // 把数据写入数据库中
+        PeriodPrepare::updateAll(['PERF_PERCENT' => $percent], 'PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum]);
+    }
+}

+ 192 - 0
common/models/PerfMonthPrepare.php

@@ -0,0 +1,192 @@
+<?php
+
+namespace common\models;
+
+use common\helpers\Tool;
+use Yii;
+use common\libs\logging\operate\valueType\Config as ValueTypeConfig;
+
+/**
+ * This is the model class for table "{{%PERF_MONTH_PREPARE}}".
+ *
+ * @property string $ID
+ * @property string $USER_ID 会员ID
+ * @property string $LAST_DEC_LV 结算时会员级别
+ * @property string $LAST_EMP_LV 结算时会员聘级
+ * @property int $LAST_STATUS 结算时会有状态
+ * @property string $FX_AMOUNT_CASH 复消现金金额
+ * @property string $PV_PCS 个人消费
+ * @property string $PV_PCS_FX 个人复消业绩
+ * @property string $PV_1L 一市场业绩
+ * @property string $PV_2L 二市场业绩
+ * @property string $PV_3L 三市场业绩
+ * @property string $PV_4L 四市场业绩
+ * @property string $PV_5L 五市场业绩
+ * @property string $VIP_PV_1L_ZC VIP一市场报单业绩
+ * @property string $VIP_PV_2L_ZC VIP二市场报单业绩
+ * @property string $VIP_PV_3L_ZC VIP三市场报单业绩
+ * @property string $VIP_PV_4L_ZC VIP四市场报单业绩
+ * @property string $VIP_PV_5L_ZC VIP五市场报单业绩
+ * @property string $VIP_SURPLUS_1L_ZC VIP一市场剩余报单业绩
+ * @property string $VIP_SURPLUS_2L_ZC VIP二市场剩余报单业绩
+ * @property string $VIP_SURPLUS_3L_ZC VIP三市场剩余报单业绩
+ * @property string $VIP_SURPLUS_4L_ZC VIP四市场剩余报单业绩
+ * @property string $VIP_SURPLUS_5L_ZC VIP五市场剩余报单业绩
+ * @property string $PV_1L_TOTAL 一市场历史累计加该月业绩
+ * @property string $PV_2L_TOTAL 二市场历史累计加该月业绩
+ * @property string $PV_3L_TOTAL 三市场历史累计加该月业绩
+ * @property string $PV_4L_TOTAL 四市场历史累计加该月业绩
+ * @property string $PV_5L_TOTAL 五市场历史累计加该月业绩
+ * @property int $CF_PERCENT 车房养老奖分工系数
+ * @property int $LX_PERCENT 领袖分红分工系数
+ * @property int $FX_STATUS 本月复销状态作为下月发奖资格
+ * @property int $CALC_MONTH 结算月
+ * @property string $P_CALC_MONTH 表分区日期索引
+ * @property int $CREATED_AT 创建时间
+ */
+class PerfMonthPrepare extends \common\components\ActiveRecord
+{
+    const NEXT_MONTH_FX_TRUE = 1;
+    const NEXT_MONTH_FX_FALSE = 0;
+
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return '{{%PERF_MONTH_PREPARE}}';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['USER_ID', 'CALC_MONTH', 'P_CALC_MONTH', 'CREATED_AT'], 'required'],
+            [['LAST_STATUS', 'CF_PERCENT', 'LX_PERCENT', 'FX_STATUS', 'CALC_MONTH', 'CREATED_AT'], 'integer'],
+            [['FX_AMOUNT_CASH', 'PV_PCS', 'PV_PCS_FX', 'PV_1L', 'PV_2L', 'PV_3L', 'PV_4L', 'PV_5L', 'VIP_PV_1L_ZC', 'VIP_PV_2L_ZC',  'VIP_PV_3L_ZC', 'VIP_PV_4L_ZC', 'VIP_PV_5L_ZC', 'VIP_SURPLUS_1L_ZC', 'VIP_SURPLUS_2L_ZC', 'VIP_SURPLUS_3L_ZC', 'VIP_SURPLUS_4L_ZC', 'VIP_SURPLUS_5L_ZC', 'PV_1L_TOTAL', 'PV_2L_TOTAL', 'PV_3L_TOTAL', 'PV_4L_TOTAL', 'PV_5L_TOTAL'], 'number'],
+            [['ID', 'USER_ID', 'LAST_DEC_LV', 'LAST_EMP_LV'], 'string', 'max' => 32],
+            [['P_CALC_MONTH'], 'safe'],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'USER_ID' => '会员ID',
+            'LAST_DEC_LV' => '结算时会员级别',
+            'LAST_EMP_LV' => '结算时会员聘级',
+            'LAST_STATUS' => '结算时会有状态',
+            'FX_AMOUNT_CASH' => '复消现金金额',
+            'PV_PCS' => '个人消费',
+            'PV_PCS_FX' => '个人复消业绩',
+            'PV_1L' => '一市场业绩',
+            'PV_2L' => '二市场业绩',
+            'PV_3L' => '三市场业绩',
+            'PV_4L' => '四市场业绩',
+            'PV_5L' => '五市场业绩',
+            'VIP_PV_1L_ZC' => 'VIP一市场报单业绩',
+            'VIP_PV_2L_ZC' => 'VIP二市场报单业绩',
+            'VIP_PV_3L_ZC' => 'VIP三市场报单业绩',
+            'VIP_PV_4L_ZC' => 'VIP四市场报单业绩',
+            'VIP_PV_5L_ZC' => 'VIP五市场报单业绩',
+            'VIP_SURPLUS_1L_ZC' => 'VIP一市场剩余报单业绩',
+            'VIP_SURPLUS_2L_ZC' => 'VIP二市场剩余报单业绩',
+            'VIP_SURPLUS_3L_ZC' => 'VIP三市场剩余报单业绩',
+            'VIP_SURPLUS_4L_ZC' => 'VIP四市场剩余报单业绩',
+            'VIP_SURPLUS_5L_ZC' => 'VIP五市场剩余报单业绩',
+            'PV_1L_TOTAL' => '一市场历史累计加该月业绩',
+            'PV_2L_TOTAL' => '二市场历史累计加该月业绩',
+            'PV_3L_TOTAL' => '三市场历史累计加该月业绩',
+            'PV_4L_TOTAL' => '四市场历史累计加该月业绩',
+            'PV_5L_TOTAL' => '五市场历史累计加该月业绩',
+            'CF_PERCENT' => '车房养老奖分工系数',
+            'LX_PERCENT' => '领袖分红分工系数',
+            'FX_STATUS' => '本月复销状态作为下月发奖资格',
+            'CALC_MONTH' => '结算月',
+            'P_CALC_MONTH' => '表分区日期索引',
+            'CREATED_AT' => '创建时间',
+        ];
+    }
+
+    /**
+     * 获取会员的月业绩总和
+     * @param $yearMonth
+     * @param $userId
+     * @return array|null|\yii\db\ActiveRecord
+     */
+    public static function getMonthPerf($yearMonth, $userId){
+        $result = static::find()->yearMonth($yearMonth)->where('USER_ID=:USER_ID', [':USER_ID'=>$userId])->asArray()->one();
+        if(!$result){
+            $result = [
+                'USER_ID' => $userId,
+                'FX_AMOUNT_CASH' => 0,
+                'PV_PCS' => 0,
+                'PV_PSS' => 0,
+                'PV_1L' => 0,
+                'PV_2L' => 0,
+                'PV_3L' => 0,
+                'PV_4L' => 0,
+                'PV_5L' => 0,
+                'PV_1L_TOTAL' => 0,
+                'PV_2L_TOTAL' => 0,
+                'PV_3L_TOTAL' => 0,
+                'PV_4L_TOTAL' => 0,
+                'PV_5L_TOTAL' => 0,
+                'PV_PSS_TOTAL' => 0,
+                'DEC_LEVEL' => null,
+                'EMP_LEVEL' => null,
+                'CF_PERCENT' => 0,
+                'LX_PERCENT' => 0,
+                'FX_STATUS' => self::NEXT_MONTH_FX_FALSE,
+            ];
+        }
+        $result['PV_TOTAL'] = Tool::formatPrice($result['PV_1L_TOTAL']+$result['PV_2L_TOTAL']+$result['PV_3L_TOTAL']+$result['PV_4L_TOTAL']+$result['PV_5L_TOTAL']);
+        return $result;
+    }
+
+    // 获取会员的月业绩信息
+    public static function getMonthPerfPrepare($userId,$calcMonth) {
+        $result = PerfMonthPrepare::findUseSlaves()
+        ->where(
+            'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $userId,':CALC_MONTH'=>$calcMonth]
+        )
+        ->asArray()
+        ->one();
+
+        return $result;
+    }
+
+    // 校验业绩状态
+    public static function checkPrepareStatus($pv) {
+        if ($pv >= 10000) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * 操作日志记录条件
+     * @return array
+     */
+    public function attrLabelsWithLogType(){
+        return [
+            'USER_ID' => '会员ID',
+            'FX_STATUS' => [
+                'label' => '复销资格',
+                'type' => function($data){
+                    $value = $data['value'];
+                    return $value==1?'是':'否';
+                },
+            ],
+            'CALC_MONTH' => '结算月',
+        ];
+    }
+}

+ 130 - 0
common/models/PerfOrderPrepare.php

@@ -0,0 +1,130 @@
+<?php
+
+namespace common\models;
+
+use common\helpers\snowflake\SnowFake;
+use common\helpers\Tool;
+use Yii;
+use yii\base\Exception;
+
+/**
+ * This is the model class for table "{{%PERF_ORDER_PREPARE}}".
+ *
+ * @property string $ID
+ * @property string $SN 业绩单编号
+ * @property string $DEC_SN 报单编号
+ * @property string $DEC_TYPE 报单类型
+ * @property int $DEC_STATUS 业绩单状态
+ * @property string $USER_ID 产生业绩会员ID
+ * @property string $LAST_DEC_LV 结算时会员级别
+ * @property string $LAST_EMP_LV 结算时会员聘级
+ * @property int $LAST_STATUS 结算时状态
+ * @property string $LAST_REC_USER_NAME 结算时开拓者编号
+ * @property string $LAST_REC_REAL_NAME 结算时开拓者姓名
+ * @property string $PV 业绩单PV
+ * @property string $DEC_AMOUNT 报单金额
+ * @property string $LAST_SUB_COM_ID 结算时所属分公司
+ * @property int $LAST_PROVINCE 结算时省份
+ * @property int $LAST_CITY 结算时城市
+ * @property int $LAST_COUNTY 结算时地区
+ * @property string $DEC_USER_ID 报单主体ID
+ * @property string $LAST_DEC_DEC_LV 结算时报单主体级别
+ * @property string $LAST_DEC_SUB_COM_ID 结算时报单主体所属分公司
+ * @property int $LAST_DEC_PROVINCE 结算时报单主体省份
+ * @property int $LAST_DEC_CITY 结算时报单主体城市
+ * @property int $LAST_DEC_COUNTY 结算时报单主体地区
+ * @property int $PERIOD_NUM 所在期数
+ * @property int $CALC_MONTH 结算月
+ * @property string $P_CALC_MONTH 分区结算月
+ * @property int $CREATED_AT 创建时间
+ * @property int $CLOSED_AT 置废时间
+ */
+class PerfOrderPrepare extends \common\components\ActiveRecord
+{
+    //业绩单状态
+    const STATUS_NORMAL = 1; //正常
+    const STATUS_CLOSED = 2; //置废
+    const STATUS_NAME = [
+      self::STATUS_NORMAL=>'已审核',
+      self::STATUS_CLOSED=>'置废',
+    ];
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return '{{%PERF_ORDER_PREPARE}}';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['SN', 'DEC_TYPE', 'USER_ID', 'PERIOD_NUM', 'CALC_MONTH', 'P_CALC_MONTH', 'CREATED_AT', 'CLOSED_AT'], 'required'],
+            [['LAST_STATUS', 'DEC_STATUS', 'LAST_PROVINCE', 'LAST_CITY', 'LAST_COUNTY', 'LAST_DEC_PROVINCE', 'LAST_DEC_CITY', 'LAST_DEC_COUNTY', 'PERIOD_NUM', 'CALC_MONTH', 'CREATED_AT', 'CLOSED_AT'], 'integer'],
+            [['PV', 'DEC_AMOUNT'], 'number'],
+            [['ID', 'USER_ID', 'LAST_DEC_LV','LAST_EMP_LV', 'LAST_SUB_COM_ID', 'DEC_USER_ID', 'LAST_DEC_DEC_LV', 'LAST_DEC_SUB_COM_ID'], 'string', 'max' => 32],
+            [['SN', 'DEC_SN', 'DEC_TYPE'], 'string', 'max' => 32],
+            [['LAST_REC_USER_NAME'], 'string', 'max' => 16],
+            [['LAST_REC_REAL_NAME'], 'string', 'max' => 128],
+            [['P_CALC_MONTH'], 'string', 'max' => 7],
+            [['SN'], 'unique'],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'SN' => '业绩单编号',
+            'DEC_SN' => '报单编号',
+            'DEC_TYPE' => '报单类型',
+            'DEC_STATUS' => '业绩单状态',
+            'USER_ID' => '产生业绩会员ID',
+            'LAST_DEC_LV' => '结算时会员级别',
+            'LAST_EMP_LV' => '结算时会员聘级',
+            'LAST_STATUS' => '结算时状态',
+            'LAST_REC_USER_NAME' => '结算时开拓者编号',
+            'LAST_REC_REAL_NAME' => '结算时开拓者姓名',
+            'PV' => '业绩单PV',
+            'DEC_AMOUNT' => '报单金额',
+            'LAST_SUB_COM_ID' => '结算时所属分公司',
+            'LAST_PROVINCE' => '结算时省份',
+            'LAST_CITY' => '结算时城市',
+            'LAST_COUNTY' => '结算时地区',
+            'DEC_USER_ID' => '报单主体ID',
+            'LAST_DEC_DEC_LV' => '结算时报单主体级别',
+            'LAST_DEC_SUB_COM_ID' => '结算时报单主体所属分公司',
+            'LAST_DEC_PROVINCE' => '结算时报单主体省份',
+            'LAST_DEC_CITY' => '结算时报单主体城市',
+            'LAST_DEC_COUNTY' => '结算时报单主体地区',
+            'PERIOD_NUM' => '所在期数',
+            'CALC_MONTH' => '结算月',
+            'P_CALC_MONTH' => '分区结算月',
+            'CREATED_AT' => '创建时间',
+            'CLOSED_AT' => '置废时间',
+        ];
+    }
+
+    /**
+     * 获取当前最大的订单编号
+     * @return mixed
+     */
+    public static function getMaxSn(){
+        return static::find()->where('1=1')->max('SN');
+    }
+
+    /**
+     * 生成sn
+     * @return string
+     */
+    public static function generateSN() {
+        return  SnowFake::instance()->generateId();
+    }
+}

+ 228 - 0
common/models/PerfPeriodPrepare.php

@@ -0,0 +1,228 @@
+<?php
+
+namespace common\models;
+
+use common\helpers\user\Info;
+use Yii;
+
+/**
+ * This is the model class for table "{{%PERF_PERIOD_PREPARE}}".
+ * 预计算用户团队月业绩
+ *
+ * @property string $ID
+ * @property string $USER_ID 会员ID
+ * @property string $LAST_DEC_LV 结算时会员级别
+ * @property string $LAST_EMP_LV 结算时会员聘级
+ * @property int $LAST_STATUS 结算时会有状态
+ * @property string $FX_AMOUNT_CASH 复消现金金额
+ * @property string $PV_PCS 个人消费
+ * @property string $PV_PCS_ZC 个人消费注册单
+ * @property string $PV_PCS_YH 个人消费优惠单
+ * @property string $PV_PCS_ZG 个人消费增购单
+ * @property string $PV_PCS_LS 个人消费零售单
+ * @property string $PV_PCS_FX 个人消费复销单
+ * @property string $PV_PCS_FX_CASH 现金复消
+ * @property string $PV_PCS_FX_POINT 积分复消
+ * @property string $PV_1L 一市场业绩
+ * @property string $PV_1L_TOUCH 一市场对碰业绩
+ * @property string $PV_1L_ZC
+ * @property string $PV_1L_YH
+ * @property string $PV_1L_ZG
+ * @property string $PV_1L_LS
+ * @property string $PV_1L_FX
+ * @property string $PV_2L 二市场业绩
+ * @property string $PV_2L_TOUCH 二市场对碰业绩
+ * @property string $PV_2L_ZC
+ * @property string $PV_2L_YH
+ * @property string $PV_2L_ZG
+ * @property string $PV_2L_LS
+ * @property string $PV_2L_FX
+ * @property string $PV_3L 三市场业绩
+ * @property string $PV_3L_TOUCH 三市场对碰业绩
+ * @property string $PV_3L_ZC
+ * @property string $PV_3L_YH
+ * @property string $PV_3L_ZG
+ * @property string $PV_3L_LS
+ * @property string $PV_3L_FX
+ * @property string $PV_4L 四市场业绩
+ * @property string $PV_4L_TOUCH 四市场对碰业绩
+ * @property string $PV_4L_ZC
+ * @property string $PV_4L_YH
+ * @property string $PV_4L_ZG
+ * @property string $PV_4L_LS
+ * @property string $PV_4L_FX
+ * @property string $PV_5L 五市场业绩
+ * @property string $PV_5L_TOUCH 五市场对碰业绩
+ * @property string $PV_5L_ZC
+ * @property string $PV_5L_YH
+ * @property string $PV_5L_ZG
+ * @property string $PV_5L_LS
+ * @property string $PV_5L_FX
+ * @property string $PV_LS_TOUCH 隐藏零售区业绩30%后的
+ * @property string $SURPLUS_1L 一市场结余业绩
+ * @property string $SURPLUS_1L_ZC 一市场首购结余业绩
+ * @property string $SURPLUS_1L_FX 一市场复消结余业绩
+ * @property string $SURPLUS_2L 二市场结余业绩
+ * @property string $SURPLUS_2L_ZC 二市场首购结余业绩
+ * @property string $SURPLUS_2L_FX 二市场复消结余业绩
+ * @property string $SURPLUS_3L 三市场结余业绩
+ * @property string $SURPLUS_3L_ZC 三市场首购结余业绩
+ * @property string $SURPLUS_3L_FX 三市场复消结余业绩
+ * @property string $SURPLUS_4L 四市场结余业绩
+ * @property string $SURPLUS_4L_ZC 四市场首购结余业绩
+ * @property string $SURPLUS_4L_FX 四市场复消结余业绩
+ * @property string $SURPLUS_5L 五市场结余业绩
+ * @property string $SURPLUS_5L_ZC 五市场首购结余业绩
+ * @property string $SURPLUS_5L_FX 五市场复消结余业绩
+ * @property string $SURPLUS_LS 零售隐藏区结余业绩
+ * @property int $PERIOD_NUM 期数
+ * @property int $CALC_MONTH 结算月YYYYMM
+ * @property string $P_CALC_MONTH 表分区日期索引
+ * @property int $CREATED_AT 创建时间
+ */
+class PerfPeriodPrepare extends \common\components\ActiveRecord
+{
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return '{{%PERF_PERIOD_PREPARE}}';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['USER_ID', 'PERIOD_NUM', 'CALC_MONTH', 'P_CALC_MONTH', 'CREATED_AT'], 'required'],
+            [['LAST_STATUS', 'PERIOD_NUM', 'CALC_MONTH', 'CREATED_AT'], 'integer'],
+            [['FX_AMOUNT_CASH', 'PV_PCS', 'PV_PCS_ZC', 'PV_PCS_YH', 'PV_PCS_ZG', 'PV_PCS_LS', 'PV_PCS_FX', 'PV_PCS_FX_CASH', 'PV_PCS_FX_POINT', 'PV_1L', 'PV_1L_TOUCH', 'PV_1L_ZC', 'PV_1L_YH', 'PV_1L_ZG', 'PV_1L_LS', 'PV_1L_FX', 'PV_2L', 'PV_2L_TOUCH', 'PV_2L_ZC', 'PV_2L_YH', 'PV_2L_ZG', 'PV_2L_LS', 'PV_2L_FX', 'PV_3L', 'PV_3L_TOUCH', 'PV_3L_ZC', 'PV_3L_YH', 'PV_3L_ZG', 'PV_3L_LS', 'PV_3L_FX', 'PV_4L', 'PV_4L_TOUCH', 'PV_4L_ZC', 'PV_4L_YH', 'PV_4L_ZG', 'PV_4L_LS', 'PV_4L_FX', 'PV_5L', 'PV_5L_TOUCH', 'PV_5L_ZC', 'PV_5L_YH', 'PV_5L_ZG', 'PV_5L_LS', 'PV_5L_FX', 'PV_LS_TOUCH', 'SURPLUS_1L', 'SURPLUS_1L_ZC', 'SURPLUS_1L_FX', 'SURPLUS_2L', 'SURPLUS_2L_ZC', 'SURPLUS_2L_FX', 'SURPLUS_3L', 'SURPLUS_3L_ZC', 'SURPLUS_3L_FX', 'SURPLUS_4L', 'SURPLUS_4L_ZC', 'SURPLUS_4L_FX', 'SURPLUS_5L', 'SURPLUS_5L_ZC', 'SURPLUS_5L_FX', 'SURPLUS_LS'], 'number'],
+            [['ID', 'USER_ID', 'LAST_DEC_LV', 'LAST_EMP_LV'], 'string', 'max' => 32],
+            [['P_CALC_MONTH'], 'safe'],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'USER_ID' => '会员ID',
+            'LAST_DEC_LV' => '结算时会员级别',
+            'LAST_EMP_LV' => '结算时会员聘级',
+            'LAST_STATUS' => '结算时会有状态',
+            'FX_AMOUNT_CASH' => '复消现金金额',
+            'PV_PCS' => '个人消费',
+            'PV_PCS_ZC' => '个人消费注册单',
+            'PV_PCS_YH' => '个人消费优惠单',
+            'PV_PCS_ZG' => '个人消费增购单',
+            'PV_PCS_LS' => '个人消费零售单',
+            'PV_PCS_FX' => '个人消费复销单',
+            'PV_PCS_FX_CASH' => '现金复消',
+            'PV_PCS_FX_POINT' => '积分复消',
+            'PV_1L' => '一市场业绩',
+            'PV_1L_TOUCH' => '一市场对碰业绩',
+            'PV_1L_ZC' => 'Pv 1 L  Zc',
+            'PV_1L_YH' => 'Pv 1 L  Yh',
+            'PV_1L_ZG' => 'Pv 1 L  Zg',
+            'PV_1L_LS' => 'Pv 1 L  Ls',
+            'PV_1L_FX' => 'Pv 1 L  Fx',
+            'PV_2L' => '二市场业绩',
+            'PV_2L_TOUCH' => '二市场对碰业绩',
+            'PV_2L_ZC' => 'Pv 2 L  Zc',
+            'PV_2L_YH' => 'Pv 2 L  Yh',
+            'PV_2L_ZG' => 'Pv 2 L  Zg',
+            'PV_2L_LS' => 'Pv 2 L  Ls',
+            'PV_2L_FX' => 'Pv 2 L  Fx',
+            'PV_3L' => '三市场业绩',
+            'PV_3L_TOUCH' => '三市场对碰业绩',
+            'PV_3L_ZC' => 'Pv 3 L  Zc',
+            'PV_3L_YH' => 'Pv 3 L  Yh',
+            'PV_3L_ZG' => 'Pv 3 L  Zg',
+            'PV_3L_LS' => 'Pv 3 L  Ls',
+            'PV_3L_FX' => 'Pv 3 L  Fx',
+            'PV_4L' => '四市场业绩',
+            'PV_4L_TOUCH' => '四市场对碰业绩',
+            'PV_4L_ZC' => 'Pv 4 L  Zc',
+            'PV_4L_YH' => 'Pv 4 L  Yh',
+            'PV_4L_ZG' => 'Pv 4 L  Zg',
+            'PV_4L_LS' => 'Pv 4 L  Ls',
+            'PV_4L_FX' => 'Pv 4 L  Fx',
+            'PV_5L' => '五市场业绩',
+            'PV_5L_TOUCH' => '五市场对碰业绩',
+            'PV_5L_ZC' => 'Pv 5 L  Zc',
+            'PV_5L_YH' => 'Pv 5 L  Yh',
+            'PV_5L_ZG' => 'Pv 5 L  Zg',
+            'PV_5L_LS' => 'Pv 5 L  Ls',
+            'PV_5L_FX' => 'Pv 5 L  Fx',
+            'PV_LS_TOUCH' => '隐藏零售区业绩30%后的',
+            'SURPLUS_1L' => '一市场结余业绩',
+            'SURPLUS_1L_ZC' => '一市场首购结余业绩',
+            'SURPLUS_1L_FX' => '一市场复消结余业绩',
+            'SURPLUS_2L' => '二市场结余业绩',
+            'SURPLUS_2L_ZC' => '二市场首购结余业绩',
+            'SURPLUS_2L_FX' => '二市场复消结余业绩',
+            'SURPLUS_3L' => '三市场结余业绩',
+            'SURPLUS_3L_ZC' => '三市场首购结余业绩',
+            'SURPLUS_3L_FX' => '三市场复消结余业绩',
+            'SURPLUS_4L' => '四市场结余业绩',
+            'SURPLUS_4L_ZC' => '四市场首购结余业绩',
+            'SURPLUS_4L_FX' => '四市场复消结余业绩',
+            'SURPLUS_5L' => '五市场结余业绩',
+            'SURPLUS_5L_ZC' => '五市场首购结余业绩',
+            'SURPLUS_5L_FX' => '五市场复消结余业绩',
+            'SURPLUS_LS' => '零售隐藏区结余业绩',
+            'PERIOD_NUM' => '期数',
+            'CALC_MONTH' => '结算月YYYYMM',
+            'P_CALC_MONTH' => '表分区日期索引',
+            'CREATED_AT' => '创建时间',
+        ];
+    }
+
+    /**
+     * 操作日志记录条件
+     * @return array
+     */
+    public function attrLabelsWithLogType(){
+        return [
+            'USER_ID' => '会员ID',
+            'SURPLUS_1L' => '一市场结余业绩',
+            'SURPLUS_2L' => '二市场结余业绩',
+            'SURPLUS_3L' => '三市场结余业绩',
+            'SURPLUS_4L' => '四市场结余业绩',
+            'SURPLUS_5L' => '五市场结余业绩',
+            'SURPLUS_LS' => '虚拟零售区结余业绩',
+        ];
+    }
+
+    /**
+     * 获取期结余业绩
+     * @param $periodNum
+     * @param $userId
+     * @return array|\yii\db\ActiveRecord|null
+     * @throws \yii\db\Exception
+     */
+    public static function getPeriodSurplusPerf($periodNum, $userId){
+        $period = Period::instance();
+        $yearMonth = $period->getYearMonth($periodNum);
+        $result = static::findUseDbCalc()->yearMonth($yearMonth)->select('SURPLUS_1L,SURPLUS_2L,SURPLUS_3L,SURPLUS_4L,SURPLUS_5L,SURPLUS_LS')->where('USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [':USER_ID'=>$userId, ':PERIOD_NUM'=>$periodNum])->asArray()->one();
+        if(!$result){
+            $result = [
+                'USER_ID' => $userId,
+                'SURPLUS_1L' => 0,
+                'SURPLUS_2L' => 0,
+                'SURPLUS_3L' => 0,
+                'SURPLUS_4L' => 0,
+                'SURPLUS_5L' => 0,
+                'SURPLUS_LS' => 0,
+            ];
+        }
+
+        return $result;
+    }
+}

+ 155 - 0
common/models/PeriodPrepare.php

@@ -0,0 +1,155 @@
+<?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' => '创建时间',
+        ];
+    }
+
+    // 获取此业绩是否已计算完成,只有计算完成,计算完成才给用户展示
+    public static function isPerfed($periodNum) {
+        $result = PeriodPrepare::findUseSlaves()
+        ->where(
+            'PERIOD_NUM=:PERIOD_NUM ', [':PERIOD_NUM' => $periodNum]
+        )
+        ->asArray()
+        ->one();
+
+        if (isset($result['IS_PERFED']) && $result['IS_PERFED'] == 1) {
+            return true;
+        }
+
+        return false;
+    }
+
+    // 根据业绩期获取数据信息
+    public static function getInfo($periodNum) {
+        $result = PeriodPrepare::findUseSlaves()
+        ->where(
+            'PERIOD_NUM=:PERIOD_NUM ', [':PERIOD_NUM' => $periodNum]
+        )
+        ->asArray()
+        ->one();
+
+        return $result;
+    }
+}

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

+ 245 - 0
frontendEle/src/views/bonus/teams.vue

@@ -0,0 +1,245 @@
+<template>
+  <div v-loading="loading">
+    <el-table
+    border
+    :data="userData"
+    style="width: 100%"
+    :cell-style="tableCellStyle"
+    >
+    <el-table-column label="个人情况">
+      <el-table-column
+      type="index"
+      :index="indexMethod"
+          width="60px"
+          label=""
+          >
+        </el-table-column>
+        <el-table-column
+          prop="number"
+          label="会员编号"
+          >
+        </el-table-column>
+        <el-table-column
+          prop="name"
+          label="会员姓名"
+          >
+        </el-table-column>
+        <el-table-column
+          prop="perf_status_name"
+          label="状态"
+          >
+        </el-table-column>
+        <el-table-column
+          prop="user_perf"
+          label="业绩"
+          >
+        </el-table-column>
+         <el-table-column
+          prop="team_perf"
+          label="累计业绩"
+          >
+        </el-table-column>
+         <el-table-column
+          prop="total_perf"
+          label="合计"
+          >
+        </el-table-column>
+      </el-table-column>
+
+  </el-table>
+
+  <el-table
+    border
+    :data="tableData"
+    style="width: 100%;margin-top:20px;"
+    :cell-style="tableCellStyle"
+   >
+    <el-table-column label="团队情况">
+      <el-table-column
+      type="index"
+      :index="indexMethod"
+          width="60px"
+          label=""
+          >
+        </el-table-column>
+         <el-table-column
+          prop="number"
+          label="会员编号"
+          >
+        </el-table-column>
+        <el-table-column
+          prop="name"
+          label="会员姓名"
+          >
+        </el-table-column>
+        <el-table-column
+          class="dsdd"
+          prop="perf_status_name"
+          label="状态"
+          >
+        </el-table-column>
+        <el-table-column
+          prop="user_perf"
+          label="业绩"
+          >
+        </el-table-column>
+         <el-table-column
+          prop="team_perf"
+          label="累计业绩"
+          >
+        </el-table-column>
+         <el-table-column
+          prop="total_perf"
+          label="合计"
+          >
+        </el-table-column>
+      </el-table-column>
+
+  </el-table>
+  <el-descriptions  :column="2"  >
+  <el-descriptions-item label="最新计算时间" >{{calcTime}}</el-descriptions-item>
+</el-descriptions>
+  </div>
+</template>
+
+<script>
+  import network from '@/utils/network'
+  import tool from '@/utils/tool'
+  import Pagination from '@/components/Pagination'
+
+  export default {
+    name: 'bonus_teams',
+    components: {Pagination},
+    mounted() {
+      this.getData()
+    },
+    data() {
+      return {
+        calcTime:'',
+        userData:[],
+        tableData: [],
+        allData: null,
+        walletData: null,
+        dealSwitch: null,
+        loading: true,
+        dialogFlowVisible:false,
+        currentPage: 1,
+        totalPages: 1,
+        totalCount: 1,
+        pageSize: 20,
+        walletType: 'bonus',
+        walletName: '',
+        dialogLoading: false,
+        tool: tool,
+        createAt: '',
+        dealType: null,
+        remark: '',
+        dealTypes: [],
+      }
+    },
+    methods: {
+      tableCellStyle({row,column,rowIndex,columnIndex}) {
+        // console.log(row,column,rowIndex,columnIndex)
+        if (row.perf_status == '0' && columnIndex == '3') {
+            return "background-color:rgb(225, 25, 98);font-weight:bold";
+        } else if (row.perf_status == '1' && columnIndex == '3') {
+            return "background-color:rgb(31, 156, 18);font-weight:bold";
+        }
+        
+      },
+      indexMethod(index) {
+        return index + 1;
+      },
+      getData() {
+        let vueObj = this
+        vueObj.loading = true
+        network.getData('bonus/teams').then(response => {
+          this.userData = response.user
+          this.tableData = response.team
+          this.calcTime = response.calcAt
+          vueObj.loading = false
+        }).catch(response => {
+          vueObj.loading = false
+        })
+      },
+      showFlow(walletType,walletName){
+        let vueObj = this
+        this.$message({
+          message: '正在获取数据',
+          type: 'info'
+        })
+        this.walletType = walletType
+        this.walletName = walletName
+        vueObj.dialogFlowVisible = true
+        vueObj.dialogLoading = true
+        this.handleFilterClear()
+      },
+    }
+  }
+
+</script>
+<style scoped>
+  .leo-filter {
+    padding: 0 0 15px 0;
+  }
+
+  .leo-filter .filter-hidden {
+    display: none;
+  }
+
+  .filter-item {
+    margin-right: 10px;
+  }
+
+  @media (min-width: 768px) {
+    .leo-filter {
+    }
+
+    .leo-filter .filter-item {
+      display: inline-block;
+      max-width: 200px;
+    }
+
+    .leo-filter .filter-item.filter-date-month-picker {
+      display: inline-block;
+      max-width: 220px;
+    }
+
+    .leo-filter .filter-item.filter-date-range-picker {
+      display: inline-block;
+      max-width: 380px;
+    }
+
+    .leo-filter .filter-item.filter-filter-btn {
+      height: 38px;
+      width: 80px;
+    }
+
+    .leo-filter .filter-hidden {
+      display: none;
+    }
+  }
+</style>
+<style scoped>
+  .dialog-footer:after{content: '';
+    clear: both;display: table;}
+
+ 
+  .el-table .warning-row {
+    background: oldlace;
+  }
+
+  .el-table .success-row {
+    background: #f0f9eb;
+      /* color:rgb(225, 25, 98)   */
+  }
+.el-descriptions {
+  margin-top:20px;
+}
+/deep/ .el-descriptions-item__container {
+  margin-top:10px;
+}
+/deep/ .el-descriptions-item__label.has-colon {
+  margin-left:10px;
+}  
+</style>

+ 352 - 0
vendor/composer/InstalledVersions.php

@@ -0,0 +1,352 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+    /**
+     * @var mixed[]|null
+     * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
+     */
+    private static $installed;
+
+    /**
+     * @var bool|null
+     */
+    private static $canGetVendors;
+
+    /**
+     * @var array[]
+     * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    private static $installedByVendor = array();
+
+    /**
+     * Returns a list of all package names which are present, either by being installed, replaced or provided
+     *
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackages()
+    {
+        $packages = array();
+        foreach (self::getInstalled() as $installed) {
+            $packages[] = array_keys($installed['versions']);
+        }
+
+        if (1 === \count($packages)) {
+            return $packages[0];
+        }
+
+        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+    }
+
+    /**
+     * Returns a list of all package names with a specific type e.g. 'library'
+     *
+     * @param  string   $type
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackagesByType($type)
+    {
+        $packagesByType = array();
+
+        foreach (self::getInstalled() as $installed) {
+            foreach ($installed['versions'] as $name => $package) {
+                if (isset($package['type']) && $package['type'] === $type) {
+                    $packagesByType[] = $name;
+                }
+            }
+        }
+
+        return $packagesByType;
+    }
+
+    /**
+     * Checks whether the given package is installed
+     *
+     * This also returns true if the package name is provided or replaced by another package
+     *
+     * @param  string $packageName
+     * @param  bool   $includeDevRequirements
+     * @return bool
+     */
+    public static function isInstalled($packageName, $includeDevRequirements = true)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (isset($installed['versions'][$packageName])) {
+                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the given package satisfies a version constraint
+     *
+     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+     *
+     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+     *
+     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
+     * @param  string        $packageName
+     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+     * @return bool
+     */
+    public static function satisfies(VersionParser $parser, $packageName, $constraint)
+    {
+        $constraint = $parser->parseConstraints($constraint);
+        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+        return $provided->matches($constraint);
+    }
+
+    /**
+     * Returns a version constraint representing all the range(s) which are installed for a given package
+     *
+     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+     * whether a given version of a package is installed, and not just whether it exists
+     *
+     * @param  string $packageName
+     * @return string Version constraint usable with composer/semver
+     */
+    public static function getVersionRanges($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            $ranges = array();
+            if (isset($installed['versions'][$packageName]['pretty_version'])) {
+                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+            }
+            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+            }
+            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+            }
+            if (array_key_exists('provided', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+            }
+
+            return implode(' || ', $ranges);
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getPrettyVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['pretty_version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+     */
+    public static function getReference($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['reference'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['reference'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+     */
+    public static function getInstallPath($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @return array
+     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
+     */
+    public static function getRootPackage()
+    {
+        $installed = self::getInstalled();
+
+        return $installed[0]['root'];
+    }
+
+    /**
+     * Returns the raw installed.php data for custom implementations
+     *
+     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+     * @return array[]
+     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
+     */
+    public static function getRawData()
+    {
+        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = include __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        return self::$installed;
+    }
+
+    /**
+     * Returns the raw data of all installed.php which are currently loaded for custom implementations
+     *
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    public static function getAllRawData()
+    {
+        return self::getInstalled();
+    }
+
+    /**
+     * Lets you reload the static array from another file
+     *
+     * This is only useful for complex integrations in which a project needs to use
+     * this class but then also needs to execute another project's autoloader in process,
+     * and wants to ensure both projects have access to their version of installed.php.
+     *
+     * A typical case would be PHPUnit, where it would need to make sure it reads all
+     * the data it needs from this class, then call reload() with
+     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+     * the project in which it runs can then also use this class safely, without
+     * interference between PHPUnit's dependencies and the project's dependencies.
+     *
+     * @param  array[] $data A vendor/composer/installed.php data set
+     * @return void
+     *
+     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
+     */
+    public static function reload($data)
+    {
+        self::$installed = $data;
+        self::$installedByVendor = array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    private static function getInstalled()
+    {
+        if (null === self::$canGetVendors) {
+            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+        }
+
+        $installed = array();
+
+        if (self::$canGetVendors) {
+            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+                if (isset(self::$installedByVendor[$vendorDir])) {
+                    $installed[] = self::$installedByVendor[$vendorDir];
+                } elseif (is_file($vendorDir.'/composer/installed.php')) {
+                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+                        self::$installed = $installed[count($installed) - 1];
+                    }
+                }
+            }
+        }
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = require __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+        $installed[] = self::$installed;
+
+        return $installed;
+    }
+}

+ 851 - 0
vendor/composer/installed.php

@@ -0,0 +1,851 @@
+<?php return array(
+    'root' => array(
+        'pretty_version' => '1.0.0+no-version-set',
+        'version' => '1.0.0.0',
+        'type' => 'project',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'reference' => NULL,
+        'name' => 'yiisoft/yii2-app-advanced',
+        'dev' => true,
+    ),
+    'versions' => array(
+        'anlity/yii2-swoole-async-timer' => array(
+            'pretty_version' => '0.9.2',
+            'version' => '0.9.2.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../anlity/yii2-swoole-async-timer',
+            'aliases' => array(),
+            'reference' => '60bb70e0e34951d5aa46b89fa224f471f68e666d',
+            'dev_requirement' => false,
+        ),
+        'behat/gherkin' => array(
+            'pretty_version' => 'v4.9.0',
+            'version' => '4.9.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../behat/gherkin',
+            'aliases' => array(),
+            'reference' => '0bc8d1e30e96183e4f36db9dc79caead300beff4',
+            'dev_requirement' => true,
+        ),
+        'bower-asset/bootstrap' => array(
+            'pretty_version' => 'v3.3.7',
+            'version' => '3.3.7.0',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/bootstrap',
+            'aliases' => array(),
+            'reference' => '0b9c4a4007c44201dce9a6cc1a38407005c26c86',
+            'dev_requirement' => false,
+        ),
+        'bower-asset/inputmask' => array(
+            'pretty_version' => '3.3.11',
+            'version' => '3.3.11.0',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/inputmask',
+            'aliases' => array(),
+            'reference' => '5e670ad62f50c738388d4dcec78d2888505ad77b',
+            'dev_requirement' => false,
+        ),
+        'bower-asset/jquery' => array(
+            'pretty_version' => '3.2.1',
+            'version' => '3.2.1.0',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/jquery',
+            'aliases' => array(),
+            'reference' => '77d2a51d0520d2ee44173afdf4e40a9201f5964e',
+            'dev_requirement' => false,
+        ),
+        'bower-asset/punycode' => array(
+            'pretty_version' => 'v1.3.2',
+            'version' => '1.3.2.0',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/punycode',
+            'aliases' => array(),
+            'reference' => '38c8d3131a82567bfef18da09f7f4db68c84f8a3',
+            'dev_requirement' => false,
+        ),
+        'bower-asset/typeahead.js' => array(
+            'pretty_version' => 'v0.11.1',
+            'version' => '0.11.1.0',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/typeahead.js',
+            'aliases' => array(),
+            'reference' => '588440f66559714280628a4f9799f0c4eb880a4a',
+            'dev_requirement' => true,
+        ),
+        'bower-asset/yii2-pjax' => array(
+            'pretty_version' => '2.0.7.1',
+            'version' => '2.0.7.1',
+            'type' => 'bower-asset',
+            'install_path' => __DIR__ . '/../bower-asset/yii2-pjax',
+            'aliases' => array(),
+            'reference' => 'aef7b953107264f00234902a3880eb50dafc48be',
+            'dev_requirement' => false,
+        ),
+        'cebe/markdown' => array(
+            'pretty_version' => '1.2.1',
+            'version' => '1.2.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../cebe/markdown',
+            'aliases' => array(),
+            'reference' => '9bac5e971dd391e2802dca5400bbeacbaea9eb86',
+            'dev_requirement' => false,
+        ),
+        'codeception/base' => array(
+            'pretty_version' => '2.5.6',
+            'version' => '2.5.6.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../codeception/base',
+            'aliases' => array(),
+            'reference' => 'aace5bab5593c93d8473b620f70754135a1eb4f0',
+            'dev_requirement' => true,
+        ),
+        'codeception/phpunit-wrapper' => array(
+            'pretty_version' => '7.8.2',
+            'version' => '7.8.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../codeception/phpunit-wrapper',
+            'aliases' => array(),
+            'reference' => 'cafed18048826790c527843f9b85e8cc79b866f1',
+            'dev_requirement' => true,
+        ),
+        'codeception/stub' => array(
+            'pretty_version' => '2.1.0',
+            'version' => '2.1.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../codeception/stub',
+            'aliases' => array(),
+            'reference' => '853657f988942f7afb69becf3fd0059f192c705a',
+            'dev_requirement' => true,
+        ),
+        'codeception/verify' => array(
+            'pretty_version' => '0.3.3',
+            'version' => '0.3.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../codeception/verify',
+            'aliases' => array(),
+            'reference' => '5d649dda453cd814dadc4bb053060cd2c6bb4b4c',
+            'dev_requirement' => true,
+        ),
+        'doctrine/instantiator' => array(
+            'pretty_version' => '1.4.0',
+            'version' => '1.4.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../doctrine/instantiator',
+            'aliases' => array(),
+            'reference' => 'd56bf6102915de5702778fe20f2de3b2fe570b5b',
+            'dev_requirement' => true,
+        ),
+        'doctrine/lexer' => array(
+            'pretty_version' => '1.2.1',
+            'version' => '1.2.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../doctrine/lexer',
+            'aliases' => array(),
+            'reference' => 'e864bbf5904cb8f5bb334f99209b48018522f042',
+            'dev_requirement' => false,
+        ),
+        'egulias/email-validator' => array(
+            'pretty_version' => '3.1.2',
+            'version' => '3.1.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../egulias/email-validator',
+            'aliases' => array(),
+            'reference' => 'ee0db30118f661fb166bcffbf5d82032df484697',
+            'dev_requirement' => false,
+        ),
+        'ezyang/htmlpurifier' => array(
+            'pretty_version' => 'v4.13.0',
+            'version' => '4.13.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
+            'aliases' => array(),
+            'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
+            'dev_requirement' => false,
+        ),
+        'fakerphp/faker' => array(
+            'pretty_version' => 'v1.17.0',
+            'version' => '1.17.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../fakerphp/faker',
+            'aliases' => array(),
+            'reference' => 'b85e9d44eae8c52cca7aa0939483611f7232b669',
+            'dev_requirement' => true,
+        ),
+        'godruoyi/php-snowflake' => array(
+            'pretty_version' => '1.1.1',
+            'version' => '1.1.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../godruoyi/php-snowflake',
+            'aliases' => array(),
+            'reference' => 'd8cbe72ed375b45033b7042e3d03340ce4fa479f',
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/psr7' => array(
+            'pretty_version' => '1.8.3',
+            'version' => '1.8.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/psr7',
+            'aliases' => array(),
+            'reference' => '1afdd860a2566ed3c2b0b4a3de6e23434a79ec85',
+            'dev_requirement' => true,
+        ),
+        'maennchen/zipstream-php' => array(
+            'pretty_version' => '2.1.0',
+            'version' => '2.1.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../maennchen/zipstream-php',
+            'aliases' => array(),
+            'reference' => 'c4c5803cc1f93df3d2448478ef79394a5981cc58',
+            'dev_requirement' => false,
+        ),
+        'markbaker/complex' => array(
+            'pretty_version' => '3.0.1',
+            'version' => '3.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../markbaker/complex',
+            'aliases' => array(),
+            'reference' => 'ab8bc271e404909db09ff2d5ffa1e538085c0f22',
+            'dev_requirement' => false,
+        ),
+        'markbaker/matrix' => array(
+            'pretty_version' => '3.0.0',
+            'version' => '3.0.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../markbaker/matrix',
+            'aliases' => array(),
+            'reference' => 'c66aefcafb4f6c269510e9ac46b82619a904c576',
+            'dev_requirement' => false,
+        ),
+        'myclabs/deep-copy' => array(
+            'pretty_version' => '1.10.2',
+            'version' => '1.10.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../myclabs/deep-copy',
+            'aliases' => array(),
+            'reference' => '776f831124e9c62e1a2c601ecc52e776d8bb7220',
+            'dev_requirement' => true,
+            'replaced' => array(
+                0 => '1.10.2',
+            ),
+        ),
+        'myclabs/php-enum' => array(
+            'pretty_version' => '1.8.3',
+            'version' => '1.8.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../myclabs/php-enum',
+            'aliases' => array(),
+            'reference' => 'b942d263c641ddb5190929ff840c68f78713e937',
+            'dev_requirement' => false,
+        ),
+        'paragonie/random_compat' => array(
+            'pretty_version' => 'v9.99.100',
+            'version' => '9.99.100.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../paragonie/random_compat',
+            'aliases' => array(),
+            'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
+            'dev_requirement' => false,
+        ),
+        'phar-io/manifest' => array(
+            'pretty_version' => '1.0.3',
+            'version' => '1.0.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phar-io/manifest',
+            'aliases' => array(),
+            'reference' => '7761fcacf03b4d4f16e7ccb606d4879ca431fcf4',
+            'dev_requirement' => true,
+        ),
+        'phar-io/version' => array(
+            'pretty_version' => '2.0.1',
+            'version' => '2.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phar-io/version',
+            'aliases' => array(),
+            'reference' => '45a2ec53a73c70ce41d55cedef9063630abaf1b6',
+            'dev_requirement' => true,
+        ),
+        'phpdocumentor/reflection-common' => array(
+            'pretty_version' => '2.2.0',
+            'version' => '2.2.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpdocumentor/reflection-common',
+            'aliases' => array(),
+            'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b',
+            'dev_requirement' => true,
+        ),
+        'phpdocumentor/reflection-docblock' => array(
+            'pretty_version' => '5.3.0',
+            'version' => '5.3.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock',
+            'aliases' => array(),
+            'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170',
+            'dev_requirement' => true,
+        ),
+        'phpdocumentor/type-resolver' => array(
+            'pretty_version' => '1.5.1',
+            'version' => '1.5.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpdocumentor/type-resolver',
+            'aliases' => array(),
+            'reference' => 'a12f7e301eb7258bb68acd89d4aefa05c2906cae',
+            'dev_requirement' => true,
+        ),
+        'phpoffice/phpspreadsheet' => array(
+            'pretty_version' => '1.20.0',
+            'version' => '1.20.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
+            'aliases' => array(),
+            'reference' => '44436f270bb134b4a94670f3d020a85dfa0a3c02',
+            'dev_requirement' => false,
+        ),
+        'phpspec/php-diff' => array(
+            'pretty_version' => 'v1.1.3',
+            'version' => '1.1.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpspec/php-diff',
+            'aliases' => array(),
+            'reference' => 'fc1156187f9f6c8395886fe85ed88a0a245d72e9',
+            'dev_requirement' => true,
+        ),
+        'phpspec/prophecy' => array(
+            'pretty_version' => 'v1.15.0',
+            'version' => '1.15.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpspec/prophecy',
+            'aliases' => array(),
+            'reference' => 'bbcd7380b0ebf3961ee21409db7b38bc31d69a13',
+            'dev_requirement' => true,
+        ),
+        'phpunit/php-code-coverage' => array(
+            'pretty_version' => '6.1.4',
+            'version' => '6.1.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/php-code-coverage',
+            'aliases' => array(),
+            'reference' => '807e6013b00af69b6c5d9ceb4282d0393dbb9d8d',
+            'dev_requirement' => true,
+        ),
+        'phpunit/php-file-iterator' => array(
+            'pretty_version' => '2.0.5',
+            'version' => '2.0.5.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/php-file-iterator',
+            'aliases' => array(),
+            'reference' => '42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5',
+            'dev_requirement' => true,
+        ),
+        'phpunit/php-text-template' => array(
+            'pretty_version' => '1.2.1',
+            'version' => '1.2.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/php-text-template',
+            'aliases' => array(),
+            'reference' => '31f8b717e51d9a2afca6c9f046f5d69fc27c8686',
+            'dev_requirement' => true,
+        ),
+        'phpunit/php-timer' => array(
+            'pretty_version' => '2.1.3',
+            'version' => '2.1.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/php-timer',
+            'aliases' => array(),
+            'reference' => '2454ae1765516d20c4ffe103d85a58a9a3bd5662',
+            'dev_requirement' => true,
+        ),
+        'phpunit/php-token-stream' => array(
+            'pretty_version' => '3.1.3',
+            'version' => '3.1.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/php-token-stream',
+            'aliases' => array(),
+            'reference' => '9c1da83261628cb24b6a6df371b6e312b3954768',
+            'dev_requirement' => true,
+        ),
+        'phpunit/phpunit' => array(
+            'pretty_version' => '7.5.20',
+            'version' => '7.5.20.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpunit/phpunit',
+            'aliases' => array(),
+            'reference' => '9467db479d1b0487c99733bb1e7944d32deded2c',
+            'dev_requirement' => true,
+        ),
+        'psr/container' => array(
+            'pretty_version' => '1.1.2',
+            'version' => '1.1.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/container',
+            'aliases' => array(),
+            'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
+            'dev_requirement' => true,
+        ),
+        'psr/event-dispatcher-implementation' => array(
+            'dev_requirement' => true,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/http-client' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-client',
+            'aliases' => array(),
+            'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
+            'dev_requirement' => false,
+        ),
+        'psr/http-factory' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-factory',
+            'aliases' => array(),
+            'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
+            'dev_requirement' => false,
+        ),
+        'psr/http-message' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-message',
+            'aliases' => array(),
+            'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
+            'dev_requirement' => false,
+        ),
+        'psr/http-message-implementation' => array(
+            'dev_requirement' => true,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/log-implementation' => array(
+            'dev_requirement' => true,
+            'provided' => array(
+                0 => '1.0|2.0',
+            ),
+        ),
+        'psr/simple-cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/simple-cache',
+            'aliases' => array(),
+            'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
+            'dev_requirement' => false,
+        ),
+        'ralouphie/getallheaders' => array(
+            'pretty_version' => '3.0.3',
+            'version' => '3.0.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ralouphie/getallheaders',
+            'aliases' => array(),
+            'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+            'dev_requirement' => true,
+        ),
+        'sebastian/code-unit-reverse-lookup' => array(
+            'pretty_version' => '1.0.2',
+            'version' => '1.0.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup',
+            'aliases' => array(),
+            'reference' => '1de8cd5c010cb153fcd68b8d0f64606f523f7619',
+            'dev_requirement' => true,
+        ),
+        'sebastian/comparator' => array(
+            'pretty_version' => '3.0.3',
+            'version' => '3.0.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/comparator',
+            'aliases' => array(),
+            'reference' => '1071dfcef776a57013124ff35e1fc41ccd294758',
+            'dev_requirement' => true,
+        ),
+        'sebastian/diff' => array(
+            'pretty_version' => '3.0.3',
+            'version' => '3.0.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/diff',
+            'aliases' => array(),
+            'reference' => '14f72dd46eaf2f2293cbe79c93cc0bc43161a211',
+            'dev_requirement' => true,
+        ),
+        'sebastian/environment' => array(
+            'pretty_version' => '4.2.4',
+            'version' => '4.2.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/environment',
+            'aliases' => array(),
+            'reference' => 'd47bbbad83711771f167c72d4e3f25f7fcc1f8b0',
+            'dev_requirement' => true,
+        ),
+        'sebastian/exporter' => array(
+            'pretty_version' => '3.1.4',
+            'version' => '3.1.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/exporter',
+            'aliases' => array(),
+            'reference' => '0c32ea2e40dbf59de29f3b49bf375176ce7dd8db',
+            'dev_requirement' => true,
+        ),
+        'sebastian/global-state' => array(
+            'pretty_version' => '2.0.0',
+            'version' => '2.0.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/global-state',
+            'aliases' => array(),
+            'reference' => 'e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4',
+            'dev_requirement' => true,
+        ),
+        'sebastian/object-enumerator' => array(
+            'pretty_version' => '3.0.4',
+            'version' => '3.0.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/object-enumerator',
+            'aliases' => array(),
+            'reference' => 'e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2',
+            'dev_requirement' => true,
+        ),
+        'sebastian/object-reflector' => array(
+            'pretty_version' => '1.1.2',
+            'version' => '1.1.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/object-reflector',
+            'aliases' => array(),
+            'reference' => '9b8772b9cbd456ab45d4a598d2dd1a1bced6363d',
+            'dev_requirement' => true,
+        ),
+        'sebastian/recursion-context' => array(
+            'pretty_version' => '3.0.1',
+            'version' => '3.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/recursion-context',
+            'aliases' => array(),
+            'reference' => '367dcba38d6e1977be014dc4b22f47a484dac7fb',
+            'dev_requirement' => true,
+        ),
+        'sebastian/resource-operations' => array(
+            'pretty_version' => '2.0.2',
+            'version' => '2.0.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/resource-operations',
+            'aliases' => array(),
+            'reference' => '31d35ca87926450c44eae7e2611d45a7a65ea8b3',
+            'dev_requirement' => true,
+        ),
+        'sebastian/version' => array(
+            'pretty_version' => '2.0.1',
+            'version' => '2.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sebastian/version',
+            'aliases' => array(),
+            'reference' => '99732be0ddb3361e16ad77b68ba41efc8e979019',
+            'dev_requirement' => true,
+        ),
+        'sunmoon/yii2-phpspreadsheet' => array(
+            'pretty_version' => '1.2.0',
+            'version' => '1.2.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sunmoon/yii2-phpspreadsheet',
+            'aliases' => array(),
+            'reference' => '51fc4d0183eb81e654b3360ac18e631fc4b89c09',
+            'dev_requirement' => false,
+        ),
+        'swiftmailer/swiftmailer' => array(
+            'pretty_version' => 'v6.3.0',
+            'version' => '6.3.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../swiftmailer/swiftmailer',
+            'aliases' => array(),
+            'reference' => '8a5d5072dca8f48460fce2f4131fcc495eec654c',
+            'dev_requirement' => false,
+        ),
+        'symfony/browser-kit' => array(
+            'pretty_version' => 'v4.4.27',
+            'version' => '4.4.27.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/browser-kit',
+            'aliases' => array(),
+            'reference' => '9629d1524d8ced5a4ec3e94abdbd638b4ec8319b',
+            'dev_requirement' => true,
+        ),
+        'symfony/console' => array(
+            'pretty_version' => 'v4.4.34',
+            'version' => '4.4.34.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/console',
+            'aliases' => array(),
+            'reference' => '329b3a75cc6b16d435ba1b1a41df54a53382a3f0',
+            'dev_requirement' => true,
+        ),
+        'symfony/css-selector' => array(
+            'pretty_version' => 'v4.4.27',
+            'version' => '4.4.27.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/css-selector',
+            'aliases' => array(),
+            'reference' => '5194f18bd80d106f11efa8f7cd0fbdcc3af96ce6',
+            'dev_requirement' => true,
+        ),
+        'symfony/deprecation-contracts' => array(
+            'pretty_version' => 'v2.5.0',
+            'version' => '2.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
+            'aliases' => array(),
+            'reference' => '6f981ee24cf69ee7ce9736146d1c57c2780598a8',
+            'dev_requirement' => true,
+        ),
+        'symfony/dom-crawler' => array(
+            'pretty_version' => 'v4.4.30',
+            'version' => '4.4.30.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/dom-crawler',
+            'aliases' => array(),
+            'reference' => '4632ae3567746c7e915c33c67a2fb6ab746090c4',
+            'dev_requirement' => true,
+        ),
+        'symfony/event-dispatcher' => array(
+            'pretty_version' => 'v4.4.34',
+            'version' => '4.4.34.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/event-dispatcher',
+            'aliases' => array(),
+            'reference' => '1a024b45369c9d55d76b6b8a241bd20c9ea1cbd8',
+            'dev_requirement' => true,
+        ),
+        'symfony/event-dispatcher-contracts' => array(
+            'pretty_version' => 'v1.1.11',
+            'version' => '1.1.11.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
+            'aliases' => array(),
+            'reference' => '01e9a4efac0ee33a05dfdf93b346f62e7d0e998c',
+            'dev_requirement' => true,
+        ),
+        'symfony/event-dispatcher-implementation' => array(
+            'dev_requirement' => true,
+            'provided' => array(
+                0 => '1.1',
+            ),
+        ),
+        'symfony/finder' => array(
+            'pretty_version' => 'v4.4.30',
+            'version' => '4.4.30.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/finder',
+            'aliases' => array(),
+            'reference' => '70362f1e112280d75b30087c7598b837c1b468b6',
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-ctype' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
+            'aliases' => array(),
+            'reference' => '46cd95797e9df938fdd2b03693b5fca5e64b01ce',
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-iconv' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-iconv',
+            'aliases' => array(),
+            'reference' => '63b5bb7db83e5673936d6e3b8b3e022ff6474933',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-intl-idn' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
+            'aliases' => array(),
+            'reference' => '65bd267525e82759e7d8c4e8ceea44f398838e65',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-intl-normalizer' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
+            'aliases' => array(),
+            'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-mbstring' => array(
+            'pretty_version' => 'v1.23.1',
+            'version' => '1.23.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+            'aliases' => array(),
+            'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-php72' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php72',
+            'aliases' => array(),
+            'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-php73' => array(
+            'pretty_version' => 'v1.23.0',
+            'version' => '1.23.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php73',
+            'aliases' => array(),
+            'reference' => 'fba8933c384d6476ab14fb7b8526e5287ca7e010',
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-php80' => array(
+            'pretty_version' => 'v1.23.1',
+            'version' => '1.23.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+            'aliases' => array(),
+            'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
+            'dev_requirement' => true,
+        ),
+        'symfony/service-contracts' => array(
+            'pretty_version' => 'v2.5.0',
+            'version' => '2.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/service-contracts',
+            'aliases' => array(),
+            'reference' => '1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc',
+            'dev_requirement' => true,
+        ),
+        'symfony/yaml' => array(
+            'pretty_version' => 'v4.4.34',
+            'version' => '4.4.34.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/yaml',
+            'aliases' => array(),
+            'reference' => '2c309e258adeb9970229042be39b360d34986fad',
+            'dev_requirement' => true,
+        ),
+        'theseer/tokenizer' => array(
+            'pretty_version' => '1.2.1',
+            'version' => '1.2.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../theseer/tokenizer',
+            'aliases' => array(),
+            'reference' => '34a41e998c2183e22995f158c581e7b5e755ab9e',
+            'dev_requirement' => true,
+        ),
+        'webmozart/assert' => array(
+            'pretty_version' => '1.10.0',
+            'version' => '1.10.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../webmozart/assert',
+            'aliases' => array(),
+            'reference' => '6964c76c7804814a842473e0c8fd15bab0f18e25',
+            'dev_requirement' => true,
+        ),
+        'yiisoft/yii2' => array(
+            'pretty_version' => '2.0.43',
+            'version' => '2.0.43.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../yiisoft/yii2',
+            'aliases' => array(),
+            'reference' => 'f370955faa3067d9b27879aaf14b0978a805cd59',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-app-advanced' => array(
+            'pretty_version' => '1.0.0+no-version-set',
+            'version' => '1.0.0.0',
+            'type' => 'project',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'reference' => NULL,
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-bootstrap' => array(
+            'pretty_version' => '2.0.11',
+            'version' => '2.0.11.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-bootstrap',
+            'aliases' => array(),
+            'reference' => '83d144f4089adaa7064ad60dc4c1436daa2eb30e',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-composer' => array(
+            'pretty_version' => '2.0.10',
+            'version' => '2.0.10.0',
+            'type' => 'composer-plugin',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-composer',
+            'aliases' => array(),
+            'reference' => '94bb3f66e779e2774f8776d6e1bdeab402940510',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-debug' => array(
+            'pretty_version' => '2.0.14',
+            'version' => '2.0.14.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-debug',
+            'aliases' => array(),
+            'reference' => 'dc5a4a8529de1a41dbb037dbabf1f3f93002f21d',
+            'dev_requirement' => true,
+        ),
+        'yiisoft/yii2-faker' => array(
+            'pretty_version' => '2.0.5',
+            'version' => '2.0.5.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-faker',
+            'aliases' => array(),
+            'reference' => '8c361657143bfaea58ff7dcc9bf51f1991a46f5d',
+            'dev_requirement' => true,
+        ),
+        'yiisoft/yii2-gii' => array(
+            'pretty_version' => '2.0.8',
+            'version' => '2.0.8.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-gii',
+            'aliases' => array(),
+            'reference' => 'c02adc552bcf3a0ef6f3694a9dcbf209f4885ab1',
+            'dev_requirement' => true,
+        ),
+        'yiisoft/yii2-httpclient' => array(
+            'pretty_version' => '2.0.14',
+            'version' => '2.0.14.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-httpclient',
+            'aliases' => array(),
+            'reference' => '50d670d2e1a30a354c27aeebf806a2db16954836',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-mongodb' => array(
+            'pretty_version' => '2.1.12',
+            'version' => '2.1.12.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-mongodb',
+            'aliases' => array(),
+            'reference' => '4a74369a2b233f2def02579766e1eceadb8964be',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-redis' => array(
+            'pretty_version' => '2.0.16',
+            'version' => '2.0.16.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-redis',
+            'aliases' => array(),
+            'reference' => '1b9efe97d8add594256b51089fbf7a56f31e3c9c',
+            'dev_requirement' => false,
+        ),
+        'yiisoft/yii2-swiftmailer' => array(
+            'pretty_version' => '2.1.2',
+            'version' => '2.1.2.0',
+            'type' => 'yii2-extension',
+            'install_path' => __DIR__ . '/../yiisoft/yii2-swiftmailer',
+            'aliases' => array(),
+            'reference' => '09659a55959f9e64b8178d842b64a9ffae42b994',
+            'dev_requirement' => false,
+        ),
+    ),
+);

+ 26 - 0
vendor/composer/platform_check.php

@@ -0,0 +1,26 @@
+<?php
+
+// platform_check.php @generated by Composer
+
+$issues = array();
+
+if (!(PHP_VERSION_ID >= 70300)) {
+    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+    if (!headers_sent()) {
+        header('HTTP/1.1 500 Internal Server Error');
+    }
+    if (!ini_get('display_errors')) {
+        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+        } elseif (!headers_sent()) {
+            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+        }
+    }
+    trigger_error(
+        'Composer detected issues in your platform: ' . implode(' ', $issues),
+        E_USER_ERROR
+    );
+}