处理付款订单
parent
f22a9a7cc5
commit
0b845f4efc
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
namespace App\Console\Commands\Dealer;
|
||||
|
||||
use App\Enums\DealerEarningStatus;
|
||||
use App\Enums\DealerLvl;
|
||||
use App\Enums\DealerOrderSettleState;
|
||||
use App\Enums\DealerOrderStatus;
|
||||
use App\Models\Dealer;
|
||||
use App\Models\DealerChannelSubsidyLog;
|
||||
use App\Models\DealerManagerSalesLog;
|
||||
use App\Models\DealerManageSubsidyLog;
|
||||
use App\Models\DealerOrder;
|
||||
|
|
@ -47,7 +49,7 @@ class OrderProcessCommand extends Command
|
|||
DealerOrderStatus::Completed,
|
||||
])->chunkById(200, function ($orders) {
|
||||
$orders->load([
|
||||
'userInfo.dealer',
|
||||
'dealer.userInfo',
|
||||
'products.productManageSubsidyRules',
|
||||
]);
|
||||
|
||||
|
|
@ -77,27 +79,236 @@ class OrderProcessCommand extends Command
|
|||
*/
|
||||
protected function handleDealerOrder(DealerOrder $dealerOrder)
|
||||
{
|
||||
$tz = now();
|
||||
|
||||
// 获取下单经销商的所有上级经销商
|
||||
$dealers = $this->getDealers($dealerOrder->userInfo);
|
||||
$tz = now()->toDateTimeString();
|
||||
|
||||
// 当前链上的全部经销商(含下单经销商)
|
||||
$chainDealers = [$dealerOrder->userInfo->dealer, ...$dealers];
|
||||
$dealers = [
|
||||
$dealerOrder->dealer,
|
||||
...$dealerOrder->dealer->getDealers(),
|
||||
];
|
||||
|
||||
// 签约经销商的进货日志
|
||||
$this->handlePurchaseLogsOfContractedDealer($dealerOrder, $tz);
|
||||
|
||||
// 管理者的销售业绩
|
||||
$this->handleManagerSalesLogs($dealerOrder, $chainDealers, $tz);
|
||||
$this->handleManagerSalesLogs($dealerOrder, $dealers, $tz);
|
||||
|
||||
// 一级签约经销商和二级经销商的管理津贴
|
||||
$this->handleManageSubsidyLogs($dealerOrder, $chainDealers, $tz);
|
||||
$this->handleManageSubsidyLogs($dealerOrder, $dealers, $tz);
|
||||
|
||||
// 渠道补贴
|
||||
$this->handleChannelSubsidy($dealerOrder);
|
||||
|
||||
if ($dealerOrder->dealer->wasChanged('lvl')) {
|
||||
foreach ($dealers as $dealer) {
|
||||
$dealer->attemptUpgrade();
|
||||
}
|
||||
}
|
||||
|
||||
// 将订单标记为已处理
|
||||
// $dealerOrder->forceFill([
|
||||
// 'settle_state' => DealerOrderSettleState::Processed,
|
||||
// ])->save();
|
||||
$dealerOrder->forceFill([
|
||||
'settle_state' => DealerOrderSettleState::Processed,
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算渠道补贴
|
||||
*
|
||||
* @param \App\Models\DealerOrder $dealerOrder
|
||||
* @return void
|
||||
*/
|
||||
protected function handleChannelSubsidy(DealerOrder $dealerOrder)
|
||||
{
|
||||
$lvl = $dealerOrder->dealer->lvl;
|
||||
|
||||
if ($dealerOrder->total_amount >= app_settings('dealer.upgrade_amount_'.DealerLvl::Contracted->value)) {
|
||||
// 升级为签约
|
||||
if ($lvl->value < DealerLvl::Contracted->value) {
|
||||
$lvl = DealerLvl::Contracted;
|
||||
}
|
||||
} elseif ($dealerOrder->total_amount >= app_settings('dealer.upgrade_amount_'.DealerLvl::Special->value)) {
|
||||
// 升级为特约
|
||||
if ($lvl->value < DealerLvl::Special->value) {
|
||||
$lvl = DealerLvl::Special;
|
||||
}
|
||||
} elseif ($dealerOrder->total_amount >= app_settings('dealer.upgrade_amount_'.DealerLvl::Gold->value)) {
|
||||
// 升级为金牌
|
||||
if ($lvl->value < DealerLvl::Gold->value) {
|
||||
$lvl = DealerLvl::Gold;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果经销商等级小于金牌,则没有渠道补贴
|
||||
if ($lvl->value < DealerLvl::Gold->value) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$dealers, $rule] = $this->mapDealersAndRuleOfChannel($dealerOrder->dealer, $lvl);
|
||||
|
||||
// 升级金额
|
||||
$upgradeAmount = app_settings('dealer.upgrade_amount_'.$lvl->value);
|
||||
// 手续费比例
|
||||
$feeRate = bcdiv(app_settings('dealer.fee_rate'), '100', 10);
|
||||
|
||||
foreach ($dealers as $key => $dealer) {
|
||||
$ruleKey = $dealer->lvl->value.'_'.$key;
|
||||
|
||||
if ($dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||
$ruleKey = DealerLvl::Contracted->value.'_'.$key;
|
||||
}
|
||||
|
||||
// 补贴金额
|
||||
$subsidyAmount = $rule[$ruleKey];
|
||||
|
||||
$totalAmount = bcmul($subsidyAmount, $dealerOrder->total_amount, 10);
|
||||
$totalAmount = bcdiv($totalAmount, $upgradeAmount, 3);
|
||||
$totalAmount = round($totalAmount, 2);
|
||||
|
||||
$channelSubsidyLog = DealerChannelSubsidyLog::create([
|
||||
'user_id' => $dealer->user_id,
|
||||
'lvl' => $dealer->lvl,
|
||||
'order_id' => $dealerOrder->id,
|
||||
'total_amount' => $totalAmount,
|
||||
'order_id' => $dealerOrder->id,
|
||||
'remark' => "补贴总额={$dealerOrder->total_amount}/{$upgradeAmount}*{$subsidyAmount}",
|
||||
]);
|
||||
|
||||
$fee = bcmul($totalAmount, bcdiv($feeRate, '100', 5), 3);
|
||||
$fee = round($fee, 2);
|
||||
|
||||
$channelSubsidyLog->earning()->create([
|
||||
'user_id' => $dealer->user_id,
|
||||
'lvl' => $dealer->lvl,
|
||||
'is_manager' => $dealer->is_manager,
|
||||
'total_amount' => $totalAmount,
|
||||
'total_earnings' => bcsub($totalAmount, $fee, 2),
|
||||
'fee' => $fee,
|
||||
'fee_rate' => $feeRate,
|
||||
'payer_id' => $dealerOrder->consignor_id,
|
||||
'status' => DealerEarningStatus::Pending,
|
||||
'remark' => "订单号: {$dealerOrder->sn}",
|
||||
]);
|
||||
}
|
||||
|
||||
$dealerOrder->dealer->upgrade($lvl, '进货升级');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取渠道补贴经销商和补贴规则
|
||||
*
|
||||
* @param \App\Models\Dealer $dealer
|
||||
* @param \App\Enums\DealerLvl $lvl
|
||||
* @return array
|
||||
*/
|
||||
protected function mapDealersAndRuleOfChannel(Dealer $dealer, DealerLvl $lvl): array
|
||||
{
|
||||
// 渠道补贴经销商
|
||||
$dealers = [];
|
||||
// 渠道补贴规则
|
||||
$rule = null;
|
||||
// 是否升级
|
||||
$isUp = $lvl->value > $dealer->lvl->value;
|
||||
// 最后参与渠道补贴的经销商
|
||||
$last = null;
|
||||
|
||||
foreach ($dealer->getRealDealers() as $_dealer) {
|
||||
// 如果经销商等级小于金牌, 那么跳过
|
||||
if ($_dealer->lvl->value < DealerLvl::Gold->value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($lvl->value >= DealerLvl::Contracted->value) {
|
||||
if ($last === null) {
|
||||
if ($_dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||
// 渠道补贴规则: 签约 -> 签约 -> 签约
|
||||
$rule = app_settings(sprintf(
|
||||
'dealer.channel_rules.%s_%s',
|
||||
DealerLvl::Contracted->value,
|
||||
DealerLvl::Contracted->value
|
||||
));
|
||||
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
$last = $_dealer;
|
||||
} elseif ($isUp && $_dealer->isSpecialDealer()) {
|
||||
// 渠道补贴规则: 签约 -> 特邀 -> 签约 -> 签约
|
||||
$rule = app_settings(sprintf(
|
||||
'dealer.channel_rules.%s_%s',
|
||||
DealerLvl::Contracted->value,
|
||||
DealerLvl::Special->value
|
||||
));
|
||||
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
$last = $_dealer;
|
||||
}
|
||||
} elseif ($_dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
// 如果最后参与渠道补贴的经销商是签约, 那么已经找到所有参与渠道补贴的经销商
|
||||
if ($last->lvl->value >= DealerLvl::Contracted->value) {
|
||||
break;
|
||||
}
|
||||
|
||||
$last = $_dealer;
|
||||
}
|
||||
} elseif ($lvl === DealerLvl::Special) {
|
||||
if ($_dealer->lvl->value > DealerLvl::Special->value) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($last === null) {
|
||||
if ($_dealer->isSpecialDealer()) {
|
||||
// 渠道补贴规则: 特邀 -> 特邀 -> 特邀
|
||||
$rule = app_settings(sprintf(
|
||||
'dealer.channel_rules.%s_%s',
|
||||
DealerLvl::Special->value,
|
||||
DealerLvl::Special->value
|
||||
));
|
||||
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
$last = $_dealer;
|
||||
} elseif ($isUp && $_dealer->isGoldDealer()) {
|
||||
// 渠道补贴规则: 特邀 -> 金牌 -> 特邀 -> 特邀
|
||||
$rule = app_settings(sprintf(
|
||||
'dealer.channel_rules.%s_%s',
|
||||
DealerLvl::Special->value,
|
||||
DealerLvl::Gold->value
|
||||
));
|
||||
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
$last = $_dealer;
|
||||
}
|
||||
} elseif ($_dealer->isSpecialDealer()) {
|
||||
$dealers[] = $_dealer;
|
||||
|
||||
if ($last->isSpecialDealer()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$last = $_dealer;
|
||||
}
|
||||
} elseif ($lvl === DealerLvl::Gold) {
|
||||
if ($_dealer->lvl->value >= DealerLvl::Gold->value) {
|
||||
if ($_dealer->isGoldDealer()) {
|
||||
// 渠道补贴规则: 金牌 -> 金牌
|
||||
$rule = app_settings(sprintf(
|
||||
'dealer.channel_rules.%s_%s',
|
||||
DealerLvl::Gold->value,
|
||||
DealerLvl::Gold->value
|
||||
));
|
||||
|
||||
$dealers[] = $_dealer;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$dealers, $rule];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,7 +328,7 @@ class OrderProcessCommand extends Command
|
|||
|
||||
if ($dealer->lvl->value < DealerLvl::Contracted->value) {
|
||||
// 如果订单金额小于升级签约经销商的金额,则结束
|
||||
if ($dealerOrder->total_amount < 26400) {
|
||||
if ($dealerOrder->total_amount < app_settings('dealer.upgrade_amount_'.DealerLvl::Contracted->value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -271,23 +482,23 @@ class OrderProcessCommand extends Command
|
|||
}
|
||||
|
||||
/**
|
||||
* 获取给定用户的上级经销商
|
||||
* 获取给定用户的实际上级经销商
|
||||
*
|
||||
* @param \App\Models\UserInfo $userInfo
|
||||
* @return array
|
||||
*/
|
||||
protected function getDealers(UserInfo $userInfo): array
|
||||
protected function getRealDealers(UserInfo $userInfo): array
|
||||
{
|
||||
$ancestors = [];
|
||||
|
||||
if (empty($pids = $userInfo->parent_ids)) {
|
||||
if (empty($pids = $userInfo->real_parent_ids)) {
|
||||
return $ancestors;
|
||||
}
|
||||
|
||||
$ancestors = UserInfo::with(['dealer'])
|
||||
->whereIn('user_id', $pids)
|
||||
->latest('depth')
|
||||
->get(['user_id', 'depth']);
|
||||
->get(['user_id']);
|
||||
|
||||
return $ancestors->map(function ($item) {
|
||||
return $item->dealer;
|
||||
|
|
|
|||
|
|
@ -139,15 +139,169 @@ class Dealer extends Model
|
|||
}
|
||||
|
||||
/**
|
||||
* 变更等级
|
||||
* 获取直属金牌经销商数量
|
||||
*
|
||||
* @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 changeLvl(DealerLvl $lvl, ?string $remark = null)
|
||||
public function upgrade(DealerLvl $lvl, ?string $remark = null)
|
||||
{
|
||||
if ($this->lvl === $lvl) {
|
||||
if ($this->lvl->value >= $lvl->value) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue