// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\common\model; use app\common\enum\user\AccumulatePointsScene; use app\common\model\user\AccumulatePointsLog; use app\common\library\helper; use app\common\model\store\Setting as SettingModel; use app\common\model\user\CommissionsDetail; use app\common\model\user\PointsLog as PointsLogModel; use app\common\model\user\UserIdcards; use app\common\service\BaseService; use think\Exception; use think\facade\Log; use think\model\relation\BelongsTo; use think\model\relation\HasMany; use think\model\relation\HasOne; /** * 用户模型类 * Class User * @package app\common\model */ class User extends BaseModel { // 定义表名 protected $name = 'user'; // 定义主键 protected $pk = 'user_id'; // 性别 private $gender = [0 => '未知', 1 => '男', 2 => '女']; // 用户角色 const ROLE_ARR = [1 => '普通用户', 2 => '店老板', 3 => '店长', 4 => '店员', 5 => '厨师',99=>'推荐官']; const COMMISSION_ARR = [1 => '普通推荐官', 2 => '高级推荐官', 3 => '超级推荐官']; const NORMAL_USER = 1; const SHOP_BOSS = 2; const SHOP_MG = 3; const SHOP_SELLER = 4; const SHOP_CHEF = 5; const COMMISSION_USER = 99; /*用户活动来源 start*/ const ACT_SOURCE_PROMOTION_MONITOR = 1; // 渠道推广 const ACT_SOURCE_GROUP_BUY = 2;//拼团活动 const ACT_SOURCE_KJ = 3;//砍价活动 const ACT_SOURCE_GROUP_BUY_LB = 4;//拼团裂变活动 /*用户活动来源 end*/ //TODO 有新增活动来源时请补充下面的 ACT_SOURCE_OPTIONS const ACT_SOURCE_OPTIONS = [0 => '未区分来源', 1 => '渠道推广',2 => '拼团活动', 3 => '砍价活动',4=>'拼团裂变']; /** * 关联用户头像表 * @return HasOne */ public function avatar() { return $this->hasOne('uploadFile', 'file_id', 'avatar_id') ->bind(['avatar_url' => 'preview_url']); } /** * 关联会员等级表 * @return BelongsTo */ public function grade() { $module = self::getCalledModule(); return $this->belongsTo("app\\{$module}\\model\\user\\Grade", 'grade_id'); } /** * 关联收货地址表 * @return HasMany */ public function address() { return $this->hasMany('UserAddress'); } /** * 关联收货地址表 (默认地址) * @return BelongsTo */ public function addressDefault() { return $this->belongsTo('UserAddress', 'address_id'); } public function shops() { return $this->hasOne('Shops', 'shop_id', 'shop_id'); } public function bindShops() { return $this->hasOne('Shops', 'shop_id', 'bind_shop_id'); } public function upperUser() { return $this->hasOne('User', 'user_id', 'upper_user_id'); } public function idcard() { return $this->hasOne(UserIdcards::class, 'user_id', 'user_id'); } /** * 获取器:显示性别 * @param $value * @return mixed */ public function getGenderAttr($value) { return $this->gender[$value]; } public function getRoleTextAttr($value, $data) { $role = $data['role']??1; if ($role == self::COMMISSION_USER){ return self::COMMISSION_ARR[$data['seller_grade']??1]; } return self::ROLE_ARR[$role] ?? ''; } public function getWjsyjAmountAttr(){ $sum_fc_amount = CommissionsDetail::where("user_id",$this->user_id)->where("clearing_status",0)->sum('clearing_money'); return $sum_fc_amount; } public function getLastLoginTimeAttr($value) { return $value ? date('Y-m-d H:i:s') : ''; } /** * 获取用户信息 * @param $where * @param array $with * @return array|null|static */ public static function detail($where, $with = []) { $filter = ['is_delete' => 0]; if (is_array($where)) { $filter = array_merge($filter, $where); } else { $filter['user_id'] = (int)$where; } return static::get($filter, $with); } /** * 累积用户的实际消费金额 * @param int $userId * @param $expendMoney * @return mixed */ public static function setIncUserExpend(int $userId, float $expendMoney) { return (new static)->setInc($userId, 'expend_money', $expendMoney); } /** * 累积用户可用余额 * @param int $userId * @param $money * @return mixed */ public static function setIncBalance(int $userId, float $money) { return (new static)->setInc($userId, 'balance', $money); } /** * 消减用户可用余额 * @param int $userId * @param $money * @return mixed */ public static function setDecBalance(int $userId, float $money) { return (new static)->setDec([['user_id', '=', $userId]], 'balance', $money); } /** * 指定会员等级下是否存在用户 * @param int $gradeId * @return bool */ public static function checkExistByGradeId(int $gradeId) { $model = new static; return (bool)$model->where('grade_id', '=', (int)$gradeId) ->where('is_delete', '=', 0) ->value('user_id'); } /** * 累积用户总消费金额 * @param int $userId * @param $money * @return mixed */ public static function setIncPayMoney(int $userId, float $money) { return (new static)->setInc($userId, 'pay_money', $money); } /** * 累积用户实际消费的金额 (批量) * @param array $data * @return bool */ public function onBatchIncExpendMoney(array $data) { foreach ($data as $userId => $expendMoney) { static::setIncUserExpend($userId, (float)$expendMoney); } return true; } /** * 累积用户的可用积分数量 (批量) * @param array $data * @return bool */ public function onBatchIncPoints(array $data) { foreach ($data as $userId => $value) { $this->setInc($userId, 'points', $value); } return true; } public static function setIncGrowthValue($user,$money){ if($user['member_expire_time']>time()){ //有会员并且未过期 //用户直接添加用户积分 $growth_value = SettingModel::getItem('member_growth')['growth_value']; $num = helper::bcmul($money,$growth_value); return (new static)->setInc($user['user_id'], 'growth_value', (float)$num); } } /** * 累积用户的可用积分 * @param int $userId 用户ID * @param int $points 累计的积分 * @param string $describe * @return mixed */ public static function setIncPoints(int $userId, int $points, string $describe) { // 新增积分变动明细 PointsLogModel::add([ 'user_id' => $userId, 'value' => $points, 'describe' => $describe, ]); // 更新用户可用积分 return (new static)->setInc($userId, 'points', $points); } /** * @param int $userId * @param int $payMoney 支付金额 * @param int $scene 积分场景 * @param string $describe * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public static function setIncAccumulatePoints(int $userId, string $payMoney, int $scene = AccumulatePointsScene::RECHARGE, string $describe = '') { $rate = SettingModel::getItem('points_rate')['points_rate']; $points = bcmul(strval($payMoney),$rate,0); // 新增积分变动明细 AccumulatePointsLog::add([ 'user_id' => $userId, 'value' => $points, 'scene' => $scene, 'describe' => $describe, ]); // 更新用户可用积分 return (new static)->setInc($userId, 'accumulate_points', intval($points)); } /** * 积分扣减 * @param int $userId * @param float $payMoney * @param int $scene * @param string $describe * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public static function setDecAccumulatePoints(int $userId, string $payMoney, int $scene = AccumulatePointsScene::RECHARGE, string $describe = '') { $rate = SettingModel::getItem('points_rate')['points_2_money']; $points = bcmul(strval($payMoney),$rate,0); // 新增积分变动明细 AccumulatePointsLog::add([ 'user_id' => $userId, 'value' => $points, 'scene' => $scene, 'describe' => $describe, ]); // 更新用户可用积分 return (new static)->setDec($userId, 'accumulate_points', intval($points)); } /** * 多字段增减 * @param array|int|bool $where 支持自增ID 也支持where语句 * @param array $incData //自增字段 * @param array $decData //自减字段 * @param array $data //正常update字段 * @return mixed */ public static function setIncDecByField($where, $incData , $decData, $data=[]) { return (new static)->setIncDec($where, $incData, $decData, $data); } /** * 字段递减 * @param array|int|bool $where 支持自增ID 也支持where语句 * @param string $field //字段 * @param float $step // * @param array $data //正常update字段 * @return mixed */ public static function setDecByField($where, string $field, float $step = 1) { return (new static)->setDec($where, $field, $step); } /** * 字段递增 * @param array|int|bool $where 支持自增ID 也支持where语句 * @param string $field //字段 * @param float $step // * @param array $data //正常update字段 * @return mixed */ public static function setIncByField($where, string $field, float $step = 1) { return (new static)->setInc($where, $field, $step); } /** * 创建新用户通过手机号,用于管理后台门店管理模块 * 注:该方法只适用于后台门店管理创建新用户 * @param $nickname * @param $mobile * @param int $shopsId * @param int $role * @return false|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public static function createUserByMobile($nickname,$mobile,$shopsId=0, int $role=self::NORMAL_USER,$bindShopId = \app\store\model\Shops::ZD_SHOP_ID){ Log::error(__METHOD__.',role ---:'.$role); $oldUser = User::where('mobile', $mobile)->find(); if ($oldUser && !$oldUser->isEmpty()){ $userId = $oldUser->getAttr('user_id'); // 要清空上级关系 $up = [ 'upper_user_id' => 0, 'bind_shop_id' => 0 ]; if ($oldUser->getAttr('role') != $role){ $up['role'] = $role; $up['shop_id'] = $shopsId; } User::where('user_id',$userId)->update($up); return $userId; } //上级用户id,店铺id,角色身份 $user = new self(); //$data = ['nick_name'=>$nickname,'mobile'=>$mobile,'shop_id'=>$shopsId,'role'=>$role,"store"=>getStoreId()]; try { //需要在名厨数据库加用户 $postData = [ 'mobile' => $mobile, 'openid' => "", 'source' => 12 ]; $res = curl_post(config('chef.serv_cookhome').'/api/wx/third_platform_register', $postData); if ($res == false){ Log::error($mobile.'系统繁忙'); return false; } $res = json_decode($res, true); // 获取名厨用户id if (!isset($res['id']) || !$res['id']){ Log::error($mobile.'系统繁忙'); return false; } $chef_user_id = $res['id']; Log::error(__METHOD__.',role ---:'.$role); $user->user_id = $chef_user_id; $user->nick_name = $nickname; $user->mobile = $mobile; $user->shop_id = $shopsId; $user->bind_shop_id = 0; $user->role = $role; $user->store = getStoreId(); $user->save(); }catch (\Exception $e){ Log::error($e->getMessage()); return false; } return $user->user_id; } /** * @param $shopId * @param $roles * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public static function getCommissionUsers($shopId,$roles): array { return self::where('shop_id',$shopId)->whereIn('role',$roles)->field('user_id,role')->select()->toArray(); } /** * 店员交接 * @param $userId * @param $role * @return bool */ public function updateUserRole($userId,$role=self::NORMAL_USER){ User::where('user_id',$userId)->update(['role'=>$role,'shop_id'=>0]); return true; } /** * 交接顾客 * @param $userId * @param $toUserId * @param $shopId * @return bool */ public function consumersHandover($userId,$toUserId,$shopId){ $count = User::where('upper_user_id',$userId)->where('bind_shop_id',$shopId)->count(); User::where('upper_user_id',$userId)->where('bind_shop_id',$shopId)->update(['upper_user_id'=>$toUserId]); return $count; } /** * 生成虚拟手机号 * @return string */ public static function makeVirtualMobile($type) { $last = Shops::where('is_virtual', Shops::SHOP_TYPE_VIRTUAL)->count(); $prefix = "YSCV"; // $mobile = $prefix.time().rand(100, 999); $mobile = $prefix."166".str_pad((string)($last+1),7,"0",STR_PAD_LEFT).$type; // 检查是否存在 if (User::where('mobile', $mobile)->count() > 0) { return false; } return $mobile; } /** * 生成虚拟名字 * @return string */ public static function makeVirtualName($prefix = '') { $last = Shops::where('is_virtual', Shops::SHOP_TYPE_VIRTUAL)->count(); $name = $prefix.str_pad((string)($last+1),2,"0",STR_PAD_LEFT); return $name; } /** *获取未下过单的用户ID */ public static function getNewUserIds(){ $lists = self::alias('us')->where('is_delete',0) ->whereNotExists('select 1 from yoshop_order where user_id=us.user_id and pay_status=20') ->field('us.user_id')->select(); return $lists->column('user_id'); } /** *获取下过单的用户ID */ public static function getOldUserIds(){ $lists = self::alias('us')->where('is_delete',0) ->whereExists('select 1 from yoshop_order where user_id=us.user_id and pay_status=20') ->field('us.user_id')->select(); return $lists->column('user_id'); } }