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

203 lines
6.2 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\DealerManagerSubsidyStatus;
use App\Models\Dealer;
use App\Models\DealerManagerSubsidy;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
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
{--force : 是否强制操作运行}';
/**
* 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 = $tz->copy()->subMonthNoOverflow()->endOfMonth();
$head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】';
$cacheKey = $this->cacheKey($startAt, $endAt);
// 如果不是强制执行,则需检查是否已结算过
if (! $this->option('force') && Cache::has($cacheKey)) {
return $this->warn("{$head}管理者津贴已结算");
}
$this->info("{$head}------------[开始]管理者津贴结算------------");
if ($this->option('force')) {
$this->info("{$head}正在删除旧数据...");
DealerManagerSubsidy::where('start_at', $startAt)->where('end_at', $endAt)->delete();
$this->info("{$head}数据删除成功");
}
$this->info("{$head}数据写入中...");
$this->settle($startAt, $endAt, 500);
$this->info("{$head}写入成功, 总耗时: ".$this->formatDuration($tz->diffInMilliseconds(now(), false)));
$this->info("{$head}------------[结束]管理者津贴结算------------".PHP_EOL);
Cache::put($cacheKey, 1, $tz->endOfMonth());
return 0;
}
/**
* 管理津贴结算结算
*
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @param int $count
* @return void
*/
protected function settle(Carbon $startAt, Carbon $endAt, int $count = 200): void
{
$feeRate = app_settings('dealer.fee_rate');
$lastId = Cache::get(
$cacheKey = $this->cacheKey($startAt, $endAt).':last_id'
);
do {
$dealers = Dealer::where('is_manager', 1)
->forPageAfterId($count, $lastId, 'id')
->get();
$dealersCount = $dealers->count();
if ($dealersCount == 0) {
break;
}
$tz = now()->toDateTimeString();
$earnings = [];
foreach ($dealers as $dealer) {
[$totalAmount, $remark] = $this->calculateTotalAmount($dealer, $startAt, $endAt);
// 如果 补贴总金额 > 0则添加管理者补贴记录
if (bccomp($totalAmount, '0', 2) === 1) {
// 计算手续费
$fee = bcmul($totalAmount, bcdiv($feeRate, '100', 10), 2);
$earnings[] = [
'user_id' => $dealer->user_id,
'total_amount' => $totalAmount,
'real_amount' => bcsub($totalAmount, $fee, 2),
'fee' => $fee,
'fee_rate' => $feeRate,
'start_at' => $startAt,
'end_at' => $endAt,
'lvl' => $dealer->lvl,
'is_manager' => $dealer->is_manager,
'status' => DealerManagerSubsidyStatus::Pending,
'remark' => $remark,
'created_at' => $tz,
'updated_at' => $tz,
];
}
$lastId = $dealer->id;
}
DealerManagerSubsidy::insert($earnings);
Cache::put($cacheKey, $lastId, $endAt->addMonthNoOverflow());
unset($dealers, $earnings);
} while ($dealersCount == $count);
Cache::forget($cacheKey);
}
/**
* 计算补贴总金额
*
* @param \App\Models\Dealer
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @return array
*/
protected function calculateTotalAmount(Dealer $dealer, Carbon $startAt, Carbon $endAt): array
{
$salesLogs = $dealer->managerSalesLogs()
->with(['product'])
->select('product_id', DB::raw('sum(sales_volume) as sales_volume'))
->whereBetween('order_completed_at', [$startAt, $endAt])
->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];
}
/**
* 生成缓存的 key
*
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @return void
*/
protected function cacheKey(Carbon $startAt, Carbon $endAt)
{
return $startAt->format('Ymd').'_'.$endAt->format('Ymd').'_dealer_manager_subsidy';
}
/**
* 格式化时间
*
* @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';
}
}