187 lines
5.9 KiB
PHP
187 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands\Dealer;
|
|
|
|
use App\Enums\DealerEarningStatus;
|
|
use App\Enums\DealerEarningType;
|
|
use App\Enums\DealerLvl;
|
|
use App\Models\Dealer;
|
|
use App\Models\DealerEarning;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class ManageSubsidySettleCommand extends Command
|
|
{
|
|
/**
|
|
* The name and signature of the console command.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $signature = 'dealer:manage-subsidy-settle
|
|
{--force : 是否强制操作运行}';
|
|
|
|
/**
|
|
* The console command description.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $description = '结算一级经销商和二级经销商的管理津贴';
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function handle()
|
|
{
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 管理津贴结算
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| 管理津贴结算时间为每月的5号和20号。
|
|
|
|
|
| 5号结算上月20号0点到当月4号23点59分59秒的管理津贴
|
|
| 20号结算当月5号0点到19号23点59分59秒的管理津贴
|
|
|
|
|
*/
|
|
|
|
$tz = now();
|
|
|
|
if ($tz->day >= 20) {
|
|
$startAt = $tz->copy()->setDay(5)->startOfDay();
|
|
$endAt = $tz->copy()->setDay(19)->endOfDay();
|
|
} elseif ($tz->day >= 5) {
|
|
$startAt = $tz->copy()->subMonthNoOverflow()->set('day', 20)->startOfDay();
|
|
$endAt = $tz->copy()->set('day', 4)->endOfDay();
|
|
} else {
|
|
$startAt = $tz->copy()->subMonthNoOverflow()->setDay(5)->startOfDay();
|
|
$endAt = $startAt->copy()->subMonthNoOverflow()->setDay(19)->endOfDay();
|
|
}
|
|
|
|
$head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】';
|
|
|
|
// 如果不是强制执行,则需检查是否已结算过
|
|
if (! $this->option('force') && Cache::has($this->cacheKey($startAt, $endAt))) {
|
|
return $this->warn("{$head}管理津贴已结算");
|
|
}
|
|
|
|
$this->info("{$head}------------[开始]管理津贴结算------------");
|
|
|
|
if ($this->option('force')) {
|
|
$this->info("{$head}正在删除旧数据...");
|
|
DealerEarning::manageSubsidy()->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($this->cacheKey($startAt, $endAt), 1, $endAt->tomorrow());
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 管理津贴结算结算
|
|
*
|
|
* @param \Illuminate\Support\Carbon $startAt
|
|
* @param \Illuminate\Support\Carbon $endAt
|
|
* @param int $count
|
|
* @return void
|
|
*/
|
|
protected function settle(Carbon $startAt, Carbon $endAt, $count = 200): void
|
|
{
|
|
$feeRate = app_settings('dealer.fee_rate');
|
|
|
|
$lastId = Cache::get(
|
|
$key = $this->cacheKey($startAt, $endAt).':last_id'
|
|
);
|
|
|
|
do {
|
|
$dealers = Dealer::where('lvl', '>=', DealerLvl::Secondary)
|
|
->forPageAfterId($count, $lastId, 'id')
|
|
->get();
|
|
|
|
$countDealers = $dealers->count();
|
|
|
|
if ($countDealers == 0) {
|
|
break;
|
|
}
|
|
|
|
$earnings = [];
|
|
$time = now()->toDateTimeString();
|
|
|
|
foreach ($dealers as $dealer) {
|
|
$totalAmount = $dealer->manageSubsidyLogs()
|
|
->whereBetween('order_completed_at', [$startAt, $endAt])
|
|
->sum('total_amount');
|
|
|
|
if (bccomp($totalAmount, '0', 2) === 1) {
|
|
// 计算手续费
|
|
$fee = bcmul($totalAmount, bcdiv($feeRate, '100', 10), 2);
|
|
|
|
$earnings[] = [
|
|
'user_id' => $dealer->user_id,
|
|
'total_amount' => $totalAmount,
|
|
'fee' => $fee,
|
|
'fee_rate' => $feeRate,
|
|
'type' => DealerEarningType::ManageSubsidy,
|
|
'start_at' => $startAt,
|
|
'end_at' => $endAt,
|
|
'lvl' => $dealer->lvl,
|
|
'is_manager' => $dealer->is_manager,
|
|
'status' => DealerEarningStatus::Pending,
|
|
'description' => '管理津贴',
|
|
'created_at' => $time,
|
|
'updated_at' => $time,
|
|
];
|
|
}
|
|
|
|
$lastId = $dealer->id;
|
|
}
|
|
|
|
DealerEarning::insert($earnings);
|
|
|
|
Cache::put($key, $lastId, $endAt);
|
|
|
|
unset($dealers, $earnings);
|
|
} while ($countDealers == $count);
|
|
|
|
Cache::forget($key);
|
|
}
|
|
|
|
/**
|
|
* 生成缓存的 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_manage_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';
|
|
}
|
|
}
|