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

406 lines
11 KiB
PHP

<?php
namespace App\Models;
use App\Casts\JsonArray;
use App\Enums\DealerLvl;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Dealer extends Model
{
use HasDateTimeFormatter;
protected $attributes = [
'lvl' => DealerLvl::None,
'is_sale' => false,
'is_manager' => false,
];
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',
];
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()
{
$tz = now();
$tz = now();
if ($tz->day >= 20) {
// 结算当月5号-19号的管理津贴
$startAt = $tz->copy()->setDay(5)->startOfDay();
$endAt = $tz->copy()->setDay(19)->endOfDay();
} elseif ($tz->day >= 5) {
// 结算上月20号-到当月4号的管理津贴
$startAt = $tz->copy()->subMonthNoOverflow()->set('day', 20)->startOfDay();
$endAt = $tz->copy()->set('day', 4)->endOfDay();
} else {
// 结算上月5号-到19号的管理津贴
$startAt = $tz->copy()->subMonthNoOverflow()->setDay(5)->startOfDay();
$endAt = $startAt->copy()->setDay(19)->endOfDay();
}
return DealerPurchaseLog::query()->whereBetween('order_completed_at', [$startAt, $endAt])
->where('path', 'like', "{$this->userInfo->full_path}%")
->sum('total_amount');
}
public function getCalculateTotalAmountAttribute()
{
$tz = now();
$tz = now();
if ($tz->day >= 20) {
// 结算当月5号-19号的管理津贴
$startAt = $tz->copy()->setDay(5)->startOfDay();
$endAt = $tz->copy()->setDay(19)->endOfDay();
} elseif ($tz->day >= 5) {
// 结算上月20号-到当月4号的管理津贴
$startAt = $tz->copy()->subMonthNoOverflow()->set('day', 20)->startOfDay();
$endAt = $tz->copy()->set('day', 4)->endOfDay();
} else {
// 结算上月5号-到19号的管理津贴
$startAt = $tz->copy()->subMonthNoOverflow()->setDay(5)->startOfDay();
$endAt = $startAt->copy()->setDay(19)->endOfDay();
}
$subsidyLogs = DealerManageSubsidyLog::select([
'product_id',
DB::raw('sum(sales_volume) as sales_volume'),
DB::raw('sum(total_amount) as total_amount'),
])->where(
'user_id', $this->user_id
)->whereBetween(
'order_completed_at', [$startAt, $endAt]
)->groupBy('product_id')->get();
// 补贴总金额
$totalAmount = 0;
foreach ($subsidyLogs as $subsidyLog) {
$totalAmount = bcadd($totalAmount, $subsidyLog->total_amount, 2);
}
return $totalAmount;
}
/**
* 确认此经销商是否是金牌经销商
*
* @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->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();
}
}
}