"分享首页", self::SOURCE_SHARE_POSTER => "分享海报", self::SOURCE_SHARE_GOODS => "分享商品", self::SOURCE_SHARE_CONTENT => "分享内容", self::SOURCE_SHARE_VIDEO => "分享视频", self::SOURCE_SHARE_NEWS => "分享资讯", self::SOURCE_SHARE_CARD => "分享名片", self::SOURCE_SHARE_O2O => "分享O2O门店", self::SOURCE_ADD_PLATFORM => "后台添加", self::SOURCE_DIY_PAGE => "自定义页面",// 装修页 self::SOURCE_GROUP_BUY_ACTIVE_GOODS => "分享拼团活动",// 装修页 self::SOURCE_BARGAIN_ACTIVE_ORDER => "分享我的砍价活动",// 装修页 self::SOURCE_BARGAIN_ACTIVE => "分享砍价活动",// 装修页 self::SOURCE_SCORE_MALL => "分享积分商品",// 装修页 self::SOURCE_LUCKY_GROUP_GOODS => "分享幸运拼团商品",// 装修页 self::SOURCE_SAlARY => "薪资插件注册",// 装修页 self::SOURCE_VALET_ORDER => "代客下单",// 装修页 self::SOURCE_WECHAT_VIDEO_SHOP => "微信视频小店",// 装修页 self::SOURCE_MATERIAL => "朋友圈素材",// 装修页 self::SOURCE_FUN_TOWN => "好玩小镇",// 装修页 self::SOURCE_AIYUNUO => "爱优诺",// 装修页 self::SOURCE_VALET_ORDER_DEFAULT_USER => "代客下单默认用户",// 装修页 self::SOURCE_DOUBLE_COPY_VIRTUAL_USER => "二二复制虚拟用户",// 装修页 self::SOURCE_HEALTH_EXAMINATION => "健康驿站",// 装修页 self::SOURCE_XIAOE => "小鹅通", self::SOURCE_SHEN_QUAN_YONG_USER_SYNC => "申泉泳酒业用户同步", ]; const TYPE_WECHAT = 'wechat'; const TYPE_MP_WX = 'mp-wx'; const TYPE_H5 = 'h5'; const TYPE_APP = 'app'; const TYPE_MANUAL = 'manual'; const TYPE_FACEBOOK_APP = 'facebook_app'; const TYPE_WECHAT_VIDEO_SHOP = 'wechat-video-shop'; const TYPE_OTHER = 'other'; const TYPE_NAME_LIST = array( self::TYPE_WECHAT => '微信公众号', self::TYPE_MP_WX => '小程序', self::TYPE_H5 => 'H5', self::TYPE_APP => 'APP', self::TYPE_MANUAL => '手动导入', self::TYPE_FACEBOOK_APP => 'Facebook-APP', self::TYPE_WECHAT_VIDEO_SHOP => '微信视频小店', self::TYPE_OTHER => '其他', self::PLATFORM_MP_ALI => '支付宝小程序', self::PLATFORM_XIAOE => '小鹅通', self::PLATFORM_SHEN_QUAN_YONG_USER_SYNC => '申泉泳酒业用户同步', ); public static $head_list = [ '0' => [ 'field' => 'serial_number', 'field_name' => '序号', ], '1' => [ 'field' => 'nickname', 'field_name' => '昵称', ], '2' => [ 'field' => 'mobile', 'field_name' => '绑定手机号', ], '3' => [ 'field' => 'invite_mobile', 'field_name' => '上级推荐人手机号', ], '4' => [ 'field' => 'balance', 'field_name' => '余额', ], '5' => [ 'field' => 'score', 'field_name' => '积分', ], '6' => [ 'field' => 'commission', 'field_name' => '佣金', ], '7' => [ 'field' => 'level', 'field_name' => '权重', ], ]; public static $max_count = 5000; public static $column_num = 7; /** * {@inheritdoc} */ public static function tableName() { return '{{%user}}'; } /** * {@inheritdoc} */ public function rules() { return [ [['mall_id', 'mch_id', 'store_id', 'mobile', 'area_code', 'temp_parent_id', 'parent_id', 'second_parent_id', 'third_parent_id', 'junior_at', 'created_at', 'last_login_at', 'birthday', 'upgrade_level_at', 'inviter_at', 'is_inviter', 'status', 'level', 'source'], 'integer'], [['username', 'nickname', 'device_type', 'device_mac'], 'string', 'max' => 64], [['nickname', 'device_type', 'device_mac'], 'safe'], [['password', 'transaction_password'], 'string', 'max' => 128], // [['mobile'], 'match', 'pattern' => '/^1\d{10}$/', 'message' => '请输入正确的手机号码'], [['avatar_url'], 'string', 'max' => 255], [['platform'], 'string', 'max' => 45], [['login_ip'], 'string', 'max' => 15], [['base64_code'], 'string', 'max' => 10], ]; } /** * {@inheritdoc} */ public function attributeLabels() { return [ 'id' => 'ID', 'base64_code' => 'user_id的64进制', 'mall_id' => '商城ID', 'mch_id' => '商户ID', 'store_id' => '门店id', 'username' => '用户名', 'password' => '密码', 'transaction_password' => '交易密码', 'area_code' => '手机区号', 'mobile' => '手机号', 'nickname' => '昵称', 'avatar_url' => '头像', 'platform' => '平台名字:app:微信授权、WECHAT:公众号、MP-WX:小程序', 'temp_parent_id' => '临时父级', 'parent_id' => '第一父级ID(直推人id)', 'second_parent_id' => '第二推荐人id', 'third_parent_id' => '第三推荐人id', 'junior_at' => '成为下级时间', 'created_at' => '添加时间', 'last_login_at' => '最后登录时间', 'upgrade_level_at' => '升级时间', 'inviter_at' => '邀请时间', 'login_ip' => '用户登录ip', 'is_inviter' => '是否是邀请者', 'status' => '状态[-1:删除;0:禁用;1启用]', 'level' => '会员等级,-1为普通会员,对应jxmall_mall_member_level表level字段', 'source' => '用户来源1分享首页2分享海报3分享商品4分享内容5分享视频6分享资讯7分享名片', 'device_type' => '登录设备', 'device_mac' => '登录设备MAC地址', ]; } /** * 关联标签 * @Author: lun * @DateTime: 2022/3/14 0014 10:36 * @Copyright: copyright (c) 2021 广东七件事集团 * @return \yii\db\ActiveQuery */ public function getUserLabel() { return $this->hasMany(UserLabel::class, ['id' => 'label_id']) ->select('id,name,color') ->where(['status' => StatusEnum::ENABLED]) ->via('userLabelRelationship'); } /** * 用户标签关联 * @Author: lun * @DateTime: 2022/3/14 0014 10:36 * @Copyright: copyright (c) 2021 广东七件事集团 * @return \yii\db\ActiveQuery */ public function getUserLabelRelationship() { return $this->hasMany(UserLabelRelationship::class, ['user_id' => 'id'])->select('label_id,user_id'); } /** * 获取上级 - 关联 * @desc * @return \yii\db\ActiveQuery */ public function getParentCustom() { return $this->hasOne(User::class, ['id' => 'parent_id'])->select('id,username,mobile,nickname,parent_id,avatar_url'); } /** * @return \yii\db\ActiveQuery */ public function getUserFreezeCommission() { return $this->hasOne(UserFreezeCommission::class, ['user_id' => 'id']); } public function getUserAchievementStatisticsTotal() { return $this->hasOne(UserAchievementStatisticsTotal::class, ['user_id' => 'id']); } /** * 保存数据 * @param array $params * @return bool|User * @throws \yii\db\Exception */ public static function setData(array $params) { $t = Yii::$app->db->beginTransaction(); try { $model = self::saveDataMainFunc($params); $t->commit(); UserInviteCode::setData([ 'user_id' => $model->id, 'mall_id' =>$params['mall_id'] ]); return $model; } catch (Exception $e) { $t->rollBack(); self::$static_error = $e->getMessage(); Yii::error('注册用户报错:' . $e->getFile().',第'.$e->getLine().'行,原因:'.$e->getMessage()); return false; } } /** * 用户注册主体方法 * @param array $params * @return User * @throws Exception */ public static function saveDataMainFunc(array $params) { $is_close_register = MallSetting::conf($params['mall_id'],'user.is_close_register'); if ($is_close_register == 1) throw new Exception('站点维护中,暂时无法注册'); if (!empty($params['id'])) { $model = self::findOne(['id' => $params['id'], 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($model)) throw new Exception('服务不存在或已删除'); } else { $model = new self(); $model->loadDefaultValues(); } $parent_id = $second_parent_id =$third_parent_id =0; //传推荐人手机号码 $relation_setting = \Yii::$app->services->setting->mall->get($params['mall_id'], 'user_relation_setting.relation_setting'); if (!empty($relation_setting)) $relation_setting = json_decode($relation_setting, true); $relation_setting_status = 1; if(empty($relation_setting['status'])) { $relation_setting_status = 0; } if (!empty($params['invite_mobile'])){ $is_invite_register = MallSetting::conf($params['mall_id'],'user.is_invite_register'); $parent = User::findOne(['mall_id' => $params['mall_id'], 'mobile' => $params['invite_mobile'],'is_inviter'=>1, 'status' => 1]); if(!empty($relation_setting['become_child_way'])&&$relation_setting['become_child_way']==4){ if(empty($parent)) throw new Exception('填写的推荐人手机号不存在'); } if($is_invite_register && empty($parent)) throw new Exception('填写的推荐人手机号不存在'); }else{ //传推荐人会员id if (!empty($params['parent_id']) && $params['parent_id'] != -1){ $parent = User::findOne(['id'=>$params['parent_id'],'mall_id' => $params['mall_id'],'is_inviter'=>1]); } } if ($relation_setting_status==1&&!empty($parent)){ if($params['mall_id']!=$parent['mall_id']) throw new Exception('商城交叉'); $parent_id = $parent->id??0; $second_parent_id = $parent->parent_id??0; $third_parent_id = $parent->second_parent_id??0; } $params['parent_id'] = 0; if(!empty($params['platform'])&&$params['platform']!= User::TYPE_MANUAL){ //非后台手动添加的会员,需受关系设置配置影响 if(!empty($relation_setting['become_child_way'])){ switch ($relation_setting['become_child_way']){ case 1: case 4: case 5: $params['parent_id'] = $parent_id; $params['second_parent_id'] =$second_parent_id; $params['third_parent_id'] = $third_parent_id; break; case 2: case 3: $params['temp_parent_id'] = $parent_id; $parent_id = 0; $params['parent_id'] = $parent_id; break; } } // if (!empty($relation_setting['become_child_way']) && $relation_setting['become_child_way'] == 1) { // $params['parent_id'] = $parent_id; // $params['second_parent_id'] =$second_parent_id; // $params['third_parent_id'] = $third_parent_id; // } else { // $params['temp_parent_id'] = $parent_id; // $parent_id = 0; // $params['parent_id'] = $parent_id; // } }else{ $params['parent_id'] = $parent_id; $params['second_parent_id'] =$second_parent_id; $params['third_parent_id'] = $third_parent_id; } if(!empty($relation_setting['status'])&&!empty($relation_setting['get_power_way'])&&$relation_setting['get_power_way']==1) $params['is_inviter'] = 1; if (!$model->load($params, '') || !$model->save()) throw new Exception($model->getErrorMessage()); $model->base64_code = Base64Helper::dec2Base64($model->id); $res = $model->save(); if ($res === false) throw new Exception('转码失败'); $params['user_id'] = $model->id; $res = UserWallet::setData($params); if ($res === false) throw new Exception($model->getErrorMessage()); $param = [ 'user_id' => $model->id, 'parent_id' => $parent_id, ]; Yii::$app->custom->logs("关系链绑定数据", json_encode($param)); $res = UserPartitionRelationship::setData($param); if ($res === false) throw new Exception(UserPartitionRelationship::getStaticError()); return $model; } /** * 没有事务的注册用户方法 * @param array $params * @return User * @throws Exception */ public static function setDataByNoTransaction(array $params) { $model = self::saveDataMainFunc($params); UserInviteCode::setData([ 'user_id' => $model->id, 'mall_id' =>$params['mall_id'] ]); return $model; } /** * @param array $where * @param string $select * @param array $with * @param int $is_array * @return array|User|\yii\db\ActiveRecord|null */ public static function getUser(array $where, $select = '*', array $with = [], int $is_array = 0) { $default_cond = [['<>', 'status', StatusEnum::DELETE]]; $where = array_merge($default_cond, $where); $query = self::find(); self::paramPack(['where' => $where, 'with' => $with], $query); return $query->select($select)->asArray($is_array)->one(); } /** * @param array $where * @param string $select * @param array $with * @param int $is_array * @return array|User[]|\yii\db\ActiveRecord[] */ public static function getUserList(array $where, $select = '*', array $with = [], int $is_array = 0) { $default_cond = [['<>', 'status', StatusEnum::DELETE]]; $where = array_merge($default_cond, $where); $query = self::find(); self::paramPack(['where' => $where, 'with' => $with], $query); return $query->select($select)->asArray($is_array)->all(); } /** * @param int|string $id * @return User|IdentityInterface|null */ public static function findIdentity($id) { $userData = self::findOne($id); if (!empty($userData) && $userData->status == StatusEnum::ENABLED) { return $userData; } return null; } /** * @param mixed $token * @param null $type * @return User|IdentityInterface|null */ public static function findIdentityByAccessToken($token, $type = null) { return static::findOne(['access_token' => $token]); } /** * @return int|string */ public function getId() { return $this->id; } /** * @return string|null */ public function getAuthKey() { return $this->auth_key; } /** * @param string $authKey * @return bool|null */ public function validateAuthKey($authKey) { return $this->getAuthKey() === $authKey; } /** * 关联用户钱包 * @return \yii\db\ActiveQuery */ public function getUserWallet() { return $this->hasOne(UserWallet::class, ['user_id' => 'id']); } /** * 关联会员等级 * @return \yii\db\ActiveQuery */ public function getUserLevel() { return $this->hasOne(UserLevel::class, ['level' => 'level'])->andWhere(['status' => StatusEnum::ENABLED]); } public function getUserLevelTwo() { return $this->hasOne(UserLevel::class, ['level' => 'level', 'mall_id' => 'mall_id'])->andWhere(['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); } public function getUserDigital() { return $this->hasOne(UserDigital::class, ['user_id' => 'id'])->andWhere(['status' => StatusEnum::ENABLED]); } /** * 关联会员渠道信息 * @return \yii\db\ActiveQuery */ public function getUserTeamStatistics() { return $this->hasOne(UserTeamStatistics::class, ['user_id' => 'id']); } public function getParent() { return $this->hasOne(User::class, ['id' => 'parent_id']); } /** * 关联买点 */ public function getBuyingPoint() { return $this->hasMany(BuyingPointDay::class, ['user_id' => 'id']) ->where(['in', 'page_type', ['goods_detail', 'group_buy', 'bargain']]) ->select(['sum(browse_num) browse_num', 'user_id', 'item_id']) ->asArray() ->groupBy(['item_id']); } /** * 畅捷通请求 * * @return \yii\db\ActiveQuery */ public function getAddonsChanjetRequest() { return $this ->hasOne(AddonsChanjetRequest::class, ['table_id' => 'id']) ->orderBy('updated_at desc') ->select('id, table_id, request_status, updated_at') ->where([ 'table' => self::tableName(), 'path' => [Request::PATHS['PARTNER_CREATE_BATCH'], Request::PATHS['PARTNER_UPDATE']] ]) ->andWhere(['>', 'request_status', 0]); } /** * 管理后台会员详情 * @param $mall_id * @param $user_id * @return array */ public static function getUserDetail($mall_id, $user_id) { $user = self::getOne([['id'=>$user_id]],true,['parent']); $user_level = UserLevel::findOne(['level' => $user['level'], 'mall_id'=>$mall_id,'status' => [StatusEnum::ENABLED,StatusEnum::DISABLED]]); $area = UserExtra::findOne(['user_id' => $user_id]); $user_address = UserAddress::findOne(['user_id' => $user_id, 'is_default' => 1, 'status' => StatusEnum::ENABLED]); if (!empty($area)) $area = $area->toArray(); $user['source'] = (self::$sources)[$user['source']]; $user['area']['province'] = ''; $user['area']['city'] = ''; $user['area']['area'] = ''; $user['remark'] = ''; $user['all_platform'] = UserLoginLog::getAllPlatform($user_id); $user['birthday'] = ''; $user['wechat'] = ''; $user['sex'] = ''; $user['id_card'] = ''; $user['sex_text'] = ''; $user['team'] = []; if (!empty($area)) { $user['area']['province'] = $area['province']; $user['area']['city'] = $area['city']; $user['area']['area'] = $area['area']; $user['remark'] = $area['remark']; $user['birthday'] = $area['birthday']; $user['wechat'] = $area['wechat']; $user['sex'] = $area['sex']; $user['id_card'] = $area['id_card']; $user['sex_text'] = !empty(UserExtra::SEX_ARR[$area['sex']]) ? UserExtra::SEX_ARR[$area['sex']] : ''; } $user['level'] = !empty($user_level['name']) ? $user_level['name'] : MallSetting::getDefaultLevelName($mall_id); $user['address'] = !empty($user_address) ? $user_address['province'].$user_address['city'].$user_address['district'].$user_address['town'].$user_address['detail'] : ''; $user['platform'] = !empty(self::TYPE_NAME_LIST[$user['platform']]) ? self::TYPE_NAME_LIST[$user['platform']] : ''; $user['buy_power'] = []; $parent = $user['parent']; $user['parent_nickname'] = empty($parent) ? '' : ($parent['nickname']?$parent['nickname']:$parent['id']); $user['interest'] = []; //$user['tag'] = UserTagRelate::getUserTagList($mall_id, $user_id); $where[] = ['=','user_id',$user_id]; $where[] = ['=','mall_id',$mall_id]; $where[] = ['=','status',StatusEnum::ENABLED]; $with = ['userLabel' => function($qurey){ $qurey->select('name,id,color'); }]; $user['tag'] = UserLabelRelationship::lists(['where' =>$where,'with' => $with,'select' => 'label_id,status,id'],true); if (!empty($user['tag'])) { // 过滤到标签中 userLabel为 null的数据 $user['tag'] = array_filter($user['tag'], function ($item) { return !empty($item['userLabel']); }); } $user_team_statistics = UserTeamStatistics::findOne(['user_id' => $user_id]); if (!empty($user_team_statistics)) { $user['team'] = [ 'team_count' => $user_team_statistics['user_team_total'], 'first' => $user_team_statistics['user_direct_total'], 'second' => $user_team_statistics['user_indirect_total'] ]; $user['buy_power'] = [ 'total_price' => !empty($user_team_statistics['pay_order_price_total']) ? $user_team_statistics['pay_order_price_total'] : '0.00', 'total_orders' => !empty($user_team_statistics['pay_order_total']) ? $user_team_statistics['pay_order_total'] : 0, 'unit_price' => !empty($user_team_statistics['order_total']) ? bcdiv($user_team_statistics['order_price_total'] / $user_team_statistics['order_total'], 1, 2) : '0.00', 'last_time' => !empty($order['created_at']) ? date('Y-m-d H:i:s', $order['created_at']) : '-', 'total_refund_price' => !empty($user_team_statistics['order_refund_price_total']) ? $user_team_statistics['order_refund_price_total'] : '0.00', 'total_refund_orders' => !empty($user_team_statistics['order_refund_total']) ? $user_team_statistics['order_refund_total'] : 0, ]; } $user['user_promote_identity'] = self::getUserPromoteIdentity($user_id,$mall_id); $user['user_property'] = User::property($mall_id, $user_id); $user['user_level_list'] = UserLevel::getListIndexByLevelColumn($mall_id); //会员期限 $user['user_level_expired'] = '-'; if($user_level && isset($user_level['is_open_expired']) && $user_level['is_open_expired']){ $user_level_expired = UserLevelExpired::findOne(['user_id'=> $user_id,'level'=>$user_level['level'],'status'=>StatusEnum::ENABLED]); if($user_level_expired){ $user['user_level_expired'] = date('Y-m-d H:i:s', $user_level_expired['expired_at']); } } // 判断是否显示我的客户 if (MallAddons::isInstall($mall_id, 'TeamData')) $user['is_show_my_customer'] = 1; $cateIdMap = MemberLabelEnum::getMap(); $userMemberLabelModel = UserMemberLabel::findOne(['user_id'=>$user_id]); $memberLabelList = []; if(!empty($userMemberLabelModel)){ $memberLabelIds = []; foreach ($cateIdMap as $cateId=>$val){ $memberLabelIds[]=$userMemberLabelModel['cate_id'.$cateId]; } $memberLabelList = MemberLabel::lists(['where'=>[['id'=>$memberLabelIds]],'select'=>'id,name,color']); } $user['userMemberLabel'] = $memberLabelList; $user['invite_code'] = UserInviteCode::find()->where(['and', ['mall_id' => $mall_id], ['user_id' => $user_id]])->select('code')->scalar() ?? ''; $user_info = UserInfo::findOne(['mall_id'=>$mall_id,'user_id'=>$user['id'],'platform'=>User::PLATFORM_WECHAT,'status'=>StatusEnum::ENABLED]); $is_follow = 0; if(!empty($user_info)){ $wechat_subscribe =WechatSubscribe::findOne(['mall_id'=>$mall_id,'from_user_name'=>$user_info['openid']]); if(!empty($wechat_subscribe)&&$wechat_subscribe['subscribe_status']==1){ $is_follow = '已关注'; } } $user['is_follow'] = $is_follow; return $user; } /** * 通过h5登录 * @param $params * @return array|bool|User|\yii\db\ActiveRecord */ public static function loginByH5($params) { try { $where[] = ['mall_id' => $params['mall_id']]; $where[] = ['status' => StatusEnum::ENABLED]; //$where[] = ['or', ['username' => $params['username']], ['mobile' => $params['username']]]; $where[] = ['mobile' => $params['username']]; $user = User::getUser($where); if (empty($user)) throw new Exception('账号不存在'); if (empty($params['password']) && empty($params['captcha'])) throw new Exception('必须选择一种登录方式'); if (!empty($params['password'])) { if (!\Yii::$app->getSecurity()->validatePassword(trim($params['password']), $user->password)) throw new Exception('密码错误'); } else { if (YII_ENV == 'prod') { if (!Sms::checkValidateCode($params['username'], $params['captcha'],Sms::SMS_TYPE_USER_LOGIN)) throw new Exception('验证码不正确'); } } $user->last_login_at = time(); $user->login_ip = ArrayHelper::get_client_ip(); $res = $user->save(); if ($res === false) throw new Exception(User::getStaticError()); return $user; } catch (\Exception $e) { self::$static_error = $e->getMessage(); return false; } } /** * 获取推荐人列表 * @param $params * @return array|bool|mixed|void */ public static function getCanBindInviter($params) { $parent_id = 0; if(empty($params['inviter_id'])&&empty($params['keyword'])){ }else{ $query = self::find()->where(['mall_id'=>$params['mall_id']]); if (!empty($params['inviter_id'])) $query->andWhere(['id'=>$params['inviter_id']]); if (!empty($params['keyword'])) $query->andWhere(['mobile'=>$params['keyword']]); $user =$query->one(); if(!empty($user)){ list($tree,$parent_deep,$all_tree, $all_tree_arr) = UserPartitionRelationship::getTree($user['id']); $parent_ids = []; foreach ($all_tree_arr as $item){ $parent_ids[]= Base64Helper::Base642dec($item); } if(!in_array($params['user_id'],$parent_ids))$parent_id = $user['id']; } } $user_list = User::listPage(['where' => [['mall_id' => $params['mall_id']], ['in', 'id', $parent_id], ['is_inviter' => 1]]]); if (!empty($user_list['list'])) { $user_level_arr = UserLevel::getUserLevelArr($params['mall_id']); foreach ($user_list['list'] as &$v) { $v['level_name'] = !empty($user_level_arr[$v['level']]) ? $user_level_arr[$v['level']] : MallSetting::getDefaultLevelName($params['mall_id']);; } } return $user_list; } /** * 修改推荐人,加锁 * @param $params * @throws \Exception */ public static function updateParentByLock($params) { if(!empty($params['parent_id'])){ $user_model = User::findOne($params['user_id']); if($user_model->parent_id==$params['parent_id']){ throw new \Exception('原上级与要修改的一样'); } \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK_CHANGE_RELATIONSHIP, RabbitMqEnum::CHANGE_RELATIONSHIP_QUEUE, $params, UserPartitionRelationship::class, 'changeRelationship'); }else{ $user_model = User::findOne($params['user_id']); if($user_model->parent_id==0){ throw new \Exception('上级已经是平台'); } \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK_CHANGE_RELATIONSHIP, RabbitMqEnum::CHANGE_RELATIONSHIP_QUEUE, $params, UserPartitionRelationship::class, 'changeRelationshipToPlatform'); } return true; } /** * 批量导入会员 * @param $params * @return array|bool */ public static function importUsers($params) { $t = Yii::$app->db->beginTransaction(); try { self::isCanImport($params['mall_id']); $csvImport = new CsvImportForm(); $data = $csvImport->setDataForm($params) ->setMaxCount(self::$max_count) ->setImportFieldConfig(self::$head_list) ->setColumnNum(self::$column_num) ->readCsvData(); if (!$data) throw new \Exception(CsvImportForm::getStaticError()); $success_counts = $fail_counts = 0; $counts = count($data); $fail_arr = []; $mobile_user_id_arr = []; $success_user_id_arr = []; $merge_arr = []; foreach ($data as $item) { if(!empty($item['balance'])){ $item['total_balance'] = $item['balance']; }else{ $item['balance'] = 0; $item['total_balance'] = 0; } if(!empty($item['score'])){ $item['total_score'] = $item['score']; }else{ $item['score'] = 0; $item['total_score'] = 0; } if(!empty($item['commission'])){ $item['total_commission'] = $item['commission']; }else{ $item['commission'] = 0; $item['total_commission'] = 0; } $param = $item; $param['platform'] = User::TYPE_MANUAL; $param['mall_id'] = $params['mall_id']; $param['source'] = User::SOURCE_ADD_PLATFORM; $password = substr($param['mobile'],-6,6); $param['username'] = $param['mobile']; $param['password'] = Yii::$app->getSecurity()->generatePasswordHash($password, 4); $merge_arr[] = $param; } // 数组组装 $user_merge = ArrayHelper::buildTree($merge_arr,'mobile', 'invite_mobile', 'child'); self::batchAddUsers('import', $params['mall_id'], $user_merge, $success_counts, $fail_arr, $fail_counts, $success_user_id_arr,$mobile_user_id_arr); $param['counts'] = $counts; $param['success_counts'] = $success_counts; $param['fail_counts'] = $fail_counts; $param['status'] = 1; $user_import_log_model = UserImportLog::setData($param); if (!$user_import_log_model) throw new \Exception(UserImportLog::getStaticError()); if (!empty($fail_arr)) { $res = UserImportFailLog::setData($fail_arr, $user_import_log_model->id); if (!$res) throw new \Exception(UserImportFailLog::getStaticError()); } $t->commit(); //触发余额+佣金+积分日志 self::importUserLog($merge_arr, $mobile_user_id_arr); // 触发注册成功事件,事务提交完成后触发 foreach ($success_user_id_arr as $user_id){ $event = new UserRegisterEvent($params['mall_id']); $data = ['user_id' => $user_id, 'platform' => User::TYPE_MANUAL]; Yii::$app->services->events->dispatch($event, $data, $event->listeners); } return ['counts' => $counts, 'success_counts' => $success_counts, 'fail_counts' => $fail_counts]; } catch (\Exception $e) { self::$static_error = $e->getMessage(); $t->rollBack(); return false; } } /** * 触发余额+佣金+积分日志 * @param array $data 导入用户信息数据 * @param array $mobile_user_id_arr 用户对于user_id * @return void * @throws \Exception */ public static function importUserLog(array $data, array $mobile_user_id_arr) { $insert_wallet = [];//插入数据 $mobile_list = array_keys($mobile_user_id_arr); foreach ($data as $val) { if (!in_array($val['mobile'], $mobile_list)) { continue; } $user_id = $mobile_user_id_arr[$val['mobile']]; $insert_wallet_item = [ 'mall_id' => $val['mall_id'], 'user_id' => $user_id, 'is_frozen' => false, 'source_table_id' => $user_id, 'from_type' => UserWalletEnum::RECHARGE, 'capital_type' => UserWalletEnum::IMPORT_RECHARGE_PLATFORM, ]; if (!empty($val['balance'])) {//余额 $insert_wallet_item['wallet_type'] = 'balance'; $insert_wallet_item['money'] = $val['balance']; $insert_wallet_item['source_table'] = 'balance_log'; $insert_wallet_item['desc'] = '后台批量导入余额'; $insert_wallet[] = $insert_wallet_item; } if (!empty($val['score'])) {//积分 $insert_wallet_item['wallet_type'] = 'score'; $insert_wallet_item['money'] = $val['score']; $insert_wallet_item['source_table'] = 'score_log'; $insert_wallet_item['desc'] = '后台批量导入积分'; $insert_wallet[] = $insert_wallet_item; } if (!empty($val['commission'])) {//佣金 $insert_wallet_item['wallet_type'] = 'commission'; $insert_wallet_item['money'] = $val['commission']; $insert_wallet_item['source_table'] = 'commission_log'; $insert_wallet_item['desc'] = '后台批量导入佣金'; $insert_wallet[] = $insert_wallet_item; } } if ($insert_wallet) UserWalletService::batchHandleByQueue($insert_wallet); } public static function importUsersSync($params) { $t = Yii::$app->db->beginTransaction(); try { self::isCanImport($params['mall_id']); $basePath = \Yii::$app->basePath; if (empty($_FILES) || !isset($_FILES['file'])) throw new \Exception('请上传csv文件'); $fileName = $_FILES['file']['name']; $tmpName = $_FILES['file']['tmp_name']; $basePath = $basePath . '/web/uploads/'; if (!is_dir($basePath))mkdir($basePath, 0775, true); $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); if ($ext != 'csv') throw new \Exception('请上传csv文件'); $uploadFile = $basePath . 'ADMIN-' . date('Y-m-d His') . '.' . $ext; //上传 move_uploaded_file($tmpName, $uploadFile); $success_counts = $fail_counts = 0; $counts = 0; $param['counts'] = $counts; $param['success_counts'] = $success_counts; $param['fail_counts'] = $fail_counts; $param['upload_file'] = $uploadFile; $param['mall_id'] = $params['mall_id']; $user_import_log_model = UserImportLog::setData($param); if (!$user_import_log_model) throw new \Exception(UserImportLog::getStaticError()); $t->commit(); $params = ['id'=>$user_import_log_model['id']]; Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK_IMPORT_USER, RabbitMqEnum::IMPORT_USER, $params, self::class, 'syncImportUser'); return ['counts' => $counts, 'success_counts' => $success_counts, 'fail_counts' => $fail_counts]; } catch (\Exception $e) { self::$static_error = $e->getMessage(); $t->rollBack(); return false; } } public static function isCanImport($mall_id){ $time = strtotime('2023-03-17 23:59:59'); $res = UserImportLog::find()->where(['mall_id'=>$mall_id,'status'=>3])->andWhere(['>=','created_at',$time])->one(); if(!empty($res)) throw new \Exception('等上一次导入执行完再导入'); } //异步执行 public static function syncImportUser($params){ if(empty($params['id'])) return false; $model = UserImportLog::findOne(['id' => $params['id']]); if (!empty($model['upload_file'])) { $upload_file = $model['upload_file']; $mall_id = $model['mall_id']; $cvsFile = fopen($upload_file, 'r'); //开始读取csv文件数据 $fail_arr = []; $success_counts = $fail_counts =$counts = $i = 0; $counts = 0; $success_user_id_arr = []; $data = [];// 初始化数据 $mobile_user_id_arr = []; while ($fileData = fgetcsv($cvsFile)) { $i++; if ($i == 1) continue;//过滤表头 $counts++; $mobile = 0; $commission = 0; $score = 0; $balance = 0; $nickname = ''; $invite_mobile = ''; $level = 0; foreach ($fileData as $k => &$val) { $val = mb_convert_encoding(trim($val), "UTF-8", "GBK"); switch ($k) { case 1: $nickname = !empty($val)?$val:''; break; case 2: $mobile = !empty($val)?trim($val):0; break; case 3: $invite_mobile = !empty($val)?$val:0; break; case 4: $balance = !empty($val)?$val:0; break; case 5: $score = !empty($val)?$val:0; break; case 6: $commission = !empty($val)?$val:0; break; case 7: $level = !empty($val) ? trim($val) : 0; break; } } $param['mall_id'] = $mall_id; $param['mobile'] = $mobile; $param['commission'] = $commission; $param['total_commission'] = $commission; $param['score'] = $score ?? 0; $param['total_score'] = $score; $param['balance'] = $balance; $param['total_balance'] = $balance; $param['invite_mobile'] = $invite_mobile; $param['platform'] = User::TYPE_MANUAL; $param['nickname'] = $nickname; $param['source'] = User::SOURCE_ADD_PLATFORM; $password = substr($param['mobile'], -6, 6); $param['username'] = $param['mobile']; $param['level'] = $level; $param['password'] = Yii::$app->getSecurity()->generatePasswordHash($password, 4); $data[] = $param; } // 数组组装 $user_merge = ArrayHelper::buildTree($data, 'mobile', 'invite_mobile', 'child'); self::batchAddUsers('syncImport', $mall_id, $user_merge, $success_counts, $fail_arr, $fail_counts, $success_user_id_arr, $mobile_user_id_arr); $model->counts = $counts; $model->success_counts = $success_counts; $model->fail_counts = $fail_counts; $model->status = 1; if (!$model->save()) throw new \Exception($model->getErrorMessage()); //触发余额+佣金+积分日志 self::importUserLog($data, $mobile_user_id_arr); if (!empty($fail_arr)) { $res = UserImportFailLog::setData($fail_arr, $model->id); if (!$res) throw new \Exception(UserImportFailLog::getStaticError()); } } } /** * 批量插入用户 * @Author: lun * @DateTime: 2023/8/3 0003 15:16 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param $users * @param int $success_counts * @param array $fail_arr * @param int $fail_counts * @throws Exception */ public static function batchAddUsers($type, $mall_id, $users, &$success_counts = 0, &$fail_arr = [], &$fail_counts = 0, &$success_user_id_arr = [],&$mobile_user_id_arr = []) { // 因为后面佣金等异步提交会增加金额所以前期数据要清除 $money_list = ['score', 'total_score', 'balance', 'total_balance', 'commission', 'total_commission']; foreach ($users as $user) { $fail_params = $user; unset($fail_params['child']);// 移除下级 // 将手机号验证改为国内及香港手机号验证 $combinedPattern = '/^(?:1[3-9]\d{9}|(?:\+852|00852)?\d{8})$/'; if (!preg_match($combinedPattern, $user['mobile'])) { $fail_params['reason'] = '手机号码错误'; list($fail_arr, $fail_counts) = UserImportFailLog::packFailArr($fail_params, $fail_arr, $fail_counts); } else { foreach ($money_list as $item) { unset($user[$item]); } $where = []; $where[] = ['mall_id' => $mall_id]; $where[] = ['mobile' => $user['mobile']]; if (!empty(User::getUser($where))) { $fail_params['reason'] = '手机号码已存在'; list($fail_arr, $fail_counts) = UserImportFailLog::packFailArr($fail_params, $fail_arr, $fail_counts); } else { // 保存用户 // 用户权重导入(判断权重是否存在) if (!empty($user['level'])) { $exists = UserLevel::findOne(['mall_id' => $mall_id, 'level' => $user['level'], 'status' => [StatusEnum::DISABLED, StatusEnum::ENABLED]]); if (!$exists) { $fail_params['reason'] = '用户权重不存在'; list($fail_arr, $fail_counts) = UserImportFailLog::packFailArr($fail_params, $fail_arr, $fail_counts); continue; } } $res = User::setData($user); if ($res) { $success_user_id_arr[] = $res['id']; $mobile_user_id_arr[$user['mobile']] = $res['id']; $success_counts++; if ($type == 'syncImport') {// 异步处理触发注册事件 $event = new UserRegisterEvent($mall_id); $data = ['user_id' => $res['id'], 'platform' => User::TYPE_MANUAL]; Yii::$app->services->events->dispatch($event, $data, $event->listeners); } } else { $fail_params['reason'] = User::getStaticError(); list($fail_arr, $fail_counts) = UserImportFailLog::packFailArr($fail_params, $fail_arr, $fail_counts); } } } // 子级用户处理 if (!empty($user['child'])) { self::batchAddUsers($type, $mall_id, $user['child'], $success_counts, $fail_arr, $fail_counts, $success_user_id_arr, $mobile_user_id_arr); } } } /** * 搜索用户 * @param $keywork * @param $mall_id */ public static function searchUser($params) { $query = self::find()->alias('u') ->where(['u.status' => StatusEnum::ENABLED, 'u.mall_id' => $params['mall_id']]); //默认不存在no_inviter字段,o2o门店插件添加技师时搜索用户传入参数,不限制需要邀请资格 if (empty($params['no_inviter'])) { $query->andWhere(['u.is_inviter' => 1]); } if (isset($params['keyword']) && !empty($params['keyword'])) { $query->andWhere(['or', ['like', 'nickname', $params['keyword']], ['like', 'mobile', $params['keyword']], ['like', 'id', $params['keyword']]]); } $list = $query->limit(20)->select('u.id,u.nickname,u.mobile')->asArray()->all(); foreach ($list as &$item) { if (empty($item['nickname'])) { $item['nickname'] = $item['mobile'] . "(id:{$item['id']})"; } } return $list; } /** * @desc:公众号绑定手机号 * @Author: hua * @Date: 2021/10/22 * @Time: 15:01 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @param int $is_check_code * @return array|false */ public function bind($params, $is_check_code = 0) { try { $mall_setting = Yii::$app->services->setting->mall->get($params['mall_id'], 'user'); $check_sms_code_value = $mall_setting['check_sms_code'] ?? 1; //手机验证码验证 if (YII_ENV == 'prod' && $check_sms_code_value) { //短信验证码 if (!Sms::checkValidateCode($params['mobile'], $params['captcha'],Sms::SMS_TYPE_MOBILE_BIND)) throw new Exception('验证码不正确'); } $where = [['mobile' => $params['mobile']], ['mall_id' => $params['mall_id']], ['status' => [StatusEnum::DISABLED, StatusEnum::ENABLED]]]; $user = User::getOne($where); $openid = \Yii::$app->request->headers->get('openid'); $where = []; $where['openid'] = $openid; $where['mall_id'] = $params['mall_id']; $where['status'] = StatusEnum::ENABLED; if (!empty($params["platform"])) $where['platform'] = $params["platform"]; $user_info = UserInfo::findOne($where); if (!empty($user)) { if (!empty($user_info)) { $res = UserInfo::findOne(['mall_id' => $params['mall_id'], 'user_id' => $user->id,'platform'=>$user_info->platform,'status'=>StatusEnum::ENABLED]); if (!empty($res)) throw new Exception('该手机号码已经被注册'); $user_info->user_id = $user->id; $user_info->save(); return \Yii::$app->services->apiAccessToken->getAccessToken($user, 'api'); } throw new Exception('手机号已被使用'); } else { //小鹅通特殊操作 if ($user_info && $user_info->user_id) { $params['id'] = $user_info->user_id; $user = User::getOne([['id' => $user_info->user_id], ['status' => [StatusEnum::DISABLED, StatusEnum::ENABLED]]]); if ($user && $user->parent_id) { $params['parent_id'] = $user->parent_id; } } $password = substr($params['mobile'],-6,6); $params['username'] = $params['mobile']; $params['password'] = \Yii::$app->getSecurity()->generatePasswordHash($password); $params['last_login_at'] = time(); if (!empty($user_info)) { $platform_data = json_decode($user_info->platform_data, true); $params['nickname'] = $params['avatar_url'] = ''; if(!empty($platform_data['nickname'])&&!empty($platform_data['headimgurl'])){ $params['nickname'] = (string)$platform_data['nickname']; $params['avatar_url'] = $platform_data['headimgurl']; } if(!empty($platform_data['nickName'])&&!empty($platform_data['avatarUrl'])){ $params['nickname'] = (string)$platform_data['nickName']; $params['avatar_url'] = $platform_data['avatarUrl']; } $params['platform'] = $user_info->platform??''; } $user = User::setData($params); if ($user == false) throw new Exception(User::getStaticError()); // 公众号授权手机触发注册事件 $event = new UserRegisterEvent($user->mall_id); $data = ['user_id' => $user->id, 'platform' => $user->platform]; \Yii::$app->services->events->dispatch($event, $data, $event->listeners); if (!empty($user_info)) { $user_info->user_id = $user->id; $user_info->save(); } \Yii::$app->user->login($user); // 触发登录成功事件,事务提交完成后触发 $event = new UserLoginEvent($user->mall_id); \Yii::$app->services->events->dispatch($event, ['mall_id' => $user->mall_id, 'nickname' => $user->nickname, 'user_id' => $user->id, 'platform' => $user->platform, 'ip' => ArrayHelper::get_client_ip()], $event->listeners); } return \Yii::$app->services->apiAccessToken->getAccessToken($user, 'api'); } catch (\Exception $e) { self::$static_error = $e->getMessage(); return false; } } /** * @desc:修改个人资料 * @Author: hua * @Date: 2021/10/28 * @Time: 9:56 * @Copyright: copyright (c) 2021 广东七件事集团 * @param array $params * @return User|false * @throws \yii\db\Exception */ public static function change(array $params) { $t = Yii::$app->db->beginTransaction(); try { $operator = ''; if (!empty($params['id'])) { $model = self::findOne(['id' => $params['id'], 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($model)) throw new Exception('服务不存在或已删除'); $old_mobile = $model['mobile']; $operator = $model['id']; } else { $model = new self(); $model->loadDefaultValues(); } if (!empty($params['birthday'])) $params['birthday'] = strtotime($params['birthday'] . ' 00:00:00'); if (!$model->load($params, '') || !$model->save()) throw new Exception($model->getErrorMessage()); if(!empty($old_mobile)&&!empty($params['mobile'])&&$params['mobile'] != $old_mobile){ $param['new_mobile'] = $params['mobile']; $param['old_mobile'] = $old_mobile; $param['operator'] = (string)$operator; $param['user_id'] = $params['id']; $param['mall_id'] = $params['mall_id']; $param['type'] = 1; ChangeMobileLog::setData($param); } $t->commit(); return $model; } catch (Exception $e) { $t->rollBack(); self::$static_error = $e->getMessage(); return false; } } /** * 异步导出至下载中心 * @Author zhenjianhua * @DateTime 2021-11-12 16:01:25 * @copyright: Copyright (c) 2020 广东七件事集团 * @param array $data * @return void */ public static function exportHandleOld(array $data) { date_default_timezone_set('PRC'); $download_id = $data['download_id'] ?? 0; $download = Download::findOne(['id' => $download_id]); if($download){ try{ $params = json_decode($download->params,true); $filename = $download->name; $type = $download->type; $mall_id = $params['mall_id']; $model = self::find(); $model->where(['mall_id'=>$params['mall_id']]); if (!empty($params['register_start'])) { $model->andWhere(['>=', 'created_at', strtotime($params['register_start'])]); } if (!empty($params['register_end'])) { $model->andWhere(['<=', 'created_at', strtotime($params['register_end'])]); } $model->with(['parent','userLevel'=>function($query)use($mall_id){ $query->where(['mall_id'=>$mall_id]); },'userWallet']); $fields = $params['fields']; $fields_arr = self::fieldsList(); $have_select_field_arr = []; foreach ($fields as $value){ $have_select_field_arr[]=$fields_arr[$value]; } $csv = new CsvTool(); $csv->filename = $filename; $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type); $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC; $csv->header = $have_select_field_arr; foreach ($model->batch() as $users) { // $users 是一个包含100条或小于100条用户表数据的数组 empty($csv->header) && $csv->header =array_keys($users[0]); $csv->data = array_map(function($user)use($fields){ $row = []; foreach ($fields as $field){ if($field=='platform'){ $temp = self::TYPE_NAME_LIST; if(!empty($user['platform'])&&!empty($temp[$user['platform']])){ $row[] = $temp[$user['platform']]??''; }else{ $row[] = $temp[$user['platform']] = ''; } }else if($field=='parent_mobile'){ $row[] = $user['parent']['mobile']??''; }else if($field=='level'){ $row[] = $user['userLevel']['name']??'默认等级'; }else if($field=='created_at'){ $row[] = !empty($user['created_at'])?date('Y-m-d H:i:s',$user['created_at']):''; }else if(in_array($field,['commission', 'balance', 'score'])){ $wallet = $user->userWallet; $row[] = $wallet[$field] ?? 0; }else{ if((isset($user[$field]))) $row[]=$user[$field]??''; } } return $row; },$users); $csv->export(); } $url = $csv->upload($params['mall_id'],$csv->relative_filename); $download->status = 2; $download->url = $url; $download->num = $csv->line_num; $download->size = $csv->file_size; $res = $download->save(); return true; }catch(Exception $e){ $download->status = 3; self::setStaticError($e->getMessage()); return false; } } } public static function exportHandle(array $data) { date_default_timezone_set('PRC'); $download_id = $data['download_id'] ?? 0; $download = Download::findOne(['id' => $download_id]); if($download){ try{ $params = json_decode($download->params,true); $isChanjetExport = !empty($params['is_chanjet_addons']); $filename = $download->name; $type = $download->type; $mall_id = $params['mall_id']; $fields = $params['fields']; $fields_arr = $isChanjetExport ? self::chanjetFieldsList() : self::fieldsList(); $have_select_field_arr = []; foreach ($fields as $value){ $have_select_field_arr[]=$fields_arr[$value]; } $csv = new CsvTool(); $csv->filename = $filename; $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type); $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC; $csv->header = $have_select_field_arr; $select = 'u.id,u.id as user_id,nickname,username,avatar_url,mobile,level,u.status,platform,u.is_inviter, balance,commission,u.source,score,u.created_at,u.parent_id'; $with = []; // 畅捷通导出 if ($isChanjetExport) { $with[] = 'addonsChanjetRequest'; $select .= ',u.updated_at,uw.frozen_commission'; $user_level_arr = UserLevel::getUserLevelArr($mall_id); } $query = User::find() ->alias('u') ->with($with) ->leftJoin(UserWallet::tableName() . 'uw', 'uw.user_id = u.id') ->where(['u.mall_id'=>$params['mall_id']]) ->andWhere(['u.status'=>[StatusEnum::ENABLED,StatusEnum::DISABLED]]); // 用户条件筛选搜索 // 根据用户id精准查找 if (!empty($params['user_id'])){ $query->andWhere(['u.id'=>$params['user_id']]); } //根据会员标签进行搜索 if (!empty($params['memberLabelIds'])){ $cateIdArr = []; foreach ($params['memberLabelIds'] as $value){ $temp_arr = explode('_', $value); $cateIdArr[$temp_arr[0]][] = $temp_arr[1]; } foreach ($cateIdArr as $cate_id => $memberLabelIds) { $query->andWhere(['uml.'.'cate_id' . $cate_id=>$memberLabelIds]); } $query->leftJoin(UserMemberLabel::tableName() . 'uml', 'uml.user_id = u.id'); } // 根据用户昵称或手机号码查找 if (!empty($params['nickname_or_mobile'])){ $query->andWhere([ 'OR', ['like', 'u.nickname', $params['nickname_or_mobile']], ['like', 'u.mobile', $params['nickname_or_mobile']], ]); } // 查找上级推荐人 if (!empty($params['parent_id'])){ $query->andWhere(['u.parent_id'=>$params['parent_id']]); } // 查找注册来源渠道 if (!empty($params['source']) && $params['source'] != 'all') { $query->andWhere(['u.platform'=>$params['source']]); } // 根据用户渠道查找 if (isset($params['channel']) && $params['channel'] != 'all'){ $query->andWhere(['u.platform'=>$params['channel']]); } // 查找注册时间 if (!empty($params['register_start'])) { $query->andWhere(['>=', 'u.created_at', strtotime($params['register_start'])]); } if (!empty($params['register_end'])) { $query->andWhere(['<=', 'u.created_at', strtotime($params['register_end'])]); } // 最后更新时间 if (!empty($params['update_start'])) { $query->andWhere(['>=', 'u.updated_at', strtotime($params['update_start'])]); } if (!empty($params['update_end'])) { $query->andWhere(['<=', 'u.updated_at', strtotime($params['update_end'])]); } // 查找余额范围 if (!empty($params['balance_start'])) { $query->andWhere(['>', 'uw.balance', $params['balance_start']]); } if (!empty($params['balance_end'])) { $query->andWhere(['<', 'uw.balance', $params['balance_end']]); } // 查找积分范围 if (!empty($params['score_start'])) { $query->andWhere(['>', 'uw.score', $params['score_start']]); } if (!empty($params['score_end'])) { $query->andWhere(['<', 'uw.score', $params['score_end']]); } // 查找佣金范围 if (!empty($params['commission_start']) && !empty($params['commission_end'])){ $query->andWhere(['between', 'uw.total_commission', $params['commission_start'], $params['commission_end']]); } if (!empty($params['commission_start']) && empty($params['commission_end'])){ $query->andWhere(['>', 'uw.total_commission', $params['commission_start']]); } if (empty($params['commission_start']) && !empty($params['commission_end'])){ $query->andWhere(['<', 'uw.total_commission', $params['commission_end']]); } // 黑名单 if (!empty($params['black'])) { $black = $params['black'] == 2 ? 1 : 0; $query->andWhere(['=', 'u.status', $black]); } //添加等级查询 $levels = UserLevel::getListIndexByLevelColumn($params['mall_id']); $data['levels'] = $levels; if (isset($params['level']) && $params['level'] !== ''){ $query->andWhere(['=', 'u.level', $params['level']]); } //根据会员标签进行搜索 if (!empty($params['lableValue'])){ $user_label_where = ['mall_id' =>$params['mall_id'],'status' => StatusEnum::ENABLED,'label_id' => $params['lableValue']]; $user_ids = UserLabelRelationship::find()->select("user_id")->where($user_label_where)->asArray()->column(); $query->andWhere([ 'u.id'=>$user_ids]); } // 查找上级推荐人手机号 if (isset($params['p_mobile']) && $params['p_mobile'] !== '') { $query->andWhere([ 'in', 'u.parent_id', User::find() ->where([ 'mall_id' => $mall_id, 'status' => [StatusEnum::ENABLED,StatusEnum::DISABLED] ]) ->andWhere(['like', 'mobile', $params['p_mobile']]) ->select('id') ->column() ]); } $with = ['parent','userLevel'=>function($qu)use($mall_id){ $qu->where(['mall_id'=>$mall_id, 'status' => StatusEnum::ENABLED]); }]; //导出选择了数字币 增加对应查询 if (in_array('digital', $params['fields'], true)) { $with['userDigital'] = function($query) { $query->select(['user_id', 'digital']); }; } $query->orderBy('u.id desc')->select($select) ->with($with); $i = 1; $page_size = 1000; $data_list = []; while ($users = $query ->offset(($i - 1) * $page_size)->groupBy('user_id')->limit($page_size)->asArray()->all()) { // $users 是一个包含100条或小于100条用户表数据的数组 empty($csv->header) && $csv->header =array_keys($users[0]); if((in_array('redpack',$fields)||in_array('frozen_redpack',$fields))&&MallAddons::isInstall($mall_id,'Redpack')){ $user_id_arr = array_column($users,'id'); $redpack_wallet_list = RedpackWallet::lists(['where'=>[['user_id'=>$user_id_arr],['status'=>StatusEnum::ENABLED]],'index'=>'user_id']); } foreach($users as $user){ $row = []; foreach ($fields as $field){ if($field=='platform'){ $temp = self::TYPE_NAME_LIST; if(!empty($user['platform'])&&!empty($temp[$user['platform']])){ $row[] = $temp[$user['platform']]??''; }else{ $row[] = $temp[$user['platform']] = ''; } }else if($field=='parent_mobile'){ $row[] = $user['parent']['mobile']??''; }else if($field=='level'){ $row[] = $user['userLevel']['name'] ?? MallSetting::getDefaultLevelName($mall_id); }else if($field=='created_at'){ $row[] = !empty($user['created_at'])?date('Y-m-d H:i:s',$user['created_at']):''; }else if(in_array($field,['commission', 'balance', 'score'])){ $row[] =$user[$field]??0; }else if(in_array($field,['redpack', 'frozen_redpack'])){ if(isset($redpack_wallet_list)&&isset($redpack_wallet_list[$user['id']])){ $row[] = $redpack_wallet_list[$user['id']][$field]; }else{ $row[] = 0; } }else if ($field === 'chanjet_updated_at') { if (isset($user['addonsChanjetRequest']['updated_at'])) { $row[] = date('Y-m-d H:i:s', $user['addonsChanjetRequest']['updated_at']); }else { $row[] = ''; } }else if ($field === 'chanjet_request_status') { if (isset($user['addonsChanjetRequest']['request_status'])) { $row[] = AddonsChanjetRequestEnum::getMap()[$user['addonsChanjetRequest']['request_status']] ?? ''; }else { $row[] = ''; } }else if ($field === 'level_name') { $row[] = empty($user_level_arr[$user['level']]) ? MallSetting::getDefaultLevelName($mall_id) : $user_level_arr[$user['level']]; }else if ($field === 'nickname') {//会员昵称太多特殊符号,发现有+这个符号加上某些特殊符号一起导出会导致文件乱码,现在把+替换成空格导出 $row[] = $user['nickname'] ? str_replace('+', ' ', $user['nickname']) : ''; }else if ($field === 'digital') { $user_digital = $user['userDigital'] ?? []; $row[] = $user_digital['digital'] ?? 0; } else{ if((isset($user[$field]))) $row[]=$user[$field]??''; } } $data_list[]=$row; } $i++; } $csv->data = $data_list; $csv->export(); $url = $csv->upload($params['mall_id'],$csv->relative_filename); $download->status = 2; $download->url = $url; $download->num = $csv->line_num; $download->size = $csv->file_size; $res = $download->save(); return true; }catch(Exception $e){ $download->status = 3; self::setStaticError($e->getMessage()); return false; } } } public static function fieldsList() { return [ 'platform' => '所属平台', 'id' => '用户ID', 'username' => '真实姓名', 'nickname' => '昵称', 'mobile' => '绑定手机号', 'level' => '会员等级', 'created_at' => '加入时间', 'parent_mobile' => '上级手机号码', 'commission'=> '佣金', 'balance' => '余额', 'score' => '积分', 'redpack' => '激活红包', 'frozen_redpack' => '冻结红包', 'digital' => '数字币', ]; } public static function chanjetFieldsList() { return [ 'id' => '会员ID', 'username' => '会员', 'mobile' => '手机号', 'level_name' => '会员等级', 'balance' => '余额', 'frozen_commission'=> '佣金', 'created_at' => '加入时间', 'updated_at' => '最后更新时间', 'chanjet_updated_at' => '最后推送时间', 'chanjet_request_status' => '推送状态', ]; } /** * @desc:推广身份 * @Author: hua * @Date: 2021/11/22 * @Time: 9:20 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $user_id * @param $mall_id * @return array */ public static function getUserPromoteIdentity($user_id, $mall_id) { $data = []; $addons_list = MallAddons::getEnableAddonsName($mall_id); $arr = [ [ 'addons'=>AddonsEnum::ADDONS_NAME_DISTRIBUTION, 'name'=>'分销商等级', 'model'=>Distribution::class ], [ 'addons'=>AddonsEnum::ADDONS_NAME_AGENT, 'name'=>'渠道等级', 'model'=>Agent::class ], [ 'addons'=>AddonsEnum::ADDONS_NAME_BOSS, 'name'=>'股东等级', 'model'=>AddonsBoss::class ], [ 'addons'=>AddonsEnum::ADDONS_NAME_BOSS_WEIGHT, 'name'=>'股东等级', 'model'=>\addons\BossWeight\common\models\AddonsBoss::class ] ]; $where = []; $where[]=['user_id'=>$user_id]; $where[]=['mall_id'=>$mall_id]; $where[]=['<>','status',StatusEnum::DELETE]; foreach ($arr as $item){ if(!in_array($item['addons'],$addons_list)) continue; if($item['addons']==AddonsEnum::ADDONS_NAME_BOSS_WEIGHT){ $with_key = 'bossLevel'; }else{ $with_key = lcfirst($item['addons']).'Level'; } $result = $item['model']::getOne($where,true,[$with_key=>function($query)use($mall_id){ $query->where(['mall_id'=>$mall_id])->andWhere(['<>','status',StatusEnum::DELETE]); }]); if (!empty($result)) { $data[] = [ 'name' => $item['name'], 'level_name' => $result[$with_key]['name']??'默认等级', 'time' => !empty($result['upgrade_level_at']) ? date('Y-m-d H:i:s', $result['upgrade_level_at']) : '-' ]; } } return $data; } /** * 用户资产 * @Author: lun * @DateTime: 2021/11/23 0023 19:12 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param $user_id */ public static function property($mall_id, $user_id) { // 查询用户资产 $user_wallet = UserWallet::findOne(['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED]); // 余额 $balance_name = Yii::$app->services->setting->mall->get($mall_id,'balance.balance_name'); $data[] = [ 'englists' => 'balance', 'name' => $balance_name, 'list' => [['name' => '可用'.$balance_name, 'val' => $user_wallet->balance], ['name' => '已使用', 'val' => $user_wallet->total_use_balance], ['name' => '已提现', 'val' => $user_wallet->balance_withdrawal]], ]; // 积分 $score_name = Yii::$app->services->setting->mall->get($mall_id,'score.score_name'); $data[] =[ 'englists' => 'score', 'name' => $score_name, 'list' => [['name' => '可用' . $score_name, 'val' => $user_wallet->score], ['name' => '已使用' . $score_name, 'val' => $user_wallet->total_use_score, '转余额' => '0']],// TODO 转余额功能暂未开发 ]; // 佣金 $data[] =[ 'englists' => 'commission', 'name' => '佣金', 'list' => [['name' => '当前佣金', 'val' => $user_wallet->commission], ['name' => '待结算', 'val' => $user_wallet->frozen_commission], ['name' => '已提现', 'val' => $user_wallet->commission_withdrawal]], ]; // 红包拓客 $is_install_redpack = MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_REDPACK); if($is_install_redpack){ // 红包拓客 $user_redpack = RedpackWallet::getOne([['mall_id' => $mall_id,'user_id' => $user_id,'status' => StatusEnum::ENABLED]],true); $data[] =[ 'englists' => 'redpack', 'name' => '红包', 'list' => [['name' => '当前可用激活红包', 'val' => $user_redpack['redpack'] ?? 0], ['name' => '可用冻结红包', 'val' => $user_redpack['frozen_redpack'] ?? 0], ['name' => '已使用激活红包', 'val' => $user_redpack['total_use_redpack'] ?? 0],['name' => '已使用冻结红包', 'val' => $user_redpack['total_use_frozen_redpack'] ?? 0]], ]; } // 优惠券 $is_install_coupon = MallAddons::isInstall($mall_id, 'Coupon'); if ($is_install_coupon) { //统计已经使用 $coupon_where = "acu.status = ".StatusEnum::ENABLED." and acu.user_id = ".$user_id; $coupon_where .= " and acu.giving_status <> 2"; $coupon_where .= " and acu.coupon_status = 2"; $coupon = AddonsCouponUserRelate::find() ->alias("acu") ->leftJoin(AddonsCoupon::tableName() . ' as ac', 'ac.id = acu.coupon_id') ->select('count(acu.id) num , acu.is_use') ->where($coupon_where) ->groupBy('acu.is_use') ->asArray() ->all(); // 统计门店已经使用 // $overdue_where = "end_time <".time()." and status = ".StatusEnum::ENABLED." and user_id = ".$user_id; $overdue_where = ['user_id' => $user_id, 'coupon_status' => AddonsCouponEnum::STATUS_EXPIRED]; $overdue_coupon = AddonsCouponUserRelate::find()->where($overdue_where)->count(); // 统计已失效 $failure_where = ['user_id' => $user_id, 'coupon_status' => AddonsCouponEnum::STATUS_FAILURE]; $failure_coupon = AddonsCouponUserRelate::find()->where($failure_where)->count(); $couponCount = []; foreach ($coupon as $v) $couponCount[$v['is_use']] = $v['num']; //统计已经过期(判断插件是否安装) if (MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_STORE)) { $storeCoupon = StoreCouponUserRelate::find() ->alias("acu") ->leftJoin(AddonsCoupon::tableName() . ' as ac', 'ac.id = acu.coupon_id') ->select(['sum(if(acu.is_use = 0, 1, 0)) as num', 'sum(if(acu.is_use = 1, 1, 0)) as used', 'sum(if(acu.coupon_status = 3, 1, 0)) as expire', 'sum(if(acu.coupon_status = 4, 1, 0)) as lose']) ->where($coupon_where) ->andWhere(['from_type' => 1]) ->asArray() ->one(); } else { $storeCoupon = [ 'num' => 0, 'used' => 0, 'expire' => 0, 'lose' => 0 ]; } $data[] =[ 'englists' => 'coupon', 'name' => '优惠券', 'list' => [ ['name' => '可使用', 'val' => ($couponCount['0'] + $storeCoupon['num']) ?? 0], ['name' => '已使用', 'val' => ($couponCount['1'] + $storeCoupon['used']) ?? 0], ['name' => '已过期', 'val' => ($overdue_coupon + $storeCoupon['expire'])], ['name' => '已失效', 'val' => ($failure_coupon + $storeCoupon['lose'])], ], ]; } // 次卡 $is_install_secondary_card = MallAddons::isInstall($mall_id, 'SecondaryCard'); if ($is_install_secondary_card) { $query = SecondaryCardOrder::find()->where(['mall_id'=>$mall_id,'user_id'=>$user_id,'status'=>StatusEnum::ENABLED])->andWhere(['>','open_time',0]); $can_query = clone $query; $can_use = $can_query->andWhere(['=','order_status',0])->andWhere(['>','verifiable_times',0])->count(); $use_query = clone $query; $use = $use_query->andWhere(['=','verifiable_times',0])->count(); $exp_query = clone $query; $exp = $exp_query->andWhere(['order_status'=>2])->count(); $data[] =[ 'englists' => 'secondary_card', 'name' => '次卡', 'list' => [['name' => '可使用', 'val' => $can_use ?? 0], ['name' => '已使用', 'val' => $use ?? 0], ['name' => '已过期', 'val' => $exp ?? 0]],// TODO 已过期优惠券暂无开发 ]; } //数字币 $digital_is_enable = \Yii::$app->services->setting->mall->get($mall_id, 'digital.is_enable'); if ($digital_is_enable) { $digital = UserDigital::getOne([['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED]], true); $digital_use = DigitalLog::find()->where([ 'mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED, 'change_type' => 'sub', 'from_type' => 'transfer', 'capital_type' => 'transfer_give', 'send_status' => DigitalLog::SEND_STATUS_NORMAL ]) ->sum('change_num'); $data[] =[ 'englists' => 'digital', 'name' => '数字币', 'list' => [['name' => '可使用', 'val' => $digital['digital'] ?? 0], ['name' => '已使用', 'val' => $digital_use ?? 0], ['name' => '待结算', 'val' => $digital['frozen_digital'] ?? 0]], ]; } return $data; } /** * 分片查询 * @Author: lun * @DateTime: 2021/12/4 0004 10:21 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @param $user_id * @param $offset * @param $limit * @return bool|mixed */ public static function batchGetUsers($params, $part, $limit){ $params['offset'] = ($part-1)*$limit; $params['limit'] = $limit; return self::lists($params); } /** * @desc:订单支付,获取发展资格 * @Author: hua * @Date: 2021/12/6 * @Time: 15:48 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param $user_id * @param $order * @return bool */ public static function getInviterByPay($mall_id, $user_id, $order){ $relation_setting = \Yii::$app->services->setting->mall->get($mall_id, 'user_relation_setting.relation_setting'); $is_inviter = 1; if (!empty($relation_setting)) { $relation_setting = json_decode($relation_setting, true); //付款后 if (!empty($relation_setting['status']) && !empty($relation_setting['buy_compute_way']) && $relation_setting['buy_compute_way'] == 1) { $user = User::findOne(['id' => $user_id]); if ($user->is_inviter) return true; $where = [ 'mall_id' => $mall_id, 'user_id' => $user_id, 'pay_status' => 1, 'order_status' => [OrderStatusEnum::PAY, OrderStatusEnum::SHIPMENTS, OrderStatusEnum::SING, OrderStatusEnum::ACCOMPLISH] ]; if (!empty($relation_setting['get_power_way']) && $relation_setting['get_power_way'] == 3) { User::getIsInviterByOr($user, $where, $order, $is_inviter, $relation_setting); } if (!empty($relation_setting['get_power_way']) && $relation_setting['get_power_way'] == 4) { //与 User::getIsInviterByAnd($user, $where, $order, $is_inviter, $relation_setting); } } } } /** * @desc:订单完成,获取发展资格 * @Author: hua * @Date: 2021/12/6 * @Time: 15:49 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mall_id * @param $user_id * @param $order * @return bool */ public static function getInviterByOrderFinish($mall_id, $user_id, $order){ $relation_setting = \Yii::$app->services->setting->mall->get($mall_id, 'user_relation_setting', 'relation_setting'); $is_inviter = 1; if (!empty($relation_setting['relation_setting'])) { $relation_setting = json_decode($relation_setting['relation_setting'], true); //订单完成 if (!empty($relation_setting['status']) && !empty($relation_setting['buy_compute_way']) && $relation_setting['buy_compute_way'] == 2) { $user = User::findOne(['id' => $user_id]); if ($user->is_inviter) return true; $where = [ 'mall_id' => $mall_id, 'user_id' => $user_id, 'pay_status' => 1, 'order_status' => [ OrderStatusEnum::ACCOMPLISH] ]; if (!empty($relation_setting['get_power_way']) && $relation_setting['get_power_way'] == 3) { User::getIsInviterByOr($user, $where, $order, $is_inviter, $relation_setting); } if (!empty($relation_setting['get_power_way']) && $relation_setting['get_power_way'] == 4) { //与 User::getIsInviterByAnd($user, $where, $order, $is_inviter, $relation_setting); } } } } /** * @desc:或 * @Author: hua * @Date: 2021/12/6 * @Time: 15:49 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $user * @param $where * @param $order * @param $is_inviter * @param $relation_setting * @return bool */ private static function getIsInviterByOr($user,$where,$order,$is_inviter,$relation_setting){ //或 //消费次数 if(!empty($relation_setting['buy_num_selected'])){ //消费次数 $counts = Order::find()->where($where)->count(); if ($counts >= $relation_setting['buy_num']){ $user->is_inviter = $is_inviter; $user->save(); return true; } } //消费金额 if(!empty($relation_setting['buy_price_selected'])){ $total_pay_money = Order::find()->where($where)->sum('pay_money'); if ($total_pay_money >= $relation_setting['buy_price']){ $user->is_inviter = $is_inviter; $user->save(); return true; } } //购买商品 if(!empty($relation_setting['buy_goods_selected'])){ $res = self::buyGoodsSelected($relation_setting,$order); if($res){ $user->is_inviter = $is_inviter; $user->save(); } } } /** * @desc:与 * @Author: hua * @Date: 2021/12/6 * @Time: 15:49 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $user * @param $where * @param $order * @param $is_inviter * @param $relation_setting * @return false */ private static function getIsInviterByAnd($user,$where,$order,$is_inviter,$relation_setting){ if(!empty($relation_setting['buy_num_selected'])){ //消费次数 $counts = Order::find()->where($where)->count(); if ($counts < $relation_setting['buy_num']) return false; } //消费金额 if(!empty($relation_setting['buy_price_selected'])){ $total_pay_money = Order::find()->where($where)->sum('pay_money'); if ($total_pay_money < $relation_setting['buy_price']) return false; } //购买商品 if($relation_setting['buy_goods_selected']){ $res = self::buyGoodsSelected($relation_setting,$order); if($res==false) return false; } $user->is_inviter = $is_inviter; $user->save(); return true; } /** * @desc:购买商品 * @Author: hua * @Date: 2021/12/6 * @Time: 15:49 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $relation_setting * @param $user * @param $is_inviter * @param $order * @return bool */ private static function buyGoodsSelected($relation_setting,$order){ if($relation_setting['buy_goods_way']==1){ return true; } if($relation_setting['buy_goods_way']==2){ $goods_id_arr = array_column($order['detail'],'goods_id'); $setting_goods_id_arr = $relation_setting['goods_ids'] ?? []; if(array_intersect($goods_id_arr,$setting_goods_id_arr)){ return true; } } if($relation_setting['buy_goods_way']==3){ $goods_id_arr = array_column($order['detail'],'goods_id'); $goods_cate_list = GoodsCateRelate::findAll(['goods_id'=>$goods_id_arr]); $cate_id_arr = array_column($goods_cate_list,'cate_id'); $setting_cate_ids = $relation_setting['cat_ids'] ?? []; if(array_intersect($cate_id_arr,$setting_cate_ids)){ return true; } } return false; } /** * 导出渠道人数 */ public static function exportTeamSizeHandle(array $data) { $download_id = $data['download_id'] ?? 0; $download = Download::findOne(['id' => $download_id]); if ($download) { try { $params = json_decode($download->params,true); $filename = $download->name; $type = $download->type; $where['where'][] = ['=', 'u.mall_id', $params['mall_id']]; $where['where'][] = ['=', 'u.status', StatusEnum::ENABLED]; if (isset($params['level'])) $where['where'][] = ['=', 'u.level', $params['level']]; if (isset($params['user_id']) && !empty($params['user_id'])) $where['where'][] = ['=', 'u.id', $params['user_id']]; if (isset($params['start_time']) && !empty($params['start_time']) && isset($params['end_time']) && !empty($params['end_time'])) { $where['where'][] = ['>=', 'u.created_at', strtotime($params['start_time'])]; $where['where'][] = ['<=', 'u.created_at', strtotime($params['end_time'])]; } if (isset($params['keyword']) && !empty($params['keyword'])) { $where['where'][] = [ 'or', ['like', 'u.nickname', $params['keyword']], ['like', 'u.mobile', $params['keyword']] ]; } $where['alias'] = 'u'; $where['select'] = ['u.id', 'u.nickname', 'u.mobile', 'u.level level_name', 'uts.user_team_total', 'uts.user_direct_total', 'uts.user_indirect_total', 'uts.team_finish_order_total','uts.team_finish_order_price_total',]; $where['order'] = 'u.id asc'; $where['join'] = [['LEFT JOIN', UserTeamStatistics::tableName() .' as uts', 'u.id=uts.user_id']]; $model = self::find(); self::paramPack($where, $model); $levels = UserLevel::getListIndexByLevelColumn($params['mall_id'], [StatusEnum::ENABLED, StatusEnum::DISABLED]); $list = []; foreach ($model->asArray()->each(500) as $l) { $l['level_name'] = $levels[$l['level_name']] ?? MallSetting::getDefaultLevelName($download->mall_id); $l['user_team_total'] = $l['user_team_total'] ?? 0; $l['user_direct_total'] = $l['user_direct_total'] ?? 0; $l['user_indirect_total'] = $l['user_indirect_total'] ?? 0; $l['team_finish_order_total'] = $l['team_finish_order_total'] ?? 0; $l['team_finish_order_price_total'] = $l['team_finish_order_price_total'] ?? 0; $list[] = $l; } if (!empty($list)) { $csv = new CsvTool(); $csv->filename = $filename; $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type); $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC; $csv->header = ['用户ID', '昵称', '手机号','等级','渠道人数', '好友人数', '粉丝人数', '渠道订单数', '团队总业绩']; $csv->data = $list; $csv->export(); $csv->updateDown($download, $params['mall_id']); } } catch (\Exception $e) { $download->status = 3; $res = $download->save(); self::setStaticError($e->getMessage()); return false; } } } /** * @param $params * @return true * @throws Exception */ public static function updateMobile($params){ //检验新的手机号 $user = User::findOne(['id'=>$params['user_id'],'mall_id'=>$params['mall_id'],'status'=>[StatusEnum::ENABLED,StatusEnum::DISABLED]]); if(empty($user)) throw new Exception('会员不存在'); if($params['mobile'] == $user->mobile) throw new \Exception('手机号与原手机号一致'); // 如果有安装 好玩小镇那么就需要判断是否能使用当前号码 if (MallAddons::isInstall($params['mall_id'], AddonsEnum::ADDONS_NAME_FUN_TOWN)) { GameAsyncHelper::validMobile($params['mall_id'], $params['mobile']); } $old_mobile = $user->mobile; $where[] = ['mall_id' => $params['mall_id']]; $where[] = ['mobile' => $params['mobile']]; $where[] = ['status' => [StatusEnum::ENABLED,StatusEnum::DISABLED]]; if (User::getUser($where)) throw new \Exception( '手机号码已注册'); //验证码 $user->mobile = $params['mobile']; $user->username = $params['mobile']; $res = $user->save(); if(empty($res)) throw new \Exception('修改失败'); $params['new_mobile'] = $params['mobile']; $params['old_mobile'] = $old_mobile; $params['type'] = 1; ChangeMobileLog::setData($params); // 触发用户信息修改事件 $event = new UserUpdateEvent($params['mall_id']); Yii::$app->services->events->dispatch( $event, [ 'user_id'=>$params['user_id'], 'mall_id' => $params['mall_id'], 'old_mobile' => $old_mobile, 'is_admin' => true, 'operator_user_id' => $params['operator_user_id'] ], $event->listeners ); return true; } public static function getInviterMsg($mallId, $allowInviter) { $inviter_msg = []; $config = Yii::$app->services->setting->mall->get($mallId, 'poster_setting.is_create_poster'); if (!empty($config)) { $setting = json_decode($config, true); if (!empty($setting['value']) && $setting['value'] == 2) {// 无推广资格,并且不允许推广 $allowInviter = 0; $relation_setting = \Yii::$app->services->setting->mall->get($mallId, 'user_relation_setting.relation_setting'); if (!empty($relation_setting)) { $relation_setting = json_decode($relation_setting, true); // get_power_way【1=无条件,3=或,4=与】 switch ($relation_setting['get_power_way']) { case 3: $inviter_msg[] = "需满足以下任意条件即可推广!"; break; case 4: $inviter_msg[] = "需满足以下所有条件即可推广!"; break; default: $inviter_msg[] = "您暂无推广资格"; break; } if ($relation_setting['buy_num_selected'] == 1) $inviter_msg[] = "消费次数:{$relation_setting['buy_num']}次"; if ($relation_setting['buy_price_selected'] == 1) $inviter_msg[] = "消费金额:{$relation_setting['buy_price']}元"; // 1=任意商品,2=指定商品,3=指定商品分类 switch ($relation_setting['buy_goods_way']) { case 1: $inviter_msg[] = "购买商城任意商品"; break; case 2: $goods_msg = ''; if($relation_setting['goods_list']){ foreach ($relation_setting['goods_list'] as $goods) { $goods_msg .= "【{$goods['name']}】"; } } $inviter_msg[] = "购买:{$goods_msg}商品"; break; case 3: $cat_msg = ''; foreach ($relation_setting['cat_list'] as $cat) { $cat_msg .= "【{$cat['label']}】"; } $inviter_msg[] = "购买:【{$cat_msg}】分类商品"; break; } } } } return [$allowInviter, $inviter_msg]; } //发送公众号消息 // $send_message_data = ['user_id'=>$user_id, 'mall_id' => $data['mall_id']],]; public static function teamAddSendMessage($send_message_data){ $mall_id = $send_message_data['mall_id']; $user_id = $send_message_data['user_id']; $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id); if(empty($parent_id_arr))return false; foreach ($parent_id_arr as $parent_id){ $user_info = UserInfo::findOne(['mall_id' => $mall_id, 'user_id' => $parent_id, 'status' => StatusEnum::ENABLED,'platform'=>'wechat']); if (empty($user_info)) return false; $h5 = \Yii::$app->services->setting->mall->get($mall_id, 'basic.web_url'); if (empty($h5)) return false; $mall = Mall::findOne(['id'=>$mall_id]); if(empty($mall)) return false; $h5 = substr($h5, 0, strpos($h5, '?')); $url = $h5.'plugins/public/promotion/client'; WechatHelper::sendTemplateMessage($mall_id,'team_add',$user_info['openid'],$url,[]); } } public static function withdrawalSuccessSendMessage($send_message_data){ $mall_id = $send_message_data['mall_id']; $user_id = $send_message_data['user_id']; $type = $send_message_data['type']; $user_info = UserInfo::findOne(['mall_id' => $mall_id, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED,'platform'=>'wechat']); if (empty($user_info)) return false; $h5 = \Yii::$app->services->setting->mall->get($mall_id, 'basic.web_url'); if (empty($h5)) return false; $mall = Mall::findOne(['id'=>$mall_id]); if(empty($mall)) return false; $h5 = substr($h5, 0, strpos($h5, '?')); $url = $h5.'plugins/pages/assets/balance/list?type=2'; WechatHelper::sendTemplateMessage($mall_id,'withdrawal_success',$user_info['openid'],$url,[]); } public static function addBlacklist($params){ $t = null; try { $user_ids = explode(',', $params['user_id']); $list = User::lists(['where'=>[['in', 'id',$user_ids]]],false); $isEnable = !empty($params['status']) && $params['status']==StatusEnum::ENABLED; if ($isEnable) { $delLogList = UserDelLog::find() ->where([ 'user_id' => $user_ids, 'is_recovered' => StatusEnum::DISABLED, 'mall_id' => $params['mall_id'] ]) ->select('user_id, old_mobile') ->indexBy('user_id') ->asArray() ->all(); $registeredMobiles = self::find() ->select('mobile') ->where([ 'mobile' => array_column($delLogList, 'old_mobile'), 'status' => StatusEnum::ENABLED, 'mall_id' => $params['mall_id'] ]) ->column(); } $t = Yii::$app->db->beginTransaction(); foreach ($list as $user){ // 查询手机号有没有被注册,注册了则不能恢复 if ($isEnable && isset($delLogList[$user->id])) { if (in_array($delLogList[$user->id]['old_mobile'], $registeredMobiles)) { throw new \Exception('该用户手机号已被占用,不允许恢复!'); } // 是否是被注销删除的用户,如果是则恢复 self::recoveryUser($user); } $user->status = $params['status']; $user->save(); } if(empty($params['status'])){ self::disableAccessToken($user_ids); } $t->commit(); return true; }catch (\Exception $e){ isset($t) && $t->rollBack(); throw new \Exception($e->getMessage()); } } /** * 检查是否被注销,如果被注销将其恢复 * * @param $user * * @return void * @throws \Exception */ protected static function recoveryUser($user) { $user_del_log = UserDelLog::find()->where(['user_id' => $user->id, 'is_recovered' => StatusEnum::DISABLED])->one(); if (!$user_del_log) { return; } $user_del_log->is_recovered = StatusEnum::ENABLED; $user_del_log->recover_time = time(); $user_del_log->save(); if ($user->username == $user_del_log->new_mobile) { $user->username = $user_del_log->old_mobile; } $user->mobile = $user_del_log->old_mobile; UserInfo::updateAll(['status'=>StatusEnum::ENABLED],['user_id'=>$user->id]); } protected static function disableAccessToken($user_ids) { $access_token_list = AccessToken::lists(['where'=>[ ['user_id'=>$user_ids], ['group'=>'api'] ], 'index'=>'user_id' ]); foreach ($access_token_list as $item){ $access_token = $item['access_token']; Yii::$app->cache->delete(Yii::$app->services->apiAccessToken->getCacheKey($access_token)); } AccessToken::updateAll(['status'=>StatusEnum::DISABLED],['user_id'=>$user_ids,'group'=>'api']); return true; } /** * @param integer $mall_id * @param string $keyword * @return static */ public static function getUserModelByKeyword(int $mall_id, string $keyword, string $field = 'id') { return static::find() ->select($field) ->where(['mall_id' => $mall_id]) ->andWhere([ 'or', ['like', 'nickname', $keyword], ['like', 'mobile', $keyword], ]); } /** * @param integer $mall_id * @param string $keyword * @param string $field * @return array */ public static function getUserIdsByKeyword(int $mall_id, string $keyword) { return static::getUserModelByKeyword( $mall_id, $keyword, 'id' )->column(); } /** * 更改用户登录设备 * * @param integer $id * @param string $device_type * @param string $device_mac * @return int */ public static function updateLoginDevice(int $id, string $device_type, string $device_mac) { return static::updateAll(['device_type' => $device_type, 'device_mac' => $device_mac], ['id' => $id]); } /** * 获取用户父级 * * @param integer $id * @return ActiveRecord|array|null a single row of query result. Depending on the setting of [[asArray]], */ public static function getUserParents(int $id) { return static::find() ->select(['parent_id', 'second_parent_id', 'third_parent_id']) ->where(['id' => $id, 'status' => StatusEnum::ENABLED]) ->one(); } /** * @param int $mallId * @param int $userId * * @return false|int|string|null */ public static function getUserMobile(int $mallId, int $userId) { return static::find() ->where([ 'status' => [StatusEnum::DISABLED, StatusEnum::ENABLED], 'mall_id' => $mallId, 'id' => $userId ]) ->select('mobile') ->scalar() ?: ''; } public function getUserLevelExpired() { return $this ->hasMany(UserLevelExpired::class, ['user_id' => 'id']) ->where(['status' => StatusEnum::ENABLED]) ->select('user_id, level, expired_at'); } public static function searchWhereIds(int $mall_id, $keyword) { return self::find()->where(['mall_id' => $mall_id]) ->andWhere(['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]) ->andWhere(['or', ['like', 'nickname', $keyword], ['like', 'mobile', $keyword], ['like', 'id', $keyword]])->select('id')->column(); } /** * 获取团队中对应层级有多少人数 * @param $user_id //会员id * @param $level //查询层级 * @return false|int|string|null */ public static function getTeamlevelCount($user_id,$level){ list($tree,$parent_deep,$all_tree, $all_tree_arr) = UserPartitionRelationship::getTree($user_id); $count = (new \yii\db\Query()) ->select(['COUNT(DISTINCT u.id) as count']) ->from(['u' => 'qimall_user']) ->innerJoin(['upr' => 'qimall_user_partition_relationship'], 'u.id = upr.user_id') ->where(['u.level' => $level,'u.status'=>StatusEnum::ENABLED]) ->andWhere(['like', 'upr.tree', "{$tree},%", false]) ->scalar(); return $count; } }