6
0
Fork 0
jiqu-library-server/app/Models/UserInfo.php

499 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Models;
use App\Helpers\Str as StrHelper;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class UserInfo extends Model
{
use HasDateTimeFormatter;
public const GENDER_UNKNOWN = 'unknown'; // 未知
public const GENDER_MALE = 'male'; // 男性
public const GENDER_FEMALE = 'female'; // 女性
public const AGENT_LEVEL_CIVILIAN = 0;
public const AGENT_LEVEL_VIP = 1;
public const AGENT_LEVEL_COMMUNITY = 2;
public const AGENT_LEVEL_DISTRICT = 3;
public const AGENT_LEVEL_CITY = 4;
public const AGENT_LEVEL_PROVINCE = 5;
public const AGENT_LEVEL_BRANCH = 6;
public const AGENT_LEVEL_DIRECTOR = 7;
/**
* @var string
*/
protected $primaryKey = 'user_id';
/**
* @var bool
*/
public $incrementing = false;
/**
* @var array
*/
protected $attributes = [
'gender' => self::GENDER_UNKNOWN,
'bonusable' => true,
];
/**
* @var array
*/
protected $fillable = [
'inviter_id',
'nickname',
'avatar',
'gender',
'birthday',
'bonusable',
'depth',
'path',
'agent_level',
'quota_v1',
'quota_v2',
'growth_value',
'pre_growth_value',
'group_sales_value',
'real_inviter_id',
];
/**
* @var array
*/
protected $casts = [
'birthday' => 'date',
'bonusable' => 'bool',
];
/**
* 代理等级排名,从低到高
*
* @var array
*/
public static $agentLevelRanks = [
self::AGENT_LEVEL_CIVILIAN => 1,
self::AGENT_LEVEL_VIP => 2,
self::AGENT_LEVEL_COMMUNITY => 3,
self::AGENT_LEVEL_DISTRICT => 4,
self::AGENT_LEVEL_CITY => 5,
self::AGENT_LEVEL_PROVINCE => 6,
self::AGENT_LEVEL_BRANCH => 7,
self::AGENT_LEVEL_DIRECTOR => 8,
];
/**
* 代理等级配置 key
*
* @var array
*/
public static $agentLevelKeys = [
self::AGENT_LEVEL_CIVILIAN => 'civilian',
self::AGENT_LEVEL_VIP => 'vip',
self::AGENT_LEVEL_COMMUNITY => 'community',
self::AGENT_LEVEL_DISTRICT => 'district',
self::AGENT_LEVEL_CITY => 'city',
self::AGENT_LEVEL_PROVINCE => 'province',
self::AGENT_LEVEL_BRANCH => 'branch',
self::AGENT_LEVEL_DIRECTOR => 'director',
];
public static $genderTexts = [
self::GENDER_UNKNOWN => '未知',
self::GENDER_MALE => '男性',
self::GENDER_FEMALE => '女性',
];
/**
* 代理等级文本
*
* @var array
*/
public static $agentLevelTexts = [
self::AGENT_LEVEL_CIVILIAN => '粉丝',
self::AGENT_LEVEL_VIP => '会员',
self::AGENT_LEVEL_COMMUNITY => '铁牌会员',
self::AGENT_LEVEL_DISTRICT => '铜牌会员',
self::AGENT_LEVEL_CITY => '银牌会员',
self::AGENT_LEVEL_PROVINCE => '金牌会员',
self::AGENT_LEVEL_BRANCH => '钻石会员',
self::AGENT_LEVEL_DIRECTOR => '默认用户',
];
/**
* 代理等级图标
*
* @var array
*/
public static $agentLevelIcons = [
self::AGENT_LEVEL_COMMUNITY => 'https://cdn.zichunsheng.cn/statics/icons/lvl_2.png',
self::AGENT_LEVEL_DISTRICT => 'https://cdn.zichunsheng.cn/statics/icons/lvl_3.png',
self::AGENT_LEVEL_CITY => 'https://cdn.zichunsheng.cn/statics/icons/lvl_4.png',
self::AGENT_LEVEL_PROVINCE => 'https://cdn.zichunsheng.cn/statics/icons/lvl_5.png',
self::AGENT_LEVEL_BRANCH => 'https://cdn.zichunsheng.cn/statics/icons/lvl_6.png',
];
/**
* {@inheritdoc}
*/
protected static function booted()
{
parent::saving(function ($userInfo) {
// 如果没有邀请码,则自动分配邀请码
if ($userInfo->code === null) {
do {
$userInfo->code = strtolower(StrHelper::randomAlpha(6));
} while (static::where('code', $userInfo->code)->exists());
} elseif ($userInfo->isDirty('code')) {
$userInfo->code = strtolower($userInfo->code);
}
});
}
/**
* 用户
*
* @return void
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* 获取此用户的邀请人信息
*/
public function inviterInfo()
{
return $this->belongsTo(UserInfo::class, 'inviter_id');
}
/**
* 获取此用户的真实邀请人信息
*/
public function realInviterInfo()
{
return $this->belongsTo(UserInfo::class, 'real_inviter_id');
}
/**
* 获取此用户的预收益
*/
public function distributionPreIncomes()
{
return $this->hasMany(DistributionPreIncome::class, 'user_id', 'user_id');
}
/**
* 获取此用户的代理升级日志
*/
public function agentUpgradeLogs()
{
return $this->hasMany(AgentUpgradeLog::class, 'user_id', 'user_id');
}
/**
* 属于此用户的经销商信息
*/
public function dealer()
{
return $this->hasOne(Dealer::class, 'user_id', 'user_id');
}
/**
* 获取此用户的直推店铺总数
*/
public function getVipAgentsCount()
{
return static::where('inviter_id', $this->getKey())
->where('agent_level', '>=', static::AGENT_LEVEL_VIP)
->count();
}
/**
* 获取此用户的不同线上的下级区级代理总数
*/
public function getDistrictAgentsCountOnDifferentLines()
{
$path = $this->full_path;
// 获取所有区级以上的代理
$agents = static::where('agent_level', '>=', static::AGENT_LEVEL_DISTRICT)
->where('path', 'like', "{$path}%")
->get();
$lines = [];
foreach ($agents as $agent) {
preg_match("#\A{$path}\d+-#", $agent->full_path, $matches);
$line = $matches[0];
if (! isset($lines[$line])) {
$lines[$line] = 1;
}
}
return count($lines);
}
/**
* 获取此用户的不同线上的下级市级代理总数
*/
public function getCityAgentsCountOnDifferentLines()
{
$path = $this->full_path;
// 获取所有市级以上的代理
$agents = static::where('agent_level', '>=', static::AGENT_LEVEL_CITY)
->where('path', 'like', "$path%")
->get();
$lines = [];
foreach ($agents as $agent) {
preg_match("#\A{$path}\d+-#", $agent->full_path, $matches);
$line = $matches[0];
if (! isset($lines[$line])) {
$lines[$line] = 1;
}
}
return count($lines);
}
/**
* 获取此用户的不同线上的下级省级代理总数
*/
public function getProvinceAgentsCountOnDifferentLines()
{
$path = $this->full_path;
// 获取所有省级以上的代理
$agents = static::where('agent_level', '>=', static::AGENT_LEVEL_PROVINCE)
->where('path', 'like', "$path%")
->get();
$lines = [];
foreach ($agents as $agent) {
preg_match("#\A{$path}\d+-#", $agent->full_path, $matches);
$line = $matches[0];
if (! isset($lines[$line])) {
$lines[$line] = 1;
}
}
return count($lines);
}
/**
* 尝试提升代理等级
*
* @return void
*/
public function attemptUpgradeAgentLevel(): void
{
$lvl = $this->agent_level;
// 如果代理等级是分公司或董事时,不能继续提升代理等级
if (in_array($lvl, [static::AGENT_LEVEL_BRANCH, static::AGENT_LEVEL_DIRECTOR])) {
return;
}
$rules = config('agent.upgrade_rules');
// 如果成长值不足650时不能升级
if (bccomp($this->growth_value, $rules['vip']['sales_value']) < 0) {
return;
}
// 如果代理等级是粉丝,则可升级为店铺
if ($lvl === static::AGENT_LEVEL_CIVILIAN) {
$lvl = static::AGENT_LEVEL_VIP;
}
// 团队销售值
$salesValue = $this->team_sales_value;
if ($lvl === static::AGENT_LEVEL_VIP) {
$vipsCount = $this->getVipAgentsCount();
// 如果直推店铺人数>=6并且团队销售值>=65000则可升级为区级代理
// 或者直推店铺人数>=4则可升级为社区
if (
$vipsCount >= $rules['district']['vips_agents_count']
&& bccomp($salesValue, $rules['district']['team_sales_value']) >= 0
) {
$lvl = static::AGENT_LEVEL_DISTRICT;
} elseif ($vipsCount >= $rules['community']['vips_agents_count']) {
$lvl = static::AGENT_LEVEL_COMMUNITY;
}
} elseif ($lvl === static::AGENT_LEVEL_COMMUNITY && bccomp($salesValue, $rules['district']['team_sales_value']) >= 0) {
if ($this->getVipAgentsCount() >= $rules['district']['vips_agents_count']) {
$lvl = static::AGENT_LEVEL_DISTRICT;
}
}
if ($lvl === static::AGENT_LEVEL_DISTRICT && bccomp($salesValue, $rules['city']['team_sales_value']) >= 0) {
if ($this->getDistrictAgentsCountOnDifferentLines() >= $rules['city']['district_agents_count']) {
$lvl = static::AGENT_LEVEL_CITY;
}
}
if ($lvl === static::AGENT_LEVEL_CITY && bccomp($salesValue, $rules['province']['team_sales_value']) >= 0) {
if ($this->getCityAgentsCountOnDifferentLines() >= $rules['province']['city_agents_count']) {
$lvl = static::AGENT_LEVEL_PROVINCE;
}
}
if ($lvl === static::AGENT_LEVEL_PROVINCE && bccomp($salesValue, $rules['branch']['team_sales_value']) >= 0) {
if ($this->getProvinceAgentsCountOnDifferentLines() >= $rules['branch']['province_agents_count']) {
$lvl = static::AGENT_LEVEL_BRANCH;
}
}
$this->changeAgentLvl($lvl, '达到升级条件');
}
/**
* 变更代理等级
*
* @param int $lvl
* @param string|null $remark
* @return void
*/
public function changeAgentLvl(int $lvl, ?string $remark = null)
{
if ($this->agent_level === $lvl) {
return $lvl;
}
$beforeAgentLevel = $this->agent_level;
$this->update([
'agent_level' => $lvl,
]);
$this->agentUpgradeLogs()->create([
'before_agent_level' => $beforeAgentLevel,
'change_agent_level' => $lvl,
'remark' => $remark,
]);
}
/**
* 变更预收益成长值
*
* @param float $growthValue
* @param bool $downgrade
* @return void
*/
public function incrPreGrowthValue($growthValue, $downgrade = true)
{
if (bccomp($growthValue, '0', 2) === 0) {
return;
}
// 增加预收益的成长值
$this->increment('pre_growth_value', $growthValue);
$totalGrowthValue = bcadd($this->growth_value, $this->pre_growth_value, 2);
$compared = bccomp($totalGrowthValue, config('agent.upgrade_rules.vip.sales_value'), 2);
if ($this->agent_level === static::AGENT_LEVEL_VIP && $compared < 0) {
if ($downgrade) {
$this->update([
'agent_level' => static::AGENT_LEVEL_CIVILIAN,
]);
}
} elseif ($this->agent_level === static::AGENT_LEVEL_CIVILIAN && $compared >= 0) {
$this->update([
'agent_level' => static::AGENT_LEVEL_VIP,
]);
}
}
/**
* 获取此用户的所有父级ID
*
* @return array
*/
public function getParentIdsAttribute(): array
{
if ($path = trim($this->path, '-')) {
return explode('-', $path);
}
return [];
}
public function getRealParentIdsAttribute(): array
{
$rpids = (array) $this->realInviterInfo?->parent_ids;
if ($this->real_inviter_id) {
array_push($rpids, $this->real_inviter_id);
}
return $rpids;
}
/**
* 代理等级排名
*
* @return int
*/
public function getAgentLevelRankAttribute(): int
{
return static::$agentLevelRanks[$this->agent_level] ?? 0;
}
/**
* 代理等级配置 key
*
* @return string
*/
public function getAgentLevelKeyAttribute(): string
{
return static::$agentLevelKeys[$this->agent_level] ?? 'unknown';
}
public function getAgentLevelNameAttribute(): string
{
return static::$agentLevelTexts[$this->agent_level] ?? '未知';
}
public function getAgentLevelIconAttribute(): string
{
return static::$agentLevelIcons[$this->agent_level] ?? '';
}
/**
* 获取完整的邀请路径
*
* @return string
*/
public function getFullPathAttribute(): string
{
return Str::finish($this->path.$this->getKey(), '-');
}
/**
* 获团队销售值
*
* @return string
*/
public function getTeamSalesValueAttribute(): string
{
return bcadd($this->growth_value, $this->group_sales_value, 2);
}
}