380 lines
9.9 KiB
PHP
380 lines
9.9 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Casts\JsonArray;
|
|
use App\Enums\DealerLvl;
|
|
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
class Dealer extends Model
|
|
{
|
|
use HasDateTimeFormatter;
|
|
|
|
protected $attributes = [
|
|
'lvl' => 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 wallet()
|
|
{
|
|
return $this->hasOne(DealerWallet::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 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::Secondary)->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();
|
|
}
|
|
}
|
|
|
|
public function canWithdraw()
|
|
{
|
|
$days = app_settings('dealer.withdraw_days', 7);
|
|
return DealerWalletToBankLog::where('user_id', $this->user_id)->where('created_at', '>', now()->subDays($days))->doesntExist();
|
|
}
|
|
}
|