diff --git a/app/Console/Commands/Dealer/ManagerSubsidySettleCommand.php b/app/Console/Commands/Dealer/ManagerSubsidySettleCommand.php index 9f2e3c31..53fc13a4 100644 --- a/app/Console/Commands/Dealer/ManagerSubsidySettleCommand.php +++ b/app/Console/Commands/Dealer/ManagerSubsidySettleCommand.php @@ -4,10 +4,10 @@ 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\Cache; use Illuminate\Support\Facades\DB; class ManagerSubsidySettleCommand extends Command @@ -17,8 +17,7 @@ class ManagerSubsidySettleCommand extends Command * * @var string */ - protected $signature = 'dealer:manager-subsidy-settle - {--force : 是否强制操作运行}'; + protected $signature = 'dealer:manager-subsidy-settle'; /** * The console command description. @@ -37,54 +36,42 @@ class ManagerSubsidySettleCommand extends Command $tz = now(); $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').'】'; - $cacheKey = $this->cacheKey($startAt, $endAt); + $this->info("{$head}------------[开始]管理者津贴结算------------".PHP_EOL); - // 如果不是强制执行,则需检查是否已结算过 - if (! $this->option('force') && Cache::has($cacheKey)) { - return $this->warn("{$head}管理者津贴已结算"); - } + $this->info("{$head}管理者津贴初始化..."); + $this->initializeManagerSubsidies($startAt, $endAt, 500); + $this->info("{$head}管理者津贴初始化完成".PHP_EOL); - $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}管理者津贴结算..."); + $this->settleManagerSubsidies($startAt, $endAt); + $this->info("{$head}管理者津贴结算完成".PHP_EOL); + $this->info("{$head}Done! 总耗时: ".$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 + protected function initializeManagerSubsidies(Carbon $startAt, Carbon $endAt, $count = 200): void { $feeRate = app_settings('dealer.fee_rate'); - $lastId = Cache::get( - $cacheKey = $this->cacheKey($startAt, $endAt).':last_id' - ); + $lastId = $this->getLastDealerId($startAt, $endAt); do { - $dealers = Dealer::where('is_manager', 1) + $dealers = Dealer::where('is_manager', true) ->forPageAfterId($count, $lastId, 'id') ->get(); @@ -94,65 +81,88 @@ class ManagerSubsidySettleCommand extends Command break; } + $managerSubsidies = []; $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, - ]; - } + $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($earnings); + DealerManagerSubsidy::insert($managerSubsidies); - Cache::put($cacheKey, $lastId, $endAt->addMonthNoOverflow()); - - unset($dealers, $earnings); + unset($dealers, $managerSubsidies); } 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 \Illuminate\Support\Carbon $startAt - * @param \Illuminate\Support\Carbon $endAt * @return array */ - protected function calculateTotalAmount(Dealer $dealer, Carbon $startAt, Carbon $endAt): array + protected function calculateTotalAmount(DealerManagerSubsidy $subsidy): array { - $salesLogs = $dealer->managerSalesLogs() - ->with(['product']) - ->select('product_id', DB::raw('sum(sales_volume) as sales_volume')) - ->whereBetween('order_completed_at', [$startAt, $endAt]) + $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 = ''; @@ -172,15 +182,20 @@ class ManagerSubsidySettleCommand extends Command } /** - * 生成缓存的 key + * 获取给定时间端内的最后一个经销商补贴所属经销商的ID * * @param \Illuminate\Support\Carbon $startAt * @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; } /** diff --git a/app/Models/DealerManagerSubsidy.php b/app/Models/DealerManagerSubsidy.php index c1400ba1..a1f55e7f 100644 --- a/app/Models/DealerManagerSubsidy.php +++ b/app/Models/DealerManagerSubsidy.php @@ -11,6 +11,7 @@ class DealerManagerSubsidy extends Model protected $attributes = [ 'lvl' => DealerLvl::None, 'is_manager' => false, + 'is_settle' => false, ]; protected $casts = [ @@ -19,6 +20,7 @@ class DealerManagerSubsidy extends Model 'start_at' => 'datetime', 'end_at' => 'datetime', 'status' => DealerManagerSubsidyStatus::class, + 'is_settle' => 'bool', ]; protected $fillable = [ @@ -33,5 +35,14 @@ class DealerManagerSubsidy extends Model 'end_at', 'status', 'remark', + 'is_settle', ]; + + /** + * 此管理津贴所属的经销商 + */ + public function dealer() + { + return $this->belongsTo(Dealer::class, 'user_id', 'user_id'); + } } diff --git a/database/migrations/2022_01_20_142233_add_is_settle_to_dealer_manager_subsidies_table.php b/database/migrations/2022_01_20_142233_add_is_settle_to_dealer_manager_subsidies_table.php new file mode 100644 index 00000000..386252da --- /dev/null +++ b/database/migrations/2022_01_20_142233_add_is_settle_to_dealer_manager_subsidies_table.php @@ -0,0 +1,32 @@ +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'); + }); + } +}