DealerLvl::None, 'is_sale' => true, 'is_manager' => false, 'self_sales_value' => 0, 'team_sales_value' => 0, ]; protected $casts = [ 'lvl' => DealerLvl::class, 'is_sale' => 'bool', 'is_manager' => 'bool', 'pay_info' => JsonArray::class, 'contracted_lvl_at' => 'datetime', ]; protected $fillable = [ 'user_id', 'lvl', 'is_sale', 'is_manager', 'pay_info', 'contracted_lvl_at', 'bonds', 'self_sales_value', 'team_sales_value', ]; public function user() { return $this->belongsTo(User::class, 'user_id'); } /** * 属于此经销商的用户信息 */ public function userInfo() { return $this->hasOne(UserInfo::class, 'user_id', 'user_id'); } /** * 属于此经销商的管理者津贴 */ public function managerSalesLogs() { return $this->hasMany(DealerManagerSalesLog::class, 'user_id', 'user_id'); } /** * 属于此经销商的管理者津贴 */ public function manageSubsidyLogs() { return $this->hasMany(DealerManageSubsidyLog::class, 'user_id', 'user_id'); } /** * 属于此经销商的升级日志 */ public function upgradeLogs() { return $this->hasMany(DealerUpgradeLog::class, 'user_id', 'user_id'); } public function getLvlTextAttribute() { return $this->lvl->text(); } /** * 统计经销商进货补贴实时的【基数业绩】 * * @return void */ public function getSaleValuesAttribute() { // return $this->self_sales_value + $this->team_sales_value; $tz = now(); if ($tz->day >= 20) { // 结算当月20号开始的业绩 $startAt = $tz->copy()->setDay(20)->startOfDay(); } elseif ($tz->day >= 5) { // 结算当月5号开始的的业绩 $startAt = $tz->copy()->setDay(5)->startOfDay(); } else { // 结算上月20号开始的业绩 $startAt = $tz->copy()->subMonthNoOverflow()->setDay(20)->startOfDay(); } return DealerPurchaseLog::query()->where('order_completed_at', '>=', $startAt) ->where('path', 'like', "{$this->userInfo->full_path}%") ->sum('total_amount'); } /** * 实时管理津贴 * * @return void */ public function getCalculateTotalAmountAttribute() { $tz = now(); if ($tz->day >= 20) { // 结算当月20号开始的管理津贴 $startAt = $tz->copy()->setDay(20)->startOfDay(); } elseif ($tz->day >= 5) { // 结算当月5号开始的管理津贴 $startAt = $tz->copy()->setDay(5)->startOfDay(); } else { // 结算上月20号开始的管理津贴 $startAt = $tz->copy()->subMonthNoOverflow()->setDay(20)->startOfDay(); } return DealerManageSubsidyLog::where( 'user_id', $this->user_id )->where('order_completed_at', '>=', $startAt)->sum('total_amount'); } /** * 确认此经销商是否是金牌经销商 * * @return boolean */ public function isGoldDealer() { return $this->lvl === DealerLvl::Gold; } /** * 确认此经销商是否是特邀经销商 * * @return boolean */ public function isSpecialDealer() { return $this->lvl === DealerLvl::Special; } /** * 获取此用户的所有上级经销商 * * @return array */ public function getDealers() { if (empty($pids = $this->userInfo->parent_ids)) { return []; } $ancestors = UserInfo::with(['dealer']) ->whereIn('user_id', $pids) ->latest('depth') ->get(['user_id']); return $ancestors->map(function ($item) { return $item->dealer; })->all(); } /** * 获取此用户的所有直属上级经销商 * * @return array */ public function getRealDealers() { if (empty($pids = $this->userInfo->real_parent_ids)) { return []; } $ancestors = UserInfo::with(['dealer']) ->whereIn('user_id', $pids) ->latest('depth') ->get(['user_id']); return $ancestors->map(function ($item) { return $item->dealer; })->all(); } /** * 获取直属金牌经销商数量 * * @return int */ public function getDirectGoldDealersCount(): int { return static::whereHas('userInfo', function ($query) { $query->where('inviter_id', $this->user_id); })->where('lvl', '>=', DealerLvl::Gold)->count(); } /** * 获取直属的特邀经销商数量 * * @return int */ public function getDirectSpecialDealersCount(): int { return static::whereHas('userInfo', function ($query) { $query->where('inviter_id', $this->user_id); })->where('lvl', '>=', DealerLvl::Special)->count(); } /** * 获取直属的签约经销商数量 * * @return int */ public function getDirectContractedDealersCount(): int { return static::whereHas('userInfo', function ($query) { $query->where('inviter_id', $this->user_id); })->where('lvl', '>=', DealerLvl::Contracted)->count(); } /** * 获取不同线上的非直属签约经销商人数(每条线上最多算一个) * * @return int */ public function getIndirectContractedDealersCount(): int { $path = $this->userInfo->full_path; $dealers = static::whereHas('userInfo', function ($query) use ($path) { $query->where('inviter_id', '!=', $this->user_id)->where('path', 'like', "{$path}%"); })->where('lvl', '>=', DealerLvl::Contracted)->get(); $dealers->load('userInfo:user_id,path'); $lines = []; foreach ($dealers as $dealer) { preg_match("#\A{$path}\d+-#", $dealer->userInfo->full_path, $matches); $line = $matches[0]; if (! isset($lines[$line])) { $lines[$line] = 1; } } return count($lines); } /** * 获取直属的二级经销商数量 * * @return int */ public function getDirectSecondaryDealersCount(): int { return static::whereHas('userInfo', function ($query) { $query->where('inviter_id', $this->user_id); })->where('lvl', '>=', DealerLvl::Special)->count(); } /** * 尝试升级 * * @return void */ public function attemptUpgrade() { $lvl = $this->lvl; if (in_array($lvl, [DealerLvl::None, DealerLvl::Top])) { return; } $remark = ''; if ($lvl === DealerLvl::Gold && $this->getDirectGoldDealersCount() >=5) { $lvl = DealerLvl::Special; $remark .= '有5个直推金牌'; } if ($lvl === DealerLvl::Special && $this->getDirectSpecialDealersCount() >= 4) { $lvl = DealerLvl::Contracted; if ($remark !== '') { $remark .= ';'; } $remark .= '有4个直推特邀'; } if ($lvl === DealerLvl::Contracted) { // 直推签约经销商数量 $directDealersCount = $this->getDirectContractedDealersCount(); if ($directDealersCount >= 3) { $surplus = 9 - $directDealersCount; if ($surplus <= 0) { $lvl = DealerLvl::Secondary; if ($remark !== '') { $remark .= ';'; } $remark .= "有{$directDealersCount}个直推签约"; } else { // 非直属签约人数 $indirectDealersCount = $this->getIndirectContractedDealersCount(); if ($indirectDealersCount >= $surplus) { $lvl = DealerLvl::Secondary; if ($remark !== '') { $remark .= ';'; } $remark .= "有{$directDealersCount}个直推签约,{$indirectDealersCount}个间接签约"; } } } } if ($lvl === DealerLvl::Secondary && $this->getDirectSecondaryDealersCount() >= 4) { $lvl = DealerLvl::Top; if ($remark !== '') { $remark .= ';'; } $remark .= '有4个直推二级'; } $this->upgrade($lvl, $remark); } /** * 直接升级 * * @param \App\Enums\DealerLvl $lvl * @param string|null $remark * @return void */ public function upgrade(DealerLvl $lvl, ?string $remark = null) { if ($this->lvl->value >= $lvl->value) { return; } $before = $this->lvl; if ($lvl->value < DealerLvl::Contracted->value) { $this->contracted_lvl_at = null; } elseif ($lvl->value >= DealerLvl::Contracted->value && $this->contracted_lvl_at === null) { $this->contracted_lvl_at = now(); } $this->lvl = $lvl; $this->save(); $this->upgradeLogs()->create([ 'before_lvl' => $before, 'change_lvl' => $lvl, 'remark' => $remark, ]); // 变更代理等级 $mapAgentLvl = $this->lvl->agentLvl(); if ($this->userInfo->agent_level < $mapAgentLvl) { $this->userInfo->agent_level = $mapAgentLvl; $this->userInfo->save(); } } }