6
0
Fork 0
jiqu-library-server/app/Console/Commands/Dealer/OrderProcessCommand.php

297 lines
8.3 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\Console\Commands\Dealer;
use App\Enums\DealerLvl;
use App\Enums\DealerOrderSettleState;
use App\Enums\DealerOrderStatus;
use App\Models\Dealer;
use App\Models\DealerManagerSalesLog;
use App\Models\DealerManageSubsidyLog;
use App\Models\DealerOrder;
use App\Models\DealerPurchaseLog;
use App\Models\UserInfo;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Throwable;
class OrderProcessCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dealer:order-process';
/**
* The console command description.
*
* @var string
*/
protected $description = '处理结算状态是待处理的已付款经销商订单';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
DealerOrder::where(
'settle_state',
DealerOrderSettleState::Pending
)->whereIn('status', [
DealerOrderStatus::Paid,
DealerOrderStatus::Shipped,
DealerOrderStatus::Completed,
])->chunkById(200, function ($orders) {
$orders->load([
'userInfo.dealer',
'products.productManageSubsidyRules',
]);
foreach ($orders as $order) {
try {
DB::beginTransaction();
$this->handleDealerOrder($order);
DB::commit();
} catch (Throwable $e) {
DB::rollBack();
report($e);
}
}
});
return 0;
}
/**
* 处理经销商订单
*
* @param \App\Models\DealerOrder $dealerOrder
* @return void
*/
protected function handleDealerOrder(DealerOrder $dealerOrder)
{
$tz = now();
// 获取下单经销商的所有上级经销商
$dealers = $this->getDealers($dealerOrder->userInfo);
// 当前链上的全部经销商(含下单经销商)
$chainDealers = [$dealerOrder->userInfo->dealer, ...$dealers];
// 签约经销商的进货日志
$this->handlePurchaseLogsOfContractedDealer($dealerOrder, $tz);
// 管理者的销售业绩
$this->handleManagerSalesLogs($dealerOrder, $chainDealers, $tz);
// 一级签约经销商和二级经销商的管理津贴
$this->handleManageSubsidyLogs($dealerOrder, $chainDealers, $tz);
// 将订单标记为已处理
// $dealerOrder->forceFill([
// 'settle_state' => DealerOrderSettleState::Processed,
// ])->save();
}
/**
* 生成签约经销商的进货日志
*
* @param \App\Models\DealerOrder $dealerOrder
* @param array $dealers
* @param string $tz
* @return void
*/
protected function handlePurchaseLogsOfContractedDealer(DealerOrder $dealerOrder, string $tz)
{
$dealer = $dealerOrder->userInfo->dealer;
// 采购业绩是否算自己的业绩
$valid = true;
if ($dealer->lvl->value < DealerLvl::Contracted->value) {
// 如果订单金额小于升级签约经销商的金额,则结束
if ($dealerOrder->total_amount < 26400) {
return;
}
$valid = false;
}
$log = new DealerPurchaseLog([
'user_id' => $dealer->user_id,
'lvl' => $dealer->lvl,
'order_id' => $dealerOrder->id,
'total_amount' => $dealerOrder->total_amount,
'path' => $valid ? $dealerOrder->userInfo->full_path : $dealerOrder->userInfo->path,
'remark' => $valid ? null : '升级签约',
]);
$log->setCreatedAt($tz);
$log->setUpdatedAt($tz);
$log->save();
}
/**
* 分配一级签约经销商和二级经销商的管理津贴
*
* @param \App\Models\DealerOrder $dealerOrder
* @param array $dealers
* @param string $tz
* @return void
*/
protected function handleManageSubsidyLogs(DealerOrder $dealerOrder, array $dealers, string $tz)
{
$logs = [];
foreach ($dealerOrder->products as $product) {
if ($product->productManageSubsidyRules->isEmpty()) {
continue;
}
// 管理津贴分配规则
$rules = $product->productManageSubsidyRules->keyBy('lvl');
$last = null;
$ranking = 0;
foreach ($dealers as $dealer) {
// 如果当前经销商等级没有对应的管理津贴分配规则,则忽略
if (is_null($rule = $rules->get($dealer->lvl->value))) {
continue;
}
// 同等级管理津贴最多给三次
if ($last === null || $dealer->lvl->value > $last->lvl->value) {
$ranking = 1;
} elseif ($ranking < 3 && $dealer->lvl->value === $last->lvl->value) {
$ranking++;
} else {
continue;
}
$subsidy = $rule->{"price_{$ranking}st"};
if (bccomp($subsidy, '0') === 1) {
$logs[] = [
'user_id' => $dealer->user_id,
'order_id' => $product->order_id,
'product_id' => $product->product_id,
'lvl' => $dealer->lvl,
'sales_volume' => $product->qty,
'total_amount' => bcmul($product->qty, $subsidy, 2),
'created_at' => $tz,
'updated_at' => $tz,
];
}
$last = $dealer;
}
}
DealerManageSubsidyLog::insert($logs);
}
/**
* 过滤出可能会享受管理津贴的经销商每个等级最多3人
*
* @param array $dealers
* @return array
*/
protected function mapManageSubsidyDealers(array $dealers): array
{
$map = [];
$last = null;
$ranking = 1;
foreach ($dealers as $dealer) {
if ($last === null || $dealer->lvl->value > $last->lvl->value) {
$last = $dealer;
$map[] = $last;
$ranking = 1;
} elseif ($ranking < 3 && $dealer->lvl->value === $last->lvl->value) {
$last = $dealer;
$map[] = $last;
$ranking++;
}
}
return $map;
}
/**
* 生成管理者的销售业绩
*
* @param \App\Models\DealerOrder $dealerOrder
* @param array $dealers
* @param string $tz
* @return void
*/
protected function handleManagerSalesLogs(DealerOrder $dealerOrder, array $dealers, string $tz): void
{
if (is_null($manager = $this->firstManager($dealers))) {
return;
}
$logs = [];
foreach ($dealerOrder->products as $product) {
$logs[] = [
'user_id' => $manager->user_id,
'lvl' => $manager->lvl,
'order_id' => $product->order_id,
'product_id' => $product->product_id,
'sales_volume' => $product->qty,
'created_at' => $tz,
'updated_at' => $tz,
];
}
DealerManagerSalesLog::insert($logs);
}
/**
* 从给定的经销商中获取第一个管理者
*
* @param array $dealers
* @return \App\Models\Dealer|null
*/
protected function firstManager(array $dealers): ?Dealer
{
foreach ($dealers as $dealer) {
if ($dealer->is_manager) {
return $dealer;
}
}
}
/**
* 获取给定用户的上级经销商
*
* @param \App\Models\UserInfo $userInfo
* @return array
*/
protected function getDealers(UserInfo $userInfo): array
{
$ancestors = [];
if (empty($pids = $userInfo->parent_ids)) {
return $ancestors;
}
$ancestors = UserInfo::with(['dealer'])
->whereIn('user_id', $pids)
->latest('depth')
->get(['user_id', 'depth']);
return $ancestors->map(function ($item) {
return $item->dealer;
})->all();
}
}