6
0
Fork 0

优化管理者津贴结算

release
李静 2022-02-20 14:38:18 +08:00
parent ca74fc1c22
commit ec9cbcfe5a
3 changed files with 128 additions and 70 deletions

View File

@ -4,10 +4,10 @@ namespace App\Console\Commands\Dealer;
use App\Enums\DealerManagerSubsidyStatus; use App\Enums\DealerManagerSubsidyStatus;
use App\Models\Dealer; use App\Models\Dealer;
use App\Models\DealerManagerSalesLog;
use App\Models\DealerManagerSubsidy; use App\Models\DealerManagerSubsidy;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
class ManagerSubsidySettleCommand extends Command class ManagerSubsidySettleCommand extends Command
@ -17,8 +17,7 @@ class ManagerSubsidySettleCommand extends Command
* *
* @var string * @var string
*/ */
protected $signature = 'dealer:manager-subsidy-settle protected $signature = 'dealer:manager-subsidy-settle';
{--force : 是否强制操作运行}';
/** /**
* The console command description. * The console command description.
@ -37,54 +36,42 @@ class ManagerSubsidySettleCommand extends Command
$tz = now(); $tz = now();
$startAt = $tz->copy()->subMonthNoOverflow()->startOfMonth(); $startAt = $tz->copy()->subMonthNoOverflow()->startOfMonth();
$endAt = $tz->copy()->subMonthNoOverflow()->endOfMonth(); $endAt = $startAt->copy()->endOfMonth();
$head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】'; $head = '【'.$startAt->format('Y/m/d').'-'.$endAt->format('Y/m/d').'】';
$cacheKey = $this->cacheKey($startAt, $endAt); $this->info("{$head}------------[开始]管理者津贴结算------------".PHP_EOL);
// 如果不是强制执行,则需检查是否已结算过 $this->info("{$head}管理者津贴初始化...");
if (! $this->option('force') && Cache::has($cacheKey)) { $this->initializeManagerSubsidies($startAt, $endAt, 500);
return $this->warn("{$head}管理者津贴已结算"); $this->info("{$head}管理者津贴初始化完成".PHP_EOL);
}
$this->info("{$head}------------[开始]管理者津贴结算------------"); $this->info("{$head}管理者津贴结算...");
$this->settleManagerSubsidies($startAt, $endAt);
if ($this->option('force')) { $this->info("{$head}管理者津贴结算完成".PHP_EOL);
$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}Done! 总耗时: ".$this->formatDuration($tz->diffInMilliseconds(now(), false)));
$this->info("{$head}------------[结束]管理者津贴结算------------".PHP_EOL); $this->info("{$head}------------[结束]管理者津贴结算------------".PHP_EOL);
Cache::put($cacheKey, 1, $tz->endOfMonth());
return 0; return 0;
} }
/** /**
* 管理津贴结算结算 * 初始化管理津贴
* *
* @param \Illuminate\Support\Carbon $startAt * @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt * @param \Illuminate\Support\Carbon $endAt
* @param int $count * @param int $count
* @return void * @return void
*/ */
protected function settle(Carbon $startAt, Carbon $endAt, int $count = 200): void protected function initializeManagerSubsidies(Carbon $startAt, Carbon $endAt, $count = 200): void
{ {
$feeRate = app_settings('dealer.fee_rate'); $feeRate = app_settings('dealer.fee_rate');
$lastId = Cache::get( $lastId = $this->getLastDealerId($startAt, $endAt);
$cacheKey = $this->cacheKey($startAt, $endAt).':last_id'
);
do { do {
$dealers = Dealer::where('is_manager', 1) $dealers = Dealer::where('is_manager', true)
->forPageAfterId($count, $lastId, 'id') ->forPageAfterId($count, $lastId, 'id')
->get(); ->get();
@ -94,65 +81,88 @@ class ManagerSubsidySettleCommand extends Command
break; break;
} }
$managerSubsidies = [];
$tz = now()->toDateTimeString(); $tz = now()->toDateTimeString();
$earnings = [];
foreach ($dealers as $dealer) { foreach ($dealers as $dealer) {
[$totalAmount, $remark] = $this->calculateTotalAmount($dealer, $startAt, $endAt); $managerSubsidies[] = [
'user_id' => $dealer->user_id,
// 如果 补贴总金额 > 0则添加管理者补贴记录 'total_amount' => 0,
if (bccomp($totalAmount, '0', 2) === 1) { 'real_amount' => 0,
// 计算手续费 'fee' => 0,
$fee = bcmul($totalAmount, bcdiv($feeRate, '100', 10), 2); 'fee_rate' => $feeRate,
'start_at' => $startAt,
$earnings[] = [ 'end_at' => $endAt,
'user_id' => $dealer->user_id, 'lvl' => $dealer->lvl,
'total_amount' => $totalAmount, 'is_manager' => $dealer->is_manager,
'real_amount' => bcsub($totalAmount, $fee, 2), 'status' => DealerManagerSubsidyStatus::Pending,
'fee' => $fee, 'is_settle' => false,
'fee_rate' => $feeRate, 'created_at' => $tz,
'start_at' => $startAt, 'updated_at' => $tz,
'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; $lastId = $dealer->id;
} }
DealerManagerSubsidy::insert($earnings); DealerManagerSubsidy::insert($managerSubsidies);
Cache::put($cacheKey, $lastId, $endAt->addMonthNoOverflow()); unset($dealers, $managerSubsidies);
unset($dealers, $earnings);
} while ($dealersCount == $count); } while ($dealersCount == $count);
}
Cache::forget($cacheKey); /**
* 结算管理者津贴
*
* @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 * @param \App\Models\Dealer
* @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt
* @return array * @return array
*/ */
protected function calculateTotalAmount(Dealer $dealer, Carbon $startAt, Carbon $endAt): array protected function calculateTotalAmount(DealerManagerSubsidy $subsidy): array
{ {
$salesLogs = $dealer->managerSalesLogs() $salesLogs = DealerManagerSalesLog::with(['product'])
->with(['product']) ->select(['product_id', DB::raw('sum(sales_volume) as sales_volume')])
->select('product_id', DB::raw('sum(sales_volume) as sales_volume')) ->where('user_id', $subsidy->user_id)
->whereBetween('order_completed_at', [$startAt, $endAt]) ->whereBetween('order_completed_at', [$subsidy->start_at, $subsidy->end_at])
->groupBy('product_id') ->groupBy('product_id')
->get(); ->get();
// 补贴总金额
// 补贴总额
$totalAmount = 0; $totalAmount = 0;
// 备注信息 // 备注信息
$remark = ''; $remark = '';
@ -172,15 +182,20 @@ class ManagerSubsidySettleCommand extends Command
} }
/** /**
* 生成缓存的 key * 获取给定时间端内的最后一个经销商补贴所属经销商的ID
* *
* @param \Illuminate\Support\Carbon $startAt * @param \Illuminate\Support\Carbon $startAt
* @param \Illuminate\Support\Carbon $endAt * @param \Illuminate\Support\Carbon $endAt
* @return void * @return int|null
*/ */
protected function cacheKey(Carbon $startAt, Carbon $endAt) protected function getLastDealerId(Carbon $startAt, Carbon $endAt): ?int
{ {
return $startAt->format('Ymd').'_'.$endAt->format('Ymd').'_dealer_manager_subsidy'; $lastManagerSubsidy = DealerManagerSubsidy::where('start_at', $startAt)
->where('end_at', $endAt)
->latest('id')
->first();
return $lastManagerSubsidy?->dealer?->id;
} }
/** /**

View File

@ -11,6 +11,7 @@ class DealerManagerSubsidy extends Model
protected $attributes = [ protected $attributes = [
'lvl' => DealerLvl::None, 'lvl' => DealerLvl::None,
'is_manager' => false, 'is_manager' => false,
'is_settle' => false,
]; ];
protected $casts = [ protected $casts = [
@ -19,6 +20,7 @@ class DealerManagerSubsidy extends Model
'start_at' => 'datetime', 'start_at' => 'datetime',
'end_at' => 'datetime', 'end_at' => 'datetime',
'status' => DealerManagerSubsidyStatus::class, 'status' => DealerManagerSubsidyStatus::class,
'is_settle' => 'bool',
]; ];
protected $fillable = [ protected $fillable = [
@ -33,5 +35,14 @@ class DealerManagerSubsidy extends Model
'end_at', 'end_at',
'status', 'status',
'remark', 'remark',
'is_settle',
]; ];
/**
* 此管理津贴所属的经销商
*/
public function dealer()
{
return $this->belongsTo(Dealer::class, 'user_id', 'user_id');
}
} }

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsSettleToDealerManagerSubsidiesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('dealer_manager_subsidies', function (Blueprint $table) {
$table->boolean('is_settle')->default(0)->comment('是否结算');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('dealer_manager_subsidies', function (Blueprint $table) {
$table->dropColumn('is_settle');
});
}
}