custom->logs("二二开始,id=".json_encode($order['id'])); try { self::$task_counter_arr = [];// 初始化 $order['order_status'] = $order_status;// 订单状态赋值 $configs = Yii::$app->services->setting->addons->get($order['mall_id'], DoubleCopyEnum::ADDONS_NAME, 'basic'); if($configs && isset($configs['is_open_level_limit']) && !empty($configs['is_open_level_limit'])){ $order_by = 'level asc'; $is_open_level_limit = true; }else{ $order_by = 'level desc'; $is_open_level_limit = false; } // 购买升级-生成链动用户数据 $upgrade = new BuyGoodsUpgrade(); $upgrade_uid = $upgrade->execute(DoubleCopyEnum::ADDONS_NAME, (new DoubleCopyUser()), (new DoubleCopyLevel()), $order,$order_by,$is_open_level_limit, null, null, function ($model) { $model->upgrade_boss_at = !$model->upgrade_boss_at && $model->level >= 2 ? $model->upgrade_level_at : 0; }); Yii::$app->custom->logs("二二关系,id=".json_encode($order['id']).',结果:'.json_encode($upgrade_uid)); // 绑定链动用户之间的关系 $is_upgrade = false;// 是否是升级[0=否,1=是] if ($upgrade_uid) { if (isset($configs['auto_virtual_user']) && !empty($configs['auto_virtual_user'])) { // 查询用户升级后的等级 $user_level = DoubleCopyUser::find()->where(['mall_id' => $order['mall_id'], 'user_id' => $upgrade_uid])->select('level')->scalar(); if (!empty($user_level) && $user_level >= 2) { self::createVirtualUser($order['mall_id'], $order['user_id']); } } $res = self::bindingRelation($order['mall_id'], $order['user_id']); if ($res === false) throw new \Exception(self::getStaticError()); $is_upgrade = true; } // 赠送用户奖励 $res = Reward::compute($order, $is_upgrade); Yii::$app->custom->logs("二二赠送:".json_encode($order['id']).',结果:'.json_encode($res)); if ($res === false) throw new \Exception(Reward::getStaticError()); if (Reward::$task_counter_arr) self::$task_counter_arr = Reward::$task_counter_arr; //赠送积分 $res = Reward::compute($order, $is_upgrade,'score'); if ($res === false) throw new \Exception(Reward::getStaticError()); //赠送额外积分 - 判断插件是否有开启 if (MallAddons::isInstall($order['mall_id'], AddonsEnum::ADDONS_NAME_POINT_UPPER_LIMIT)) { // && (new UserService())->getUserQuota($order['mall_id'], $order['user_id']) > 0 if (!empty((new SettingService())->isEnable($order['mall_id']))) { $res = Reward::compute($order, $is_upgrade,'additional_score'); if ($res === false) throw new \Exception(Reward::getStaticError()); } } // 条件升级 $res = (new ConditionUpgrade())->execute($order); if ($res === false) throw new \Exception(DoubleCopyUser::getStaticError()); //二二复制代理升级事件 if($is_upgrade || !empty($res)){ $event = new UpgradeEvent($order['mall_id']); $data = [ 'id' => $order['id'], 'mall_id' => $order['mall_id'], 'user_id' => $order['user_id'], ]; \Yii::$app->services->events->dispatch($event, $data, $event->listeners); } Yii::$app->custom->logs("二二结束,id=".json_encode($order['id'])); return true; } catch (\Exception $e) { var_dump($e->getMessage(), $e->getFile(), $e->getLine()); self::setStaticError($e->getMessage()); return false; } } /** * 绑定关系 * @Author: lun * @DateTime: 2022/5/16 0016 18:56 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param $user_id */ public static function bindingRelation($mall_id, $user_id) { $trans = Yii::$app->db->beginTransaction(); try { // 获取用户信息 $user = DoubleCopyUser::findOne(['user_id' => $user_id, 'status' => StatusEnum::ENABLED]); // 获取用户直推上级id $parent_id = User::find()->select('parent_id')->where(['id' => $user_id])->scalar(); // 查询用户上两级用户id $parent_ids = UserPartitionRelationship::getParentIdArr($user_id); if ($parent_ids) $parent_ids = array_reverse($parent_ids);// 倒序数组 $pos = 0;// 位置 $topid = 0;// 顶层老板id // 如果用户已升级过并且关系已绑好则直接跳出 if ($user->pos != 0) { //异步检查用户是否达到解冻冻结基金标准 self::fundThaw($mall_id, $parent_ids); $trans->commit(); return true; } // 增加上级团队数量 DoubleCopyUser::updateAllCounters(['team_num' => 1], ['user_id' => $parent_ids, 'status' => StatusEnum::ENABLED]); // 获取老板等级配置 $level = DoubleCopyLevel::getOne([['mall_id' => $mall_id, 'level' => DoubleCopyEnum::LEVEL_BOSS, 'status' => StatusEnum::ENABLED]], true, 'setting'); $upgrade_num = 0;// 需要直推的升级数量 if ($level['upgrade_type_condition'] == 1) { // json解析升级条件数量 $json = Json::decode($level['checked_condition_values'], true); $upgrade_num = $json[0]['value']['val0'] ?: 0; } // 根据上级id计算当前用户所处位置 if ($parent_id) { // 获取用户相对上级的位置 $last_pos = DoubleCopyUser::find()->select('pos')->where(['pid' => $parent_id, 'status' => StatusEnum::ENABLED])->orderBy('pos desc')->scalar(); $pos = empty($last_pos) ? 1 : $last_pos + 1;// 用户位置 // 查询上级用户信息 $parent = DoubleCopyUser::findOne(['user_id' => $parent_id, 'status' => StatusEnum::ENABLED]); if ($parent) { $parent->help_num += 1; if (!$parent->save()) throw new Exception('上级数据保存失败:'.$parent->getError()); } // 当前用户位置大于1、2号位,topid则一定是推荐人 if ($pos > $upgrade_num) { $topid = $parent_id; } else { if($parent_ids){ // 获取所有上级所在的位置 $all_parents = DoubleCopyUser::find()->select('user_id,pos,pid')->where(['user_id' => $parent_ids, 'status' => StatusEnum::ENABLED])->orderBy([new Expression('FIELD (user_id, '.implode(',', $parent_ids).')')])->asArray()->all(); foreach ($all_parents as $item) { // 如果当前位置是大于或等于3号位则表示此用户上级必定是老板 if ($item['pos'] > $upgrade_num) { $topid = $item['pid']; break; } // 若所有上级都处于1、2号位那代表最顶层的用户为topid // $topid = $item['user_id']; } } } } // 查询当前用户等级是否为代理,若是代理则查询是否已满足一二号位 // if ($level['upgrade_type_condition'] == 1) { // 获取直推下级代理/老板数量 $count = DoubleCopyUser::find()->select('id')->where(['pid' => $user->user_id, 'status' => StatusEnum::ENABLED])->count(); $user->help_num = $count; // } // 保存用户位置数据 $user->pid = $parent_id; $user->topid = $topid; $user->pos = $pos; if (!$user->save()) throw new Exception('用户pid,topid,pos失败:'.$parent->getError()); $trans->commit(); // 异步检查用户是否达到解冻冻结基金标准 // 放入延时队列处理 self::fundThaw($mall_id, $parent_ids); // if ($parent_ids) { // // 放入延时队列处理 // Yii::$app->services->rabbitMq->delay(60, ['mall_id' => $mall_id, 'parent_ids' => implode(',', $parent_ids),'method' => 'releaseFrozen'], self::class, 'queueFrozen'); // } // 刚升级的用户(pid=当前用户)需要统计团队下所有的代理+老板人数插入team_num字段 if (!empty($count) && $user->team_num == 0) { Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, ['user_id' => $user->user_id], self::class, 'countTeamNum'); } return true; } catch (\Exception $e) { $trans->rollBack(); self::setStaticError($e->getMessage()); return false; } } //异步检查用户是否达到解冻冻结基金标准 public static function fundThaw($mall_id, $parent_ids) { if (!empty($parent_ids)) { Yii::$app->services->rabbitMq->delay(60, ['mall_id' => $mall_id, 'parent_ids' => implode(',', $parent_ids),'method' => 'releaseFrozen'], self::class, 'queueFrozen'); } } /** * 统计用户团队数量 * @Author: lun * @DateTime: 2022/5/18 0018 20:38 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @return bool */ public static function countTeamNum($params) { try { $user_id = $params['user_id'];// 需要统计的用户 $offset = 1; $limit = 1000; $params['select'] = 'user_id,deep'; $team_num = 0; list($tree, $deep, $all_tree, $all_tree_arr) = UserPartitionRelationship::getTree($user_id); while ($list = UserPartitionRelationship::batchGetTeamData($offset, $limit, $tree, $params)) { $user_ids = array_column($list, 'user_id'); // 统计团队中已经成为经理或老板的用户 $count = DoubleCopyUser::find()->select('id')->where(['user_id' => $user_ids, 'status' => StatusEnum::ENABLED])->count(); $team_num += $count; $offset++; } // 修改用户数据 if ($count) { $res = DoubleCopyUser::updateAllCounters(['team_num' => $team_num], ['user_id' => $user_id, 'status' => StatusEnum::ENABLED]); if ($res == false) throw new \Exception(DoubleCopyUser::getStaticError()); } return true; } catch (\Exception $e) { $exception = FormatHelper::exception($e, "二二复制批量统计用户团队数量"); echo $exception; Yii::error($exception); return false; } } /** * 延时队列放到订单队列保持数据一致性 * @Author:lun * @Date:2023-12-04 10:00 * @Copyright:copyright(c)2023 广东七件事集团 * @param $params * @return true */ public static function queueFrozen($params) { $method = $params['method']; if (empty($method)) { Yii::error('冻结基金放订单队列失败:'.json_encode($params)); return true; } switch ($method) { case 'releaseFrozen': Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_ORDER, RabbitMqEnum::ORDER_QUEUE, $params, self::class, $method); break; case 'unfreeze': Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_ORDER, RabbitMqEnum::ORDER_QUEUE, $params, self::class, $method); break; } return true; } /** * 用户释放冻结基金 * @Author: lun * @DateTime: 2022/5/18 0018 16:13 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $user_id * @throws \Exception */ public static function releaseFrozen($params) { $trans = Yii::$app->db->beginTransaction(); try { $uids = $params['parent_ids']; $users = DoubleCopyUser::find()->where(['user_id' => explode(',', $uids), 'is_thaw' => StatusEnum::DISABLED])->andWhere(['>=', 'level', DoubleCopyEnum::LEVEL_BOSS])->all(); if (empty($users)) return true; // 获取老板等级的解冻用户数量 $setting = DoubleCopyLevelSetting::find()->where(['mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED])->andWhere(['>=','level',DoubleCopyEnum::LEVEL_BOSS])->indexBy('level')->asArray()->all(); if (empty($setting)) return true; // 获取冻结基金名称 $reward_arr = Yii::$app->services->setting->addons->get($params['mall_id'], DoubleCopyEnum::ADDONS_NAME, 'basic.reward_name'); $reward_name = is_array($reward_arr) ? $reward_arr : json_decode($reward_arr, true); $frozen_name = $reward_name['freeze_fund'] ?? '冻结基金'; foreach ($users as $user) { // if (empty($setting[$user->level]['freeze_fund_num'])) continue; $freeze_fund_num = $setting[$user->level]['freeze_fund_num'] ?? 0; self::unfreezeHandle([$user], $frozen_name.'释放', 1, 0, 0, $freeze_fund_num, $setting[$user->level]); } $trans->commit(); return true; } catch (\Exception $e) { $trans->rollBack(); $exception = FormatHelper::exception($e, "二二复制用户释放冻结基金"); echo $exception; Yii::error($exception); return false; } } /** * 业绩解冻 * @Author: lun * @DateTime: 2022/9/9 0009 9:34 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @return bool */ public static function unfreeze($params) { $trans = Yii::$app->db->beginTransaction(); try { $user_ids = explode(',', $params['user_ids']); // 查询开启了阶梯解冻设置的等级 $levels = DoubleCopyLevel::find()->where(['mall_id' => $params['mall_id'], 'open_ladder' => StatusEnum::ENABLED, 'status' => StatusEnum::ENABLED])->andWhere(['>=','level',DoubleCopyEnum::LEVEL_BOSS])->indexBy('level')->asArray()->all(); if (empty($levels)) { $trans->commit(); return true; } // 获取冻结基金名称 $reward_arr = Yii::$app->services->setting->addons->get($params['mall_id'], DoubleCopyEnum::ADDONS_NAME, 'basic.reward_name'); $reward_name = is_array($reward_arr) ? $reward_arr : json_decode($reward_arr, true); $frozen_name = $reward_name['freeze_fund'] ?? '冻结基金'; foreach($levels as $level) { // 查询符合等级的用户 $users = DoubleCopyUser::find()->where(['user_id' => $user_ids, 'level' => $level['level'], 'status' => StatusEnum::ENABLED])->andWhere(['<>','is_thaw', 1])->all(); if ($users) { $ladder_setting = Json::decode($level['ladder_setting'], true); if (empty($ladder_setting)) continue; $ladder_setting = ArrayHelper::arraySort($ladder_setting, 'thaw_percent', 'desc');// 按照数据的百分比进行倒叙 foreach ($users as $user) { // if ($user['frozen_fund'] <= 0) continue;// 无冻结基金用户直接退出 foreach ($ladder_setting as $setting) { if ($user['thaw_percent'] < $setting['thaw_percent']) { // 查询用户前N个市场的业绩 $team = DoubleCopyUser::find()->select('achievement')->where(['pid' => $user['user_id']])->andWhere(['<=', 'pos', $setting['market']])->asArray()->all(); if (empty($team)) continue; // 若单市场业绩大于0怎判断市场是否足够数量 if (!empty($setting['single_market']) && $setting['market'] > count($team)) continue; $is_single_pass = true; $achievement = 0;// 总业绩 foreach ($team as $info) { // 判断单个市场是否及格 if ($info['achievement'] < $setting['single_market']) { $is_single_pass = false; break; } $achievement += $info['achievement']; } if ($is_single_pass == false) continue; // 符合业绩奖解冻 if ($achievement >= $setting['achievement']) { $user->thaw_percent = $setting['thaw_percent']; // 计算解冻金额 if ($setting['thaw_percent'] >= 100) { // 百分百解冻 self::unfreezeHandle([$user], $frozen_name.'全部释放', 2, $user->frozen_fund, $user->frozen_fund_score); } else { // 部分解冻 $unfreeze_money = sprintf("%.2f",substr(sprintf("%.3f", ($user['frozen_fund'] * $setting['thaw_percent'] / 100)), 0, -1));// 不四舍五入保留两位小数 $unfreeze_score = sprintf("%.2f",substr(sprintf("%.3f", ($user['frozen_fund_score'] * $setting['thaw_percent'] / 100)), 0, -1));// 不四舍五入保留两位小数 self::unfreezeHandle([$user], $frozen_name.'部分释放', 3, $unfreeze_money, $unfreeze_score); } continue; } } } } } } $trans->commit(); return true; } catch (\Exception $e) { $trans->rollBack(); $exception = FormatHelper::exception($e, "二二复制阶梯解冻"); Yii::error($exception); echo $exception; return true; } } /** * 冻结基金释放处理 * @Author: lun * @DateTime: 2022/9/8 0008 18:44 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $users * @param string $desc * @param int $thaw_type 释放类型[1=满足条件释放,2=阶梯100%释放,3=阶梯部分释放] * @param int $unfreeze_money 解冻金额 * @param int $unfreeze_score 解冻积分 * @param int $freeze_fund_num * @throws Exception */ public static function unfreezeHandle($users, $desc = '冻结基金释放', $thaw_type = 1, $unfreeze_money = 0, $unfreeze_score = 0, $freeze_fund_num = 0, $setting = []) { foreach ($users as $user) { // 解冻条件 // 1、本人必须是老板 // 2、助力1、2号位必须是老板 // 3、1、2号位的团队数量必须达到一定数量 if ($thaw_type == 1) { $thaw = DoubleCopyUser::getForzenUser($user['user_id'], $freeze_fund_num); //如果解冻条件不达标并且勾选了额外解冻条件,则进入二次校验 if ($thaw['is_thaw'] == 0 && (!empty($setting) && $setting['is_thaw'] == 1)) { $thaw = DoubleCopyUser::checkUnForzen($user['user_id'], $setting); } if ($thaw['is_thaw'] == 0) continue; } if (in_array($thaw_type, [1, 2])) { $unfreeze_money = $user->frozen_fund; $unfreeze_score = $user->frozen_fund_score;// 解冻的积分 $no_settlement_money = DoubleCopyCommission::getNoSettlementForzen($user['user_id']); $no_settlement_score = DoubleCopyCommission::getNoSettlementForzen($user['user_id'], 'score'); echo "thaw_type={$thaw_type},用户剩余未结算的冻结基金:".$no_settlement_money,',未结算冻结积分:'.$no_settlement_score.PHP_EOL; $unfreeze_money += $no_settlement_money; $unfreeze_score += $no_settlement_score; } echo '解冻1:用户ID='.$user->user_id.',type='.$thaw_type.',解冻金额:'.$unfreeze_money.',用户账户冻结基金:'.$user->frozen_fund.',解冻积分:'.$unfreeze_score.',用户账户冻结积分:'.$user->frozen_fund_score.PHP_EOL; $user->commission += $unfreeze_money; if ($user->frozen_fund >= $unfreeze_money) { $user->frozen_fund -= $unfreeze_money; } else { $user->frozen_fund = 0; } $user->score += $unfreeze_score; if ($user->frozen_fund_score >= $unfreeze_score) { $user->frozen_fund_score -= $unfreeze_score; } else { $user->frozen_fund_score = 0; } $user->is_thaw = $thaw_type == 3 ? 2 : 1; if (!$user->save()) throw new Exception($user->getError()); // 冻结资金记录修改状态 $settlement_type = $thaw_type == 3 ? 2 : 1; $status = $thaw_type == 3 ? [0] : [0, 2]; DoubleCopyCommission::updateAll(['settlement_type' => $settlement_type, 'updated_at' => time()], ['user_id' => $user->user_id, 'capital_type' => DoubleCopyEnum::FREEZE_FUND, 'settlement_type' => $status]); echo '解冻2:用户ID='.$user->user_id.',type='.$thaw_type.',解冻金额:'.$unfreeze_money.',用户账户冻结基金:'.$user->frozen_fund.',解冻积分:'.$unfreeze_score.',用户账户冻结积分:'.$user->frozen_fund_score.PHP_EOL; if ($unfreeze_money > 0) { $insert_wallet[] = [ 'mall_id' => $user->mall_id, 'user_id' => $user->user_id, 'is_frozen' => false, 'wallet_type' => 'commission', 'money' => $unfreeze_money, 'desc' => $desc, 'source_table' => 'addons_double_copy_commission', 'source_table_id' => 0, 'from_type' => DoubleCopyEnum::ADDONS_NAME, 'capital_type' => UserWalletEnum::BOSS_BONUS_FREEZE_FUND, ]; } if ($unfreeze_score > 0) { $insert_wallet[] = [ 'mall_id' => $user->mall_id, 'user_id' => $user->user_id, 'is_frozen' => false, 'wallet_type' => 'score', 'money' => $unfreeze_score, 'desc' => $desc, 'source_table' => 'addons_double_copy_commission', 'source_table_id' => 0, 'from_type' => DoubleCopyEnum::ADDONS_NAME, 'capital_type' => UserWalletEnum::BOSS_BONUS_FREEZE_FUND, ]; } } // 插入钱包 if (!empty($insert_wallet)) { $res = UserWalletService::batchHandleByQueue($insert_wallet); if (empty($res)) throw new \Exception('插入钱包队列:' . UserWalletService::getStaticError()); } } public static function createVirtualUser($mall_id, $user_id) { try { if (empty($mall_id) || empty($user_id)) return false; $target_num = DoubleCopyLevel::getUpgradeNum($mall_id); if (empty($target_num)) return false; // 查询现有的虚拟会员数量 $virtual_num = DoubleCopyUser::find()->where(['mall_id' => $mall_id, 'pid' => $user_id, 'status' => StatusEnum::ENABLED, 'is_virtual' => 1])->count(); $virtual_num = empty($virtual_num) ? 0 : intval($virtual_num); if ($virtual_num >= $target_num) return false; // 判断填充位会员是否存在,都存在则不创建 for ($i = 0; $i < $target_num - $virtual_num; $i++) { // 创建虚拟会员 $virtual_mobile = '800' . StringHelper::generateRandCode(8); $user = User::setData([ 'mall_id' => $mall_id, 'parent_id' => $user_id, 'nickname' => '虚拟用户' . StringHelper::generateRandCode(5), 'mobile' => $virtual_mobile, 'username' => $virtual_mobile, 'source' => defined('\common\models\user\User::SOURCE_DOUBLE_COPY_VIRTUAL_USER') ? User::SOURCE_DOUBLE_COPY_VIRTUAL_USER : 50, 'platform' => User::TYPE_MANUAL, 'password' => Yii::$app->getSecurity()->generatePasswordHash(substr($virtual_mobile,-6,6)) ]); if ($user) { $double_user = DoubleCopyUser::setData([ 'mall_id' => $mall_id, 'user_id' => $user->id, 'level' => 1, 'upgrade_status' => DoubleCopyEnum::UPGRADE_STATUS_MANUAL, 'is_virtual' => 1 ]); if ($double_user) self::bindingRelation($mall_id, $user->id); } } }catch (\Exception $e){ Yii::$app->custom->logs('[二二复制]User_id:' . $user_id . $e->getMessage()); return false; } } }