db->beginTransaction(); try { $grant = AchievementGrantLog::findOne(['id' => $grant_id, 'status' => StatusEnum::ENABLED, 'is_wait' => 0]); if (empty($grant)) throw new \Exception("规则不存在"); //判断业绩奖励是否开启 $configs = \Yii::$app->services->setting->addons->get($grant['mall_id'], AddonsEnum::ADDONS_NAME_ACHIEVEMENT, 'basic'); if (empty($configs['status'])) throw new \Exception("业绩奖励没开启"); $list = AchievementAwardLog::findAll(['grant_id' => $grant_id, 'mall_id' => $grant['mall_id'], 'status' => StatusEnum::ENABLED]); $user_id_arr = array_column($list, 'user_id'); $sum_list = AchievementAwardLog::lists([ 'where' => [ ['user_id' => $user_id_arr], ['mall_id' => $grant['mall_id']], ['status' => StatusEnum::ENABLED], ['is_end' => 1] ], 'index' => 'user_id', 'group' => 'user_id', 'select' => 'sum(award_money) as money,user_id' ]); $total = 0;//总业绩 $user_num = 0; $sum_award = 0; //计算奖励 foreach ($list as $k => $v) { //统计团队业绩 $user_id = $v['user_id']; $money = 0; $offset = 1; $limit = 1000; $params['select'] = 'user_id,deep'; list($tree, $deep, $all_tree, $all_tree_arr) = UserPartitionRelationship::getTree($user_id); while ($child_list = UserPartitionRelationship::batchGetTeamData($offset, $limit, $tree, $params)) { $user_ids = array_column($child_list, 'user_id'); $team_achievement_user_list = AchievementUser::lists(['where' => [['user_id' => $user_ids], ['status' => StatusEnum::ENABLED]]]); $team_ids = array_column($team_achievement_user_list, 'user_id'); //获取到下级的所有业绩 $personal_achievement = AchievementAwardLog::find()->where(['mall_id' => $v['mall_id'], 'status' => StatusEnum::ENABLED, 'grant_id' => $grant['id']]) ->andWhere(['in', 'user_id', $team_ids])->sum('personal_achievement'); if (!empty($personal_achievement)) $money += $personal_achievement; $offset++; } $v->team_achievement += $money; $v->achievement_sum += $money; $award = self::confirmProportion($grant['award_proportion'], $v['achievement_sum'], $v['personal_achievement'], $grant['settlement_mode']); $v->award_proportion = $award['proportion']; if ($grant['settlement_mode'] == 0) { //不含极差 $v->award_money = $award['money']; $v->is_end = 1; //总计 $sum_money = 0; if (isset($sum_list[$v['user_id']])) $sum_money = $sum_list[$v['user_id']]['money']; $sum_money = $sum_money + $award['money']; $v->award_sum = $sum_money; } else { $v->parent_team = self::getParentAchievementUser($user_id); $v->proportion_money = $award['money']; } if (!$v->save()) throw new \Exception("业绩修改奖励日志失败"); $total += $v->personal_achievement; $user_num++; $sum_award += $award['money']; } if ($grant->settlement_mode == 1) $sum_award = self::planB($grant, $list, $user_id_arr);//极差 //平级奖励 $grant->total_performance = $total; $grant->user_num = $user_num; $grant->award_money = $sum_award; $grant->is_wait = 1; if (!$grant->save()) throw new \Exception("业绩修改规则日志失败"); $t->commit(); return true; } catch (Exception $e) { $t->rollBack(); \Yii::error('业绩待结算失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage()); self::$static_error = '业绩待结算失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage(); return true; } } /** * @desc:极差的结算方案 * @Author: hua * @Date: 2022/3/8 * @Time: 16:44 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $grant * @param $list * @param $user_id_arr * @return int|mixed * @throws \Exception */ public static function planB($grant, $list, $user_id_arr) { $sum_award = 0; $achievement_award_log_list = AchievementAwardLog::lists([ 'where' => [ ['parent_team' => $user_id_arr], ['mall_id' => $grant['mall_id']], ['grant_id' => $grant['id']], ['status' => StatusEnum::ENABLED], ], 'index' => 'parent_team', 'group' => 'parent_team', 'select' => 'sum(proportion_money) as money,parent_team', ]); $achievement_award_log_list_end = AchievementAwardLog::lists([ 'where' => [ ['parent_team' => $user_id_arr], ['mall_id' => $grant['mall_id']], ['status' => StatusEnum::ENABLED], ['is_end' => 1], ], 'index' => 'user_id', 'group' => 'user_id', 'select' => 'sum(proportion_money) as money,user_id', ]); foreach ($list as $k => $v) { //查看所有下级的结算金额 $money = 0; if (isset($achievement_award_log_list[$v['user_id']])) $money = $achievement_award_log_list[$v['user_id']]['money']; $award_money = $v['proportion_money'] - $money > 0 ? $v['proportion_money'] - $money : 0; $v->award_money = $award_money; $v->is_end = 1; //总计 $sum_money = 0; $sum_money += $award_money; if (isset($achievement_award_log_list_end[$v['user_id']])) $sum_money += $achievement_award_log_list_end[$v['user_id']]['money']; $v->award_sum = $sum_money; if (!$v->save()) throw new \Exception("业绩修改奖励日志失败"); $sum_award += $v->award_money; } return $sum_award; } /** * @desc:计算奖励金额 * @Author: hua * @Date: 2022/3/8 * @Time: 16:46 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $list * @param $sum * @param $personal * @param $settlement_mode * @return array */ public static function confirmProportion($list, $sum, $personal, $settlement_mode, $is_team_achievement = false) { $list = json_decode($list, true); $column = array_column($list, 'money'); array_multisort($column, SORT_ASC, $list);//升序 $proportion = 0;//比例 $money = 0;//奖励金额 foreach ($list as $k => $v) { if ($sum >= $v['money']) { $proportion = $v['proportion']; if ($settlement_mode == 0) { $money = $v['proportion'] * $personal / 100; } else { $money = ($sum * $proportion) / 100; if ($is_team_achievement == 1) { $money = (($sum - $personal) * $proportion) / 100; } } } } return ['proportion' => $proportion, 'money' => $money]; } /** * @desc:获取上级团长user_id * @Author: hua * @Date: 2022/3/8 * @Time: 16:46 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $user_id * @return int|mixed */ public static function getParentAchievementUser($user_id) { //订单付款者不是团长身份,就往他的上级找 $id = 0; $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id); $parent_id_arr = array_reverse($parent_id_arr); $parent_achievement_user_list = AchievementUser::lists(['where' => [['user_id' => $parent_id_arr], ['status' => StatusEnum::ENABLED]], 'index' => 'user_id']); foreach ($parent_id_arr as $user_id) { if (isset($parent_achievement_user_list[$user_id])) { $achievement_user = $parent_achievement_user_list[$user_id]; $id = $achievement_user['user_id']; break; } } return $id; } /** * @desc:结算业绩 * @Author: hua * @Date: 2022/3/8 * @Time: 16:47 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $id * @return bool * @throws \Exception */ public static function grantAchievement($id) { if (is_array($id)) { $id = $id['id']; } $grant = AchievementGrantLog::findOne(['id' => $id, 'status' => StatusEnum::ENABLED, 'is_settlement' => 0]); if (empty($grant)) return true; //判断业绩奖励是否开启 $configs = \Yii::$app->services->setting->addons->get($grant['mall_id'], AddonsEnum::ADDONS_NAME_ACHIEVEMENT, 'basic'); if (empty($configs['status'])) return true; $t = \Yii::$app->db->beginTransaction(); try { $list = AchievementAwardLog::findAll(['grant_id' => $id, 'mall_id' => $grant['mall_id'], 'status' => StatusEnum::ENABLED, 'is_settlement' => 0]); $beg_time = date('Y.m.d', $grant['created_at']); $end_time = date('Y.m.d', $grant['end_time'] - 1); $remark = $beg_time . '-' . $end_time; $insert_wallet = []; $award_log_ids = []; foreach ($list as $item) { //统计团队业绩 $award_money = $item['award_money'] + $item['equal_money']; //新增不结算判断 if ($award_money > 0 && $item['is_skip_settlement'] == 0) { //发送佣金队列 $award_money = bcmul($award_money, 1, 2); $desc = '用户(' . $item['user_id'] . '),获得业绩奖励,金额:' . $award_money; // echo $desc.PHP_EOL; $insert_wallet [] = ['mall_id' => $item['mall_id'], 'user_id' => $item['user_id'], 'is_frozen' => false, 'wallet_type' => 'commission', 'money' => $award_money, 'desc' => $desc, 'source_table' => AchievementAwardLog::tableName(), 'source_table_id' => $item['id'], 'from_type' => AddonsEnum::ADDONS_NAME_ACHIEVEMENT, 'capital_type' => UserWalletEnum::ACHIEVEMENT_REWARD, ]; //todo 微信推送,暂时不做推送,看后期规划 if (!empty($configs['is_notice'])) { } } $award_log_ids[] = $item['id']; } AchievementAwardLog::updateAll(['is_settlement' => 1, 'is_end' => 1], ['id' => $award_log_ids]); $grant->is_settlement = 1; if (!$grant->save()) throw new \Exception("业绩结算修改规则日志失败"); // 批量插入数据 try { //投递到资产队列 if ($insert_wallet) { $res = UserWalletService::batchHandleByQueue($insert_wallet); if (empty($res)) throw new \Exception(UserWalletService::getStaticError()); foreach ($insert_wallet as $k => $user) { $achievement = AchievementUser::findOne(['user_id' => $user['user_id']]); $achievement->total_commission += $user['money']; $res = $achievement->save(); if (empty($res)) throw new \Exception(AchievementUser::getStaticError()); } } } catch (\Exception $e) { \Yii::error('DistributionBase:addFrozenCommission' . $e->getMessage()); } $t->commit(); return true; } catch (Exception $e) { $t->rollBack(); \Yii::error('业绩结算失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage()); self::$static_error = '业绩结算失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage(); return true; } } /** * @desc:整点添加规则 * @Author: hua * @Date: 2022/3/8 * @Time: 17:12 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param int $type 0,正常生成,1:更新配置后重新生成 * @return bool * @throws \Exception */ public static function addGrantLog($mall_id, $type = 0) { $time = time(); // $time = '1647219869';//调测使用 $is_install = MallAddons::isInstall($mall_id, AchievementEnum::ADDONS_NAME); if ($is_install == false) return true; //判断业绩奖励是否开启 $configs = \Yii::$app->services->setting->addons->get($mall_id, AddonsEnum::ADDONS_NAME_ACHIEVEMENT, 'basic'); if (empty($configs['status'])) return true; //查看最新一期是否存在 $status = AchievementGrantLog::find()->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'is_create' => 0]) ->andWhere(['>', 'end_time', $time])->one(); if (!empty($status)) return true; $t = \Yii::$app->db->beginTransaction(); try { //0,正常生成,1:更新配置后重新生成 if ($type == 0) { AchievementGrantLog::updateAll(['is_create' => 1], ['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'is_create' => 0]); } else { AchievementGrantLog::updateAll(['status' => StatusEnum::DELETE], ['mall_id' => $mall_id, 'is_wait' => 0, 'status' => StatusEnum::ENABLED, 'is_create' => 0]); } // $time = $configs['settlement_cycle'] == 0 ? strtotime('next monday') : strtotime(date("Y-m-d H:i:s", mktime(0, 0, 0, date("m") + 1, 1, date("Y")))); if ($configs['settlement_cycle'] == 0) { $time = strtotime('next monday'); } elseif ($configs['settlement_cycle'] == 1) { $time = mktime(0, 0, 0, date("m") + 1, 1, date("Y")); } elseif ($configs['settlement_cycle'] == 2) { $current_month = date('n'); $current_year = date('Y'); // 计算当前季度起始月份 (1,4,7,10) $current_quarter_start = floor(($current_month - 1) / 3) * 3 + 1; // 计算下个季度起始月份 $next_quarter_month = $current_quarter_start + 3; $next_year = $current_year; if ($next_quarter_month > 12) { $next_quarter_month -= 12; $next_year++; } $time = mktime(0, 0, 0, $next_quarter_month, 1, $next_year); } $cycle_time = $configs['settlement_time']; $award_proportion = $configs['award_proportion']; $settlement_cycle = $configs['settlement_cycle']; $delay_time = $configs['delay_time']; $statistical_methods = $configs['statistical_methods']; $settlement_mode = $configs['settlement_mode']; $grantLog = new AchievementGrantLog(); $grantLog->mall_id = $mall_id; $grantLog->award_proportion = $award_proportion; $grantLog->cycle = $settlement_cycle; $grantLog->cycle_time = $cycle_time; $grantLog->wait_settlement_time = strtotime(date('Y-m-d ' . $cycle_time, $time)); $grantLog->settlement_time = strtotime(date('Y-m-d ' . $cycle_time, $time)) + $delay_time * 86400; $grantLog->statistical_methods = $statistical_methods; $grantLog->end_time = $time; $grantLog->settlement_mode = $settlement_mode; $grantLog->is_equal = $configs['is_equal'] ?? 0; $grantLog->equal_percent = $configs['equal_percent'] ?? 0; $grantLog->equal_price_first = $configs['equal_price_first'] ?? 0; $grantLog->equal_price_second = $configs['equal_price_second'] ?? 0; $grantLog->is_team_achievement = $configs['team_achievement'] ?? 0; $grantLog->is_award_need_confirm = $configs['is_award_need_confirm'] ?? 0; $grantLog->is_leader_first_month_no_award = $configs['is_leader_first_month_no_award'] ?? 0; if (!$grantLog->save()) throw new \Exception("创建下一期规则日志失败"); $t->commit(); return true; } catch (Exception $e) { $t->rollBack(); \Yii::error('创建下一期规则日志失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage()); self::$static_error = '创建下一期规则日志失败' . PHP_EOL . $e->getFile() . '(' . $e->getLine() . ')' . PHP_EOL . "message:" . $e->getMessage(); return true; } } /** * @desc:编辑日志 * @Author: hua * @Date: 2022/3/8 * @Time: 17:12 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @return bool */ public function setLogStatus($mall_id) { try { $res = AchievementGrantLog::updateAll(['status' => StatusEnum::DELETE], ['mall_id' => $mall_id, 'is_settlement' => 0]); \Yii::$app->custom->logs('setLogStatus->AchievementGrantLog:update_count' . $res); $res = AchievementAwardLog::updateAll(['status' => StatusEnum::DELETE], ['mall_id' => $mall_id, 'is_settlement' => 0]); \Yii::$app->custom->logs('setLogStatus->AchievementAwardLog:update_count' . $res); return true; } catch (Exception $e) { return false; } } /** * 填充上级 * @param $data * @return void */ public static function fillParentTeam($data) { $mall_id = $data['mall_id']; $user_id = $data['user_id']; $grant = AchievementGrantLog::findOne(['mall_id' => $mall_id, 'status' => 1, 'is_wait' => 0, 'is_create' => 0]); if (!empty($grant)) { AchievementOrderLogic::fillParentTeamByEmpty($mall_id, $grant['id'], $grant['settlement_mode']); AchievementOrderLogic::updateParentTeam($mall_id, $grant['id'], $user_id); } $grant->award_proportion = json_decode($grant['award_proportion'], true); self::fixParentAchievement($grant, $user_id); $grant['award_proportion'] = json_encode($grant['award_proportion']); AchievementOrderLogic::updateGrant($grant); } /** * 修正上级的业绩 * * @param $grant * @param $user_id * @return void * @throws Exception */ public static function fixParentAchievement($grant, $user_id) { $mall_id = $grant['mall_id']; $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id); $parent_id_arr[] = $user_id; $parent_id_arr = array_reverse($parent_id_arr); $achievement_user_map = self::getAchievementUserMap($mall_id, $parent_id_arr); if (!empty($parent_id_arr)) { $new_parent_achievement_award_log_map = self::getParentAchievementAwardLogMap($grant['id'], $parent_id_arr); $new_parent_achievement_award_log_list_sort = []; foreach ($parent_id_arr as $pid) { if (!isset($new_parent_achievement_award_log_map[$pid])) { if (isset($achievement_user_map[$pid])) { $new_parent_achievement_award_log_list_sort[] = self::getTempModel($mall_id, $pid, $grant['id']); } } else { $new_parent_achievement_award_log_list_sort[] = $new_parent_achievement_award_log_map[$pid]; } } if (!empty($new_parent_achievement_award_log_list_sort)) { self::handleAchievement($grant, $new_parent_achievement_award_log_list_sort); } } } /** * 获取团长map * * @param $mall_id * @param $parent_id_arr * @return false|mixed */ public static function getAchievementUserMap($mall_id, $parent_id_arr) { return AchievementUser::lists([ 'where' => [ ['user_id' => $parent_id_arr], ['mall_id' => $mall_id], ['status' => StatusEnum::ENABLED] ], 'index' => 'user_id' ]); } public static function getParentAchievementAwardLogMap($grant_id, $parent_id_arr) { $achievement_award_log_list = AchievementAwardLog::lists([ 'where' => [ ['user_id' => $parent_id_arr], ['grant_id' => $grant_id], ['status' => StatusEnum::ENABLED] ], 'index' => 'user_id' ], false); if (empty($achievement_award_log_list)) { return []; //旧上级没有本周期的业绩奖励记录 } return $achievement_award_log_list; } /** * 获取临时模型 * * @param $mall_id * @param $user_id * @param $grant_id * @return AchievementAwardLog */ public static function getTempModel($mall_id, $user_id, $grant_id) { $model = new AchievementAwardLog(); $model->parent_team = $model->user_id = $user_id; $model->grant_id = $grant_id; $model->mall_id = $mall_id; $model->parent_team = AchievementLogic::getParentAchievementUser($user_id); $model->sub_personal_achievement = 0; return $model; } /** * 处理团队业绩 * * @param $grant * @param $new_parent_achievement_award_log_list_sort * @return void * @throws Exception */ public static function handleAchievement($grant, $new_parent_achievement_award_log_list_sort) { $settlement_mode = $grant['settlement_mode']; $grant_id = $grant['id']; $award_proportion = $grant['award_proportion']; $list = $user_id_arr = []; foreach ($new_parent_achievement_award_log_list_sort as $log) { $log->parent_team = AchievementLogic::getParentAchievementUser($log->user_id); $log->save(); if ($settlement_mode == 2) { self::planC($log, $grant_id, $award_proportion, $settlement_mode); } else { $team_achievement = $log->team_achievement; $child_achievement_sum = self::handleAchievementExtra($log); if (empty($child_achievement_sum)) { $child_achievement_sum = 0; } if ($team_achievement == $child_achievement_sum) { //团队业绩无变化 continue; } $log->team_achievement = $child_achievement_sum; $log->achievement_sum = $child_achievement_sum + $log->personal_achievement; if (!empty($log->achievement_sum)) { $log->save(); } $award = AchievementLogic::confirmProportion($award_proportion, $log->achievement_sum, $log->personal_achievement, $settlement_mode); $log->award_proportion = $award['proportion']; if ($settlement_mode == 0) { $log->award_money = $award['money']; } else { $log->proportion_money = $award['money']; } if (!$log->save()) { var_dump('处理个人业绩日志时失败'); } if ($settlement_mode == 1) { $list[] = $log; $user_id_arr[] = $log->user_id; } } } if ($settlement_mode == 1 && !empty($list)) { AchievementOrderLogic::planB($grant, $list, $user_id_arr);//极差 } } /** * 处理扩展表的团队业绩,同时返回会员的下级们的总业绩 * @param $log * @return bool|float|int|mixed|string */ public static function handleAchievementExtra($log) { $user_id = $log->user_id; $grant_id = $log->grant_id; $child_achievement_award_log_list = self::getAchievementAwardLogListByParentTeam($user_id, $grant_id); $child_user_ids = array_column($child_achievement_award_log_list, 'user_id'); $child_team_achievement = AchievementAwardLogExtra::find()->where(['user_id' => $child_user_ids, 'grant_id' => $grant_id]) ->sum('team_achievement'); $total_personal_achievement = array_sum(array_column($child_achievement_award_log_list, 'personal_achievement')); $team_achievement = 0; if ($child_team_achievement) { $team_achievement = $child_team_achievement; } if ($total_personal_achievement) { $team_achievement = $team_achievement + $total_personal_achievement; } AchievementAwardLogExtra::updateAll(['team_achievement' => $team_achievement], ['user_id' => $user_id, 'grant_id' => $grant_id]); return $team_achievement; } /** * 业绩极差 * * @param $log * @param $grant_id * @param $award_proportion * @param $settlement_mode * @return void */ public static function planC($log, $grant_id, $award_proportion, $settlement_mode) { $configs = \Yii::$app->services->setting->addons->get($log['mall_id'], AddonsEnum::ADDONS_NAME_ACHIEVEMENT, 'basic'); $team_achievement = $log->team_achievement; $child_achievement_sum = self::getTeamAchievementByParentTeamC($log->user_id, $grant_id); $child_equal_first = self::getEqualFirstByParentTeamC($log->user_id, $grant_id); $child_equal_second = self::getEqualSecondByParentTeamC($log->user_id, $grant_id); if (empty($child_achievement_sum)) { $child_achievement_sum = 0; } $log->achievement_sum = $log->team_achievement + $log->personal_achievement; if ($team_achievement != $child_achievement_sum) { $log->team_achievement = $child_achievement_sum ?? 0; $log->achievement_sum = $log->team_achievement + $log->personal_achievement; $log->save(); $award_proportion = json_encode($award_proportion); $award = AchievementLogic::confirmProportion($award_proportion, $log->achievement_sum, $log->personal_achievement, $settlement_mode); $log->award_proportion = $award['proportion']; $log->award_money = $award['money']; } $log->team_equal_first = empty($configs['equal_type']) ? ($child_equal_first ?? 0) : 0; $log->team_equal_second = empty($configs['equal_type']) ? ($child_equal_second ?? 0) : 0; if (!$log->save()) { var_dump('处理个人业绩日志时失败'); } } /** * 获取团队业绩,c * * @param $user_id * @param $grant_id * @return bool|int|mixed|string|null */ public static function getTeamAchievementByParentTeamC($user_id, $grant_id) { return AchievementAwardLog::find()->where([ 'parent_team' => $user_id, 'grant_id' => $grant_id, 'status' => StatusEnum::ENABLED, 'award_money' => 0 ])->sum('achievement_sum'); } /** * 获取平1,c * @param $user_id * @param $grant_id * @return bool|int|mixed|string|null */ public static function getEqualFirstByParentTeamC($user_id, $grant_id) { return AchievementAwardLog::find()->where([ 'parent_team' => $user_id, 'grant_id' => $grant_id, 'status' => StatusEnum::ENABLED, 'award_money' => 0 ])->sum('equal_first'); } /** * 获取平2,c * @param $user_id * @param $grant_id * @return bool|int|mixed|string|null */ public static function getEqualSecondByParentTeamC($user_id, $grant_id) { return AchievementAwardLog::find()->where([ 'parent_team' => $user_id, 'grant_id' => $grant_id, 'award_money' => 0 ])->sum('equal_second'); } /** * 获取奖励明细列表 * * @param $user_id * @param $grant_id * @return array|\yii\db\ActiveRecord[] */ public static function getAchievementAwardLogListByParentTeam($user_id, $grant_id) { return AchievementAwardLog::find()->where([ 'parent_team' => $user_id, 'grant_id' => $grant_id ])->all(); } }