services->setting->addons->get($mallId, 'Boss', 'basic'); if ($config['is_enable'] == StatusEnum::ENABLED) { $continue = false; // 获取结算周期,0=天,1=周,2=月 $compute_period = $config['compute_period']; switch ($config['compute_period']) { case 1: $start_day = date("Ymd", strtotime("-1 day")); $end_day = $start_day; break; case 2: if (date('w') != 1) $continue = true;// 非周一直接退出 $start_day = date("Ymd", strtotime("last Monday")); $end_day = date('Ymd', strtotime('-1 sunday', time()));; break; case 3: if (date('d') != 1) $continue = true;// 非当月1号直接退出 $start_day = date("Ym01", strtotime("-1 month")); $end_day = date('Ymd', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400); break; case LevelEnum::PERIOD_CUSTOM_DAYS: // 没配置直接退出 if (empty($config['custom_compute_days'])) { $continue = true; break; } // 自定义天数 $custom_compute_days = (int)$config['custom_compute_days']; $latestJobDateLimit = AddonsBossCommissionJob::find() ->where(['mall_id' => $mallId, 'compute_period' => $compute_period, 'status' => StatusEnum::ENABLED]) ->orderBy('id desc') ->select('date_limit') ->scalar(); // 得到本次开始时间 $start_day = date("Ymd", strtotime("-$custom_compute_days day")); // 包含在这个时间则直接退出 if ($latestJobDateLimit) { [, $latestEndDay] = explode('-', $latestJobDateLimit); if ($latestEndDay >= $start_day) { $continue = true; break; } } $end_day = date("Ymd", strtotime("-1 day")); break; } if ($continue) continue; $date_limit = $start_day . '-' . $end_day; $job = AddonsBossCommissionJob::findOne(['mall_id' => $mallId, 'compute_period' => $compute_period, 'date_limit' => $date_limit, 'status' => StatusEnum::ENABLED]); if ($job) continue; // 生成执行记录 $job = new AddonsBossCommissionJob(); $job->mall_id = $mallId; $job->date_limit = $date_limit; $job->compute_period = $compute_period; if (!$job->save()) throw new Exception($job->getErrorMessage()); $res = $this->addCommissionLog($mallId, $config, $start_day, $end_day, $job->id); // 发放股东团队业绩奖励 $bossPerformanceLogic = new BossPerformanceLogic(); $bossPerformanceLogic->sendPerformancePrize($mallId, $config, $start_day, $end_day, $job->id); //if($res === false) throw new Exception($this->getError()); } } foreach ($mall_list as $mall){ $mallId = $mall['id']; // 获取基础配置 $config = Yii::$app->services->setting->addons->get($mallId, 'Boss', 'basic'); // 奖金池 if($config['is_enable'] == StatusEnum::ENABLED && ($config['is_prize_pool'] ?? StatusEnum::DISABLED) == StatusEnum::ENABLED){ list( 'continue' => $continue, 'start_day' => $start_day, 'end_day' => $end_day, 'compute_period' => $compute_period ) = $this->getExecutePeriod($config, 'prize_pool_period'); if ($continue) continue; $date_limit = $start_day . '-' . $end_day; $date_limit = $start_day . '-' . $end_day; $job = BossPoolPrizeJob::findOne(['mall_id' => $mallId, 'compute_period' => $compute_period, 'date_limit' => $date_limit, 'status' => StatusEnum::ENABLED]); if ($job) continue; // 生成执行记录 $job = new BossPoolPrizeJob(); $job->mall_id = $mallId; $job->date_limit = $date_limit; $job->compute_period = $compute_period; $last_period = BossPoolPrizeJob::find()->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED]) ->select('period')->orderBy('id DESC')->scalar(); $period = $last_period ? $last_period + 1 : 1; $job->period = $period; if (!$job->save()) throw new Exception($job->getErrorMessage()); $poolPrizeLogic = new PoolPrizeLogic(); $poolPrizeLogic->send($mallId, $config, $start_day, $end_day, $job->id); } } return true; } } protected function getExecutePeriod($config, $key) { $continue = false; $start_day = 0; $end_day = 0; // 获取结算周期,0=天,1=周,2=月 $compute_period = $config[$key]; switch ($config[$key]) { case 1: $start_day = date("Ymd", strtotime("-1 day")); // $start_day = date("Ymd"); $end_day = $start_day; break; case 2: if (date('w') != 1) $continue = true; // 非周一直接退出 $start_day = date("Ymd", strtotime("last Monday")); $end_day = date('Ymd', strtotime('-1 sunday', time()));; break; case 3: if (date('d') != 1) $continue = true; // 非当月1号直接退出 $start_day = date("Ym01", strtotime("-1 month")); $end_day = date('Ymd', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400); break; } return compact('continue', 'start_day', 'end_day', 'compute_period'); } /** * 增加boss分红佣金 * @Author: lun * @DateTime: 2021/11/5 0005 14:27 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mallId * @param $config * @param $start_day * @param $end_time * @return bool */ public function addCommissionLog($mallId, $config, $start_day, $end_day, $job_id = 0) { if ($config['is_enable'] == StatusEnum::DISABLED) { Yii::error('系统没有开启股东提成'); return true; } $trans = Yii::$app->db->beginTransaction(); try { // 初始化数据 $time = time(); $table_name = 'addons_boss_commission_log'; $reward = []; // 获取等级设置 $setting = AddonsBossLevelSetting::find()->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])->indexBy('level')->asArray()->all(); foreach ($setting as $level => &$item) { $item['extra_restrict_keys'] = json_decode($item['extra_restrict_keys'], true) ?? []; $item['extra_restrict_values'] = json_decode($item['extra_restrict_values'], true) ?? []; } // 检查是否开启沉淀池,并且比例不为零 $sediment_percent = !empty($config['is_sediment']) ? $config['sediment_percent'] ?? 0 : 0; $besides_price_type = [LevelEnum::DIGITAL_PRIZE, LevelEnum::EXTRA_DIGITAL_PRIZE]; // 获取分红奖励列表 $i = 1; $page_size = 1000; while ($reward_list = AddonsBossRewardLog::find()->select('user_id,sum(amounts) amounts,sum(commission) commission,type,from_type') ->where(['mall_id' => $mallId, 'is_settlement' => StatusEnum::DISABLED]) ->andFilterWhere(['between', 'date', $start_day, $end_day]) ->groupBy('user_id,type') ->offset(($i - 1) * $page_size)->limit($page_size)->asArray()->all()) { // 获取股东信息 $boss_uids = array_unique(array_column($reward_list, 'user_id')); $boss_arr = AddonsBoss::find()->select('user_id,level,created_at')->where(['user_id' => $boss_uids, 'status' => StatusEnum::ENABLED])->indexBy('user_id')->asArray()->all(); // 生成计算好的结算数据 foreach ($reward_list as $item) { if (empty($boss_arr[$item['user_id']])) continue; $user_level = $boss_arr[$item['user_id']]['level'];// 股东当前等级 if(!in_array($item['type'], $besides_price_type)){ if ($item['type'] == 2 && !empty($setting[$user_level]['extra_restrict']) && !empty($setting[$user_level]['extra_restrict_keys'])) { // 符合条件三的用户 if (in_array(2, $setting[$user_level]['extra_restrict_keys'])) { $item['commission'] = $this->restrictCond3($boss_arr[$item['user_id']], $setting[$user_level]['extra_restrict_values'][2]['value'], $time, $item['commission']); } } // 增加沉淀池数据 if ($sediment_percent) { // sediment_type[1=永久分红,2=额外分红,3=永久+额外分红] if ($config['sediment_type'] == 1 && $item['type'] == 1 || $config['sediment_type'] == 2 && $item['type'] == 2 || $config['sediment_type'] == 3) { $item['level'] = $user_level; $sediment = AddonsBossRewardLog::createSediment($mallId, $item, $sediment_percent, $job_id); $item['commission'] = $sediment['commission']; $item['sedimen_money'] = $sediment['sedimen_money']; !empty($sediment['reward']) && $reward[] = $sediment['reward']; } } } if ($item['commission'] < 0.01) continue;// 小于一分钱不允许插入数据 $rows[] = [ 'mall_id' => $mallId, 'user_id' => $item['user_id'], 'amounts' => $item['amounts'], 'commission' => $item['commission'], 'sedimen_money' => $item['sedimen_money'] ?? 0, 'type' => $item['type'], 'compute_period' => $config['compute_period'], 'start_time' => $start_day, 'end_time' => $end_day, 'created_at' => $time, 'updated_at' => $time, 'from_type' => $item['from_type'], ]; } $i++; } if (empty($rows)) throw new Exception('佣金记录为空'); // 生成数据 $field = ['mall_id','user_id','amounts','commission','sedimen_money','type','compute_period','start_time','end_time','created_at','updated_at', 'from_type']; $res = Yii::$app->db->createCommand()->batchInsert(AddonsBossCommissionLog::tableName(), $field, $rows)->execute(); if (!$res) throw new Exception('批量生成分红数据失败'); // 数据生成完成记录表修改结算状态 AddonsBossRewardLog::updateAll( ['is_settlement' => StatusEnum::ENABLED, 'updated_at' => $time], ['and', ['mall_id' => $mallId, 'is_settlement' => StatusEnum::DISABLED],['between', 'date', $start_day, $end_day]] ); // 生成沉淀池数据 if ($reward) { $field = ['mall_id','user_id','type','level','amounts','commission','settlement_config','settlement_data','is_settlement','date','created_at','updated_at']; Yii::$app->db->createCommand()->batchInsert(AddonsBossRewardLog::tableName(), $field, $reward)->execute(); } $digital_arr = []; $k = 1; $page_log = 1000; // 增加对应股东分佣金额 while ($log_list = AddonsBossCommissionLog::find()->where(['mall_id' => $mallId,'start_time' => $start_day,'end_time' => $end_day])->andWhere(['!=', 'type', LevelEnum::PERFORMANCE_PRIZE]) ->offset(($k - 1) * $page_log)->limit($page_log)->asArray()->all()) { foreach ($log_list as $item) { if(in_array($item['type'], $besides_price_type)){ $desc = $item['type'] == LevelEnum::DIGITAL_PRIZE ? '股东管理数字币永久分红' : '股东管理额外分红数字币'; $digital_arr[] = [ 'mall_id' => $mallId, 'user_id' => $item['user_id'], 'change_num' => $item['commission'], 'is_frozen' => false, 'params' => [ 'desc' => $desc, 'source_table' => $table_name, 'source_table_id' => $item['id'], 'from_type' => BossEnum::ADDONS_NAME, 'capital_type' => BossEnum::ADDONS_NAME, 'order_no' => '' ] ]; if ($item['type'] == LevelEnum::DIGITAL_PRIZE) { $boss_commission[$item['user_id']]['digital'] = $item['commission']; } else { $boss_commission[$item['user_id']]['extra_digital'] = $item['commission']; } }else{ $insert_wallet[] = [ 'mall_id' => $mallId, 'user_id' => $item['user_id'], 'is_frozen' => false, 'wallet_type' => 'commission', 'money' => $item['commission'], 'desc' => '股东分红佣金', 'source_table' => $table_name, 'source_table_id' => $item['id'], 'from_type' => BossEnum::ADDONS_NAME, 'capital_type' => $item['type'] == 1 ? UserWalletEnum::FOREVER : UserWalletEnum::BO_EXTRA, ]; if ($item['type'] == 1) { $boss_commission[$item['user_id']]['commission'] = $item['commission']; } else { $boss_commission[$item['user_id']]['extra_commission'] = $item['commission']; } } } $k++; } // 增加用户股东金额 foreach ($boss_commission as $user_id => $commission) { $boss = AddonsBoss::findOne(['mall_id' => $mallId, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED]); $boss->commission = empty($commission['commission']) ? $boss->commission : $boss->commission + $commission['commission']; $boss->extra_commission = empty($commission['extra_commission']) ? $boss->extra_commission : $boss->extra_commission + $commission['extra_commission']; $boss->total_commission = $boss->commission + $boss->extra_commission + $boss->performance_commission; $boss->digital = empty($commission['digital']) ? $boss->digital : $boss->digital + $commission['digital']; $boss->extra_digital = empty($commission['extra_digital']) ? $boss->extra_digital : $boss->extra_digital + $commission['extra_digital']; $boss->total_digital = $boss->digital + $boss->extra_digital; if (!$boss->save()) throw new \Exception($boss->getErrorMessage()); } $trans->commit(); if ($insert_wallet) { UserWalletService::batchHandleByQueue($insert_wallet); } if($digital_arr){ foreach($digital_arr as $val){ $res = UserDigital::handleUserDigital($val['mall_id'], $val['user_id'], $val['change_num'], $val['is_frozen'], $val['params']); if ($res === false) { \Yii::error(__METHOD__. '//股东定时分红赠送数字币,err:' . UserDigital::getStaticError()); } } } return true; } catch (Exception $e) { $trans->rollBack(); $exception = FormatHelper::exception($e, "mall_id={$mallId} 股东定时分红任务失败"); Yii::error($exception); $this->setError($exception); return false; } } /** * desc@股东额外分红限制条件3 * __天内最多可获得__元额外分红 * @Author: lun * @DateTime: 2022/9/13 0013 14:39 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $boss * @param $setting * @param $time * @param int $available_commission * @return int */ public function restrictCond3($boss, $setting, $time, $available_commission = 0) { $user_id = $boss['user_id']; // 获取N天的时间戳 - 增加300秒作为误差值 $end_time = $time - (86400 * $setting['day'] + 300); if ($boss['created_at'] < $end_time) return 0;// 超过N天直接没有额外收入 $original_commission = $available_commission; // 计算N天内已获得的额外分红金额 - 增加300秒作为误差值 $extra_commission = AddonsBossCommissionLog::find()->where(['user_id' => $user_id, 'type' => 2, 'status' => StatusEnum::ENABLED]) ->andWhere(['>=', 'created_at', $end_time])->sum('commission') ?? 0; // 如果N天内已获得的金额大于或等于设置金额则不再获得金额 if ($extra_commission >= $setting['money']) { $available_commission = 0; } else { $surplus_extra = $setting['money'] - $extra_commission;// 剩余可得额外分红 // 如果本次结算额外分红大于剩余可得额外分红,则最多只能获取到剩余的分红 if ($available_commission >= $surplus_extra) $available_commission = $surplus_extra; } // 将不发送额外分红的用户数据存入日志,便于查询 if ($original_commission > $available_commission) { FileHelper::writeLog($this->getLogPath('restrictCond3'), "user_id={$user_id} 本次原额外分红={$original_commission},extra_commission={$extra_commission},set_money={$setting['money']},只得到{$available_commission}元额外分红"); } return $available_commission; } protected function getLogPath($type) { return Yii::getAlias('@runtime') . "/logs/boss/" . $type . '/' . date('Y_m_d') . '.txt'; } }