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

218 lines
6.6 KiB
PHP

<?php
namespace App\Console\Commands\Dealer;
use App\Enums\DealerManagerSubsidyStatus;
use App\Models\Dealer;
use App\Models\DealerManagerSalesLog;
use App\Models\DealerManagerSubsidy;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class ManagerSubsidySettleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dealer:manager-subsidy-settle';
/**
* The console command description.
*
* @var string
*/
protected $description = '结算上个月的管理者津贴';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$tz = now();
$startAt = $tz->copy()->subMonthNoOverflow()->startOfMonth();
$endAt = $startAt->copy()->endOfMonth();
$head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】';
$this->info("{$head}------------[开始]管理者津贴结算------------".PHP_EOL);
$this->info("{$head}管理者津贴初始化...");
$this->initializeManagerSubsidies($startAt, $endAt, 500);
$this->info("{$head}管理者津贴初始化完成".PHP_EOL);
$this->info("{$head}管理者津贴结算...");
$this->settleManagerSubsidies($startAt, $endAt);
$this->info("{$head}管理者津贴结算完成".PHP_EOL);
$this->info("{$head}Done! 总耗时: ".$this->formatDuration($tz->diffInMilliseconds(now(), false)));
$this->info("{$head}------------[结束]管理者津贴结算------------".PHP_EOL);
return 0;
}
/**
* 初始化管理者津贴
*
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @param int $count
* @return void
*/
protected function initializeManagerSubsidies(Carbon $startAt, Carbon $endAt, $count = 200): void
{
$feeRate = app_settings('dealer.fee_rate');
$lastId = $this->getLastDealerId($startAt, $endAt);
do {
$dealers = Dealer::where('is_manager', true)
->forPageAfterId($count, $lastId, 'id')
->get();
$dealersCount = $dealers->count();
if ($dealersCount == 0) {
break;
}
$managerSubsidies = [];
$tz = now()->toDateTimeString();
foreach ($dealers as $dealer) {
$managerSubsidies[] = [
'user_id' => $dealer->user_id,
'total_amount' => 0,
'real_amount' => 0,
'fee' => 0,
'fee_rate' => $feeRate,
'start_at' => $startAt,
'end_at' => $endAt,
'lvl' => $dealer->lvl,
'is_manager' => $dealer->is_manager,
'status' => DealerManagerSubsidyStatus::Pending,
'is_settle' => false,
'created_at' => $tz,
'updated_at' => $tz,
];
$lastId = $dealer->id;
}
DealerManagerSubsidy::insert($managerSubsidies);
unset($dealers, $managerSubsidies);
} while ($dealersCount == $count);
}
/**
* 结算管理者津贴
*
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @return void
*/
protected function settleManagerSubsidies(Carbon $startAt, Carbon $endAt)
{
DealerManagerSubsidy::where('start_at', $startAt)->where('end_at', $endAt)->where('is_settle', false)->chunkById(500, function ($subsidies) {
foreach ($subsidies as $subsidy) {
$this->settleManagerSubsidy($subsidy);
}
});
}
/**
* 结算管理者津贴
*
* @param \App\Models\DealerManagerSubsidy
* @return void
*/
protected function settleManagerSubsidy(DealerManagerSubsidy $subsidy)
{
[$totalAmount, $remark] = $this->calculateTotalAmount($subsidy);
$fee = bcmul($totalAmount, bcdiv($subsidy->fee_rate, '100', 5), 2);
$subsidy->forceFill([
'total_amount' => $totalAmount,
'real_amount' => bcsub($totalAmount, $fee, 2),
'fee' => $fee,
'remark' => $remark,
'is_settle' => true,
])->save();
}
/**
* 计算补贴总金额
*
* @param \App\Models\Dealer
* @return array
*/
protected function calculateTotalAmount(DealerManagerSubsidy $subsidy): array
{
$salesLogs = DealerManagerSalesLog::with(['product'])
->select(['product_id', DB::raw('sum(sales_volume) as sales_volume')])
->where('user_id', $subsidy->user_id)
->whereBetween('order_completed_at', [$subsidy->start_at, $subsidy->end_at])
->groupBy('product_id')
->get();
// 补贴总额
$totalAmount = 0;
// 备注信息
$remark = '';
foreach ($salesLogs as $salesLog) {
$amount = bcmul($salesLog->sales_volume, $salesLog->product->manager_subsidy, 2);
$totalAmount = bcadd($totalAmount, $amount, 2);
if ($remark !== '') {
$remark .= "\n";
}
$remark .= "{$salesLog->product->name}】销量: {$salesLog->sales_volume}, 补贴金额: {$amount}";
}
return [$totalAmount, $remark];
}
/**
* 获取给定时间端内的最后一个经销商补贴所属经销商的ID
*
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @return int|null
*/
protected function getLastDealerId(Carbon $startAt, Carbon $endAt): ?int
{
$lastManagerSubsidy = DealerManagerSubsidy::where('start_at', $startAt)
->where('end_at', $endAt)
->latest('id')
->first();
return $lastManagerSubsidy?->dealer?->id;
}
/**
* 格式化时间
*
* @param float $milliseconds
* @return string
*/
protected function formatDuration($milliseconds): string
{
if ($milliseconds < 0.01) {
return round($milliseconds * 1000) . 'μs';
} elseif ($milliseconds >= 1000) {
return round($milliseconds / 1000, 2) . 's';
}
return $milliseconds . 'ms';
}
}